Sfoglia il codice sorgente

Merge pull request #1707 from weseek/reactify-admin/brushup-setupStrategies-display

Reactify admin/brushup setup strategies display
Yuki Takei 6 anni fa
parent
commit
03bdfd68c8

+ 1 - 0
resource/locales/en-US/translation.json

@@ -389,6 +389,7 @@
     "admin_and_author": "Admin and Author",
     "anyone": "Anyone",
     "Authentication mechanism settings": "Authentication Mechanism Settings",
+    "setup_is_not_yet_complete": "Setup is not yet complete",
     "alert_siteUrl_is_not_set": "'Site URL' is NOT set. Set it from the {{link}}",
     "xss_prevent_setting": "Prevent XSS(Cross Site Scripting)",
     "xss_prevent_setting_link": "Go to Markdown settings",

+ 1 - 0
resource/locales/ja/translation.json

@@ -386,6 +386,7 @@
     "admin_and_author": "管理者とページ作者が可能",
     "anyone": "誰でも可能",
     "Authentication mechanism settings": "認証機構設定",
+    "setup_is_not_yet_complete":"セットアップはまだ完了してません",
     "alert_siteUrl_is_not_set": "'サイトURL' が設定されていません。{{link}} から設定してください。",
     "xss_prevent_setting": "XSS(Cross Site Scripting)対策設定",
     "xss_prevent_setting_link": "マークダウン設定ページに移動",

+ 19 - 12
src/client/js/components/Admin/Security/BasicSecuritySetting.jsx

