Просмотр исходного кода

Merge pull request #1558 from weseek/reactify-admin/create-local-security-container

Reactify admin/create local security container
Yuki Takei 6 лет назад
Родитель
Сommit
8f79b2e1d0

+ 4 - 2
src/client/js/app.jsx

@@ -66,6 +66,7 @@ import AdminBasicSecurityContainer from './services/AdminBasicSecurityContainer'
 import AdminGoogleSecurityContainer from './services/AdminGoogleSecurityContainer';
 import AdminGoogleSecurityContainer from './services/AdminGoogleSecurityContainer';
 import AdminGithubSecurityContainer from './services/AdminGithubSecurityConatainer';
 import AdminGithubSecurityContainer from './services/AdminGithubSecurityConatainer';
 import AdminTwitterSecurityContainer from './services/AdminTwitterSecurityContainer';
 import AdminTwitterSecurityContainer from './services/AdminTwitterSecurityContainer';
+import AdminLocalSecurityContainer from './services/AdminLocalSecurityContainer';
 
 
 const logger = loggerFactory('growi:app');
 const logger = loggerFactory('growi:app');
 
 
@@ -249,6 +250,7 @@ if (adminMarkDownSettingElem != null) {
 const adminSecuritySettingElem = document.getElementById('admin-security-setting');
 const adminSecuritySettingElem = document.getElementById('admin-security-setting');
 if (adminSecuritySettingElem != null) {
 if (adminSecuritySettingElem != null) {
   const adminGeneralSecurityContainer = new AdminGeneralSecurityContainer(appContainer);
   const adminGeneralSecurityContainer = new AdminGeneralSecurityContainer(appContainer);
+  const adminLocalSecurityContainer = new AdminLocalSecurityContainer(appContainer);
   const adminLdapSecurityContainer = new AdminLdapSecurityContainer(appContainer);
   const adminLdapSecurityContainer = new AdminLdapSecurityContainer(appContainer);
   const adminSamlSecurityContainer = new AdminSamlSecurityContainer(appContainer);
   const adminSamlSecurityContainer = new AdminSamlSecurityContainer(appContainer);
   const adminOidcSecurityContainer = new AdminOidcSecurityContainer(appContainer);
   const adminOidcSecurityContainer = new AdminOidcSecurityContainer(appContainer);
@@ -257,8 +259,8 @@ if (adminSecuritySettingElem != null) {
   const adminGithubSecurityContainer = new AdminGithubSecurityContainer(appContainer);
   const adminGithubSecurityContainer = new AdminGithubSecurityContainer(appContainer);
   const adminTwitterSecurityContainer = new AdminTwitterSecurityContainer(appContainer);
   const adminTwitterSecurityContainer = new AdminTwitterSecurityContainer(appContainer);
   const adminSecurityContainers = [
   const adminSecurityContainers = [
-    adminGeneralSecurityContainer, adminLdapSecurityContainer, adminSamlSecurityContainer, adminOidcSecurityContainer, adminBasicSecurityContainer,
-    adminGoogleSecurityContainer, adminGithubSecurityContainer, adminTwitterSecurityContainer,
+    adminGeneralSecurityContainer, adminLocalSecurityContainer, adminLdapSecurityContainer, adminSamlSecurityContainer,
+    adminOidcSecurityContainer, adminBasicSecurityContainer, adminGoogleSecurityContainer, adminGithubSecurityContainer, adminTwitterSecurityContainer,
   ];
   ];
   ReactDOM.render(
   ReactDOM.render(
     <Provider inject={[...injectableContainers, ...adminSecurityContainers]}>
     <Provider inject={[...injectableContainers, ...adminSecurityContainers]}>

+ 20 - 17
src/client/js/components/Admin/Security/LocalSecuritySetting.jsx

@@ -8,6 +8,7 @@ import { toastSuccess, toastError } from '../../../util/apiNotification';
 
 
 import AppContainer from '../../../services/AppContainer';
 import AppContainer from '../../../services/AppContainer';
 import AdminGeneralSecurityContainer from '../../../services/AdminGeneralSecurityContainer';
 import AdminGeneralSecurityContainer from '../../../services/AdminGeneralSecurityContainer';
+import AdminLocalSecurityContainer from '../../../services/AdminLocalSecurityContainer';
 
 
 class LocalSecuritySetting extends React.Component {
 class LocalSecuritySetting extends React.Component {
 
 
@@ -17,14 +18,14 @@ class LocalSecuritySetting extends React.Component {
     this.state = {
     this.state = {
       retrieveError: null,
       retrieveError: null,
     };
     };
-    this.putLocalSecuritySetting = this.putLocalSecuritySetting.bind(this);
+    this.onClickSubmit = this.onClickSubmit.bind(this);
   }
   }
 
 
   async componentDidMount() {
   async componentDidMount() {
-    const { adminGeneralSecurityContainer } = this.props;
+    const { adminLocalSecurityContainer } = this.props;
 
 
     try {
     try {
-      await adminGeneralSecurityContainer.retrieveSecurityData();
+      await adminLocalSecurityContainer.retrieveSecurityData();
     }
     }
     catch (err) {
     catch (err) {
       toastError(err);
       toastError(err);
@@ -33,10 +34,10 @@ class LocalSecuritySetting extends React.Component {
   }
   }
 
 
 
 
-  async putLocalSecuritySetting() {
-    const { t, adminGeneralSecurityContainer } = this.props;
+  async onClickSubmit() {
+    const { t, adminLocalSecurityContainer } = this.props;
     try {
     try {
-      await adminGeneralSecurityContainer.updateLocalSecuritySetting();
+      await adminLocalSecurityContainer.updateLocalSecuritySetting();
       toastSuccess(t('security_setting.updated_general_security_setting'));
       toastSuccess(t('security_setting.updated_general_security_setting'));
     }
     }
     catch (err) {
     catch (err) {
@@ -45,8 +46,8 @@ class LocalSecuritySetting extends React.Component {
   }
   }
 
 
   render() {
   render() {
-    const { t, adminGeneralSecurityContainer } = this.props;
-    const { registrationMode } = adminGeneralSecurityContainer.state;
+    const { t, adminGeneralSecurityContainer, adminLocalSecurityContainer } = this.props;
+    const { registrationMode } = adminLocalSecurityContainer.state;
 
 
     return (
     return (
       <React.Fragment>
       <React.Fragment>
@@ -105,7 +106,7 @@ class LocalSecuritySetting extends React.Component {
                         key="Open"
                         key="Open"
                         role="presentation"
                         role="presentation"
                         type="button"
                         type="button"
-                        onClick={() => { adminGeneralSecurityContainer.changeRegistrationMode('Open') }}
+                        onClick={() => { adminLocalSecurityContainer.changeRegistrationMode('Open') }}
                       >
                       >
                         <a role="menuitem">{t('security_setting.registration_mode.open')}</a>
                         <a role="menuitem">{t('security_setting.registration_mode.open')}</a>
                       </li>
                       </li>
@@ -113,7 +114,7 @@ class LocalSecuritySetting extends React.Component {
                         key="Restricted"
                         key="Restricted"
                         role="presentation"
                         role="presentation"
                         type="button"
                         type="button"
-                        onClick={() => { adminGeneralSecurityContainer.changeRegistrationMode('Restricted') }}
+                        onClick={() => { adminLocalSecurityContainer.changeRegistrationMode('Restricted') }}
                       >
                       >
                         <a role="menuitem">{t('security_setting.registration_mode.restricted')}</a>
                         <a role="menuitem">{t('security_setting.registration_mode.restricted')}</a>
                       </li>
                       </li>
@@ -121,7 +122,7 @@ class LocalSecuritySetting extends React.Component {
                         key="Closed"
                         key="Closed"
                         role="presentation"
                         role="presentation"
                         type="button"
                         type="button"
-                        onClick={() => { adminGeneralSecurityContainer.changeRegistrationMode('Closed') }}
+                        onClick={() => { adminLocalSecurityContainer.changeRegistrationMode('Closed') }}
                       >
                       >
                         <a role="menuitem">{t('security_setting.registration_mode.closed')}</a>
                         <a role="menuitem">{t('security_setting.registration_mode.closed')}</a>
                       </li>
                       </li>
@@ -141,8 +142,8 @@ class LocalSecuritySetting extends React.Component {
                     className="form-control"
                     className="form-control"
                     type="textarea"
                     type="textarea"
                     name="registrationWhiteList"
                     name="registrationWhiteList"
-                    value={adminGeneralSecurityContainer.state.registrationWhiteList}
-                    onChange={e => adminGeneralSecurityContainer.changeRegistrationWhiteList(e.target.value)}
+                    value={adminLocalSecurityContainer.state.registrationWhiteList}
+                    onChange={e => adminLocalSecurityContainer.changeRegistrationWhiteList(e.target.value)}
                   />
                   />
                   <p className="help-block small">{t('security_setting.restrict_emails')}<br />{t('security_setting.for_instance')}
                   <p className="help-block small">{t('security_setting.restrict_emails')}<br />{t('security_setting.for_instance')}
                     <code>@growi.org</code>{t('security_setting.only_those')}<br />
                     <code>@growi.org</code>{t('security_setting.only_those')}<br />
@@ -154,9 +155,10 @@ class LocalSecuritySetting extends React.Component {
           </div>
           </div>
         )}
         )}
 
 
-        {/*  TODO replace component */}
-        <div className="col-xs-offset-3 col-xs-6 mb-5">
-          <button type="submit" className="btn btn-primary" onClick={this.putLocalSecuritySetting}>{t('Update')}</button>
+        <div className="row my-3">
+          <div className="col-xs-offset-3 col-xs-5">
+            <button type="button" className="btn btn-primary" disabled={this.state.retrieveError != null} onClick={this.onClickSubmit}>{t('Update')}</button>
+          </div>
         </div>
         </div>
 
 
       </React.Fragment>
       </React.Fragment>
@@ -169,10 +171,11 @@ LocalSecuritySetting.propTypes = {
   t: PropTypes.func.isRequired, // i18next
   t: PropTypes.func.isRequired, // i18next
   appContainer: PropTypes.instanceOf(AppContainer).isRequired,
   appContainer: PropTypes.instanceOf(AppContainer).isRequired,
   adminGeneralSecurityContainer: PropTypes.instanceOf(AdminGeneralSecurityContainer).isRequired,
   adminGeneralSecurityContainer: PropTypes.instanceOf(AdminGeneralSecurityContainer).isRequired,
+  adminLocalSecurityContainer: PropTypes.instanceOf(AdminLocalSecurityContainer).isRequired,
 };
 };
 
 
 const LocalSecuritySettingWrapper = (props) => {
 const LocalSecuritySettingWrapper = (props) => {
-  return createSubscribedElement(LocalSecuritySetting, props, [AppContainer, AdminGeneralSecurityContainer]);
+  return createSubscribedElement(LocalSecuritySetting, props, [AppContainer, AdminGeneralSecurityContainer, AdminLocalSecurityContainer]);
 };
 };
 
 
 export default withTranslation()(LocalSecuritySettingWrapper);
 export default withTranslation()(LocalSecuritySettingWrapper);

+ 9 - 37
src/client/js/services/AdminGeneralSecurityContainer.js

@@ -27,8 +27,6 @@ export default class AdminGeneralSecurityContainer extends Container {
       useOnlyEnvVarsForSomeOptions: false,
       useOnlyEnvVarsForSomeOptions: false,
       appSiteUrl: appContainer.config.crowi.url || '',
       appSiteUrl: appContainer.config.crowi.url || '',
       isLocalEnabled: false,
       isLocalEnabled: false,
-      registrationMode: 'Open',
-      registrationWhiteList: '',
       isLdapEnabled: false,
       isLdapEnabled: false,
       isSamlEnabled: false,
       isSamlEnabled: false,
       isOidcEnabled: false,
       isOidcEnabled: false,
@@ -42,19 +40,22 @@ export default class AdminGeneralSecurityContainer extends Container {
   }
   }
 
 
   async retrieveSecurityData() {
   async retrieveSecurityData() {
-    // TODO GW-956 separate local setting container
     const response = await this.appContainer.apiv3.get('/security-setting/');
     const response = await this.appContainer.apiv3.get('/security-setting/');
-    const { generalSetting, localSetting } = response.data.securityParams;
+    const { generalSetting, generalAuth } = response.data.securityParams;
     this.onIsWikiModeForced(generalSetting.wikiMode);
     this.onIsWikiModeForced(generalSetting.wikiMode);
     this.setState({
     this.setState({
-      currentRestrictGuestMode: generalSetting.restrictGuestMode || 'Deny',
       currentPageCompleteDeletionAuthority: generalSetting.pageCompleteDeletionAuthority || 'anyone',
       currentPageCompleteDeletionAuthority: generalSetting.pageCompleteDeletionAuthority || 'anyone',
       isHideRestrictedByOwner: generalSetting.hideRestrictedByOwner || false,
       isHideRestrictedByOwner: generalSetting.hideRestrictedByOwner || false,
       isHideRestrictedByGroup: generalSetting.hideRestrictedByGroup || false,
       isHideRestrictedByGroup: generalSetting.hideRestrictedByGroup || false,
       wikiMode: generalSetting.wikiMode || '',
       wikiMode: generalSetting.wikiMode || '',
-      isLocalEnabled: localSetting.isLocalEnabled || false,
-      registrationMode: localSetting.registrationMode || 'Open',
-      registrationWhiteList: localSetting.registrationWhiteList.join('\n') || '',
+      isLocalEnabled: generalAuth.isLocalEnabled || false,
+      isLdapEnabled: generalAuth.isLdapEnabled || false,
+      isSamlEnabled: generalAuth.isSamlEnabled || false,
+      isOidcEnabled: generalAuth.isOidcEnabled || false,
+      isBasicEnabled: generalAuth.isBasicEnabled || false,
+      isGoogleEnabled: generalAuth.isGoogleEnabled || false,
+      isGithubEnabled: generalAuth.isGithubEnabled || false,
+      isTwitterEnabled: generalAuth.isTwitterEnabled || false,
     });
     });
   }
   }
 
 
@@ -144,35 +145,6 @@ export default class AdminGeneralSecurityContainer extends Container {
     this.switchAuthentication('isLocalEnabled', 'local');
     this.switchAuthentication('isLocalEnabled', 'local');
   }
   }
 
 
-  /**
-   * Change registration mode
-   */
-  changeRegistrationMode(value) {
-    this.setState({ registrationMode: value });
-  }
-
-  /**
-   * Change registration white list
-   */
-  changeRegistrationWhiteList(value) {
-    this.setState({ registrationWhiteList: value });
-  }
-
-  /**
-  * update local security setting
-  */
-  async updateLocalSecuritySetting() {
-    let { registrationWhiteList } = this.state;
-    registrationWhiteList = Array.isArray(registrationWhiteList) ? registrationWhiteList : registrationWhiteList.split('\n');
-    const response = await this.appContainer.apiv3.put('/security-setting/local-setting', {
-      isLocalEnabled: this.state.isLocalEnabled,
-      registrationMode: this.state.registrationMode,
-      registrationWhiteList,
-    });
-    const { localSecuritySettingParams } = response.data;
-    return localSecuritySettingParams;
-  }
-
   /**
   /**
    * Switch LDAP enabled
    * Switch LDAP enabled
    */
    */

+ 79 - 0
src/client/js/services/AdminLocalSecurityContainer.js

@@ -0,0 +1,79 @@
+import { Container } from 'unstated';
+
+import loggerFactory from '@alias/logger';
+
+// eslint-disable-next-line no-unused-vars
+const logger = loggerFactory('growi:security:AdminLocalSecurityContainer');
+
+/**
+ * Service container for admin security page (LocalSecuritySetting.jsx)
+ * @extends {Container} unstated Container
+ */
+export default class AdminLocalSecurityContainer extends Container {
+
+  constructor(appContainer) {
+    super();
+
+    this.appContainer = appContainer;
+
+    this.state = {
+      registrationMode: 'Open',
+      registrationWhiteList: '',
+    };
+
+  }
+
+  async retrieveSecurityData() {
+    const response = await this.appContainer.apiv3.get('/security-setting/');
+    const { localSetting } = response.data.securityParams;
+    this.setState({
+      registrationMode: localSetting.registrationMode || 'Open',
+      registrationWhiteList: localSetting.registrationWhiteList.join('\n') || '',
+    });
+  }
+
+  /**
+   * Workaround for the mangling in production build to break constructor.name
+   */
+  static getClassName() {
+    return 'AdminLocalSecurityContainer';
+  }
+
+
+  /**
+   * Change registration mode
+   */
+  changeRegistrationMode(value) {
+    this.setState({ registrationMode: value });
+  }
+
+  /**
+   * Change registration white list
+   */
+  changeRegistrationWhiteList(value) {
+    this.setState({ registrationWhiteList: value });
+  }
+
+  /**
+   * update local security setting
+   */
+  async updateLocalSecuritySetting() {
+    let { registrationWhiteList } = this.state;
+    registrationWhiteList = Array.isArray(registrationWhiteList) ? registrationWhiteList : registrationWhiteList.split('\n');
+    const response = await this.appContainer.apiv3.put('/security-setting/local-setting', {
+      registrationMode: this.state.registrationMode,
+      registrationWhiteList,
+    });
+
+    const { localSettingParams } = response.data;
+
+    this.setState({
+      registrationMode: localSettingParams.registrationMode || 'Open',
+      registrationWhiteList: localSettingParams.registrationWhiteList || '',
+    });
+
+    return localSettingParams;
+  }
+
+
+}

+ 1 - 7
src/server/routes/apiv3/security-setting.js

@@ -27,7 +27,6 @@ const validator = {
     ]),
     ]),
   ],
   ],
   localSetting: [
   localSetting: [
-    body('isLocalEnabled').isBoolean(),
     body('registrationMode').isString(),
     body('registrationMode').isString(),
     body('registrationWhiteList').isArray(),
     body('registrationWhiteList').isArray(),
   ],
   ],
@@ -314,11 +313,11 @@ module.exports = (crowi) => {
         wikiMode: await crowi.configManager.getConfig('crowi', 'security:wikiMode'),
         wikiMode: await crowi.configManager.getConfig('crowi', 'security:wikiMode'),
       },
       },
       localSetting: {
       localSetting: {
-        isLocalEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-local:isEnabled'),
         registrationMode: await crowi.configManager.getConfig('crowi', 'security:registrationMode'),
         registrationMode: await crowi.configManager.getConfig('crowi', 'security:registrationMode'),
         registrationWhiteList: await crowi.configManager.getConfig('crowi', 'security:registrationWhiteList'),
         registrationWhiteList: await crowi.configManager.getConfig('crowi', 'security:registrationWhiteList'),
       },
       },
       generalAuth: {
       generalAuth: {
+        isLocalEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-local:isEnabled'),
         isLdapEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:isEnabled'),
         isLdapEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:isEnabled'),
         isSamlEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-saml:isEnabled'),
         isSamlEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-saml:isEnabled'),
         isOidcEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:isEnabled'),
         isOidcEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:isEnabled'),
@@ -378,19 +377,16 @@ module.exports = (crowi) => {
         isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-basic:isSameUsernameTreatedAsIdenticalUser'),
         isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-basic:isSameUsernameTreatedAsIdenticalUser'),
       },
       },
       googleOAuth: {
       googleOAuth: {
-        isGoogleStrategySetup: await crowi.passportService.isGoogleStrategySetup,
         googleClientId: await crowi.configManager.getConfig('crowi', 'security:passport-google:clientId'),
         googleClientId: await crowi.configManager.getConfig('crowi', 'security:passport-google:clientId'),
         googleClientSecret: await crowi.configManager.getConfig('crowi', 'security:passport-google:clientSecret'),
         googleClientSecret: await crowi.configManager.getConfig('crowi', 'security:passport-google:clientSecret'),
         isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-google:isSameUsernameTreatedAsIdenticalUser'),
         isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-google:isSameUsernameTreatedAsIdenticalUser'),
       },
       },
       githubOAuth: {
       githubOAuth: {
-        isGitHubStrategySetup: await crowi.passportService.isGitHubStrategySetup,
         githubClientId: await crowi.configManager.getConfig('crowi', 'security:passport-github:clientId'),
         githubClientId: await crowi.configManager.getConfig('crowi', 'security:passport-github:clientId'),
         githubClientSecret: await crowi.configManager.getConfig('crowi', 'security:passport-github:clientSecret'),
         githubClientSecret: await crowi.configManager.getConfig('crowi', 'security:passport-github:clientSecret'),
         isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-github:isSameUsernameTreatedAsIdenticalUser'),
         isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-github:isSameUsernameTreatedAsIdenticalUser'),
       },
       },
       twitterOAuth: {
       twitterOAuth: {
-        isTwitterStrategySetup: await crowi.passportService.isTwitterStrategySetup,
         twitterConsumerKey: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:consumerKey'),
         twitterConsumerKey: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:consumerKey'),
         twitterConsumerSecret: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:consumerSecret'),
         twitterConsumerSecret: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:consumerSecret'),
         isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:isSameUsernameTreatedAsIdenticalUser'),
         isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:isSameUsernameTreatedAsIdenticalUser'),
@@ -531,7 +527,6 @@ module.exports = (crowi) => {
    */
    */
   router.put('/local-setting', loginRequiredStrictly, adminRequired, csrf, validator.localSetting, ApiV3FormValidator, async(req, res) => {
   router.put('/local-setting', loginRequiredStrictly, adminRequired, csrf, validator.localSetting, ApiV3FormValidator, async(req, res) => {
     const requestParams = {
     const requestParams = {
-      'security:passport-local:isEnabled': req.body.isLocalEnabled,
       'security:registrationMode': req.body.registrationMode,
       'security:registrationMode': req.body.registrationMode,
       'security:registrationWhiteList': req.body.registrationWhiteList,
       'security:registrationWhiteList': req.body.registrationWhiteList,
     };
     };
@@ -539,7 +534,6 @@ module.exports = (crowi) => {
       await crowi.configManager.updateConfigsInTheSameNamespace('crowi', requestParams);
       await crowi.configManager.updateConfigsInTheSameNamespace('crowi', requestParams);
       await crowi.passportService.setupStrategyById('local');
       await crowi.passportService.setupStrategyById('local');
       const localSettingParams = {
       const localSettingParams = {
-        isLocalEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-local:isEnabled'),
         registrationMode: await crowi.configManager.getConfig('crowi', 'security:registrationMode'),
         registrationMode: await crowi.configManager.getConfig('crowi', 'security:registrationMode'),
         registrationWhiteList: await crowi.configManager.getConfig('crowi', 'security:registrationWhiteList'),
         registrationWhiteList: await crowi.configManager.getConfig('crowi', 'security:registrationWhiteList'),
       };
       };