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.

340 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 the characters query
  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 the addCharacter mutation
  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. input := args.Input
  87. user := session.FromContext(ctx).User()
  88. if user == nil || !user.Permitted("member", "character.add") {
  89. return nil, ErrUnauthorized
  90. }
  91. nick := input.Nick
  92. name := input.Name
  93. shortName := ""
  94. if input.ShortName != nil {
  95. shortName = *input.ShortName
  96. } else {
  97. shortName = strings.SplitN(input.Name, " ", 2)[0]
  98. }
  99. author := user.ID
  100. if input.Author != nil {
  101. author = *input.Author
  102. if author != user.ID && !user.Permitted("character.add") {
  103. return nil, ErrPermissionDenied
  104. }
  105. }
  106. description := ""
  107. if input.Description != nil {
  108. description = *input.Description
  109. }
  110. character, err := character.New(nick, name, shortName, author, description)
  111. if err != nil {
  112. return nil, err
  113. }
  114. go change.Submit("Character", "add", user.ID, character.ID, map[string]interface{}{
  115. "name": character.Name,
  116. "nick": character.Nicks[0],
  117. "author": character.Author,
  118. })
  119. log.ScheduleCharacterUpdate()
  120. return &CharacterResolver{C: character}, nil
  121. }
  122. // CharacterNickInput is args for mutation addCharacterNick/removeCharacterNick
  123. type CharacterNickInput struct {
  124. ID string
  125. Nick string
  126. }
  127. // AddCharacterNick resolves the addCharacterNick mutation
  128. func (r *MutationResolver) AddCharacterNick(ctx context.Context, args struct{ Input *CharacterNickInput }) (*CharacterResolver, error) {
  129. input := args.Input
  130. user := session.FromContext(ctx).User()
  131. if user == nil || !user.Permitted("member") {
  132. return nil, ErrUnauthorized
  133. }
  134. character, err := character.FindID(input.ID)
  135. if err != nil {
  136. return nil, err
  137. }
  138. if character.Author != user.ID && !user.Permitted("character.edit") {
  139. return nil, ErrPermissionDenied
  140. }
  141. err = character.AddNick(input.Nick)
  142. if err != nil {
  143. return nil, err
  144. }
  145. go change.Submit("Character", "add.nick", user.ID, character.ID, map[string]interface{}{
  146. "nick": input.Nick,
  147. })
  148. log.ScheduleCharacterUpdate()
  149. return &CharacterResolver{C: character}, nil
  150. }
  151. // RemoveCharacterNick resolves the removeCharacterNick mutation
  152. func (r *MutationResolver) RemoveCharacterNick(ctx context.Context, args struct{ Input *CharacterNickInput }) (*CharacterResolver, error) {
  153. input := args.Input
  154. user := session.FromContext(ctx).User()
  155. if user == nil || !user.Permitted("member") {
  156. return nil, ErrUnauthorized
  157. }
  158. character, err := character.FindID(input.ID)
  159. if err != nil {
  160. return nil, err
  161. }
  162. if character.Author != user.ID && !user.Permitted("character.edit") {
  163. return nil, ErrPermissionDenied
  164. }
  165. err = character.RemoveNick(input.Nick)
  166. if err != nil {
  167. return nil, err
  168. }
  169. go change.Submit("Character", "remove.nick", user.ID, character.ID, map[string]interface{}{
  170. "nick": input.Nick,
  171. })
  172. log.ScheduleCharacterUpdate()
  173. return &CharacterResolver{C: character}, nil
  174. }
  175. // CharacterEditInput is args for mutation addCharacterNick/removeCharacterNick
  176. type CharacterEditInput struct {
  177. ID string
  178. Name *string
  179. ShortName *string
  180. Description *string
  181. }
  182. // EditCharacter resolves the editCharacter mutation
  183. func (r *MutationResolver) EditCharacter(ctx context.Context, args struct{ Input *CharacterEditInput }) (*CharacterResolver, error) {
  184. input := args.Input
  185. user := session.FromContext(ctx).User()
  186. if user == nil || !user.Permitted("member") {
  187. return nil, ErrUnauthorized
  188. }
  189. character, err := character.FindID(input.ID)
  190. if err != nil {
  191. return nil, err
  192. }
  193. if character.Author != user.ID && !user.Permitted("character.edit") {
  194. return nil, ErrPermissionDenied
  195. }
  196. name := ""
  197. if input.Name != nil {
  198. name = *input.Name
  199. }
  200. shortName := ""
  201. if input.ShortName != nil {
  202. shortName = *input.ShortName
  203. }
  204. description := ""
  205. if input.Description != nil {
  206. description = *input.Description
  207. }
  208. err = character.Edit(name, shortName, description)
  209. if err != nil {
  210. return nil, err
  211. }
  212. go change.Submit("Character", "edit", user.ID, character.ID, map[string]interface{}{
  213. "name": character.Name,
  214. "shortName": character.ShortName,
  215. "description": character.Description,
  216. })
  217. return &CharacterResolver{C: character}, nil
  218. }
  219. // RemoveCharacter resolves the removeCharacter mutation
  220. func (r *MutationResolver) RemoveCharacter(ctx context.Context, args struct{ ID string }) (*CharacterResolver, error) {
  221. user := session.FromContext(ctx).User()
  222. if user == nil || !user.Permitted("member") {
  223. return nil, ErrUnauthorized
  224. }
  225. character, err := character.FindID(args.ID)
  226. if err != nil {
  227. return nil, err
  228. }
  229. if character.Author != user.ID && !user.Permitted("character.remove") {
  230. return nil, ErrPermissionDenied
  231. }
  232. err = character.Remove()
  233. if err != nil {
  234. return nil, err
  235. }
  236. go change.Submit("Character", "remove", user.ID, character.ID, map[string]interface{}{
  237. "name": character.Name,
  238. "author": character.Author,
  239. "nicks": character.Nicks,
  240. })
  241. return &CharacterResolver{C: character}, nil
  242. }
  243. // ID is a property resolver
  244. func (r *CharacterResolver) ID() string {
  245. return r.C.ID
  246. }
  247. // Nick is a property resolver
  248. func (r *CharacterResolver) Nick() *string {
  249. if len(r.C.Nicks) == 0 {
  250. return nil
  251. }
  252. return &r.C.Nicks[0]
  253. }
  254. // Nicks is a property resolver
  255. func (r *CharacterResolver) Nicks() []string {
  256. return r.C.Nicks
  257. }
  258. // Name is a property resolver
  259. func (r *CharacterResolver) Name() string {
  260. return r.C.Name
  261. }
  262. // ShortName is a property resolver
  263. func (r *CharacterResolver) ShortName() string {
  264. return r.C.ShortName
  265. }
  266. // Author is a property resolver
  267. func (r *CharacterResolver) Author() string {
  268. return r.C.Author
  269. }
  270. // Description is a property resolver
  271. func (r *CharacterResolver) Description() string {
  272. return r.C.Description
  273. }