@@ -35,10 +35,11 @@ class BasicSecurityManagement extends React.Component {
   }
 
   async onClickSubmit() {
-    const { t, adminBasicSecurityContainer } = this.props;
+    const { t, adminBasicSecurityContainer, adminGeneralSecurityContainer } = this.props;
 
     try {
       await adminBasicSecurityContainer.updateBasicSetting();
+      await adminGeneralSecurityContainer.retrieveSetupStratedies();
       toastSuccess(t('security_setting.Basic.updated_basic'));
     }
     catch (err) {
@@ -48,6 +49,7 @@ class BasicSecurityManagement extends React.Component {
 
   render() {
     const { t, adminGeneralSecurityContainer, adminBasicSecurityContainer } = this.props;
+    const { isBasicEnabled } = adminGeneralSecurityContainer.state;
 
     if (this.state.isRetrieving) {
       return null;
@@ -56,7 +58,7 @@ class BasicSecurityManagement extends React.Component {
       <React.Fragment>
 
         <h2 className="alert-anchor border-bottom">
-          { t('security_setting.Basic.name') } { t('security_setting.configuration') }
+          { t('security_setting.Basic.name') }
         </h2>
 
         {this.state.retrieveError != null && (
@@ -66,7 +68,9 @@ class BasicSecurityManagement extends React.Component {
         )}
 
         <div className="row mb-5">
-          <strong className="col-xs-3 text-right">{ t('security_setting.Basic.name') }</strong>
+          <div className="col-xs-3 my-3 text-right">
+            <strong>{t('security_setting.Basic.name')}</strong>
+          </div>
           <div className="col-xs-6 text-left">
             <div className="checkbox checkbox-success">
               <input
@@ -85,10 +89,12 @@ class BasicSecurityManagement extends React.Component {
                 { t('security_setting.Basic.desc_2')}
               </small>
             </p>
+            {(!adminGeneralSecurityContainer.state.setupStrategies.includes('basic') && isBasicEnabled)
+            && <div className="label label-warning">{t('security_setting.setup_is_not_yet_complete')}</div>}
           </div>
         </div>
 
-        {adminGeneralSecurityContainer.state.isBasicEnabled && (
+        {isBasicEnabled && (
         <React.Fragment>
           <div className="row mb-5">
             <div className="col-xs-offset-3 col-xs-6 text-left">
@@ -109,16 +115,17 @@ class BasicSecurityManagement extends React.Component {
               </p>
             </div>
           </div>
-        </React.Fragment>
-        )}
 
-        <div className="row my-3">
-          <div className="col-xs-offset-4 col-xs-5">
-            <button type="button" className="btn btn-primary" disabled={adminBasicSecurityContainer.state.retrieveError != null} onClick={this.onClickSubmit}>
-              { t('Update') }
-            </button>
+          <div className="row my-3">
+            <div className="col-xs-offset-4 col-xs-5">
+              <button type="button" className="btn btn-primary" disabled={adminBasicSecurityContainer.state.retrieveError != null} onClick={this.onClickSubmit}>
+                {t('Update')}
+              </button>
+            </div>
           </div>
-        </div>
+
+        </React.Fragment>
+        )}
 
       </React.Fragment>
     );

+ 20 - 12
src/client/js/components/Admin/Security/GitHubSecuritySetting.jsx

@@ -35,10 +35,11 @@ class GitHubSecurityManagement extends React.Component {
   }
 
   async onClickSubmit() {
-    const { t, adminGitHubSecurityContainer } = this.props;
+    const { t, adminGitHubSecurityContainer, adminGeneralSecurityContainer } = this.props;
 
     try {
       await adminGitHubSecurityContainer.updateGitHubSetting();
+      await adminGeneralSecurityContainer.retrieveSetupStratedies();
       toastSuccess(t('security_setting.OAuth.GitHub.updated_github'));
     }
     catch (err) {
@@ -48,6 +49,7 @@ class GitHubSecurityManagement extends React.Component {
 
   render() {
     const { t, adminGeneralSecurityContainer, adminGitHubSecurityContainer } = this.props;
+    const { isGitHubEnabled } = adminGeneralSecurityContainer.state;
 
     if (this.state.isRetrieving) {
       return null;
@@ -57,7 +59,7 @@ 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')}
         </h2>
 
         {this.state.retrieveError != null && (
@@ -67,7 +69,9 @@ class GitHubSecurityManagement extends React.Component {
         )}
 
         <div className="row mb-5">
-          <strong className="col-xs-3 text-right">{t('security_setting.OAuth.GitHub.name')}</strong>
+          <div className="col-xs-3 my-3 text-right">
+            <strong>{t('security_setting.OAuth.GitHub.name')}</strong>
+          </div>
           <div className="col-xs-6 text-left">
             <div className="checkbox checkbox-success">
               <input
@@ -80,6 +84,8 @@ class GitHubSecurityManagement extends React.Component {
                 {t('security_setting.OAuth.GitHub.enable_github')}
               </label>
             </div>
+            {(!adminGeneralSecurityContainer.state.setupStrategies.includes('github') && isGitHubEnabled)
+              && <div className="label label-warning">{t('security_setting.setup_is_not_yet_complete')}</div>}
           </div>
         </div>
 
@@ -106,9 +112,11 @@ class GitHubSecurityManagement extends React.Component {
         </div>
 
 
-        {adminGeneralSecurityContainer.state.isGitHubEnabled && (
+        {isGitHubEnabled && (
           <React.Fragment>
 
+            <h3 className="border-bottom">{t('security_setting.configuration')}</h3>
+
             <div className="row mb-5">
               <label htmlFor="githubClientId" className="col-xs-3 text-right">{t('security_setting.clientID')}</label>
               <div className="col-xs-6">
@@ -161,17 +169,17 @@ class GitHubSecurityManagement extends React.Component {
               </div>
             </div>
 
+            <div className="row my-3">
+              <div className="col-xs-offset-3 col-xs-5">
+                <div className="btn btn-primary" disabled={adminGitHubSecurityContainer.state.retrieveError != null} onClick={this.onClickSubmit}>
+                  {t('Update')}
+                </div>
+              </div>
+            </div>
+
           </React.Fragment>
         )}
 
-        <div className="row my-3">
-          <div className="col-xs-offset-3 col-xs-5">
-            <div className="btn btn-primary" disabled={adminGitHubSecurityContainer.state.retrieveError != null} onClick={this.onClickSubmit}>
-              {t('Update')}
-            </div>
-          </div>
-        </div>
-
         <hr />
 
         <div style={{ minHeight: '300px' }}>

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

@@ -35,10 +35,11 @@ class GoogleSecurityManagement extends React.Component {
   }
 
   async onClickSubmit() {
-    const { t, adminGoogleSecurityContainer } = this.props;
+    const { t, adminGoogleSecurityContainer, adminGeneralSecurityContainer } = this.props;
 
     try {
       await adminGoogleSecurityContainer.updateGoogleSetting();
+      await adminGeneralSecurityContainer.retrieveSetupStratedies();
       toastSuccess(t('security_setting.OAuth.Google.updated_google'));
     }
     catch (err) {
@@ -48,6 +49,7 @@ class GoogleSecurityManagement extends React.Component {
 
   render() {
     const { t, adminGeneralSecurityContainer, adminGoogleSecurityContainer } = this.props;
+    const { isGoogleEnabled } = adminGeneralSecurityContainer.state;
 
     if (this.state.isRetrieving) {
       return null;
@@ -57,7 +59,7 @@ class GoogleSecurityManagement extends React.Component {
       <React.Fragment>
 
         <h2 className="alert-anchor border-bottom">
-          {t('security_setting.OAuth.Google.name')} {t('security_setting.configuration')}
+          {t('security_setting.OAuth.Google.name')}
         </h2>
 
         {this.state.retrieveError != null && (
@@ -67,7 +69,9 @@ class GoogleSecurityManagement extends React.Component {
         )}
 
         <div className="row mb-5">
-          <strong className="col-xs-3 text-right">{t('security_setting.OAuth.Google.name')}</strong>
+          <div className="col-xs-3 my-3 text-right">
+            <strong>{t('security_setting.OAuth.Google.name')}</strong>
+          </div>
           <div className="col-xs-6 text-left">
             <div className="checkbox checkbox-success">
               <input
@@ -80,6 +84,8 @@ class GoogleSecurityManagement extends React.Component {
                 {t('security_setting.OAuth.Google.enable_google')}
               </label>
             </div>
+            {(!adminGeneralSecurityContainer.state.setupStrategies.includes('google') && isGoogleEnabled)
+              && <div className="label label-warning">{t('security_setting.setup_is_not_yet_complete')}</div>}
           </div>
         </div>
 
@@ -106,9 +112,11 @@ class GoogleSecurityManagement extends React.Component {
         </div>
 
 
-        {adminGeneralSecurityContainer.state.isGoogleEnabled && (
+        {isGoogleEnabled && (
           <React.Fragment>
 
+            <h3 className="border-bottom">{t('security_setting.configuration')}</h3>
+
             <div className="row mb-5">
               <label htmlFor="googleClientId" className="col-xs-3 text-right">{t('security_setting.clientID')}</label>
               <div className="col-xs-6">
@@ -161,17 +169,22 @@ class GoogleSecurityManagement extends React.Component {
               </div>
             </div>
 
+            <div className="row my-3">
+              <div className="col-xs-offset-3 col-xs-5">
+                <button
+                  type="button"
+                  className="btn btn-primary"
+                  disabled={adminGoogleSecurityContainer.state.retrieveError != null}
+                  onClick={this.onClickSubmit}
+                >
+                  {t('Update')}
+                </button>
+              </div>
+            </div>
+
           </React.Fragment>
         )}
 
-        <div className="row my-3">
-          <div className="col-xs-offset-3 col-xs-5">
-            <button type="button" className="btn btn-primary" disabled={adminGoogleSecurityContainer.state.retrieveError != null} onClick={this.onClickSubmit}>
-              {t('Update')}
-            </button>
-          </div>
-        </div>
-
         <hr />
 
         <div style={{ minHeight: '300px' }}>

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

@@ -39,10 +39,11 @@ class LdapSecuritySetting extends React.Component {
   }
 
   async onClickSubmit() {
-    const { t, adminLdapSecurityContainer } = this.props;
+    const { t, adminLdapSecurityContainer, adminGeneralSecurityContainer } = this.props;
 
     try {
       await adminLdapSecurityContainer.updateLdapSetting();
+      await adminGeneralSecurityContainer.retrieveSetupStratedies();
       toastSuccess(t('security_setting.ldap.updated_ldap'));
     }
     catch (err) {
@@ -69,11 +70,13 @@ class LdapSecuritySetting extends React.Component {
       <React.Fragment>
 
         <h2 className="alert-anchor border-bottom">
-          LDAP {t('security_setting.configuration')}
+          LDAP
         </h2>
 
         <div className="row mb-5">
-          <strong className="col-xs-3 text-right">Use LDAP</strong>
+          <div className="col-xs-3 my-3 text-right">
+            <strong>Use LDAP</strong>
+          </div>
           <div className="col-xs-6 text-left">
             <div className="checkbox checkbox-success">
               <input
@@ -86,12 +89,17 @@ class LdapSecuritySetting extends React.Component {
                 {t('security_setting.ldap.enable_ldap')}
               </label>
             </div>
+            {(!adminGeneralSecurityContainer.state.setupStrategies.includes('ldap') && isLdapEnabled)
+              && <div className="label label-warning">{t('security_setting.setup_is_not_yet_complete')}</div>}
           </div>
         </div>
 
 
         {isLdapEnabled && (
           <React.Fragment>
+
+            <h3 className="border-bottom">{t('security_setting.configuration')}</h3>
+
             <div className="row mb-5">
               <label htmlFor="serverUrl" className="col-xs-3 control-label text-right">Server URL</label>
               <div className="col-xs-6">
@@ -384,20 +392,23 @@ class LdapSecuritySetting extends React.Component {
                 </p>
               </div>
             </div>
+            <div className="row my-3">
+              <div className="col-xs-offset-3 col-xs-5">
+                <button
+                  type="button"
+                  className="btn btn-primary"
+                  disabled={adminLdapSecurityContainer.state.retrieveError != null}
+                  onClick={this.onClickSubmit}
+                >
+                  {t('Update')}
+                </button>
+                <button type="button" className="btn btn-default ml-2" onClick={this.openLdapAuthTestModal}>{t('security_setting.ldap.test_config')}</button>
+              </div>
+            </div>
 
           </React.Fragment>
         )}
 
-        <div className="row my-3">
-          <div className="col-xs-offset-3 col-xs-5">
-            <button type="button" className="btn btn-primary" disabled={adminLdapSecurityContainer.state.retrieveError != null} onClick={this.onClickSubmit}>
-              {t('Update')}
-            </button>
-            {adminGeneralSecurityContainer.state.isLdapEnabled
-              && <button type="button" className="btn btn-default ml-2" onClick={this.openLdapAuthTestModal}>{t('security_setting.ldap.test_config')}</button>
-            }
-          </div>
-        </div>
 
         <LdapAuthTestModal isOpen={this.state.isLdapAuthTestModalShown} onClose={this.closeLdapAuthTestModal} />
 

+ 28 - 13
src/client/js/components/Admin/Security/LocalSecuritySetting.jsx

@@ -35,9 +35,10 @@ class LocalSecuritySetting extends React.Component {
 
 
   async onClickSubmit() {
-    const { t, adminLocalSecurityContainer } = this.props;
+    const { t, adminGeneralSecurityContainer, adminLocalSecurityContainer } = this.props;
     try {
       await adminLocalSecurityContainer.updateLocalSecuritySetting();
+      await adminGeneralSecurityContainer.retrieveSetupStratedies();
       toastSuccess(t('security_setting.updated_general_security_setting'));
     }
     catch (err) {
@@ -48,6 +49,7 @@ class LocalSecuritySetting extends React.Component {
   render() {
     const { t, adminGeneralSecurityContainer, adminLocalSecurityContainer } = this.props;
     const { registrationMode } = adminLocalSecurityContainer.state;
+    const { isLocalEnabled } = adminGeneralSecurityContainer.state;
 
     if (this.state.isRetrieving) {
       return null;
@@ -61,7 +63,7 @@ class LocalSecuritySetting extends React.Component {
           </div>
         )}
         <h2 className="alert-anchor border-bottom">
-          {t('security_setting.Local.name')} {t('security_setting.configuration')}
+          {t('security_setting.Local.name')}
         </h2>
 
         {adminGeneralSecurityContainer.state.useOnlyEnvVarsForSomeOptions && (
@@ -73,7 +75,9 @@ class LocalSecuritySetting extends React.Component {
         )}
 
         <div className="row mb-5">
-          <strong className="col-xs-3 text-right">{t('security_setting.Local.name')}</strong>
+          <div className="col-xs-3 my-3 text-right">
+            <strong>{t('security_setting.Local.name')}</strong>
+          </div>
           <div className="col-xs-6 text-left">
             <div className="checkbox checkbox-success">
               <input
@@ -86,11 +90,16 @@ class LocalSecuritySetting extends React.Component {
                 {t('security_setting.Local.enable_local')}
               </label>
             </div>
+            {(!adminGeneralSecurityContainer.state.setupStrategies.includes('local') && isLocalEnabled)
+            && <div className="label label-warning">{t('security_setting.setup_is_not_yet_complete')}</div>}
           </div>
         </div>
 
-        {adminGeneralSecurityContainer.state.isLocalEnabled && (
-          <div>
+        {isLocalEnabled && (
+          <React.Fragment>
+
+            <h3 className="border-bottom">{t('security_setting.configuration')}</h3>
+
             <div className="row mb-5">
               <strong className="col-xs-3 text-right">{t('Register limitation')}</strong>
               <div className="col-xs-9 text-left">
@@ -156,16 +165,22 @@ class LocalSecuritySetting extends React.Component {
                 </div>
               </div>
             </div>
-          </div>
+
+            <div className="row my-3">
+              <div className="col-xs-offset-3 col-xs-5">
+                <button
+                  type="button"
+                  className="btn btn-primary"
+                  disabled={adminLocalSecurityContainer.state.retrieveError != null}
+                  onClick={this.onClickSubmit}
+                >
+                  {t('Update')}
+                </button>
+              </div>
+            </div>
+          </React.Fragment>
         )}
 
-        <div className="row my-3">
-          <div className="col-xs-offset-3 col-xs-5">
-            <button type="button" className="btn btn-primary" disabled={adminLocalSecurityContainer.state.retrieveError != null} onClick={this.onClickSubmit}>
-              {t('Update')}
-            </button>
-          </div>
-        </div>
 
       </React.Fragment>
     );

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

@@ -35,10 +35,11 @@ class OidcSecurityManagement extends React.Component {
   }
 
   async onClickSubmit() {
-    const { t, adminOidcSecurityContainer } = this.props;
+    const { t, adminOidcSecurityContainer, adminGeneralSecurityContainer } = this.props;
 
     try {
       await adminOidcSecurityContainer.updateOidcSetting();
+      await adminGeneralSecurityContainer.retrieveSetupStratedies();
       toastSuccess(t('security_setting.OAuth.OIDC.updated_oidc'));
     }
     catch (err) {
@@ -48,6 +49,7 @@ class OidcSecurityManagement extends React.Component {
 
   render() {
     const { t, adminGeneralSecurityContainer, adminOidcSecurityContainer } = this.props;
+    const { isOidcEnabled } = adminGeneralSecurityContainer.state;
 
     if (this.state.isRetrieving) {
       return null;
@@ -58,11 +60,13 @@ class OidcSecurityManagement extends React.Component {
       <React.Fragment>
 
         <h2 className="alert-anchor border-bottom">
-          {t('security_setting.OAuth.OIDC.name')} {t('security_setting.configuration')}
+          {t('security_setting.OAuth.OIDC.name')}
         </h2>
 
         <div className="row mb-5">
-          <strong className="col-xs-3 text-right">{t('security_setting.OAuth.OIDC.name')}</strong>
+          <div className="col-xs-3 my-3 text-right">
+            <strong>{t('security_setting.OAuth.OIDC.name')}</strong>
+          </div>
           <div className="col-xs-6 text-left">
             <div className="checkbox checkbox-success">
               <input
@@ -75,6 +79,8 @@ class OidcSecurityManagement extends React.Component {
                 {t('security_setting.OAuth.enable_oidc')}
               </label>
             </div>
+            {(!adminGeneralSecurityContainer.state.setupStrategies.includes('oidc') && isOidcEnabled)
+              && <div className="label label-warning">{t('security_setting.setup_is_not_yet_complete')}</div>}
           </div>
         </div>
 
@@ -100,9 +106,11 @@ class OidcSecurityManagement extends React.Component {
           </div>
         </div>
 
-        {adminGeneralSecurityContainer.state.isOidcEnabled && (
+        {isOidcEnabled && (
           <React.Fragment>
 
+            <h3 className="border-bottom">{t('security_setting.configuration')}</h3>
+
             <div className="row mb-5">
               <label htmlFor="oidcProviderName" className="col-xs-3 text-right">{t('security_setting.providerName')}</label>
               <div className="col-xs-6">
@@ -294,16 +302,21 @@ class OidcSecurityManagement extends React.Component {
               </div>
             </div>
 
+            <div className="row my-3">
+              <div className="col-xs-offset-3 col-xs-5">
+                <button
+                  type="button"
+                  className="btn btn-primary"
+                  disabled={adminOidcSecurityContainer.state.retrieveError != null}
+                  onClick={this.onClickSubmit}
+                >
+                  {t('Update')}
+                </button>
+              </div>
+            </div>
           </React.Fragment>
         )}
 
-        <div className="row my-3">
-          <div className="col-xs-offset-3 col-xs-5">
-            <button type="button" className="btn btn-primary" disabled={adminOidcSecurityContainer.state.retrieveError != null} onClick={this.onClickSubmit}>
-              {t('Update')}
-            </button>
-          </div>
-        </div>
 
         <hr />
 

+ 23 - 14
src/client/js/components/Admin/Security/SamlSecuritySetting.jsx

@@ -55,10 +55,11 @@ class SamlSecurityManagement extends React.Component {
   }
 
   async onClickSubmit() {
-    const { t, adminSamlSecurityContainer } = this.props;
+    const { t, adminSamlSecurityContainer, adminGeneralSecurityContainer } = this.props;
 
     try {
       await adminSamlSecurityContainer.updateSamlSetting();
+      await adminGeneralSecurityContainer.retrieveSetupStratedies();
       toastSuccess(t('security_setting.SAML.updated_saml'));
     }
     catch (err) {
@@ -69,6 +70,7 @@ class SamlSecurityManagement extends React.Component {
   render() {
     const { t, adminGeneralSecurityContainer, adminSamlSecurityContainer } = this.props;
     const { useOnlyEnvVars } = adminSamlSecurityContainer.state;
+    const { isSamlEnabled } = adminGeneralSecurityContainer.state;
 
     if (this.state.isRetrieving) {
       return null;
@@ -77,7 +79,7 @@ class SamlSecurityManagement extends React.Component {
       <React.Fragment>
 
         <h2 className="alert-anchor border-bottom">
-          {t('security_setting.SAML.name')} {t('security_setting.configuration')}
+          {t('security_setting.SAML.name')}
         </h2>
 
         {useOnlyEnvVars && (
@@ -88,7 +90,9 @@ class SamlSecurityManagement extends React.Component {
         )}
 
         <div className="row mb-5">
-          <strong className="col-xs-3 text-right">{t('security_setting.SAML.name')}</strong>
+          <div className="col-xs-3 my-3 text-right">
+            <strong>{t('security_setting.SAML.name')}</strong>
+          </div>
           <div className="col-xs-6 text-left">
             <div className="checkbox checkbox-success">
               <input
@@ -101,6 +105,8 @@ class SamlSecurityManagement extends React.Component {
                 {t('security_setting.SAML.enable_saml')}
               </label>
             </div>
+            {(!adminGeneralSecurityContainer.state.setupStrategies.includes('ldap') && isSamlEnabled)
+              && <div className="label label-warning">{t('security_setting.setup_is_not_yet_complete')}</div>}
           </div>
         </div>
 
@@ -126,7 +132,7 @@ class SamlSecurityManagement extends React.Component {
           </div>
         </div>
 
-        {adminGeneralSecurityContainer.state.isSamlEnabled && (
+        {isSamlEnabled && (
           <React.Fragment>
 
             {(adminSamlSecurityContainer.state.missingMandatoryConfigKeys.length !== 0) && (
@@ -507,19 +513,22 @@ pWVdnzS1VCO8fKsJ7YYIr+JmHvseph3kFUOI5RqkCcMZlKUv83aUThsTHw==
               </tbody>
             </table>
 
-          </React.Fragment>
+            <div className="row my-3">
+              <div className="col-xs-offset-3 col-xs-5">
+                <button
+                  type="button"
+                  className="btn btn-primary"
+                  disabled={adminSamlSecurityContainer.state.retrieveError != null}
+                  onClick={this.onClickSubmit}
+                >
+                  {t('Update')}
+                </button>
+              </div>
+            </div>
 
+          </React.Fragment>
         )}
 
-        <div className="row my-3">
-          <div className="col-xs-offset-3 col-xs-5">
-            <button type="button" className="btn btn-primary" disabled={adminSamlSecurityContainer.state.retrieveError != null} onClick={this.onClickSubmit}>
-              {t('Update')}
-            </button>
-          </div>
-        </div>
-
-
       </React.Fragment>
     );
 

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

@@ -35,10 +35,11 @@ class TwitterSecurityManagement extends React.Component {
   }
 
   async onClickSubmit() {
-    const { t, adminTwitterSecurityContainer } = this.props;
+    const { t, adminTwitterSecurityContainer, adminGeneralSecurityContainer } = this.props;
 
     try {
       await adminTwitterSecurityContainer.updateTwitterSetting();
+      await adminGeneralSecurityContainer.retrieveSetupStratedies();
       toastSuccess(t('security_setting.OAuth.Twitter.updated_twitter'));
     }
     catch (err) {
@@ -48,6 +49,7 @@ class TwitterSecurityManagement extends React.Component {
 
   render() {
     const { t, adminGeneralSecurityContainer, adminTwitterSecurityContainer } = this.props;
+    const { isTwitterEnabled } = adminTwitterSecurityContainer.state;
 
     if (this.state.isRetrieving) {
       return null;
@@ -57,7 +59,7 @@ 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')}
         </h2>
 
         {this.state.retrieveError != null && (
@@ -67,7 +69,9 @@ class TwitterSecurityManagement extends React.Component {
         )}
 
         <div className="row mb-5">
-          <strong className="col-xs-3 text-right">{t('security_setting.OAuth.Twitter.name')}</strong>
+          <div className="col-xs-3 my-3 text-right">
+            <strong>{t('security_setting.OAuth.Twitter.name')}</strong>
+          </div>
           <div className="col-xs-6 text-left">
             <div className="checkbox checkbox-success">
               <input
@@ -80,6 +84,8 @@ class TwitterSecurityManagement extends React.Component {
                 {t('security_setting.OAuth.Twitter.enable_twitter')}
               </label>
             </div>
+            {(!adminGeneralSecurityContainer.state.setupStrategies.includes('twitter') && isTwitterEnabled)
+              && <div className="label label-warning">{t('security_setting.setup_is_not_yet_complete')}</div>}
           </div>
         </div>
 
@@ -106,9 +112,11 @@ class TwitterSecurityManagement extends React.Component {
         </div>
 
 
-        {adminGeneralSecurityContainer.state.isTwitterEnabled && (
+        {isTwitterEnabled && (
           <React.Fragment>
 
+            <h3 className="border-bottom">{t('security_setting.configuration')}</h3>
+
             <div className="row mb-5">
               <label htmlFor="TwitterConsumerId" className="col-xs-3 text-right">{t('security_setting.clientID')}</label>
               <div className="col-xs-6">
@@ -161,17 +169,22 @@ class TwitterSecurityManagement extends React.Component {
               </div>
             </div>
 
+            <div className="row my-3">
+              <div className="col-xs-offset-3 col-xs-5">
+                <button
+                  type="button"
+                  className="btn btn-primary"
+                  disabled={adminTwitterSecurityContainer.state.retrieveError != null}
+                  onClick={this.onClickSubmit}
+                >
+                  {t('Update')}
+                </button>
+              </div>
+            </div>
+
           </React.Fragment>
         )}
 
-        <div className="row my-3">
-          <div className="col-xs-offset-3 col-xs-5">
-            <button type="button" className="btn btn-primary" disabled={adminTwitterSecurityContainer.state.retrieveError != null} onClick={this.onClickSubmit}>
-              {t('Update')}
-            </button>
-          </div>
-        </div>
-
         <hr />
 
         <div style={{ minHeight: '300px' }}>

+ 17 - 0
src/client/js/services/AdminGeneralSecurityContainer.js

@@ -31,12 +31,14 @@ export default class AdminGeneralSecurityContainer extends Container {
       isGoogleEnabled: false,
       isGitHubEnabled: false,
       isTwitterEnabled: false,
+      setupStrategies: [],
     };
 
     this.onIsWikiModeForced = this.onIsWikiModeForced.bind(this);
   }
 
   async retrieveSecurityData() {
+    await this.retrieveSetupStratedies();
     const response = await this.appContainer.apiv3.get('/security-setting/');
     const { generalSetting, generalAuth } = response.data.securityParams;
     this.onIsWikiModeForced(generalSetting.wikiMode);
@@ -132,6 +134,7 @@ export default class AdminGeneralSecurityContainer extends Container {
         isEnabled,
         authId,
       });
+      await this.retrieveSetupStratedies();
       this.setState({ [stateVariableName]: isEnabled });
     }
     catch (err) {
@@ -139,6 +142,20 @@ export default class AdminGeneralSecurityContainer extends Container {
     }
   }
 
+  /**
+   * Retrieve SetupStratedies
+   */
+  async retrieveSetupStratedies() {
+    try {
+      const response = await this.appContainer.apiv3.get('/security-setting/authentication');
+      const { setupStrategies } = response.data;
+      this.setState({ setupStrategies });
+    }
+    catch (err) {
+      toastError(err);
+    }
+  }
+
   /**
    * Switch local enabled
    */

+ 28 - 0
src/server/routes/apiv3/security-setting.js

@@ -465,6 +465,34 @@ module.exports = (crowi) => {
 
   });
 
+  /**
+   * @swagger
+   *
+   *    /_api/v3/security-setting/authentication:
+   *      get:
+   *        tags: [SecuritySetting, apiv3]
+   *        description: Get setup strategies for passport
+   *        responses:
+   *          200:
+   *            description: params of setup strategies
+   *            content:
+   *              application/json:
+   *                schema:
+   *                  properties:
+   *                    setupStrategies:
+   *                      type: array
+   *                      description: setup strategies list
+   *                      items:
+   *                        type: string
+   *                        description: setup strategie
+   *                      example: ["local"]
+   */
+  router.get('/authentication/', loginRequiredStrictly, adminRequired, async(req, res) => {
+    const setupStrategies = await crowi.passportService.getSetupStrategies();
+
+    return res.apiv3({ setupStrategies });
+  });
+
   /**
    * @swagger
    *