security-setting.js 60 KB

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