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

174 lines
5.0 KiB

  1. package queries
  2. import (
  3. "context"
  4. "errors"
  5. "time"
  6. "git.aiterp.net/rpdata/api/models/changekeys"
  7. "git.aiterp.net/rpdata/api/models/changes"
  8. "git.aiterp.net/rpdata/api/models/comments"
  9. "git.aiterp.net/rpdata/api/internal/auth"
  10. "git.aiterp.net/rpdata/api/models/stories"
  11. "git.aiterp.net/rpdata/api/graph2/input"
  12. "git.aiterp.net/rpdata/api/models"
  13. "git.aiterp.net/rpdata/api/models/chapters"
  14. )
  15. // Queries
  16. func (r *resolver) Chapter(ctx context.Context, id string) (models.Chapter, error) {
  17. return chapters.FindID(id)
  18. }
  19. // Mutations
  20. func (r *mutationResolver) AddChapter(ctx context.Context, input input.ChapterAddInput) (models.Chapter, error) {
  21. story, err := stories.FindID(input.StoryID)
  22. if err != nil {
  23. return models.Chapter{}, errors.New("Story not found")
  24. }
  25. token := auth.TokenFromContext(ctx)
  26. if !token.Permitted("member", "story.add") {
  27. return models.Chapter{}, errors.New("Unauthorized")
  28. }
  29. author := token.UserID
  30. if input.Author != nil && *input.Author != author {
  31. if !token.Permitted("story.add") {
  32. return models.Chapter{}, errors.New("False pretender")
  33. }
  34. author = *input.Author
  35. }
  36. if !story.Open && story.Author != author {
  37. return models.Chapter{}, errors.New("Story is not open")
  38. }
  39. commentMode := models.ChapterCommentModeDisabled
  40. if input.CommentMode != nil {
  41. commentMode = *input.CommentMode
  42. }
  43. chapter, err := chapters.Add(story, input.Title, author, input.Source, time.Now(), input.FictionalDate, commentMode)
  44. if err != nil {
  45. return models.Chapter{}, errors.New("Failed to create chapter: " + err.Error())
  46. }
  47. go changes.Submit("Chapter", "add", token.UserID, story.Listed, changekeys.Listed(story, chapter), story, chapter)
  48. return chapter, nil
  49. }
  50. func (r *mutationResolver) MoveChapter(ctx context.Context, input input.ChapterMoveInput) (models.Chapter, error) {
  51. chapter, err := chapters.FindID(input.ID)
  52. if err != nil {
  53. return models.Chapter{}, errors.New("Chapter not found")
  54. }
  55. token := auth.TokenFromContext(ctx)
  56. if !token.Authenticated() || !token.PermittedUser(chapter.Author, "member", "chapter.move") {
  57. return models.Chapter{}, errors.New("You are not allowed to move this chapter")
  58. }
  59. target, err := stories.FindID(input.StoryID)
  60. if err != nil {
  61. return models.Chapter{}, errors.New("Target story not found")
  62. }
  63. if !target.Open && !token.PermittedUser(target.Author, "member", "chapter.move") {
  64. return models.Chapter{}, errors.New("You are not permitted to move chapters to this story")
  65. }
  66. oldStoryID := chapter.StoryID
  67. chapter, err = chapters.Move(chapter, target)
  68. if err != nil {
  69. return models.Chapter{}, errors.New("Failed to move chapter: " + err.Error())
  70. }
  71. go func() {
  72. story, err := stories.FindID(chapter.StoryID)
  73. if err != nil {
  74. story.ID = chapter.StoryID
  75. }
  76. oldStory, err := stories.FindID(oldStoryID)
  77. if err != nil {
  78. oldStory.ID = oldStoryID
  79. }
  80. changes.Submit("Chapter", "move-out", chapter.Author, oldStory.Listed, changekeys.Many(oldStory, chapter), chapter)
  81. changes.Submit("Chapter", "move-in", token.UserID, story.Listed, changekeys.Listed(story, chapter), story, chapter)
  82. }()
  83. return chapter, nil
  84. }
  85. func (r *mutationResolver) EditChapter(ctx context.Context, input input.ChapterEditInput) (models.Chapter, error) {
  86. chapter, err := chapters.FindID(input.ID)
  87. if err != nil {
  88. return models.Chapter{}, errors.New("Chapter not found")
  89. }
  90. token := auth.TokenFromContext(ctx)
  91. if !token.Authenticated() || !token.PermittedUser(chapter.Author, "member", "chapter.edit") {
  92. return models.Chapter{}, errors.New("Unauthorized")
  93. }
  94. if input.ClearFictionalDate != nil && *input.ClearFictionalDate == true {
  95. input.FictionalDate = &time.Time{}
  96. }
  97. chapter, err = chapters.Edit(chapter, input.Title, input.Source, input.FictionalDate, input.CommentMode, input.CommentsLocked)
  98. if err != nil {
  99. return models.Chapter{}, errors.New("Failed to edit chapter: " + err.Error())
  100. }
  101. go func() {
  102. story, err := stories.FindID(chapter.StoryID)
  103. if err != nil {
  104. story.ID = chapter.StoryID
  105. }
  106. changes.Submit("Chapter", "edit", token.UserID, story.Listed, changekeys.Many(story, chapter), chapter)
  107. }()
  108. return chapter, nil
  109. }
  110. func (r *mutationResolver) RemoveChapter(ctx context.Context, input input.ChapterRemoveInput) (models.Chapter, error) {
  111. chapter, err := chapters.FindID(input.ID)
  112. if err != nil {
  113. return models.Chapter{}, errors.New("Chapter not found")
  114. }
  115. token := auth.TokenFromContext(ctx)
  116. if !token.Authenticated() || !token.PermittedUser(chapter.Author, "member", "chapter.remove") {
  117. return models.Chapter{}, errors.New("Unauthorized")
  118. }
  119. chapter, err = chapters.Remove(chapter)
  120. if err != nil {
  121. return models.Chapter{}, errors.New("Failed to remove chapter: " + err.Error())
  122. }
  123. err = comments.RemoveChapter(chapter)
  124. if err != nil {
  125. return models.Chapter{}, errors.New("Chapter was removed, but comment removal failed: " + err.Error())
  126. }
  127. go func() {
  128. story, err := stories.FindID(chapter.StoryID)
  129. if err != nil {
  130. story.ID = chapter.StoryID
  131. }
  132. changes.Submit("Chapter", "remove", token.UserID, story.Listed, changekeys.Many(story, chapter), chapter)
  133. }()
  134. return chapter, nil
  135. }