security-setting.js 58 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231
  1. import { ErrorV3 } from '@growi/core';
  2. import { SupportedAction } from '~/interfaces/activity';
  3. import { PageDeleteConfigValue } from '~/interfaces/page-delete-config';
  4. import loggerFactory from '~/utils/logger';
  5. import { removeNullPropertyFromObject } from '~/utils/object-utils';
  6. import { validateDeleteConfigs, prepareDeleteConfigValuesForCalc } from '~/utils/page-delete-config';
  7. import { generateAddActivityMiddleware } from '../../middlewares/add-activity';
  8. import { apiV3FormValidator } from '../../middlewares/apiv3-form-validator';
  9. const logger = loggerFactory('growi:routes:apiv3:security-setting');
  10. const express = require('express');
  11. const router = express.Router();
  12. const { body } = require('express-validator');
  13. const validator = {
  14. generalSetting: [
  15. body('sessionMaxAge').optional({ checkFalsy: true }).trim().isInt(),
  16. body('restrictGuestMode').if(value => value != null).isString().isIn([
  17. 'Deny', 'Readonly',
  18. ]),
  19. body('pageCompleteDeletionAuthority').if(value => value != null).isString().isIn(Object.values(PageDeleteConfigValue)),
  20. body('hideRestrictedByOwner').if(value => value != null).isBoolean(),
  21. body('hideRestrictedByGroup').if(value => value != null).isBoolean(),
  22. ],
  23. shareLinkSetting: [
  24. body('disableLinkSharing').if(value => value != null).isBoolean(),
  25. ],
  26. authenticationSetting: [
  27. body('isEnabled').if(value => value != null).isBoolean(),
  28. body('authId').isString().isIn([
  29. 'local', 'ldap', 'saml', 'oidc', 'google', 'github', 'twitter',
  30. ]),
  31. ],
  32. localSetting: [
  33. body('registrationMode').isString().isIn([
  34. 'Open', 'Restricted', 'Closed',
  35. ]),
  36. body('registrationWhiteList').if(value => value != null).isArray().customSanitizer((value, { req }) => {
  37. return value.filter(email => email !== '');
  38. }),
  39. ],
  40. ldapAuth: [
  41. body('serverUrl').if(value => value != null).isString(),
  42. body('isUserBind').if(value => value != null).isBoolean(),
  43. body('ldapBindDN').if(value => value != null).isString(),
  44. body('ldapBindDNPassword').if(value => value != null).isString(),
  45. body('ldapSearchFilter').if(value => value != null).isString(),
  46. body('ldapAttrMapUsername').if(value => value != null).isString(),
  47. body('isSameUsernameTreatedAsIdenticalUser').if(value => value != null).isBoolean(),
  48. body('ldapAttrMapMail').if(value => value != null).isString(),
  49. body('ldapAttrMapName').if(value => value != null).isString(),
  50. body('ldapGroupSearchBase').if(value => value != null).isString(),
  51. body('ldapGroupSearchFilter').if(value => value != null).isString(),
  52. body('ldapGroupDnProperty').if(value => value != null).isString(),
  53. ],
  54. samlAuth: [
  55. body('entryPoint').if(value => value != null).isString(),
  56. body('issuer').if(value => value != null).isString(),
  57. body('cert').if(value => value != null).isString(),
  58. body('attrMapId').if(value => value != null).isString(),
  59. body('attrMapUsername').if(value => value != null).isString(),
  60. body('attrMapMail').if(value => value != null).isString(),
  61. body('attrMapFirstName').if(value => value != null).isString(),
  62. body('attrMapLastName').if(value => value != null).isString(),
  63. body('isSameUsernameTreatedAsIdenticalUser').if(value => value != null).isBoolean(),
  64. body('isSameEmailTreatedAsIdenticalUser').if(value => value != null).isBoolean(),
  65. body('ABLCRule').if(value => value != null).isString(),
  66. ],
  67. oidcAuth: [
  68. body('oidcProviderName').if(value => value != null).isString(),
  69. body('oidcIssuerHost').if(value => value != null).isString(),
  70. body('oidcAuthorizationEndpoint').if(value => value != null).isString(),
  71. body('oidcTokenEndpoint').if(value => value != null).isString(),
  72. body('oidcRevocationEndpoint').if(value => value != null).isString(),
  73. body('oidcIntrospectionEndpoint').if(value => value != null).isString(),
  74. body('oidcUserInfoEndpoint').if(value => value != null).isString(),
  75. body('oidcEndSessionEndpoint').if(value => value != null).isString(),
  76. body('oidcRegistrationEndpoint').if(value => value != null).isString(),
  77. body('oidcJWKSUri').if(value => value != null).isString(),
  78. body('oidcClientId').if(value => value != null).isString(),
  79. body('oidcClientSecret').if(value => value != null).isString(),
  80. body('oidcAttrMapId').if(value => value != null).isString(),
  81. body('oidcAttrMapUserName').if(value => value != null).isString(),
  82. body('oidcAttrMapEmail').if(value => value != null).isString(),
  83. body('isSameUsernameTreatedAsIdenticalUser').if(value => value != null).isBoolean(),
  84. body('isSameEmailTreatedAsIdenticalUser').if(value => value != null).isBoolean(),
  85. ],
  86. googleOAuth: [
  87. body('googleClientId').if(value => value != null).isString(),
  88. body('googleClientSecret').if(value => value != null).isString(),
  89. body('isSameUsernameTreatedAsIdenticalUser').if(value => value != null).isBoolean(),
  90. ],
  91. githubOAuth: [
  92. body('githubClientId').if(value => value != null).isString(),
  93. body('githubClientSecret').if(value => value != null).isString(),
  94. body('isSameUsernameTreatedAsIdenticalUser').if(value => value != null).isBoolean(),
  95. ],
  96. twitterOAuth: [
  97. body('twitterConsumerKey').if(value => value != null).isString(),
  98. body('twitterConsumerSecret').if(value => value != null).isString(),
  99. body('isSameUsernameTreatedAsIdenticalUser').if(value => value != null).isBoolean(),
  100. ],
  101. };
  102. /**
  103. * @swagger
  104. * tags:
  105. * name: SecuritySetting
  106. */
  107. /**
  108. * @swagger
  109. *
  110. * components:
  111. * schemas:
  112. * GeneralSetting:
  113. * type: object
  114. * properties:
  115. * restrictGuestMode:
  116. * type: string
  117. * description: type of restrictGuestMode
  118. * pageCompleteDeletionAuthority:
  119. * type: string
  120. * description: type of pageDeletionAuthority
  121. * hideRestrictedByOwner:
  122. * type: boolean
  123. * description: enable hide by owner
  124. * hideRestrictedByGroup:
  125. * type: boolean
  126. * description: enable hide by group
  127. * ShareLinkSetting:
  128. * type: object
  129. * properties:
  130. * disableLinkSharing:
  131. * type: boolean
  132. * description: disable link sharing
  133. * LocalSetting:
  134. * type: object
  135. * properties:
  136. * isLocalEnabled:
  137. * type: boolean
  138. * description: local setting mode
  139. * registrationMode:
  140. * type: string
  141. * description: type of registrationMode
  142. * registrationWhiteList:
  143. * type: array
  144. * description: array of regsitrationList
  145. * items:
  146. * type: string
  147. * description: registration whiteList
  148. * LdapAuthSetting:
  149. * type: object
  150. * properties:
  151. * serverUrl:
  152. * type: string
  153. * description: server url for ldap
  154. * isUserBind:
  155. * type: boolean
  156. * description: enable user bind
  157. * ldapBindDN:
  158. * type: string
  159. * description: the query used to bind with the directory service
  160. * ldapBindDNPassword:
  161. * type: string
  162. * description: the password that is entered in the login page will be used to bind
  163. * ldapSearchFilter:
  164. * type: string
  165. * description: the query used to locate the authenticated user
  166. * ldapAttrMapUsername:
  167. * type: string
  168. * description: specification of mappings for username when creating new users
  169. * isSameUsernameTreatedAsIdenticalUser:
  170. * type: boolean
  171. * description: local account automatically linked the user name matched
  172. * ldapAttrMapMail:
  173. * type: string
  174. * description: specification of mappings for mail address when creating new users
  175. * ldapAttrMapName:
  176. * type: string
  177. * description: Specification of mappings for full name address when creating new users
  178. * ldapGroupSearchBase:
  179. * type: string
  180. * description: the base DN from which to search for groups.
  181. * ldapGroupSearchFilter:
  182. * type: string
  183. * description: the query used to filter for groups
  184. * ldapGroupDnProperty:
  185. * type: string
  186. * description: The property of user object to use in dn interpolation of Group Search Filter
  187. * SamlAuthSetting:
  188. * type: object
  189. * properties:
  190. * samlEntryPoint:
  191. * type: string
  192. * description: entry point for saml
  193. * samlIssuer:
  194. * type: string
  195. * description: issuer for saml
  196. * samlCert:
  197. * type: string
  198. * description: certificate for saml
  199. * samlAttrMapId:
  200. * type: string
  201. * description: attribute mapping id for saml
  202. * samlAttrMapUserName:
  203. * type: string
  204. * description: attribute mapping user name for saml
  205. * samlAttrMapMail:
  206. * type: string
  207. * description: attribute mapping mail for saml
  208. * samlAttrMapFirstName:
  209. * type: string
  210. * description: attribute mapping first name for saml
  211. * samlAttrMapLastName:
  212. * type: string
  213. * description: attribute mapping last name for saml
  214. * isSameUsernameTreatedAsIdenticalUser:
  215. * type: boolean
  216. * description: local account automatically linked the user name matched
  217. * isSameEmailTreatedAsIdenticalUser:
  218. * type: boolean
  219. * description: local account automatically linked the email matched
  220. * samlABLCRule:
  221. * type: string
  222. * description: ABLCRule for saml
  223. * OidcAuthSetting:
  224. * type: object
  225. * properties:
  226. * oidcProviderName:
  227. * type: string
  228. * description: provider name for oidc
  229. * oidcIssuerHost:
  230. * type: string
  231. * description: issuer host for oidc
  232. * oidcAuthorizationEndpoint:
  233. * type: string
  234. * description: authorization endpoint for oidc
  235. * oidcTokenEndpoint:
  236. * type: string
  237. * description: token endpoint for oidc
  238. * oidcRevocationEndpoint:
  239. * type: string
  240. * description: revocation endpoint for oidc
  241. * oidcIntrospectionEndpoint:
  242. * type: string
  243. * description: introspection endpoint for oidc
  244. * oidcUserInfoEndpoint:
  245. * type: string
  246. * description: userinfo endpoint for oidc
  247. * oidcEndSessionEndpoint:
  248. * type: string
  249. * description: end session endpoint for oidc
  250. * oidcRegistrationEndpoint:
  251. * type: string
  252. * description: registration endpoint for oidc
  253. * oidcJWKSUri:
  254. * type: string
  255. * description: JSON Web Key Set URI for oidc
  256. * oidcClientId:
  257. * type: string
  258. * description: client id for oidc
  259. * oidcClientSecret:
  260. * type: string
  261. * description: client secret for oidc
  262. * oidcAttrMapId:
  263. * type: string
  264. * description: attr map id for oidc
  265. * oidcAttrMapUserName:
  266. * type: string
  267. * description: attr map username for oidc
  268. * oidcAttrMapName:
  269. * type: string
  270. * description: attr map name for oidc
  271. * oidcAttrMapMail:
  272. * type: string
  273. * description: attr map mail for oidc
  274. * isSameUsernameTreatedAsIdenticalUser:
  275. * type: boolean
  276. * description: local account automatically linked the user name matched
  277. * isSameEmailTreatedAsIdenticalUser:
  278. * type: boolean
  279. * description: local account automatically linked the email matched
  280. * GitHubOAuthSetting:
  281. * type: object
  282. * properties:
  283. * githubClientId:
  284. * type: string
  285. * description: key of comsumer
  286. * githubClientSecret:
  287. * type: string
  288. * description: password of comsumer
  289. * isSameUsernameTreatedAsIdenticalUser:
  290. * type: boolean
  291. * description: local account automatically linked the email matched
  292. * GoogleOAuthSetting:
  293. * type: object
  294. * properties:
  295. * googleClientId:
  296. * type: string
  297. * description: key of comsumer
  298. * googleClientSecret:
  299. * type: string
  300. * description: password of comsumer
  301. * isSameUsernameTreatedAsIdenticalUser:
  302. * type: boolean
  303. * description: local account automatically linked the email matched
  304. * TwitterOAuthSetting:
  305. * type: object
  306. * properties:
  307. * twitterConsumerKey:
  308. * type: string
  309. * description: key of comsumer
  310. * twitterConsumerSecret:
  311. * type: string
  312. * description: password of comsumer
  313. * isSameUsernameTreatedAsIdenticalUser:
  314. * type: boolean
  315. * description: local account automatically linked the email matched
  316. */
  317. module.exports = (crowi) => {
  318. const loginRequiredStrictly = require('../../middlewares/login-required')(crowi);
  319. const adminRequired = require('../../middlewares/admin-required')(crowi);
  320. const addActivity = generateAddActivityMiddleware(crowi);
  321. const activityEvent = crowi.event('activity');
  322. async function updateAndReloadStrategySettings(authId, params) {
  323. const { configManager, passportService } = crowi;
  324. // update config without publishing S2sMessage
  325. await configManager.updateConfigsInTheSameNamespace('crowi', params, true);
  326. await passportService.setupStrategyById(authId);
  327. passportService.publishUpdatedMessage(authId);
  328. }
  329. /**
  330. * @swagger
  331. *
  332. * /_api/v3/security-setting/:
  333. * get:
  334. * tags: [SecuritySetting, apiv3]
  335. * description: Get security paramators
  336. * responses:
  337. * 200:
  338. * description: params of security
  339. * content:
  340. * application/json:
  341. * schema:
  342. * properties:
  343. * securityParams:
  344. * type: object
  345. * description: security params
  346. */
  347. router.get('/', loginRequiredStrictly, adminRequired, async(req, res) => {
  348. const securityParams = {
  349. generalSetting: {
  350. restrictGuestMode: crowi.aclService.getGuestModeValue(),
  351. pageDeletionAuthority: await crowi.configManager.getConfig('crowi', 'security:pageDeletionAuthority'),
  352. pageCompleteDeletionAuthority: await crowi.configManager.getConfig('crowi', 'security:pageCompleteDeletionAuthority'),
  353. pageRecursiveDeletionAuthority: await crowi.configManager.getConfig('crowi', 'security:pageRecursiveDeletionAuthority'),
  354. pageRecursiveCompleteDeletionAuthority: await crowi.configManager.getConfig('crowi', 'security:pageRecursiveCompleteDeletionAuthority'),
  355. hideRestrictedByOwner: await crowi.configManager.getConfig('crowi', 'security:list-policy:hideRestrictedByOwner'),
  356. hideRestrictedByGroup: await crowi.configManager.getConfig('crowi', 'security:list-policy:hideRestrictedByGroup'),
  357. wikiMode: await crowi.configManager.getConfig('crowi', 'security:wikiMode'),
  358. sessionMaxAge: await crowi.configManager.getConfig('crowi', 'security:sessionMaxAge'),
  359. },
  360. shareLinkSetting: {
  361. disableLinkSharing: await crowi.configManager.getConfig('crowi', 'security:disableLinkSharing'),
  362. },
  363. localSetting: {
  364. useOnlyEnvVarsForSomeOptions: await crowi.configManager.getConfig('crowi', 'security:passport-local:useOnlyEnvVarsForSomeOptions'),
  365. registrationMode: await crowi.configManager.getConfig('crowi', 'security:registrationMode'),
  366. registrationWhiteList: await crowi.configManager.getConfig('crowi', 'security:registrationWhiteList'),
  367. isPasswordResetEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-local:isPasswordResetEnabled'),
  368. isEmailAuthenticationEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-local:isEmailAuthenticationEnabled'),
  369. },
  370. generalAuth: {
  371. isLocalEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-local:isEnabled'),
  372. isLdapEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:isEnabled'),
  373. isSamlEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-saml:isEnabled'),
  374. isOidcEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:isEnabled'),
  375. isGoogleEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-google:isEnabled'),
  376. isGitHubEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-github:isEnabled'),
  377. isTwitterEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:isEnabled'),
  378. },
  379. ldapAuth: {
  380. serverUrl: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:serverUrl'),
  381. isUserBind: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:isUserBind'),
  382. ldapBindDN: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:bindDN'),
  383. ldapBindDNPassword: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:bindDNPassword'),
  384. ldapSearchFilter: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:searchFilter'),
  385. ldapAttrMapUsername: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:attrMapUsername'),
  386. isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:isSameUsernameTreatedAsIdenticalUser'),
  387. ldapAttrMapMail: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:attrMapMail'),
  388. ldapAttrMapName: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:attrMapName'),
  389. ldapGroupSearchBase: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:groupSearchBase'),
  390. ldapGroupSearchFilter: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:groupSearchFilter'),
  391. ldapGroupDnProperty: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:groupDnProperty'),
  392. },
  393. samlAuth: {
  394. missingMandatoryConfigKeys: await crowi.passportService.getSamlMissingMandatoryConfigKeys(),
  395. useOnlyEnvVarsForSomeOptions: await crowi.configManager.getConfigFromEnvVars('crowi', 'security:passport-saml:useOnlyEnvVarsForSomeOptions'),
  396. samlEntryPoint: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:entryPoint'),
  397. samlEnvVarEntryPoint: await crowi.configManager.getConfigFromEnvVars('crowi', 'security:passport-saml:entryPoint'),
  398. samlIssuer: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:issuer'),
  399. samlEnvVarIssuer: await crowi.configManager.getConfigFromEnvVars('crowi', 'security:passport-saml:issuer'),
  400. samlCert: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:cert'),
  401. samlEnvVarCert: await crowi.configManager.getConfigFromEnvVars('crowi', 'security:passport-saml:cert'),
  402. samlAttrMapId: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:attrMapId'),
  403. samlEnvVarAttrMapId: await crowi.configManager.getConfigFromEnvVars('crowi', 'security:passport-saml:attrMapId'),
  404. samlAttrMapUsername: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:attrMapUsername'),
  405. samlEnvVarAttrMapUsername: await crowi.configManager.getConfigFromEnvVars('crowi', 'security:passport-saml:attrMapUsername'),
  406. samlAttrMapMail: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:attrMapMail'),
  407. samlEnvVarAttrMapMail: await crowi.configManager.getConfigFromEnvVars('crowi', 'security:passport-saml:attrMapMail'),
  408. samlAttrMapFirstName: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:attrMapFirstName'),
  409. samlEnvVarAttrMapFirstName: await crowi.configManager.getConfigFromEnvVars('crowi', 'security:passport-saml:attrMapFirstName'),
  410. samlAttrMapLastName: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:attrMapLastName'),
  411. samlEnvVarAttrMapLastName: await crowi.configManager.getConfigFromEnvVars('crowi', 'security:passport-saml:attrMapLastName'),
  412. isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-saml:isSameUsernameTreatedAsIdenticalUser'),
  413. isSameEmailTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-saml:isSameEmailTreatedAsIdenticalUser'),
  414. samlABLCRule: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:ABLCRule'),
  415. samlEnvVarABLCRule: await crowi.configManager.getConfigFromEnvVars('crowi', 'security:passport-saml:ABLCRule'),
  416. },
  417. oidcAuth: {
  418. oidcProviderName: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:providerName'),
  419. oidcIssuerHost: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:issuerHost'),
  420. oidcAuthorizationEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:authorizationEndpoint'),
  421. oidcTokenEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:tokenEndpoint'),
  422. oidcRevocationEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:revocationEndpoint'),
  423. oidcIntrospectionEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:introspectionEndpoint'),
  424. oidcUserInfoEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:userInfoEndpoint'),
  425. oidcEndSessionEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:endSessionEndpoint'),
  426. oidcRegistrationEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:registrationEndpoint'),
  427. oidcJWKSUri: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:jwksUri'),
  428. oidcClientId: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:clientId'),
  429. oidcClientSecret: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:clientSecret'),
  430. oidcAttrMapId: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:attrMapId'),
  431. oidcAttrMapUserName: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:attrMapUserName'),
  432. oidcAttrMapName: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:attrMapName'),
  433. oidcAttrMapEmail: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:attrMapMail'),
  434. isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:isSameUsernameTreatedAsIdenticalUser'),
  435. isSameEmailTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:isSameEmailTreatedAsIdenticalUser'),
  436. },
  437. googleOAuth: {
  438. googleClientId: await crowi.configManager.getConfig('crowi', 'security:passport-google:clientId'),
  439. googleClientSecret: await crowi.configManager.getConfig('crowi', 'security:passport-google:clientSecret'),
  440. isSameEmailTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-google:isSameEmailTreatedAsIdenticalUser'),
  441. },
  442. githubOAuth: {
  443. githubClientId: await crowi.configManager.getConfig('crowi', 'security:passport-github:clientId'),
  444. githubClientSecret: await crowi.configManager.getConfig('crowi', 'security:passport-github:clientSecret'),
  445. isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-github:isSameUsernameTreatedAsIdenticalUser'),
  446. },
  447. twitterOAuth: {
  448. twitterConsumerKey: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:consumerKey'),
  449. twitterConsumerSecret: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:consumerSecret'),
  450. isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:isSameUsernameTreatedAsIdenticalUser'),
  451. },
  452. };
  453. return res.apiv3({ securityParams });
  454. });
  455. /**
  456. * @swagger
  457. *
  458. * /_api/v3/security-setting/authentication/enabled:
  459. * put:
  460. * tags: [SecuritySetting, apiv3]
  461. * description: Update authentication isEnabled
  462. * requestBody:
  463. * required: true
  464. * content:
  465. * application/json:
  466. * schema:
  467. * type: object
  468. * properties:
  469. * isEnabled:
  470. * type: boolean
  471. * target:
  472. * type: string
  473. * responses:
  474. * 200:
  475. * description: Succeeded to enable authentication
  476. * content:
  477. * application/json:
  478. * schema:
  479. * type: object
  480. * description: updated param
  481. */
  482. // eslint-disable-next-line max-len
  483. router.put('/authentication/enabled', loginRequiredStrictly, adminRequired, addActivity, validator.authenticationSetting, apiV3FormValidator, async(req, res) => {
  484. const { isEnabled, authId } = req.body;
  485. let setupStrategies = await crowi.passportService.getSetupStrategies();
  486. const parameters = {};
  487. // Reflect request param
  488. setupStrategies = setupStrategies.filter(strategy => strategy !== authId);
  489. if (setupStrategies.length === 0) {
  490. return res.apiv3Err(new ErrorV3('Can not turn everything off'), 405);
  491. }
  492. const enableParams = { [`security:passport-${authId}:isEnabled`]: isEnabled };
  493. try {
  494. await updateAndReloadStrategySettings(authId, enableParams);
  495. const responseParams = {
  496. [`security:passport-${authId}:isEnabled`]: await crowi.configManager.getConfig('crowi', `security:passport-${authId}:isEnabled`),
  497. };
  498. switch (authId) {
  499. case 'local':
  500. if (isEnabled) {
  501. parameters.action = SupportedAction.ACTION_ADMIN_AUTH_ID_PASS_ENABLED;
  502. break;
  503. }
  504. parameters.action = SupportedAction.ACTION_ADMIN_AUTH_ID_PASS_DISABLED;
  505. break;
  506. case 'ldap':
  507. if (isEnabled) {
  508. parameters.action = SupportedAction.ACTION_ADMIN_AUTH_LDAP_ENABLED;
  509. break;
  510. }
  511. parameters.action = SupportedAction.ACTION_ADMIN_AUTH_LDAP_DISABLED;
  512. break;
  513. case 'saml':
  514. if (isEnabled) {
  515. parameters.action = SupportedAction.ACTION_ADMIN_AUTH_SAML_ENABLED;
  516. break;
  517. }
  518. parameters.action = SupportedAction.ACTION_ADMIN_AUTH_SAML_DISABLED;
  519. break;
  520. case 'oidc':
  521. if (isEnabled) {
  522. parameters.action = SupportedAction.ACTION_ADMIN_AUTH_OIDC_ENABLED;
  523. break;
  524. }
  525. parameters.action = SupportedAction.ACTION_ADMIN_AUTH_OIDC_DISABLED;
  526. break;
  527. case 'google':
  528. if (isEnabled) {
  529. parameters.action = SupportedAction.ACTION_ADMIN_AUTH_GOOGLE_ENABLED;
  530. break;
  531. }
  532. parameters.action = SupportedAction.ACTION_ADMIN_AUTH_GOOGLE_DISABLED;
  533. break;
  534. case 'github':
  535. if (isEnabled) {
  536. parameters.action = SupportedAction.ACTION_ADMIN_AUTH_GITHUB_ENABLED;
  537. break;
  538. }
  539. parameters.action = SupportedAction.ACTION_ADMIN_AUTH_GITHUB_DISABLED;
  540. break;
  541. case 'twitter':
  542. if (isEnabled) {
  543. parameters.action = SupportedAction.ACTION_ADMIN_AUTH_TWITTER_ENABLED;
  544. break;
  545. }
  546. parameters.action = SupportedAction.ACTION_ADMIN_AUTH_TWITTER_DISABLED;
  547. break;
  548. }
  549. activityEvent.emit('update', res.locals.activity._id, parameters);
  550. return res.apiv3({ responseParams });
  551. }
  552. catch (err) {
  553. const msg = 'Error occurred in updating enable setting';
  554. logger.error('Error', err);
  555. return res.apiv3Err(new ErrorV3(msg, 'update-enable-setting failed'));
  556. }
  557. });
  558. /**
  559. * @swagger
  560. *
  561. * /_api/v3/security-setting/authentication:
  562. * get:
  563. * tags: [SecuritySetting, apiv3]
  564. * description: Get setup strategies for passport
  565. * responses:
  566. * 200:
  567. * description: params of setup strategies
  568. * content:
  569. * application/json:
  570. * schema:
  571. * properties:
  572. * setupStrategies:
  573. * type: array
  574. * description: setup strategies list
  575. * items:
  576. * type: string
  577. * description: setup strategie
  578. * example: ["local"]
  579. */
  580. router.get('/authentication/', loginRequiredStrictly, adminRequired, async(req, res) => {
  581. const setupStrategies = await crowi.passportService.getSetupStrategies();
  582. return res.apiv3({ setupStrategies });
  583. });
  584. /**
  585. * @swagger
  586. *
  587. * /_api/v3/security-setting/general-setting:
  588. * put:
  589. * tags: [SecuritySetting, apiv3]
  590. * description: Update GeneralSetting
  591. * requestBody:
  592. * required: true
  593. * content:
  594. * application/json:
  595. * schema:
  596. * $ref: '#/components/schemas/GeneralSetting'
  597. * responses:
  598. * 200:
  599. * description: Succeeded to update general Setting
  600. * content:
  601. * application/json:
  602. * schema:
  603. * $ref: '#/components/schemas/GeneralSetting'
  604. */
  605. router.put('/general-setting', loginRequiredStrictly, adminRequired, addActivity, validator.generalSetting, apiV3FormValidator, async(req, res) => {
  606. const updateData = {
  607. 'security:sessionMaxAge': parseInt(req.body.sessionMaxAge),
  608. 'security:restrictGuestMode': req.body.restrictGuestMode,
  609. 'security:pageDeletionAuthority': req.body.pageDeletionAuthority,
  610. 'security:pageRecursiveDeletionAuthority': req.body.pageRecursiveDeletionAuthority,
  611. 'security:pageCompleteDeletionAuthority': req.body.pageCompleteDeletionAuthority,
  612. 'security:pageRecursiveCompleteDeletionAuthority': req.body.pageRecursiveCompleteDeletionAuthority,
  613. 'security:list-policy:hideRestrictedByOwner': req.body.hideRestrictedByOwner,
  614. 'security:list-policy:hideRestrictedByGroup': req.body.hideRestrictedByGroup,
  615. };
  616. // Validate delete config
  617. const [singleAuthority1, recursiveAuthority1] = prepareDeleteConfigValuesForCalc(req.body.pageDeletionAuthority, req.body.pageRecursiveDeletionAuthority);
  618. // eslint-disable-next-line max-len
  619. const [singleAuthority2, recursiveAuthority2] = prepareDeleteConfigValuesForCalc(req.body.pageCompleteDeletionAuthority, req.body.pageRecursiveCompleteDeletionAuthority);
  620. const isDeleteConfigNormalized = validateDeleteConfigs(singleAuthority1, recursiveAuthority1)
  621. && validateDeleteConfigs(singleAuthority2, recursiveAuthority2);
  622. if (!isDeleteConfigNormalized) {
  623. return res.apiv3Err(new ErrorV3('Delete config values are not correct.', 'delete_config_not_normalized'));
  624. }
  625. const wikiMode = await crowi.configManager.getConfig('crowi', 'security:wikiMode');
  626. if (wikiMode === 'private' || wikiMode === 'public') {
  627. logger.debug('security:restrictGuestMode will not be changed because wiki mode is forced to set');
  628. delete updateData['security:restrictGuestMode'];
  629. }
  630. try {
  631. await crowi.configManager.updateConfigsInTheSameNamespace('crowi', updateData);
  632. const securitySettingParams = {
  633. sessionMaxAge: await crowi.configManager.getConfig('crowi', 'security:sessionMaxAge'),
  634. restrictGuestMode: await crowi.configManager.getConfig('crowi', 'security:restrictGuestMode'),
  635. pageDeletionAuthority: await crowi.configManager.getConfig('crowi', 'security:pageDeletionAuthority'),
  636. pageCompleteDeletionAuthority: await crowi.configManager.getConfig('crowi', 'security:pageCompleteDeletionAuthority'),
  637. pageRecursiveDeletionAuthority: await crowi.configManager.getConfig('crowi', 'security:pageRecursiveDeletionAuthority'),
  638. pageRecursiveCompleteDeletionAuthority: await crowi.configManager.getConfig('crowi', 'security:pageRecursiveCompleteDeletionAuthority'),
  639. hideRestrictedByOwner: await crowi.configManager.getConfig('crowi', 'security:list-policy:hideRestrictedByOwner'),
  640. hideRestrictedByGroup: await crowi.configManager.getConfig('crowi', 'security:list-policy:hideRestrictedByGroup'),
  641. };
  642. const parameters = { action: SupportedAction.ACTION_ADMIN_SECURITY_SETTINGS_UPDATE };
  643. activityEvent.emit('update', res.locals.activity._id, parameters);
  644. return res.apiv3({ securitySettingParams });
  645. }
  646. catch (err) {
  647. const msg = 'Error occurred in updating security setting';
  648. logger.error('Error', err);
  649. return res.apiv3Err(new ErrorV3(msg, 'update-secuirty-setting failed'));
  650. }
  651. });
  652. /**
  653. * @swagger
  654. *
  655. * /_api/v3/security-setting/share-link-setting:
  656. * put:
  657. * tags: [SecuritySetting, apiv3]
  658. * description: Update ShareLink Setting
  659. * requestBody:
  660. * required: true
  661. * content:
  662. * application/json:
  663. * schema:
  664. * $ref: '#/components/schemas/ShareLinkSetting'
  665. * responses:
  666. * 200:
  667. * description: Succeeded to update ShareLink Setting
  668. * content:
  669. * application/json:
  670. * schema:
  671. * $ref: '#/components/schemas/ShareLinkSetting'
  672. */
  673. router.put('/share-link-setting', loginRequiredStrictly, adminRequired, addActivity, validator.generalSetting, apiV3FormValidator, async(req, res) => {
  674. const updateData = {
  675. 'security:disableLinkSharing': req.body.disableLinkSharing,
  676. };
  677. try {
  678. await crowi.configManager.updateConfigsInTheSameNamespace('crowi', updateData);
  679. const securitySettingParams = {
  680. disableLinkSharing: crowi.configManager.getConfig('crowi', 'security:disableLinkSharing'),
  681. };
  682. // eslint-disable-next-line max-len
  683. const parameters = { action: updateData['security:disableLinkSharing'] ? SupportedAction.ACTION_ADMIN_REJECT_SHARE_LINK : SupportedAction.ACTION_ADMIN_PERMIT_SHARE_LINK };
  684. activityEvent.emit('update', res.locals.activity._id, parameters);
  685. return res.apiv3({ securitySettingParams });
  686. }
  687. catch (err) {
  688. const msg = 'Error occurred in updating security setting';
  689. logger.error('Error', err);
  690. return res.apiv3Err(new ErrorV3(msg, 'update-secuirty-setting failed'));
  691. }
  692. });
  693. /**
  694. * @swagger
  695. *
  696. * /_api/v3/security-setting/all-share-links:
  697. * get:
  698. * tags: [ShareLinkSettings, apiv3]
  699. * description: Get All ShareLinks at Share Link Setting
  700. * responses:
  701. * 200:
  702. * description: all share links
  703. * content:
  704. * application/json:
  705. * schema:
  706. * properties:
  707. * securityParams:
  708. * type: object
  709. * description: suceed to get all share links
  710. */
  711. router.get('/all-share-links/', loginRequiredStrictly, adminRequired, async(req, res) => {
  712. const ShareLink = crowi.model('ShareLink');
  713. const page = parseInt(req.query.page) || 1;
  714. const limit = 10;
  715. const linkQuery = {};
  716. try {
  717. const paginateResult = await ShareLink.paginate(
  718. linkQuery,
  719. {
  720. page,
  721. limit,
  722. populate: {
  723. path: 'relatedPage',
  724. select: 'path',
  725. },
  726. },
  727. );
  728. return res.apiv3({ paginateResult });
  729. }
  730. catch (err) {
  731. const msg = 'Error occured in get share link';
  732. logger.error('Error', err);
  733. return res.apiv3Err(new ErrorV3(msg, 'get-all-share-links-failed'));
  734. }
  735. });
  736. /**
  737. * @swagger
  738. *
  739. * /_api/v3/security-setting/all-share-links:
  740. * delete:
  741. * tags: [ShareLinkSettings, apiv3]
  742. * description: Delete All ShareLinks at Share Link Setting
  743. * responses:
  744. * 200:
  745. * description: succeed to delete all share links
  746. */
  747. router.delete('/all-share-links/', loginRequiredStrictly, adminRequired, async(req, res) => {
  748. const ShareLink = crowi.model('ShareLink');
  749. try {
  750. const removedAct = await ShareLink.remove({});
  751. const removeTotal = await removedAct.n;
  752. return res.apiv3({ removeTotal });
  753. }
  754. catch (err) {
  755. const msg = 'Error occured in delete all share links';
  756. logger.error('Error', err);
  757. return res.apiv3Err(new ErrorV3(msg, 'failed-to-delete-all-share-links'));
  758. }
  759. });
  760. /**
  761. * @swagger
  762. *
  763. * /_api/v3/security-setting/local-setting:
  764. * put:
  765. * tags: [LocalSetting, apiv3]
  766. * description: Update LocalSetting
  767. * requestBody:
  768. * required: true
  769. * content:
  770. * application/json:
  771. * schema:
  772. * $ref: '#/components/schemas/LocalSetting'
  773. * responses:
  774. * 200:
  775. * description: Succeeded to update local Setting
  776. * content:
  777. * application/json:
  778. * schema:
  779. * $ref: '#/components/schemas/LocalSetting'
  780. */
  781. router.put('/local-setting', loginRequiredStrictly, adminRequired, addActivity, validator.localSetting, apiV3FormValidator, async(req, res) => {
  782. const requestParams = {
  783. 'security:registrationMode': req.body.registrationMode,
  784. 'security:registrationWhiteList': req.body.registrationWhiteList,
  785. 'security:passport-local:isPasswordResetEnabled': req.body.isPasswordResetEnabled,
  786. 'security:passport-local:isEmailAuthenticationEnabled': req.body.isEmailAuthenticationEnabled,
  787. };
  788. try {
  789. await updateAndReloadStrategySettings('local', requestParams);
  790. const localSettingParams = {
  791. registrationMode: await crowi.configManager.getConfig('crowi', 'security:registrationMode'),
  792. registrationWhiteList: await crowi.configManager.getConfig('crowi', 'security:registrationWhiteList'),
  793. isPasswordResetEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-local:isPasswordResetEnabled'),
  794. isEmailAuthenticationEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-local:isEmailAuthenticationEnabled'),
  795. };
  796. const parameters = { action: SupportedAction.ACTION_ADMIN_AUTH_ID_PASS_UPDATE };
  797. activityEvent.emit('update', res.locals.activity._id, parameters);
  798. return res.apiv3({ localSettingParams });
  799. }
  800. catch (err) {
  801. const msg = 'Error occurred in updating local setting';
  802. logger.error('Error', err);
  803. return res.apiv3Err(new ErrorV3(msg, 'update-local-setting failed'));
  804. }
  805. });
  806. /**
  807. * @swagger
  808. *
  809. * /_api/v3/security-setting/ldap:
  810. * put:
  811. * tags: [SecuritySetting, apiv3]
  812. * description: Update LDAP setting
  813. * requestBody:
  814. * required: true
  815. * content:
  816. * application/json:
  817. * schema:
  818. * $ref: '#/components/schemas/LdapAuthSetting'
  819. * responses:
  820. * 200:
  821. * description: Succeeded to update LDAP setting
  822. * content:
  823. * application/json:
  824. * schema:
  825. * $ref: '#/components/schemas/LdapAuthSetting'
  826. */
  827. router.put('/ldap', loginRequiredStrictly, adminRequired, addActivity, validator.ldapAuth, apiV3FormValidator, async(req, res) => {
  828. const requestParams = {
  829. 'security:passport-ldap:serverUrl': req.body.serverUrl,
  830. 'security:passport-ldap:isUserBind': req.body.isUserBind,
  831. 'security:passport-ldap:bindDN': req.body.ldapBindDN,
  832. 'security:passport-ldap:bindDNPassword': req.body.ldapBindDNPassword,
  833. 'security:passport-ldap:searchFilter': req.body.ldapSearchFilter,
  834. 'security:passport-ldap:attrMapUsername': req.body.ldapAttrMapUsername,
  835. 'security:passport-ldap:isSameUsernameTreatedAsIdenticalUser': req.body.isSameUsernameTreatedAsIdenticalUser,
  836. 'security:passport-ldap:attrMapMail': req.body.ldapAttrMapMail,
  837. 'security:passport-ldap:attrMapName': req.body.ldapAttrMapName,
  838. 'security:passport-ldap:groupSearchBase': req.body.ldapGroupSearchBase,
  839. 'security:passport-ldap:groupSearchFilter': req.body.ldapGroupSearchFilter,
  840. 'security:passport-ldap:groupDnProperty': req.body.ldapGroupDnProperty,
  841. };
  842. try {
  843. await updateAndReloadStrategySettings('ldap', requestParams);
  844. const securitySettingParams = {
  845. serverUrl: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:serverUrl'),
  846. isUserBind: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:isUserBind'),
  847. ldapBindDN: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:bindDN'),
  848. ldapBindDNPassword: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:bindDNPassword'),
  849. ldapSearchFilter: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:searchFilter'),
  850. ldapAttrMapUsername: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:attrMapUsername'),
  851. isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:isSameUsernameTreatedAsIdenticalUser'),
  852. ldapAttrMapMail: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:attrMapMail'),
  853. ldapAttrMapName: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:attrMapName'),
  854. ldapGroupSearchBase: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:groupSearchBase'),
  855. ldapGroupSearchFilter: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:groupSearchFilter'),
  856. ldapGroupDnProperty: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:groupDnProperty'),
  857. };
  858. const parameters = { action: SupportedAction.ACTION_ADMIN_AUTH_LDAP_UPDATE };
  859. activityEvent.emit('update', res.locals.activity._id, parameters);
  860. return res.apiv3({ securitySettingParams });
  861. }
  862. catch (err) {
  863. const msg = 'Error occurred in updating SAML setting';
  864. logger.error('Error', err);
  865. return res.apiv3Err(new ErrorV3(msg, 'update-SAML-failed'));
  866. }
  867. });
  868. /**
  869. * @swagger
  870. *
  871. * /_api/v3/security-setting/saml:
  872. * put:
  873. * tags: [SecuritySetting, apiv3]
  874. * description: Update SAML setting
  875. * requestBody:
  876. * required: true
  877. * content:
  878. * application/json:
  879. * schema:
  880. * $ref: '#/components/schemas/SamlAuthSetting'
  881. * responses:
  882. * 200:
  883. * description: Succeeded to update SAML setting
  884. * content:
  885. * application/json:
  886. * schema:
  887. * $ref: '#/components/schemas/SamlAuthSetting'
  888. */
  889. router.put('/saml', loginRequiredStrictly, adminRequired, addActivity, validator.samlAuth, apiV3FormValidator, async(req, res) => {
  890. // For the value of each mandatory items,
  891. // check whether it from the environment variables is empty and form value to update it is empty
  892. // validate the syntax of a attribute - based login control rule
  893. const invalidValues = [];
  894. for (const configKey of crowi.passportService.mandatoryConfigKeysForSaml) {
  895. const key = configKey.replace('security:passport-saml:', '');
  896. const formValue = req.body[key];
  897. if (crowi.configManager.getConfigFromEnvVars('crowi', configKey) === null && formValue == null) {
  898. const formItemName = req.t(`security_setting.form_item_name.${key}`);
  899. invalidValues.push(req.t('form_validation.required', formItemName));
  900. }
  901. }
  902. if (invalidValues.length !== 0) {
  903. return res.apiv3Err(req.t('form_validation.error_message'), 400, invalidValues);
  904. }
  905. const rule = req.body.ABLCRule;
  906. // Empty string disables attribute-based login control.
  907. // So, when rule is empty string, validation is passed.
  908. if (rule != null) {
  909. try {
  910. crowi.passportService.parseABLCRule(rule);
  911. }
  912. catch (err) {
  913. return res.apiv3Err(req.t('form_validation.invalid_syntax', req.t('security_settings.form_item_name.ABLCRule')), 400);
  914. }
  915. }
  916. const requestParams = {
  917. 'security:passport-saml:entryPoint': req.body.entryPoint,
  918. 'security:passport-saml:issuer': req.body.issuer,
  919. 'security:passport-saml:cert': req.body.cert,
  920. 'security:passport-saml:attrMapId': req.body.attrMapId,
  921. 'security:passport-saml:attrMapUsername': req.body.attrMapUsername,
  922. 'security:passport-saml:attrMapMail': req.body.attrMapMail,
  923. 'security:passport-saml:attrMapFirstName': req.body.attrMapFirstName,
  924. 'security:passport-saml:attrMapLastName': req.body.attrMapLastName,
  925. 'security:passport-saml:isSameUsernameTreatedAsIdenticalUser': req.body.isSameUsernameTreatedAsIdenticalUser,
  926. 'security:passport-saml:isSameEmailTreatedAsIdenticalUser': req.body.isSameEmailTreatedAsIdenticalUser,
  927. 'security:passport-saml:ABLCRule': req.body.ABLCRule,
  928. };
  929. try {
  930. await updateAndReloadStrategySettings('saml', requestParams);
  931. const securitySettingParams = {
  932. missingMandatoryConfigKeys: await crowi.passportService.getSamlMissingMandatoryConfigKeys(),
  933. samlEntryPoint: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:entryPoint'),
  934. samlIssuer: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:issuer'),
  935. samlCert: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:cert'),
  936. samlAttrMapId: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:attrMapId'),
  937. samlAttrMapUsername: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:attrMapUsername'),
  938. samlAttrMapMail: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:attrMapMail'),
  939. samlAttrMapFirstName: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:attrMapFirstName'),
  940. samlAttrMapLastName: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:attrMapLastName'),
  941. isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-saml:isSameUsernameTreatedAsIdenticalUser'),
  942. isSameEmailTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-saml:isSameEmailTreatedAsIdenticalUser'),
  943. samlABLCRule: await crowi.configManager.getConfig('crowi', 'security:passport-saml:ABLCRule'),
  944. };
  945. const parameters = { action: SupportedAction.ACTION_ADMIN_AUTH_SAML_UPDATE };
  946. activityEvent.emit('update', res.locals.activity._id, parameters);
  947. return res.apiv3({ securitySettingParams });
  948. }
  949. catch (err) {
  950. const msg = 'Error occurred in updating SAML setting';
  951. logger.error('Error', err);
  952. return res.apiv3Err(new ErrorV3(msg, 'update-SAML-failed'));
  953. }
  954. });
  955. /**
  956. * @swagger
  957. *
  958. * /_api/v3/security-setting/oidc:
  959. * put:
  960. * tags: [SecuritySetting, apiv3]
  961. * description: Update OpenID Connect setting
  962. * requestBody:
  963. * required: true
  964. * content:
  965. * application/json:
  966. * schema:
  967. * $ref: '#/components/schemas/OidcAuthSetting'
  968. * responses:
  969. * 200:
  970. * description: Succeeded to update OpenID Connect setting
  971. * content:
  972. * application/json:
  973. * schema:
  974. * $ref: '#/components/schemas/OidcAuthSetting'
  975. */
  976. router.put('/oidc', loginRequiredStrictly, adminRequired, addActivity, validator.oidcAuth, apiV3FormValidator, async(req, res) => {
  977. const requestParams = {
  978. 'security:passport-oidc:providerName': req.body.oidcProviderName,
  979. 'security:passport-oidc:issuerHost': req.body.oidcIssuerHost,
  980. 'security:passport-oidc:authorizationEndpoint': req.body.oidcAuthorizationEndpoint,
  981. 'security:passport-oidc:tokenEndpoint': req.body.oidcTokenEndpoint,
  982. 'security:passport-oidc:revocationEndpoint': req.body.oidcRevocationEndpoint,
  983. 'security:passport-oidc:introspectionEndpoint': req.body.oidcIntrospectionEndpoint,
  984. 'security:passport-oidc:userInfoEndpoint': req.body.oidcUserInfoEndpoint,
  985. 'security:passport-oidc:endSessionEndpoint': req.body.oidcEndSessionEndpoint,
  986. 'security:passport-oidc:registrationEndpoint': req.body.oidcRegistrationEndpoint,
  987. 'security:passport-oidc:jwksUri': req.body.oidcJWKSUri,
  988. 'security:passport-oidc:clientId': req.body.oidcClientId,
  989. 'security:passport-oidc:clientSecret': req.body.oidcClientSecret,
  990. 'security:passport-oidc:attrMapId': req.body.oidcAttrMapId,
  991. 'security:passport-oidc:attrMapUserName': req.body.oidcAttrMapUserName,
  992. 'security:passport-oidc:attrMapName': req.body.oidcAttrMapName,
  993. 'security:passport-oidc:attrMapMail': req.body.oidcAttrMapEmail,
  994. 'security:passport-oidc:isSameUsernameTreatedAsIdenticalUser': req.body.isSameUsernameTreatedAsIdenticalUser,
  995. 'security:passport-oidc:isSameEmailTreatedAsIdenticalUser': req.body.isSameEmailTreatedAsIdenticalUser,
  996. };
  997. try {
  998. await updateAndReloadStrategySettings('oidc', requestParams);
  999. const securitySettingParams = {
  1000. oidcProviderName: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:providerName'),
  1001. oidcIssuerHost: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:issuerHost'),
  1002. oidcAuthorizationEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:authorizationEndpoint'),
  1003. oidcTokenEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:tokenEndpoint'),
  1004. oidcRevocationEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:revocationEndpoint'),
  1005. oidcIntrospectionEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:introspectionEndpoint'),
  1006. oidcUserInfoEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:userInfoEndpoint'),
  1007. oidcEndSessionEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:endSessionEndpoint'),
  1008. oidcRegistrationEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:registrationEndpoint'),
  1009. oidcJWKSUri: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:jwksUri'),
  1010. oidcClientId: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:clientId'),
  1011. oidcClientSecret: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:clientSecret'),
  1012. oidcAttrMapId: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:attrMapId'),
  1013. oidcAttrMapUserName: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:attrMapUserName'),
  1014. oidcAttrMapName: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:attrMapName'),
  1015. oidcAttrMapEmail: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:attrMapMail'),
  1016. isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:isSameUsernameTreatedAsIdenticalUser'),
  1017. isSameEmailTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:isSameEmailTreatedAsIdenticalUser'),
  1018. };
  1019. const parameters = { action: SupportedAction.ACTION_ADMIN_AUTH_OIDC_UPDATE };
  1020. activityEvent.emit('update', res.locals.activity._id, parameters);
  1021. return res.apiv3({ securitySettingParams });
  1022. }
  1023. catch (err) {
  1024. const msg = 'Error occurred in updating OpenIDConnect';
  1025. logger.error('Error', err);
  1026. return res.apiv3Err(new ErrorV3(msg, 'update-OpenIDConnect-failed'));
  1027. }
  1028. });
  1029. /**
  1030. * @swagger
  1031. *
  1032. * /_api/v3/security-setting/google-oauth:
  1033. * put:
  1034. * tags: [SecuritySetting, apiv3]
  1035. * description: Update google OAuth
  1036. * requestBody:
  1037. * required: true
  1038. * content:
  1039. * application/json:
  1040. * schema:
  1041. * $ref: '#/components/schemas/GoogleOAuthSetting'
  1042. * responses:
  1043. * 200:
  1044. * description: Succeeded to google OAuth
  1045. * content:
  1046. * application/json:
  1047. * schema:
  1048. * $ref: '#/components/schemas/GoogleOAuthSetting'
  1049. */
  1050. router.put('/google-oauth', loginRequiredStrictly, adminRequired, addActivity, validator.googleOAuth, apiV3FormValidator, async(req, res) => {
  1051. const requestParams = {
  1052. 'security:passport-google:clientId': req.body.googleClientId,
  1053. 'security:passport-google:clientSecret': req.body.googleClientSecret,
  1054. 'security:passport-google:isSameEmailTreatedAsIdenticalUser': req.body.isSameEmailTreatedAsIdenticalUser,
  1055. };
  1056. try {
  1057. await updateAndReloadStrategySettings('google', requestParams);
  1058. const securitySettingParams = {
  1059. googleClientId: await crowi.configManager.getConfig('crowi', 'security:passport-google:clientId'),
  1060. googleClientSecret: await crowi.configManager.getConfig('crowi', 'security:passport-google:clientSecret'),
  1061. isSameEmailTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-google:isSameEmailTreatedAsIdenticalUser'),
  1062. };
  1063. const parameters = { action: SupportedAction.ACTION_ADMIN_AUTH_GOOGLE_UPDATE };
  1064. activityEvent.emit('update', res.locals.activity._id, parameters);
  1065. return res.apiv3({ securitySettingParams });
  1066. }
  1067. catch (err) {
  1068. const msg = 'Error occurred in updating googleOAuth';
  1069. logger.error('Error', err);
  1070. return res.apiv3Err(new ErrorV3(msg, 'update-googleOAuth-failed'));
  1071. }
  1072. });
  1073. /**
  1074. * @swagger
  1075. *
  1076. * /_api/v3/security-setting/github-oauth:
  1077. * put:
  1078. * tags: [SecuritySetting, apiv3]
  1079. * description: Update github OAuth
  1080. * requestBody:
  1081. * required: true
  1082. * content:
  1083. * application/json:
  1084. * schema:
  1085. * $ref: '#/components/schemas/GitHubOAuthSetting'
  1086. * responses:
  1087. * 200:
  1088. * description: Succeeded to github OAuth
  1089. * content:
  1090. * application/json:
  1091. * schema:
  1092. * $ref: '#/components/schemas/GitHubOAuthSetting'
  1093. */
  1094. router.put('/github-oauth', loginRequiredStrictly, adminRequired, addActivity, validator.githubOAuth, apiV3FormValidator, async(req, res) => {
  1095. const requestParams = {
  1096. 'security:passport-github:clientId': req.body.githubClientId,
  1097. 'security:passport-github:clientSecret': req.body.githubClientSecret,
  1098. 'security:passport-github:isSameUsernameTreatedAsIdenticalUser': req.body.isSameUsernameTreatedAsIdenticalUser,
  1099. };
  1100. try {
  1101. await updateAndReloadStrategySettings('github', requestParams);
  1102. const securitySettingParams = {
  1103. githubClientId: await crowi.configManager.getConfig('crowi', 'security:passport-github:clientId'),
  1104. githubClientSecret: await crowi.configManager.getConfig('crowi', 'security:passport-github:clientSecret'),
  1105. isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-github:isSameUsernameTreatedAsIdenticalUser'),
  1106. };
  1107. const parameters = { action: SupportedAction.ACTION_ADMIN_AUTH_GITHUB_UPDATE };
  1108. activityEvent.emit('update', res.locals.activity._id, parameters);
  1109. return res.apiv3({ securitySettingParams });
  1110. }
  1111. catch (err) {
  1112. // reset strategy
  1113. await crowi.passportService.resetGitHubStrategy();
  1114. const msg = 'Error occurred in updating githubOAuth';
  1115. logger.error('Error', err);
  1116. return res.apiv3Err(new ErrorV3(msg, 'update-githubOAuth-failed'));
  1117. }
  1118. });
  1119. /**
  1120. * @swagger
  1121. *
  1122. * /_api/v3/security-setting/twitter-oauth:
  1123. * put:
  1124. * tags: [SecuritySetting, apiv3]
  1125. * description: Update twitter OAuth
  1126. * requestBody:
  1127. * required: true
  1128. * content:
  1129. * application/json:
  1130. * schema:
  1131. * $ref: '#/components/schemas/TwitterOAuthSetting'
  1132. * responses:
  1133. * 200:
  1134. * description: Succeeded to update twitter OAuth
  1135. * content:
  1136. * application/json:
  1137. * schema:
  1138. * $ref: '#/components/schemas/TwitterOAuthSetting'
  1139. */
  1140. router.put('/twitter-oauth', loginRequiredStrictly, adminRequired, addActivity, validator.twitterOAuth, apiV3FormValidator, async(req, res) => {
  1141. let requestParams = {
  1142. 'security:passport-twitter:consumerKey': req.body.twitterConsumerKey,
  1143. 'security:passport-twitter:consumerSecret': req.body.twitterConsumerSecret,
  1144. 'security:passport-twitter:isSameUsernameTreatedAsIdenticalUser': req.body.isSameUsernameTreatedAsIdenticalUser,
  1145. };
  1146. requestParams = removeNullPropertyFromObject(requestParams);
  1147. try {
  1148. await updateAndReloadStrategySettings('twitter', requestParams);
  1149. const securitySettingParams = {
  1150. twitterConsumerId: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:consumerKey'),
  1151. twitterConsumerSecret: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:consumerSecret'),
  1152. isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:isSameUsernameTreatedAsIdenticalUser'),
  1153. };
  1154. const parameters = { action: SupportedAction.ACTION_ADMIN_AUTH_TWITTER_UPDATE };
  1155. activityEvent.emit('update', res.locals.activity._id, parameters);
  1156. return res.apiv3({ securitySettingParams });
  1157. }
  1158. catch (err) {
  1159. const msg = 'Error occurred in updating twitterOAuth';
  1160. logger.error('Error', err);
  1161. return res.apiv3Err(new ErrorV3(msg, 'update-twitterOAuth-failed'));
  1162. }
  1163. });
  1164. return router;
  1165. };