diff --git a/api/gqlgen.yml b/api/gqlgen.yml index e12dcc01..8b535f37 100644 --- a/api/gqlgen.yml +++ b/api/gqlgen.yml @@ -36,3 +36,5 @@ models: model: github.com/viktorstrate/photoview/api/graphql/models.Album ShareToken: model: github.com/viktorstrate/photoview/api/graphql/models.ShareToken + SiteInfo: + model: github.com/viktorstrate/photoview/api/graphql/models.SiteInfo diff --git a/api/graphql/generated.go b/api/graphql/generated.go index a3be4d14..2c138c48 100644 --- a/api/graphql/generated.go +++ b/api/graphql/generated.go @@ -40,13 +40,10 @@ 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 { @@ -216,8 +213,6 @@ 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) @@ -226,8 +221,6 @@ type AlbumResolver interface { 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) @@ -235,10 +228,6 @@ type MediaResolver interface { 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) @@ -272,22 +261,11 @@ type QueryResolver interface { Search(ctx context.Context, query string, limitMedia *int, limitAlbums *int) (*models.SearchResult, error) } type ShareTokenResolver interface { - ID(ctx context.Context, obj *models.ShareToken) (int, error) - HasPassword(ctx context.Context, obj *models.ShareToken) (bool, 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 @@ -1330,15 +1308,15 @@ type Query { onlyWithFavorites: Boolean ): [Album!]! "Get album by id, user must own the album or be admin" - album(id: Int!): Album! + album(id: ID!): Album! "List of media owned by the logged in user" myMedia(filter: Filter): [Media!]! "Get media by id, user must own the media or be admin" - media(id: Int!): Media! + media(id: ID!): Media! "Get a list of media by their ids, user must own the media or be admin" - mediaList(ids: [Int!]!): [Media!]! + mediaList(ids: [ID!]!): [Media!]! "Get media owned by the logged in user, returned in GeoJson format" myMediaGeoJson: Any! @@ -1371,22 +1349,22 @@ type Mutation { "Scan all users for new media" scanAll: ScannerResult! @isAdmin "Scan a single user for new media" - scanUser(userId: Int!): ScannerResult! + scanUser(userId: ID!): ScannerResult! "Generate share token for album" - shareAlbum(albumId: Int!, expire: Time, password: String): ShareToken + shareAlbum(albumId: ID!, expire: Time, password: String): ShareToken "Generate share token for media" - shareMedia(mediaId: Int!, expire: Time, password: String): ShareToken + shareMedia(mediaId: ID!, expire: Time, password: String): ShareToken "Delete a share token by it's token value" deleteShareToken(token: String!): ShareToken "Set a password for a token, if null is passed for the password argument, the password will be cleared" protectShareToken(token: String!, password: String): ShareToken "Mark or unmark a media as being a favorite" - favoriteMedia(mediaId: Int!, favorite: Boolean!): Media + favoriteMedia(mediaId: ID!, favorite: Boolean!): Media updateUser( - id: Int! + id: ID! username: String rootPath: String password: String @@ -1398,7 +1376,7 @@ type Mutation { password: String admin: Boolean! ): User @isAdmin - deleteUser(id: Int!): User @isAdmin + deleteUser(id: ID!): User @isAdmin """ Set how often, in seconds, the server should automatically scan for new media, @@ -1448,7 +1426,7 @@ type ScannerResult { "A token used to publicly access an album or media" type ShareToken { - id: Int! + id: ID! token: String! "The user who created the token" owner: User! @@ -1473,7 +1451,7 @@ type SiteInfo { } type User { - id: Int! + id: ID! username: String! #albums: [Album] "Local filepath for the user's photos" @@ -1483,7 +1461,7 @@ type User { } type Album { - id: Int! + id: ID! title: String! "The media inside this album" media( @@ -1528,7 +1506,7 @@ enum MediaType { } type Media { - id: Int! + id: ID! title: String! "Local filepath for the media" path: String! @@ -1551,7 +1529,7 @@ type Media { "EXIF metadata from the camera" type MediaEXIF { - id: Int! + id: ID! media: Media! "The model name of the camera" camera: String @@ -1575,14 +1553,14 @@ type MediaEXIF { } type VideoMetadata { - id: Int! + id: ID! media: Media! width: Int! height: Int! duration: Float! codec: String framerate: Float - bitrate: Int + bitrate: String colorProfile: String audio: String } @@ -1726,7 +1704,7 @@ func (ec *executionContext) field_Mutation_deleteUser_args(ctx context.Context, var arg0 int if tmp, ok := rawArgs["id"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - arg0, err = ec.unmarshalNInt2int(ctx, tmp) + arg0, err = ec.unmarshalNID2int(ctx, tmp) if err != nil { return nil, err } @@ -1741,7 +1719,7 @@ func (ec *executionContext) field_Mutation_favoriteMedia_args(ctx context.Contex var arg0 int if tmp, ok := rawArgs["mediaId"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("mediaId")) - arg0, err = ec.unmarshalNInt2int(ctx, tmp) + arg0, err = ec.unmarshalNID2int(ctx, tmp) if err != nil { return nil, err } @@ -1855,7 +1833,7 @@ func (ec *executionContext) field_Mutation_scanUser_args(ctx context.Context, ra var arg0 int if tmp, ok := rawArgs["userId"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("userId")) - arg0, err = ec.unmarshalNInt2int(ctx, tmp) + arg0, err = ec.unmarshalNID2int(ctx, tmp) if err != nil { return nil, err } @@ -1900,7 +1878,7 @@ func (ec *executionContext) field_Mutation_shareAlbum_args(ctx context.Context, var arg0 int if tmp, ok := rawArgs["albumId"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("albumId")) - arg0, err = ec.unmarshalNInt2int(ctx, tmp) + arg0, err = ec.unmarshalNID2int(ctx, tmp) if err != nil { return nil, err } @@ -1933,7 +1911,7 @@ func (ec *executionContext) field_Mutation_shareMedia_args(ctx context.Context, var arg0 int if tmp, ok := rawArgs["mediaId"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("mediaId")) - arg0, err = ec.unmarshalNInt2int(ctx, tmp) + arg0, err = ec.unmarshalNID2int(ctx, tmp) if err != nil { return nil, err } @@ -1966,7 +1944,7 @@ func (ec *executionContext) field_Mutation_updateUser_args(ctx context.Context, var arg0 int if tmp, ok := rawArgs["id"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - arg0, err = ec.unmarshalNInt2int(ctx, tmp) + arg0, err = ec.unmarshalNID2int(ctx, tmp) if err != nil { return nil, err } @@ -2032,7 +2010,7 @@ func (ec *executionContext) field_Query_album_args(ctx context.Context, rawArgs var arg0 int if tmp, ok := rawArgs["id"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - arg0, err = ec.unmarshalNInt2int(ctx, tmp) + arg0, err = ec.unmarshalNID2int(ctx, tmp) if err != nil { return nil, err } @@ -2047,7 +2025,7 @@ func (ec *executionContext) field_Query_mediaList_args(ctx context.Context, rawA var arg0 []int if tmp, ok := rawArgs["ids"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("ids")) - arg0, err = ec.unmarshalNInt2ᚕintᚄ(ctx, tmp) + arg0, err = ec.unmarshalNID2ᚕintᚄ(ctx, tmp) if err != nil { return nil, err } @@ -2062,7 +2040,7 @@ func (ec *executionContext) field_Query_media_args(ctx context.Context, rawArgs var arg0 int if tmp, ok := rawArgs["id"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - arg0, err = ec.unmarshalNInt2int(ctx, tmp) + arg0, err = ec.unmarshalNID2int(ctx, tmp) if err != nil { return nil, err } @@ -2273,14 +2251,14 @@ func (ec *executionContext) _Album_id(ctx context.Context, field graphql.Collect 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().ID(rctx, obj) + return obj.ID, nil }) if err != nil { ec.Error(ctx, err) @@ -2294,7 +2272,7 @@ func (ec *executionContext) _Album_id(ctx context.Context, field graphql.Collect } res := resTmp.(int) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNID2int(ctx, field.Selections, res) } func (ec *executionContext) _Album_title(ctx context.Context, field graphql.CollectedField, obj *models.Album) (ret graphql.Marshaler) { @@ -2730,14 +2708,14 @@ func (ec *executionContext) _Media_id(ctx context.Context, field graphql.Collect 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().ID(rctx, obj) + return obj.ID, nil }) if err != nil { ec.Error(ctx, err) @@ -2751,7 +2729,7 @@ func (ec *executionContext) _Media_id(ctx context.Context, field graphql.Collect } res := resTmp.(int) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNID2int(ctx, field.Selections, res) } func (ec *executionContext) _Media_title(ctx context.Context, field graphql.CollectedField, obj *models.Media) (ret graphql.Marshaler) { @@ -3243,14 +3221,14 @@ func (ec *executionContext) _MediaEXIF_id(ctx context.Context, field graphql.Col Object: "MediaEXIF", 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.MediaEXIF().ID(rctx, obj) + return obj.ID, nil }) if err != nil { ec.Error(ctx, err) @@ -3264,7 +3242,7 @@ func (ec *executionContext) _MediaEXIF_id(ctx context.Context, field graphql.Col } res := resTmp.(int) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNID2int(ctx, field.Selections, res) } func (ec *executionContext) _MediaEXIF_media(ctx context.Context, field graphql.CollectedField, obj *models.MediaEXIF) (ret graphql.Marshaler) { @@ -3279,13 +3257,13 @@ func (ec *executionContext) _MediaEXIF_media(ctx context.Context, field graphql. Field: field, Args: nil, IsMethod: true, - IsResolver: true, + 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.MediaEXIF().Media(rctx, obj) + return obj.Media(), nil }) if err != nil { ec.Error(ctx, err) @@ -5568,14 +5546,14 @@ func (ec *executionContext) _ShareToken_id(ctx context.Context, field graphql.Co 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().ID(rctx, obj) + return obj.ID, nil }) if err != nil { ec.Error(ctx, err) @@ -5589,7 +5567,7 @@ func (ec *executionContext) _ShareToken_id(ctx context.Context, field graphql.Co } res := resTmp.(int) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNID2int(ctx, field.Selections, res) } func (ec *executionContext) _ShareToken_token(ctx context.Context, field graphql.CollectedField, obj *models.ShareToken) (ret graphql.Marshaler) { @@ -5994,14 +5972,14 @@ func (ec *executionContext) _User_id(ctx context.Context, field graphql.Collecte Object: "User", 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.User().ID(rctx, obj) + return obj.ID, nil }) if err != nil { ec.Error(ctx, err) @@ -6015,7 +5993,7 @@ func (ec *executionContext) _User_id(ctx context.Context, field graphql.Collecte } res := resTmp.(int) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNID2int(ctx, field.Selections, res) } func (ec *executionContext) _User_username(ctx context.Context, field graphql.CollectedField, obj *models.User) (ret graphql.Marshaler) { @@ -6154,14 +6132,14 @@ func (ec *executionContext) _VideoMetadata_id(ctx context.Context, field graphql Object: "VideoMetadata", 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.VideoMetadata().ID(rctx, obj) + return obj.ID, nil }) if err != nil { ec.Error(ctx, err) @@ -6175,7 +6153,7 @@ func (ec *executionContext) _VideoMetadata_id(ctx context.Context, field graphql } res := resTmp.(int) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNID2int(ctx, field.Selections, res) } func (ec *executionContext) _VideoMetadata_media(ctx context.Context, field graphql.CollectedField, obj *models.VideoMetadata) (ret graphql.Marshaler) { @@ -6190,13 +6168,13 @@ func (ec *executionContext) _VideoMetadata_media(ctx context.Context, field grap Field: field, Args: nil, IsMethod: true, - IsResolver: true, + 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.VideoMetadata().Media(rctx, obj) + return obj.Media(), nil }) if err != nil { ec.Error(ctx, err) @@ -6393,14 +6371,14 @@ func (ec *executionContext) _VideoMetadata_bitrate(ctx context.Context, field gr Object: "VideoMetadata", 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.VideoMetadata().Bitrate(rctx, obj) + return obj.Bitrate, nil }) if err != nil { ec.Error(ctx, err) @@ -6409,9 +6387,9 @@ func (ec *executionContext) _VideoMetadata_bitrate(ctx context.Context, field gr if resTmp == nil { return graphql.Null } - res := resTmp.(*int) + res := resTmp.(*string) fc.Result = res - return ec.marshalOInt2ᚖint(ctx, field.Selections, res) + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } func (ec *executionContext) _VideoMetadata_colorProfile(ctx context.Context, field graphql.CollectedField, obj *models.VideoMetadata) (ret graphql.Marshaler) { @@ -7629,19 +7607,10 @@ func (ec *executionContext) _Album(ctx context.Context, sel ast.SelectionSet, ob case "__typename": out.Values[i] = graphql.MarshalString("Album") case "id": - 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 - }) + out.Values[i] = ec._Album_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } case "title": out.Values[i] = ec._Album_title(ctx, field, obj) if out.Values[i] == graphql.Null { @@ -7780,19 +7749,10 @@ func (ec *executionContext) _Media(ctx context.Context, sel ast.SelectionSet, ob case "__typename": out.Values[i] = graphql.MarshalString("Media") case "id": - 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 - }) + out.Values[i] = ec._Media_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } case "title": out.Values[i] = ec._Media_title(ctx, field, obj) if out.Values[i] == graphql.Null { @@ -7941,33 +7901,15 @@ func (ec *executionContext) _MediaEXIF(ctx context.Context, sel ast.SelectionSet case "__typename": out.Values[i] = graphql.MarshalString("MediaEXIF") case "id": - 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 - }) + out.Values[i] = ec._MediaEXIF_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } 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._MediaEXIF_media(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - return res - }) + out.Values[i] = ec._MediaEXIF_media(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } case "camera": out.Values[i] = ec._MediaEXIF_camera(ctx, field, obj) case "maker": @@ -8465,19 +8407,10 @@ func (ec *executionContext) _ShareToken(ctx context.Context, sel ast.SelectionSe case "__typename": out.Values[i] = graphql.MarshalString("ShareToken") case "id": - 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_id(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - return res - }) + 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 { @@ -8588,33 +8521,24 @@ func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj case "__typename": out.Values[i] = graphql.MarshalString("User") case "id": - 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 - }) + out.Values[i] = ec._User_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } case "username": out.Values[i] = ec._User_username(ctx, field, obj) if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) + invalids++ } case "rootPath": out.Values[i] = ec._User_rootPath(ctx, field, obj) if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) + invalids++ } case "admin": out.Values[i] = ec._User_admin(ctx, field, obj) if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) + invalids++ } default: panic("unknown field " + strconv.Quote(field.Name)) @@ -8639,63 +8563,36 @@ func (ec *executionContext) _VideoMetadata(ctx context.Context, sel ast.Selectio case "__typename": out.Values[i] = graphql.MarshalString("VideoMetadata") case "id": - 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 - }) + out.Values[i] = ec._VideoMetadata_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } 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._VideoMetadata_media(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - return res - }) + out.Values[i] = ec._VideoMetadata_media(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } case "width": out.Values[i] = ec._VideoMetadata_width(ctx, field, obj) if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) + invalids++ } case "height": out.Values[i] = ec._VideoMetadata_height(ctx, field, obj) if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) + invalids++ } case "duration": out.Values[i] = ec._VideoMetadata_duration(ctx, field, obj) if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) + invalids++ } case "codec": out.Values[i] = ec._VideoMetadata_codec(ctx, field, obj) case "framerate": out.Values[i] = ec._VideoMetadata_framerate(ctx, field, obj) case "bitrate": - 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 - }) + out.Values[i] = ec._VideoMetadata_bitrate(ctx, field, obj) case "colorProfile": out.Values[i] = ec._VideoMetadata_colorProfile(ctx, field, obj) case "audio": @@ -9072,6 +8969,51 @@ func (ec *executionContext) marshalNFloat2float64(ctx context.Context, sel ast.S return res } +func (ec *executionContext) unmarshalNID2int(ctx context.Context, v interface{}) (int, error) { + res, err := graphql.UnmarshalIntID(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNID2int(ctx context.Context, sel ast.SelectionSet, v int) graphql.Marshaler { + res := graphql.MarshalIntID(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + } + return res +} + +func (ec *executionContext) unmarshalNID2ᚕintᚄ(ctx context.Context, v interface{}) ([]int, error) { + var vSlice []interface{} + if v != nil { + if tmp1, ok := v.([]interface{}); ok { + vSlice = tmp1 + } else { + vSlice = []interface{}{v} + } + } + var err error + res := make([]int, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNID2int(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalNID2ᚕintᚄ(ctx context.Context, sel ast.SelectionSet, v []int) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + for i := range v { + ret[i] = ec.marshalNID2int(ctx, sel, v[i]) + } + + return ret +} + func (ec *executionContext) unmarshalNInt2int(ctx context.Context, v interface{}) (int, error) { res, err := graphql.UnmarshalInt(v) return res, graphql.ErrorOnPath(ctx, err) @@ -9102,36 +9044,6 @@ func (ec *executionContext) marshalNInt2int64(ctx context.Context, sel ast.Selec return res } -func (ec *executionContext) unmarshalNInt2ᚕintᚄ(ctx context.Context, v interface{}) ([]int, error) { - var vSlice []interface{} - if v != nil { - if tmp1, ok := v.([]interface{}); ok { - vSlice = tmp1 - } else { - vSlice = []interface{}{v} - } - } - var err error - res := make([]int, len(vSlice)) - for i := range vSlice { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNInt2int(ctx, vSlice[i]) - if err != nil { - return nil, err - } - } - return res, nil -} - -func (ec *executionContext) marshalNInt2ᚕintᚄ(ctx context.Context, sel ast.SelectionSet, v []int) graphql.Marshaler { - ret := make(graphql.Array, len(v)) - for i := range v { - ret[i] = ec.marshalNInt2int(ctx, sel, v[i]) - } - - return ret -} - func (ec *executionContext) marshalNMedia2githubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐMedia(ctx context.Context, sel ast.SelectionSet, v models.Media) graphql.Marshaler { return ec._Media(ctx, sel, &v) } diff --git a/api/graphql/models/album.go b/api/graphql/models/album.go index b4d86763..161e9a32 100644 --- a/api/graphql/models/album.go +++ b/api/graphql/models/album.go @@ -8,11 +8,11 @@ import ( ) type Album struct { - gorm.Model + Model Title string - ParentAlbumID *uint + ParentAlbumID *int ParentAlbum *Album - OwnerID uint + OwnerID int Owner User Path string PathHash string `gorm:"unique"` diff --git a/api/graphql/models/base.go b/api/graphql/models/base.go new file mode 100644 index 00000000..9d4147dd --- /dev/null +++ b/api/graphql/models/base.go @@ -0,0 +1,14 @@ +package models + +import ( + "time" + + "gorm.io/gorm" +) + +type Model struct { + ID int `gorm:"primarykey"` + CreatedAt time.Time + UpdatedAt time.Time + DeletedAt gorm.DeletedAt `gorm:"index"` +} diff --git a/api/graphql/models/generated.go b/api/graphql/models/generated.go index 3413a2e6..09b0b8c0 100644 --- a/api/graphql/models/generated.go +++ b/api/graphql/models/generated.go @@ -51,15 +51,6 @@ type SearchResult struct { Media []*Media `json:"media"` } -// 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 MediaType string const ( diff --git a/api/graphql/models/media.go b/api/graphql/models/media.go index 2651e046..4bc70f69 100644 --- a/api/graphql/models/media.go +++ b/api/graphql/models/media.go @@ -6,24 +6,23 @@ import ( "time" "github.com/viktorstrate/photoview/api/utils" - "gorm.io/gorm" ) type Media struct { - gorm.Model + Model Title string Path string PathHash string - AlbumID uint + AlbumID int Album Album - ExifID *uint + ExifID *int Exif *MediaEXIF MediaURL []MediaURL DateShot time.Time DateImported time.Time Favorite bool Type MediaType - VideoMetadataID *uint + VideoMetadataID *int VideoMetadata *VideoMetadata SideCarPath *string SideCarHash *string @@ -44,8 +43,8 @@ const ( ) type MediaURL struct { - gorm.Model - MediaID uint + Model + MediaID int Media Media MediaName string Width int diff --git a/api/graphql/models/media_exif.go b/api/graphql/models/media_exif.go index 6090cbb1..f4a98f8b 100644 --- a/api/graphql/models/media_exif.go +++ b/api/graphql/models/media_exif.go @@ -2,12 +2,10 @@ package models import ( "time" - - "gorm.io/gorm" ) type MediaEXIF struct { - gorm.Model + Model Camera *string Maker *string Lens *string @@ -22,3 +20,7 @@ type MediaEXIF struct { GPSLatitude *float64 GPSLonitude *float64 } + +func (exif *MediaEXIF) Media() *Media { + panic("not implemented") +} diff --git a/api/graphql/models/share_token.go b/api/graphql/models/share_token.go index a60a5cdc..055eebf6 100644 --- a/api/graphql/models/share_token.go +++ b/api/graphql/models/share_token.go @@ -2,20 +2,18 @@ package models import ( "time" - - "gorm.io/gorm" ) type ShareToken struct { - gorm.Model + Model Value string - OwnerID uint + OwnerID int Owner User Expire *time.Time Password *string - AlbumID *uint + AlbumID *int Album Album - MediaID *uint + MediaID *int Media *Media } diff --git a/api/graphql/models/site_info.go b/api/graphql/models/site_info.go index 0dc6f19a..97b9bec8 100644 --- a/api/graphql/models/site_info.go +++ b/api/graphql/models/site_info.go @@ -6,7 +6,7 @@ import ( ) type SiteInfo struct { - gorm.Model + Model InitialSetup bool PeriodicScanInterval int ConcurrentWorkers int diff --git a/api/graphql/models/user.go b/api/graphql/models/user.go index 5b8d6a82..864c70d0 100644 --- a/api/graphql/models/user.go +++ b/api/graphql/models/user.go @@ -13,7 +13,7 @@ import ( ) type User struct { - gorm.Model + Model Username string `gorm:"unique,size:128"` Password *string `gorm:"size:256` RootPath string `gorm:"size:512` @@ -25,8 +25,8 @@ type User struct { // } type AccessToken struct { - gorm.Model - UserID uint + Model + UserID int User User `gorm:"constraint:OnDelete:CASCADE;"` Value string `gorm:"size:24` Expire time.Time diff --git a/api/graphql/models/utils.go b/api/graphql/models/utils.go index 5cec5a41..6a446b4d 100644 --- a/api/graphql/models/utils.go +++ b/api/graphql/models/utils.go @@ -6,6 +6,8 @@ import ( ) func (filter *Filter) FormatSQL(context string) (string, error) { + // TODO: Migrate method to gorm + if filter == nil { return "", nil } diff --git a/api/graphql/models/video_metadata.go b/api/graphql/models/video_metadata.go index 727e4968..75f2efa9 100644 --- a/api/graphql/models/video_metadata.go +++ b/api/graphql/models/video_metadata.go @@ -1,11 +1,7 @@ package models -import ( - "gorm.io/gorm" -) - type VideoMetadata struct { - gorm.Model + Model Width int Height int Duration float64 @@ -15,3 +11,7 @@ type VideoMetadata struct { ColorProfile *string Audio *string } + +func (metadata *VideoMetadata) Media() *Media { + panic("not implemented") +} diff --git a/api/graphql/resolvers/album.go b/api/graphql/resolvers/album.go index 5d0353a7..f4b98e35 100644 --- a/api/graphql/resolvers/album.go +++ b/api/graphql/resolvers/album.go @@ -2,7 +2,8 @@ package resolvers import ( "context" - "database/sql" + "fmt" + "log" api "github.com/viktorstrate/photoview/api/graphql" "github.com/viktorstrate/photoview/api/graphql/auth" @@ -15,41 +16,26 @@ func (r *queryResolver) MyAlbums(ctx context.Context, filter *models.Filter, onl return nil, auth.ErrUnauthorized } - filterSQL, err := filter.FormatSQL("album") - if err != nil { - return nil, err + query := r.Database.Where("owner_id = ?", user.ID) + + if onlyRoot != nil && *onlyRoot == true { + query = query.Where("parent_album = ()", query.Model(&models.Album{})).Select("id").Where("parent_album IS NULL AND owner_id = ?", user.ID) } - var rows *sql.Rows + if showEmpty == nil || *showEmpty == false { + subQuery := r.Database.Model(&models.Media{}).Where("album_id = album.album_id") - filterFavorites := " AND favorite = 1" - if onlyWithFavorites == nil || *onlyWithFavorites == false { - filterFavorites = "" - } - - filterEmpty := " AND EXISTS (SELECT * FROM media WHERE album_id = album.album_id" + filterFavorites + ") " - if showEmpty != nil && *showEmpty == true && (onlyWithFavorites == nil || *onlyWithFavorites == false) { - filterEmpty = "" - } - - if onlyRoot == nil || *onlyRoot == false { - rows, err = r.Database.Query("SELECT * FROM album WHERE owner_id = ?"+filterEmpty+filterSQL, user.UserID) - if err != nil { - return nil, err - } - } else { - rows, err = r.Database.Query(` - SELECT * FROM album WHERE owner_id = ? AND parent_album = ( - SELECT album_id FROM album WHERE parent_album IS NULL AND owner_id = ? - ) - `+filterEmpty+filterSQL, user.UserID, user.UserID) - if err != nil { - return nil, err + if onlyWithFavorites != nil && *onlyWithFavorites == true { + subQuery = subQuery.Where("favorite = 1") } + + query = query.Where("EXISTS (?)", subQuery) } - albums, err := models.NewAlbumsFromRows(rows) - if err != nil { + // TODO: Incorporate models.FormatSQL + + var albums []*models.Album + if err := query.Find(albums).Error; err != nil { return nil, err } @@ -62,13 +48,12 @@ func (r *queryResolver) Album(ctx context.Context, id int) (*models.Album, error return nil, auth.ErrUnauthorized } - row := r.Database.QueryRow("SELECT * FROM album WHERE album_id = ? AND owner_id = ?", id, user.UserID) - album, err := models.NewAlbumFromRow(row) - if err != nil { + var album models.Album + if err := r.Database.Where("owner_id = ?", user.ID).First(&album, id).Error; err != nil { return nil, err } - return album, nil + return &album, nil } func (r *Resolver) Album() api.AlbumResolver { @@ -77,32 +62,21 @@ func (r *Resolver) Album() api.AlbumResolver { type albumResolver struct{ *Resolver } -func (r *albumResolver) Media(ctx context.Context, obj *models.Album, filter *models.Filter, onlyFavorites *bool) ([]*models.Media, error) { +func (r *albumResolver) Media(ctx context.Context, album *models.Album, filter *models.Filter, onlyFavorites *bool) ([]*models.Media, error) { - filterSQL, err := filter.FormatSQL("media") - if err != nil { - return nil, err + query := r.Database. + Joins("Album"). + Where("Album.id = ?", album.ID). + Where("media.id IN (?)", r.Database.Model(&models.MediaURL{})).Select("media_id").Where("media_url.media_id = media.id") + + if onlyFavorites != nil && *onlyFavorites == true { + query = query.Where("media.favorite = 1") } - filterFavorites := " AND media.favorite = 1 " - if onlyFavorites == nil || *onlyFavorites == false { - filterFavorites = "" - } + // TODO: Incorporate filter.FormatSQL - mediaRows, err := r.Database.Query(` - SELECT media.* FROM album, media - WHERE album.album_id = ? AND media.album_id = album.album_id - AND media.media_id IN ( - SELECT media_id FROM media_url WHERE media_url.media_id = media.media_id - ) - `+filterFavorites+filterSQL, obj.AlbumID) - if err != nil { - return nil, err - } - defer mediaRows.Close() - - media, err := models.NewMediaFromRows(mediaRows) - if err != nil { + var media []*models.Media + if err := query.Find(&media).Error; err != nil { return nil, err } @@ -111,47 +85,44 @@ func (r *albumResolver) Media(ctx context.Context, obj *models.Album, filter *mo func (r *albumResolver) Thumbnail(ctx context.Context, obj *models.Album) (*models.Media, error) { - row := r.Database.QueryRow(` - WITH recursive sub_albums AS ( - SELECT * FROM album AS root WHERE album_id = ? - UNION ALL - SELECT child.* FROM album AS child JOIN sub_albums ON child.parent_album = sub_albums.album_id - ) + log.Println("TODO: Album thumbnail migrated yet") - SELECT * FROM media WHERE media.album_id IN ( - SELECT album_id FROM sub_albums - ) AND media.media_id IN ( - SELECT media_id FROM media_url WHERE media_url.media_id = media.media_id - ) LIMIT 1 - `, obj.AlbumID) + return nil, nil - media, err := models.NewMediaFromRow(row) - if err != nil { - if err == sql.ErrNoRows { - return nil, nil - } else { - return nil, err - } - } + // row := r.Database.QueryRow(` + // WITH recursive sub_albums AS ( + // SELECT * FROM album AS root WHERE album_id = ? + // UNION ALL + // SELECT child.* FROM album AS child JOIN sub_albums ON child.parent_album = sub_albums.album_id + // ) - return media, nil + // SELECT * FROM media WHERE media.album_id IN ( + // SELECT album_id FROM sub_albums + // ) AND media.media_id IN ( + // SELECT media_id FROM media_url WHERE media_url.media_id = media.media_id + // ) LIMIT 1 + // `, obj.AlbumID) + + // media, err := models.NewMediaFromRow(row) + // if err != nil { + // if err == sql.ErrNoRows { + // return nil, nil + // } else { + // return nil, err + // } + // } + + // return media, nil } -func (r *albumResolver) SubAlbums(ctx context.Context, obj *models.Album, filter *models.Filter) ([]*models.Album, error) { - filterSQL, err := filter.FormatSQL("album") - if err != nil { +func (r *albumResolver) SubAlbums(ctx context.Context, parent *models.Album, filter *models.Filter) ([]*models.Album, error) { + + var albums []*models.Album + if err := r.Database.Where("parent_album = ?", parent.ID).Find(albums).Error; err != nil { return nil, err } - rows, err := r.Database.Query("SELECT * FROM album WHERE parent_album = ?"+filterSQL, obj.AlbumID) - if err != nil { - return nil, err - } - - albums, err := models.NewAlbumsFromRows(rows) - if err != nil { - return nil, err - } + // TODO: Incorporate filter.FormatSQL return albums, nil } @@ -164,34 +135,38 @@ func (r *albumResolver) Owner(ctx context.Context, obj *models.Album) (*models.U panic("not implemented") } -func (r *albumResolver) Shares(ctx context.Context, obj *models.Album) ([]*models.ShareToken, error) { - rows, err := r.Database.Query("SELECT * FROM share_token WHERE album_id = ?", obj.ID()) - if err != nil { +func (r *albumResolver) Shares(ctx context.Context, album *models.Album) ([]*models.ShareToken, error) { + + var shareTokens []*models.ShareToken + if err := r.Database.Where("album_id = ?", album.ID).Find(shareTokens).Error; err != nil { return nil, err } - defer rows.Close() - return models.NewShareTokensFromRows(rows) + return shareTokens, nil } func (r *albumResolver) Path(ctx context.Context, obj *models.Album) ([]*models.Album, error) { - user := auth.UserFromContext(ctx) - if user == nil { - empty := make([]*models.Album, 0) - return empty, nil - } - rows, err := r.Database.Query(` - WITH recursive path_albums AS ( - SELECT * FROM album anchor WHERE anchor.album_id = ? - UNION - SELECT parent.* FROM path_albums child JOIN album parent ON parent.album_id = child.parent_album - ) - SELECT * FROM path_albums WHERE album_id != ? AND owner_id = ? - `, obj.AlbumID, obj.AlbumID, user.UserID) - if err != nil { - return nil, err - } + fmt.Println("TODO: Album path not migrated yet") - return models.NewAlbumsFromRows(rows) + return make([]*models.Album, 0), nil + // user := auth.UserFromContext(ctx) + // if user == nil { + // empty := make([]*models.Album, 0) + // return empty, nil + // } + + // rows, err := r.Database.Query(` + // WITH recursive path_albums AS ( + // SELECT * FROM album anchor WHERE anchor.album_id = ? + // UNION + // SELECT parent.* FROM path_albums child JOIN album parent ON parent.album_id = child.parent_album + // ) + // SELECT * FROM path_albums WHERE album_id != ? AND owner_id = ? + // `, obj.AlbumID, obj.AlbumID, user.UserID) + // if err != nil { + // return nil, err + // } + + // return models.NewAlbumsFromRows(rows) } diff --git a/api/graphql/resolvers/mediaGeoJson.go b/api/graphql/resolvers/mediaGeoJson.go index ea4de3ec..0f12f1a7 100644 --- a/api/graphql/resolvers/mediaGeoJson.go +++ b/api/graphql/resolvers/mediaGeoJson.go @@ -2,12 +2,7 @@ package resolvers import ( "context" - "errors" "os" - "path" - - "github.com/viktorstrate/photoview/api/graphql/auth" - "github.com/viktorstrate/photoview/api/utils" ) type geoJSONFeatureCollection struct { @@ -62,69 +57,71 @@ func makeGeoJSONFeatureGeometryPoint(lat float64, long float64) geoJSONFeatureGe func (r *queryResolver) MyMediaGeoJSON(ctx context.Context) (interface{}, error) { - user := auth.UserFromContext(ctx) - if user == nil { - return nil, errors.New("unauthorized") - } + // user := auth.UserFromContext(ctx) + // if user == nil { + // return nil, errors.New("unauthorized") + // } - rows, err := r.Database.Query(` - SELECT media.media_id, media.title, - url.media_name AS thumbnail_name, url.width AS thumbnail_width, url.height AS thumbnail_height, - exif.gps_latitude, exif.gps_longitude FROM media_exif exif - INNER JOIN media ON exif.exif_id = media.exif_id - INNER JOIN media_url url ON media.media_id = url.media_id - INNER JOIN album ON media.album_id = album.album_id - WHERE exif.gps_latitude IS NOT NULL - AND exif.gps_longitude IS NOT NULL - AND url.purpose = 'thumbnail' - AND album.owner_id = ?; - `, user.UserID) - defer rows.Close() - if err != nil { - return nil, err - } + // rows, err := r.Database.Query(` + // SELECT media.media_id, media.title, + // url.media_name AS thumbnail_name, url.width AS thumbnail_width, url.height AS thumbnail_height, + // exif.gps_latitude, exif.gps_longitude FROM media_exif exif + // INNER JOIN media ON exif.exif_id = media.exif_id + // INNER JOIN media_url url ON media.media_id = url.media_id + // INNER JOIN album ON media.album_id = album.album_id + // WHERE exif.gps_latitude IS NOT NULL + // AND exif.gps_longitude IS NOT NULL + // AND url.purpose = 'thumbnail' + // AND album.owner_id = ?; + // `, user.UserID) + // defer rows.Close() + // if err != nil { + // return nil, err + // } - features := make([]geoJSONFeature, 0) + // features := make([]geoJSONFeature, 0) - for rows.Next() { + // for rows.Next() { - var mediaID int - var mediaTitle string - var thumbnailName string - var thumbnailWidth int - var thumbnailHeight int - var latitude float64 - var longitude float64 + // var mediaID int + // var mediaTitle string + // var thumbnailName string + // var thumbnailWidth int + // var thumbnailHeight int + // var latitude float64 + // var longitude float64 - if err := rows.Scan(&mediaID, &mediaTitle, &thumbnailName, &thumbnailWidth, &thumbnailHeight, &latitude, &longitude); err != nil { - return nil, err - } + // if err := rows.Scan(&mediaID, &mediaTitle, &thumbnailName, &thumbnailWidth, &thumbnailHeight, &latitude, &longitude); err != nil { + // return nil, err + // } - geoPoint := makeGeoJSONFeatureGeometryPoint(latitude, longitude) + // geoPoint := makeGeoJSONFeatureGeometryPoint(latitude, longitude) - thumbnailURL := utils.ApiEndpointUrl() - thumbnailURL.Path = path.Join(thumbnailURL.Path, "photo", thumbnailName) + // thumbnailURL := utils.ApiEndpointUrl() + // thumbnailURL.Path = path.Join(thumbnailURL.Path, "photo", thumbnailName) - properties := geoJSONMediaProperties{ - MediaID: mediaID, - MediaTitle: mediaTitle, - Thumbnail: struct { - URL string `json:"url"` - Width int `json:"width"` - Height int `json:"height"` - }{ - URL: thumbnailURL.String(), - Width: thumbnailWidth, - Height: thumbnailHeight, - }, - } + // properties := geoJSONMediaProperties{ + // MediaID: mediaID, + // MediaTitle: mediaTitle, + // Thumbnail: struct { + // URL string `json:"url"` + // Width int `json:"width"` + // Height int `json:"height"` + // }{ + // URL: thumbnailURL.String(), + // Width: thumbnailWidth, + // Height: thumbnailHeight, + // }, + // } - features = append(features, makeGeoJSONFeature(properties, geoPoint)) - } + // features = append(features, makeGeoJSONFeature(properties, geoPoint)) + // } - featureCollection := makeGeoJSONFeatureCollection(features) + // featureCollection := makeGeoJSONFeatureCollection(features) - return featureCollection, nil + // return featureCollection, nil + + panic("to be migrated") } func (r *queryResolver) MapboxToken(ctx context.Context) (*string, error) { diff --git a/api/graphql/resolvers/search.go b/api/graphql/resolvers/search.go index 47a7d01f..47064956 100644 --- a/api/graphql/resolvers/search.go +++ b/api/graphql/resolvers/search.go @@ -3,71 +3,70 @@ package resolvers import ( "context" - "github.com/pkg/errors" - "github.com/viktorstrate/photoview/api/graphql/auth" "github.com/viktorstrate/photoview/api/graphql/models" ) func (r *Resolver) Search(ctx context.Context, query string, _limitMedia *int, _limitAlbums *int) (*models.SearchResult, error) { - user := auth.UserFromContext(ctx) - if user == nil { - return nil, auth.ErrUnauthorized - } + // user := auth.UserFromContext(ctx) + // if user == nil { + // return nil, auth.ErrUnauthorized + // } - limitMedia := 10 - limitAlbums := 10 + // limitMedia := 10 + // limitAlbums := 10 - if _limitMedia != nil { - limitMedia = *_limitMedia - } + // if _limitMedia != nil { + // limitMedia = *_limitMedia + // } - if _limitAlbums != nil { - limitAlbums = *_limitAlbums - } + // if _limitAlbums != nil { + // limitAlbums = *_limitAlbums + // } - wildQuery := "%" + query + "%" + // wildQuery := "%" + query + "%" - photoRows, err := r.Database.Query(` - SELECT media.* FROM media JOIN album ON media.album_id = album.album_id - WHERE album.owner_id = ? AND ( media.title LIKE ? OR media.path LIKE ? ) - ORDER BY ( - case when media.title LIKE ? then 2 - when media.path LIKE ? then 1 - end ) DESC - LIMIT ? - `, user.UserID, wildQuery, wildQuery, wildQuery, wildQuery, limitMedia) - if err != nil { - return nil, errors.Wrapf(err, "searching media") - } + // photoRows, err := r.Database.Query(` + // SELECT media.* FROM media JOIN album ON media.album_id = album.album_id + // WHERE album.owner_id = ? AND ( media.title LIKE ? OR media.path LIKE ? ) + // ORDER BY ( + // case when media.title LIKE ? then 2 + // when media.path LIKE ? then 1 + // end ) DESC + // LIMIT ? + // `, user.UserID, wildQuery, wildQuery, wildQuery, wildQuery, limitMedia) + // if err != nil { + // return nil, errors.Wrapf(err, "searching media") + // } - photos, err := models.NewMediaFromRows(photoRows) - if err != nil { - return nil, err - } + // photos, err := models.NewMediaFromRows(photoRows) + // if err != nil { + // return nil, err + // } - albumRows, err := r.Database.Query(` - SELECT * FROM album - WHERE owner_id = ? AND ( title LIKE ? OR path LIKE ? ) - ORDER BY ( - case when title LIKE ? then 2 - when path LIKE ? then 1 - end ) DESC - LIMIT ? - `, user.UserID, wildQuery, wildQuery, wildQuery, wildQuery, limitAlbums) - if err != nil { - return nil, errors.Wrapf(err, "searching albums") - } + // albumRows, err := r.Database.Query(` + // SELECT * FROM album + // WHERE owner_id = ? AND ( title LIKE ? OR path LIKE ? ) + // ORDER BY ( + // case when title LIKE ? then 2 + // when path LIKE ? then 1 + // end ) DESC + // LIMIT ? + // `, user.UserID, wildQuery, wildQuery, wildQuery, wildQuery, limitAlbums) + // if err != nil { + // return nil, errors.Wrapf(err, "searching albums") + // } - albums, err := models.NewAlbumsFromRows(albumRows) - if err != nil { - return nil, err - } + // albums, err := models.NewAlbumsFromRows(albumRows) + // if err != nil { + // return nil, err + // } - result := models.SearchResult{ - Query: query, - Media: photos, - Albums: albums, - } + // result := models.SearchResult{ + // Query: query, + // Media: photos, + // Albums: albums, + // } - return &result, nil + // return &result, nil + panic("to be migrated") } diff --git a/api/graphql/resolvers/share_token.go b/api/graphql/resolvers/share_token.go index c1d8792f..8fcb32c9 100644 --- a/api/graphql/resolvers/share_token.go +++ b/api/graphql/resolvers/share_token.go @@ -111,7 +111,7 @@ func (r *queryResolver) ShareTokenValidatePassword(ctx context.Context, tokenVal return true, nil } -func (r *mutationResolver) ShareAlbum(ctx context.Context, albumID uint, expire *time.Time, password *string) (*models.ShareToken, error) { +func (r *mutationResolver) ShareAlbum(ctx context.Context, albumID int, expire *time.Time, password *string) (*models.ShareToken, error) { user := auth.UserFromContext(ctx) if user == nil { return nil, auth.ErrUnauthorized @@ -152,7 +152,7 @@ func (r *mutationResolver) ShareAlbum(ctx context.Context, albumID uint, expire return &shareToken, nil } -func (r *mutationResolver) ShareMedia(ctx context.Context, mediaID uint, expire *time.Time, password *string) (*models.ShareToken, error) { +func (r *mutationResolver) ShareMedia(ctx context.Context, mediaID int, expire *time.Time, password *string) (*models.ShareToken, error) { user := auth.UserFromContext(ctx) if user == nil { return nil, auth.ErrUnauthorized diff --git a/api/graphql/schema.graphql b/api/graphql/schema.graphql index 05544ba7..3c8e95cf 100644 --- a/api/graphql/schema.graphql +++ b/api/graphql/schema.graphql @@ -34,15 +34,15 @@ type Query { onlyWithFavorites: Boolean ): [Album!]! "Get album by id, user must own the album or be admin" - album(id: Int!): Album! + album(id: ID!): Album! "List of media owned by the logged in user" myMedia(filter: Filter): [Media!]! "Get media by id, user must own the media or be admin" - media(id: Int!): Media! + media(id: ID!): Media! "Get a list of media by their ids, user must own the media or be admin" - mediaList(ids: [Int!]!): [Media!]! + mediaList(ids: [ID!]!): [Media!]! "Get media owned by the logged in user, returned in GeoJson format" myMediaGeoJson: Any! @@ -75,22 +75,22 @@ type Mutation { "Scan all users for new media" scanAll: ScannerResult! @isAdmin "Scan a single user for new media" - scanUser(userId: Int!): ScannerResult! + scanUser(userId: ID!): ScannerResult! "Generate share token for album" - shareAlbum(albumId: Int!, expire: Time, password: String): ShareToken + shareAlbum(albumId: ID!, expire: Time, password: String): ShareToken "Generate share token for media" - shareMedia(mediaId: Int!, expire: Time, password: String): ShareToken + shareMedia(mediaId: ID!, expire: Time, password: String): ShareToken "Delete a share token by it's token value" deleteShareToken(token: String!): ShareToken "Set a password for a token, if null is passed for the password argument, the password will be cleared" protectShareToken(token: String!, password: String): ShareToken "Mark or unmark a media as being a favorite" - favoriteMedia(mediaId: Int!, favorite: Boolean!): Media + favoriteMedia(mediaId: ID!, favorite: Boolean!): Media updateUser( - id: Int! + id: ID! username: String rootPath: String password: String @@ -102,7 +102,7 @@ type Mutation { password: String admin: Boolean! ): User @isAdmin - deleteUser(id: Int!): User @isAdmin + deleteUser(id: ID!): User @isAdmin """ Set how often, in seconds, the server should automatically scan for new media, @@ -152,7 +152,7 @@ type ScannerResult { "A token used to publicly access an album or media" type ShareToken { - id: Int! + id: ID! token: String! "The user who created the token" owner: User! @@ -177,7 +177,7 @@ type SiteInfo { } type User { - id: Int! + id: ID! username: String! #albums: [Album] "Local filepath for the user's photos" @@ -187,7 +187,7 @@ type User { } type Album { - id: Int! + id: ID! title: String! "The media inside this album" media( @@ -232,7 +232,7 @@ enum MediaType { } type Media { - id: Int! + id: ID! title: String! "Local filepath for the media" path: String! @@ -255,7 +255,7 @@ type Media { "EXIF metadata from the camera" type MediaEXIF { - id: Int! + id: ID! media: Media! "The model name of the camera" camera: String @@ -279,14 +279,14 @@ type MediaEXIF { } type VideoMetadata { - id: Int! + id: ID! media: Media! width: Int! height: Int! duration: Float! codec: String framerate: Float - bitrate: Int + bitrate: String colorProfile: String audio: String } diff --git a/api/scanner/cleanup_media.go b/api/scanner/cleanup_media.go index a3aadd76..8a48ea25 100644 --- a/api/scanner/cleanup_media.go +++ b/api/scanner/cleanup_media.go @@ -11,8 +11,8 @@ import ( "gorm.io/gorm" ) -func CleanupMedia(db *gorm.DB, albumId uint, albumMedia []*models.Media) []error { - albumMediaIds := make([]uint, len(albumMedia)) +func CleanupMedia(db *gorm.DB, albumId int, albumMedia []*models.Media) []error { + albumMediaIds := make([]int, len(albumMedia)) for i, media := range albumMedia { albumMediaIds[i] = media.ID } diff --git a/api/scanner/process_photo.go b/api/scanner/process_photo.go index 842c10cf..6e122753 100644 --- a/api/scanner/process_photo.go +++ b/api/scanner/process_photo.go @@ -22,7 +22,7 @@ import ( ) // Higher order function used to check if MediaURL for a given MediaPurpose exists -func makePhotoURLChecker(tx *gorm.DB, mediaID uint) (func(purpose models.MediaPurpose) (*models.MediaURL, error), error) { +func makePhotoURLChecker(tx *gorm.DB, mediaID int) (func(purpose models.MediaPurpose) (*models.MediaURL, error), error) { return func(purpose models.MediaPurpose) (*models.MediaURL, error) { var mediaURL models.MediaURL diff --git a/api/scanner/scanner_media.go b/api/scanner/scanner_media.go index 7845d291..05dde2b1 100644 --- a/api/scanner/scanner_media.go +++ b/api/scanner/scanner_media.go @@ -47,7 +47,7 @@ func hashSideCarFile(path *string) *string { return &hash } -func ScanMedia(tx *gorm.DB, mediaPath string, albumId uint, cache *AlbumScannerCache) (*models.Media, bool, error) { +func ScanMedia(tx *gorm.DB, mediaPath string, albumId int, cache *AlbumScannerCache) (*models.Media, bool, error) { mediaName := path.Base(mediaPath) // Check if media already exists diff --git a/api/scanner/scanner_user.go b/api/scanner/scanner_user.go index bd3e4918..8be0c24c 100644 --- a/api/scanner/scanner_user.go +++ b/api/scanner/scanner_user.go @@ -28,7 +28,7 @@ func findAlbumsForUser(db *gorm.DB, user *models.User, album_cache *AlbumScanner type scanInfo struct { path string - parentID *uint + parentID *int } scanQueue := list.New()