itizawa 6 tahun lalu
induk
melakukan
7a17cd5fbb

+ 24 - 24
src/client/js/components/Admin/Security/GithubSecuritySetting.jsx

@@ -58,34 +58,34 @@ class GithubSecurityManagement extends React.Component {
       <React.Fragment>
 
         <h2 className="alert-anchor border-bottom">
-          { t('security_setting.OAuth.GitHub.name') } { t('security_setting.configuration') }
+          {t('security_setting.OAuth.GitHub.name')} {t('security_setting.configuration')}
         </h2>
 
         {this.state.retrieveError != null && (
-        <div className="alert alert-danger">
-          <p>{t('Error occurred')} : {this.state.err}</p>
-        </div>
+          <div className="alert alert-danger">
+            <p>{t('Error occurred')} : {this.state.err}</p>
+          </div>
         )}
 
         <div className="row mb-5">
-          <strong className="col-xs-3 text-right">{ t('security_setting.OAuth.GitHub.name') }</strong>
+          <strong className="col-xs-3 text-right">{t('security_setting.OAuth.GitHub.name')}</strong>
           <div className="col-xs-6 text-left">
             <div className="checkbox checkbox-success">
               <input
                 id="isGithubEnabled"
                 type="checkbox"
-                checked={adminGeneralSecurityContainer.state.isGithubOAuthEnabled}
+                checked={adminGeneralSecurityContainer.state.isGitHubEnabled}
                 onChange={() => { adminGeneralSecurityContainer.switchIsGithubOAuthEnabled() }}
               />
               <label htmlFor="isGithubEnabled">
-                { t('security_setting.OAuth.GitHub.enable_github') }
+                {t('security_setting.OAuth.GitHub.enable_github')}
               </label>
             </div>
           </div>
         </div>
 
         <div className="row mb-5">
-          <label className="col-xs-3 text-right">{ t('security_setting.callback_URL') }</label>
+          <label className="col-xs-3 text-right">{t('security_setting.callback_URL')}</label>
           <div className="col-xs-6">
             <input
               className="form-control"
@@ -93,21 +93,21 @@ class GithubSecurityManagement extends React.Component {
               value={adminGithubSecurityContainer.state.appSiteUrl}
               readOnly
             />
-            <p className="help-block small">{ t('security_setting.desc_of_callback_URL', { AuthName: 'OAuth' }) }</p>
+            <p className="help-block small">{t('security_setting.desc_of_callback_URL', { AuthName: 'OAuth' })}</p>
             {!adminGeneralSecurityContainer.state.appSiteUrl && (
-            <div className="alert alert-danger">
-              <i
-                className="icon-exclamation"
-                // eslint-disable-next-line max-len
-                dangerouslySetInnerHTML={{ __html: t('security_setting.alert_siteUrl_is_not_set', { link: `<a href="/admin/app">${t('App settings')}<i class="icon-login"></i></a>` }) }}
-              />
-            </div>
+              <div className="alert alert-danger">
+                <i
+                  className="icon-exclamation"
+                  // eslint-disable-next-line max-len
+                  dangerouslySetInnerHTML={{ __html: t('security_setting.alert_siteUrl_is_not_set', { link: `<a href="/admin/app">${t('App settings')}<i class="icon-login"></i></a>` }) }}
+                />
+              </div>
             )}
           </div>
         </div>
 
 
-        {adminGeneralSecurityContainer.state.isGithubOAuthEnabled && (
+        {adminGeneralSecurityContainer.state.isGithubEnabled && (
           <React.Fragment>
 
             {!adminGithubSecurityContainer.state.isGitHubStrategySetup && (
@@ -117,7 +117,7 @@ class GithubSecurityManagement extends React.Component {
             )}
 
             <div className="row mb-5">
-              <label htmlFor="githubClientId" className="col-xs-3 text-right">{ t('security_setting.clientID') }</label>
+              <label htmlFor="githubClientId" className="col-xs-3 text-right">{t('security_setting.clientID')}</label>
               <div className="col-xs-6">
                 <input
                   className="form-control"
@@ -133,7 +133,7 @@ class GithubSecurityManagement extends React.Component {
             </div>
 
             <div className="row mb-5">
-              <label htmlFor="githubClientSecret" className="col-xs-3 text-right">{ t('security_setting.client_secret') }</label>
+              <label htmlFor="githubClientSecret" className="col-xs-3 text-right">{t('security_setting.client_secret')}</label>
               <div className="col-xs-6">
                 <input
                   className="form-control"
@@ -173,7 +173,7 @@ class GithubSecurityManagement extends React.Component {
 
         <div className="row my-3">
           <div className="col-xs-offset-3 col-xs-5">
-            <div className="btn btn-primary" disabled={this.state.retrieveError != null} onClick={this.onClickSubmit}>{ t('Update') }</div>
+            <div className="btn btn-primary" disabled={this.state.retrieveError != null} onClick={this.onClickSubmit}>{t('Update')}</div>
           </div>
         </div>
 
@@ -182,13 +182,13 @@ class GithubSecurityManagement extends React.Component {
         <div style={{ minHeight: '300px' }}>
           <h4>
             <i className="icon-question" aria-hidden="true"></i>
-            <a href="#collapseHelpForGithubOauth" data-toggle="collapse"> { t('security_setting.OAuth.how_to.github') }</a>
+            <a href="#collapseHelpForGithubOauth" data-toggle="collapse"> {t('security_setting.OAuth.how_to.github')}</a>
           </h4>
           <ol id="collapseHelpForGithubOauth" className="collapse">
             {/* eslint-disable-next-line max-len */}
-            <li dangerouslySetInnerHTML={{ __html:  t('security_setting.OAuth.GitHub.register_1', { link: '<a href="https://github.com/settings/developers" target=_blank>GitHub Developer Settings</a>' }) }} />
-            <li dangerouslySetInnerHTML={{ __html:  t('security_setting.OAuth.GitHub.register_2', { url: adminGithubSecurityContainer.state.callbackUrl }) }} />
-            <li dangerouslySetInnerHTML={{ __html:  t('security_setting.OAuth.GitHub.register_3') }} />
+            <li dangerouslySetInnerHTML={{ __html: t('security_setting.OAuth.GitHub.register_1', { link: '<a href="https://github.com/settings/developers" target=_blank>GitHub Developer Settings</a>' }) }} />
+            <li dangerouslySetInnerHTML={{ __html: t('security_setting.OAuth.GitHub.register_2', { url: adminGithubSecurityContainer.state.callbackUrl }) }} />
+            <li dangerouslySetInnerHTML={{ __html: t('security_setting.OAuth.GitHub.register_3') }} />
           </ol>
         </div>
 

+ 2 - 2
src/client/js/components/Admin/Security/GoogleSecuritySetting.jsx

@@ -74,7 +74,7 @@ class GoogleSecurityManagement extends React.Component {
               <input
                 id="isGoogleEnabled"
                 type="checkbox"
-                checked={adminGeneralSecurityContainer.state.isGoogleOAuthEnabled}
+                checked={adminGeneralSecurityContainer.state.isGoogleEnabled}
                 onChange={() => { adminGeneralSecurityContainer.switchIsGoogleOAuthEnabled() }}
               />
               <label htmlFor="isGoogleEnabled">
@@ -107,7 +107,7 @@ class GoogleSecurityManagement extends React.Component {
         </div>
 
 
-        {adminGeneralSecurityContainer.state.isGoogleOAuthEnabled && (
+        {adminGeneralSecurityContainer.state.isGoogleEnabled && (
           <React.Fragment>
 
             {!adminGoogleSecurityContainer.state.isGoogleStrategySetup && (

+ 26 - 26
src/client/js/components/Admin/Security/TwitterSecuritySetting.jsx

@@ -58,34 +58,34 @@ class TwitterSecurityManagement extends React.Component {
       <React.Fragment>
 
         <h2 className="alert-anchor border-bottom">
-          { t('security_setting.OAuth.Twitter.name') } { t('security_setting.configuration') }
+          {t('security_setting.OAuth.Twitter.name')} {t('security_setting.configuration')}
         </h2>
 
         {this.state.retrieveError != null && (
-        <div className="alert alert-danger">
-          <p>{t('Error occurred')} : {this.state.err}</p>
-        </div>
+          <div className="alert alert-danger">
+            <p>{t('Error occurred')} : {this.state.err}</p>
+          </div>
         )}
 
         <div className="row mb-5">
-          <strong className="col-xs-3 text-right">{ t('security_setting.OAuth.Twitter.name') }</strong>
+          <strong className="col-xs-3 text-right">{t('security_setting.OAuth.Twitter.name')}</strong>
           <div className="col-xs-6 text-left">
             <div className="checkbox checkbox-success">
               <input
                 id="isTwitterEnabled"
                 type="checkbox"
-                checked={adminGeneralSecurityContainer.state.isTwitterOAuthEnabled}
+                checked={adminGeneralSecurityContainer.state.isTwitterEnabled}
                 onChange={() => { adminGeneralSecurityContainer.switchIsTwitterOAuthEnabled() }}
               />
               <label htmlFor="isTwitterEnabled">
-                { t('security_setting.OAuth.Twitter.enable_twitter') }
+                {t('security_setting.OAuth.Twitter.enable_twitter')}
               </label>
             </div>
           </div>
         </div>
 
         <div className="row mb-5">
-          <label className="col-xs-3 text-right">{ t('security_setting.callback_URL') }</label>
+          <label className="col-xs-3 text-right">{t('security_setting.callback_URL')}</label>
           <div className="col-xs-6">
             <input
               className="form-control"
@@ -93,21 +93,21 @@ class TwitterSecurityManagement extends React.Component {
               value={adminTwitterSecurityContainer.state.callbackUrl}
               readOnly
             />
-            <p className="help-block small">{ t('security_setting.desc_of_callback_URL', { AuthName: 'OAuth' }) }</p>
+            <p className="help-block small">{t('security_setting.desc_of_callback_URL', { AuthName: 'OAuth' })}</p>
             {!adminGeneralSecurityContainer.state.appSiteUrl && (
-            <div className="alert alert-danger">
-              <i
-                className="icon-exclamation"
-                // eslint-disable-next-line max-len
-                dangerouslySetInnerHTML={{ __html: t('security_setting.alert_siteUrl_is_not_set', { link: `<a href="/admin/app">${t('App settings')}<i class="icon-login"></i></a>` }) }}
-              />
-            </div>
+              <div className="alert alert-danger">
+                <i
+                  className="icon-exclamation"
+                  // eslint-disable-next-line max-len
+                  dangerouslySetInnerHTML={{ __html: t('security_setting.alert_siteUrl_is_not_set', { link: `<a href="/admin/app">${t('App settings')}<i class="icon-login"></i></a>` }) }}
+                />
+              </div>
             )}
           </div>
         </div>
 
 
-        {adminGeneralSecurityContainer.state.isTwitterOAuthEnabled && (
+        {adminGeneralSecurityContainer.state.isTwitterEnabled && (
           <React.Fragment>
 
             {!adminTwitterSecurityContainer.state.isTwitterStrategySetup && (
@@ -117,7 +117,7 @@ class TwitterSecurityManagement extends React.Component {
             )}
 
             <div className="row mb-5">
-              <label htmlFor="TwitterConsumerId" className="col-xs-3 text-right">{ t('security_setting.clientID') }</label>
+              <label htmlFor="TwitterConsumerId" className="col-xs-3 text-right">{t('security_setting.clientID')}</label>
               <div className="col-xs-6">
                 <input
                   className="form-control"
@@ -133,7 +133,7 @@ class TwitterSecurityManagement extends React.Component {
             </div>
 
             <div className="row mb-5">
-              <label htmlFor="TwitterConsumerSecret" className="col-xs-3 text-right">{ t('security_setting.client_secret') }</label>
+              <label htmlFor="TwitterConsumerSecret" className="col-xs-3 text-right">{t('security_setting.client_secret')}</label>
               <div className="col-xs-6">
                 <input
                   className="form-control"
@@ -173,7 +173,7 @@ class TwitterSecurityManagement extends React.Component {
 
         <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>
+            <button type="button" className="btn btn-primary" disabled={this.state.retrieveError != null} onClick={this.onClickSubmit}>{t('Update')}</button>
           </div>
         </div>
 
@@ -182,16 +182,16 @@ class TwitterSecurityManagement extends React.Component {
         <div style={{ minHeight: '300px' }}>
           <h4>
             <i className="icon-question" aria-hidden="true"></i>
-            <a href="#collapseHelpForTwitterOauth" data-toggle="collapse"> { t('security_setting.OAuth.how_to.twitter') }</a>
+            <a href="#collapseHelpForTwitterOauth" data-toggle="collapse"> {t('security_setting.OAuth.how_to.twitter')}</a>
           </h4>
           <ol id="collapseHelpForTwitterOauth" className="collapse">
             {/* eslint-disable-next-line max-len */}
-            <li dangerouslySetInnerHTML={{ __html:  t('security_setting.OAuth.Twitter.register_1', { link: '<a href="https://apps.twitter.com/" target=_blank>Twitter Application Management</a>' }) }} />
-            <li dangerouslySetInnerHTML={{ __html:  t('security_setting.OAuth.Twitter.register_2') }} />
-            <li dangerouslySetInnerHTML={{ __html:  t('security_setting.OAuth.Twitter.register_3') }} />
+            <li dangerouslySetInnerHTML={{ __html: t('security_setting.OAuth.Twitter.register_1', { link: '<a href="https://apps.twitter.com/" target=_blank>Twitter Application Management</a>' }) }} />
+            <li dangerouslySetInnerHTML={{ __html: t('security_setting.OAuth.Twitter.register_2') }} />
+            <li dangerouslySetInnerHTML={{ __html: t('security_setting.OAuth.Twitter.register_3') }} />
             {/* eslint-disable-next-line max-len */}
-            <li dangerouslySetInnerHTML={{ __html:  t('security_setting.OAuth.Twitter.register_4', { url: adminTwitterSecurityContainer.state.callbackUrl }) }} />
-            <li dangerouslySetInnerHTML={{ __html:  t('security_setting.OAuth.Twitter.register_5') }} />
+            <li dangerouslySetInnerHTML={{ __html: t('security_setting.OAuth.Twitter.register_4', { url: adminTwitterSecurityContainer.state.callbackUrl }) }} />
+            <li dangerouslySetInnerHTML={{ __html: t('security_setting.OAuth.Twitter.register_5') }} />
           </ol>
         </div>
 

+ 14 - 15
src/client/js/services/AdminGeneralSecurityContainer.js

@@ -33,9 +33,9 @@ export default class AdminGeneralSecurityContainer extends Container {
       isSamlEnabled: true,
       isOidcEnabled: true,
       isBasicEnabled: true,
-      isGoogleOAuthEnabled: true,
-      isGithubOAuthEnabled: true,
-      isTwitterOAuthEnabled: true,
+      isGoogleEnabled: true,
+      isGithubEnabled: true,
+      isTwitterEnabled: true,
     };
 
     this.onIsWikiModeForced = this.onIsWikiModeForced.bind(this);
@@ -124,14 +124,13 @@ export default class AdminGeneralSecurityContainer extends Container {
    * Switch authentication
    */
   async switchAuthentication(auth) {
-    const isEnabled = this.state[auth];
-    const target = auth.toLowerCase();
+    const isEnabled = !this.state[`is${auth}Enabled`];
     try {
       await this.appContainer.apiv3.put('/security-setting/authentication', {
         isEnabled,
-        target,
+        auth,
       });
-      this.setState({ [target]: isEnabled });
+      this.setState({ [`is${auth}Enabled`]: isEnabled });
     }
     catch (err) {
       toastError(err);
@@ -142,7 +141,7 @@ export default class AdminGeneralSecurityContainer extends Container {
    * Switch local enabled
    */
   async switchIsLocalEnabled() {
-    this.switchAuthentication('local');
+    this.switchAuthentication('Local');
   }
 
   /**
@@ -178,49 +177,49 @@ export default class AdminGeneralSecurityContainer extends Container {
    * Switch LDAP enabled
    */
   async switchIsLdapEnabled() {
-    this.switchAuthentication('ldap');
+    this.switchAuthentication('Ldap');
   }
 
   /**
    * Switch SAML enabled
    */
   async switchIsSamlEnabled() {
-    this.switchAuthentication('saml');
+    this.switchAuthentication('Saml');
   }
 
   /**
    * Switch Oidc enabled
    */
   async switchIsOidcEnabled() {
-    this.switchAuthentication('oidc');
+    this.switchAuthentication('Oidc');
   }
 
   /**
    * Switch Basic enabled
    */
   async switchIsBasicEnabled() {
-    this.switchAuthentication('basic');
+    this.switchAuthentication('Basic');
   }
 
   /**
    * Switch GoogleOAuth enabled
    */
   async switchIsGoogleOAuthEnabled() {
-    this.switchAuthentication('google');
+    this.switchAuthentication('Google');
   }
 
   /**
    * Switch GithubOAuth enabled
    */
   async switchIsGithubOAuthEnabled() {
-    this.switchAuthentication('github');
+    this.switchAuthentication('GitHub');
   }
 
   /**
    * Switch TwitterOAuth enabled
    */
   async switchIsTwitterOAuthEnabled() {
-    this.switchAuthentication('twitter');
+    this.switchAuthentication('Twitter');
   }
 
 }

+ 11 - 6
src/server/routes/apiv3/security-setting.js

@@ -22,8 +22,8 @@ const validator = {
   ],
   authenticationSetting: [
     body('isEnabled').isBoolean(),
-    body('target').isString().isIn([
-      'local', 'ldap', 'saml', 'oidc', 'basic', 'google', 'github', 'twitter',
+    body('auth').isString().isIn([
+      'Local', 'Ldap', 'Saml', 'Oidc', 'Basic', 'Google', 'GitHub', 'Twitter',
     ]),
   ],
   localSetting: [
@@ -427,22 +427,27 @@ module.exports = (crowi) => {
    *                  description: updated param
    */
   router.put('/authentication', loginRequiredStrictly, adminRequired, csrf, validator.authenticationSetting, ApiV3FormValidator, async(req, res) => {
-    const { isEnabled, target } = req.body;
+    const { isEnabled, auth } = req.body;
+    const authLowerCase = auth.toLowerCase();
 
     let setupStrategies = await crowi.passportService.getSetupStrategies();
 
     // Reflect request param
-    setupStrategies = setupStrategies.filter(strategy => strategy !== `passport-${target}`);
+    setupStrategies = setupStrategies.filter(strategy => strategy !== `passport-${authLowerCase}`);
 
     if (setupStrategies.length === 0) {
       return res.apiv3Err(new ErrorV3('Can not turn everything off'));
     }
 
-    const enableParams = { [`security:passport-${target}:isEnabled`]: isEnabled };
+    const enableParams = { [`security:passport-${authLowerCase}:isEnabled`]: isEnabled };
 
     try {
       await crowi.configManager.updateConfigsInTheSameNamespace('crowi', enableParams);
-      const responseParams = { [`security:passport-${target}:isEnabled`]: await crowi.configManager.getConfig('crowi', `security:passport-${target}:isEnabled`) };
+
+      await crowi.passportService.setupStrategyByAuth(auth);
+
+      const responseParams = { [`security:passport-${authLowerCase}:isEnabled`]: await crowi.configManager.getConfig('crowi', `security:passport-${authLowerCase}:isEnabled`) };
+
       return res.apiv3({ responseParams });
     }
     catch (err) {

+ 16 - 0
src/server/service/passport.js

@@ -1,3 +1,4 @@
+/* eslint-disable no-eval */
 const debug = require('debug')('growi:service:PassportService');
 const urljoin = require('url-join');
 const passport = require('passport');
@@ -104,6 +105,21 @@ class PassportService {
     return setupStrategies;
   }
 
+  /**
+   * setup strategy by target name
+   */
+  setupStrategyByAuth(auth) {
+
+    try {
+      eval(`this.reset${auth}Strategy()`);
+      eval(`this.setup${auth}Strategy()`);
+    }
+    catch (err) {
+      debug(err);
+      eval(`this.reset${auth}Strategy()`);
+    }
+  }
+
   /**
    * reset LocalStrategy
    *