+141
-2
@@ -4,18 +4,20 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/internal/session"
|
||||||
|
"git.aiterp.net/rpdata/api/model/change"
|
||||||
"git.aiterp.net/rpdata/api/model/story"
|
"git.aiterp.net/rpdata/api/model/story"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ChapterResolver for the Chapter graphql type
|
// ChapterResolver for the Chapter graphql type
|
||||||
type ChapterResolver struct{ C story.Chapter }
|
type ChapterResolver struct{ C story.Chapter }
|
||||||
|
|
||||||
// ChapterArgs is args for channel query
|
// ChapterArgs is args for chapter query
|
||||||
type ChapterArgs struct {
|
type ChapterArgs struct {
|
||||||
ID string
|
ID string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chapter implements the channel query
|
// Chapter implements the chapter query
|
||||||
func (r *QueryResolver) Chapter(ctx context.Context, args *ChapterArgs) (*ChapterResolver, error) {
|
func (r *QueryResolver) Chapter(ctx context.Context, args *ChapterArgs) (*ChapterResolver, error) {
|
||||||
chapter, err := story.FindChapterID(args.ID)
|
chapter, err := story.FindChapterID(args.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -25,6 +27,143 @@ func (r *QueryResolver) Chapter(ctx context.Context, args *ChapterArgs) (*Chapte
|
|||||||
return &ChapterResolver{C: chapter}, nil
|
return &ChapterResolver{C: chapter}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddChapterArgs is args for the addChapter mutation
|
||||||
|
type AddChapterArgs struct {
|
||||||
|
Input *AddChapterInput
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddChapterInput is input for the addChapter mutation
|
||||||
|
type AddChapterInput struct {
|
||||||
|
StoryID string
|
||||||
|
Title string
|
||||||
|
Author *string
|
||||||
|
Source string
|
||||||
|
FictionalDate *string
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddChapter implements the addChapter mutation
|
||||||
|
func (r *MutationResolver) AddChapter(ctx context.Context, args *AddChapterArgs) (*ChapterResolver, error) {
|
||||||
|
user := session.FromContext(ctx).User()
|
||||||
|
if user == nil || !user.Permitted("member", "chapter.add") {
|
||||||
|
return nil, ErrUnauthorized
|
||||||
|
}
|
||||||
|
|
||||||
|
story, err := story.FindID(args.Input.StoryID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
author := user.ID
|
||||||
|
if args.Input.Author != nil {
|
||||||
|
author = *args.Input.Author
|
||||||
|
|
||||||
|
if user.ID != author && !user.Permitted("chapter.add") {
|
||||||
|
return nil, ErrPermissionDenied
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fictionalDate := time.Time{}
|
||||||
|
if args.Input.FictionalDate != nil {
|
||||||
|
fictionalDate, err = time.Parse(time.RFC3339Nano, *args.Input.FictionalDate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chapter, err := story.AddChapter(args.Input.Title, author, args.Input.Source, time.Now(), fictionalDate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
change.Submit("Chapter", "add", user.ID, chapter.ID, map[string]interface{}{
|
||||||
|
"title": args.Input.Title,
|
||||||
|
"author": author,
|
||||||
|
"fictionalDate": fictionalDate,
|
||||||
|
})
|
||||||
|
|
||||||
|
return &ChapterResolver{C: chapter}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditChapterArgs is args for the addChapter mutation
|
||||||
|
type EditChapterArgs struct {
|
||||||
|
Input *EditChapterInput
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditChapterInput is input for the addChapter mutation
|
||||||
|
type EditChapterInput struct {
|
||||||
|
ID string
|
||||||
|
Title *string
|
||||||
|
Source *string
|
||||||
|
FictionalDate *string
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditChapter implements the editChapter mutation
|
||||||
|
func (r *MutationResolver) EditChapter(ctx context.Context, args *EditChapterArgs) (*ChapterResolver, error) {
|
||||||
|
user := session.FromContext(ctx).User()
|
||||||
|
if user == nil || !user.Permitted("member", "chapter.edit") {
|
||||||
|
return nil, ErrUnauthorized
|
||||||
|
}
|
||||||
|
|
||||||
|
chapter, err := story.FindChapterID(args.Input.ID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if chapter.Author != user.ID && !user.Permitted("chapter.edit") {
|
||||||
|
return nil, ErrPermissionDenied
|
||||||
|
}
|
||||||
|
|
||||||
|
var fictionalDate *time.Time
|
||||||
|
if args.Input.FictionalDate != nil {
|
||||||
|
date, err := time.Parse(time.RFC3339Nano, *args.Input.FictionalDate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fictionalDate = &date
|
||||||
|
}
|
||||||
|
|
||||||
|
err = chapter.Edit(args.Input.Title, args.Input.Source, fictionalDate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
change.Submit("Chapter", "edit", user.ID, chapter.ID, map[string]interface{}{
|
||||||
|
"title": args.Input.Title,
|
||||||
|
"source": args.Input.Source,
|
||||||
|
"fictionalDate": fictionalDate,
|
||||||
|
})
|
||||||
|
|
||||||
|
return &ChapterResolver{C: chapter}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteChapterArgs is args for the addChapter mutation
|
||||||
|
type DeleteChapterArgs struct {
|
||||||
|
ID string
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveChapter implements the removeChapter mutation
|
||||||
|
func (r *MutationResolver) RemoveChapter(ctx context.Context, args *DeleteChapterArgs) (*ChapterResolver, error) {
|
||||||
|
user := session.FromContext(ctx).User()
|
||||||
|
if user == nil || !user.Permitted("member", "chapter.edit") {
|
||||||
|
return nil, ErrUnauthorized
|
||||||
|
}
|
||||||
|
|
||||||
|
chapter, err := story.FindChapterID(args.ID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = chapter.Remove()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
change.Submit("Chapter", "remove", user.ID, chapter.ID, nil)
|
||||||
|
|
||||||
|
return &ChapterResolver{C: chapter}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ID resolves Chapter.id
|
// ID resolves Chapter.id
|
||||||
func (r *ChapterResolver) ID() string {
|
func (r *ChapterResolver) ID() string {
|
||||||
return r.C.ID
|
return r.C.ID
|
||||||
|
|||||||
@@ -113,6 +113,16 @@ type Mutation {
|
|||||||
removeFile(id: String!): File
|
removeFile(id: String!): File
|
||||||
|
|
||||||
|
|
||||||
|
# Add a chapter to a story
|
||||||
|
addChapter(input: ChapterAddInput!): Chapter!
|
||||||
|
|
||||||
|
# Edit a chapter
|
||||||
|
editChapter(input: ChapterEditInput!): Chapter!
|
||||||
|
|
||||||
|
# Remove a chapter
|
||||||
|
removeChapter(id: String!): Chapter!
|
||||||
|
|
||||||
|
|
||||||
# Log in
|
# Log in
|
||||||
login(username: String!, password: String!): Session!
|
login(username: String!, password: String!): Session!
|
||||||
|
|
||||||
|
|||||||
@@ -20,4 +20,40 @@ type Chapter {
|
|||||||
|
|
||||||
# The date of edit.
|
# The date of edit.
|
||||||
editedDate: String!
|
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
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user