user.js 8.7 KB

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