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.

202 lines
6.2 KiB

  1. const graphHelper = require('../../helpers/graph')
  2. const safeRegex = require('safe-regex')
  3. const _ = require('lodash')
  4. const gql = require('graphql')
  5. /* global WIKI */
  6. module.exports = {
  7. Query: {
  8. async groups () { return {} }
  9. },
  10. Mutation: {
  11. async groups () { return {} }
  12. },
  13. GroupQuery: {
  14. /**
  15. * FETCH ALL GROUPS
  16. */
  17. async list () {
  18. return WIKI.models.groups.query().select(
  19. 'groups.*',
  20. WIKI.models.groups.relatedQuery('users').count().as('userCount')
  21. )
  22. },
  23. /**
  24. * FETCH A SINGLE GROUP
  25. */
  26. async single(obj, args) {
  27. return WIKI.models.groups.query().findById(args.id)
  28. }
  29. },
  30. GroupMutation: {
  31. /**
  32. * ASSIGN USER TO GROUP
  33. */
  34. async assignUser (obj, args, { req }) {
  35. // Check for guest user
  36. if (args.userId === 2) {
  37. throw new gql.GraphQLError('Cannot assign the Guest user to a group.')
  38. }
  39. // Check for valid group
  40. const grp = await WIKI.models.groups.query().findById(args.groupId)
  41. if (!grp) {
  42. throw new gql.GraphQLError('Invalid Group ID')
  43. }
  44. // Check assigned permissions for write:groups
  45. if (
  46. WIKI.auth.checkExclusiveAccess(req.user, ['write:groups'], ['manage:groups', 'manage:system']) &&
  47. grp.permissions.some(p => {
  48. const resType = _.last(p.split(':'))
  49. return ['users', 'groups', 'navigation', 'theme', 'api', 'system'].includes(resType)
  50. })
  51. ) {
  52. throw new gql.GraphQLError('You are not authorized to assign a user to this elevated group.')
  53. }
  54. // Check for valid user
  55. const usr = await WIKI.models.users.query().findById(args.userId)
  56. if (!usr) {
  57. throw new gql.GraphQLError('Invalid User ID')
  58. }
  59. // Check for existing relation
  60. const relExist = await WIKI.models.knex('userGroups').where({
  61. userId: args.userId,
  62. groupId: args.groupId
  63. }).first()
  64. if (relExist) {
  65. throw new gql.GraphQLError('User is already assigned to group.')
  66. }
  67. // Assign user to group
  68. await grp.$relatedQuery('users').relate(usr.id)
  69. // Revoke tokens for this user
  70. WIKI.auth.revokeUserTokens({ id: usr.id, kind: 'u' })
  71. WIKI.events.outbound.emit('addAuthRevoke', { id: usr.id, kind: 'u' })
  72. return {
  73. responseResult: graphHelper.generateSuccess('User has been assigned to group.')
  74. }
  75. },
  76. /**
  77. * CREATE NEW GROUP
  78. */
  79. async create (obj, args, { req }) {
  80. const group = await WIKI.models.groups.query().insertAndFetch({
  81. name: args.name,
  82. permissions: JSON.stringify(WIKI.data.groups.defaultPermissions),
  83. pageRules: JSON.stringify(WIKI.data.groups.defaultPageRules),
  84. isSystem: false
  85. })
  86. await WIKI.auth.reloadGroups()
  87. WIKI.events.outbound.emit('reloadGroups')
  88. return {
  89. responseResult: graphHelper.generateSuccess('Group created successfully.'),
  90. group
  91. }
  92. },
  93. /**
  94. * DELETE GROUP
  95. */
  96. async delete (obj, args) {
  97. if (args.id === 1 || args.id === 2) {
  98. throw new gql.GraphQLError('Cannot delete this group.')
  99. }
  100. await WIKI.models.groups.query().deleteById(args.id)
  101. WIKI.auth.revokeUserTokens({ id: args.id, kind: 'g' })
  102. WIKI.events.outbound.emit('addAuthRevoke', { id: args.id, kind: 'g' })
  103. await WIKI.auth.reloadGroups()
  104. WIKI.events.outbound.emit('reloadGroups')
  105. return {
  106. responseResult: graphHelper.generateSuccess('Group has been deleted.')
  107. }
  108. },
  109. /**
  110. * UNASSIGN USER FROM GROUP
  111. */
  112. async unassignUser (obj, args) {
  113. if (args.userId === 2) {
  114. throw new gql.GraphQLError('Cannot unassign Guest user')
  115. }
  116. if (args.userId === 1 && args.groupId === 1) {
  117. throw new gql.GraphQLError('Cannot unassign Administrator user from Administrators group.')
  118. }
  119. const grp = await WIKI.models.groups.query().findById(args.groupId)
  120. if (!grp) {
  121. throw new gql.GraphQLError('Invalid Group ID')
  122. }
  123. const usr = await WIKI.models.users.query().findById(args.userId)
  124. if (!usr) {
  125. throw new gql.GraphQLError('Invalid User ID')
  126. }
  127. await grp.$relatedQuery('users').unrelate().where('userId', usr.id)
  128. WIKI.auth.revokeUserTokens({ id: usr.id, kind: 'u' })
  129. WIKI.events.outbound.emit('addAuthRevoke', { id: usr.id, kind: 'u' })
  130. return {
  131. responseResult: graphHelper.generateSuccess('User has been unassigned from group.')
  132. }
  133. },
  134. /**
  135. * UPDATE GROUP
  136. */
  137. async update (obj, args, { req }) {
  138. // Check for unsafe regex page rules
  139. if (_.some(args.pageRules, pr => {
  140. return pr.match === 'REGEX' && !safeRegex(pr.path)
  141. })) {
  142. throw new gql.GraphQLError('Some Page Rules contains unsafe or exponential time regex.')
  143. }
  144. // Set default redirect on login value
  145. if (_.isEmpty(args.redirectOnLogin)) {
  146. args.redirectOnLogin = '/'
  147. }
  148. // Check assigned permissions for write:groups
  149. if (
  150. WIKI.auth.checkExclusiveAccess(req.user, ['write:groups'], ['manage:groups', 'manage:system']) &&
  151. args.permissions.some(p => {
  152. const resType = _.last(p.split(':'))
  153. return ['users', 'groups', 'navigation', 'theme', 'api', 'system'].includes(resType)
  154. })
  155. ) {
  156. throw new gql.GraphQLError('You are not authorized to manage this group or assign these permissions.')
  157. }
  158. // Update group
  159. await WIKI.models.groups.query().patch({
  160. name: args.name,
  161. redirectOnLogin: args.redirectOnLogin,
  162. permissions: JSON.stringify(args.permissions),
  163. pageRules: JSON.stringify(args.pageRules)
  164. }).where('id', args.id)
  165. // Revoke tokens for this group
  166. WIKI.auth.revokeUserTokens({ id: args.id, kind: 'g' })
  167. WIKI.events.outbound.emit('addAuthRevoke', { id: args.id, kind: 'g' })
  168. // Reload group permissions
  169. await WIKI.auth.reloadGroups()
  170. WIKI.events.outbound.emit('reloadGroups')
  171. return {
  172. responseResult: graphHelper.generateSuccess('Group has been updated.')
  173. }
  174. }
  175. },
  176. Group: {
  177. users (grp) {
  178. return grp.$relatedQuery('users')
  179. }
  180. }
  181. }