1
Fork 0

Add resolvers for user albums and root_albums

This commit is contained in:
viktorstrate 2020-12-27 20:07:54 +01:00
parent aeb05bca49
commit 96546f6556
No known key found for this signature in database
GPG Key ID: 3F855605109C1E8A
5 changed files with 155 additions and 57 deletions

View File

@ -24,6 +24,9 @@ models:
model: github.com/99designs/gqlgen/graphql.IntID model: github.com/99designs/gqlgen/graphql.IntID
User: User:
model: github.com/photoview/photoview/api/graphql/models.User model: github.com/photoview/photoview/api/graphql/models.User
fields:
albums:
resolver: true
Media: Media:
model: github.com/photoview/photoview/api/graphql/models.Media model: github.com/photoview/photoview/api/graphql/models.Media
MediaURL: MediaURL:

View File

@ -44,6 +44,7 @@ type ResolverRoot interface {
Query() QueryResolver Query() QueryResolver
ShareToken() ShareTokenResolver ShareToken() ShareTokenResolver
Subscription() SubscriptionResolver Subscription() SubscriptionResolver
User() UserResolver
} }
type DirectiveRoot struct { type DirectiveRoot struct {
@ -191,10 +192,11 @@ type ComplexityRoot struct {
} }
User struct { User struct {
Admin func(childComplexity int) int Admin func(childComplexity int) int
Albums func(childComplexity int) int Albums func(childComplexity int) int
ID func(childComplexity int) int ID func(childComplexity int) int
Username func(childComplexity int) int RootAlbums func(childComplexity int) int
Username func(childComplexity int) int
} }
VideoMetadata struct { VideoMetadata struct {
@ -268,6 +270,10 @@ type ShareTokenResolver interface {
type SubscriptionResolver interface { type SubscriptionResolver interface {
Notification(ctx context.Context) (<-chan *models.Notification, error) Notification(ctx context.Context) (<-chan *models.Notification, error)
} }
type UserResolver interface {
Albums(ctx context.Context, obj *models.User) ([]*models.Album, error)
RootAlbums(ctx context.Context, obj *models.User) ([]*models.Album, error)
}
type executableSchema struct { type executableSchema struct {
resolvers ResolverRoot resolvers ResolverRoot
@ -1104,6 +1110,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.User.ID(childComplexity), true return e.complexity.User.ID(childComplexity), true
case "User.rootAlbums":
if e.complexity.User.RootAlbums == nil {
break
}
return e.complexity.User.RootAlbums(childComplexity), true
case "User.username": case "User.username":
if e.complexity.User.Username == nil { if e.complexity.User.Username == nil {
break break
@ -1436,8 +1449,10 @@ type User {
username: String! username: String!
#albums: [Album] #albums: [Album]
# rootPath: String! @isAdmin # rootPath: String! @isAdmin
"Top level albums owned by this user" "All albums owned by this user"
albums: [Album!]! @isAdmin albums: [Album!]! @isAdmin
"Top level albums owned by this user"
rootAlbums: [Album!]! @isAdmin
admin: Boolean! admin: Boolean!
#shareTokens: [ShareToken] #shareTokens: [ShareToken]
} }
@ -5931,15 +5946,15 @@ func (ec *executionContext) _User_albums(ctx context.Context, field graphql.Coll
Object: "User", Object: "User",
Field: field, Field: field,
Args: nil, Args: nil,
IsMethod: false, IsMethod: true,
IsResolver: false, IsResolver: true,
} }
ctx = graphql.WithFieldContext(ctx, fc) ctx = graphql.WithFieldContext(ctx, fc)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
directive0 := func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children ctx = rctx // use context from middleware stack in children
return obj.Albums, nil return ec.resolvers.User().Albums(rctx, obj)
} }
directive1 := func(ctx context.Context) (interface{}, error) { directive1 := func(ctx context.Context) (interface{}, error) {
if ec.directives.IsAdmin == nil { if ec.directives.IsAdmin == nil {
@ -5955,10 +5970,10 @@ func (ec *executionContext) _User_albums(ctx context.Context, field graphql.Coll
if tmp == nil { if tmp == nil {
return nil, nil return nil, nil
} }
if data, ok := tmp.([]models.Album); ok { if data, ok := tmp.([]*models.Album); ok {
return data, nil return data, nil
} }
return nil, fmt.Errorf(`unexpected type %T from directive, should be []github.com/photoview/photoview/api/graphql/models.Album`, tmp) return nil, fmt.Errorf(`unexpected type %T from directive, should be []*github.com/photoview/photoview/api/graphql/models.Album`, tmp)
}) })
if err != nil { if err != nil {
ec.Error(ctx, err) ec.Error(ctx, err)
@ -5970,9 +5985,64 @@ func (ec *executionContext) _User_albums(ctx context.Context, field graphql.Coll
} }
return graphql.Null return graphql.Null
} }
res := resTmp.([]models.Album) res := resTmp.([]*models.Album)
fc.Result = res fc.Result = res
return ec.marshalNAlbum2ᚕgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐAlbumᚄ(ctx, field.Selections, res) return ec.marshalNAlbum2ᚕᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐAlbumᚄ(ctx, field.Selections, res)
}
func (ec *executionContext) _User_rootAlbums(ctx context.Context, field graphql.CollectedField, obj *models.User) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
fc := &graphql.FieldContext{
Object: "User",
Field: field,
Args: nil,
IsMethod: true,
IsResolver: true,
}
ctx = graphql.WithFieldContext(ctx, fc)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
directive0 := func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return ec.resolvers.User().RootAlbums(rctx, obj)
}
directive1 := func(ctx context.Context) (interface{}, error) {
if ec.directives.IsAdmin == nil {
return nil, errors.New("directive isAdmin is not implemented")
}
return ec.directives.IsAdmin(ctx, obj, directive0)
}
tmp, err := directive1(rctx)
if err != nil {
return nil, graphql.ErrorOnPath(ctx, err)
}
if tmp == nil {
return nil, nil
}
if data, ok := tmp.([]*models.Album); ok {
return data, nil
}
return nil, fmt.Errorf(`unexpected type %T from directive, should be []*github.com/photoview/photoview/api/graphql/models.Album`, tmp)
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
if !graphql.HasFieldError(ctx, fc) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.([]*models.Album)
fc.Result = res
return ec.marshalNAlbum2ᚕᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐAlbumᚄ(ctx, field.Selections, res)
} }
func (ec *executionContext) _User_admin(ctx context.Context, field graphql.CollectedField, obj *models.User) (ret graphql.Marshaler) { func (ec *executionContext) _User_admin(ctx context.Context, field graphql.CollectedField, obj *models.User) (ret graphql.Marshaler) {
@ -8425,22 +8495,45 @@ func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj
case "id": case "id":
out.Values[i] = ec._User_id(ctx, field, obj) out.Values[i] = ec._User_id(ctx, field, obj)
if out.Values[i] == graphql.Null { if out.Values[i] == graphql.Null {
invalids++ atomic.AddUint32(&invalids, 1)
} }
case "username": case "username":
out.Values[i] = ec._User_username(ctx, field, obj) out.Values[i] = ec._User_username(ctx, field, obj)
if out.Values[i] == graphql.Null { if out.Values[i] == graphql.Null {
invalids++ atomic.AddUint32(&invalids, 1)
} }
case "albums": case "albums":
out.Values[i] = ec._User_albums(ctx, field, obj) field := field
if out.Values[i] == graphql.Null { out.Concurrently(i, func() (res graphql.Marshaler) {
invalids++ defer func() {
} if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
}
}()
res = ec._User_albums(ctx, field, obj)
if res == graphql.Null {
atomic.AddUint32(&invalids, 1)
}
return res
})
case "rootAlbums":
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_rootAlbums(ctx, field, obj)
if res == graphql.Null {
atomic.AddUint32(&invalids, 1)
}
return res
})
case "admin": case "admin":
out.Values[i] = ec._User_admin(ctx, field, obj) out.Values[i] = ec._User_admin(ctx, field, obj)
if out.Values[i] == graphql.Null { if out.Values[i] == graphql.Null {
invalids++ atomic.AddUint32(&invalids, 1)
} }
default: default:
panic("unknown field " + strconv.Quote(field.Name)) panic("unknown field " + strconv.Quote(field.Name))
@ -8759,43 +8852,6 @@ func (ec *executionContext) marshalNAlbum2githubᚗcomᚋphotoviewᚋphotoview
return ec._Album(ctx, sel, &v) return ec._Album(ctx, sel, &v)
} }
func (ec *executionContext) marshalNAlbum2ᚕgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐAlbumᚄ(ctx context.Context, sel ast.SelectionSet, v []models.Album) graphql.Marshaler {
ret := make(graphql.Array, len(v))
var wg sync.WaitGroup
isLen1 := len(v) == 1
if !isLen1 {
wg.Add(len(v))
}
for i := range v {
i := i
fc := &graphql.FieldContext{
Index: &i,
Result: &v[i],
}
ctx := graphql.WithFieldContext(ctx, fc)
f := func(i int) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = nil
}
}()
if !isLen1 {
defer wg.Done()
}
ret[i] = ec.marshalNAlbum2githubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐAlbum(ctx, sel, v[i])
}
if isLen1 {
f(i)
} else {
go f(i)
}
}
wg.Wait()
return ret
}
func (ec *executionContext) marshalNAlbum2ᚕᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐAlbumᚄ(ctx context.Context, sel ast.SelectionSet, v []*models.Album) graphql.Marshaler { func (ec *executionContext) marshalNAlbum2ᚕᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐAlbumᚄ(ctx context.Context, sel ast.SelectionSet, v []*models.Album) graphql.Marshaler {
ret := make(graphql.Array, len(v)) ret := make(graphql.Array, len(v))
var wg sync.WaitGroup var wg sync.WaitGroup

View File

@ -3,6 +3,7 @@ package resolvers
import ( import (
"context" "context"
api "github.com/photoview/photoview/api/graphql"
"github.com/photoview/photoview/api/graphql/auth" "github.com/photoview/photoview/api/graphql/auth"
"github.com/photoview/photoview/api/graphql/models" "github.com/photoview/photoview/api/graphql/models"
"github.com/photoview/photoview/api/scanner" "github.com/photoview/photoview/api/scanner"
@ -11,6 +12,14 @@ import (
"gorm.io/gorm" "gorm.io/gorm"
) )
type userResolver struct {
*Resolver
}
func (r *Resolver) User() api.UserResolver {
return &userResolver{r}
}
func (r *queryResolver) User(ctx context.Context, filter *models.Filter) ([]*models.User, error) { func (r *queryResolver) User(ctx context.Context, filter *models.Filter) ([]*models.User, error) {
var users []*models.User var users []*models.User
@ -22,6 +31,30 @@ func (r *queryResolver) User(ctx context.Context, filter *models.Filter) ([]*mod
return users, nil return users, nil
} }
func (r *userResolver) Albums(ctx context.Context, user *models.User) ([]*models.Album, error) {
user.FillAlbums(r.Database)
pointerAlbums := make([]*models.Album, len(user.Albums))
for i, album := range user.Albums {
pointerAlbums[i] = &album
}
return pointerAlbums, nil
}
func (r *userResolver) RootAlbums(ctx context.Context, user *models.User) (albums []*models.Album, err error) {
err = r.Database.Model(&user).
Where("albums.parent_album_id NOT IN (?)",
r.Database.Table("user_albums").
Select("albums.id").
Joins("JOIN albums ON albums.id = user_albums.album_id AND user_albums.user_id = ?", user.ID),
).Or("albums.parent_album_id IS NULL").
Association("Albums").Find(&albums)
return
}
func (r *queryResolver) MyUser(ctx context.Context) (*models.User, error) { func (r *queryResolver) MyUser(ctx context.Context) (*models.User, error) {
user := auth.UserFromContext(ctx) user := auth.UserFromContext(ctx)

View File

@ -172,8 +172,10 @@ type User {
username: String! username: String!
#albums: [Album] #albums: [Album]
# rootPath: String! @isAdmin # rootPath: String! @isAdmin
"Top level albums owned by this user" "All albums owned by this user"
albums: [Album!]! @isAdmin albums: [Album!]! @isAdmin
"Top level albums owned by this user"
rootAlbums: [Album!]! @isAdmin
admin: Boolean! admin: Boolean!
#shareTokens: [ShareToken] #shareTokens: [ShareToken]
} }

View File

@ -13,6 +13,10 @@ const USERS_QUERY = gql`
username username
# rootPath # rootPath
admin admin
albums {
id
filePath
}
} }
} }
` `