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.

177 lines
4.9 KiB

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