diff --git a/graphql/resolver/queries/resolver.go b/graphql/resolver/queries/resolver.go index 7b547ae..81e283f 100644 --- a/graphql/resolver/queries/resolver.go +++ b/graphql/resolver/queries/resolver.go @@ -9,3 +9,9 @@ type QueryResolver struct{} // ErrCannotResolve is returned when a resolver constructor is at its wit's end var ErrCannotResolve = errors.New("Cannot resolve due to invalid arguments") + +// ErrUnauthorized is when a guest acts like they own the place +var ErrUnauthorized = errors.New("Unauthorized") + +// ErrPermissionDenied is returned when users act above their station +var ErrPermissionDenied = errors.New("Permission denied") diff --git a/graphql/resolver/queries/stories.go b/graphql/resolver/queries/stories.go index cbf572e..240c2de 100644 --- a/graphql/resolver/queries/stories.go +++ b/graphql/resolver/queries/stories.go @@ -5,6 +5,7 @@ import ( "time" "git.aiterp.net/rpdata/api/graphql/resolver/types" + "git.aiterp.net/rpdata/api/internal/session" "git.aiterp.net/rpdata/api/model/story" ) @@ -19,6 +20,8 @@ type StoriesArg struct { EarliestFictionalDate *string LatestFictionalDate *string Limit *int32 + Open *bool + Unlisted *bool } } @@ -58,12 +61,28 @@ func (r *QueryResolver) Stories(ctx context.Context, args *StoriesArg) ([]*types } } + unlisted := filter.Unlisted != nil && *filter.Unlisted == true + if unlisted { + user := session.FromContext(ctx).User() + if user == nil { + return nil, ErrUnauthorized + } + + if author != "" && author != user.ID && !user.Permitted("story.unlisted") { + return nil, ErrPermissionDenied + } + + author = user.ID + } + + open := filter.Open + limit := 30 if filter != nil && filter.Limit != nil { limit = int(*filter.Limit) } - stories, err := story.List(author, tags, earliest, latest, limit) + stories, err := story.List(author, tags, earliest, latest, unlisted, open, limit) if err != nil { return nil, err } diff --git a/graphql/schema/types/story.graphql b/graphql/schema/types/story.graphql index af32c8a..a9928f0 100644 --- a/graphql/schema/types/story.graphql +++ b/graphql/schema/types/story.graphql @@ -43,6 +43,12 @@ input StoriesFilter { # What tags to query for tags: [TagInput!] + # If true, it will only show unlisted page you have access to + unlisted: Boolean + + # Whether the page is open for additions by other users + open: Boolean + # The earliest fictionalDate earliestFictionalDate: String diff --git a/internal/session/defaults.go b/internal/session/defaults.go index 23c2ccf..35ba45d 100644 --- a/internal/session/defaults.go +++ b/internal/session/defaults.go @@ -32,6 +32,7 @@ func AllPermissions() map[string]string { "post.remove": "Can remove posts", "story.edit": "Can edit non-owned stories", "story.remove": "Can remove non-owned stories", + "story.unlisted": "Can view unlisted stories by other users", "file.upload": "Can upload files", "file.edit": "Can edit non-owned files", "file.remove": "Can remove non-owned files", diff --git a/model/story/story.go b/model/story/story.go index ac79f0a..345cdb1 100644 --- a/model/story/story.go +++ b/model/story/story.go @@ -193,7 +193,7 @@ func FindID(id string) (Story, error) { } // List lists stories by any non-zero criteria passed with it. -func List(author string, tags []Tag, earliest, latest time.Time, limit int) ([]Story, error) { +func List(author string, tags []Tag, earliest, latest time.Time, unlisted bool, open *bool, limit int) ([]Story, error) { query := bson.M{} if author != "" { @@ -219,6 +219,12 @@ func List(author string, tags []Tag, earliest, latest time.Time, limit int) ([]S } } + query["unlisted"] = unlisted + + if open != nil { + query["open"] = *open + } + stories := make([]Story, 0, 128) err := storyCollection.Find(query).Limit(limit).All(&stories)