From 22e328b94b2546a660e788e8cb95a3e64d7d25fa Mon Sep 17 00:00:00 2001 From: viktorstrate Date: Fri, 27 Nov 2020 16:02:10 +0100 Subject: [PATCH] Replace database, mostly share token --- api/graphql/generated.go | 418 +++++++++++++++------------ api/graphql/models/generated.go | 14 +- api/graphql/resolvers/scanner.go | 35 +-- api/graphql/resolvers/share_token.go | 196 ++++++------- 4 files changed, 343 insertions(+), 320 deletions(-) diff --git a/api/graphql/generated.go b/api/graphql/generated.go index 1b3171e4..1c40df49 100644 --- a/api/graphql/generated.go +++ b/api/graphql/generated.go @@ -40,10 +40,13 @@ type Config struct { type ResolverRoot interface { Album() AlbumResolver Media() MediaResolver + MediaEXIF() MediaEXIFResolver Mutation() MutationResolver Query() QueryResolver ShareToken() ShareTokenResolver Subscription() SubscriptionResolver + User() UserResolver + VideoMetadata() VideoMetadataResolver } type DirectiveRoot struct { @@ -213,26 +216,29 @@ type ComplexityRoot struct { } type AlbumResolver interface { + ID(ctx context.Context, obj *models.Album) (int, error) + Media(ctx context.Context, obj *models.Album, filter *models.Filter, onlyFavorites *bool) ([]*models.Media, error) SubAlbums(ctx context.Context, obj *models.Album, filter *models.Filter) ([]*models.Album, error) - ParentAlbum(ctx context.Context, obj *models.Album) (*models.Album, error) - Owner(ctx context.Context, obj *models.Album) (*models.User, error) Thumbnail(ctx context.Context, obj *models.Album) (*models.Media, error) Path(ctx context.Context, obj *models.Album) ([]*models.Album, error) Shares(ctx context.Context, obj *models.Album) ([]*models.ShareToken, error) } type MediaResolver interface { + ID(ctx context.Context, obj *models.Media) (int, error) + Thumbnail(ctx context.Context, obj *models.Media) (*models.MediaURL, error) HighRes(ctx context.Context, obj *models.Media) (*models.MediaURL, error) VideoWeb(ctx context.Context, obj *models.Media) (*models.MediaURL, error) - Album(ctx context.Context, obj *models.Media) (*models.Album, error) - Exif(ctx context.Context, obj *models.Media) (*models.MediaEXIF, error) - VideoMetadata(ctx context.Context, obj *models.Media) (*models.VideoMetadata, error) Shares(ctx context.Context, obj *models.Media) ([]*models.ShareToken, error) Downloads(ctx context.Context, obj *models.Media) ([]*models.MediaDownload, error) } +type MediaEXIFResolver interface { + ID(ctx context.Context, obj *models.MediaEXIF) (int, error) + Media(ctx context.Context, obj *models.MediaEXIF) (*models.Media, error) +} type MutationResolver interface { AuthorizeUser(ctx context.Context, username string, password string) (*models.AuthorizeResult, error) RegisterUser(ctx context.Context, username string, password string, rootPath string) (*models.AuthorizeResult, error) @@ -266,15 +272,22 @@ type QueryResolver interface { Search(ctx context.Context, query string, limitMedia *int, limitAlbums *int) (*models.SearchResult, error) } type ShareTokenResolver interface { - Owner(ctx context.Context, obj *models.ShareToken) (*models.User, error) + ID(ctx context.Context, obj *models.ShareToken) (int, error) HasPassword(ctx context.Context, obj *models.ShareToken) (bool, error) - Album(ctx context.Context, obj *models.ShareToken) (*models.Album, error) - Media(ctx context.Context, obj *models.ShareToken) (*models.Media, error) } type SubscriptionResolver interface { Notification(ctx context.Context) (<-chan *models.Notification, error) } +type UserResolver interface { + ID(ctx context.Context, obj *models.User) (int, error) +} +type VideoMetadataResolver interface { + ID(ctx context.Context, obj *models.VideoMetadata) (int, error) + Media(ctx context.Context, obj *models.VideoMetadata) (*models.Media, error) + + Bitrate(ctx context.Context, obj *models.VideoMetadata) (*int, error) +} type executableSchema struct { resolvers ResolverRoot @@ -2261,13 +2274,13 @@ func (ec *executionContext) _Album_id(ctx context.Context, field graphql.Collect Field: field, Args: nil, IsMethod: true, - IsResolver: false, + IsResolver: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.ID(), nil + return ec.resolvers.Album().ID(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -2414,14 +2427,14 @@ func (ec *executionContext) _Album_parentAlbum(ctx context.Context, field graphq Object: "Album", Field: field, Args: nil, - IsMethod: true, - IsResolver: true, + IsMethod: false, + IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Album().ParentAlbum(rctx, obj) + return obj.ParentAlbum, nil }) if err != nil { ec.Error(ctx, err) @@ -2446,14 +2459,14 @@ func (ec *executionContext) _Album_owner(ctx context.Context, field graphql.Coll Object: "Album", Field: field, Args: nil, - IsMethod: true, - IsResolver: true, + IsMethod: false, + IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Album().Owner(rctx, obj) + return obj.Owner, nil }) if err != nil { ec.Error(ctx, err) @@ -2465,9 +2478,9 @@ func (ec *executionContext) _Album_owner(ctx context.Context, field graphql.Coll } return graphql.Null } - res := resTmp.(*models.User) + res := resTmp.(models.User) fc.Result = res - return ec.marshalNUser2ᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐUser(ctx, field.Selections, res) + return ec.marshalNUser2githubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐUser(ctx, field.Selections, res) } func (ec *executionContext) _Album_filePath(ctx context.Context, field graphql.CollectedField, obj *models.Album) (ret graphql.Marshaler) { @@ -2718,13 +2731,13 @@ func (ec *executionContext) _Media_id(ctx context.Context, field graphql.Collect Field: field, Args: nil, IsMethod: true, - IsResolver: false, + IsResolver: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.ID(), nil + return ec.resolvers.Media().ID(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -2921,14 +2934,14 @@ func (ec *executionContext) _Media_album(ctx context.Context, field graphql.Coll Object: "Media", Field: field, Args: nil, - IsMethod: true, - IsResolver: true, + IsMethod: false, + IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Media().Album(rctx, obj) + return obj.Album, nil }) if err != nil { ec.Error(ctx, err) @@ -2940,9 +2953,9 @@ func (ec *executionContext) _Media_album(ctx context.Context, field graphql.Coll } return graphql.Null } - res := resTmp.(*models.Album) + res := resTmp.(models.Album) fc.Result = res - return ec.marshalNAlbum2ᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐAlbum(ctx, field.Selections, res) + return ec.marshalNAlbum2githubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐAlbum(ctx, field.Selections, res) } func (ec *executionContext) _Media_exif(ctx context.Context, field graphql.CollectedField, obj *models.Media) (ret graphql.Marshaler) { @@ -2956,14 +2969,14 @@ func (ec *executionContext) _Media_exif(ctx context.Context, field graphql.Colle Object: "Media", Field: field, Args: nil, - IsMethod: true, - IsResolver: true, + IsMethod: false, + IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Media().Exif(rctx, obj) + return obj.Exif, nil }) if err != nil { ec.Error(ctx, err) @@ -2972,9 +2985,9 @@ func (ec *executionContext) _Media_exif(ctx context.Context, field graphql.Colle if resTmp == nil { return graphql.Null } - res := resTmp.(*models.MediaEXIF) + res := resTmp.(models.MediaEXIF) fc.Result = res - return ec.marshalOMediaEXIF2ᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐMediaEXIF(ctx, field.Selections, res) + return ec.marshalOMediaEXIF2githubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐMediaEXIF(ctx, field.Selections, res) } func (ec *executionContext) _Media_videoMetadata(ctx context.Context, field graphql.CollectedField, obj *models.Media) (ret graphql.Marshaler) { @@ -2988,14 +3001,14 @@ func (ec *executionContext) _Media_videoMetadata(ctx context.Context, field grap Object: "Media", Field: field, Args: nil, - IsMethod: true, - IsResolver: true, + IsMethod: false, + IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Media().VideoMetadata(rctx, obj) + return obj.VideoMetadata, nil }) if err != nil { ec.Error(ctx, err) @@ -3231,13 +3244,13 @@ func (ec *executionContext) _MediaEXIF_id(ctx context.Context, field graphql.Col Field: field, Args: nil, IsMethod: true, - IsResolver: false, + IsResolver: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.ID(), nil + return ec.resolvers.MediaEXIF().ID(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -3266,13 +3279,13 @@ func (ec *executionContext) _MediaEXIF_media(ctx context.Context, field graphql. Field: field, Args: nil, IsMethod: true, - IsResolver: false, + IsResolver: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Media(), nil + return ec.resolvers.MediaEXIF().Media(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -3744,9 +3757,9 @@ func (ec *executionContext) _MediaURL_fileSize(ctx context.Context, field graphq } return graphql.Null } - res := resTmp.(int) + res := resTmp.(int64) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNInt2int64(ctx, field.Selections, res) } func (ec *executionContext) _Mutation_authorizeUser(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { @@ -5556,13 +5569,13 @@ func (ec *executionContext) _ShareToken_id(ctx context.Context, field graphql.Co Field: field, Args: nil, IsMethod: true, - IsResolver: false, + IsResolver: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.ID(), nil + return ec.resolvers.ShareToken().ID(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -5625,14 +5638,14 @@ func (ec *executionContext) _ShareToken_owner(ctx context.Context, field graphql Object: "ShareToken", Field: field, Args: nil, - IsMethod: true, - IsResolver: true, + IsMethod: false, + IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.ShareToken().Owner(rctx, obj) + return obj.Owner, nil }) if err != nil { ec.Error(ctx, err) @@ -5644,9 +5657,9 @@ func (ec *executionContext) _ShareToken_owner(ctx context.Context, field graphql } return graphql.Null } - res := resTmp.(*models.User) + res := resTmp.(models.User) fc.Result = res - return ec.marshalNUser2ᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐUser(ctx, field.Selections, res) + return ec.marshalNUser2githubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐUser(ctx, field.Selections, res) } func (ec *executionContext) _ShareToken_expire(ctx context.Context, field graphql.CollectedField, obj *models.ShareToken) (ret graphql.Marshaler) { @@ -5727,14 +5740,14 @@ func (ec *executionContext) _ShareToken_album(ctx context.Context, field graphql Object: "ShareToken", Field: field, Args: nil, - IsMethod: true, - IsResolver: true, + IsMethod: false, + IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.ShareToken().Album(rctx, obj) + return obj.Album, nil }) if err != nil { ec.Error(ctx, err) @@ -5743,9 +5756,9 @@ func (ec *executionContext) _ShareToken_album(ctx context.Context, field graphql if resTmp == nil { return graphql.Null } - res := resTmp.(*models.Album) + res := resTmp.(models.Album) fc.Result = res - return ec.marshalOAlbum2ᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐAlbum(ctx, field.Selections, res) + return ec.marshalOAlbum2githubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐAlbum(ctx, field.Selections, res) } func (ec *executionContext) _ShareToken_media(ctx context.Context, field graphql.CollectedField, obj *models.ShareToken) (ret graphql.Marshaler) { @@ -5759,14 +5772,14 @@ func (ec *executionContext) _ShareToken_media(ctx context.Context, field graphql Object: "ShareToken", Field: field, Args: nil, - IsMethod: true, - IsResolver: true, + IsMethod: false, + IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.ShareToken().Media(rctx, obj) + return obj.Media, nil }) if err != nil { ec.Error(ctx, err) @@ -5982,13 +5995,13 @@ func (ec *executionContext) _User_id(ctx context.Context, field graphql.Collecte Field: field, Args: nil, IsMethod: true, - IsResolver: false, + IsResolver: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.ID(), nil + return ec.resolvers.User().ID(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -6142,13 +6155,13 @@ func (ec *executionContext) _VideoMetadata_id(ctx context.Context, field graphql Field: field, Args: nil, IsMethod: true, - IsResolver: false, + IsResolver: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.ID(), nil + return ec.resolvers.VideoMetadata().ID(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -6177,13 +6190,13 @@ func (ec *executionContext) _VideoMetadata_media(ctx context.Context, field grap Field: field, Args: nil, IsMethod: true, - IsResolver: false, + IsResolver: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Media(), nil + return ec.resolvers.VideoMetadata().Media(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -6380,14 +6393,14 @@ func (ec *executionContext) _VideoMetadata_bitrate(ctx context.Context, field gr Object: "VideoMetadata", Field: field, Args: nil, - IsMethod: false, - IsResolver: false, + IsMethod: true, + IsResolver: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Bitrate, nil + return ec.resolvers.VideoMetadata().Bitrate(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -7616,10 +7629,19 @@ func (ec *executionContext) _Album(ctx context.Context, sel ast.SelectionSet, ob case "__typename": out.Values[i] = graphql.MarshalString("Album") case "id": - out.Values[i] = ec._Album_id(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Album_id(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) case "title": out.Values[i] = ec._Album_title(ctx, field, obj) if out.Values[i] == graphql.Null { @@ -7654,30 +7676,12 @@ func (ec *executionContext) _Album(ctx context.Context, sel ast.SelectionSet, ob return res }) case "parentAlbum": - field := field - out.Concurrently(i, func() (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Album_parentAlbum(ctx, field, obj) - return res - }) + out.Values[i] = ec._Album_parentAlbum(ctx, field, obj) case "owner": - field := field - out.Concurrently(i, func() (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Album_owner(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - return res - }) + out.Values[i] = ec._Album_owner(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } case "filePath": out.Values[i] = ec._Album_filePath(ctx, field, obj) if out.Values[i] == graphql.Null { @@ -7776,10 +7780,19 @@ func (ec *executionContext) _Media(ctx context.Context, sel ast.SelectionSet, ob case "__typename": out.Values[i] = graphql.MarshalString("Media") case "id": - out.Values[i] = ec._Media_id(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Media_id(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) case "title": out.Values[i] = ec._Media_title(ctx, field, obj) if out.Values[i] == graphql.Null { @@ -7827,41 +7840,14 @@ func (ec *executionContext) _Media(ctx context.Context, sel ast.SelectionSet, ob return res }) case "album": - field := field - out.Concurrently(i, func() (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Media_album(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - return res - }) + out.Values[i] = ec._Media_album(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } case "exif": - field := field - out.Concurrently(i, func() (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Media_exif(ctx, field, obj) - return res - }) + out.Values[i] = ec._Media_exif(ctx, field, obj) case "videoMetadata": - field := field - out.Concurrently(i, func() (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Media_videoMetadata(ctx, field, obj) - return res - }) + out.Values[i] = ec._Media_videoMetadata(ctx, field, obj) case "favorite": out.Values[i] = ec._Media_favorite(ctx, field, obj) if out.Values[i] == graphql.Null { @@ -7955,15 +7941,33 @@ func (ec *executionContext) _MediaEXIF(ctx context.Context, sel ast.SelectionSet case "__typename": out.Values[i] = graphql.MarshalString("MediaEXIF") case "id": - out.Values[i] = ec._MediaEXIF_id(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ - } + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._MediaEXIF_id(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) case "media": - out.Values[i] = ec._MediaEXIF_media(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ - } + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._MediaEXIF_media(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) case "camera": out.Values[i] = ec._MediaEXIF_camera(ctx, field, obj) case "maker": @@ -8461,16 +8465,6 @@ func (ec *executionContext) _ShareToken(ctx context.Context, sel ast.SelectionSe case "__typename": out.Values[i] = graphql.MarshalString("ShareToken") case "id": - out.Values[i] = ec._ShareToken_id(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "token": - out.Values[i] = ec._ShareToken_token(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "owner": field := field out.Concurrently(i, func() (res graphql.Marshaler) { defer func() { @@ -8478,12 +8472,22 @@ func (ec *executionContext) _ShareToken(ctx context.Context, sel ast.SelectionSe ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._ShareToken_owner(ctx, field, obj) + res = ec._ShareToken_id(ctx, field, obj) if res == graphql.Null { atomic.AddUint32(&invalids, 1) } return res }) + case "token": + out.Values[i] = ec._ShareToken_token(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + case "owner": + out.Values[i] = ec._ShareToken_owner(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } case "expire": out.Values[i] = ec._ShareToken_expire(ctx, field, obj) case "hasPassword": @@ -8501,27 +8505,9 @@ func (ec *executionContext) _ShareToken(ctx context.Context, sel ast.SelectionSe return res }) case "album": - field := field - out.Concurrently(i, func() (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._ShareToken_album(ctx, field, obj) - return res - }) + out.Values[i] = ec._ShareToken_album(ctx, field, obj) case "media": - field := field - out.Concurrently(i, func() (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._ShareToken_media(ctx, field, obj) - return res - }) + out.Values[i] = ec._ShareToken_media(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -8602,24 +8588,33 @@ func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj case "__typename": out.Values[i] = graphql.MarshalString("User") case "id": - out.Values[i] = ec._User_id(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ - } + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._User_id(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) case "username": out.Values[i] = ec._User_username(ctx, field, obj) if out.Values[i] == graphql.Null { - invalids++ + atomic.AddUint32(&invalids, 1) } case "rootPath": out.Values[i] = ec._User_rootPath(ctx, field, obj) if out.Values[i] == graphql.Null { - invalids++ + atomic.AddUint32(&invalids, 1) } case "admin": out.Values[i] = ec._User_admin(ctx, field, obj) if out.Values[i] == graphql.Null { - invalids++ + atomic.AddUint32(&invalids, 1) } default: panic("unknown field " + strconv.Quote(field.Name)) @@ -8644,36 +8639,63 @@ func (ec *executionContext) _VideoMetadata(ctx context.Context, sel ast.Selectio case "__typename": out.Values[i] = graphql.MarshalString("VideoMetadata") case "id": - out.Values[i] = ec._VideoMetadata_id(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ - } + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._VideoMetadata_id(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) case "media": - out.Values[i] = ec._VideoMetadata_media(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ - } + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._VideoMetadata_media(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) case "width": out.Values[i] = ec._VideoMetadata_width(ctx, field, obj) if out.Values[i] == graphql.Null { - invalids++ + atomic.AddUint32(&invalids, 1) } case "height": out.Values[i] = ec._VideoMetadata_height(ctx, field, obj) if out.Values[i] == graphql.Null { - invalids++ + atomic.AddUint32(&invalids, 1) } case "duration": out.Values[i] = ec._VideoMetadata_duration(ctx, field, obj) if out.Values[i] == graphql.Null { - invalids++ + atomic.AddUint32(&invalids, 1) } case "codec": out.Values[i] = ec._VideoMetadata_codec(ctx, field, obj) case "framerate": out.Values[i] = ec._VideoMetadata_framerate(ctx, field, obj) case "bitrate": - out.Values[i] = ec._VideoMetadata_bitrate(ctx, field, obj) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._VideoMetadata_bitrate(ctx, field, obj) + return res + }) case "colorProfile": out.Values[i] = ec._VideoMetadata_colorProfile(ctx, field, obj) case "audio": @@ -9065,6 +9087,21 @@ func (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.Selecti return res } +func (ec *executionContext) unmarshalNInt2int64(ctx context.Context, v interface{}) (int64, error) { + res, err := graphql.UnmarshalInt64(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNInt2int64(ctx context.Context, sel ast.SelectionSet, v int64) graphql.Marshaler { + res := graphql.MarshalInt64(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + } + return res +} + func (ec *executionContext) unmarshalNInt2ᚕintᚄ(ctx context.Context, v interface{}) ([]int, error) { var vSlice []interface{} if v != nil { @@ -9629,6 +9666,10 @@ func (ec *executionContext) marshalN__TypeKind2string(ctx context.Context, sel a return res } +func (ec *executionContext) marshalOAlbum2githubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐAlbum(ctx context.Context, sel ast.SelectionSet, v models.Album) graphql.Marshaler { + return ec._Album(ctx, sel, &v) +} + func (ec *executionContext) marshalOAlbum2ᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐAlbum(ctx context.Context, sel ast.SelectionSet, v *models.Album) graphql.Marshaler { if v == nil { return graphql.Null @@ -9712,11 +9753,8 @@ func (ec *executionContext) marshalOMedia2ᚖgithubᚗcomᚋviktorstrateᚋphoto return ec._Media(ctx, sel, v) } -func (ec *executionContext) marshalOMediaEXIF2ᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐMediaEXIF(ctx context.Context, sel ast.SelectionSet, v *models.MediaEXIF) graphql.Marshaler { - if v == nil { - return graphql.Null - } - return ec._MediaEXIF(ctx, sel, v) +func (ec *executionContext) marshalOMediaEXIF2githubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐMediaEXIF(ctx context.Context, sel ast.SelectionSet, v models.MediaEXIF) graphql.Marshaler { + return ec._MediaEXIF(ctx, sel, &v) } func (ec *executionContext) marshalOMediaURL2ᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐMediaURL(ctx context.Context, sel ast.SelectionSet, v *models.MediaURL) graphql.Marshaler { diff --git a/api/graphql/models/generated.go b/api/graphql/models/generated.go index d727ede8..3413a2e6 100644 --- a/api/graphql/models/generated.go +++ b/api/graphql/models/generated.go @@ -52,13 +52,13 @@ type SearchResult struct { } // General information about the site -// type SiteInfo struct { -// InitialSetup bool `json:"initialSetup"` -// // How often automatic scans should be initiated in seconds -// PeriodicScanInterval int `json:"periodicScanInterval"` -// // How many max concurrent scanner jobs that should run at once -// ConcurrentWorkers int `json:"concurrentWorkers"` -// } +type SiteInfo struct { + InitialSetup bool `json:"initialSetup"` + // How often automatic scans should be initiated in seconds + PeriodicScanInterval int `json:"periodicScanInterval"` + // How many max concurrent scanner jobs that should run at once + ConcurrentWorkers int `json:"concurrentWorkers"` +} type MediaType string diff --git a/api/graphql/resolvers/scanner.go b/api/graphql/resolvers/scanner.go index 9d3eab0b..c1863ea9 100644 --- a/api/graphql/resolvers/scanner.go +++ b/api/graphql/resolvers/scanner.go @@ -25,13 +25,14 @@ func (r *mutationResolver) ScanAll(ctx context.Context) (*models.ScannerResult, } func (r *mutationResolver) ScanUser(ctx context.Context, userID int) (*models.ScannerResult, error) { - row := r.Database.QueryRow("SELECT * FROM user WHERE user_id = ?", userID) - user, err := models.NewUserFromRow(row) - if err != nil { + + var user models.User + + if err := r.Database.First(&user, userID).Error; err != nil { return nil, errors.Wrap(err, "get user from database") } - scanner.AddUserToQueue(user) + scanner.AddUserToQueue(&user) startMessage := "Scanner started" return &models.ScannerResult{ @@ -46,21 +47,18 @@ func (r *mutationResolver) SetPeriodicScanInterval(ctx context.Context, interval return 0, errors.New("interval must be 0 or above") } - _, err := r.Database.Exec("UPDATE site_info SET periodic_scan_interval = ?", interval) - if err != nil { + if err := r.Database.Model(&models.SiteInfo{}).Update("periodic_scan_interval", interval).Error; err != nil { return 0, err } - var dbInterval int - - row := r.Database.QueryRow("SELECT periodic_scan_interval FROM site_info") - if err = row.Scan(&dbInterval); err != nil { + var siteInfo models.SiteInfo + if err := r.Database.First(&siteInfo).Error; err != nil { return 0, err } - scanner.ChangePeriodicScanInterval(time.Duration(dbInterval) * time.Second) + scanner.ChangePeriodicScanInterval(time.Duration(siteInfo.PeriodicScanInterval) * time.Second) - return dbInterval, nil + return siteInfo.PeriodicScanInterval, nil } func (r *mutationResolver) SetScannerConcurrentWorkers(ctx context.Context, workers int) (int, error) { @@ -68,19 +66,16 @@ func (r *mutationResolver) SetScannerConcurrentWorkers(ctx context.Context, work return 0, errors.New("concurrent workers must at least be 1") } - _, err := r.Database.Exec("UPDATE site_info SET concurrent_workers = ?", workers) - if err != nil { + if err := r.Database.Model(&models.SiteInfo{}).Update("concurrent_workers", workers).Error; err != nil { return 0, err } - var dbWorkers int - - row := r.Database.QueryRow("SELECT concurrent_workers FROM site_info") - if err = row.Scan(&dbWorkers); err != nil { + var siteInfo models.SiteInfo + if err := r.Database.First(&siteInfo).Error; err != nil { return 0, err } - scanner.ChangeScannerConcurrentWorkers(dbWorkers) + scanner.ChangeScannerConcurrentWorkers(siteInfo.ConcurrentWorkers) - return dbWorkers, nil + return siteInfo.ConcurrentWorkers, nil } diff --git a/api/graphql/resolvers/share_token.go b/api/graphql/resolvers/share_token.go index 616059a2..c1d8792f 100644 --- a/api/graphql/resolvers/share_token.go +++ b/api/graphql/resolvers/share_token.go @@ -2,7 +2,6 @@ package resolvers import ( "context" - "database/sql" "time" "github.com/pkg/errors" @@ -23,38 +22,36 @@ func (r *Resolver) ShareToken() api.ShareTokenResolver { return &shareTokenResolver{r} } -func (r *shareTokenResolver) Owner(ctx context.Context, obj *models.ShareToken) (*models.User, error) { - row := r.Database.QueryRow("SELECT * FROM user WHERE user.user_id = ?", obj.OwnerID) - return models.NewUserFromRow(row) -} +// PROBABLY NOT NEEDED ANYMORE -func (r *shareTokenResolver) Album(ctx context.Context, obj *models.ShareToken) (*models.Album, error) { - row := r.Database.QueryRow("SELECT * FROM album WHERE album.album_id = ?", obj.AlbumID) - album, err := models.NewAlbumFromRow(row) - if err != nil { - if err == sql.ErrNoRows { - return nil, nil - } else { - return nil, errors.Wrap(err, "could not get album of share token from database") - } - } +// func (r *shareTokenResolver) Owner(ctx context.Context, obj *models.ShareToken) (*models.User, error) { +// var user models.User +// if err := r.Database.First(&user, obj.OwnerID).Error; err != nil { +// return nil, err +// } - return album, nil -} +// return &user, nil +// } -func (r *shareTokenResolver) Media(ctx context.Context, obj *models.ShareToken) (*models.Media, error) { - row := r.Database.QueryRow("SELECT * FROM media WHERE media.media_id = ?", obj.MediaID) - media, err := models.NewMediaFromRow(row) - if err != nil { - if err == sql.ErrNoRows { - return nil, nil - } else { - return nil, errors.Wrap(err, "could not get media of share token from database") - } - } +// func (r *shareTokenResolver) Album(ctx context.Context, obj *models.ShareToken) (*models.Album, error) { - return media, nil -} +// var album models.Album +// if err := r.Database.First(&album, obj.AlbumID).Error; err != nil { +// return nil, err +// } + +// return &album, nil +// } + +// func (r *shareTokenResolver) Media(ctx context.Context, obj *models.ShareToken) (*models.Media, error) { + +// var media models.Media +// if err := r.Database.First(&media, obj.MediaID).Error; err != nil { +// return nil, err +// } + +// return &media, nil +// } func (r *shareTokenResolver) HasPassword(ctx context.Context, obj *models.ShareToken) (bool, error) { hasPassword := obj.Password != nil @@ -63,10 +60,9 @@ func (r *shareTokenResolver) HasPassword(ctx context.Context, obj *models.ShareT func (r *queryResolver) ShareToken(ctx context.Context, tokenValue string, password *string) (*models.ShareToken, error) { - row := r.Database.QueryRow("SELECT * FROM share_token WHERE value = ?", tokenValue) - token, err := models.NewShareTokenFromRow(row) - if err != nil { - if err == sql.ErrNoRows { + var token models.ShareToken + if err := r.Database.Where("value = ?", tokenValue).First(&token).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.New("share not found") } else { return nil, errors.Wrap(err, "failed to get share token from database") @@ -83,14 +79,13 @@ func (r *queryResolver) ShareToken(ctx context.Context, tokenValue string, passw } } - return token, nil + return &token, nil } func (r *queryResolver) ShareTokenValidatePassword(ctx context.Context, tokenValue string, password *string) (bool, error) { - row := r.Database.QueryRow("SELECT * FROM share_token WHERE value = ?", tokenValue) - token, err := models.NewShareTokenFromRow(row) - if err != nil { - if err == sql.ErrNoRows { + var token models.ShareToken + if err := r.Database.Where("value = ?", tokenValue).First(&token).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { return false, errors.New("share not found") } else { return false, errors.Wrap(err, "failed to get share token from database") @@ -116,93 +111,92 @@ func (r *queryResolver) ShareTokenValidatePassword(ctx context.Context, tokenVal return true, nil } -func (r *mutationResolver) ShareAlbum(ctx context.Context, albumID int, expire *time.Time, password *string) (*models.ShareToken, error) { +func (r *mutationResolver) ShareAlbum(ctx context.Context, albumID uint, expire *time.Time, password *string) (*models.ShareToken, error) { user := auth.UserFromContext(ctx) if user == nil { return nil, auth.ErrUnauthorized } - rows, err := r.Database.Query("SELECT owner_id FROM album WHERE album.album_id = ? AND album.owner_id = ?", albumID, user.UserID) - if err != nil { + var count int64 + if err := r.Database.Model(&models.Album{}).Where("owner_id = ?", user.ID).Count(&count).Error; err != nil { return nil, errors.Wrap(err, "failed to validate album owner with database") } - if rows.Next() == false { + + if count == 0 { return nil, auth.ErrUnauthorized } - rows.Close() - var hashed_password *string = nil + var hashedPassword *string = nil if password != nil { hashedPassBytes, err := bcrypt.GenerateFromPassword([]byte(*password), 12) if err != nil { return nil, errors.Wrap(err, "failed to hash token password") } - hashed_str := string(hashedPassBytes) - hashed_password = &hashed_str + hashedStr := string(hashedPassBytes) + hashedPassword = &hashedStr } - token := utils.GenerateToken() - res, err := r.Database.Exec("INSERT INTO share_token (value, owner_id, expire, password, album_id) VALUES (?, ?, ?, ?, ?)", token, user.UserID, expire, hashed_password, albumID) - if err != nil { + shareToken := models.ShareToken{ + Value: utils.GenerateToken(), + OwnerID: user.ID, + Expire: expire, + Password: hashedPassword, + AlbumID: &albumID, + MediaID: nil, + } + + if err := r.Database.Create(&shareToken).Error; err != nil { return nil, errors.Wrap(err, "failed to insert new share token into database") } - token_id, err := res.LastInsertId() - if err != nil { - return nil, errors.Wrap(err, "could not get database id of new album share token") - } - - return &models.ShareToken{ - TokenID: int(token_id), - Value: token, - OwnerID: user.UserID, - Expire: expire, - Password: password, - AlbumID: &albumID, - MediaID: nil, - }, nil + return &shareToken, nil } -func (r *mutationResolver) ShareMedia(ctx context.Context, mediaID int, expire *time.Time, password *string) (*models.ShareToken, error) { +func (r *mutationResolver) ShareMedia(ctx context.Context, mediaID uint, expire *time.Time, password *string) (*models.ShareToken, error) { user := auth.UserFromContext(ctx) if user == nil { return nil, auth.ErrUnauthorized } - rows, err := r.Database.Query("SELECT owner_id FROM album, media WHERE media.media_id = ? AND media.album_id = album.album_id AND album.owner_id = ?", mediaID, user.UserID) + var media models.Media + if err := r.Database.Where("owner_id = ?", user.ID).First(&media, mediaID).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, auth.ErrUnauthorized + } else { + return nil, errors.Wrap(err, "failed to validate media owner with database") + } + } + + var count int64 + + err := r.Database.Raw("SELECT owner_id FROM album, media WHERE media.media_id = ? AND media.album_id = album.album_id AND album.owner_id = ?", mediaID, user.ID).Count(&count).Error if err != nil { return nil, errors.Wrap(err, "error validating owner of media with database") } - if rows.Next() == false { + + if count == 0 { return nil, auth.ErrUnauthorized } - rows.Close() - hashed_password, err := hashSharePassword(password) + hashedPassword, err := hashSharePassword(password) if err != nil { return nil, err } - token := utils.GenerateToken() - res, err := r.Database.Exec("INSERT INTO share_token (value, owner_id, expire, password, media_id) VALUES (?, ?, ?, ?, ?)", token, user.UserID, expire, hashed_password, mediaID) - if err != nil { + shareToken := models.ShareToken{ + Value: utils.GenerateToken(), + OwnerID: user.ID, + Expire: expire, + Password: hashedPassword, + AlbumID: nil, + MediaID: &mediaID, + } + + if err := r.Database.Create(&shareToken).Error; err != nil { return nil, errors.Wrap(err, "failed to insert new share token into database") } - token_id, err := res.LastInsertId() - if err != nil { - return nil, errors.Wrap(err, "could not get database id of new media share token") - } - - return &models.ShareToken{ - TokenID: int(token_id), - Value: token, - OwnerID: user.UserID, - Expire: expire, - Password: password, - AlbumID: nil, - MediaID: &mediaID, - }, nil + return &shareToken, nil } func (r *mutationResolver) DeleteShareToken(ctx context.Context, tokenValue string) (*models.ShareToken, error) { @@ -216,7 +210,7 @@ func (r *mutationResolver) DeleteShareToken(ctx context.Context, tokenValue stri return nil, err } - if _, err := r.Database.Exec("DELETE FROM share_token WHERE token_id = ?", token.TokenID); err != nil { + if err := r.Database.Delete(&token).Error; err != nil { return nil, errors.Wrapf(err, "failed to delete share token (%s) from database", tokenValue) } @@ -234,46 +228,42 @@ func (r *mutationResolver) ProtectShareToken(ctx context.Context, tokenValue str return nil, err } - hashed_password, err := hashSharePassword(password) + hashedPassword, err := hashSharePassword(password) if err != nil { return nil, err } - _, err = r.Database.Exec("UPDATE share_token SET password = ? WHERE token_id = ?", hashed_password, token.TokenID) - if err != nil { + token.Password = hashedPassword + + if err := r.Database.Save(&token).Error; err != nil { return nil, errors.Wrap(err, "failed to update password for share token") } - updatedToken := r.Database.QueryRow("SELECT * FROM share_token WHERE value = ?", tokenValue) - return models.NewShareTokenFromRow(updatedToken) + return token, nil } func hashSharePassword(password *string) (*string, error) { - var hashed_password *string = nil + var hashedPassword *string = nil if password != nil { hashedPassBytes, err := bcrypt.GenerateFromPassword([]byte(*password), 12) if err != nil { return nil, errors.Wrap(err, "failed to generate hash for share password") } - hashed_str := string(hashedPassBytes) - hashed_password = &hashed_str + hashedStr := string(hashedPassBytes) + hashedPassword = &hashedStr } - return hashed_password, nil + return hashedPassword, nil } func getUserToken(db *gorm.DB, user *models.User, tokenValue string) (*models.ShareToken, error) { - row := db.QueryRow(` - SELECT share_token.* FROM share_token, user WHERE - share_token.value = ? AND - share_token.owner_id = user.user_id AND - (user.user_id = ? OR user.admin = TRUE) - `, tokenValue, user.UserID) - token, err := models.NewShareTokenFromRow(row) + var token models.ShareToken + err := db.Where("share_tokens.value = ?", tokenValue).Joins("Owner").Where("users.id = ? OR users.admin = TRUE").First(&token).Error + if err != nil { return nil, errors.Wrap(err, "failed to get user share token from database") } - return token, nil + return &token, nil }