security-setting.js 54 KB

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