Gisle Aune
6 years ago
62 changed files with 0 additions and 3180 deletions
-
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
-
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
-
23graphql/resolver/queries/channel.go
-
43graphql/resolver/queries/channels.go
-
23graphql/resolver/queries/chapter.go
-
43graphql/resolver/queries/character.go
-
60graphql/resolver/queries/characters.go
-
23graphql/resolver/queries/file.go
-
45graphql/resolver/queries/files.go
-
23graphql/resolver/queries/log.go
-
49graphql/resolver/queries/logs.go
-
23graphql/resolver/queries/post.go
-
28graphql/resolver/queries/posts.go
-
17graphql/resolver/queries/resolver.go
-
109graphql/resolver/queries/stories.go
-
23graphql/resolver/queries/story.go
-
21graphql/resolver/queries/tags.go
-
13graphql/resolver/resolver.go
-
39graphql/resolver/types/channel.go
-
50graphql/resolver/types/chapter.go
-
45graphql/resolver/types/character.go
-
59graphql/resolver/types/file.go
-
117graphql/resolver/types/log.go
-
45graphql/resolver/types/post.go
-
80graphql/resolver/types/story.go
-
16graphql/resolver/types/tag.go
-
141graphql/schema/root.graphql
-
21graphql/schema/schema.go
-
4graphql/schema/types/change.graphql
-
63graphql/schema/types/channel.graphql
-
59graphql/schema/types/chapter.graphql
-
86graphql/schema/types/character.graphql
-
52graphql/schema/types/file.graphql
-
132graphql/schema/types/log.graphql
-
68graphql/schema/types/post.graphql
-
151graphql/schema/types/story.graphql
-
36graphql/schema/types/tag.graphql
-
8graphql/schema/types/user.graphql
@ -1,59 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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 |
|
||||
|
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.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", token.UserID, channel.Name, map[string]interface{}{ |
|
||||
"logged": channel.Logged, |
|
||||
"hub": channel.Hub, |
|
||||
"location": input.LocationName, |
|
||||
"event": input.EventName, |
|
||||
}) |
|
||||
|
|
||||
return &types.ChannelResolver{C: channel}, nil |
|
||||
} |
|
@ -1,67 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
"time" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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 |
|
||||
|
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.Permitted("member", "chapter.add") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
story, err := story.FindID(input.StoryID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
author := token.UserID |
|
||||
if input.Author != nil { |
|
||||
author = *input.Author |
|
||||
|
|
||||
if token.UserID != author && !token.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", token.UserID, chapter.ID, map[string]interface{}{ |
|
||||
"title": input.Title, |
|
||||
"author": author, |
|
||||
"fictionalDate": fictionalDate, |
|
||||
}) |
|
||||
|
|
||||
return &types.ChapterResolver{C: chapter}, nil |
|
||||
} |
|
@ -1,70 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
"strings" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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 |
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.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 := token.UserID |
|
||||
if input.Author != nil { |
|
||||
author = *input.Author |
|
||||
|
|
||||
if author != token.UserID && !token.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", token.UserID, character.ID, map[string]interface{}{ |
|
||||
"name": character.Name, |
|
||||
"nick": character.Nicks[0], |
|
||||
"author": character.Author, |
|
||||
}) |
|
||||
|
|
||||
log.ScheduleCharacterUpdate() |
|
||||
|
|
||||
return &types.CharacterResolver{C: character}, nil |
|
||||
} |
|
@ -1,48 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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 |
|
||||
|
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.Permitted("member") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
character, err := character.FindID(input.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
if character.Author != token.UserID && !token.Permitted("character.edit") { |
|
||||
return nil, ErrPermissionDenied |
|
||||
} |
|
||||
|
|
||||
err = character.AddNick(input.Nick) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Character", "add.nick", token.UserID, character.ID, map[string]interface{}{ |
|
||||
"nick": input.Nick, |
|
||||
}) |
|
||||
|
|
||||
log.ScheduleCharacterUpdate() |
|
||||
|
|
||||
return &types.CharacterResolver{C: character}, nil |
|
||||
} |
|
@ -1,70 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
"time" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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 |
|
||||
|
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.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", token.UserID, 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 |
|
||||
} |
|
@ -1,60 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
"time" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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 |
|
||||
|
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.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", token.UserID, 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 |
|
||||
} |
|
@ -1,83 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
"time" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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 |
|
||||
|
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.Permitted("member", "story.add") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
author := token.UserID |
|
||||
if input.Author != nil { |
|
||||
author = *input.Author |
|
||||
|
|
||||
if token.UserID != author && !token.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", token.UserID, story.ID, map[string]interface{}{ |
|
||||
"name": input.Name, |
|
||||
"category": input.Category, |
|
||||
"author": input.Author, |
|
||||
}) |
|
||||
|
|
||||
return &types.StoryResolver{S: story}, nil |
|
||||
} |
|
@ -1,53 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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} |
|
||||
|
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.Permitted("member", "story.edit") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
story, err := story.FindID(input.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
if story.Author != token.UserID && !token.Permitted("story.edit") { |
|
||||
return nil, ErrPermissionDenied |
|
||||
} |
|
||||
|
|
||||
err = story.AddTag(tag) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Story", "add.tag", token.UserID, story.ID, map[string]interface{}{ |
|
||||
"kind": tag.Kind, |
|
||||
"name": tag.Name, |
|
||||
}) |
|
||||
|
|
||||
return &types.StoryResolver{S: story}, nil |
|
||||
} |
|
@ -1,50 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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 |
|
||||
|
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.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", token.UserID, channel.Name, map[string]interface{}{ |
|
||||
"logged": input.Logged, |
|
||||
"hub": input.Hub, |
|
||||
"location": input.LocationName, |
|
||||
"event": input.EventName, |
|
||||
}) |
|
||||
|
|
||||
return &types.ChannelResolver{C: channel}, nil |
|
||||
} |
|
@ -1,63 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
"time" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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 |
|
||||
|
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.Permitted("member", "chapter.edit") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
chapter, err := story.FindChapterID(input.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
if chapter.Author != token.UserID && !token.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", token.UserID, chapter.ID, map[string]interface{}{ |
|
||||
"title": input.Title, |
|
||||
"source": input.Source, |
|
||||
"fictionalDate": fictionalDate, |
|
||||
}) |
|
||||
|
|
||||
return &types.ChapterResolver{C: chapter}, nil |
|
||||
} |
|
@ -1,64 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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 |
|
||||
|
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.Permitted("member") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
character, err := character.FindID(input.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
if character.Author != token.UserID && !token.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", token.UserID, character.ID, map[string]interface{}{ |
|
||||
"name": character.Name, |
|
||||
"shortName": character.ShortName, |
|
||||
"description": character.Description, |
|
||||
}) |
|
||||
|
|
||||
return &types.CharacterResolver{C: character}, nil |
|
||||
} |
|
@ -1,43 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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 |
|
||||
|
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.Permitted("member") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
file, err := file.FindID(input.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
if file.Author != token.UserID && !token.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 |
|
||||
} |
|
@ -1,51 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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 |
|
||||
|
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.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", token.UserID, 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 |
|
||||
} |
|
@ -1,63 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
"time" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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 |
|
||||
|
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.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", token.UserID, 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 |
|
||||
} |
|
@ -1,69 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
"time" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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 |
|
||||
|
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.Permitted("member", "story.edit") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
story, err := story.FindID(input.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
if story.Author != token.UserID && !token.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", token.UserID, 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 |
|
||||
} |
|
@ -1,45 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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 |
|
||||
|
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.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", token.UserID, post.ID, map[string]interface{}{ |
|
||||
"logId": post.LogID, |
|
||||
"targetIndex": input.ToPosition, |
|
||||
}) |
|
||||
|
|
||||
return &types.PostResolver{P: post}, nil |
|
||||
} |
|
@ -1,37 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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) { |
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.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", token.UserID, channel.Name, nil) |
|
||||
|
|
||||
return &types.ChannelResolver{C: channel}, nil |
|
||||
} |
|
@ -1,37 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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) { |
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.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", token.UserID, chapter.ID, nil) |
|
||||
|
|
||||
return &types.ChapterResolver{C: chapter}, nil |
|
||||
} |
|
@ -1,44 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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) { |
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.Permitted("member") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
character, err := character.FindID(args.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
if character.Author != token.UserID && !token.Permitted("character.remove") { |
|
||||
return nil, ErrPermissionDenied |
|
||||
} |
|
||||
|
|
||||
err = character.Remove() |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Character", "remove", token.UserID, character.ID, map[string]interface{}{ |
|
||||
"name": character.Name, |
|
||||
"author": character.Author, |
|
||||
"nicks": character.Nicks, |
|
||||
}) |
|
||||
|
|
||||
return &types.CharacterResolver{C: character}, nil |
|
||||
} |
|
@ -1,48 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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 |
|
||||
|
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.Permitted("member") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
character, err := character.FindID(input.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
if character.Author != token.UserID && !token.Permitted("character.edit") { |
|
||||
return nil, ErrPermissionDenied |
|
||||
} |
|
||||
|
|
||||
err = character.RemoveNick(input.Nick) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Character", "remove.nick", token.UserID, character.ID, map[string]interface{}{ |
|
||||
"nick": input.Nick, |
|
||||
}) |
|
||||
|
|
||||
log.ScheduleCharacterUpdate() |
|
||||
|
|
||||
return &types.CharacterResolver{C: character}, nil |
|
||||
} |
|
@ -1,37 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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) { |
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.Permitted("member") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
file, err := file.FindID(args.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
if file.Author != token.UserID && !token.Permitted("file.remove") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
err = file.Delete() |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
return &types.FileResolver{F: file}, nil |
|
||||
} |
|
@ -1,37 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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) { |
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.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", token.UserID, log.ID, nil) |
|
||||
|
|
||||
return &types.LogResolver{L: log}, nil |
|
||||
} |
|
@ -1,36 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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) { |
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.Permitted("post.remove") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
post, err := log.RemovePost(args.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Post", "remove", token.UserID, post.ID, map[string]interface{}{ |
|
||||
"logId": post.LogID, |
|
||||
}) |
|
||||
|
|
||||
go log.UpdateCharacters(post.LogID) |
|
||||
|
|
||||
return &types.PostResolver{P: post}, nil |
|
||||
} |
|
@ -1,41 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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) { |
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.Permitted("member", "story.edit") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
story, err := story.FindID(args.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
if story.Author != token.UserID && !token.Permitted("story.remove") { |
|
||||
return nil, ErrPermissionDenied |
|
||||
} |
|
||||
|
|
||||
err = story.Remove() |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Story", "remove", token.UserID, story.ID, nil) |
|
||||
|
|
||||
return &types.StoryResolver{S: story}, nil |
|
||||
} |
|
@ -1,53 +0,0 @@ |
|||||
package mutations |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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} |
|
||||
|
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
if !token.Permitted("member", "story.edit") { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
story, err := story.FindID(input.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
if story.Author != token.UserID && !token.Permitted("story.edit") { |
|
||||
return nil, ErrPermissionDenied |
|
||||
} |
|
||||
|
|
||||
err = story.RemoveTag(tag) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
go change.Submit("Story", "remove.tag", token.UserID, story.ID, map[string]interface{}{ |
|
||||
"kind": tag.Kind, |
|
||||
"name": tag.Name, |
|
||||
}) |
|
||||
|
|
||||
return &types.StoryResolver{S: story}, nil |
|
||||
} |
|
@ -1,14 +0,0 @@ |
|||||
// 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,23 +0,0 @@ |
|||||
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 |
|
||||
} |
|
@ -1,43 +0,0 @@ |
|||||
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 { |
|
||||
Filter *struct { |
|
||||
Logged *bool |
|
||||
EventName *string |
|
||||
LocationName *string |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// Channels resolves the channels query
|
|
||||
func (r *QueryResolver) Channels(ctx context.Context, args *ChannelsArgs) ([]*types.ChannelResolver, error) { |
|
||||
var channels []channel.Channel |
|
||||
var err error |
|
||||
|
|
||||
filter := args.Filter |
|
||||
if filter != nil { |
|
||||
channels, err = channel.List(filter.Logged, filter.EventName, filter.LocationName) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
} else { |
|
||||
channels, err = channel.List(nil, nil, nil) |
|
||||
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 |
|
||||
} |
|
@ -1,23 +0,0 @@ |
|||||
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 |
|
||||
} |
|
@ -1,43 +0,0 @@ |
|||||
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 |
|
||||
} |
|
@ -1,60 +0,0 @@ |
|||||
package queries |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/model/character" |
|
||||
) |
|
||||
|
|
||||
// CharactersArgs is args for characters query
|
|
||||
type CharactersArgs struct { |
|
||||
Filter *struct { |
|
||||
IDs *[]string |
|
||||
Nicks *[]string |
|
||||
Names *[]string |
|
||||
Author *string |
|
||||
Search *string |
|
||||
Logged *bool |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// Characters resolves the characters query
|
|
||||
func (r *QueryResolver) Characters(ctx context.Context, args *CharactersArgs) ([]*types.CharacterResolver, error) { |
|
||||
var characters []character.Character |
|
||||
var err error |
|
||||
|
|
||||
filter := args.Filter |
|
||||
if filter != nil { |
|
||||
var ids []string |
|
||||
var nicks []string |
|
||||
var names []string |
|
||||
|
|
||||
if filter.IDs != nil { |
|
||||
ids = *filter.IDs |
|
||||
} |
|
||||
if filter.Nicks != nil { |
|
||||
nicks = *filter.Nicks |
|
||||
} |
|
||||
if filter.Names != nil { |
|
||||
names = *filter.Names |
|
||||
} |
|
||||
|
|
||||
characters, err = character.ListFilter(ids, nicks, names, filter.Author, filter.Search, filter.Logged) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
} else { |
|
||||
characters, err = character.List() |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
resolvers := make([]*types.CharacterResolver, 0, len(characters)) |
|
||||
for _, character := range characters { |
|
||||
resolvers = append(resolvers, &types.CharacterResolver{C: character}) |
|
||||
} |
|
||||
|
|
||||
return resolvers, nil |
|
||||
} |
|
@ -1,23 +0,0 @@ |
|||||
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 |
|
||||
} |
|
@ -1,45 +0,0 @@ |
|||||
package queries |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"git.aiterp.net/rpdata/api/model/file" |
|
||||
) |
|
||||
|
|
||||
// FilesArgs is args for files query
|
|
||||
type FilesArgs struct { |
|
||||
Filter *struct { |
|
||||
Public *bool |
|
||||
MimeTypes *[]string |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// Files resolves the file query
|
|
||||
func (r *QueryResolver) Files(ctx context.Context, args *FilesArgs) ([]*types.FileResolver, error) { |
|
||||
filter := args.Filter |
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
|
|
||||
author := "" |
|
||||
if token != nil { |
|
||||
author = token.UserID |
|
||||
} |
|
||||
|
|
||||
mimeTypes := []string(nil) |
|
||||
if filter.MimeTypes != nil { |
|
||||
mimeTypes = *filter.MimeTypes |
|
||||
} |
|
||||
|
|
||||
files, err := file.List(author, filter.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 |
|
||||
} |
|
@ -1,23 +0,0 @@ |
|||||
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) { |
|
||||
log, err := log.FindID(args.ID) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
return &types.LogResolver{L: log}, nil |
|
||||
} |
|
@ -1,49 +0,0 @@ |
|||||
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/log" |
|
||||
) |
|
||||
|
|
||||
// LogsArgs is args for the logs query
|
|
||||
type LogsArgs struct { |
|
||||
Filter *log.Filter |
|
||||
} |
|
||||
|
|
||||
// Logs resolves the logs query
|
|
||||
func (r *QueryResolver) Logs(ctx context.Context, args *LogsArgs) ([]*types.LogResolver, error) { |
|
||||
var logs []log.Log |
|
||||
|
|
||||
filter := args.Filter |
|
||||
if filter == nil { |
|
||||
filter = log.NewFilter().WithLimit(100) |
|
||||
} |
|
||||
|
|
||||
logs, err := log.List(filter) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
if len(logs) >= 100 { |
|
||||
loader := loader.FromContext(ctx) |
|
||||
if loader == nil { |
|
||||
return nil, errors.New("no loader") |
|
||||
} |
|
||||
|
|
||||
for _, log := range logs { |
|
||||
loader.PrimeCharacters("id", log.CharacterIDs...) |
|
||||
loader.PrimeChannels("name", log.Channel) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
resolvers := make([]*types.LogResolver, len(logs)) |
|
||||
for i := range logs { |
|
||||
resolvers[i] = &types.LogResolver{L: logs[i]} |
|
||||
} |
|
||||
|
|
||||
return resolvers, nil |
|
||||
} |
|
@ -1,23 +0,0 @@ |
|||||
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 |
|
||||
} |
|
@ -1,28 +0,0 @@ |
|||||
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 |
|
||||
} |
|
@ -1,17 +0,0 @@ |
|||||
// 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") |
|
||||
|
|
||||
// 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,109 +0,0 @@ |
|||||
package queries |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
"time" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/internal/auth" |
|
||||
"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 |
|
||||
Category *string |
|
||||
Limit *int32 |
|
||||
Open *bool |
|
||||
Unlisted *bool |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// Stories resolves the stories query
|
|
||||
func (r *QueryResolver) Stories(ctx context.Context, args *StoriesArg) ([]*types.StoryResolver, error) { |
|
||||
var err error |
|
||||
|
|
||||
token := auth.TokenFromContext(ctx) |
|
||||
|
|
||||
filter := args.Filter |
|
||||
|
|
||||
author := "" |
|
||||
category := "" |
|
||||
tags := make([]story.Tag, 0, 8) |
|
||||
earliest := time.Time{} |
|
||||
latest := time.Time{} |
|
||||
unlisted := false |
|
||||
open := (*bool)(nil) |
|
||||
limit := 0 |
|
||||
|
|
||||
if filter != nil { |
|
||||
if filter.Author != nil { |
|
||||
author = *filter.Author |
|
||||
} |
|
||||
|
|
||||
if filter.Category != nil { |
|
||||
category = *filter.Category |
|
||||
} |
|
||||
|
|
||||
if filter.Tags != nil { |
|
||||
for _, tagInput := range *filter.Tags { |
|
||||
tags = append(tags, story.Tag{ |
|
||||
Kind: tagInput.Kind, |
|
||||
Name: tagInput.Name, |
|
||||
}) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if filter.EarliestFictionalDate != nil { |
|
||||
earliest, err = time.Parse(time.RFC3339Nano, *filter.EarliestFictionalDate) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if filter.LatestFictionalDate != nil { |
|
||||
latest, err = time.Parse(time.RFC3339Nano, *filter.LatestFictionalDate) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if filter.Limit != nil { |
|
||||
limit = int(*filter.Limit) |
|
||||
} |
|
||||
|
|
||||
unlisted = filter.Unlisted != nil && *filter.Unlisted == true |
|
||||
if unlisted { |
|
||||
if token == nil { |
|
||||
return nil, ErrUnauthorized |
|
||||
} |
|
||||
|
|
||||
if author != "" && author != token.UserID && !token.Permitted("story.unlisted") { |
|
||||
return nil, ErrPermissionDenied |
|
||||
} |
|
||||
|
|
||||
author = token.UserID |
|
||||
} |
|
||||
|
|
||||
open = filter.Open |
|
||||
} |
|
||||
|
|
||||
stories, err := story.List(author, category, tags, earliest, latest, unlisted, open, 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 |
|
||||
} |
|
@ -1,23 +0,0 @@ |
|||||
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,21 +0,0 @@ |
|||||
package queries |
|
||||
|
|
||||
import ( |
|
||||
"git.aiterp.net/rpdata/api/graphql/resolver/types" |
|
||||
"git.aiterp.net/rpdata/api/model/story" |
|
||||
) |
|
||||
|
|
||||
// Tags resolves the tags query
|
|
||||
func (r *QueryResolver) Tags() ([]*types.TagResolver, error) { |
|
||||
tags, err := story.ListTags() |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
resolvers := make([]*types.TagResolver, len(tags)) |
|
||||
for i, tag := range tags { |
|
||||
resolvers[i] = &types.TagResolver{T: tag} |
|
||||
} |
|
||||
|
|
||||
return resolvers, nil |
|
||||
} |
|
@ -1,13 +0,0 @@ |
|||||
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,39 +0,0 @@ |
|||||
package types |
|
||||
|
|
||||
import "git.aiterp.net/rpdata/api/model/channel" |
|
||||
|
|
||||
// ChannelResolver for the Channel graphql type
|
|
||||
type ChannelResolver struct{ C channel.Channel } |
|
||||
|
|
||||
// Name resolves channel.name
|
|
||||
func (r *ChannelResolver) Name() string { |
|
||||
return r.C.Name |
|
||||
} |
|
||||
|
|
||||
// Logged resolves channel.logged
|
|
||||
func (r *ChannelResolver) Logged() bool { |
|
||||
return r.C.Logged |
|
||||
} |
|
||||
|
|
||||
// Hub resolves channel.hub
|
|
||||
func (r *ChannelResolver) Hub() bool { |
|
||||
return r.C.Hub |
|
||||
} |
|
||||
|
|
||||
// EventName resolves channel.eventName
|
|
||||
func (r *ChannelResolver) EventName() *string { |
|
||||
if r.C.Event == "" { |
|
||||
return nil |
|
||||
} |
|
||||
|
|
||||
return &r.C.Event |
|
||||
} |
|
||||
|
|
||||
// LocationName resolves channel.locationName
|
|
||||
func (r *ChannelResolver) LocationName() *string { |
|
||||
if r.C.Location == "" { |
|
||||
return nil |
|
||||
} |
|
||||
|
|
||||
return &r.C.Location |
|
||||
} |
|
@ -1,50 +0,0 @@ |
|||||
package types |
|
||||
|
|
||||
import ( |
|
||||
"time" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/model/story" |
|
||||
) |
|
||||
|
|
||||
// ChapterResolver for the Chapter graphql type
|
|
||||
type ChapterResolver struct{ C story.Chapter } |
|
||||
|
|
||||
// ID resolves Chapter.id
|
|
||||
func (r *ChapterResolver) ID() string { |
|
||||
return r.C.ID |
|
||||
} |
|
||||
|
|
||||
// StoryID resolves Chapter.storyId
|
|
||||
func (r *ChapterResolver) StoryID() string { |
|
||||
return r.C.StoryID |
|
||||
} |
|
||||
|
|
||||
// Title resolves Chapter.title
|
|
||||
func (r *ChapterResolver) Title() string { |
|
||||
return r.C.Title |
|
||||
} |
|
||||
|
|
||||
// Author resolves Chapter.author
|
|
||||
func (r *ChapterResolver) Author() string { |
|
||||
return r.C.Author |
|
||||
} |
|
||||
|
|
||||
// Source resolves Chapter.source
|
|
||||
func (r *ChapterResolver) Source() string { |
|
||||
return r.C.Source |
|
||||
} |
|
||||
|
|
||||
// CreatedDate resolves Chapter.createdDate
|
|
||||
func (r *ChapterResolver) CreatedDate() string { |
|
||||
return r.C.CreatedDate.Format(time.RFC3339Nano) |
|
||||
} |
|
||||
|
|
||||
// FictionalDate resolves Chapter.fictionalDate
|
|
||||
func (r *ChapterResolver) FictionalDate() string { |
|
||||
return r.C.FictionalDate.Format(time.RFC3339Nano) |
|
||||
} |
|
||||
|
|
||||
// EditedDate resolves Chapter.editedDate
|
|
||||
func (r *ChapterResolver) EditedDate() string { |
|
||||
return r.C.EditedDate.Format(time.RFC3339Nano) |
|
||||
} |
|
@ -1,45 +0,0 @@ |
|||||
package types |
|
||||
|
|
||||
import "git.aiterp.net/rpdata/api/model/character" |
|
||||
|
|
||||
// CharacterResolver for the Character graphql type
|
|
||||
type CharacterResolver struct{ C character.Character } |
|
||||
|
|
||||
// ID is a property resolver
|
|
||||
func (r *CharacterResolver) ID() string { |
|
||||
return r.C.ID |
|
||||
} |
|
||||
|
|
||||
// Nick is a property resolver
|
|
||||
func (r *CharacterResolver) Nick() *string { |
|
||||
if len(r.C.Nicks) == 0 { |
|
||||
return nil |
|
||||
} |
|
||||
|
|
||||
return &r.C.Nicks[0] |
|
||||
} |
|
||||
|
|
||||
// Nicks is a property resolver
|
|
||||
func (r *CharacterResolver) Nicks() []string { |
|
||||
return r.C.Nicks |
|
||||
} |
|
||||
|
|
||||
// Name is a property resolver
|
|
||||
func (r *CharacterResolver) Name() string { |
|
||||
return r.C.Name |
|
||||
} |
|
||||
|
|
||||
// ShortName is a property resolver
|
|
||||
func (r *CharacterResolver) ShortName() string { |
|
||||
return r.C.ShortName |
|
||||
} |
|
||||
|
|
||||
// Author is a property resolver
|
|
||||
func (r *CharacterResolver) Author() string { |
|
||||
return r.C.Author |
|
||||
} |
|
||||
|
|
||||
// Description is a property resolver
|
|
||||
func (r *CharacterResolver) Description() string { |
|
||||
return r.C.Description |
|
||||
} |
|
@ -1,59 +0,0 @@ |
|||||
package types |
|
||||
|
|
||||
import ( |
|
||||
"time" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/model/file" |
|
||||
) |
|
||||
|
|
||||
// FileResolver for the File graphql type
|
|
||||
type FileResolver struct{ F file.File } |
|
||||
|
|
||||
// ID resolves File.id
|
|
||||
func (f *FileResolver) ID() string { |
|
||||
return f.F.ID |
|
||||
} |
|
||||
|
|
||||
// Author resolves File.author
|
|
||||
func (f *FileResolver) Author() string { |
|
||||
return f.F.Author |
|
||||
} |
|
||||
|
|
||||
// Kind resolves File.kind
|
|
||||
func (f *FileResolver) Kind() string { |
|
||||
return f.F.Kind |
|
||||
} |
|
||||
|
|
||||
// Time resolves File.time
|
|
||||
func (f *FileResolver) Time() string { |
|
||||
return f.F.Time.Format(time.RFC3339Nano) |
|
||||
} |
|
||||
|
|
||||
// Public resolves File.public
|
|
||||
func (f *FileResolver) Public() bool { |
|
||||
return f.F.Public |
|
||||
} |
|
||||
|
|
||||
// Name resolves File.name
|
|
||||
func (f *FileResolver) Name() string { |
|
||||
return f.F.Name |
|
||||
} |
|
||||
|
|
||||
// MimeType resolves File.mimeType
|
|
||||
func (f *FileResolver) MimeType() string { |
|
||||
return f.F.MimeType |
|
||||
} |
|
||||
|
|
||||
// Size resolves File.size
|
|
||||
func (f *FileResolver) Size() int32 { |
|
||||
return int32(f.F.Size) |
|
||||
} |
|
||||
|
|
||||
// URL resolves File.url
|
|
||||
func (f *FileResolver) URL() *string { |
|
||||
if f.F.URL == "" { |
|
||||
return nil |
|
||||
} |
|
||||
|
|
||||
return &f.F.URL |
|
||||
} |
|
@ -1,117 +0,0 @@ |
|||||
package types |
|
||||
|
|
||||
import ( |
|
||||
"context" |
|
||||
"errors" |
|
||||
"time" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/graphql/loader" |
|
||||
"git.aiterp.net/rpdata/api/model/log" |
|
||||
) |
|
||||
|
|
||||
// LogResolver for the Log graphql type
|
|
||||
type LogResolver struct{ L log.Log } |
|
||||
|
|
||||
// ID resolves Log.id
|
|
||||
func (r *LogResolver) ID() string { |
|
||||
return r.L.ID |
|
||||
} |
|
||||
|
|
||||
// ShortID resolves Log.shortId
|
|
||||
func (r *LogResolver) ShortID() string { |
|
||||
return r.L.ShortID |
|
||||
} |
|
||||
|
|
||||
// Date resolves Log.date
|
|
||||
func (r *LogResolver) Date() string { |
|
||||
return r.L.Date.Format(time.RFC3339Nano) |
|
||||
} |
|
||||
|
|
||||
// ChannelName resolves Log.channelName
|
|
||||
func (r *LogResolver) ChannelName() string { |
|
||||
return r.L.Channel |
|
||||
} |
|
||||
|
|
||||
// Channel resolves Log.channe
|
|
||||
func (r *LogResolver) Channel(ctx context.Context) (*ChannelResolver, error) { |
|
||||
loader := loader.FromContext(ctx) |
|
||||
if loader == nil { |
|
||||
return nil, errors.New("no loader") |
|
||||
} |
|
||||
|
|
||||
channel, err := loader.Channel("name", r.L.Channel) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
return &ChannelResolver{C: channel}, nil |
|
||||
} |
|
||||
|
|
||||
// Title resolves Log.title
|
|
||||
func (r *LogResolver) Title() string { |
|
||||
return r.L.Title |
|
||||
} |
|
||||
|
|
||||
// Event resolves Log.event
|
|
||||
func (r *LogResolver) Event() string { |
|
||||
return r.L.Event |
|
||||
} |
|
||||
|
|
||||
// Description resolves Log.description
|
|
||||
func (r *LogResolver) Description() string { |
|
||||
return r.L.Description |
|
||||
} |
|
||||
|
|
||||
// Open resolves Log.open
|
|
||||
func (r *LogResolver) Open() bool { |
|
||||
return r.L.Open |
|
||||
} |
|
||||
|
|
||||
// Characters resolves Log.characters
|
|
||||
func (r *LogResolver) Characters(ctx context.Context) ([]*CharacterResolver, error) { |
|
||||
loader := loader.FromContext(ctx) |
|
||||
if loader == nil { |
|
||||
return nil, errors.New("no loader") |
|
||||
} |
|
||||
|
|
||||
chars, err := loader.Characters("id", r.L.CharacterIDs...) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
resolvers := make([]*CharacterResolver, 0, len(chars)) |
|
||||
for i := range chars { |
|
||||
if chars[i].ID == "" { |
|
||||
continue |
|
||||
} |
|
||||
|
|
||||
resolvers = append(resolvers, &CharacterResolver{C: chars[i]}) |
|
||||
} |
|
||||
|
|
||||
return resolvers, nil |
|
||||
} |
|
||||
|
|
||||
// Posts resolves Log.posts
|
|
||||
func (r *LogResolver) Posts(ctx context.Context, args *LogPostArgs) ([]*PostResolver, error) { |
|
||||
var kinds []string |
|
||||
if args.Kinds != nil { |
|
||||
kinds = *args.Kinds |
|
||||
} |
|
||||
|
|
||||
posts, err := r.L.Posts(kinds...) |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
resolvers := make([]*PostResolver, len(posts)) |
|
||||
for i := range posts { |
|
||||
resolvers[i] = &PostResolver{posts[i]} |
|
||||
} |
|
||||
|
|
||||
return resolvers, nil |
|
||||
} |
|
||||
|
|
||||
// LogPostArgs is an arg
|
|
||||
type LogPostArgs struct { |
|
||||
Kinds *[]string |
|
||||
} |
|
@ -1,45 +0,0 @@ |
|||||
package types |
|
||||
|
|
||||
import ( |
|
||||
"time" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/model/log" |
|
||||
) |
|
||||
|
|
||||
// PostResolver for the Post graphql type
|
|
||||
type PostResolver struct{ P log.Post } |
|
||||
|
|
||||
// ID resolves Post.id
|
|
||||
func (r *PostResolver) ID() string { |
|
||||
return r.P.ID |
|
||||
} |
|
||||
|
|
||||
// LogID resolves Post.logId
|
|
||||
func (r *PostResolver) LogID() string { |
|
||||
return r.P.LogID |
|
||||
} |
|
||||
|
|
||||
// Time resolves Post.time
|
|
||||
func (r *PostResolver) Time() string { |
|
||||
return r.P.Time.Format(time.RFC3339Nano) |
|
||||
} |
|
||||
|
|
||||
// Kind resolves Post.logId
|
|
||||
func (r *PostResolver) Kind() string { |
|
||||
return r.P.Kind |
|
||||
} |
|
||||
|
|
||||
// Nick resolves Post.nick
|
|
||||
func (r *PostResolver) Nick() string { |
|
||||
return r.P.Nick |
|
||||
} |
|
||||
|
|
||||
// Text resolves Post.text
|
|
||||
func (r *PostResolver) Text() string { |
|
||||
return r.P.Text |
|
||||
} |
|
||||
|
|
||||
// Position resolves Post.text
|
|
||||
func (r *PostResolver) Position() int32 { |
|
||||
return int32(r.P.Position) |
|
||||
} |
|
@ -1,80 +0,0 @@ |
|||||
package types |
|
||||
|
|
||||
import ( |
|
||||
"time" |
|
||||
|
|
||||
"git.aiterp.net/rpdata/api/model/story" |
|
||||
) |
|
||||
|
|
||||
// StoryResolver for the Story graphql type
|
|
||||
type StoryResolver struct{ S story.Story } |
|
||||
|
|
||||
// ID resolves Story.id
|
|
||||
func (r *StoryResolver) ID() string { |
|
||||
return r.S.ID |
|
||||
} |
|
||||
|
|
||||
// Author resolves Story.author
|
|
||||
func (r *StoryResolver) Author() string { |
|
||||
return r.S.Author |
|
||||
} |
|
||||
|
|
||||
// Name resolves Story.name
|
|
||||
func (r *StoryResolver) Name() string { |
|
||||
return r.S.Name |
|
||||
} |
|
||||
|
|
||||
// Category resolves Story.category
|
|
||||
func (r *StoryResolver) Category() string { |
|
||||
return r.S.Category |
|
||||
} |
|
||||
|
|
||||
// Open resolves Story.open
|
|
||||
func (r *StoryResolver) Open() bool { |
|
||||
return r.S.Open |
|
||||
} |
|
||||
|
|
||||
// Listed resolves Story.listed
|
|
||||
func (r *StoryResolver) Listed() bool { |
|
||||
return r.S.Listed |
|
||||
} |
|
||||
|
|
||||
// Tags resolves Story.tags
|
|
||||
func (r *StoryResolver) Tags() []*TagResolver { |
|
||||
resolvers := make([]*TagResolver, len(r.S.Tags)) |
|
||||
for i, tag := range r.S.Tags { |
|
||||
resolvers[i] = &TagResolver{T: tag} |
|
||||
} |
|
||||
|
|
||||
return resolvers |
|
||||
} |
|
||||
|
|
||||
// Chapters resolves Story.chapters
|
|
||||
func (r *StoryResolver) Chapters() ([]*ChapterResolver, error) { |
|
||||
chapters, err := r.S.Chapters() |
|
||||
if err != nil { |
|
||||
return nil, err |
|
||||
} |
|
||||
|
|
||||
resolvers := make([]*ChapterResolver, len(chapters)) |
|
||||
for i, chapter := range chapters { |
|
||||
resolvers[i] = &ChapterResolver{C: chapter} |
|
||||
} |
|
||||
|
|
||||
return resolvers, nil |
|
||||
} |
|
||||
|
|
||||
// CreatedDate resolves Story.createdDate
|
|
||||
func (r *StoryResolver) CreatedDate() string { |
|
||||
return r.S.CreatedDate.Format(time.RFC3339Nano) |
|
||||
} |
|
||||
|
|
||||
// FictionalDate resolves Story.fictionalDate
|
|
||||
func (r *StoryResolver) FictionalDate() string { |
|
||||
return r.S.FictionalDate.Format(time.RFC3339Nano) |
|
||||
} |
|
||||
|
|
||||
// UpdatedDate resolves Story.updatedDate
|
|
||||
func (r *StoryResolver) UpdatedDate() string { |
|
||||
return r.S.UpdatedDate.Format(time.RFC3339Nano) |
|
||||
} |
|
@ -1,16 +0,0 @@ |
|||||
package types |
|
||||
|
|
||||
import "git.aiterp.net/rpdata/api/model/story" |
|
||||
|
|
||||
// TagResolver for the Tag graphql type
|
|
||||
type TagResolver struct{ T story.Tag } |
|
||||
|
|
||||
// Kind resolves Tag.kind
|
|
||||
func (r *TagResolver) Kind() string { |
|
||||
return r.T.Kind |
|
||||
} |
|
||||
|
|
||||
// Name resolves Tag.name
|
|
||||
func (r *TagResolver) Name() string { |
|
||||
return r.T.Name |
|
||||
} |
|
@ -1,141 +0,0 @@ |
|||||
# The Query type represents the read entry points into the API. |
|
||||
type Query { |
|
||||
# Find character by either an ID or a nick. |
|
||||
character(id: String, nick: String): Character |
|
||||
|
|
||||
# Find characters |
|
||||
characters(filter: CharactersFilter): [Character!]! |
|
||||
|
|
||||
|
|
||||
# Find channel by name |
|
||||
channel(name: String!): Channel |
|
||||
|
|
||||
# Find channels |
|
||||
channels(filter: ChannelsFilter): [Channel!]! |
|
||||
|
|
||||
|
|
||||
# Find log by ID |
|
||||
log(id: String!): Log |
|
||||
|
|
||||
# Find logs |
|
||||
logs(filter: LogsFilter): [LogHeader!]! |
|
||||
|
|
||||
|
|
||||
# Find post by ID. |
|
||||
post(id: String!): Post |
|
||||
|
|
||||
# Find posts by IDs. It's meant to allow other parts of the UI to link to a cluster of posts, e.g. for a room description for the |
|
||||
# Mapp should it ever become a thing. This does not have a filter, since it's meant to be queried in the logs' response's selection set. |
|
||||
posts(ids: [String!]!): [Post!]! |
|
||||
|
|
||||
|
|
||||
# Find file by ID |
|
||||
file(id: String!): File |
|
||||
|
|
||||
# Find files |
|
||||
files(filter: FilesFilter): [File!]! |
|
||||
|
|
||||
|
|
||||
# Find story by ID |
|
||||
story(id: String!): Story |
|
||||
|
|
||||
# Find stories |
|
||||
stories(filter: StoriesFilter): [Story!]! |
|
||||
|
|
||||
|
|
||||
# Find story chapter by ID |
|
||||
chapter(id: String!): Chapter |
|
||||
|
|
||||
|
|
||||
# Find all distinct tags used in stories |
|
||||
tags: [Tag!]! |
|
||||
} |
|
||||
|
|
||||
# The Mutation type represents write entry points into the API. |
|
||||
type Mutation { |
|
||||
# Add a new character |
|
||||
addCharacter(input: CharacterAddInput!): Character! |
|
||||
|
|
||||
# Add nick to character |
|
||||
addCharacterNick(input: CharacterNickInput!): Character! |
|
||||
|
|
||||
# Remove nick from character |
|
||||
removeCharacterNick(input: CharacterNickInput!): Character! |
|
||||
|
|
||||
# Edit character |
|
||||
editCharacter(input: CharacterEditInput!): Character! |
|
||||
|
|
||||
# Remove a character |
|
||||
removeCharacter(id: String!): Character! |
|
||||
|
|
||||
|
|
||||
# Add a channel |
|
||||
addChannel(input: ChannelAddInput!): Channel! |
|
||||
|
|
||||
# Edit a channel |
|
||||
editChannel(input: ChannelEditInput!): Channel! |
|
||||
|
|
||||
# Remove a channel |
|
||||
removeChannel(name: String!): Channel! |
|
||||
|
|
||||
|
|
||||
# Add a new log |
|
||||
addLog(input: LogAddInput!): Log! |
|
||||
|
|
||||
# Edit a log |
|
||||
editLog(input: LogEditInput!): Log! |
|
||||
|
|
||||
# Remove a log |
|
||||
removeLog(id: String!): Log! |
|
||||
|
|
||||
|
|
||||
# Add a post |
|
||||
addPost(input: AddPostInput!): Post! |
|
||||
|
|
||||
# Edit a post |
|
||||
editPost(input: EditPostInput!): Post! |
|
||||
|
|
||||
# Move a post |
|
||||
movePost(input: MovePostInput!): Post! |
|
||||
|
|
||||
# Remove a post |
|
||||
removePost(id: String!): Post! |
|
||||
|
|
||||
|
|
||||
# Edit a file |
|
||||
editFile(input: EditFileInput!): File! |
|
||||
|
|
||||
# Remove a file |
|
||||
removeFile(id: String!): File! |
|
||||
|
|
||||
|
|
||||
# Add a story |
|
||||
addStory(input: StoryAddInput!): Story! |
|
||||
|
|
||||
# Add a story tag |
|
||||
addStoryTag(input: StoryTagAddInput!): Story! |
|
||||
|
|
||||
# Remove a story tag |
|
||||
removeStoryTag(input: StoryTagRemoveInput!): Story! |
|
||||
|
|
||||
# Edit a story |
|
||||
editStory(input: StoryEditInput!): Story! |
|
||||
|
|
||||
# Remove a story |
|
||||
removeStory(id: String!): Story! |
|
||||
|
|
||||
|
|
||||
# Add a chapter to a story |
|
||||
addChapter(input: ChapterAddInput!): Chapter! |
|
||||
|
|
||||
# Edit a chapter |
|
||||
editChapter(input: ChapterEditInput!): Chapter! |
|
||||
|
|
||||
# Remove a chapter |
|
||||
removeChapter(id: String!): Chapter! |
|
||||
} |
|
||||
|
|
||||
schema { |
|
||||
query: Query |
|
||||
mutation: Mutation |
|
||||
} |
|
@ -1,21 +0,0 @@ |
|||||
package schema |
|
||||
|
|
||||
//go:generate go-bindata -ignore=\.go -pkg=schema -o=bindata.go ./...
|
|
||||
|
|
||||
import "bytes" |
|
||||
|
|
||||
// String gets the schema
|
|
||||
func String() string { |
|
||||
buf := bytes.Buffer{} |
|
||||
for _, name := range AssetNames() { |
|
||||
b := MustAsset(name) |
|
||||
buf.Write(b) |
|
||||
|
|
||||
// Add a newline if the file does not end in a newline.
|
|
||||
if len(b) > 0 && b[len(b)-1] != '\n' { |
|
||||
buf.WriteByte('\n') |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return buf.String() |
|
||||
} |
|
@ -1,4 +0,0 @@ |
|||||
# A Change is a part of the history that can be used to keep clients up to date. |
|
||||
type Change { |
|
||||
id: Int! |
|
||||
} |
|
@ -1,63 +0,0 @@ |
|||||
# Information about an IRC channel |
|
||||
type Channel { |
|
||||
# The channel's name |
|
||||
name: String! |
|
||||
|
|
||||
# Whether the channel should be logged |
|
||||
logged: Boolean! |
|
||||
|
|
||||
# Whether the channel is a hub channel |
|
||||
hub: Boolean! |
|
||||
|
|
||||
# The event name, or `null` if none is specified |
|
||||
eventName: String |
|
||||
|
|
||||
# The location name, or `null` if none is specified |
|
||||
locationName: String |
|
||||
} |
|
||||
|
|
||||
# Filters for the channels query |
|
||||
input ChannelsFilter { |
|
||||
# Filter to either logged or unlogged channels |
|
||||
logged: Boolean |
|
||||
|
|
||||
# Filter by event name |
|
||||
eventName: String |
|
||||
|
|
||||
# Filter by location name |
|
||||
locationName: String |
|
||||
} |
|
||||
|
|
||||
input ChannelAddInput { |
|
||||
# The channel's name |
|
||||
name: String! |
|
||||
|
|
||||
# Whether the channel should be logged |
|
||||
logged: Boolean |
|
||||
|
|
||||
# Whether the channel is a hub channel |
|
||||
hub: Boolean |
|
||||
|
|
||||
# The event name, or `null` if none is specified |
|
||||
eventName: String |
|
||||
|
|
||||
# The location name, or `null` if none is specified |
|
||||
locationName: String |
|
||||
} |
|
||||
|
|
||||
input ChannelEditInput { |
|
||||
# The channel's name |
|
||||
name: String! |
|
||||
|
|
||||
# Whether the channel should be logged |
|
||||
logged: Boolean |
|
||||
|
|
||||
# Whether the channel is a hub channel |
|
||||
hub: Boolean |
|
||||
|
|
||||
# The event name, or `null` if none is specified |
|
||||
eventName: String |
|
||||
|
|
||||
# The location name, or `null` if none is specified |
|
||||
locationName: String |
|
||||
} |
|
@ -1,59 +0,0 @@ |
|||||
# A Chapter is the main content body of a story. |
|
||||
type Chapter { |
|
||||
# The chapter's ID |
|
||||
id: String! |
|
||||
|
|
||||
# The chapter's title |
|
||||
title: String! |
|
||||
|
|
||||
# The chapter's author |
|
||||
author: String! |
|
||||
|
|
||||
# The chapter's source |
|
||||
source: String! |
|
||||
|
|
||||
# When the chapter was posted initialy |
|
||||
createdDate: String! |
|
||||
|
|
||||
# The in-universe date and time of the chapter |
|
||||
fictionalDate: String! |
|
||||
|
|
||||
# The date of edit. |
|
||||
editedDate: String! |
|
||||
} |
|
||||
|
|
||||
# Input for addChapter mutation |
|
||||
input ChapterAddInput { |
|
||||
# The story to add a chapter to |
|
||||
storyId: String! |
|
||||
|
|
||||
# The title to give the chapter. It can not be left empty |
|
||||
title: String! |
|
||||
|
|
||||
# The author to set for the chapter. It will use the logged in user ID, and only |
|
||||
# users with appropriate permissions can post as another author. Even then, it's only |
|
||||
# for importing/moving content. This author name will not be used when logging the |
|
||||
# submission |
|
||||
author: String |
|
||||
|
|
||||
# The markdown source for the content |
|
||||
source: String! |
|
||||
|
|
||||
# Optionally, assign a fictional date for the chapter |
|
||||
fictionalDate: String |
|
||||
} |
|
||||
|
|
||||
# Input for editChapter mutation |
|
||||
input ChapterEditInput { |
|
||||
# The chapter to edit |
|
||||
id: String! |
|
||||
|
|
||||
# Change the chapter's title |
|
||||
title: String |
|
||||
|
|
||||
# Change the source |
|
||||
source: String |
|
||||
|
|
||||
# Set the fictional date for a chapter |
|
||||
fictionalDate: String |
|
||||
} |
|
@ -1,86 +0,0 @@ |
|||||
# A Character represents an RP character |
|
||||
type Character { |
|
||||
# A unique identifier for the character |
|
||||
id: String! |
|
||||
|
|
||||
# The primary IRC nick belonging to the character |
|
||||
nick: String |
|
||||
|
|
||||
# All IRC nicks associated with this character |
|
||||
nicks: [String!]! |
|
||||
|
|
||||
# The character's author |
|
||||
author: String! |
|
||||
|
|
||||
# The character's name |
|
||||
name: String! |
|
||||
|
|
||||
# The name to display when space is scarce, usually the first/given name |
|
||||
shortName: String! |
|
||||
|
|
||||
# A short description of the character |
|
||||
description: String! |
|
||||
} |
|
||||
|
|
||||
# Filter for characters query |
|
||||
input CharactersFilter { |
|
||||
# Filter by character IDs |
|
||||
ids: [String!] |
|
||||
|
|
||||
# Filter by nicks |
|
||||
nicks: [String!] |
|
||||
|
|
||||
# Filter by names |
|
||||
names: [String!] |
|
||||
|
|
||||
# Filter by author |
|
||||
author: String |
|
||||
|
|
||||
# Filter by text search matching against the character's description |
|
||||
search: String |
|
||||
|
|
||||
# Filter by whether they've been part of a log. |
|
||||
logged: Boolean |
|
||||
} |
|
||||
|
|
||||
# Input for adding characters |
|
||||
input CharacterAddInput { |
|
||||
# The primary IRC nick name to recognize this character by |
|
||||
nick: String! |
|
||||
|
|
||||
# The character's name |
|
||||
name: String! |
|
||||
|
|
||||
# Optioanl shortened name. By default, it uses the first token in the name |
|
||||
shortName: String |
|
||||
|
|
||||
# Description for a character. |
|
||||
description: String |
|
||||
|
|
||||
# Optioanlly, specify another author. This needs special permissions if it's not |
|
||||
# your own username |
|
||||
author: String |
|
||||
} |
|
||||
|
|
||||
# Input for addNick and removeNick mutation |
|
||||
input CharacterNickInput { |
|
||||
# The ID of the character |
|
||||
id: String! |
|
||||
|
|
||||
# The nick to add or remove |
|
||||
nick: String! |
|
||||
} |
|
||||
|
|
||||
input CharacterEditInput { |
|
||||
# The id for the character to edit |
|
||||
id: String! |
|
||||
|
|
||||
# The full name of the character -- not the salarian full name! |
|
||||
name: String |
|
||||
|
|
||||
# The character's short name that is used in compact lists |
|
||||
shortName: String |
|
||||
|
|
||||
# A short description for the character |
|
||||
description: String |
|
||||
} |
|
@ -1,52 +0,0 @@ |
|||||
# A File contains information about a file and where to download it. |
|
||||
type File { |
|
||||
# The file's unique ID |
|
||||
id: String! |
|
||||
|
|
||||
# The kind of file. Most will be "upload", but some that are ported from the wiki will have other values for this. |
|
||||
kind: String! |
|
||||
|
|
||||
# The time of uploading |
|
||||
time: String! |
|
||||
|
|
||||
# Whether the file is publicly listable. Someone with knowledge of the ID |
|
||||
# will still be able to view it, however. |
|
||||
public: Boolean! |
|
||||
|
|
||||
# The file's name |
|
||||
name: String! |
|
||||
|
|
||||
# The MIME type of the file |
|
||||
mimeType: String! |
|
||||
|
|
||||
# The file's size in bytes |
|
||||
size: Int! |
|
||||
|
|
||||
# The uploader |
|
||||
author: String! |
|
||||
|
|
||||
# The URL where the file is hosted |
|
||||
url: String |
|
||||
} |
|
||||
|
|
||||
# Filter for the files quiery. |
|
||||
input FilesFilter { |
|
||||
# If set, this will limit the results to either public or private files. |
|
||||
public: Boolean |
|
||||
|
|
||||
# Limit the MIME types of the files. |
|
||||
mimeTypes: [String!] |
|
||||
} |
|
||||
|
|
||||
# Input for editFile mutation |
|
||||
input EditFileInput { |
|
||||
# The file's unique ID |
|
||||
id: String! |
|
||||
|
|
||||
# Whether the file is publicly listable. Someone with knowledge of the ID |
|
||||
# will still be able to view it, however. |
|
||||
public: Boolean |
|
||||
|
|
||||
# The file's name |
|
||||
name: String |
|
||||
} |
|
@ -1,132 +0,0 @@ |
|||||
# A Log is the "file" of an RP session |
|
||||
type Log { |
|
||||
# A unique identifier for the log. |
|
||||
id: String! |
|
||||
|
|
||||
# A secondary unique identifier for the log. This is a lot shorter and more suitable for storage when |
|
||||
# the link doesn't need to be as expressive. |
|
||||
shortId: String! |
|
||||
|
|
||||
# The date for a log. |
|
||||
date: String! |
|
||||
|
|
||||
# The channel of a log. |
|
||||
channelName: String! |
|
||||
|
|
||||
# Information about the channel this log is in. |
|
||||
channel: Channel! |
|
||||
|
|
||||
# The session's title. |
|
||||
title: String! |
|
||||
|
|
||||
# The log's event, which is the same as the tags in the previous logbot site. |
|
||||
# Empty string means that it's no event. |
|
||||
event: String! |
|
||||
|
|
||||
# The description of a session, which is empty if unset. |
|
||||
description: String! |
|
||||
|
|
||||
# Whether the log session is open. |
|
||||
open: Boolean! |
|
||||
|
|
||||
# The characters involved in the log file. |
|
||||
characters: [Character!]! |
|
||||
|
|
||||
# The posts of the logfile, which can be filtered by kinds. |
|
||||
posts(kinds:[String!]): [Post!]! |
|
||||
} |
|
||||
|
|
||||
# Filter for logs query |
|
||||
input LogsFilter { |
|
||||
# Channels to limit results to (inclusive) |
|
||||
channels: [String!] |
|
||||
|
|
||||
# Events to limit results to (inclusive) |
|
||||
events: [String!] |
|
||||
|
|
||||
# Characters to limit results to (exclusive) |
|
||||
characters: [String!] |
|
||||
|
|
||||
# Search post content |
|
||||
search: String |
|
||||
|
|
||||
# Limit by whether it's open or not |
|
||||
open: Boolean |
|
||||
|
|
||||
# Limit the amount of results you get back |
|
||||
limit: Int |
|
||||
} |
|
||||
|
|
||||
# Input for addLog mutation |
|
||||
input LogAddInput { |
|
||||
# The date of the log, in RFC3339 format with up to nanosecond precision |
|
||||
date: String! |
|
||||
|
|
||||
# The channel where the log is set |
|
||||
channel: String! |
|
||||
|
|
||||
# Optional: The log title |
|
||||
title: String |
|
||||
|
|
||||
# Optional: Whether the log is open |
|
||||
open: Boolean |
|
||||
|
|
||||
# Optional: The log event name |
|
||||
event: String |
|
||||
|
|
||||
# Optional: A short description of the log |
|
||||
description: String |
|
||||
} |
|
||||
|
|
||||
# Input for addLog mutation |
|
||||
input LogEditInput { |
|
||||
# The id of the log |
|
||||
id: String! |
|
||||
|
|
||||
# The log title |
|
||||
title: String |
|
||||
|
|
||||
# The log event name |
|
||||
event: String |
|
||||
|
|
||||
# A short description of the log |
|
||||
description: String |
|
||||
|
|
||||
# Open/close the log |
|
||||
open: Boolean |
|
||||
} |
|
||||
|
|
||||
# A LogHeader is a cut-down version of Log that does not allow getting the actual posts. |
|
||||
type LogHeader { |
|
||||
# A unique identifier for the log. |
|
||||
id: String! |
|
||||
|
|
||||
# A secondary unique identifier for the log. This is a lot shorter and more suitable for storage when |
|
||||
# the link doesn't need to be as expressive. |
|
||||
shortId: String! |
|
||||
|
|
||||
# The date for a log. |
|
||||
date: String! |
|
||||
|
|
||||
# The channel name of a log. |
|
||||
channelName: String! |
|
||||
|
|
||||
# Information about the channel this log is in. |
|
||||
channel: Channel! |
|
||||
|
|
||||
# The session's title. |
|
||||
title: String! |
|
||||
|
|
||||
# The log's event, which is the same as the tags in the previous logbot site. |
|
||||
# Empty string means that it's no event. |
|
||||
event: String! |
|
||||
|
|
||||
# The description of a session, which is empty if unset. |
|
||||
description: String! |
|
||||
|
|
||||
# Whether the log session is open. |
|
||||
open: Boolean! |
|
||||
|
|
||||
# The characters involved in the log file. |
|
||||
characters: [Character!]! |
|
||||
} |
|
@ -1,68 +0,0 @@ |
|||||
# A Post is a part of a log |
|
||||
type Post { |
|
||||
# The post's ID |
|
||||
id: String! |
|
||||
|
|
||||
# The post's Log ID. This is the closest thing to a link back since this API graph doesn't have any cycles. |
|
||||
logId: String! |
|
||||
|
|
||||
# The date and time of posting |
|
||||
time: String! |
|
||||
|
|
||||
# The kind of post this is. Only "text", "scene" and "action" are RP, while others are annotations and 'commands'. |
|
||||
kind: String! |
|
||||
|
|
||||
# The character nick |
|
||||
nick: String! |
|
||||
|
|
||||
# The post's text, which purpose depends on the kind |
|
||||
text: String! |
|
||||
|
|
||||
# The post's position, used for reordering |
|
||||
position: Int! |
|
||||
} |
|
||||
|
|
||||
# Input for the addPost mutation |
|
||||
input AddPostInput { |
|
||||
# The log's ID that this post should be a part of |
|
||||
logId: String! |
|
||||
|
|
||||
# The date and time of posting, in a RFC3339 format with up to a nanosecond's precision |
|
||||
time: String! |
|
||||
|
|
||||
# The kind of post this is. Only "text", "scene" and "action" are RP, while others are annotations and 'commands'. |
|
||||
kind: String! |
|
||||
|
|
||||
# The character nick, or command invoker for non-RP stuff |
|
||||
nick: String! |
|
||||
|
|
||||
# The post's text, which purpose depends on the kind |
|
||||
text: String! |
|
||||
} |
|
||||
|
|
||||
# Input for the editPost mutation |
|
||||
input EditPostInput { |
|
||||
# The Post ID |
|
||||
id: String! |
|
||||
|
|
||||
# The date and time of posting, in a RFC3339 format with up to a nanosecond's precision |
|
||||
time: String |
|
||||
|
|
||||
# The kind of post this is. Only "text", "scene" and "action" are RP, while others are annotations and 'commands'. |
|
||||
kind: String |
|
||||
|
|
||||
# The character nick, or command invoker for non-RP stuff |
|
||||
nick: String |
|
||||
|
|
||||
# The post's text, which purpose depends on the kind |
|
||||
text: String |
|
||||
} |
|
||||
|
|
||||
# Input for the movePost mutation |
|
||||
input MovePostInput { |
|
||||
# The Post ID |
|
||||
id: String! |
|
||||
|
|
||||
# Target index |
|
||||
toPosition: Int! |
|
||||
} |
|
@ -1,151 +0,0 @@ |
|||||
# A Story is a piece of content that, unlike wiki articles, are not something that should be ordered by time instead of title. It can |
|
||||
# contain multiple chapters by one or more autohrs |
|
||||
type Story { |
|
||||
# The story's ID |
|
||||
id: String! |
|
||||
|
|
||||
# The story's name, which will show up in the lists. |
|
||||
name: String! |
|
||||
|
|
||||
# The story's author |
|
||||
author: String! |
|
||||
|
|
||||
# Whether other users may add/edit chapters to the story. |
|
||||
open: Boolean! |
|
||||
|
|
||||
# Whether users without a direct link can find this story. |
|
||||
listed: Boolean! |
|
||||
|
|
||||
# The category of the story |
|
||||
category: StoryCategory! |
|
||||
|
|
||||
# The tags for this tory |
|
||||
tags: [Tag!]! |
|
||||
|
|
||||
# The chapters of this story |
|
||||
chapters: [Chapter!]! |
|
||||
|
|
||||
# The date the story was created (RFC3339 format). |
|
||||
createdDate: String! |
|
||||
|
|
||||
# The date the story is set in (RFC3339 format). |
|
||||
fictionalDate: String! |
|
||||
|
|
||||
# The date of the last major update to the story (RFC3339 format). This being bumped means a new chapter has been added. |
|
||||
updatedDate: String! |
|
||||
} |
|
||||
|
|
||||
# Filter for stories query. |
|
||||
input StoriesFilter { |
|
||||
# What author to query for |
|
||||
author: String |
|
||||
|
|
||||
# What category to query for |
|
||||
category: StoryCategory |
|
||||
|
|
||||
# What tags to query for |
|
||||
tags: [TagInput!] |
|
||||
|
|
||||
# If true, it will only show unlisted page you have access to |
|
||||
unlisted: Boolean |
|
||||
|
|
||||
# Whether the page is open for additions by other users |
|
||||
open: Boolean |
|
||||
|
|
||||
# The earliest fictionalDate |
|
||||
earliestFictionalDate: String |
|
||||
|
|
||||
# The latest fictionalDate |
|
||||
latestFictionalDate: String |
|
||||
|
|
||||
# The max amount of stories to get (default: 30) |
|
||||
limit: Int |
|
||||
} |
|
||||
|
|
||||
# Input for the addStory mutation |
|
||||
input StoryAddInput { |
|
||||
# Set the name of the story, which will show up as the title, and as a suggestion for |
|
||||
# the first chapter being added. |
|
||||
name: String! |
|
||||
|
|
||||
# Set the category for the new story. |
|
||||
category: StoryCategory! |
|
||||
|
|
||||
# Add the story under another name. This requires the story.add permission, and should not be |
|
||||
# abused. The action will be logged with the actual creator's user ID. |
|
||||
author: String |
|
||||
|
|
||||
# Allow other users to post chapters to the story. |
|
||||
open: Boolean |
|
||||
|
|
||||
# Allow other users to see this page in any lists or search results. |
|
||||
listed: Boolean |
|
||||
|
|
||||
# Set which tags the story should have. |
|
||||
tags: [TagInput!] |
|
||||
|
|
||||
# Set the fictional date of the story (RFC3339 format). |
|
||||
fictionalDate: String |
|
||||
} |
|
||||
|
|
||||
# Input for the editStory mutation |
|
||||
input StoryEditInput { |
|
||||
# What story to edit |
|
||||
id: String! |
|
||||
|
|
||||
# Set the name of the story, which will show up as the title, and as a suggestion for |
|
||||
# the first chapter being added. |
|
||||
name: String |
|
||||
|
|
||||
# Set the category for the new story. |
|
||||
category: StoryCategory |
|
||||
|
|
||||
# Add the story under another name. This requires the story.add permission, and should not be |
|
||||
# abused. The action will be logged with the actual creator's user ID. |
|
||||
author: String |
|
||||
|
|
||||
# Change whether to allow others to add chapters |
|
||||
open: Boolean |
|
||||
|
|
||||
# Change whether to show this story in the list and search results |
|
||||
listed: Boolean |
|
||||
|
|
||||
# Set the fictional date of the story (RFC3339 format). |
|
||||
fictionalDate: String |
|
||||
} |
|
||||
|
|
||||
# Input for the addStoryTag mutation |
|
||||
input StoryTagAddInput { |
|
||||
# What story to add the tag to. |
|
||||
id: String! |
|
||||
|
|
||||
# The tag to add. |
|
||||
tag: TagInput! |
|
||||
} |
|
||||
|
|
||||
# Input for the removeStoryTag mutation |
|
||||
input StoryTagRemoveInput { |
|
||||
# What story to remove the tag from. |
|
||||
id: String! |
|
||||
|
|
||||
# The tag to remove. |
|
||||
tag: TagInput! |
|
||||
} |
|
||||
|
|
||||
# Possible values for Story.category |
|
||||
enum StoryCategory { |
|
||||
# General information |
|
||||
Info |
|
||||
|
|
||||
# News stories |
|
||||
News |
|
||||
|
|
||||
# Description and content of a document or item |
|
||||
Document |
|
||||
|
|
||||
# Information about something going on in the background that may or may not inform RP |
|
||||
Background |
|
||||
|
|
||||
# A short story |
|
||||
Story |
|
||||
} |
|
@ -1,36 +0,0 @@ |
|||||
# A Tag is a means of associating stories that have details in common with one another. |
|
||||
type Tag { |
|
||||
# The tag's kind |
|
||||
kind: TagKind! |
|
||||
|
|
||||
# The tag's name |
|
||||
name: String! |
|
||||
} |
|
||||
|
|
||||
# A Tag is a means of associating stories that have details in common with one another. |
|
||||
input TagInput { |
|
||||
# The tag's kind |
|
||||
kind: TagKind! |
|
||||
|
|
||||
# The tag's name |
|
||||
name: String! |
|
||||
} |
|
||||
|
|
||||
# Allowed values for Tag.kind |
|
||||
enum TagKind { |
|
||||
# An organization is a catch all term for in-universe corporations, teams, groups, cults, forces, etc... |
|
||||
Organization |
|
||||
|
|
||||
# A character tag should have the exact full name of the character. |
|
||||
Character |
|
||||
|
|
||||
# A location is anything from a planet to an establishment. This may overlap with an organization, and if so, both |
|
||||
# kinds of tags should be used. |
|
||||
Location |
|
||||
|
|
||||
# An event is a plot or a part of a plot. |
|
||||
Event |
|
||||
|
|
||||
# None of the above, but it does still tie multiple stories together. The new story/chapter format may obsolete this tag kind. |
|
||||
Series |
|
||||
} |
|
@ -1,8 +0,0 @@ |
|||||
# The User type is for interacting with user options and settings |
|
||||
type User { |
|
||||
# Their username |
|
||||
id: String! |
|
||||
|
|
||||
# Their permission |
|
||||
permissions: [String!]! |
|
||||
} |
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue