group.js 6.3 KB

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