Browse Source

graph2: Added Story mutations

1.0
Gisle Aune 6 years ago
parent
commit
0e0d802a32
  1. 4
      graph2/queries/chapter.go
  2. 94
      graph2/queries/story.go
  3. 16
      graph2/schema/root.gql
  4. 9
      graph2/schema/types/Story.gql
  5. 29
      models/stories/add-tag.go
  6. 30
      models/stories/add.go
  7. 45
      models/stories/edit.go
  8. 34
      models/stories/remove-tag.go
  9. 10
      models/stories/remove.go

4
graph2/queries/chapter.go

@ -13,10 +13,14 @@ import (
"git.aiterp.net/rpdata/api/models/chapters"
)
// Queries
func (r *resolver) Chapter(ctx context.Context, id string) (models.Chapter, error) {
return chapters.FindID(id)
}
// Mutations
func (r *mutationResolver) AddChapter(ctx context.Context, input input.ChapterAddInput) (models.Chapter, error) {
story, err := stories.FindID(input.StoryID)
if err != nil {

94
graph2/queries/story.go

@ -3,7 +3,9 @@ package queries
import (
"context"
"errors"
"time"
"git.aiterp.net/rpdata/api/graph2/input"
"git.aiterp.net/rpdata/api/internal/auth"
"git.aiterp.net/rpdata/api/models"
"git.aiterp.net/rpdata/api/models/stories"
@ -29,3 +31,95 @@ func (r *resolver) Stories(ctx context.Context, filter *stories.Filter) ([]model
return stories.List(filter)
}
// Mutations
func (r *mutationResolver) AddStory(ctx context.Context, input input.StoryAddInput) (models.Story, error) {
token := auth.TokenFromContext(ctx)
if token == nil || !token.Permitted("member", "story.add") {
return models.Story{}, errors.New("Permission denied")
}
author := token.UserID
if input.Author != nil && *input.Author != author {
if !token.Permitted("story.add") {
return models.Story{}, errors.New("You are not permitted to add a story in another author's name")
}
author = *input.Author
}
fictionalDate := time.Time{}
if input.FictionalDate != nil {
fictionalDate = *input.FictionalDate
}
listed := input.Listed != nil && *input.Listed
open := input.Open != nil && *input.Open
return stories.Add(input.Name, author, input.Category, listed, open, input.Tags, time.Now(), fictionalDate)
}
func (r *mutationResolver) AddStoryTag(ctx context.Context, input input.StoryTagAddInput) (models.Story, error) {
token := auth.TokenFromContext(ctx)
story, err := stories.FindID(input.ID)
if err != nil {
return models.Story{}, errors.New("Story not found")
}
if token.PermittedUser(story.Author, "member", "story.edit") {
return models.Story{}, errors.New("You are not permitted to edit this story")
}
return stories.AddTag(story, input.Tag)
}
func (r *mutationResolver) RemoveStoryTag(ctx context.Context, input input.StoryTagRemoveInput) (models.Story, error) {
token := auth.TokenFromContext(ctx)
story, err := stories.FindID(input.ID)
if err != nil {
return models.Story{}, errors.New("Story not found")
}
if token.PermittedUser(story.Author, "member", "story.edit") {
return models.Story{}, errors.New("You are not permitted to edit this story")
}
return stories.RemoveTag(story, input.Tag)
}
func (r *mutationResolver) EditStory(ctx context.Context, input input.StoryEditInput) (models.Story, error) {
token := auth.TokenFromContext(ctx)
story, err := stories.FindID(input.ID)
if err != nil {
return models.Story{}, errors.New("Story not found")
}
if token.PermittedUser(story.Author, "member", "story.edit") {
return models.Story{}, errors.New("You are not permitted to remove this story")
}
if input.ClearFictionalDate != nil && *input.ClearFictionalDate {
input.FictionalDate = &time.Time{}
}
return stories.Edit(story, input.Name, input.Category, input.Listed, input.Open, input.FictionalDate)
}
func (r *mutationResolver) RemoveStory(ctx context.Context, input input.StoryRemoveInput) (models.Story, error) {
token := auth.TokenFromContext(ctx)
story, err := stories.FindID(input.ID)
if err != nil {
return models.Story{}, errors.New("Story not found")
}
if token.PermittedUser(story.Author, "member", "story.remove") {
return models.Story{}, errors.New("You are not permitted to remove this story")
}
return stories.Remove(story)
}

16
graph2/schema/root.gql

@ -59,6 +59,22 @@ type Query {
}
type Mutation {
# 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(input: StoryRemoveInput!): Story!
# Add a chapter to a story
addChapter(input: ChapterAddInput!): Chapter!

9
graph2/schema/types/Story.gql

@ -112,6 +112,9 @@ input StoryEditInput {
# Set the fictional date of the story.
fictionalDate: Date
# Clear the fictional date of the story.
clearFictionalDate: Boolean
}
# Input for the addStoryTag mutation
@ -132,6 +135,12 @@ input StoryTagRemoveInput {
tag: TagInput!
}
# Input for the removeStory mutation
input StoryRemoveInput {
# What story to remove.
id: String!
}
# Possible values for Story.category
enum StoryCategory {
# General information

29
models/stories/add-tag.go

@ -0,0 +1,29 @@
package stories
import (
"errors"
"git.aiterp.net/rpdata/api/models"
"github.com/globalsign/mgo/bson"
)
// ErrTagAlreadyExists is an error returned by Story.AddTag
var ErrTagAlreadyExists = errors.New("Tag already exists on story")
// AddTag adds a tag to the story. It returns ErrTagAlreadyExists if the tag is already there
func AddTag(story models.Story, tag models.Tag) (models.Story, error) {
for i := range story.Tags {
if story.Tags[i].Equal(tag) {
return models.Story{}, ErrTagAlreadyExists
}
}
err := collection.UpdateId(story.ID, bson.M{"$push": bson.M{"tags": tag}})
if err != nil {
return models.Story{}, err
}
story.Tags = append(story.Tags, tag)
return story, nil
}

30
models/stories/add.go

@ -0,0 +1,30 @@
package stories
import (
"time"
"git.aiterp.net/rpdata/api/models"
)
// Add creates a new story.
func Add(name, author string, category models.StoryCategory, listed, open bool, tags []models.Tag, createdDate, fictionalDate time.Time) (models.Story, error) {
story := models.Story{
ID: makeStoryID(),
Name: name,
Author: author,
Category: category,
Listed: listed,
Open: open,
Tags: tags,
CreatedDate: createdDate,
FictionalDate: fictionalDate,
UpdatedDate: createdDate,
}
err := collection.Insert(story)
if err != nil {
return models.Story{}, err
}
return story, nil
}

45
models/stories/edit.go

@ -0,0 +1,45 @@
package stories
import (
"time"
"git.aiterp.net/rpdata/api/models"
"github.com/globalsign/mgo/bson"
)
// Edit edits the story and returns the edited story if it succeeds.
func Edit(story models.Story, name *string, category *models.StoryCategory, listed, open *bool, fictionalDate *time.Time) (models.Story, error) {
changes := bson.M{}
if name != nil && *name != story.Name {
changes["name"] = *name
story.Name = *name
}
if category != nil && *category != story.Category {
changes["category"] = *category
story.Category = *category
}
if listed != nil && *listed != story.Listed {
changes["listed"] = *listed
story.Listed = *listed
}
if open != nil && *open != story.Open {
changes["open"] = *open
story.Open = *open
}
if fictionalDate != nil && !fictionalDate.Equal(story.FictionalDate) {
changes["fictionalDate"] = *fictionalDate
story.FictionalDate = *fictionalDate
}
if len(changes) == 0 {
return story, nil
}
err := collection.UpdateId(story.ID, bson.M{"$set": changes})
if err != nil {
return models.Story{}, err
}
return story, nil
}

34
models/stories/remove-tag.go

@ -0,0 +1,34 @@
package stories
import (
"errors"
"git.aiterp.net/rpdata/api/models"
"github.com/globalsign/mgo/bson"
)
// ErrTagNotExists is an error returned by Story.RemoveTag
var ErrTagNotExists = errors.New("Tag does not exist on story")
// RemoveTag removes a tag to the story. It returns ErrTagNotExists if the tag does not exist.
func RemoveTag(story models.Story, tag models.Tag) (models.Story, error) {
index := -1
for i := range story.Tags {
if story.Tags[i].Equal(tag) {
index = i
break
}
}
if index == -1 {
return models.Story{}, ErrTagNotExists
}
err := collection.UpdateId(story.ID, bson.M{"$pull": bson.M{"tags": tag}})
if err != nil {
return models.Story{}, err
}
story.Tags = append(story.Tags[:index], story.Tags[index+1:]...)
return story, nil
}

10
models/stories/remove.go

@ -0,0 +1,10 @@
package stories
import (
"git.aiterp.net/rpdata/api/models"
)
// Remove the story from the database
func Remove(story models.Story) (models.Story, error) {
return story, collection.RemoveId(story.ID)
}
Loading…
Cancel
Save