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.

330 lines
7.7 KiB

  1. package resolver
  2. import (
  3. "context"
  4. "errors"
  5. "strings"
  6. "git.aiterp.net/rpdata/api/internal/session"
  7. "git.aiterp.net/rpdata/api/loader"
  8. "git.aiterp.net/rpdata/api/model/change"
  9. "git.aiterp.net/rpdata/api/model/character"
  10. "git.aiterp.net/rpdata/api/model/log"
  11. )
  12. // CharacterResolver for the Character graphql type
  13. type CharacterResolver struct{ C character.Character }
  14. // CharacterArgs is an arg
  15. type CharacterArgs struct {
  16. ID *string
  17. Nick *string
  18. }
  19. // Character resolver
  20. func (r *QueryResolver) Character(ctx context.Context, args *CharacterArgs) (*CharacterResolver, error) {
  21. var char character.Character
  22. var err error
  23. loader := loader.FromContext(ctx)
  24. if loader == nil {
  25. return nil, errors.New("no loader")
  26. }
  27. switch {
  28. case args.ID != nil:
  29. char, err = character.FindID(*args.ID)
  30. case args.Nick != nil:
  31. char, err = character.FindNick(*args.Nick)
  32. default:
  33. err = ErrCannotResolve
  34. }
  35. if err != nil {
  36. return nil, err
  37. }
  38. return &CharacterResolver{C: char}, nil
  39. }
  40. // CharactersArgs is an arg
  41. type CharactersArgs struct {
  42. IDs *[]string
  43. Nicks *[]string
  44. Author *string
  45. }
  46. // Characters resolves
  47. func (r *QueryResolver) Characters(ctx context.Context, args *CharactersArgs) ([]*CharacterResolver, error) {
  48. var chars []character.Character
  49. var err error
  50. loader := loader.FromContext(ctx)
  51. if loader == nil {
  52. return nil, errors.New("no loader")
  53. }
  54. switch {
  55. case args.IDs != nil:
  56. chars, err = character.ListIDs(*args.IDs...)
  57. case args.Nicks != nil:
  58. chars, err = character.ListNicks(*args.Nicks...)
  59. case args.Author != nil:
  60. chars, err = character.ListAuthor(*args.Author)
  61. default:
  62. chars, err = character.List()
  63. }
  64. if err != nil {
  65. return nil, err
  66. }
  67. resolvers := make([]*CharacterResolver, 0, len(chars))
  68. for i := range chars {
  69. if chars[i].ID == "" {
  70. continue
  71. }
  72. resolvers = append(resolvers, &CharacterResolver{C: chars[i]})
  73. }
  74. return resolvers, nil
  75. }
  76. // AddCharacterInput is args for mutation addCharacter
  77. type AddCharacterInput struct {
  78. Nick string
  79. Name string
  80. ShortName *string
  81. Author *string
  82. Description *string
  83. }
  84. // AddCharacter resolves the addCharacter mutation
  85. func (r *MutationResolver) AddCharacter(ctx context.Context, args struct{ Input *AddCharacterInput }) (*CharacterResolver, error) {
  86. user := session.FromContext(ctx).User()
  87. if user == nil || !user.Permitted("member", "character.add") {
  88. return nil, ErrUnauthorized
  89. }
  90. nick := args.Input.Nick
  91. name := args.Input.Name
  92. shortName := ""
  93. if args.Input.ShortName != nil {
  94. shortName = *args.Input.ShortName
  95. } else {
  96. shortName = strings.SplitN(args.Input.Name, " ", 2)[0]
  97. }
  98. author := user.ID
  99. if args.Input.Author != nil {
  100. author = *args.Input.Author
  101. if author != user.ID && !user.Permitted("character.add") {
  102. return nil, ErrPermissionDenied
  103. }
  104. }
  105. description := ""
  106. if args.Input.Description != nil {
  107. description = *args.Input.Description
  108. }
  109. character, err := character.New(nick, name, shortName, author, description)
  110. if err != nil {
  111. return nil, err
  112. }
  113. go change.Submit("Character", "add", user.ID, character.ID, map[string]interface{}{
  114. "name": character.Name,
  115. "nick": character.Nicks[0],
  116. "author": character.Author,
  117. })
  118. log.ScheduleCharacterUpdate()
  119. return &CharacterResolver{C: character}, nil
  120. }
  121. // CharacterNickInput is args for mutation addCharacterNick/removeCharacterNick
  122. type CharacterNickInput struct {
  123. ID string
  124. Nick string
  125. }
  126. // AddCharacterNick resolves the addCharacterNick mutation
  127. func (r *MutationResolver) AddCharacterNick(ctx context.Context, args struct{ Input *CharacterNickInput }) (*CharacterResolver, error) {
  128. user := session.FromContext(ctx).User()
  129. if user == nil || !user.Permitted("member") {
  130. return nil, ErrUnauthorized
  131. }
  132. character, err := character.FindID(args.Input.ID)
  133. if err != nil {
  134. return nil, err
  135. }
  136. if character.Author != user.ID && !user.Permitted("character.edit") {
  137. return nil, ErrPermissionDenied
  138. }
  139. err = character.AddNick(args.Input.Nick)
  140. if err != nil {
  141. return nil, err
  142. }
  143. go change.Submit("Character", "add.nick", user.ID, character.ID, map[string]interface{}{
  144. "nick": args.Input.Nick,
  145. })
  146. log.ScheduleCharacterUpdate()
  147. return &CharacterResolver{C: character}, nil
  148. }
  149. // RemoveCharacterNick resolves the removeCharacterNick mutation
  150. func (r *MutationResolver) RemoveCharacterNick(ctx context.Context, args struct{ Input *CharacterNickInput }) (*CharacterResolver, error) {
  151. user := session.FromContext(ctx).User()
  152. if user == nil || !user.Permitted("member") {
  153. return nil, ErrUnauthorized
  154. }
  155. character, err := character.FindID(args.Input.ID)
  156. if err != nil {
  157. return nil, err
  158. }
  159. if character.Author != user.ID && !user.Permitted("character.edit") {
  160. return nil, ErrPermissionDenied
  161. }
  162. err = character.RemoveNick(args.Input.Nick)
  163. if err != nil {
  164. return nil, err
  165. }
  166. go change.Submit("Character", "remove.nick", user.ID, character.ID, map[string]interface{}{
  167. "nick": args.Input.Nick,
  168. })
  169. log.ScheduleCharacterUpdate()
  170. return &CharacterResolver{C: character}, nil
  171. }
  172. // CharacterEditInput is args for mutation addCharacterNick/removeCharacterNick
  173. type CharacterEditInput struct {
  174. ID string
  175. Name *string
  176. ShortName *string
  177. Description *string
  178. }
  179. // EditCharacter resolves the editCharacter mutation
  180. func (r *MutationResolver) EditCharacter(ctx context.Context, args struct{ Input *CharacterEditInput }) (*CharacterResolver, error) {
  181. user := session.FromContext(ctx).User()
  182. if user == nil || !user.Permitted("member") {
  183. return nil, ErrUnauthorized
  184. }
  185. character, err := character.FindID(args.Input.ID)
  186. if err != nil {
  187. return nil, err
  188. }
  189. if character.Author != user.ID && !user.Permitted("character.edit") {
  190. return nil, ErrPermissionDenied
  191. }
  192. name := ""
  193. if args.Input.Name != nil {
  194. name = *args.Input.Name
  195. }
  196. shortName := ""
  197. if args.Input.ShortName != nil {
  198. shortName = *args.Input.ShortName
  199. }
  200. description := ""
  201. if args.Input.Description != nil {
  202. description = *args.Input.Description
  203. }
  204. err = character.Edit(name, shortName, description)
  205. if err != nil {
  206. return nil, err
  207. }
  208. go change.Submit("Character", "edit", user.ID, character.ID, map[string]interface{}{
  209. "name": character.Name,
  210. "shortName": character.ShortName,
  211. "description": character.Description,
  212. })
  213. return &CharacterResolver{C: character}, nil
  214. }
  215. // RemoveCharacter resolves the removeCharacter mutation
  216. func (r *MutationResolver) RemoveCharacter(ctx context.Context, args struct{ ID string }) (*CharacterResolver, error) {
  217. user := session.FromContext(ctx).User()
  218. if user == nil || !user.Permitted("member") {
  219. return nil, ErrUnauthorized
  220. }
  221. character, err := character.FindID(args.ID)
  222. if err != nil {
  223. return nil, err
  224. }
  225. if character.Author != user.ID && !user.Permitted("character.remove") {
  226. return nil, ErrPermissionDenied
  227. }
  228. err = character.Remove()
  229. if err != nil {
  230. return nil, err
  231. }
  232. go change.Submit("Character", "remove", user.ID, character.ID, map[string]interface{}{
  233. "name": character.Name,
  234. "author": character.Author,
  235. "nicks": character.Nicks,
  236. })
  237. return &CharacterResolver{C: character}, nil
  238. }
  239. // ID is a property resolver
  240. func (r *CharacterResolver) ID() string {
  241. return r.C.ID
  242. }
  243. // Nick is a property resolver
  244. func (r *CharacterResolver) Nick() *string {
  245. if len(r.C.Nicks) == 0 {
  246. return nil
  247. }
  248. return &r.C.Nicks[0]
  249. }
  250. // Nicks is a property resolver
  251. func (r *CharacterResolver) Nicks() []string {
  252. return r.C.Nicks
  253. }
  254. // Name is a property resolver
  255. func (r *CharacterResolver) Name() string {
  256. return r.C.Name
  257. }
  258. // ShortName is a property resolver
  259. func (r *CharacterResolver) ShortName() string {
  260. return r.C.ShortName
  261. }
  262. // Author is a property resolver
  263. func (r *CharacterResolver) Author() string {
  264. return r.C.Author
  265. }
  266. // Description is a property resolver
  267. func (r *CharacterResolver) Description() string {
  268. return r.C.Description
  269. }