Gisle Aune
6 years ago
56 changed files with 1923 additions and 1573 deletions
-
2cmd/rpdata-graphiql/main.go
-
156graphql/resolver/channel.go
-
161graphql/resolver/chapter.go
-
299graphql/resolver/character.go
-
15graphql/resolver/error.go
-
115graphql/resolver/file.go
-
229graphql/resolver/log.go
-
59graphql/resolver/mutations/addChannel.go
-
67graphql/resolver/mutations/addChapter.go
-
70graphql/resolver/mutations/addCharacter.go
-
48graphql/resolver/mutations/addCharacterNick.go
-
70graphql/resolver/mutations/addLog.go
-
60graphql/resolver/mutations/addPost.go
-
83graphql/resolver/mutations/addStory.go
-
53graphql/resolver/mutations/addStoryTag.go
-
50graphql/resolver/mutations/editChannel.go
-
63graphql/resolver/mutations/editChapter.go
-
64graphql/resolver/mutations/editCharacter.go
-
43graphql/resolver/mutations/editFile.go
-
51graphql/resolver/mutations/editLog.go
-
63graphql/resolver/mutations/editPost.go
-
69graphql/resolver/mutations/editStory.go
-
26graphql/resolver/mutations/login.go
-
16graphql/resolver/mutations/logout.go
-
45graphql/resolver/mutations/movePost.go
-
37graphql/resolver/mutations/removeChannel.go
-
37graphql/resolver/mutations/removeChapter.go
-
44graphql/resolver/mutations/removeCharacter.go
-
48graphql/resolver/mutations/removeCharacterNick.go
-
37graphql/resolver/mutations/removeFile.go
-
37graphql/resolver/mutations/removeLog.go
-
36graphql/resolver/mutations/removePost.go
-
41graphql/resolver/mutations/removeStory.go
-
53graphql/resolver/mutations/removeStoryTag.go
-
14graphql/resolver/mutations/resolver.go
-
208graphql/resolver/post.go
-
23graphql/resolver/queries/channel.go
-
28graphql/resolver/queries/channels.go
-
23graphql/resolver/queries/chapter.go
-
43graphql/resolver/queries/character.go
-
54graphql/resolver/queries/characters.go
-
23graphql/resolver/queries/file.go
-
43graphql/resolver/queries/files.go
-
32graphql/resolver/queries/log.go
-
79graphql/resolver/queries/logs.go
-
23graphql/resolver/queries/post.go
-
28graphql/resolver/queries/posts.go
-
11graphql/resolver/queries/resolver.go
-
13graphql/resolver/queries/session.go
-
77graphql/resolver/queries/stories.go
-
23graphql/resolver/queries/story.go
-
10graphql/resolver/queries/tags.go
-
13graphql/resolver/resolver.go
-
13graphql/resolver/root.go
-
39graphql/resolver/session.go
-
329graphql/resolver/story.go
@ -1,156 +0,0 @@ |
|||||
package resolver |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/session" |
|
||||
"git.aiterp.net/rpdata/api/model/change" |
|
||||
"git.aiterp.net/rpdata/api/model/channel" |
|
||||
) |
|
||||
|
|
||||
// ChannelArgs is args for channel query
|
|
||||
type ChannelArgs struct { |
|
||||
Name string |
|
||||
} |
|
||||
|
|
||||
// Channel implements the channel query
|
|
||||
func (r *QueryResolver) Channel(ctx context.Context, args *ChannelArgs) (*types.ChannelResolver, error) { |
|
||||
channel, err := channel.FindName(args.Name) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
return &types.ChannelResolver{C: channel}, nil |
|
||||
} |
|
||||
|
|
||||
// ChannelsArgs is args for channel query
|
|
||||
type ChannelsArgs struct { |
|
||||
Logged *bool |
|
||||
} |
|
||||
|
|
||||
// Channels implements the channels query
|
|
||||
func (r *QueryResolver) Channels(ctx context.Context, args *ChannelsArgs) ([]*types.ChannelResolver, error) { |
|
||||
channels, err := channel.List(args.Logged != nil && *args.Logged) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
resolvers := make([]*types.ChannelResolver, len(channels)) |
|
||||
for i := range channels { |
|
||||
resolvers[i] = &types.ChannelResolver{C: channels[i]} |
|
||||
} |
|
||||
|
|
||||
return resolvers, nil |
|
||||
} |
|
||||
|
|
||||
// ChannelAddArgs is input for the addChannel mutation
|
|
||||
type ChannelAddArgs struct { |
|
||||
Input *struct { |
|
||||
Name string |
|
||||
Logged *bool |
|
||||
Hub *bool |
|
||||
EventName *string |
|
||||
LocationName *string |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// AddChannel resolves the addChannel mutation
|
|
||||
func (r *MutationResolver) AddChannel(ctx context.Context, args *ChannelAddArgs) (*types.ChannelResolver, error) { |
|
||||
input := args.Input |
|
||||
|
|
||||
user := session.FromContext(ctx).User() |
|
||||
if user == nil || !user.Permitted("channel.add") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
logged := input.Logged != nil && *input.Logged |
|
||||
|
|
||||
hub := input.Hub != nil && *input.Hub |
|
||||
|
|
||||
eventName := "" |
|
||||
if input.EventName != nil { |
|
||||
eventName = *input.EventName |
|
||||
} |
|
||||
|
|
||||
locationName := "" |
|
||||
if input.LocationName != nil { |
|
||||
locationName = *input.LocationName |
|
||||
} |
|
||||
|
|
||||
channel, err := channel.New(input.Name, logged, hub, eventName, locationName) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Channel", "add", user.ID, channel.Name, map[string]interface{}{ |
|
||||
"logged": channel.Logged, |
|
||||
"hub": channel.Hub, |
|
||||
"location": input.LocationName, |
|
||||
"event": input.EventName, |
|
||||
}) |
|
||||
|
|
||||
return &types.ChannelResolver{C: channel}, nil |
|
||||
} |
|
||||
|
|
||||
// ChannelEditArgs is input for the editChannel mutation
|
|
||||
type ChannelEditArgs struct { |
|
||||
Input *struct { |
|
||||
Name string |
|
||||
Logged *bool |
|
||||
Hub *bool |
|
||||
EventName *string |
|
||||
LocationName *string |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// EditChannel resolves the editChannel mutation
|
|
||||
func (r *MutationResolver) EditChannel(ctx context.Context, args *ChannelEditArgs) (*types.ChannelResolver, error) { |
|
||||
input := args.Input |
|
||||
|
|
||||
user := session.FromContext(ctx).User() |
|
||||
if user == nil || !user.Permitted("channel.edit") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
channel, err := channel.FindName(input.Name) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
err = channel.Edit(input.Logged, input.Hub, input.EventName, input.LocationName) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Channel", "edit", user.ID, channel.Name, map[string]interface{}{ |
|
||||
"logged": input.Logged, |
|
||||
"hub": input.Hub, |
|
||||
"location": input.LocationName, |
|
||||
"event": input.EventName, |
|
||||
}) |
|
||||
|
|
||||
return &types.ChannelResolver{C: channel}, nil |
|
||||
} |
|
||||
|
|
||||
// RemoveChannel resolves the editChannel mutation
|
|
||||
func (r *MutationResolver) RemoveChannel(ctx context.Context, args ChannelArgs) (*types.ChannelResolver, error) { |
|
||||
user := session.FromContext(ctx).User() |
|
||||
if user == nil || !user.Permitted("channel.remove") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
channel, err := channel.FindName(args.Name) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
err = channel.Remove() |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Channel", "remove", user.ID, channel.Name, nil) |
|
||||
|
|
||||
return &types.ChannelResolver{C: channel}, nil |
|
||||
} |
|
@ -1,161 +0,0 @@ |
|||||
package resolver |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
"time" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/session" |
|
||||
"git.aiterp.net/rpdata/api/model/change" |
|
||||
"git.aiterp.net/rpdata/api/model/story" |
|
||||
) |
|
||||
|
|
||||
// ChapterArgs is args for chapter query
|
|
||||
type ChapterArgs struct { |
|
||||
ID string |
|
||||
} |
|
||||
|
|
||||
// Chapter implements the chapter query
|
|
||||
func (r *QueryResolver) Chapter(ctx context.Context, args *ChapterArgs) (*types.ChapterResolver, error) { |
|
||||
chapter, err := story.FindChapterID(args.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
return &types.ChapterResolver{C: chapter}, nil |
|
||||
} |
|
||||
|
|
||||
// AddChapterArgs is args for the addChapter mutation
|
|
||||
type AddChapterArgs struct { |
|
||||
Input *struct { |
|
||||
StoryID string |
|
||||
Title string |
|
||||
Author *string |
|
||||
Source string |
|
||||
FictionalDate *string |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// AddChapter implements the addChapter mutation
|
|
||||
func (r *MutationResolver) AddChapter(ctx context.Context, args *AddChapterArgs) (*types.ChapterResolver, error) { |
|
||||
input := args.Input |
|
||||
|
|
||||
user := session.FromContext(ctx).User() |
|
||||
if user == nil || !user.Permitted("member", "chapter.add") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
story, err := story.FindID(input.StoryID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
author := user.ID |
|
||||
if input.Author != nil { |
|
||||
author = *input.Author |
|
||||
|
|
||||
if user.ID != author && !user.Permitted("chapter.add") { |
|
||||
return nil, ErrPermissionDenied |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
fictionalDate := time.Time{} |
|
||||
if input.FictionalDate != nil { |
|
||||
fictionalDate, err = time.Parse(time.RFC3339Nano, *input.FictionalDate) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
chapter, err := story.AddChapter(input.Title, author, input.Source, time.Now(), fictionalDate) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Chapter", "add", user.ID, chapter.ID, map[string]interface{}{ |
|
||||
"title": input.Title, |
|
||||
"author": author, |
|
||||
"fictionalDate": fictionalDate, |
|
||||
}) |
|
||||
|
|
||||
return &types.ChapterResolver{C: chapter}, nil |
|
||||
} |
|
||||
|
|
||||
// EditChapterArgs is args for the editChapter mutation
|
|
||||
type EditChapterArgs struct { |
|
||||
Input *struct { |
|
||||
ID string |
|
||||
Title *string |
|
||||
Source *string |
|
||||
FictionalDate *string |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// EditChapter implements the editChapter mutation
|
|
||||
func (r *MutationResolver) EditChapter(ctx context.Context, args *EditChapterArgs) (*types.ChapterResolver, error) { |
|
||||
input := args.Input |
|
||||
|
|
||||
user := session.FromContext(ctx).User() |
|
||||
if user == nil || !user.Permitted("member", "chapter.edit") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
chapter, err := story.FindChapterID(input.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
if chapter.Author != user.ID && !user.Permitted("chapter.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 = chapter.Edit(input.Title, input.Source, fictionalDate) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Chapter", "edit", user.ID, chapter.ID, map[string]interface{}{ |
|
||||
"title": input.Title, |
|
||||
"source": input.Source, |
|
||||
"fictionalDate": fictionalDate, |
|
||||
}) |
|
||||
|
|
||||
return &types.ChapterResolver{C: chapter}, nil |
|
||||
} |
|
||||
|
|
||||
// DeleteChapterArgs is args for the addChapter mutation
|
|
||||
type DeleteChapterArgs struct { |
|
||||
ID string |
|
||||
} |
|
||||
|
|
||||
// RemoveChapter implements the removeChapter mutation
|
|
||||
func (r *MutationResolver) RemoveChapter(ctx context.Context, args *DeleteChapterArgs) (*types.ChapterResolver, error) { |
|
||||
user := session.FromContext(ctx).User() |
|
||||
if user == nil || !user.Permitted("member", "chapter.edit") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
chapter, err := story.FindChapterID(args.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
err = chapter.Remove() |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Chapter", "remove", user.ID, chapter.ID, nil) |
|
||||
|
|
||||
return &types.ChapterResolver{C: chapter}, nil |
|
||||
} |
|
@ -1,299 +0,0 @@ |
|||||
package resolver |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
"errors" |
|
||||
"strings" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/loader" |
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/session" |
|
||||
"git.aiterp.net/rpdata/api/model/change" |
|
||||
"git.aiterp.net/rpdata/api/model/character" |
|
||||
"git.aiterp.net/rpdata/api/model/log" |
|
||||
) |
|
||||
|
|
||||
// CharacterArgs is an arg
|
|
||||
type CharacterArgs struct { |
|
||||
ID *string |
|
||||
Nick *string |
|
||||
} |
|
||||
|
|
||||
// Character resolver
|
|
||||
func (r *QueryResolver) Character(ctx context.Context, args *CharacterArgs) (*types.CharacterResolver, error) { |
|
||||
var char character.Character |
|
||||
var err error |
|
||||
|
|
||||
loader := loader.FromContext(ctx) |
|
||||
if loader == nil { |
|
||||
return nil, errors.New("no loader") |
|
||||
} |
|
||||
|
|
||||
switch { |
|
||||
case args.ID != nil: |
|
||||
char, err = character.FindID(*args.ID) |
|
||||
case args.Nick != nil: |
|
||||
char, err = character.FindNick(*args.Nick) |
|
||||
default: |
|
||||
err = ErrCannotResolve |
|
||||
} |
|
||||
|
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
return &types.CharacterResolver{C: char}, nil |
|
||||
} |
|
||||
|
|
||||
// CharactersArgs is an arg
|
|
||||
type CharactersArgs struct { |
|
||||
IDs *[]string |
|
||||
Nicks *[]string |
|
||||
Author *string |
|
||||
} |
|
||||
|
|
||||
// Characters resolves the characters query
|
|
||||
func (r *QueryResolver) Characters(ctx context.Context, args *CharactersArgs) ([]*types.CharacterResolver, error) { |
|
||||
var chars []character.Character |
|
||||
var err error |
|
||||
|
|
||||
loader := loader.FromContext(ctx) |
|
||||
if loader == nil { |
|
||||
return nil, errors.New("no loader") |
|
||||
} |
|
||||
|
|
||||
switch { |
|
||||
case args.IDs != nil: |
|
||||
chars, err = character.ListIDs(*args.IDs...) |
|
||||
case args.Nicks != nil: |
|
||||
chars, err = character.ListNicks(*args.Nicks...) |
|
||||
case args.Author != nil: |
|
||||
chars, err = character.ListAuthor(*args.Author) |
|
||||
default: |
|
||||
chars, err = character.List() |
|
||||
} |
|
||||
|
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
resolvers := make([]*types.CharacterResolver, 0, len(chars)) |
|
||||
for i := range chars { |
|
||||
if chars[i].ID == "" { |
|
||||
continue |
|
||||
} |
|
||||
|
|
||||
resolvers = append(resolvers, &types.CharacterResolver{C: chars[i]}) |
|
||||
} |
|
||||
|
|
||||
return resolvers, nil |
|
||||
} |
|
||||
|
|
||||
// AddCharacterInput is args for the addCharacter mutation
|
|
||||
type AddCharacterInput struct { |
|
||||
Nick string |
|
||||
Name string |
|
||||
ShortName *string |
|
||||
Author *string |
|
||||
Description *string |
|
||||
} |
|
||||
|
|
||||
// AddCharacter resolves the addCharacter mutation
|
|
||||
func (r *MutationResolver) AddCharacter(ctx context.Context, args struct{ Input *AddCharacterInput }) (*types.CharacterResolver, error) { |
|
||||
input := args.Input |
|
||||
user := session.FromContext(ctx).User() |
|
||||
if user == nil || !user.Permitted("member", "character.add") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
nick := input.Nick |
|
||||
|
|
||||
name := input.Name |
|
||||
|
|
||||
shortName := "" |
|
||||
if input.ShortName != nil { |
|
||||
shortName = *input.ShortName |
|
||||
} else { |
|
||||
shortName = strings.SplitN(input.Name, " ", 2)[0] |
|
||||
} |
|
||||
|
|
||||
author := user.ID |
|
||||
if input.Author != nil { |
|
||||
author = *input.Author |
|
||||
|
|
||||
if author != user.ID && !user.Permitted("character.add") { |
|
||||
return nil, ErrPermissionDenied |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
description := "" |
|
||||
if input.Description != nil { |
|
||||
description = *input.Description |
|
||||
} |
|
||||
|
|
||||
character, err := character.New(nick, name, shortName, author, description) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Character", "add", user.ID, character.ID, map[string]interface{}{ |
|
||||
"name": character.Name, |
|
||||
"nick": character.Nicks[0], |
|
||||
"author": character.Author, |
|
||||
}) |
|
||||
|
|
||||
log.ScheduleCharacterUpdate() |
|
||||
|
|
||||
return &types.CharacterResolver{C: character}, nil |
|
||||
} |
|
||||
|
|
||||
// CharacterNickInput is args for mutation addCharacterNick/removeCharacterNick
|
|
||||
type CharacterNickInput struct { |
|
||||
ID string |
|
||||
Nick string |
|
||||
} |
|
||||
|
|
||||
// AddCharacterNick resolves the addCharacterNick mutation
|
|
||||
func (r *MutationResolver) AddCharacterNick(ctx context.Context, args struct{ Input *CharacterNickInput }) (*types.CharacterResolver, error) { |
|
||||
input := args.Input |
|
||||
|
|
||||
user := session.FromContext(ctx).User() |
|
||||
if user == nil || !user.Permitted("member") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
character, err := character.FindID(input.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
if character.Author != user.ID && !user.Permitted("character.edit") { |
|
||||
return nil, ErrPermissionDenied |
|
||||
} |
|
||||
|
|
||||
err = character.AddNick(input.Nick) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Character", "add.nick", user.ID, character.ID, map[string]interface{}{ |
|
||||
"nick": input.Nick, |
|
||||
}) |
|
||||
|
|
||||
log.ScheduleCharacterUpdate() |
|
||||
|
|
||||
return &types.CharacterResolver{C: character}, nil |
|
||||
} |
|
||||
|
|
||||
// RemoveCharacterNick resolves the removeCharacterNick mutation
|
|
||||
func (r *MutationResolver) RemoveCharacterNick(ctx context.Context, args struct{ Input *CharacterNickInput }) (*types.CharacterResolver, error) { |
|
||||
input := args.Input |
|
||||
|
|
||||
user := session.FromContext(ctx).User() |
|
||||
if user == nil || !user.Permitted("member") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
character, err := character.FindID(input.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
if character.Author != user.ID && !user.Permitted("character.edit") { |
|
||||
return nil, ErrPermissionDenied |
|
||||
} |
|
||||
|
|
||||
err = character.RemoveNick(input.Nick) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Character", "remove.nick", user.ID, character.ID, map[string]interface{}{ |
|
||||
"nick": input.Nick, |
|
||||
}) |
|
||||
|
|
||||
log.ScheduleCharacterUpdate() |
|
||||
|
|
||||
return &types.CharacterResolver{C: character}, nil |
|
||||
} |
|
||||
|
|
||||
// CharacterEditInput is args for mutation addCharacterNick/removeCharacterNick
|
|
||||
type CharacterEditInput struct { |
|
||||
ID string |
|
||||
Name *string |
|
||||
ShortName *string |
|
||||
Description *string |
|
||||
} |
|
||||
|
|
||||
// EditCharacter resolves the editCharacter mutation
|
|
||||
func (r *MutationResolver) EditCharacter(ctx context.Context, args struct{ Input *CharacterEditInput }) (*types.CharacterResolver, error) { |
|
||||
input := args.Input |
|
||||
|
|
||||
user := session.FromContext(ctx).User() |
|
||||
if user == nil || !user.Permitted("member") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
character, err := character.FindID(input.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
if character.Author != user.ID && !user.Permitted("character.edit") { |
|
||||
return nil, ErrPermissionDenied |
|
||||
} |
|
||||
|
|
||||
name := "" |
|
||||
if input.Name != nil { |
|
||||
name = *input.Name |
|
||||
} |
|
||||
|
|
||||
shortName := "" |
|
||||
if input.ShortName != nil { |
|
||||
shortName = *input.ShortName |
|
||||
} |
|
||||
|
|
||||
description := "" |
|
||||
if input.Description != nil { |
|
||||
description = *input.Description |
|
||||
} |
|
||||
|
|
||||
err = character.Edit(name, shortName, description) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Character", "edit", user.ID, character.ID, map[string]interface{}{ |
|
||||
"name": character.Name, |
|
||||
"shortName": character.ShortName, |
|
||||
"description": character.Description, |
|
||||
}) |
|
||||
|
|
||||
return &types.CharacterResolver{C: character}, nil |
|
||||
} |
|
||||
|
|
||||
// RemoveCharacter resolves the removeCharacter mutation
|
|
||||
func (r *MutationResolver) RemoveCharacter(ctx context.Context, args struct{ ID string }) (*types.CharacterResolver, error) { |
|
||||
user := session.FromContext(ctx).User() |
|
||||
if user == nil || !user.Permitted("member") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
character, err := character.FindID(args.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
if character.Author != user.ID && !user.Permitted("character.remove") { |
|
||||
return nil, ErrPermissionDenied |
|
||||
} |
|
||||
|
|
||||
err = character.Remove() |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Character", "remove", user.ID, character.ID, map[string]interface{}{ |
|
||||
"name": character.Name, |
|
||||
"author": character.Author, |
|
||||
"nicks": character.Nicks, |
|
||||
}) |
|
||||
|
|
||||
return &types.CharacterResolver{C: character}, nil |
|
||||
} |
|
@ -1,15 +0,0 @@ |
|||||
package resolver |
|
||||
|
|
||||
import "errors" |
|
||||
|
|
||||
// ErrCannotResolve is returned when a resolver constructor is at its wit's end
|
|
||||
var ErrCannotResolve = errors.New("Cannot resolve due to invalid arguments") |
|
||||
|
|
||||
// ErrNotImplemented is for TODOs
|
|
||||
var ErrNotImplemented = errors.New("Resolver not implemented") |
|
||||
|
|
||||
// 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") |
|
@ -1,115 +0,0 @@ |
|||||
package resolver |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/session" |
|
||||
"git.aiterp.net/rpdata/api/model/file" |
|
||||
) |
|
||||
|
|
||||
// FileArgs is an arg
|
|
||||
type FileArgs struct { |
|
||||
ID string |
|
||||
} |
|
||||
|
|
||||
// File implements the file query
|
|
||||
func (r *QueryResolver) File(ctx context.Context, args *FileArgs) (*types.FileResolver, error) { |
|
||||
file, err := file.FindID(args.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
return &types.FileResolver{F: file}, nil |
|
||||
} |
|
||||
|
|
||||
// FilesArgs is an arg
|
|
||||
type FilesArgs struct { |
|
||||
IncludePublic *bool |
|
||||
MimeTypes *[]string |
|
||||
} |
|
||||
|
|
||||
// Files implements the file query
|
|
||||
func (r *QueryResolver) Files(ctx context.Context, args *FilesArgs) ([]*types.FileResolver, error) { |
|
||||
user := session.FromContext(ctx).User() |
|
||||
author := "" |
|
||||
if user != nil { |
|
||||
author = user.ID |
|
||||
} |
|
||||
|
|
||||
public := args.IncludePublic != nil && *args.IncludePublic == true |
|
||||
|
|
||||
mimeTypes := []string(nil) |
|
||||
if args.MimeTypes != nil { |
|
||||
mimeTypes = *args.MimeTypes |
|
||||
} |
|
||||
|
|
||||
files, err := file.List(author, public, mimeTypes) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
resolvers := make([]*types.FileResolver, len(files)) |
|
||||
for i := range files { |
|
||||
resolvers[i] = &types.FileResolver{F: files[i]} |
|
||||
} |
|
||||
|
|
||||
return resolvers, nil |
|
||||
} |
|
||||
|
|
||||
// FileEditArgs is args for the editFile mutation
|
|
||||
type FileEditArgs struct { |
|
||||
Input *struct { |
|
||||
ID string |
|
||||
Name *string |
|
||||
Public *bool |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// EditFile resolves the editFile mutation
|
|
||||
func (r *MutationResolver) EditFile(ctx context.Context, args *FileEditArgs) (*types.FileResolver, error) { |
|
||||
input := args.Input |
|
||||
|
|
||||
user := session.FromContext(ctx).User() |
|
||||
if user == nil || !user.Permitted("member") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
file, err := file.FindID(input.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
if file.Author != user.ID && !user.Permitted("file.edit") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
err = file.Edit(input.Name, input.Public) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
return &types.FileResolver{F: file}, nil |
|
||||
} |
|
||||
|
|
||||
// RemoveFile resolves the removeFIle mutation
|
|
||||
func (r *MutationResolver) RemoveFile(ctx context.Context, args *FileArgs) (*types.FileResolver, error) { |
|
||||
user := session.FromContext(ctx).User() |
|
||||
if user == nil || !user.Permitted("member") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
file, err := file.FindID(args.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
if file.Author != user.ID && !user.Permitted("file.remove") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
err = file.Delete() |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
return &types.FileResolver{F: file}, nil |
|
||||
} |
|
@ -1,229 +0,0 @@ |
|||||
package resolver |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
"time" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/model/change" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/internal/session" |
|
||||
"git.aiterp.net/rpdata/api/model/log" |
|
||||
) |
|
||||
|
|
||||
// LogArgs is an arg
|
|
||||
type LogArgs struct { |
|
||||
ID *string |
|
||||
} |
|
||||
|
|
||||
// Log finds log
|
|
||||
func (r *QueryResolver) Log(ctx context.Context, args *LogArgs) (*types.LogResolver, error) { |
|
||||
var l log.Log |
|
||||
var err error |
|
||||
|
|
||||
switch { |
|
||||
case args.ID != nil: |
|
||||
l, err = log.FindID(*args.ID) |
|
||||
default: |
|
||||
err = ErrCannotResolve |
|
||||
} |
|
||||
|
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
return &types.LogResolver{L: l}, nil |
|
||||
} |
|
||||
|
|
||||
// LogQueryArgs is args for the logs query
|
|
||||
type LogQueryArgs struct { |
|
||||
Filter *struct { |
|
||||
Search *string |
|
||||
Characters *[]string |
|
||||
Channels *[]string |
|
||||
Events *[]string |
|
||||
Open *bool |
|
||||
Limit *int32 |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// Logs resolves the logs query
|
|
||||
func (r *QueryResolver) Logs(ctx context.Context, args *LogQueryArgs) ([]*types.LogResolver, error) { |
|
||||
var logs []log.Log |
|
||||
var err error |
|
||||
|
|
||||
filter := args.Filter |
|
||||
|
|
||||
if filter != nil { |
|
||||
limit := 100 |
|
||||
search := "" |
|
||||
|
|
||||
if filter.Search != nil { |
|
||||
search = *filter.Search |
|
||||
limit = 0 |
|
||||
} |
|
||||
|
|
||||
channels := []string(nil) |
|
||||
if filter.Channels != nil { |
|
||||
channels = *filter.Channels |
|
||||
limit = 0 |
|
||||
} |
|
||||
|
|
||||
characters := []string(nil) |
|
||||
if filter.Characters != nil { |
|
||||
characters = *filter.Characters |
|
||||
limit = 0 |
|
||||
} |
|
||||
|
|
||||
events := []string(nil) |
|
||||
if filter.Events != nil { |
|
||||
events = *filter.Events |
|
||||
limit = 0 |
|
||||
} |
|
||||
|
|
||||
if filter.Limit != nil { |
|
||||
limit = int(*filter.Limit) |
|
||||
} |
|
||||
|
|
||||
open := filter.Open != nil && *filter.Open == true |
|
||||
|
|
||||
logs, err = log.ListSearch(search, channels, characters, events, open, limit) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
} else { |
|
||||
logs, err = log.List(100) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
resolvers := make([]*types.LogResolver, len(logs)) |
|
||||
for i := range logs { |
|
||||
resolvers[i] = &types.LogResolver{L: logs[i]} |
|
||||
} |
|
||||
|
|
||||
return resolvers, nil |
|
||||
} |
|
||||
|
|
||||
// LogAddArgs is args for the addLog mutation
|
|
||||
type LogAddArgs struct { |
|
||||
Input *struct { |
|
||||
Date string |
|
||||
Channel string |
|
||||
Title *string |
|
||||
Open *bool |
|
||||
Event *string |
|
||||
Description *string |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// AddLog resolves the addLog mutation
|
|
||||
func (r *MutationResolver) AddLog(ctx context.Context, args *LogAddArgs) (*types.LogResolver, error) { |
|
||||
input := args.Input |
|
||||
|
|
||||
user := session.FromContext(ctx).User() |
|
||||
if user == nil || !user.Permitted("log.add") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
date, err := time.Parse(time.RFC3339Nano, args.Input.Date) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
title := "" |
|
||||
if input.Title != nil { |
|
||||
title = *input.Title |
|
||||
} |
|
||||
|
|
||||
event := "" |
|
||||
if input.Event != nil { |
|
||||
event = *input.Event |
|
||||
} |
|
||||
|
|
||||
description := "" |
|
||||
if input.Description != nil { |
|
||||
description = *input.Description |
|
||||
} |
|
||||
|
|
||||
open := input.Open != nil && *input.Open == true |
|
||||
|
|
||||
log, err := log.New(date, input.Channel, title, event, description, open) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Log", "add", user.ID, log.ID, map[string]interface{}{ |
|
||||
"channel": log.Channel, |
|
||||
"title": log.Title, |
|
||||
"event": log.Event, |
|
||||
"description": log.Description, |
|
||||
"open": log.Open, |
|
||||
}) |
|
||||
|
|
||||
return &types.LogResolver{L: log}, nil |
|
||||
} |
|
||||
|
|
||||
// LogEditArgs is an input
|
|
||||
type LogEditArgs struct { |
|
||||
Input *struct { |
|
||||
ID string |
|
||||
Title *string |
|
||||
Event *string |
|
||||
Description *string |
|
||||
Open *bool |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// EditLog resolves the editLog mutation
|
|
||||
func (r *MutationResolver) EditLog(ctx context.Context, args *LogEditArgs) (*types.LogResolver, error) { |
|
||||
input := args.Input |
|
||||
|
|
||||
user := session.FromContext(ctx).User() |
|
||||
if user == nil || !user.Permitted("log.edit") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
log, err := log.FindID(input.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
err = log.Edit(input.Title, input.Event, input.Description, input.Open) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Log", "edit", user.ID, log.ID, map[string]interface{}{ |
|
||||
"channel": log.Channel, |
|
||||
"title": input.Title, |
|
||||
"event": input.Event, |
|
||||
"description": input.Description, |
|
||||
"open": input.Open, |
|
||||
}) |
|
||||
|
|
||||
return &types.LogResolver{L: log}, nil |
|
||||
} |
|
||||
|
|
||||
// RemoveLog resolves the removeLog mutation
|
|
||||
func (r *MutationResolver) RemoveLog(ctx context.Context, args *struct{ ID string }) (*types.LogResolver, error) { |
|
||||
user := session.FromContext(ctx).User() |
|
||||
if user == nil || !user.Permitted("log.remove") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
log, err := log.FindID(args.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
err = log.Remove() |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Log", "remove", user.ID, log.ID, nil) |
|
||||
|
|
||||
return &types.LogResolver{L: log}, nil |
|
||||
} |
|
@ -0,0 +1,59 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/change" |
||||
|
"git.aiterp.net/rpdata/api/model/channel" |
||||
|
) |
||||
|
|
||||
|
// ChannelAddArgs is input for the addChannel mutation
|
||||
|
type ChannelAddArgs struct { |
||||
|
Input *struct { |
||||
|
Name string |
||||
|
Logged *bool |
||||
|
Hub *bool |
||||
|
EventName *string |
||||
|
LocationName *string |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// AddChannel resolves the addChannel mutation
|
||||
|
func (r *MutationResolver) AddChannel(ctx context.Context, args *ChannelAddArgs) (*types.ChannelResolver, error) { |
||||
|
input := args.Input |
||||
|
|
||||
|
user := session.FromContext(ctx).User() |
||||
|
if user == nil || !user.Permitted("channel.add") { |
||||
|
return nil, ErrUnauthorized |
||||
|
} |
||||
|
|
||||
|
logged := input.Logged != nil && *input.Logged |
||||
|
|
||||
|
hub := input.Hub != nil && *input.Hub |
||||
|
|
||||
|
eventName := "" |
||||
|
if input.EventName != nil { |
||||
|
eventName = *input.EventName |
||||
|
} |
||||
|
|
||||
|
locationName := "" |
||||
|
if input.LocationName != nil { |
||||
|
locationName = *input.LocationName |
||||
|
} |
||||
|
|
||||
|
channel, err := channel.New(input.Name, logged, hub, eventName, locationName) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
go change.Submit("Channel", "add", user.ID, channel.Name, map[string]interface{}{ |
||||
|
"logged": channel.Logged, |
||||
|
"hub": channel.Hub, |
||||
|
"location": input.LocationName, |
||||
|
"event": input.EventName, |
||||
|
}) |
||||
|
|
||||
|
return &types.ChannelResolver{C: channel}, nil |
||||
|
} |
@ -0,0 +1,67 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"time" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/change" |
||||
|
"git.aiterp.net/rpdata/api/model/story" |
||||
|
) |
||||
|
|
||||
|
// AddChapterArgs is args for the addChapter mutation
|
||||
|
type AddChapterArgs struct { |
||||
|
Input *struct { |
||||
|
StoryID string |
||||
|
Title string |
||||
|
Author *string |
||||
|
Source string |
||||
|
FictionalDate *string |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// AddChapter resolves the addChapter mutation
|
||||
|
func (r *MutationResolver) AddChapter(ctx context.Context, args *AddChapterArgs) (*types.ChapterResolver, error) { |
||||
|
input := args.Input |
||||
|
|
||||
|
user := session.FromContext(ctx).User() |
||||
|
if user == nil || !user.Permitted("member", "chapter.add") { |
||||
|
return nil, ErrUnauthorized |
||||
|
} |
||||
|
|
||||
|
story, err := story.FindID(input.StoryID) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
author := user.ID |
||||
|
if input.Author != nil { |
||||
|
author = *input.Author |
||||
|
|
||||
|
if user.ID != author && !user.Permitted("chapter.add") { |
||||
|
return nil, ErrPermissionDenied |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
fictionalDate := time.Time{} |
||||
|
if input.FictionalDate != nil { |
||||
|
fictionalDate, err = time.Parse(time.RFC3339Nano, *input.FictionalDate) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
chapter, err := story.AddChapter(input.Title, author, input.Source, time.Now(), fictionalDate) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
go change.Submit("Chapter", "add", user.ID, chapter.ID, map[string]interface{}{ |
||||
|
"title": input.Title, |
||||
|
"author": author, |
||||
|
"fictionalDate": fictionalDate, |
||||
|
}) |
||||
|
|
||||
|
return &types.ChapterResolver{C: chapter}, nil |
||||
|
} |
@ -0,0 +1,70 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"strings" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/change" |
||||
|
"git.aiterp.net/rpdata/api/model/character" |
||||
|
"git.aiterp.net/rpdata/api/model/log" |
||||
|
) |
||||
|
|
||||
|
// AddCharacterInput is args for the addCharacter mutation
|
||||
|
type AddCharacterInput struct { |
||||
|
Nick string |
||||
|
Name string |
||||
|
ShortName *string |
||||
|
Author *string |
||||
|
Description *string |
||||
|
} |
||||
|
|
||||
|
// AddCharacter resolves the addCharacter mutation
|
||||
|
func (r *MutationResolver) AddCharacter(ctx context.Context, args struct{ Input *AddCharacterInput }) (*types.CharacterResolver, error) { |
||||
|
input := args.Input |
||||
|
user := session.FromContext(ctx).User() |
||||
|
if user == nil || !user.Permitted("member", "character.add") { |
||||
|
return nil, ErrUnauthorized |
||||
|
} |
||||
|
|
||||
|
nick := input.Nick |
||||
|
|
||||
|
name := input.Name |
||||
|
|
||||
|
shortName := "" |
||||
|
if input.ShortName != nil { |
||||
|
shortName = *input.ShortName |
||||
|
} else { |
||||
|
shortName = strings.SplitN(input.Name, " ", 2)[0] |
||||
|
} |
||||
|
|
||||
|
author := user.ID |
||||
|
if input.Author != nil { |
||||
|
author = *input.Author |
||||
|
|
||||
|
if author != user.ID && !user.Permitted("character.add") { |
||||
|
return nil, ErrPermissionDenied |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
description := "" |
||||
|
if input.Description != nil { |
||||
|
description = *input.Description |
||||
|
} |
||||
|
|
||||
|
character, err := character.New(nick, name, shortName, author, description) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
go change.Submit("Character", "add", user.ID, character.ID, map[string]interface{}{ |
||||
|
"name": character.Name, |
||||
|
"nick": character.Nicks[0], |
||||
|
"author": character.Author, |
||||
|
}) |
||||
|
|
||||
|
log.ScheduleCharacterUpdate() |
||||
|
|
||||
|
return &types.CharacterResolver{C: character}, nil |
||||
|
} |
@ -0,0 +1,48 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/change" |
||||
|
"git.aiterp.net/rpdata/api/model/character" |
||||
|
"git.aiterp.net/rpdata/api/model/log" |
||||
|
) |
||||
|
|
||||
|
// AddCharacterNickInput is args for the addCharacterNick mutation
|
||||
|
type AddCharacterNickInput struct { |
||||
|
ID string |
||||
|
Nick string |
||||
|
} |
||||
|
|
||||
|
// AddCharacterNick resolves the addCharacterNick mutation
|
||||
|
func (r *MutationResolver) AddCharacterNick(ctx context.Context, args struct{ Input *AddCharacterNickInput }) (*types.CharacterResolver, error) { |
||||
|
input := args.Input |
||||
|
|
||||
|
user := session.FromContext(ctx).User() |
||||
|
if user == nil || !user.Permitted("member") { |
||||
|
return nil, ErrUnauthorized |
||||
|
} |
||||
|
|
||||
|
character, err := character.FindID(input.ID) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
if character.Author != user.ID && !user.Permitted("character.edit") { |
||||
|
return nil, ErrPermissionDenied |
||||
|
} |
||||
|
|
||||
|
err = character.AddNick(input.Nick) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
go change.Submit("Character", "add.nick", user.ID, character.ID, map[string]interface{}{ |
||||
|
"nick": input.Nick, |
||||
|
}) |
||||
|
|
||||
|
log.ScheduleCharacterUpdate() |
||||
|
|
||||
|
return &types.CharacterResolver{C: character}, nil |
||||
|
} |
@ -0,0 +1,70 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"time" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/change" |
||||
|
"git.aiterp.net/rpdata/api/model/log" |
||||
|
) |
||||
|
|
||||
|
// LogAddArgs is args for the addLog mutation
|
||||
|
type LogAddArgs struct { |
||||
|
Input *struct { |
||||
|
Date string |
||||
|
Channel string |
||||
|
Title *string |
||||
|
Open *bool |
||||
|
Event *string |
||||
|
Description *string |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// AddLog resolves the addLog mutation
|
||||
|
func (r *MutationResolver) AddLog(ctx context.Context, args *LogAddArgs) (*types.LogResolver, error) { |
||||
|
input := args.Input |
||||
|
|
||||
|
user := session.FromContext(ctx).User() |
||||
|
if user == nil || !user.Permitted("log.add") { |
||||
|
return nil, ErrUnauthorized |
||||
|
} |
||||
|
|
||||
|
date, err := time.Parse(time.RFC3339Nano, args.Input.Date) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
title := "" |
||||
|
if input.Title != nil { |
||||
|
title = *input.Title |
||||
|
} |
||||
|
|
||||
|
event := "" |
||||
|
if input.Event != nil { |
||||
|
event = *input.Event |
||||
|
} |
||||
|
|
||||
|
description := "" |
||||
|
if input.Description != nil { |
||||
|
description = *input.Description |
||||
|
} |
||||
|
|
||||
|
open := input.Open != nil && *input.Open == true |
||||
|
|
||||
|
log, err := log.New(date, input.Channel, title, event, description, open) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
go change.Submit("Log", "add", user.ID, log.ID, map[string]interface{}{ |
||||
|
"channel": log.Channel, |
||||
|
"title": log.Title, |
||||
|
"event": log.Event, |
||||
|
"description": log.Description, |
||||
|
"open": log.Open, |
||||
|
}) |
||||
|
|
||||
|
return &types.LogResolver{L: log}, nil |
||||
|
} |
@ -0,0 +1,60 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"time" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/change" |
||||
|
"git.aiterp.net/rpdata/api/model/log" |
||||
|
) |
||||
|
|
||||
|
// PostAddArgs is args for addPost mutation
|
||||
|
type PostAddArgs struct { |
||||
|
Input *struct { |
||||
|
LogID string |
||||
|
Time string |
||||
|
Kind string |
||||
|
Nick string |
||||
|
Text string |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// AddPost resolves the addPost mutation
|
||||
|
func (r *MutationResolver) AddPost(ctx context.Context, args *PostAddArgs) (*types.PostResolver, error) { |
||||
|
input := args.Input |
||||
|
|
||||
|
user := session.FromContext(ctx).User() |
||||
|
if user == nil || !user.Permitted("post.add") { |
||||
|
return nil, ErrUnauthorized |
||||
|
} |
||||
|
|
||||
|
postTime, err := time.Parse(time.RFC3339Nano, input.Time) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
log, err := log.FindID(input.LogID) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
post, err := log.NewPost(postTime, input.Kind, input.Nick, input.Text) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
go change.Submit("Post", "add", user.ID, post.ID, map[string]interface{}{ |
||||
|
"logId": post.LogID, |
||||
|
"time": post.Time, |
||||
|
"kind": post.Kind, |
||||
|
"nick": post.Nick, |
||||
|
"text": post.Text, |
||||
|
"position": post.Position, |
||||
|
}) |
||||
|
|
||||
|
go log.UpdateCharacters() |
||||
|
|
||||
|
return &types.PostResolver{P: post}, nil |
||||
|
} |
@ -0,0 +1,83 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"time" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/change" |
||||
|
"git.aiterp.net/rpdata/api/model/story" |
||||
|
) |
||||
|
|
||||
|
// StoryAddArgs is args for the addStory mutation
|
||||
|
type StoryAddArgs struct { |
||||
|
Input *struct { |
||||
|
Name string |
||||
|
Category string |
||||
|
Author *string |
||||
|
Open *bool |
||||
|
Listed *bool |
||||
|
FictionalDate *string |
||||
|
Tags *[]struct { |
||||
|
Kind string |
||||
|
Name string |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// AddStory resolves the addStory mutation
|
||||
|
func (r *MutationResolver) AddStory(ctx context.Context, args *StoryAddArgs) (*types.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 &types.StoryResolver{S: story}, nil |
||||
|
} |
@ -0,0 +1,53 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/change" |
||||
|
"git.aiterp.net/rpdata/api/model/story" |
||||
|
) |
||||
|
|
||||
|
// StoryTagAddArgs is args for the addStoryTag mutation
|
||||
|
type StoryTagAddArgs struct { |
||||
|
Input *struct { |
||||
|
ID string |
||||
|
Tag struct { |
||||
|
Kind string |
||||
|
Name string |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// AddStoryTag resolves the addStoryTag mutation
|
||||
|
func (r *MutationResolver) AddStoryTag(ctx context.Context, args *StoryTagAddArgs) (*types.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 &types.StoryResolver{S: story}, nil |
||||
|
} |
@ -0,0 +1,50 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/change" |
||||
|
"git.aiterp.net/rpdata/api/model/channel" |
||||
|
) |
||||
|
|
||||
|
// ChannelEditArgs is input for the editChannel mutation
|
||||
|
type ChannelEditArgs struct { |
||||
|
Input *struct { |
||||
|
Name string |
||||
|
Logged *bool |
||||
|
Hub *bool |
||||
|
EventName *string |
||||
|
LocationName *string |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// EditChannel resolves the editChannel mutation
|
||||
|
func (r *MutationResolver) EditChannel(ctx context.Context, args *ChannelEditArgs) (*types.ChannelResolver, error) { |
||||
|
input := args.Input |
||||
|
|
||||
|
user := session.FromContext(ctx).User() |
||||
|
if user == nil || !user.Permitted("channel.edit") { |
||||
|
return nil, ErrUnauthorized |
||||
|
} |
||||
|
|
||||
|
channel, err := channel.FindName(input.Name) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
err = channel.Edit(input.Logged, input.Hub, input.EventName, input.LocationName) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
go change.Submit("Channel", "edit", user.ID, channel.Name, map[string]interface{}{ |
||||
|
"logged": input.Logged, |
||||
|
"hub": input.Hub, |
||||
|
"location": input.LocationName, |
||||
|
"event": input.EventName, |
||||
|
}) |
||||
|
|
||||
|
return &types.ChannelResolver{C: channel}, nil |
||||
|
} |
@ -0,0 +1,63 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"time" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/change" |
||||
|
"git.aiterp.net/rpdata/api/model/story" |
||||
|
) |
||||
|
|
||||
|
// EditChapterArgs is args for the editChapter mutation
|
||||
|
type EditChapterArgs struct { |
||||
|
Input *struct { |
||||
|
ID string |
||||
|
Title *string |
||||
|
Source *string |
||||
|
FictionalDate *string |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// EditChapter resolves the editChapter mutation
|
||||
|
func (r *MutationResolver) EditChapter(ctx context.Context, args *EditChapterArgs) (*types.ChapterResolver, error) { |
||||
|
input := args.Input |
||||
|
|
||||
|
user := session.FromContext(ctx).User() |
||||
|
if user == nil || !user.Permitted("member", "chapter.edit") { |
||||
|
return nil, ErrUnauthorized |
||||
|
} |
||||
|
|
||||
|
chapter, err := story.FindChapterID(input.ID) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
if chapter.Author != user.ID && !user.Permitted("chapter.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 = chapter.Edit(input.Title, input.Source, fictionalDate) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
go change.Submit("Chapter", "edit", user.ID, chapter.ID, map[string]interface{}{ |
||||
|
"title": input.Title, |
||||
|
"source": input.Source, |
||||
|
"fictionalDate": fictionalDate, |
||||
|
}) |
||||
|
|
||||
|
return &types.ChapterResolver{C: chapter}, nil |
||||
|
} |
@ -0,0 +1,64 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/change" |
||||
|
"git.aiterp.net/rpdata/api/model/character" |
||||
|
) |
||||
|
|
||||
|
// CharacterEditInput is args for mutation addCharacterNick/removeCharacterNick
|
||||
|
type CharacterEditInput struct { |
||||
|
ID string |
||||
|
Name *string |
||||
|
ShortName *string |
||||
|
Description *string |
||||
|
} |
||||
|
|
||||
|
// EditCharacter resolves the editCharacter mutation
|
||||
|
func (r *MutationResolver) EditCharacter(ctx context.Context, args struct{ Input *CharacterEditInput }) (*types.CharacterResolver, error) { |
||||
|
input := args.Input |
||||
|
|
||||
|
user := session.FromContext(ctx).User() |
||||
|
if user == nil || !user.Permitted("member") { |
||||
|
return nil, ErrUnauthorized |
||||
|
} |
||||
|
|
||||
|
character, err := character.FindID(input.ID) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
if character.Author != user.ID && !user.Permitted("character.edit") { |
||||
|
return nil, ErrPermissionDenied |
||||
|
} |
||||
|
|
||||
|
name := "" |
||||
|
if input.Name != nil { |
||||
|
name = *input.Name |
||||
|
} |
||||
|
|
||||
|
shortName := "" |
||||
|
if input.ShortName != nil { |
||||
|
shortName = *input.ShortName |
||||
|
} |
||||
|
|
||||
|
description := "" |
||||
|
if input.Description != nil { |
||||
|
description = *input.Description |
||||
|
} |
||||
|
|
||||
|
err = character.Edit(name, shortName, description) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
go change.Submit("Character", "edit", user.ID, character.ID, map[string]interface{}{ |
||||
|
"name": character.Name, |
||||
|
"shortName": character.ShortName, |
||||
|
"description": character.Description, |
||||
|
}) |
||||
|
|
||||
|
return &types.CharacterResolver{C: character}, nil |
||||
|
} |
@ -0,0 +1,43 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/file" |
||||
|
) |
||||
|
|
||||
|
// FileEditArgs is args for the editFile mutation
|
||||
|
type FileEditArgs struct { |
||||
|
Input *struct { |
||||
|
ID string |
||||
|
Name *string |
||||
|
Public *bool |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// EditFile resolves the editFile mutation
|
||||
|
func (r *MutationResolver) EditFile(ctx context.Context, args *FileEditArgs) (*types.FileResolver, error) { |
||||
|
input := args.Input |
||||
|
|
||||
|
user := session.FromContext(ctx).User() |
||||
|
if user == nil || !user.Permitted("member") { |
||||
|
return nil, ErrUnauthorized |
||||
|
} |
||||
|
|
||||
|
file, err := file.FindID(input.ID) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
if file.Author != user.ID && !user.Permitted("file.edit") { |
||||
|
return nil, ErrUnauthorized |
||||
|
} |
||||
|
|
||||
|
err = file.Edit(input.Name, input.Public) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
return &types.FileResolver{F: file}, nil |
||||
|
} |
@ -0,0 +1,51 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/change" |
||||
|
"git.aiterp.net/rpdata/api/model/log" |
||||
|
) |
||||
|
|
||||
|
// LogEditArgs is args for the editLog mutation
|
||||
|
type LogEditArgs struct { |
||||
|
Input *struct { |
||||
|
ID string |
||||
|
Title *string |
||||
|
Event *string |
||||
|
Description *string |
||||
|
Open *bool |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// EditLog resolves the editLog mutation
|
||||
|
func (r *MutationResolver) EditLog(ctx context.Context, args *LogEditArgs) (*types.LogResolver, error) { |
||||
|
input := args.Input |
||||
|
|
||||
|
user := session.FromContext(ctx).User() |
||||
|
if user == nil || !user.Permitted("log.edit") { |
||||
|
return nil, ErrUnauthorized |
||||
|
} |
||||
|
|
||||
|
log, err := log.FindID(input.ID) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
err = log.Edit(input.Title, input.Event, input.Description, input.Open) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
go change.Submit("Log", "edit", user.ID, log.ID, map[string]interface{}{ |
||||
|
"channel": log.Channel, |
||||
|
"title": input.Title, |
||||
|
"event": input.Event, |
||||
|
"description": input.Description, |
||||
|
"open": input.Open, |
||||
|
}) |
||||
|
|
||||
|
return &types.LogResolver{L: log}, nil |
||||
|
} |
@ -0,0 +1,63 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"time" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/change" |
||||
|
"git.aiterp.net/rpdata/api/model/log" |
||||
|
) |
||||
|
|
||||
|
// PostEditArgs is args for the editPost mutation
|
||||
|
type PostEditArgs struct { |
||||
|
Input *struct { |
||||
|
ID string |
||||
|
Time *string |
||||
|
Kind *string |
||||
|
Nick *string |
||||
|
Text *string |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// EditPost resolves the editPost mutation
|
||||
|
func (r *MutationResolver) EditPost(ctx context.Context, args *PostEditArgs) (*types.PostResolver, error) { |
||||
|
input := args.Input |
||||
|
|
||||
|
user := session.FromContext(ctx).User() |
||||
|
if user == nil || !user.Permitted("post.edit") { |
||||
|
return nil, ErrUnauthorized |
||||
|
} |
||||
|
|
||||
|
postTime := (*time.Time)(nil) |
||||
|
if args.Input.Time != nil { |
||||
|
t, err := time.Parse(time.RFC3339Nano, *input.Time) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
postTime = &t |
||||
|
} |
||||
|
|
||||
|
post, err := log.FindPostID(input.ID) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
err = post.Edit(postTime, input.Kind, input.Nick, input.Text) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
go change.Submit("Post", "edit", user.ID, post.ID, map[string]interface{}{ |
||||
|
"time": postTime, |
||||
|
"kind": input.Kind, |
||||
|
"nick": input.Nick, |
||||
|
"text": input.Text, |
||||
|
}) |
||||
|
|
||||
|
go log.UpdateCharacters(post.LogID) |
||||
|
|
||||
|
return &types.PostResolver{P: post}, nil |
||||
|
} |
@ -0,0 +1,69 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"time" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/change" |
||||
|
"git.aiterp.net/rpdata/api/model/story" |
||||
|
) |
||||
|
|
||||
|
// 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 resolves the editStory mutation
|
||||
|
func (r *MutationResolver) EditStory(ctx context.Context, args *StoryEditArgs) (*types.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 &types.StoryResolver{S: story}, nil |
||||
|
} |
@ -0,0 +1,26 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
) |
||||
|
|
||||
|
// LoginArgs is args for the login mutation
|
||||
|
type LoginArgs struct { |
||||
|
Username string |
||||
|
Password string |
||||
|
} |
||||
|
|
||||
|
// Login resolves the login mutation
|
||||
|
func (r *MutationResolver) Login(ctx context.Context, args *LoginArgs) (*types.SessionResolver, error) { |
||||
|
session := session.FromContext(ctx) |
||||
|
|
||||
|
err := session.Login(args.Username, args.Password) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
return &types.SessionResolver{S: session}, nil |
||||
|
} |
@ -0,0 +1,16 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
) |
||||
|
|
||||
|
// Logout resolves mutation.logout
|
||||
|
func (r *MutationResolver) Logout(ctx context.Context) (*types.SessionResolver, error) { |
||||
|
session := session.FromContext(ctx) |
||||
|
session.Logout() |
||||
|
|
||||
|
return &types.SessionResolver{S: session}, nil |
||||
|
} |
@ -0,0 +1,45 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/change" |
||||
|
"git.aiterp.net/rpdata/api/model/log" |
||||
|
) |
||||
|
|
||||
|
// PostMoveArgs is args for movePost mutation
|
||||
|
type PostMoveArgs struct { |
||||
|
Input *struct { |
||||
|
ID string |
||||
|
ToPosition int32 |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// MovePost resolves the movePost mutation
|
||||
|
func (r *MutationResolver) MovePost(ctx context.Context, args *PostMoveArgs) (*types.PostResolver, error) { |
||||
|
input := args.Input |
||||
|
|
||||
|
user := session.FromContext(ctx).User() |
||||
|
if user == nil || !user.Permitted("post.move") { |
||||
|
return nil, ErrUnauthorized |
||||
|
} |
||||
|
|
||||
|
post, err := log.FindPostID(input.ID) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
err = post.Move(int(input.ToPosition)) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
go change.Submit("Post", "move", user.ID, post.ID, map[string]interface{}{ |
||||
|
"logId": post.LogID, |
||||
|
"targetIndex": input.ToPosition, |
||||
|
}) |
||||
|
|
||||
|
return &types.PostResolver{P: post}, nil |
||||
|
} |
@ -0,0 +1,37 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/change" |
||||
|
"git.aiterp.net/rpdata/api/model/channel" |
||||
|
) |
||||
|
|
||||
|
// RemoveChannelArgs is args for removeChannels mutation
|
||||
|
type RemoveChannelArgs struct { |
||||
|
Name string |
||||
|
} |
||||
|
|
||||
|
// RemoveChannel resolves the editChannel mutation
|
||||
|
func (r *MutationResolver) RemoveChannel(ctx context.Context, args RemoveChannelArgs) (*types.ChannelResolver, error) { |
||||
|
user := session.FromContext(ctx).User() |
||||
|
if user == nil || !user.Permitted("channel.remove") { |
||||
|
return nil, ErrUnauthorized |
||||
|
} |
||||
|
|
||||
|
channel, err := channel.FindName(args.Name) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
err = channel.Remove() |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
go change.Submit("Channel", "remove", user.ID, channel.Name, nil) |
||||
|
|
||||
|
return &types.ChannelResolver{C: channel}, nil |
||||
|
} |
@ -0,0 +1,37 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/change" |
||||
|
"git.aiterp.net/rpdata/api/model/story" |
||||
|
) |
||||
|
|
||||
|
// RemoveChapterArgs is args for the addChapter mutation
|
||||
|
type RemoveChapterArgs struct { |
||||
|
ID string |
||||
|
} |
||||
|
|
||||
|
// RemoveChapter resolves the removeChapter mutation
|
||||
|
func (r *MutationResolver) RemoveChapter(ctx context.Context, args *RemoveChapterArgs) (*types.ChapterResolver, error) { |
||||
|
user := session.FromContext(ctx).User() |
||||
|
if user == nil || !user.Permitted("member", "chapter.edit") { |
||||
|
return nil, ErrUnauthorized |
||||
|
} |
||||
|
|
||||
|
chapter, err := story.FindChapterID(args.ID) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
err = chapter.Remove() |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
go change.Submit("Chapter", "remove", user.ID, chapter.ID, nil) |
||||
|
|
||||
|
return &types.ChapterResolver{C: chapter}, nil |
||||
|
} |
@ -0,0 +1,44 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/change" |
||||
|
"git.aiterp.net/rpdata/api/model/character" |
||||
|
) |
||||
|
|
||||
|
// RemoveCharacterArgs is args for the removeCharacter mutation
|
||||
|
type RemoveCharacterArgs struct { |
||||
|
ID string |
||||
|
} |
||||
|
|
||||
|
// RemoveCharacter resolves the removeCharacter mutation
|
||||
|
func (r *MutationResolver) RemoveCharacter(ctx context.Context, args RemoveCharacterArgs) (*types.CharacterResolver, error) { |
||||
|
user := session.FromContext(ctx).User() |
||||
|
if user == nil || !user.Permitted("member") { |
||||
|
return nil, ErrUnauthorized |
||||
|
} |
||||
|
|
||||
|
character, err := character.FindID(args.ID) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
if character.Author != user.ID && !user.Permitted("character.remove") { |
||||
|
return nil, ErrPermissionDenied |
||||
|
} |
||||
|
|
||||
|
err = character.Remove() |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
go change.Submit("Character", "remove", user.ID, character.ID, map[string]interface{}{ |
||||
|
"name": character.Name, |
||||
|
"author": character.Author, |
||||
|
"nicks": character.Nicks, |
||||
|
}) |
||||
|
|
||||
|
return &types.CharacterResolver{C: character}, nil |
||||
|
} |
@ -0,0 +1,48 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/change" |
||||
|
"git.aiterp.net/rpdata/api/model/character" |
||||
|
"git.aiterp.net/rpdata/api/model/log" |
||||
|
) |
||||
|
|
||||
|
// RemoveCharacterNick is args for the addCharacterNick mutation
|
||||
|
type RemoveCharacterNick struct { |
||||
|
ID string |
||||
|
Nick string |
||||
|
} |
||||
|
|
||||
|
// RemoveCharacterNick resolves the removeCharacterNick mutation
|
||||
|
func (r *MutationResolver) RemoveCharacterNick(ctx context.Context, args struct{ Input *RemoveCharacterNick }) (*types.CharacterResolver, error) { |
||||
|
input := args.Input |
||||
|
|
||||
|
user := session.FromContext(ctx).User() |
||||
|
if user == nil || !user.Permitted("member") { |
||||
|
return nil, ErrUnauthorized |
||||
|
} |
||||
|
|
||||
|
character, err := character.FindID(input.ID) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
if character.Author != user.ID && !user.Permitted("character.edit") { |
||||
|
return nil, ErrPermissionDenied |
||||
|
} |
||||
|
|
||||
|
err = character.RemoveNick(input.Nick) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
go change.Submit("Character", "remove.nick", user.ID, character.ID, map[string]interface{}{ |
||||
|
"nick": input.Nick, |
||||
|
}) |
||||
|
|
||||
|
log.ScheduleCharacterUpdate() |
||||
|
|
||||
|
return &types.CharacterResolver{C: character}, nil |
||||
|
} |
@ -0,0 +1,37 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/file" |
||||
|
) |
||||
|
|
||||
|
// RemoveFileArgs is an arg
|
||||
|
type RemoveFileArgs struct { |
||||
|
ID string |
||||
|
} |
||||
|
|
||||
|
// RemoveFile resolves the removeFIle mutation
|
||||
|
func (r *MutationResolver) RemoveFile(ctx context.Context, args *RemoveFileArgs) (*types.FileResolver, error) { |
||||
|
user := session.FromContext(ctx).User() |
||||
|
if user == nil || !user.Permitted("member") { |
||||
|
return nil, ErrUnauthorized |
||||
|
} |
||||
|
|
||||
|
file, err := file.FindID(args.ID) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
if file.Author != user.ID && !user.Permitted("file.remove") { |
||||
|
return nil, ErrUnauthorized |
||||
|
} |
||||
|
|
||||
|
err = file.Delete() |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
return &types.FileResolver{F: file}, nil |
||||
|
} |
@ -0,0 +1,37 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/change" |
||||
|
"git.aiterp.net/rpdata/api/model/log" |
||||
|
) |
||||
|
|
||||
|
// RemoveLogArgs is args for the removeLog mutation
|
||||
|
type RemoveLogArgs struct { |
||||
|
ID string |
||||
|
} |
||||
|
|
||||
|
// RemoveLog resolves the removeLog mutation
|
||||
|
func (r *MutationResolver) RemoveLog(ctx context.Context, args *RemoveLogArgs) (*types.LogResolver, error) { |
||||
|
user := session.FromContext(ctx).User() |
||||
|
if user == nil || !user.Permitted("log.remove") { |
||||
|
return nil, ErrUnauthorized |
||||
|
} |
||||
|
|
||||
|
log, err := log.FindID(args.ID) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
err = log.Remove() |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
go change.Submit("Log", "remove", user.ID, log.ID, nil) |
||||
|
|
||||
|
return &types.LogResolver{L: log}, nil |
||||
|
} |
@ -0,0 +1,36 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/change" |
||||
|
"git.aiterp.net/rpdata/api/model/log" |
||||
|
) |
||||
|
|
||||
|
// PostRemoveArgs is args for the removePost mutation
|
||||
|
type PostRemoveArgs struct { |
||||
|
ID string |
||||
|
} |
||||
|
|
||||
|
// RemovePost resolves the removePost mutation
|
||||
|
func (r *MutationResolver) RemovePost(ctx context.Context, args PostRemoveArgs) (*types.PostResolver, error) { |
||||
|
user := session.FromContext(ctx).User() |
||||
|
if user == nil || !user.Permitted("post.remove") { |
||||
|
return nil, ErrUnauthorized |
||||
|
} |
||||
|
|
||||
|
post, err := log.RemovePost(args.ID) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
go change.Submit("Post", "remove", user.ID, post.ID, map[string]interface{}{ |
||||
|
"logId": post.LogID, |
||||
|
}) |
||||
|
|
||||
|
go log.UpdateCharacters(post.LogID) |
||||
|
|
||||
|
return &types.PostResolver{P: post}, nil |
||||
|
} |
@ -0,0 +1,41 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/change" |
||||
|
"git.aiterp.net/rpdata/api/model/story" |
||||
|
) |
||||
|
|
||||
|
// StoryRemoveArgs is args for the removeStory mutation
|
||||
|
type StoryRemoveArgs struct { |
||||
|
ID string |
||||
|
} |
||||
|
|
||||
|
// RemoveStory resolves the removeStory mutation
|
||||
|
func (r *MutationResolver) RemoveStory(ctx context.Context, args *StoryRemoveArgs) (*types.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 &types.StoryResolver{S: story}, nil |
||||
|
} |
@ -0,0 +1,53 @@ |
|||||
|
package mutations |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/change" |
||||
|
"git.aiterp.net/rpdata/api/model/story" |
||||
|
) |
||||
|
|
||||
|
// StoryTagRemoveArgs is args for the removeStoryTag mutation
|
||||
|
type StoryTagRemoveArgs struct { |
||||
|
Input *struct { |
||||
|
ID string |
||||
|
Tag struct { |
||||
|
Kind string |
||||
|
Name string |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// RemoveStoryTag resolves the removeStoryTag mutation
|
||||
|
func (r *MutationResolver) RemoveStoryTag(ctx context.Context, args *StoryTagRemoveArgs) (*types.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 &types.StoryResolver{S: story}, nil |
||||
|
} |
@ -0,0 +1,14 @@ |
|||||
|
// Package mutations contains resolvers for individual GrahpQL mutations. They were previously mixed in with one another, but that caused
|
||||
|
// difficulty seeking out specific mutations.
|
||||
|
package mutations |
||||
|
|
||||
|
import "errors" |
||||
|
|
||||
|
// MutationResolver is a resolver for all mutations. The stuttery name is due to being embedded in the root resolver.
|
||||
|
type MutationResolver struct{} |
||||
|
|
||||
|
// 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") |
@ -1,208 +0,0 @@ |
|||||
package resolver |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
"time" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/session" |
|
||||
"git.aiterp.net/rpdata/api/model/change" |
|
||||
"git.aiterp.net/rpdata/api/model/log" |
|
||||
) |
|
||||
|
|
||||
// PostArgs is an arg
|
|
||||
type PostArgs struct { |
|
||||
ID string |
|
||||
} |
|
||||
|
|
||||
// Post implements the post query
|
|
||||
func (r *QueryResolver) Post(ctx context.Context, args *PostArgs) (*types.PostResolver, error) { |
|
||||
post, err := log.FindPostID(args.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
return &types.PostResolver{P: post}, nil |
|
||||
} |
|
||||
|
|
||||
// PostsArgs is an arg
|
|
||||
type PostsArgs struct { |
|
||||
IDs []string |
|
||||
} |
|
||||
|
|
||||
// Posts implements the posts query
|
|
||||
func (r *QueryResolver) Posts(ctx context.Context, args *PostsArgs) ([]*types.PostResolver, error) { |
|
||||
posts, err := log.ListPostIDs(args.IDs...) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
resolvers := make([]*types.PostResolver, len(posts)) |
|
||||
for i := range resolvers { |
|
||||
resolvers[i] = &types.PostResolver{P: posts[i]} |
|
||||
} |
|
||||
|
|
||||
return resolvers, nil |
|
||||
} |
|
||||
|
|
||||
// PostAddArgs is args for addPost mutation
|
|
||||
type PostAddArgs struct { |
|
||||
Input *struct { |
|
||||
LogID string |
|
||||
Time string |
|
||||
Kind string |
|
||||
Nick string |
|
||||
Text string |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// AddPost resolves the addPost mutation
|
|
||||
func (r *MutationResolver) AddPost(ctx context.Context, args *PostAddArgs) (*types.PostResolver, error) { |
|
||||
input := args.Input |
|
||||
|
|
||||
user := session.FromContext(ctx).User() |
|
||||
if user == nil || !user.Permitted("post.add") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
postTime, err := time.Parse(time.RFC3339Nano, input.Time) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
log, err := log.FindID(input.LogID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
post, err := log.NewPost(postTime, input.Kind, input.Nick, input.Text) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Post", "add", user.ID, post.ID, map[string]interface{}{ |
|
||||
"logId": post.LogID, |
|
||||
"time": post.Time, |
|
||||
"kind": post.Kind, |
|
||||
"nick": post.Nick, |
|
||||
"text": post.Text, |
|
||||
"position": post.Position, |
|
||||
}) |
|
||||
|
|
||||
go log.UpdateCharacters() |
|
||||
|
|
||||
return &types.PostResolver{P: post}, nil |
|
||||
} |
|
||||
|
|
||||
// PostEditArgs is args for the editPost mutation
|
|
||||
type PostEditArgs struct { |
|
||||
Input *struct { |
|
||||
ID string |
|
||||
Time *string |
|
||||
Kind *string |
|
||||
Nick *string |
|
||||
Text *string |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// EditPost resolves the editPost mutation
|
|
||||
func (r *MutationResolver) EditPost(ctx context.Context, args *PostEditArgs) (*types.PostResolver, error) { |
|
||||
input := args.Input |
|
||||
|
|
||||
user := session.FromContext(ctx).User() |
|
||||
if user == nil || !user.Permitted("post.edit") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
postTime := (*time.Time)(nil) |
|
||||
if args.Input.Time != nil { |
|
||||
t, err := time.Parse(time.RFC3339Nano, *input.Time) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
postTime = &t |
|
||||
} |
|
||||
|
|
||||
post, err := log.FindPostID(input.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
err = post.Edit(postTime, input.Kind, input.Nick, input.Text) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Post", "edit", user.ID, post.ID, map[string]interface{}{ |
|
||||
"time": postTime, |
|
||||
"kind": input.Kind, |
|
||||
"nick": input.Nick, |
|
||||
"text": input.Text, |
|
||||
}) |
|
||||
|
|
||||
go log.UpdateCharacters(post.LogID) |
|
||||
|
|
||||
return &types.PostResolver{P: post}, nil |
|
||||
} |
|
||||
|
|
||||
// PostMoveArgs is args for movePost mutation
|
|
||||
type PostMoveArgs struct { |
|
||||
Input *struct { |
|
||||
ID string |
|
||||
ToPosition int32 |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// MovePost resolves the movePost mutation
|
|
||||
func (r *MutationResolver) MovePost(ctx context.Context, args *PostMoveArgs) (*types.PostResolver, error) { |
|
||||
input := args.Input |
|
||||
|
|
||||
user := session.FromContext(ctx).User() |
|
||||
if user == nil || !user.Permitted("post.move") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
post, err := log.FindPostID(input.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
err = post.Move(int(input.ToPosition)) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Post", "move", user.ID, post.ID, map[string]interface{}{ |
|
||||
"logId": post.LogID, |
|
||||
"targetIndex": input.ToPosition, |
|
||||
}) |
|
||||
|
|
||||
return &types.PostResolver{P: post}, nil |
|
||||
} |
|
||||
|
|
||||
// PostRemoveArgs is an arg
|
|
||||
type PostRemoveArgs struct { |
|
||||
ID string |
|
||||
} |
|
||||
|
|
||||
// RemovePost resolves the removePost mutation
|
|
||||
func (r *MutationResolver) RemovePost(ctx context.Context, args PostRemoveArgs) (*types.PostResolver, error) { |
|
||||
user := session.FromContext(ctx).User() |
|
||||
if user == nil || !user.Permitted("post.remove") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
post, err := log.RemovePost(args.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Post", "remove", user.ID, post.ID, map[string]interface{}{ |
|
||||
"logId": post.LogID, |
|
||||
}) |
|
||||
|
|
||||
go log.UpdateCharacters(post.LogID) |
|
||||
|
|
||||
return &types.PostResolver{P: post}, nil |
|
||||
} |
|
@ -0,0 +1,23 @@ |
|||||
|
package queries |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/model/channel" |
||||
|
) |
||||
|
|
||||
|
// ChannelArgs is args for channel query
|
||||
|
type ChannelArgs struct { |
||||
|
Name string |
||||
|
} |
||||
|
|
||||
|
// Channel resolves the channel query
|
||||
|
func (r *QueryResolver) Channel(ctx context.Context, args *ChannelArgs) (*types.ChannelResolver, error) { |
||||
|
channel, err := channel.FindName(args.Name) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
return &types.ChannelResolver{C: channel}, nil |
||||
|
} |
@ -0,0 +1,28 @@ |
|||||
|
package queries |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/model/channel" |
||||
|
) |
||||
|
|
||||
|
// ChannelsArgs is args for channel query
|
||||
|
type ChannelsArgs struct { |
||||
|
Logged *bool |
||||
|
} |
||||
|
|
||||
|
// Channels resolves the channels query
|
||||
|
func (r *QueryResolver) Channels(ctx context.Context, args *ChannelsArgs) ([]*types.ChannelResolver, error) { |
||||
|
channels, err := channel.List(args.Logged != nil && *args.Logged) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
resolvers := make([]*types.ChannelResolver, len(channels)) |
||||
|
for i := range channels { |
||||
|
resolvers[i] = &types.ChannelResolver{C: channels[i]} |
||||
|
} |
||||
|
|
||||
|
return resolvers, nil |
||||
|
} |
@ -0,0 +1,23 @@ |
|||||
|
package queries |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/model/story" |
||||
|
) |
||||
|
|
||||
|
// ChapterArgs is args for chapter query
|
||||
|
type ChapterArgs struct { |
||||
|
ID string |
||||
|
} |
||||
|
|
||||
|
// Chapter resolves the chapter query
|
||||
|
func (r *QueryResolver) Chapter(ctx context.Context, args *ChapterArgs) (*types.ChapterResolver, error) { |
||||
|
chapter, err := story.FindChapterID(args.ID) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
return &types.ChapterResolver{C: chapter}, nil |
||||
|
} |
@ -0,0 +1,43 @@ |
|||||
|
package queries |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"errors" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/model/character" |
||||
|
) |
||||
|
|
||||
|
// ErrIncorrectArguments is returned by character query.
|
||||
|
var ErrIncorrectArguments = errors.New("You can only query character by ID or Nick") |
||||
|
|
||||
|
// CharacterArgs is args for character query
|
||||
|
type CharacterArgs struct { |
||||
|
ID *string |
||||
|
Nick *string |
||||
|
} |
||||
|
|
||||
|
// Character resolves the character query
|
||||
|
func (r *QueryResolver) Character(ctx context.Context, args *CharacterArgs) (*types.CharacterResolver, error) { |
||||
|
var char character.Character |
||||
|
var err error |
||||
|
|
||||
|
if args.Nick != nil && args.ID != nil { |
||||
|
return nil, ErrIncorrectArguments |
||||
|
} |
||||
|
|
||||
|
switch { |
||||
|
case args.ID != nil: |
||||
|
char, err = character.FindID(*args.ID) |
||||
|
case args.Nick != nil: |
||||
|
char, err = character.FindNick(*args.Nick) |
||||
|
default: |
||||
|
err = ErrIncorrectArguments |
||||
|
} |
||||
|
|
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
return &types.CharacterResolver{C: char}, nil |
||||
|
} |
@ -0,0 +1,54 @@ |
|||||
|
package queries |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"errors" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/loader" |
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/model/character" |
||||
|
) |
||||
|
|
||||
|
// CharactersArgs is args for characters query
|
||||
|
type CharactersArgs struct { |
||||
|
IDs *[]string |
||||
|
Nicks *[]string |
||||
|
Author *string |
||||
|
} |
||||
|
|
||||
|
// Characters resolves the characters query
|
||||
|
func (r *QueryResolver) Characters(ctx context.Context, args *CharactersArgs) ([]*types.CharacterResolver, error) { |
||||
|
var chars []character.Character |
||||
|
var err error |
||||
|
|
||||
|
loader := loader.FromContext(ctx) |
||||
|
if loader == nil { |
||||
|
return nil, errors.New("no loader") |
||||
|
} |
||||
|
|
||||
|
switch { |
||||
|
case args.IDs != nil: |
||||
|
chars, err = character.ListIDs(*args.IDs...) |
||||
|
case args.Nicks != nil: |
||||
|
chars, err = character.ListNicks(*args.Nicks...) |
||||
|
case args.Author != nil: |
||||
|
chars, err = character.ListAuthor(*args.Author) |
||||
|
default: |
||||
|
chars, err = character.List() |
||||
|
} |
||||
|
|
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
resolvers := make([]*types.CharacterResolver, 0, len(chars)) |
||||
|
for i := range chars { |
||||
|
if chars[i].ID == "" { |
||||
|
continue |
||||
|
} |
||||
|
|
||||
|
resolvers = append(resolvers, &types.CharacterResolver{C: chars[i]}) |
||||
|
} |
||||
|
|
||||
|
return resolvers, nil |
||||
|
} |
@ -0,0 +1,23 @@ |
|||||
|
package queries |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/model/file" |
||||
|
) |
||||
|
|
||||
|
// FileArgs is args for file query
|
||||
|
type FileArgs struct { |
||||
|
ID string |
||||
|
} |
||||
|
|
||||
|
// File resolves the file query
|
||||
|
func (r *QueryResolver) File(ctx context.Context, args *FileArgs) (*types.FileResolver, error) { |
||||
|
file, err := file.FindID(args.ID) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
return &types.FileResolver{F: file}, nil |
||||
|
} |
@ -0,0 +1,43 @@ |
|||||
|
package queries |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
"git.aiterp.net/rpdata/api/model/file" |
||||
|
) |
||||
|
|
||||
|
// FilesArgs is args for files query
|
||||
|
type FilesArgs struct { |
||||
|
IncludePublic *bool |
||||
|
MimeTypes *[]string |
||||
|
} |
||||
|
|
||||
|
// Files resolves the file query
|
||||
|
func (r *QueryResolver) Files(ctx context.Context, args *FilesArgs) ([]*types.FileResolver, error) { |
||||
|
user := session.FromContext(ctx).User() |
||||
|
author := "" |
||||
|
if user != nil { |
||||
|
author = user.ID |
||||
|
} |
||||
|
|
||||
|
public := args.IncludePublic != nil && *args.IncludePublic == true |
||||
|
|
||||
|
mimeTypes := []string(nil) |
||||
|
if args.MimeTypes != nil { |
||||
|
mimeTypes = *args.MimeTypes |
||||
|
} |
||||
|
|
||||
|
files, err := file.List(author, public, mimeTypes) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
resolvers := make([]*types.FileResolver, len(files)) |
||||
|
for i := range files { |
||||
|
resolvers[i] = &types.FileResolver{F: files[i]} |
||||
|
} |
||||
|
|
||||
|
return resolvers, nil |
||||
|
} |
@ -0,0 +1,32 @@ |
|||||
|
package queries |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/model/log" |
||||
|
) |
||||
|
|
||||
|
// LogArgs is args for log query
|
||||
|
type LogArgs struct { |
||||
|
ID *string |
||||
|
} |
||||
|
|
||||
|
// Log resolves the log query
|
||||
|
func (r *QueryResolver) Log(ctx context.Context, args *LogArgs) (*types.LogResolver, error) { |
||||
|
var l log.Log |
||||
|
var err error |
||||
|
|
||||
|
switch { |
||||
|
case args.ID != nil: |
||||
|
l, err = log.FindID(*args.ID) |
||||
|
default: |
||||
|
err = ErrCannotResolve |
||||
|
} |
||||
|
|
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
return &types.LogResolver{L: l}, nil |
||||
|
} |
@ -0,0 +1,79 @@ |
|||||
|
package queries |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/model/log" |
||||
|
) |
||||
|
|
||||
|
// LogsArgs is args for the logs query
|
||||
|
type LogsArgs struct { |
||||
|
Filter *struct { |
||||
|
Search *string |
||||
|
Characters *[]string |
||||
|
Channels *[]string |
||||
|
Events *[]string |
||||
|
Open *bool |
||||
|
Limit *int32 |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Logs resolves the logs query
|
||||
|
func (r *QueryResolver) Logs(ctx context.Context, args *LogsArgs) ([]*types.LogResolver, error) { |
||||
|
var logs []log.Log |
||||
|
var err error |
||||
|
|
||||
|
filter := args.Filter |
||||
|
|
||||
|
if filter != nil { |
||||
|
limit := 100 |
||||
|
search := "" |
||||
|
|
||||
|
if filter.Search != nil { |
||||
|
search = *filter.Search |
||||
|
limit = 0 |
||||
|
} |
||||
|
|
||||
|
channels := []string(nil) |
||||
|
if filter.Channels != nil { |
||||
|
channels = *filter.Channels |
||||
|
limit = 0 |
||||
|
} |
||||
|
|
||||
|
characters := []string(nil) |
||||
|
if filter.Characters != nil { |
||||
|
characters = *filter.Characters |
||||
|
limit = 0 |
||||
|
} |
||||
|
|
||||
|
events := []string(nil) |
||||
|
if filter.Events != nil { |
||||
|
events = *filter.Events |
||||
|
limit = 0 |
||||
|
} |
||||
|
|
||||
|
if filter.Limit != nil { |
||||
|
limit = int(*filter.Limit) |
||||
|
} |
||||
|
|
||||
|
open := filter.Open != nil && *filter.Open == true |
||||
|
|
||||
|
logs, err = log.ListSearch(search, channels, characters, events, open, limit) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
} else { |
||||
|
logs, err = log.List(100) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
resolvers := make([]*types.LogResolver, len(logs)) |
||||
|
for i := range logs { |
||||
|
resolvers[i] = &types.LogResolver{L: logs[i]} |
||||
|
} |
||||
|
|
||||
|
return resolvers, nil |
||||
|
} |
@ -0,0 +1,23 @@ |
|||||
|
package queries |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/model/log" |
||||
|
) |
||||
|
|
||||
|
// PostArgs is args for the post query
|
||||
|
type PostArgs struct { |
||||
|
ID string |
||||
|
} |
||||
|
|
||||
|
// Post resolves the post query
|
||||
|
func (r *QueryResolver) Post(ctx context.Context, args *PostArgs) (*types.PostResolver, error) { |
||||
|
post, err := log.FindPostID(args.ID) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
return &types.PostResolver{P: post}, nil |
||||
|
} |
@ -0,0 +1,28 @@ |
|||||
|
package queries |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/model/log" |
||||
|
) |
||||
|
|
||||
|
// PostsArgs is args for the posts query
|
||||
|
type PostsArgs struct { |
||||
|
IDs []string |
||||
|
} |
||||
|
|
||||
|
// Posts resolves the posts query
|
||||
|
func (r *QueryResolver) Posts(ctx context.Context, args *PostsArgs) ([]*types.PostResolver, error) { |
||||
|
posts, err := log.ListPostIDs(args.IDs...) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
resolvers := make([]*types.PostResolver, len(posts)) |
||||
|
for i := range resolvers { |
||||
|
resolvers[i] = &types.PostResolver{P: posts[i]} |
||||
|
} |
||||
|
|
||||
|
return resolvers, nil |
||||
|
} |
@ -0,0 +1,11 @@ |
|||||
|
// Package queries contains resolvers for individual GrahpQL queries. They were previously mixed in with one another, but that caused
|
||||
|
// difficulty seeking out specific queries.
|
||||
|
package queries |
||||
|
|
||||
|
import "errors" |
||||
|
|
||||
|
// QueryResolver is a resolver for all queries. The stuttery name is due to being embedded in the root resolver.
|
||||
|
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") |
@ -0,0 +1,13 @@ |
|||||
|
package queries |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/internal/session" |
||||
|
) |
||||
|
|
||||
|
// Session resolves query.session
|
||||
|
func (r *QueryResolver) Session(ctx context.Context) (*types.SessionResolver, error) { |
||||
|
return &types.SessionResolver{S: session.FromContext(ctx)}, nil |
||||
|
} |
@ -0,0 +1,77 @@ |
|||||
|
package queries |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"time" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/model/story" |
||||
|
) |
||||
|
|
||||
|
// StoriesArg is args for stories query
|
||||
|
type StoriesArg struct { |
||||
|
Filter *struct { |
||||
|
Author *string |
||||
|
Tags *[]struct { |
||||
|
Kind string |
||||
|
Name string |
||||
|
} |
||||
|
EarliestFictionalDate *string |
||||
|
LatestFictionalDate *string |
||||
|
Limit *int32 |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Stories resolves the stories query
|
||||
|
func (r *QueryResolver) Stories(ctx context.Context, args *StoriesArg) ([]*types.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([]*types.StoryResolver, len(stories)) |
||||
|
for i, story := range stories { |
||||
|
resolvers[i] = &types.StoryResolver{S: story} |
||||
|
} |
||||
|
|
||||
|
return resolvers, nil |
||||
|
} |
@ -0,0 +1,23 @@ |
|||||
|
package queries |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
|
"git.aiterp.net/rpdata/api/model/story" |
||||
|
) |
||||
|
|
||||
|
// StoryArgs is args for story query
|
||||
|
type StoryArgs struct { |
||||
|
ID string |
||||
|
} |
||||
|
|
||||
|
// Story resolves the story query
|
||||
|
func (r *QueryResolver) Story(ctx context.Context, args *StoryArgs) (*types.StoryResolver, error) { |
||||
|
story, err := story.FindID(args.ID) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
return &types.StoryResolver{S: story}, nil |
||||
|
} |
@ -1,17 +1,11 @@ |
|||||
package resolver |
|
||||
|
package queries |
||||
|
|
||||
import ( |
import ( |
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
||||
"git.aiterp.net/rpdata/api/model/story" |
"git.aiterp.net/rpdata/api/model/story" |
||||
) |
) |
||||
|
|
||||
// TagInput resolves the TagInput input
|
|
||||
type TagInput struct { |
|
||||
Kind string |
|
||||
Name string |
|
||||
} |
|
||||
|
|
||||
// Tags implements the tags query
|
|
||||
|
// Tags resolves the tags query
|
||||
func (r *QueryResolver) Tags() ([]*types.TagResolver, error) { |
func (r *QueryResolver) Tags() ([]*types.TagResolver, error) { |
||||
tags, err := story.ListTags() |
tags, err := story.ListTags() |
||||
if err != nil { |
if err != nil { |
@ -0,0 +1,13 @@ |
|||||
|
package resolver |
||||
|
|
||||
|
import ( |
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/mutations" |
||||
|
"git.aiterp.net/rpdata/api/graphql/resolver/queries" |
||||
|
) |
||||
|
|
||||
|
// The Resolver combines the query and mutation resolvers from the subpackages.
|
||||
|
// This is the one to pass along with the schema.
|
||||
|
type Resolver struct { |
||||
|
queries.QueryResolver |
||||
|
mutations.MutationResolver |
||||
|
} |
@ -1,13 +0,0 @@ |
|||||
package resolver |
|
||||
|
|
||||
// The RootResolver brings queries and mutations together. The rest is just for readability.
|
|
||||
type RootResolver struct { |
|
||||
MutationResolver |
|
||||
QueryResolver |
|
||||
} |
|
||||
|
|
||||
// The QueryResolver is the entry point for all top-level read operations.
|
|
||||
type QueryResolver struct{} |
|
||||
|
|
||||
// The MutationResolver is the entry point for all top-level mutation operations.
|
|
||||
type MutationResolver struct{} |
|
@ -1,39 +0,0 @@ |
|||||
package resolver |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/session" |
|
||||
) |
|
||||
|
|
||||
// LoginArgs is args
|
|
||||
type LoginArgs struct { |
|
||||
Username string |
|
||||
Password string |
|
||||
} |
|
||||
|
|
||||
// Session resolves query.session
|
|
||||
func (r *QueryResolver) Session(ctx context.Context) (*types.SessionResolver, error) { |
|
||||
return &types.SessionResolver{S: session.FromContext(ctx)}, nil |
|
||||
} |
|
||||
|
|
||||
// Login resolves mutation.login
|
|
||||
func (r *MutationResolver) Login(ctx context.Context, args *LoginArgs) (*types.SessionResolver, error) { |
|
||||
session := session.FromContext(ctx) |
|
||||
|
|
||||
err := session.Login(args.Username, args.Password) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
return &types.SessionResolver{S: session}, nil |
|
||||
} |
|
||||
|
|
||||
// Logout resolves mutation.logout
|
|
||||
func (r *MutationResolver) Logout(ctx context.Context) (*types.SessionResolver, error) { |
|
||||
session := session.FromContext(ctx) |
|
||||
session.Logout() |
|
||||
|
|
||||
return &types.SessionResolver{S: session}, nil |
|
||||
} |
|
@ -1,329 +0,0 @@ |
|||||
package resolver |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
"time" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/session" |
|
||||
"git.aiterp.net/rpdata/api/model/change" |
|
||||
"git.aiterp.net/rpdata/api/model/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) (*types.StoryResolver, error) { |
|
||||
story, err := story.FindID(args.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
return &types.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) ([]*types.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([]*types.StoryResolver, len(stories)) |
|
||||
for i, story := range stories { |
|
||||
resolvers[i] = &types.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) (*types.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 &types.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) (*types.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 &types.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) (*types.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 &types.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) (*types.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 &types.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) (*types.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 &types.StoryResolver{S: story}, nil |
|
||||
} |
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue