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.

265 lines
8.1 KiB

  1. const graphHelper = require('../../helpers/graph')
  2. const _ = require('lodash')
  3. /* global WIKI */
  4. module.exports = {
  5. Query: {
  6. async users() { return {} }
  7. },
  8. Mutation: {
  9. async users() { return {} }
  10. },
  11. UserQuery: {
  12. async list(obj, args, context, info) {
  13. return WIKI.models.users.query()
  14. .select('id', 'email', 'name', 'providerKey', 'isSystem', 'isActive', 'createdAt', 'lastLoginAt')
  15. },
  16. async search(obj, args, context, info) {
  17. return WIKI.models.users.query()
  18. .where('email', 'like', `%${args.query}%`)
  19. .orWhere('name', 'like', `%${args.query}%`)
  20. .limit(10)
  21. .select('id', 'email', 'name', 'providerKey', 'createdAt')
  22. },
  23. async single(obj, args, context, info) {
  24. let usr = await WIKI.models.users.query().findById(args.id)
  25. usr.password = ''
  26. usr.tfaSecret = ''
  27. const str = _.get(WIKI.auth.strategies, usr.providerKey)
  28. str.strategy = _.find(WIKI.data.authentication, ['key', str.strategyKey])
  29. usr.providerName = str.displayName
  30. usr.providerIs2FACapable = _.get(str, 'strategy.useForm', false)
  31. return usr
  32. },
  33. async profile (obj, args, context, info) {
  34. if (!context.req.user || context.req.user.id < 1 || context.req.user.id === 2) {
  35. throw new WIKI.Error.AuthRequired()
  36. }
  37. const usr = await WIKI.models.users.query().findById(context.req.user.id)
  38. if (!usr.isActive) {
  39. throw new WIKI.Error.AuthAccountBanned()
  40. }
  41. const providerInfo = _.get(WIKI.auth.strategies, usr.providerKey, {})
  42. usr.providerName = providerInfo.displayName || 'Unknown'
  43. usr.lastLoginAt = usr.lastLoginAt || usr.updatedAt
  44. usr.password = ''
  45. usr.providerId = ''
  46. usr.tfaSecret = ''
  47. return usr
  48. },
  49. async lastLogins (obj, args, context, info) {
  50. return WIKI.models.users.query()
  51. .select('id', 'name', 'lastLoginAt')
  52. .whereNotNull('lastLoginAt')
  53. .orderBy('lastLoginAt', 'desc')
  54. .limit(10)
  55. }
  56. },
  57. UserMutation: {
  58. async create (obj, args) {
  59. try {
  60. await WIKI.models.users.createNewUser(args)
  61. return {
  62. responseResult: graphHelper.generateSuccess('User created successfully')
  63. }
  64. } catch (err) {
  65. return graphHelper.generateError(err)
  66. }
  67. },
  68. async delete (obj, args) {
  69. try {
  70. if (args.id <= 2) {
  71. throw new WIKI.Error.UserDeleteProtected()
  72. }
  73. await WIKI.models.users.deleteUser(args.id, args.replaceId)
  74. WIKI.auth.revokeUserTokens({ id: args.id, kind: 'u' })
  75. WIKI.events.outbound.emit('addAuthRevoke', { id: args.id, kind: 'u' })
  76. return {
  77. responseResult: graphHelper.generateSuccess('User deleted successfully')
  78. }
  79. } catch (err) {
  80. if (err.message.indexOf('foreign') >= 0) {
  81. return graphHelper.generateError(new WIKI.Error.UserDeleteForeignConstraint())
  82. } else {
  83. return graphHelper.generateError(err)
  84. }
  85. }
  86. },
  87. async update (obj, args) {
  88. try {
  89. await WIKI.models.users.updateUser(args)
  90. return {
  91. responseResult: graphHelper.generateSuccess('User created successfully')
  92. }
  93. } catch (err) {
  94. return graphHelper.generateError(err)
  95. }
  96. },
  97. async verify (obj, args) {
  98. try {
  99. await WIKI.models.users.query().patch({ isVerified: true }).findById(args.id)
  100. return {
  101. responseResult: graphHelper.generateSuccess('User verified successfully')
  102. }
  103. } catch (err) {
  104. return graphHelper.generateError(err)
  105. }
  106. },
  107. async activate (obj, args) {
  108. try {
  109. await WIKI.models.users.query().patch({ isActive: true }).findById(args.id)
  110. return {
  111. responseResult: graphHelper.generateSuccess('User activated successfully')
  112. }
  113. } catch (err) {
  114. return graphHelper.generateError(err)
  115. }
  116. },
  117. async deactivate (obj, args) {
  118. try {
  119. if (args.id <= 2) {
  120. throw new Error('Cannot deactivate system accounts.')
  121. }
  122. await WIKI.models.users.query().patch({ isActive: false }).findById(args.id)
  123. WIKI.auth.revokeUserTokens({ id: args.id, kind: 'u' })
  124. WIKI.events.outbound.emit('addAuthRevoke', { id: args.id, kind: 'u' })
  125. return {
  126. responseResult: graphHelper.generateSuccess('User deactivated successfully')
  127. }
  128. } catch (err) {
  129. return graphHelper.generateError(err)
  130. }
  131. },
  132. async enableTFA (obj, args) {
  133. try {
  134. await WIKI.models.users.query().patch({ tfaIsActive: true, tfaSecret: null }).findById(args.id)
  135. return {
  136. responseResult: graphHelper.generateSuccess('User 2FA enabled successfully')
  137. }
  138. } catch (err) {
  139. return graphHelper.generateError(err)
  140. }
  141. },
  142. async disableTFA (obj, args) {
  143. try {
  144. await WIKI.models.users.query().patch({ tfaIsActive: false, tfaSecret: null }).findById(args.id)
  145. return {
  146. responseResult: graphHelper.generateSuccess('User 2FA disabled successfully')
  147. }
  148. } catch (err) {
  149. return graphHelper.generateError(err)
  150. }
  151. },
  152. resetPassword (obj, args) {
  153. return false
  154. },
  155. async updateProfile (obj, args, context) {
  156. try {
  157. if (!context.req.user || context.req.user.id < 1 || context.req.user.id === 2) {
  158. throw new WIKI.Error.AuthRequired()
  159. }
  160. const usr = await WIKI.models.users.query().findById(context.req.user.id)
  161. if (!usr.isActive) {
  162. throw new WIKI.Error.AuthAccountBanned()
  163. }
  164. if (!usr.isVerified) {
  165. throw new WIKI.Error.AuthAccountNotVerified()
  166. }
  167. if (!['', 'DD/MM/YYYY', 'DD.MM.YYYY', 'MM/DD/YYYY', 'YYYY-MM-DD', 'YYYY/MM/DD'].includes(args.dateFormat)) {
  168. throw new WIKI.Error.InputInvalid()
  169. }
  170. if (!['', 'light', 'dark'].includes(args.appearance)) {
  171. throw new WIKI.Error.InputInvalid()
  172. }
  173. await WIKI.models.users.updateUser({
  174. id: usr.id,
  175. name: _.trim(args.name),
  176. jobTitle: _.trim(args.jobTitle),
  177. location: _.trim(args.location),
  178. timezone: args.timezone,
  179. dateFormat: args.dateFormat,
  180. appearance: args.appearance
  181. })
  182. const newToken = await WIKI.models.users.refreshToken(usr.id)
  183. return {
  184. responseResult: graphHelper.generateSuccess('User profile updated successfully'),
  185. jwt: newToken.token
  186. }
  187. } catch (err) {
  188. return graphHelper.generateError(err)
  189. }
  190. },
  191. async changePassword (obj, args, context) {
  192. try {
  193. if (!context.req.user || context.req.user.id < 1 || context.req.user.id === 2) {
  194. throw new WIKI.Error.AuthRequired()
  195. }
  196. const usr = await WIKI.models.users.query().findById(context.req.user.id)
  197. if (!usr.isActive) {
  198. throw new WIKI.Error.AuthAccountBanned()
  199. }
  200. if (!usr.isVerified) {
  201. throw new WIKI.Error.AuthAccountNotVerified()
  202. }
  203. if (usr.providerKey !== 'local') {
  204. throw new WIKI.Error.AuthProviderInvalid()
  205. }
  206. try {
  207. await usr.verifyPassword(args.current)
  208. } catch (err) {
  209. throw new WIKI.Error.AuthPasswordInvalid()
  210. }
  211. await WIKI.models.users.updateUser({
  212. id: usr.id,
  213. newPassword: args.new
  214. })
  215. const newToken = await WIKI.models.users.refreshToken(usr)
  216. return {
  217. responseResult: graphHelper.generateSuccess('Password changed successfully'),
  218. jwt: newToken.token
  219. }
  220. } catch (err) {
  221. return graphHelper.generateError(err)
  222. }
  223. }
  224. },
  225. User: {
  226. groups (usr) {
  227. return usr.$relatedQuery('groups')
  228. }
  229. },
  230. UserProfile: {
  231. async groups (usr) {
  232. const usrGroups = await usr.$relatedQuery('groups')
  233. return usrGroups.map(g => g.name)
  234. },
  235. async pagesTotal (usr) {
  236. const result = await WIKI.models.pages.query().count('* as total').where('creatorId', usr.id).first()
  237. return _.toSafeInteger(result.total)
  238. }
  239. }
  240. }