1
Fork 0

Replace database, resolve all build-time errors

This commit is contained in:
viktorstrate 2020-11-28 21:29:31 +01:00
parent d3ebecc3b5
commit e42ac2436b
No known key found for this signature in database
GPG Key ID: 3F855605109C1E8A
21 changed files with 402 additions and 511 deletions

View File

@ -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

View File

@ -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)
}

View File

@ -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"`

View File

@ -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"`
}

View File

@ -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 (

View File

@ -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

View File

@ -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")
}

View File

@ -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
}

View File

@ -6,7 +6,7 @@ import (
)
type SiteInfo struct {
gorm.Model
Model
InitialSetup bool
PeriodicScanInterval int
ConcurrentWorkers int

View File

@ -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

View File

@ -6,6 +6,8 @@ import (
)
func (filter *Filter) FormatSQL(context string) (string, error) {
// TODO: Migrate method to gorm
if filter == nil {
return "", nil
}

View File

@ -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")
}

View File

@ -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)
}

View File

@ -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) {

View File

@ -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")
}

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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()