security-setting.js 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222
  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 csrf = require('../../middlewares/csrf')(crowi);
  330. const addActivity = generateAddActivityMiddleware(crowi);
  331. const activityEvent = crowi.event('activity');
  332. async function updateAndReloadStrategySettings(authId, params) {
  333. const { configManager, passportService } = crowi;
  334. // update config without publishing S2sMessage
  335. await configManager.updateConfigsInTheSameNamespace('crowi', params, true);
  336. await passportService.setupStrategyById(authId);
  337. passportService.publishUpdatedMessage(authId);
  338. }
  339. /**
  340. * @swagger
  341. *
  342. * /_api/v3/security-setting/:
  343. * get:
  344. * tags: [SecuritySetting, apiv3]
  345. * description: Get security paramators
  346. * responses:
  347. * 200:
  348. * description: params of security
  349. * content:
  350. * application/json:
  351. * schema:
  352. * properties:
  353. * securityParams:
  354. * type: object
  355. * description: security params
  356. */
  357. router.get('/', loginRequiredStrictly, adminRequired, async(req, res) => {
  358. const securityParams = {
  359. generalSetting: {
  360. restrictGuestMode: crowi.aclService.getGuestModeValue(),
  361. pageDeletionAuthority: await crowi.configManager.getConfig('crowi', 'security:pageDeletionAuthority'),
  362. pageCompleteDeletionAuthority: await crowi.configManager.getConfig('crowi', 'security:pageCompleteDeletionAuthority'),
  363. pageRecursiveDeletionAuthority: await crowi.configManager.getConfig('crowi', 'security:pageRecursiveDeletionAuthority'),
  364. pageRecursiveCompleteDeletionAuthority: await crowi.configManager.getConfig('crowi', 'security:pageRecursiveCompleteDeletionAuthority'),
  365. hideRestrictedByOwner: await crowi.configManager.getConfig('crowi', 'security:list-policy:hideRestrictedByOwner'),
  366. hideRestrictedByGroup: await crowi.configManager.getConfig('crowi', 'security:list-policy:hideRestrictedByGroup'),
  367. wikiMode: await crowi.configManager.getConfig('crowi', 'security:wikiMode'),
  368. sessionMaxAge: await crowi.configManager.getConfig('crowi', 'security:sessionMaxAge'),
  369. },
  370. shareLinkSetting: {
  371. disableLinkSharing: await crowi.configManager.getConfig('crowi', 'security:disableLinkSharing'),
  372. },
  373. localSetting: {
  374. useOnlyEnvVarsForSomeOptions: await crowi.configManager.getConfig('crowi', 'security:passport-local:useOnlyEnvVarsForSomeOptions'),
  375. registrationMode: await crowi.configManager.getConfig('crowi', 'security:registrationMode'),
  376. registrationWhiteList: await crowi.configManager.getConfig('crowi', 'security:registrationWhiteList'),
  377. isPasswordResetEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-local:isPasswordResetEnabled'),
  378. isEmailAuthenticationEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-local:isEmailAuthenticationEnabled'),
  379. },
  380. generalAuth: {
  381. isLocalEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-local:isEnabled'),
  382. isLdapEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:isEnabled'),
  383. isSamlEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-saml:isEnabled'),
  384. isOidcEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:isEnabled'),
  385. isBasicEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-basic:isEnabled'),
  386. isGoogleEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-google:isEnabled'),
  387. isGitHubEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-github:isEnabled'),
  388. isTwitterEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:isEnabled'),
  389. },
  390. ldapAuth: {
  391. serverUrl: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:serverUrl'),
  392. isUserBind: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:isUserBind'),
  393. ldapBindDN: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:bindDN'),
  394. ldapBindDNPassword: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:bindDNPassword'),
  395. ldapSearchFilter: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:searchFilter'),
  396. ldapAttrMapUsername: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:attrMapUsername'),
  397. isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:isSameUsernameTreatedAsIdenticalUser'),
  398. ldapAttrMapMail: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:attrMapMail'),
  399. ldapAttrMapName: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:attrMapName'),
  400. ldapGroupSearchBase: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:groupSearchBase'),
  401. ldapGroupSearchFilter: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:groupSearchFilter'),
  402. ldapGroupDnProperty: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:groupDnProperty'),
  403. },
  404. samlAuth: {
  405. missingMandatoryConfigKeys: await crowi.passportService.getSamlMissingMandatoryConfigKeys(),
  406. useOnlyEnvVarsForSomeOptions: await crowi.configManager.getConfigFromEnvVars('crowi', 'security:passport-saml:useOnlyEnvVarsForSomeOptions'),
  407. samlEntryPoint: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:entryPoint'),
  408. samlEnvVarEntryPoint: await crowi.configManager.getConfigFromEnvVars('crowi', 'security:passport-saml:entryPoint'),
  409. samlIssuer: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:issuer'),
  410. samlEnvVarIssuer: await crowi.configManager.getConfigFromEnvVars('crowi', 'security:passport-saml:issuer'),
  411. samlCert: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:cert'),
  412. samlEnvVarCert: await crowi.configManager.getConfigFromEnvVars('crowi', 'security:passport-saml:cert'),
  413. samlAttrMapId: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:attrMapId'),
  414. samlEnvVarAttrMapId: await crowi.configManager.getConfigFromEnvVars('crowi', 'security:passport-saml:attrMapId'),
  415. samlAttrMapUsername: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:attrMapUsername'),
  416. samlEnvVarAttrMapUsername: await crowi.configManager.getConfigFromEnvVars('crowi', 'security:passport-saml:attrMapUsername'),
  417. samlAttrMapMail: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:attrMapMail'),
  418. samlEnvVarAttrMapMail: await crowi.configManager.getConfigFromEnvVars('crowi', 'security:passport-saml:attrMapMail'),
  419. samlAttrMapFirstName: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:attrMapFirstName'),
  420. samlEnvVarAttrMapFirstName: await crowi.configManager.getConfigFromEnvVars('crowi', 'security:passport-saml:attrMapFirstName'),
  421. samlAttrMapLastName: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:attrMapLastName'),
  422. samlEnvVarAttrMapLastName: await crowi.configManager.getConfigFromEnvVars('crowi', 'security:passport-saml:attrMapLastName'),
  423. isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-saml:isSameUsernameTreatedAsIdenticalUser'),
  424. isSameEmailTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-saml:isSameEmailTreatedAsIdenticalUser'),
  425. samlABLCRule: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:ABLCRule'),
  426. samlEnvVarABLCRule: await crowi.configManager.getConfigFromEnvVars('crowi', 'security:passport-saml:ABLCRule'),
  427. },
  428. oidcAuth: {
  429. oidcProviderName: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:providerName'),
  430. oidcIssuerHost: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:issuerHost'),
  431. oidcAuthorizationEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:authorizationEndpoint'),
  432. oidcTokenEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:tokenEndpoint'),
  433. oidcRevocationEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:revocationEndpoint'),
  434. oidcIntrospectionEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:introspectionEndpoint'),
  435. oidcUserInfoEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:userInfoEndpoint'),
  436. oidcEndSessionEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:endSessionEndpoint'),
  437. oidcRegistrationEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:registrationEndpoint'),
  438. oidcJWKSUri: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:jwksUri'),
  439. oidcClientId: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:clientId'),
  440. oidcClientSecret: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:clientSecret'),
  441. oidcAttrMapId: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:attrMapId'),
  442. oidcAttrMapUserName: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:attrMapUserName'),
  443. oidcAttrMapName: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:attrMapName'),
  444. oidcAttrMapEmail: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:attrMapMail'),
  445. isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:isSameUsernameTreatedAsIdenticalUser'),
  446. isSameEmailTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:isSameEmailTreatedAsIdenticalUser'),
  447. },
  448. basicAuth: {
  449. isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-basic:isSameUsernameTreatedAsIdenticalUser'),
  450. },
  451. googleOAuth: {
  452. googleClientId: await crowi.configManager.getConfig('crowi', 'security:passport-google:clientId'),
  453. googleClientSecret: await crowi.configManager.getConfig('crowi', 'security:passport-google:clientSecret'),
  454. isSameEmailTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-google:isSameEmailTreatedAsIdenticalUser'),
  455. },
  456. githubOAuth: {
  457. githubClientId: await crowi.configManager.getConfig('crowi', 'security:passport-github:clientId'),
  458. githubClientSecret: await crowi.configManager.getConfig('crowi', 'security:passport-github:clientSecret'),
  459. isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-github:isSameUsernameTreatedAsIdenticalUser'),
  460. },
  461. twitterOAuth: {
  462. twitterConsumerKey: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:consumerKey'),
  463. twitterConsumerSecret: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:consumerSecret'),
  464. isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:isSameUsernameTreatedAsIdenticalUser'),
  465. },
  466. };
  467. return res.apiv3({ securityParams });
  468. });
  469. /**
  470. * @swagger
  471. *
  472. * /_api/v3/security-setting/authentication/enabled:
  473. * put:
  474. * tags: [SecuritySetting, apiv3]
  475. * description: Update authentication isEnabled
  476. * requestBody:
  477. * required: true
  478. * content:
  479. * application/json:
  480. * schema:
  481. * type: object
  482. * properties:
  483. * isEnabled:
  484. * type: boolean
  485. * target:
  486. * type: string
  487. * responses:
  488. * 200:
  489. * description: Succeeded to enable authentication
  490. * content:
  491. * application/json:
  492. * schema:
  493. * type: object
  494. * description: updated param
  495. */
  496. router.put('/authentication/enabled', loginRequiredStrictly, adminRequired, csrf, validator.authenticationSetting, apiV3FormValidator, async(req, res) => {
  497. const { isEnabled, authId } = req.body;
  498. let setupStrategies = await crowi.passportService.getSetupStrategies();
  499. // Reflect request param
  500. setupStrategies = setupStrategies.filter(strategy => strategy !== authId);
  501. if (setupStrategies.length === 0) {
  502. return res.apiv3Err(new ErrorV3('Can not turn everything off'), 405);
  503. }
  504. const enableParams = { [`security:passport-${authId}:isEnabled`]: isEnabled };
  505. try {
  506. await updateAndReloadStrategySettings(authId, enableParams);
  507. const responseParams = {
  508. [`security:passport-${authId}:isEnabled`]: await crowi.configManager.getConfig('crowi', `security:passport-${authId}:isEnabled`),
  509. };
  510. return res.apiv3({ responseParams });
  511. }
  512. catch (err) {
  513. const msg = 'Error occurred in updating enable setting';
  514. logger.error('Error', err);
  515. return res.apiv3Err(new ErrorV3(msg, 'update-enable-setting failed'));
  516. }
  517. });
  518. /**
  519. * @swagger
  520. *
  521. * /_api/v3/security-setting/authentication:
  522. * get:
  523. * tags: [SecuritySetting, apiv3]
  524. * description: Get setup strategies for passport
  525. * responses:
  526. * 200:
  527. * description: params of setup strategies
  528. * content:
  529. * application/json:
  530. * schema:
  531. * properties:
  532. * setupStrategies:
  533. * type: array
  534. * description: setup strategies list
  535. * items:
  536. * type: string
  537. * description: setup strategie
  538. * example: ["local"]
  539. */
  540. router.get('/authentication/', loginRequiredStrictly, adminRequired, async(req, res) => {
  541. const setupStrategies = await crowi.passportService.getSetupStrategies();
  542. return res.apiv3({ setupStrategies });
  543. });
  544. /**
  545. * @swagger
  546. *
  547. * /_api/v3/security-setting/general-setting:
  548. * put:
  549. * tags: [SecuritySetting, apiv3]
  550. * description: Update GeneralSetting
  551. * requestBody:
  552. * required: true
  553. * content:
  554. * application/json:
  555. * schema:
  556. * $ref: '#/components/schemas/GeneralSetting'
  557. * responses:
  558. * 200:
  559. * description: Succeeded to update general Setting
  560. * content:
  561. * application/json:
  562. * schema:
  563. * $ref: '#/components/schemas/GeneralSetting'
  564. */
  565. router.put('/general-setting', loginRequiredStrictly, adminRequired, csrf, addActivity, validator.generalSetting, apiV3FormValidator, async(req, res) => {
  566. const updateData = {
  567. 'security:sessionMaxAge': parseInt(req.body.sessionMaxAge),
  568. 'security:restrictGuestMode': req.body.restrictGuestMode,
  569. 'security:pageDeletionAuthority': req.body.pageDeletionAuthority,
  570. 'security:pageRecursiveDeletionAuthority': req.body.pageRecursiveDeletionAuthority,
  571. 'security:pageCompleteDeletionAuthority': req.body.pageCompleteDeletionAuthority,
  572. 'security:pageRecursiveCompleteDeletionAuthority': req.body.pageRecursiveCompleteDeletionAuthority,
  573. 'security:list-policy:hideRestrictedByOwner': req.body.hideRestrictedByOwner,
  574. 'security:list-policy:hideRestrictedByGroup': req.body.hideRestrictedByGroup,
  575. };
  576. // Validate delete config
  577. const [singleAuthority1, recursiveAuthority1] = prepareDeleteConfigValuesForCalc(req.body.pageDeletionAuthority, req.body.pageRecursiveDeletionAuthority);
  578. // eslint-disable-next-line max-len
  579. const [singleAuthority2, recursiveAuthority2] = prepareDeleteConfigValuesForCalc(req.body.pageCompleteDeletionAuthority, req.body.pageRecursiveCompleteDeletionAuthority);
  580. const isDeleteConfigNormalized = validateDeleteConfigs(singleAuthority1, recursiveAuthority1)
  581. && validateDeleteConfigs(singleAuthority2, recursiveAuthority2);
  582. if (!isDeleteConfigNormalized) {
  583. return res.apiv3Err(new ErrorV3('Delete config values are not correct.', 'delete_config_not_normalized'));
  584. }
  585. const wikiMode = await crowi.configManager.getConfig('crowi', 'security:wikiMode');
  586. if (wikiMode === 'private' || wikiMode === 'public') {
  587. logger.debug('security:restrictGuestMode will not be changed because wiki mode is forced to set');
  588. delete updateData['security:restrictGuestMode'];
  589. }
  590. try {
  591. await crowi.configManager.updateConfigsInTheSameNamespace('crowi', updateData);
  592. const securitySettingParams = {
  593. sessionMaxAge: await crowi.configManager.getConfig('crowi', 'security:sessionMaxAge'),
  594. restrictGuestMode: await crowi.configManager.getConfig('crowi', 'security:restrictGuestMode'),
  595. pageDeletionAuthority: await crowi.configManager.getConfig('crowi', 'security:pageDeletionAuthority'),
  596. pageCompleteDeletionAuthority: await crowi.configManager.getConfig('crowi', 'security:pageCompleteDeletionAuthority'),
  597. pageRecursiveDeletionAuthority: await crowi.configManager.getConfig('crowi', 'security:pageRecursiveDeletionAuthority'),
  598. pageRecursiveCompleteDeletionAuthority: await crowi.configManager.getConfig('crowi', 'security:pageRecursiveCompleteDeletionAuthority'),
  599. hideRestrictedByOwner: await crowi.configManager.getConfig('crowi', 'security:list-policy:hideRestrictedByOwner'),
  600. hideRestrictedByGroup: await crowi.configManager.getConfig('crowi', 'security:list-policy:hideRestrictedByGroup'),
  601. };
  602. const parameters = { action: SupportedAction.ACTION_ADMIN_SECURITY_SETTINGS_UPDATE };
  603. activityEvent.emit('update', res.locals.activity._id, parameters);
  604. return res.apiv3({ securitySettingParams });
  605. }
  606. catch (err) {
  607. const msg = 'Error occurred in updating security setting';
  608. logger.error('Error', err);
  609. return res.apiv3Err(new ErrorV3(msg, 'update-secuirty-setting failed'));
  610. }
  611. });
  612. /**
  613. * @swagger
  614. *
  615. * /_api/v3/security-setting/share-link-setting:
  616. * put:
  617. * tags: [SecuritySetting, apiv3]
  618. * description: Update ShareLink Setting
  619. * requestBody:
  620. * required: true
  621. * content:
  622. * application/json:
  623. * schema:
  624. * $ref: '#/components/schemas/ShareLinkSetting'
  625. * responses:
  626. * 200:
  627. * description: Succeeded to update ShareLink Setting
  628. * content:
  629. * application/json:
  630. * schema:
  631. * $ref: '#/components/schemas/ShareLinkSetting'
  632. */
  633. router.put('/share-link-setting', loginRequiredStrictly, adminRequired, csrf, addActivity, validator.generalSetting, apiV3FormValidator, async(req, res) => {
  634. const updateData = {
  635. 'security:disableLinkSharing': req.body.disableLinkSharing,
  636. };
  637. try {
  638. await crowi.configManager.updateConfigsInTheSameNamespace('crowi', updateData);
  639. const securitySettingParams = {
  640. disableLinkSharing: crowi.configManager.getConfig('crowi', 'security:disableLinkSharing'),
  641. };
  642. // eslint-disable-next-line max-len
  643. const parameters = { action: updateData['security:disableLinkSharing'] ? SupportedAction.ACTION_ADMIN_REJECT_SHARE_LINK : SupportedAction.ACTION_ADMIN_PERMIT_SHARE_LINK };
  644. activityEvent.emit('update', res.locals.activity._id, parameters);
  645. return res.apiv3({ securitySettingParams });
  646. }
  647. catch (err) {
  648. const msg = 'Error occurred in updating security setting';
  649. logger.error('Error', err);
  650. return res.apiv3Err(new ErrorV3(msg, 'update-secuirty-setting failed'));
  651. }
  652. });
  653. /**
  654. * @swagger
  655. *
  656. * /_api/v3/security-setting/all-share-links:
  657. * get:
  658. * tags: [ShareLinkSettings, apiv3]
  659. * description: Get All ShareLinks at Share Link Setting
  660. * responses:
  661. * 200:
  662. * description: all share links
  663. * content:
  664. * application/json:
  665. * schema:
  666. * properties:
  667. * securityParams:
  668. * type: object
  669. * description: suceed to get all share links
  670. */
  671. router.get('/all-share-links/', loginRequiredStrictly, adminRequired, async(req, res) => {
  672. const ShareLink = crowi.model('ShareLink');
  673. const page = parseInt(req.query.page) || 1;
  674. const limit = 10;
  675. const linkQuery = {};
  676. try {
  677. const paginateResult = await ShareLink.paginate(
  678. linkQuery,
  679. {
  680. page,
  681. limit,
  682. populate: {
  683. path: 'relatedPage',
  684. select: 'path',
  685. },
  686. },
  687. );
  688. return res.apiv3({ paginateResult });
  689. }
  690. catch (err) {
  691. const msg = 'Error occured in get share link';
  692. logger.error('Error', err);
  693. return res.apiv3Err(new ErrorV3(msg, 'get-all-share-links-failed'));
  694. }
  695. });
  696. /**
  697. * @swagger
  698. *
  699. * /_api/v3/security-setting/all-share-links:
  700. * delete:
  701. * tags: [ShareLinkSettings, apiv3]
  702. * description: Delete All ShareLinks at Share Link Setting
  703. * responses:
  704. * 200:
  705. * description: succeed to delete all share links
  706. */
  707. router.delete('/all-share-links/', loginRequiredStrictly, adminRequired, async(req, res) => {
  708. const ShareLink = crowi.model('ShareLink');
  709. try {
  710. const removedAct = await ShareLink.remove({});
  711. const removeTotal = await removedAct.n;
  712. return res.apiv3({ removeTotal });
  713. }
  714. catch (err) {
  715. const msg = 'Error occured in delete all share links';
  716. logger.error('Error', err);
  717. return res.apiv3Err(new ErrorV3(msg, 'failed-to-delete-all-share-links'));
  718. }
  719. });
  720. /**
  721. * @swagger
  722. *
  723. * /_api/v3/security-setting/local-setting:
  724. * put:
  725. * tags: [LocalSetting, apiv3]
  726. * description: Update LocalSetting
  727. * requestBody:
  728. * required: true
  729. * content:
  730. * application/json:
  731. * schema:
  732. * $ref: '#/components/schemas/LocalSetting'
  733. * responses:
  734. * 200:
  735. * description: Succeeded to update local Setting
  736. * content:
  737. * application/json:
  738. * schema:
  739. * $ref: '#/components/schemas/LocalSetting'
  740. */
  741. router.put('/local-setting', loginRequiredStrictly, adminRequired, csrf, addActivity, validator.localSetting, apiV3FormValidator, async(req, res) => {
  742. const requestParams = {
  743. 'security:registrationMode': req.body.registrationMode,
  744. 'security:registrationWhiteList': req.body.registrationWhiteList,
  745. 'security:passport-local:isPasswordResetEnabled': req.body.isPasswordResetEnabled,
  746. 'security:passport-local:isEmailAuthenticationEnabled': req.body.isEmailAuthenticationEnabled,
  747. };
  748. try {
  749. await updateAndReloadStrategySettings('local', requestParams);
  750. const localSettingParams = {
  751. registrationMode: await crowi.configManager.getConfig('crowi', 'security:registrationMode'),
  752. registrationWhiteList: await crowi.configManager.getConfig('crowi', 'security:registrationWhiteList'),
  753. isPasswordResetEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-local:isPasswordResetEnabled'),
  754. isEmailAuthenticationEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-local:isEmailAuthenticationEnabled'),
  755. };
  756. const parameters = { action: SupportedAction.ACTION_ADMIN_AUTH_ID_PASS_UPDATE };
  757. activityEvent.emit('update', res.locals.activity._id, parameters);
  758. return res.apiv3({ localSettingParams });
  759. }
  760. catch (err) {
  761. const msg = 'Error occurred in updating local setting';
  762. logger.error('Error', err);
  763. return res.apiv3Err(new ErrorV3(msg, 'update-local-setting failed'));
  764. }
  765. });
  766. /**
  767. * @swagger
  768. *
  769. * /_api/v3/security-setting/ldap:
  770. * put:
  771. * tags: [SecuritySetting, apiv3]
  772. * description: Update LDAP setting
  773. * requestBody:
  774. * required: true
  775. * content:
  776. * application/json:
  777. * schema:
  778. * $ref: '#/components/schemas/LdapAuthSetting'
  779. * responses:
  780. * 200:
  781. * description: Succeeded to update LDAP setting
  782. * content:
  783. * application/json:
  784. * schema:
  785. * $ref: '#/components/schemas/LdapAuthSetting'
  786. */
  787. router.put('/ldap', loginRequiredStrictly, adminRequired, csrf, addActivity, validator.ldapAuth, apiV3FormValidator, async(req, res) => {
  788. const requestParams = {
  789. 'security:passport-ldap:serverUrl': req.body.serverUrl,
  790. 'security:passport-ldap:isUserBind': req.body.isUserBind,
  791. 'security:passport-ldap:bindDN': req.body.ldapBindDN,
  792. 'security:passport-ldap:bindDNPassword': req.body.ldapBindDNPassword,
  793. 'security:passport-ldap:searchFilter': req.body.ldapSearchFilter,
  794. 'security:passport-ldap:attrMapUsername': req.body.ldapAttrMapUsername,
  795. 'security:passport-ldap:isSameUsernameTreatedAsIdenticalUser': req.body.isSameUsernameTreatedAsIdenticalUser,
  796. 'security:passport-ldap:attrMapMail': req.body.ldapAttrMapMail,
  797. 'security:passport-ldap:attrMapName': req.body.ldapAttrMapName,
  798. 'security:passport-ldap:groupSearchBase': req.body.ldapGroupSearchBase,
  799. 'security:passport-ldap:groupSearchFilter': req.body.ldapGroupSearchFilter,
  800. 'security:passport-ldap:groupDnProperty': req.body.ldapGroupDnProperty,
  801. };
  802. try {
  803. await updateAndReloadStrategySettings('ldap', requestParams);
  804. const securitySettingParams = {
  805. serverUrl: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:serverUrl'),
  806. isUserBind: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:isUserBind'),
  807. ldapBindDN: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:bindDN'),
  808. ldapBindDNPassword: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:bindDNPassword'),
  809. ldapSearchFilter: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:searchFilter'),
  810. ldapAttrMapUsername: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:attrMapUsername'),
  811. isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:isSameUsernameTreatedAsIdenticalUser'),
  812. ldapAttrMapMail: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:attrMapMail'),
  813. ldapAttrMapName: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:attrMapName'),
  814. ldapGroupSearchBase: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:groupSearchBase'),
  815. ldapGroupSearchFilter: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:groupSearchFilter'),
  816. ldapGroupDnProperty: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:groupDnProperty'),
  817. };
  818. const parameters = { action: SupportedAction.ACTION_ADMIN_AUTH_LDAP_UPDATE };
  819. activityEvent.emit('update', res.locals.activity._id, parameters);
  820. return res.apiv3({ securitySettingParams });
  821. }
  822. catch (err) {
  823. const msg = 'Error occurred in updating SAML setting';
  824. logger.error('Error', err);
  825. return res.apiv3Err(new ErrorV3(msg, 'update-SAML-failed'));
  826. }
  827. });
  828. /**
  829. * @swagger
  830. *
  831. * /_api/v3/security-setting/saml:
  832. * put:
  833. * tags: [SecuritySetting, apiv3]
  834. * description: Update SAML setting
  835. * requestBody:
  836. * required: true
  837. * content:
  838. * application/json:
  839. * schema:
  840. * $ref: '#/components/schemas/SamlAuthSetting'
  841. * responses:
  842. * 200:
  843. * description: Succeeded to update SAML setting
  844. * content:
  845. * application/json:
  846. * schema:
  847. * $ref: '#/components/schemas/SamlAuthSetting'
  848. */
  849. router.put('/saml', loginRequiredStrictly, adminRequired, csrf, validator.samlAuth, apiV3FormValidator, async(req, res) => {
  850. // For the value of each mandatory items,
  851. // check whether it from the environment variables is empty and form value to update it is empty
  852. // validate the syntax of a attribute - based login control rule
  853. const invalidValues = [];
  854. for (const configKey of crowi.passportService.mandatoryConfigKeysForSaml) {
  855. const key = configKey.replace('security:passport-saml:', '');
  856. const formValue = req.body[key];
  857. if (crowi.configManager.getConfigFromEnvVars('crowi', configKey) === null && formValue == null) {
  858. const formItemName = req.t(`security_setting.form_item_name.${key}`);
  859. invalidValues.push(req.t('form_validation.required', formItemName));
  860. }
  861. }
  862. if (invalidValues.length !== 0) {
  863. return res.apiv3Err(req.t('form_validation.error_message'), 400, invalidValues);
  864. }
  865. const rule = req.body.ABLCRule;
  866. // Empty string disables attribute-based login control.
  867. // So, when rule is empty string, validation is passed.
  868. if (rule != null) {
  869. try {
  870. crowi.passportService.parseABLCRule(rule);
  871. }
  872. catch (err) {
  873. return res.apiv3Err(req.t('form_validation.invalid_syntax', req.t('security_setting.form_item_name.ABLCRule')), 400);
  874. }
  875. }
  876. const requestParams = {
  877. 'security:passport-saml:entryPoint': req.body.entryPoint,
  878. 'security:passport-saml:issuer': req.body.issuer,
  879. 'security:passport-saml:cert': req.body.cert,
  880. 'security:passport-saml:attrMapId': req.body.attrMapId,
  881. 'security:passport-saml:attrMapUsername': req.body.attrMapUsername,
  882. 'security:passport-saml:attrMapMail': req.body.attrMapMail,
  883. 'security:passport-saml:attrMapFirstName': req.body.attrMapFirstName,
  884. 'security:passport-saml:attrMapLastName': req.body.attrMapLastName,
  885. 'security:passport-saml:isSameUsernameTreatedAsIdenticalUser': req.body.isSameUsernameTreatedAsIdenticalUser,
  886. 'security:passport-saml:isSameEmailTreatedAsIdenticalUser': req.body.isSameEmailTreatedAsIdenticalUser,
  887. 'security:passport-saml:ABLCRule': req.body.ABLCRule,
  888. };
  889. try {
  890. await updateAndReloadStrategySettings('saml', requestParams);
  891. const securitySettingParams = {
  892. missingMandatoryConfigKeys: await crowi.passportService.getSamlMissingMandatoryConfigKeys(),
  893. samlEntryPoint: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:entryPoint'),
  894. samlIssuer: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:issuer'),
  895. samlCert: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:cert'),
  896. samlAttrMapId: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:attrMapId'),
  897. samlAttrMapUsername: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:attrMapUsername'),
  898. samlAttrMapMail: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:attrMapMail'),
  899. samlAttrMapFirstName: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:attrMapFirstName'),
  900. samlAttrMapLastName: await crowi.configManager.getConfigFromDB('crowi', 'security:passport-saml:attrMapLastName'),
  901. isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-saml:isSameUsernameTreatedAsIdenticalUser'),
  902. isSameEmailTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-saml:isSameEmailTreatedAsIdenticalUser'),
  903. samlABLCRule: await crowi.configManager.getConfig('crowi', 'security:passport-saml:ABLCRule'),
  904. };
  905. return res.apiv3({ securitySettingParams });
  906. }
  907. catch (err) {
  908. const msg = 'Error occurred in updating SAML setting';
  909. logger.error('Error', err);
  910. return res.apiv3Err(new ErrorV3(msg, 'update-SAML-failed'));
  911. }
  912. });
  913. /**
  914. * @swagger
  915. *
  916. * /_api/v3/security-setting/oidc:
  917. * put:
  918. * tags: [SecuritySetting, apiv3]
  919. * description: Update OpenID Connect setting
  920. * requestBody:
  921. * required: true
  922. * content:
  923. * application/json:
  924. * schema:
  925. * $ref: '#/components/schemas/OidcAuthSetting'
  926. * responses:
  927. * 200:
  928. * description: Succeeded to update OpenID Connect setting
  929. * content:
  930. * application/json:
  931. * schema:
  932. * $ref: '#/components/schemas/OidcAuthSetting'
  933. */
  934. router.put('/oidc', loginRequiredStrictly, adminRequired, csrf, validator.oidcAuth, apiV3FormValidator, async(req, res) => {
  935. const requestParams = {
  936. 'security:passport-oidc:providerName': req.body.oidcProviderName,
  937. 'security:passport-oidc:issuerHost': req.body.oidcIssuerHost,
  938. 'security:passport-oidc:authorizationEndpoint': req.body.oidcAuthorizationEndpoint,
  939. 'security:passport-oidc:tokenEndpoint': req.body.oidcTokenEndpoint,
  940. 'security:passport-oidc:revocationEndpoint': req.body.oidcRevocationEndpoint,
  941. 'security:passport-oidc:introspectionEndpoint': req.body.oidcIntrospectionEndpoint,
  942. 'security:passport-oidc:userInfoEndpoint': req.body.oidcUserInfoEndpoint,
  943. 'security:passport-oidc:endSessionEndpoint': req.body.oidcEndSessionEndpoint,
  944. 'security:passport-oidc:registrationEndpoint': req.body.oidcRegistrationEndpoint,
  945. 'security:passport-oidc:jwksUri': req.body.oidcJWKSUri,
  946. 'security:passport-oidc:clientId': req.body.oidcClientId,
  947. 'security:passport-oidc:clientSecret': req.body.oidcClientSecret,
  948. 'security:passport-oidc:attrMapId': req.body.oidcAttrMapId,
  949. 'security:passport-oidc:attrMapUserName': req.body.oidcAttrMapUserName,
  950. 'security:passport-oidc:attrMapName': req.body.oidcAttrMapName,
  951. 'security:passport-oidc:attrMapMail': req.body.oidcAttrMapEmail,
  952. 'security:passport-oidc:isSameUsernameTreatedAsIdenticalUser': req.body.isSameUsernameTreatedAsIdenticalUser,
  953. 'security:passport-oidc:isSameEmailTreatedAsIdenticalUser': req.body.isSameEmailTreatedAsIdenticalUser,
  954. };
  955. try {
  956. await updateAndReloadStrategySettings('oidc', requestParams);
  957. const securitySettingParams = {
  958. oidcProviderName: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:providerName'),
  959. oidcIssuerHost: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:issuerHost'),
  960. oidcAuthorizationEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:authorizationEndpoint'),
  961. oidcTokenEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:tokenEndpoint'),
  962. oidcRevocationEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:revocationEndpoint'),
  963. oidcIntrospectionEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:introspectionEndpoint'),
  964. oidcUserInfoEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:userInfoEndpoint'),
  965. oidcEndSessionEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:endSessionEndpoint'),
  966. oidcRegistrationEndpoint: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:registrationEndpoint'),
  967. oidcJWKSUri: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:jwksUri'),
  968. oidcClientId: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:clientId'),
  969. oidcClientSecret: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:clientSecret'),
  970. oidcAttrMapId: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:attrMapId'),
  971. oidcAttrMapUserName: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:attrMapUserName'),
  972. oidcAttrMapName: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:attrMapName'),
  973. oidcAttrMapEmail: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:attrMapMail'),
  974. isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:isSameUsernameTreatedAsIdenticalUser'),
  975. isSameEmailTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:isSameEmailTreatedAsIdenticalUser'),
  976. };
  977. return res.apiv3({ securitySettingParams });
  978. }
  979. catch (err) {
  980. const msg = 'Error occurred in updating OpenIDConnect';
  981. logger.error('Error', err);
  982. return res.apiv3Err(new ErrorV3(msg, 'update-OpenIDConnect-failed'));
  983. }
  984. });
  985. /**
  986. * @swagger
  987. *
  988. * /_api/v3/security-setting/basic:
  989. * put:
  990. * tags: [SecuritySetting, apiv3]
  991. * description: Update basic
  992. * requestBody:
  993. * required: true
  994. * content:
  995. * application/json:
  996. * schema:
  997. * $ref: '#/components/schemas/BasicAuthSetting'
  998. * responses:
  999. * 200:
  1000. * description: Succeeded to update basic
  1001. * content:
  1002. * application/json:
  1003. * schema:
  1004. * $ref: '#/components/schemas/BasicAuthSetting'
  1005. */
  1006. router.put('/basic', loginRequiredStrictly, adminRequired, csrf, validator.basicAuth, apiV3FormValidator, async(req, res) => {
  1007. const requestParams = {
  1008. 'security:passport-basic:isSameUsernameTreatedAsIdenticalUser': req.body.isSameUsernameTreatedAsIdenticalUser,
  1009. };
  1010. try {
  1011. await updateAndReloadStrategySettings('basic', requestParams);
  1012. const securitySettingParams = {
  1013. isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-basic:isSameUsernameTreatedAsIdenticalUser'),
  1014. };
  1015. return res.apiv3({ securitySettingParams });
  1016. }
  1017. catch (err) {
  1018. const msg = 'Error occurred in updating basicAuth';
  1019. logger.error('Error', err);
  1020. return res.apiv3Err(new ErrorV3(msg, 'update-basicOAuth-failed'));
  1021. }
  1022. });
  1023. /**
  1024. * @swagger
  1025. *
  1026. * /_api/v3/security-setting/google-oauth:
  1027. * put:
  1028. * tags: [SecuritySetting, apiv3]
  1029. * description: Update google OAuth
  1030. * requestBody:
  1031. * required: true
  1032. * content:
  1033. * application/json:
  1034. * schema:
  1035. * $ref: '#/components/schemas/GoogleOAuthSetting'
  1036. * responses:
  1037. * 200:
  1038. * description: Succeeded to google OAuth
  1039. * content:
  1040. * application/json:
  1041. * schema:
  1042. * $ref: '#/components/schemas/GoogleOAuthSetting'
  1043. */
  1044. router.put('/google-oauth', loginRequiredStrictly, adminRequired, csrf, validator.googleOAuth, apiV3FormValidator, async(req, res) => {
  1045. const requestParams = {
  1046. 'security:passport-google:clientId': req.body.googleClientId,
  1047. 'security:passport-google:clientSecret': req.body.googleClientSecret,
  1048. 'security:passport-google:isSameEmailTreatedAsIdenticalUser': req.body.isSameEmailTreatedAsIdenticalUser,
  1049. };
  1050. try {
  1051. await updateAndReloadStrategySettings('google', requestParams);
  1052. const securitySettingParams = {
  1053. googleClientId: await crowi.configManager.getConfig('crowi', 'security:passport-google:clientId'),
  1054. googleClientSecret: await crowi.configManager.getConfig('crowi', 'security:passport-google:clientSecret'),
  1055. isSameEmailTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-google:isSameEmailTreatedAsIdenticalUser'),
  1056. };
  1057. return res.apiv3({ securitySettingParams });
  1058. }
  1059. catch (err) {
  1060. const msg = 'Error occurred in updating googleOAuth';
  1061. logger.error('Error', err);
  1062. return res.apiv3Err(new ErrorV3(msg, 'update-googleOAuth-failed'));
  1063. }
  1064. });
  1065. /**
  1066. * @swagger
  1067. *
  1068. * /_api/v3/security-setting/github-oauth:
  1069. * put:
  1070. * tags: [SecuritySetting, apiv3]
  1071. * description: Update github OAuth
  1072. * requestBody:
  1073. * required: true
  1074. * content:
  1075. * application/json:
  1076. * schema:
  1077. * $ref: '#/components/schemas/GitHubOAuthSetting'
  1078. * responses:
  1079. * 200:
  1080. * description: Succeeded to github OAuth
  1081. * content:
  1082. * application/json:
  1083. * schema:
  1084. * $ref: '#/components/schemas/GitHubOAuthSetting'
  1085. */
  1086. router.put('/github-oauth', loginRequiredStrictly, adminRequired, csrf, validator.githubOAuth, apiV3FormValidator, async(req, res) => {
  1087. const requestParams = {
  1088. 'security:passport-github:clientId': req.body.githubClientId,
  1089. 'security:passport-github:clientSecret': req.body.githubClientSecret,
  1090. 'security:passport-github:isSameUsernameTreatedAsIdenticalUser': req.body.isSameUsernameTreatedAsIdenticalUser,
  1091. };
  1092. try {
  1093. await updateAndReloadStrategySettings('github', requestParams);
  1094. const securitySettingParams = {
  1095. githubClientId: await crowi.configManager.getConfig('crowi', 'security:passport-github:clientId'),
  1096. githubClientSecret: await crowi.configManager.getConfig('crowi', 'security:passport-github:clientSecret'),
  1097. isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-github:isSameUsernameTreatedAsIdenticalUser'),
  1098. };
  1099. return res.apiv3({ securitySettingParams });
  1100. }
  1101. catch (err) {
  1102. // reset strategy
  1103. await crowi.passportService.resetGitHubStrategy();
  1104. const msg = 'Error occurred in updating githubOAuth';
  1105. logger.error('Error', err);
  1106. return res.apiv3Err(new ErrorV3(msg, 'update-githubOAuth-failed'));
  1107. }
  1108. });
  1109. /**
  1110. * @swagger
  1111. *
  1112. * /_api/v3/security-setting/twitter-oauth:
  1113. * put:
  1114. * tags: [SecuritySetting, apiv3]
  1115. * description: Update twitter OAuth
  1116. * requestBody:
  1117. * required: true
  1118. * content:
  1119. * application/json:
  1120. * schema:
  1121. * $ref: '#/components/schemas/TwitterOAuthSetting'
  1122. * responses:
  1123. * 200:
  1124. * description: Succeeded to update twitter OAuth
  1125. * content:
  1126. * application/json:
  1127. * schema:
  1128. * $ref: '#/components/schemas/TwitterOAuthSetting'
  1129. */
  1130. router.put('/twitter-oauth', loginRequiredStrictly, adminRequired, csrf, validator.twitterOAuth, apiV3FormValidator, async(req, res) => {
  1131. let requestParams = {
  1132. 'security:passport-twitter:consumerKey': req.body.twitterConsumerKey,
  1133. 'security:passport-twitter:consumerSecret': req.body.twitterConsumerSecret,
  1134. 'security:passport-twitter:isSameUsernameTreatedAsIdenticalUser': req.body.isSameUsernameTreatedAsIdenticalUser,
  1135. };
  1136. requestParams = removeNullPropertyFromObject(requestParams);
  1137. try {
  1138. await updateAndReloadStrategySettings('twitter', requestParams);
  1139. const securitySettingParams = {
  1140. twitterConsumerId: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:consumerKey'),
  1141. twitterConsumerSecret: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:consumerSecret'),
  1142. isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:isSameUsernameTreatedAsIdenticalUser'),
  1143. };
  1144. return res.apiv3({ securitySettingParams });
  1145. }
  1146. catch (err) {
  1147. const msg = 'Error occurred in updating twitterOAuth';
  1148. logger.error('Error', err);
  1149. return res.apiv3Err(new ErrorV3(msg, 'update-twitterOAuth-failed'));
  1150. }
  1151. });
  1152. return router;
  1153. };