GraphQL API and utilities for the rpdata project
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

402 lines
9.1 KiB

package resolver
import (
"context"
"time"
"git.aiterp.net/rpdata/api/internal/session"
"git.aiterp.net/rpdata/api/model/change"
"git.aiterp.net/rpdata/api/model/story"
"git.aiterp.net/rpdata/api/resolver/types"
)
// StoryResolver for the Story graphql type
type StoryResolver struct{ S story.Story }
// StoryArgs is args for story query
type StoryArgs struct {
ID string
}
// Story implements the story query
func (r *QueryResolver) Story(ctx context.Context, args *StoryArgs) (*StoryResolver, error) {
story, err := story.FindID(args.ID)
if err != nil {
return nil, err
}
return &StoryResolver{S: story}, nil
}
// StoriesArg is args for stories query
type StoriesArg struct {
Filter *struct {
Author *string
Tags *[]TagInput
EarliestFictionalDate *string
LatestFictionalDate *string
Limit *int32
}
}
// Stories implements the stories query
func (r *QueryResolver) Stories(ctx context.Context, args *StoriesArg) ([]*StoryResolver, error) {
filter := args.Filter
author := ""
if filter != nil && filter.Author != nil {
author = *filter.Author
}
tags := make([]story.Tag, 0, 8)
if filter != nil && filter.Tags != nil {
for _, tagInput := range *filter.Tags {
tags = append(tags, story.Tag{
Kind: tagInput.Kind,
Name: tagInput.Name,
})
}
}
earliest := time.Time{}
err := error(nil)
if filter != nil && filter.EarliestFictionalDate != nil {
earliest, err = time.Parse(time.RFC3339Nano, *filter.EarliestFictionalDate)
if err != nil {
return nil, err
}
}
latest := time.Time{}
if filter != nil && filter.LatestFictionalDate != nil {
latest, err = time.Parse(time.RFC3339Nano, *filter.LatestFictionalDate)
if err != nil {
return nil, err
}
}
limit := 30
if filter != nil && filter.Limit != nil {
limit = int(*filter.Limit)
}
stories, err := story.List(author, tags, earliest, latest, limit)
if err != nil {
return nil, err
}
resolvers := make([]*StoryResolver, len(stories))
for i, story := range stories {
resolvers[i] = &StoryResolver{S: story}
}
return resolvers, nil
}
// StoryAddArgs is args for the addStory mutation
type StoryAddArgs struct {
Input *struct {
Name string
Category string
Author *string
Open *bool
Listed *bool
Tags *[]TagInput
FictionalDate *string
}
}
// AddStory implements the addStory mutation
func (r *MutationResolver) AddStory(ctx context.Context, args *StoryAddArgs) (*StoryResolver, error) {
input := args.Input
user := session.FromContext(ctx).User()
if user == nil || !user.Permitted("member", "story.add") {
return nil, ErrUnauthorized
}
author := user.ID
if input.Author != nil {
author = *input.Author
if user.ID != author && !user.Permitted("story.add") {
return nil, ErrPermissionDenied
}
}
listed := (input.Listed != nil && *input.Listed == true)
open := (input.Open != nil && *input.Open == true)
tags := make([]story.Tag, 0, 8)
if input.Tags != nil {
for _, tagInput := range *input.Tags {
tags = append(tags, story.Tag{
Kind: tagInput.Kind,
Name: tagInput.Name,
})
}
}
fictionalDate := time.Time{}
if input.FictionalDate != nil {
date, err := time.Parse(time.RFC3339Nano, *input.FictionalDate)
if err != nil {
return nil, err
}
fictionalDate = date
}
story, err := story.New(input.Name, author, input.Category, listed, open, tags, time.Now(), fictionalDate)
if err != nil {
return nil, err
}
go change.Submit("Story", "add", user.ID, story.ID, map[string]interface{}{
"name": input.Name,
"category": input.Category,
"author": input.Author,
})
return &StoryResolver{S: story}, nil
}
// StoryTagAddArgs is args for the addStoryTag mutation
type StoryTagAddArgs struct {
Input *struct {
ID string
Tag TagInput
}
}
// AddStoryTag implements the addStoryTag mutation
func (r *MutationResolver) AddStoryTag(ctx context.Context, args *StoryTagAddArgs) (*StoryResolver, error) {
input := args.Input
tag := story.Tag{Kind: input.Tag.Kind, Name: input.Tag.Name}
user := session.FromContext(ctx).User()
if user == nil || !user.Permitted("member", "story.edit") {
return nil, ErrUnauthorized
}
story, err := story.FindID(input.ID)
if err != nil {
return nil, err
}
if story.Author != user.ID && !user.Permitted("story.edit") {
return nil, ErrPermissionDenied
}
err = story.AddTag(tag)
if err != nil {
return nil, err
}
go change.Submit("Story", "add.tag", user.ID, story.ID, map[string]interface{}{
"kind": tag.Kind,
"name": tag.Name,
})
return &StoryResolver{S: story}, nil
}
// StoryTagRemoveArgs is args for the removeStoryTag mutation
type StoryTagRemoveArgs struct {
Input *struct {
ID string
Tag TagInput
}
}
// RemoveStoryTag implements the removeStoryTag mutation
func (r *MutationResolver) RemoveStoryTag(ctx context.Context, args *StoryTagRemoveArgs) (*StoryResolver, error) {
input := args.Input
tag := story.Tag{Kind: input.Tag.Kind, Name: input.Tag.Name}
user := session.FromContext(ctx).User()
if user == nil || !user.Permitted("member", "story.edit") {
return nil, ErrUnauthorized
}
story, err := story.FindID(input.ID)
if err != nil {
return nil, err
}
if story.Author != user.ID && !user.Permitted("story.edit") {
return nil, ErrPermissionDenied
}
err = story.RemoveTag(tag)
if err != nil {
return nil, err
}
go change.Submit("Story", "remove.tag", user.ID, story.ID, map[string]interface{}{
"kind": tag.Kind,
"name": tag.Name,
})
return &StoryResolver{S: story}, nil
}
// StoryEditArgs is args for the addStory mutation
type StoryEditArgs struct {
Input *struct {
ID string
Name *string
Category *string
Author *string
Open *bool
Listed *bool
FictionalDate *string
}
}
// EditStory implements the editStory mutation
func (r *MutationResolver) EditStory(ctx context.Context, args *StoryEditArgs) (*StoryResolver, error) {
input := args.Input
user := session.FromContext(ctx).User()
if user == nil || !user.Permitted("member", "story.edit") {
return nil, ErrUnauthorized
}
story, err := story.FindID(input.ID)
if err != nil {
return nil, err
}
if story.Author != user.ID && !user.Permitted("story.edit") {
return nil, ErrPermissionDenied
}
var fictionalDate *time.Time
if input.FictionalDate != nil {
date, err := time.Parse(time.RFC3339Nano, *input.FictionalDate)
if err != nil {
return nil, err
}
fictionalDate = &date
}
err = story.Edit(input.Name, input.Category, input.Listed, input.Open, fictionalDate)
if err != nil {
return nil, err
}
go change.Submit("Story", "edit", user.ID, story.ID, map[string]interface{}{
"name": input.Name,
"category": input.Category,
"author": input.Author,
"open": input.Open,
"listed": input.Listed,
"fictionalDate": input.FictionalDate,
})
return &StoryResolver{S: story}, nil
}
// StoryRemoveArgs is args for the removeStory mutation
type StoryRemoveArgs struct {
ID string
}
// RemoveStory implements the removeStory mutation
func (r *MutationResolver) RemoveStory(ctx context.Context, args *StoryRemoveArgs) (*StoryResolver, error) {
user := session.FromContext(ctx).User()
if user == nil || !user.Permitted("member", "story.edit") {
return nil, ErrUnauthorized
}
story, err := story.FindID(args.ID)
if err != nil {
return nil, err
}
if story.Author != user.ID && !user.Permitted("story.remove") {
return nil, ErrPermissionDenied
}
err = story.Remove()
if err != nil {
return nil, err
}
go change.Submit("Story", "remove", user.ID, story.ID, nil)
return &StoryResolver{S: story}, nil
}
// ID resolves Story.id
func (r *StoryResolver) ID() string {
return r.S.ID
}
// Author resolves Story.author
func (r *StoryResolver) Author() string {
return r.S.Author
}
// Name resolves Story.name
func (r *StoryResolver) Name() string {
return r.S.Name
}
// Category resolves Story.category
func (r *StoryResolver) Category() string {
return r.S.Category
}
// Open resolves Story.open
func (r *StoryResolver) Open() bool {
return r.S.Open
}
// Listed resolves Story.listed
func (r *StoryResolver) Listed() bool {
return r.S.Listed
}
// Tags resolves Story.tags
func (r *StoryResolver) Tags() []*TagResolver {
resolvers := make([]*TagResolver, len(r.S.Tags))
for i, tag := range r.S.Tags {
resolvers[i] = &TagResolver{T: tag}
}
return resolvers
}
// Chapters resolves Story.chapters
func (r *StoryResolver) Chapters() ([]*types.ChapterResolver, error) {
chapters, err := r.S.Chapters()
if err != nil {
return nil, err
}
resolvers := make([]*types.ChapterResolver, len(chapters))
for i, chapter := range chapters {
resolvers[i] = &types.ChapterResolver{C: chapter}
}
return resolvers, nil
}
// CreatedDate resolves Story.createdDate
func (r *StoryResolver) CreatedDate() string {
return r.S.CreatedDate.Format(time.RFC3339Nano)
}
// FictionalDate resolves Story.fictionalDate
func (r *StoryResolver) FictionalDate() string {
return r.S.FictionalDate.Format(time.RFC3339Nano)
}
// UpdatedDate resolves Story.updatedDate
func (r *StoryResolver) UpdatedDate() string {
return r.S.UpdatedDate.Format(time.RFC3339Nano)
}