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.

242 lines
7.0 KiB

  1. const _ = require('lodash')
  2. const fs = require('fs-extra')
  3. const path = require('path')
  4. const graphHelper = require('../../helpers/graph')
  5. /* global WIKI */
  6. module.exports = {
  7. Query: {
  8. async authentication () { return {} }
  9. },
  10. Mutation: {
  11. async authentication () { return {} }
  12. },
  13. AuthenticationQuery: {
  14. /**
  15. * List of API Keys
  16. */
  17. async apiKeys (obj, args, context) {
  18. const keys = await WIKI.models.apiKeys.query().orderBy(['isRevoked', 'name'])
  19. return keys.map(k => ({
  20. id: k.id,
  21. name: k.name,
  22. keyShort: '...' + k.key.substring(k.key.length - 20),
  23. isRevoked: k.isRevoked,
  24. expiration: k.expiration,
  25. createdAt: k.createdAt,
  26. updatedAt: k.updatedAt
  27. }))
  28. },
  29. /**
  30. * Current API State
  31. */
  32. apiState () {
  33. return WIKI.config.api.isEnabled
  34. },
  35. /**
  36. * Fetch active authentication strategies
  37. */
  38. async strategies (obj, args, context, info) {
  39. let strategies = await WIKI.models.authentication.getStrategies(args.isEnabled)
  40. strategies = strategies.map(stg => {
  41. const strategyInfo = _.find(WIKI.data.authentication, ['key', stg.key]) || {}
  42. return {
  43. ...strategyInfo,
  44. ...stg,
  45. config: _.sortBy(_.transform(stg.config, (res, value, key) => {
  46. const configData = _.get(strategyInfo.props, key, false)
  47. if (configData) {
  48. res.push({
  49. key,
  50. value: JSON.stringify({
  51. ...configData,
  52. value
  53. })
  54. })
  55. }
  56. }, []), 'key')
  57. }
  58. })
  59. return strategies
  60. }
  61. },
  62. AuthenticationMutation: {
  63. /**
  64. * Create New API Key
  65. */
  66. async createApiKey (obj, args, context) {
  67. try {
  68. const key = await WIKI.models.apiKeys.createNewKey(args)
  69. await WIKI.auth.reloadApiKeys()
  70. WIKI.events.outbound.emit('reloadApiKeys')
  71. return {
  72. key,
  73. responseResult: graphHelper.generateSuccess('API Key created successfully')
  74. }
  75. } catch (err) {
  76. return graphHelper.generateError(err)
  77. }
  78. },
  79. /**
  80. * Perform Login
  81. */
  82. async login (obj, args, context) {
  83. try {
  84. const authResult = await WIKI.models.users.login(args, context)
  85. return {
  86. ...authResult,
  87. responseResult: graphHelper.generateSuccess('Login success')
  88. }
  89. } catch (err) {
  90. // LDAP Debug Flag
  91. if (args.strategy === 'ldap' && WIKI.config.flags.ldapdebug) {
  92. WIKI.logger.warn('LDAP LOGIN ERROR (c1): ', err)
  93. }
  94. return graphHelper.generateError(err)
  95. }
  96. },
  97. /**
  98. * Perform 2FA Login
  99. */
  100. async loginTFA (obj, args, context) {
  101. try {
  102. const authResult = await WIKI.models.users.loginTFA(args, context)
  103. return {
  104. ...authResult,
  105. responseResult: graphHelper.generateSuccess('TFA success')
  106. }
  107. } catch (err) {
  108. return graphHelper.generateError(err)
  109. }
  110. },
  111. /**
  112. * Perform Mandatory Password Change after Login
  113. */
  114. async loginChangePassword (obj, args, context) {
  115. try {
  116. const authResult = await WIKI.models.users.loginChangePassword(args, context)
  117. return {
  118. ...authResult,
  119. responseResult: graphHelper.generateSuccess('Password changed successfully')
  120. }
  121. } catch (err) {
  122. return graphHelper.generateError(err)
  123. }
  124. },
  125. /**
  126. * Register a new account
  127. */
  128. async register (obj, args, context) {
  129. try {
  130. await WIKI.models.users.register({ ...args, verify: true }, context)
  131. return {
  132. responseResult: graphHelper.generateSuccess('Registration success')
  133. }
  134. } catch (err) {
  135. return graphHelper.generateError(err)
  136. }
  137. },
  138. /**
  139. * Set API state
  140. */
  141. async setApiState (obj, args, context) {
  142. try {
  143. WIKI.config.api.isEnabled = args.enabled
  144. await WIKI.configSvc.saveToDb(['api'])
  145. return {
  146. responseResult: graphHelper.generateSuccess('API State changed successfully')
  147. }
  148. } catch (err) {
  149. return graphHelper.generateError(err)
  150. }
  151. },
  152. /**
  153. * Revoke an API key
  154. */
  155. async revokeApiKey (obj, args, context) {
  156. try {
  157. await WIKI.models.apiKeys.query().findById(args.id).patch({
  158. isRevoked: true
  159. })
  160. await WIKI.auth.reloadApiKeys()
  161. WIKI.events.outbound.emit('reloadApiKeys')
  162. return {
  163. responseResult: graphHelper.generateSuccess('API Key revoked successfully')
  164. }
  165. } catch (err) {
  166. return graphHelper.generateError(err)
  167. }
  168. },
  169. /**
  170. * Update Authentication Strategies
  171. */
  172. async updateStrategies (obj, args, context) {
  173. try {
  174. WIKI.config.auth = {
  175. audience: _.get(args, 'config.audience', WIKI.config.auth.audience),
  176. tokenExpiration: _.get(args, 'config.tokenExpiration', WIKI.config.auth.tokenExpiration),
  177. tokenRenewal: _.get(args, 'config.tokenRenewal', WIKI.config.auth.tokenRenewal)
  178. }
  179. await WIKI.configSvc.saveToDb(['auth'])
  180. for (let str of args.strategies) {
  181. await WIKI.models.authentication.query().patch({
  182. isEnabled: str.isEnabled,
  183. config: _.reduce(str.config, (result, value, key) => {
  184. _.set(result, `${value.key}`, _.get(JSON.parse(value.value), 'v', null))
  185. return result
  186. }, {}),
  187. selfRegistration: str.selfRegistration,
  188. domainWhitelist: { v: str.domainWhitelist },
  189. autoEnrollGroups: { v: str.autoEnrollGroups }
  190. }).where('key', str.key)
  191. }
  192. await WIKI.auth.activateStrategies()
  193. WIKI.events.outbound.emit('reloadAuthStrategies')
  194. return {
  195. responseResult: graphHelper.generateSuccess('Strategies updated successfully')
  196. }
  197. } catch (err) {
  198. return graphHelper.generateError(err)
  199. }
  200. },
  201. /**
  202. * Generate New Authentication Public / Private Key Certificates
  203. */
  204. async regenerateCertificates (obj, args, context) {
  205. try {
  206. await WIKI.auth.regenerateCertificates()
  207. return {
  208. responseResult: graphHelper.generateSuccess('Certificates have been regenerated successfully.')
  209. }
  210. } catch (err) {
  211. return graphHelper.generateError(err)
  212. }
  213. },
  214. /**
  215. * Reset Guest User
  216. */
  217. async resetGuestUser (obj, args, context) {
  218. try {
  219. await WIKI.auth.resetGuestUser()
  220. return {
  221. responseResult: graphHelper.generateSuccess('Guest user has been reset successfully.')
  222. }
  223. } catch (err) {
  224. return graphHelper.generateError(err)
  225. }
  226. }
  227. },
  228. AuthenticationStrategy: {
  229. icon (ap, args) {
  230. return fs.readFile(path.join(WIKI.ROOTPATH, `assets/svg/auth-icon-${ap.key}.svg`), 'utf8').catch(err => {
  231. if (err.code === 'ENOENT') {
  232. return null
  233. }
  234. throw err
  235. })
  236. }
  237. }
  238. }