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

Merge pull request #1559 from weseek/reactify-admin/adjust-layout

Reactify admin/adjust layout
itizawa 6 лет назад
Родитель
Сommit
e5898be1a6

+ 3 - 3
resource/locales/en-US/translation.json

@@ -453,8 +453,8 @@
     "optional": "Optional",
     "Treat username matching as identical": "Automatically bind external accounts newly logged in to local accounts when <code>username</code> match",
     "Treat username matching as identical_warn": "WARNING: Be aware of security because the system treats the same user as a match of <code>username</code>.",
-    "Treat email matching as identical": "Automatically bind external accounts newly logged in to local accounts when <code>%s</code> match",
-    "Treat email matching as identical_warn": "WARNING: Be aware of security because the system treats the same user as a match of <code>%s</code>.",
+    "Treat email matching as identical": "Automatically bind external accounts newly logged in to local accounts when <code>email</code> match",
+    "Treat email matching as identical_warn": "WARNING: Be aware of security because the system treats the same user as a match of <code>email</code>.",
     "Use env var if empty": "Use env var <code>{{env}}</code> if empty",
     "Use default if both are empty": "If both ​​are empty, the default value <code>{{target}}</code> is used.",
     "missing mandatory configs": "The following mandatory items are not set in either database nor environment variables.",
@@ -643,7 +643,7 @@
     "tab_switch": "Save tab-switching in the browser",
     "save_edit": "Save edit tab and history tab switching in the browser and make it object for forward/back command of the browser.",
     "by_invalidating": "By invalidating, you can make page transition as the only object for forward/back command of the browser.",
-    "nocdn_desc": "This function is disabled when the environment variable <code>NO_CDN=true</code>.<br>Github style has been forcibly applied.",
+    "nocdn_desc": "This function is disabled when the environment variable <code>NO_CDN=true</code>.<br>GitHub style has been forcibly applied.",
     "custom_title": "Custom Title",
     "custom_title_detail": "You can customize <code>%s</code> tag.<br><code>%s</code> will be automatically replaced with the app name, and <code>%s</code> will be replaced with the page name/path.",
     "custom_header": "Custom HTML Header",

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

@@ -60,13 +60,13 @@ import AdminAppContainer from './services/AdminAppContainer';
 import WebsocketContainer from './services/WebsocketContainer';
 import AdminMarkDownContainer from './services/AdminMarkDownContainer';
 import AdminExternalAccountsContainer from './services/AdminExternalAccountsContainer';
+import AdminLocalSecurityContainer from './services/AdminLocalSecurityContainer';
 import AdminSamlSecurityContainer from './services/AdminSamlSecurityContainer';
 import AdminOidcSecurityContainer from './services/AdminOidcSecurityContainer';
 import AdminBasicSecurityContainer from './services/AdminBasicSecurityContainer';
 import AdminGoogleSecurityContainer from './services/AdminGoogleSecurityContainer';
-import AdminGithubSecurityContainer from './services/AdminGithubSecurityConatainer';
+import AdminGitHubSecurityContainer from './services/AdminGitHubSecurityContainer';
 import AdminTwitterSecurityContainer from './services/AdminTwitterSecurityContainer';
-import AdminLocalSecurityContainer from './services/AdminLocalSecurityContainer';
 
 const logger = loggerFactory('growi:app');
 
@@ -256,11 +256,11 @@ if (adminSecuritySettingElem != null) {
   const adminOidcSecurityContainer = new AdminOidcSecurityContainer(appContainer);
   const adminBasicSecurityContainer = new AdminBasicSecurityContainer(appContainer);
   const adminGoogleSecurityContainer = new AdminGoogleSecurityContainer(appContainer);
-  const adminGithubSecurityContainer = new AdminGithubSecurityContainer(appContainer);
+  const adminGitHubSecurityContainer = new AdminGitHubSecurityContainer(appContainer);
   const adminTwitterSecurityContainer = new AdminTwitterSecurityContainer(appContainer);
   const adminSecurityContainers = [
     adminGeneralSecurityContainer, adminLocalSecurityContainer, adminLdapSecurityContainer, adminSamlSecurityContainer,
-    adminOidcSecurityContainer, adminBasicSecurityContainer, adminGoogleSecurityContainer, adminGithubSecurityContainer, adminTwitterSecurityContainer,
+    adminOidcSecurityContainer, adminBasicSecurityContainer, adminGoogleSecurityContainer, adminGitHubSecurityContainer, adminTwitterSecurityContainer,
   ];
   ReactDOM.render(
     <Provider inject={[...injectableContainers, ...adminSecurityContainers]}>

+ 1 - 1
src/client/js/components/Admin/App/AppSettingsPage.jsx

@@ -27,7 +27,7 @@ class AppSettingsPage extends React.Component {
     }
     catch (err) {
       toastError(err);
-      adminAppContainer.setState({ retrieveError: err });
+      adminAppContainer.setState({ retrieveError: err.message });
       logger.error(err);
     }
   }

+ 1 - 1
src/client/js/components/Admin/Customize/Customize.jsx

@@ -32,7 +32,7 @@ class Customize extends React.Component {
     }
     catch (err) {
       toastError(err);
-      adminCustomizeContainer.setState({ retrieveError: err });
+      adminCustomizeContainer.setState({ retrieveError: err.message });
       logger.error(err);
     }
 

+ 1 - 1
src/client/js/components/Admin/MarkdownSetting/MarkDownSetting.jsx

@@ -25,7 +25,7 @@ class MarkdownSetting extends React.Component {
     }
     catch (err) {
       toastError(err);
-      adminMarkDownContainer.setState({ retrieveError: err });
+      adminMarkDownContainer.setState({ retrieveError: err.message });
       logger.error(err);
     }
 

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

@@ -33,7 +33,7 @@ class BasicSecurityManagement extends React.Component {
     }
     catch (err) {
       toastError(err);
-      this.setState({ retrieveError: err });
+      this.setState({ retrieveError: err.message });
       logger.error(err);
     }
   }

+ 29 - 35
src/client/js/components/Admin/Security/GithubSecuritySetting.jsx → src/client/js/components/Admin/Security/GitHubSecuritySetting.jsx

@@ -9,11 +9,11 @@ import { toastSuccess, toastError } from '../../../util/apiNotification';
 
 import AppContainer from '../../../services/AppContainer';
 import AdminGeneralSecurityContainer from '../../../services/AdminGeneralSecurityContainer';
-import AdminGithubSecurityContainer from '../../../services/AdminGithubSecurityConatainer';
+import AdminGitHubSecurityContainer from '../../../services/AdminGitHubSecurityContainer';
 
 const logger = loggerFactory('growi:security:AdminGitHubSecurityContainer');
 
-class GithubSecurityManagement extends React.Component {
+class GitHubSecurityManagement extends React.Component {
 
   constructor(props) {
     super(props);
@@ -26,23 +26,23 @@ class GithubSecurityManagement extends React.Component {
   }
 
   async componentDidMount() {
-    const { adminGithubSecurityContainer } = this.props;
+    const { adminGitHubSecurityContainer } = this.props;
 
     try {
-      await adminGithubSecurityContainer.retrieveSecurityData();
+      await adminGitHubSecurityContainer.retrieveSecurityData();
     }
     catch (err) {
       toastError(err);
-      this.setState({ retrieveError: err });
+      this.setState({ retrieveError: err.message });
       logger.error(err);
     }
   }
 
   async onClickSubmit() {
-    const { t, adminGithubSecurityContainer } = this.props;
+    const { t, adminGitHubSecurityContainer } = this.props;
 
     try {
-      await adminGithubSecurityContainer.updateGitHubSetting();
+      await adminGitHubSecurityContainer.updateGitHubSetting();
       toastSuccess(t('security_setting.OAuth.GitHub.updated_github'));
     }
     catch (err) {
@@ -52,7 +52,7 @@ class GithubSecurityManagement extends React.Component {
   }
 
   render() {
-    const { t, adminGeneralSecurityContainer, adminGithubSecurityContainer } = this.props;
+    const { t, adminGeneralSecurityContainer, adminGitHubSecurityContainer } = this.props;
     return (
 
       <React.Fragment>
@@ -72,12 +72,12 @@ class GithubSecurityManagement extends React.Component {
           <div className="col-xs-6 text-left">
             <div className="checkbox checkbox-success">
               <input
-                id="isGithubEnabled"
+                id="isGitHubEnabled"
                 type="checkbox"
                 checked={adminGeneralSecurityContainer.state.isGitHubEnabled}
-                onChange={() => { adminGeneralSecurityContainer.switchIsGithubOAuthEnabled() }}
+                onChange={() => { adminGeneralSecurityContainer.switchIsGitHubOAuthEnabled() }}
               />
-              <label htmlFor="isGithubEnabled">
+              <label htmlFor="isGitHubEnabled">
                 {t('security_setting.OAuth.GitHub.enable_github')}
               </label>
             </div>
@@ -90,7 +90,7 @@ class GithubSecurityManagement extends React.Component {
             <input
               className="form-control"
               type="text"
-              value={adminGithubSecurityContainer.state.appSiteUrl}
+              value={adminGitHubSecurityContainer.state.appSiteUrl}
               readOnly
             />
             <p className="help-block small">{t('security_setting.desc_of_callback_URL', { AuthName: 'OAuth' })}</p>
@@ -107,15 +107,9 @@ class GithubSecurityManagement extends React.Component {
         </div>
 
 
-        {adminGeneralSecurityContainer.state.isGithubEnabled && (
+        {adminGeneralSecurityContainer.state.isGitHubEnabled && (
           <React.Fragment>
 
-            {!adminGithubSecurityContainer.state.isGitHubStrategySetup && (
-              <div className="alert alert-warning">
-                <p>{t('security_setting.setup_not_completed_yet')}</p>
-              </div>
-            )}
-
             <div className="row mb-5">
               <label htmlFor="githubClientId" className="col-xs-3 text-right">{t('security_setting.clientID')}</label>
               <div className="col-xs-6">
@@ -123,8 +117,8 @@ class GithubSecurityManagement extends React.Component {
                   className="form-control"
                   type="text"
                   name="githubClientId"
-                  value={adminGithubSecurityContainer.state.githubClientId}
-                  onChange={e => adminGithubSecurityContainer.changeGithubClientId(e.target.value)}
+                  value={adminGitHubSecurityContainer.state.githubClientId}
+                  onChange={e => adminGitHubSecurityContainer.changeGitHubClientId(e.target.value)}
                 />
                 <p className="help-block">
                   <small dangerouslySetInnerHTML={{ __html: t('security_setting.Use env var if empty', { env: 'OAUTH_GITHUB_CLIENT_ID' }) }} />
@@ -139,8 +133,8 @@ class GithubSecurityManagement extends React.Component {
                   className="form-control"
                   type="text"
                   name="githubClientSecret"
-                  defaultValue={adminGithubSecurityContainer.state.githubClientSecret}
-                  onChange={e => adminGithubSecurityContainer.changeGithubClientSecret(e.target.value)}
+                  defaultValue={adminGitHubSecurityContainer.state.githubClientSecret}
+                  onChange={e => adminGitHubSecurityContainer.changeGitHubClientSecret(e.target.value)}
                 />
                 <p className="help-block">
                   <small dangerouslySetInnerHTML={{ __html: t('security_setting.Use env var if empty', { env: 'OAUTH_GITHUB_CLIENT_SECRET' }) }} />
@@ -152,13 +146,13 @@ class GithubSecurityManagement extends React.Component {
               <div className="col-xs-offset-3 col-xs-6 text-left">
                 <div className="checkbox checkbox-success">
                   <input
-                    id="bindByUserNameGithub"
+                    id="bindByUserNameGitHub"
                     type="checkbox"
-                    checked={adminGithubSecurityContainer.state.isSameUsernameTreatedAsIdenticalUser}
-                    onChange={() => { adminGithubSecurityContainer.switchIsSameUsernameTreatedAsIdenticalUser() }}
+                    checked={adminGitHubSecurityContainer.state.isSameUsernameTreatedAsIdenticalUser}
+                    onChange={() => { adminGitHubSecurityContainer.switchIsSameUsernameTreatedAsIdenticalUser() }}
                   />
                   <label
-                    htmlFor="bindByUserNameGithub"
+                    htmlFor="bindByUserNameGitHub"
                     dangerouslySetInnerHTML={{ __html: t('security_setting.Treat email matching as identical') }}
                   />
                 </div>
@@ -182,12 +176,12 @@ 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">
+          <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_2', { url: adminGitHubSecurityContainer.state.callbackUrl }) }} />
             <li dangerouslySetInnerHTML={{ __html: t('security_setting.OAuth.GitHub.register_3') }} />
           </ol>
         </div>
@@ -201,15 +195,15 @@ class GithubSecurityManagement extends React.Component {
 }
 
 
-GithubSecurityManagement.propTypes = {
+GitHubSecurityManagement.propTypes = {
   t: PropTypes.func.isRequired, // i18next
   appContainer: PropTypes.instanceOf(AppContainer).isRequired,
   adminGeneralSecurityContainer: PropTypes.instanceOf(AdminGeneralSecurityContainer).isRequired,
-  adminGithubSecurityContainer: PropTypes.instanceOf(AdminGithubSecurityContainer).isRequired,
+  adminGitHubSecurityContainer: PropTypes.instanceOf(AdminGitHubSecurityContainer).isRequired,
 };
 
-const GithubSecurityManagementWrapper = (props) => {
-  return createSubscribedElement(GithubSecurityManagement, props, [AppContainer, AdminGeneralSecurityContainer, AdminGithubSecurityContainer]);
+const GitHubSecurityManagementWrapper = (props) => {
+  return createSubscribedElement(GitHubSecurityManagement, props, [AppContainer, AdminGeneralSecurityContainer, AdminGitHubSecurityContainer]);
 };
 
-export default withTranslation()(GithubSecurityManagementWrapper);
+export default withTranslation()(GitHubSecurityManagementWrapper);

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

@@ -33,7 +33,7 @@ class GoogleSecurityManagement extends React.Component {
     }
     catch (err) {
       toastError(err);
-      this.setState({ retrieveError: err });
+      this.setState({ retrieveError: err.message });
       logger.error(err);
     }
   }
@@ -110,12 +110,6 @@ class GoogleSecurityManagement extends React.Component {
         {adminGeneralSecurityContainer.state.isGoogleEnabled && (
           <React.Fragment>
 
-            {!adminGoogleSecurityContainer.state.isGoogleStrategySetup && (
-              <div className="alert alert-warning">
-                <p>{t('security_setting.setup_not_completed_yet')}</p>
-              </div>
-            )}
-
             <div className="row mb-5">
               <label htmlFor="googleClientId" className="col-xs-3 text-right">{t('security_setting.clientID')}</label>
               <div className="col-xs-6">

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

@@ -36,7 +36,7 @@ class LdapSecuritySetting extends React.Component {
     }
     catch (err) {
       toastError(err);
-      this.setState({ retrieveError: err });
+      this.setState({ retrieveError: err.message });
       logger.error(err);
     }
   }

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

@@ -29,7 +29,7 @@ class LocalSecuritySetting extends React.Component {
     }
     catch (err) {
       toastError(err);
-      this.setState({ retrieveError: err });
+      this.setState({ retrieveError: err.message });
     }
   }
 

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

@@ -33,7 +33,7 @@ class OidcSecurityManagement extends React.Component {
     }
     catch (err) {
       toastError(err);
-      this.setState({ retrieveError: err });
+      this.setState({ retrieveError: err.message });
       logger.error(err);
     }
   }
@@ -314,8 +314,8 @@ class OidcSecurityManagement extends React.Component {
 
         <div style={{ minHeight: '300px' }}>
           <h4>
-            <i className="icon-question" aria-hidden="true"></i>
-            <a href="#collapseHelpForOidcOauth" data-toggle="collapse">{t('security_setting.OAuth.how_to.oidc')}</a>
+            <i className="icon-question" aria-hidden="true" />
+            <a href="#collapseHelpForOidcOauth" data-toggle="collapse"> {t('security_setting.OAuth.how_to.oidc')}</a>
           </h4>
           <ol id="collapseHelpForOidcOauth" className="collapse">
             <li>{t('security_setting.OAuth.OIDC.register_1')}</li>

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

@@ -51,7 +51,7 @@ class SamlSecurityManagement extends React.Component {
     }
     catch (err) {
       toastError(err);
-      this.setState({ retrieveError: err });
+      this.setState({ retrieveError: err.message });
       logger.error(err);
     }
   }

+ 6 - 3
src/client/js/components/Admin/Security/SecurityManagement.jsx

@@ -12,7 +12,7 @@ import OidcSecuritySetting from './OidcSecuritySetting';
 import SecuritySetting from './SecuritySetting';
 import BasicSecuritySetting from './BasicSecuritySetting';
 import GoogleSecuritySetting from './GoogleSecuritySetting';
-import GithubSecuritySetting from './GithubSecuritySetting';
+import GitHubSecuritySetting from './GitHubSecuritySetting';
 import TwitterSecuritySetting from './TwitterSecuritySetting';
 import FacebookSecuritySetting from './FacebookSecuritySetting';
 
@@ -27,7 +27,9 @@ class SecurityManagement extends React.Component {
     const { t } = this.props;
     return (
       <Fragment>
-        <div><SecuritySetting /></div>
+        <div>
+          <SecuritySetting />
+        </div>
 
         {/* XSS configuration link */}
         <div className="mb-5">
@@ -39,6 +41,7 @@ class SecurityManagement extends React.Component {
           </div>
         </div>
 
+        {/* TODO GW-226 adapt BS4 */}
         <div className="auth-mechanism-configurations m-t-10">
           <h2 className="border-bottom">{t('security_setting.Authentication mechanism settings')}</h2>
           <div className="passport-settings">
@@ -91,7 +94,7 @@ class SecurityManagement extends React.Component {
                 <GoogleSecuritySetting />
               </div>
               <div id="passport-github" className="tab-pane" role="tabpanel">
-                <GithubSecuritySetting />
+                <GitHubSecuritySetting />
               </div>
               <div id="passport-twitter" className="tab-pane" role="tabpanel">
                 <TwitterSecuritySetting />

+ 28 - 21
src/client/js/components/Admin/Security/SecuritySetting.jsx

@@ -28,7 +28,7 @@ class SecuritySetting extends React.Component {
     }
     catch (err) {
       toastError(err);
-      this.setState({ retrieveError: err });
+      this.setState({ retrieveError: err.message });
     }
   }
 
@@ -45,7 +45,7 @@ class SecuritySetting extends React.Component {
 
   render() {
     const { t, adminGeneralSecurityContainer } = this.props;
-    const { currentRestrictGuestMode } = adminGeneralSecurityContainer.state;
+    const { currentRestrictGuestMode, currentPageCompleteDeletionAuthority } = adminGeneralSecurityContainer.state;
     const helpPageListingByOwner = { __html: t('security_setting.page_listing_1') };
     const helpPageListingByGroup = { __html: t('security_setting.page_listing_2') };
     // eslint-disable-next-line max-len
@@ -55,13 +55,14 @@ class SecuritySetting extends React.Component {
     return (
       <React.Fragment>
         <fieldset>
-          <legend className="alert-anchor">{t('security_settings')}</legend>
+          <h2 className="alert-anchor border-bottom">
+            {t('security_settings')}
+          </h2>
           {this.state.retrieveError != null && (
             <div className="alert alert-danger">
-              <p>{t('Error occurred')} : {this.state.err}</p>
+              <p>{t('Error occurred')} : {this.state.retrieveError}</p>
             </div>
           )}
-          {/* TODO adjust layout */}
           <div className="row mb-5">
             <strong className="col-xs-3 text-right"> {t('security_setting.Guest Users Access')} </strong>
             <div className="col-xs-9 text-left">
@@ -75,8 +76,10 @@ class SecuritySetting extends React.Component {
                     aria-expanded="false"
                     disabled={adminGeneralSecurityContainer.state.isWikiModeForced}
                   >
-                    {currentRestrictGuestMode === 'Deny' && <span className="pull-left">{t('security_setting.guest_mode.deny')}</span>}
-                    {currentRestrictGuestMode === 'Readonly' && <span className="pull-left">{t('security_setting.guest_mode.readonly')}</span>}
+                    <span className="pull-left">
+                      {currentRestrictGuestMode === 'Deny' && t('security_setting.guest_mode.deny')}
+                      {currentRestrictGuestMode === 'Readonly' && t('security_setting.guest_mode.readonly')}
+                    </span>
                     <span className="bs-caret pull-right">
                       <span className="caret" />
                     </span>
@@ -127,7 +130,7 @@ class SecuritySetting extends React.Component {
                   onChange={() => { adminGeneralSecurityContainer.switchIsHideRestrictedByOwner() }}
                 />
                 <label htmlFor="isHideRestrictedByOwner">
-                  <p className="help-block small">{t('security_setting.page_listing_1_desc')}</p>
+                  {t('security_setting.page_listing_1_desc')}
                 </label>
               </div>
             </div>
@@ -144,7 +147,7 @@ class SecuritySetting extends React.Component {
                   onChange={() => { adminGeneralSecurityContainer.switchIsHideRestrictedByGroup() }}
                 />
                 <label htmlFor="isHideRestrictedByGroup">
-                  <p className="help-block small">{t('security_setting.page_listing_2_desc')}</p>
+                  {t('security_setting.page_listing_2_desc')}
                 </label>
               </div>
             </div>
@@ -156,7 +159,11 @@ class SecuritySetting extends React.Component {
               <div className="my-0 btn-group">
                 <div className="dropdown">
                   <button className="btn btn-default dropdown-toggle w-100" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
-                    <span className="pull-left">{t(`security_setting.${adminGeneralSecurityContainer.state.currentPageCompleteDeletionAuthority}`)}</span>
+                    <span className="pull-left">
+                      {currentPageCompleteDeletionAuthority === 'anyOne' && t('security_setting.anyone')}
+                      {currentPageCompleteDeletionAuthority === 'adminOnly' && t('security_setting.admin_only')}
+                      {currentPageCompleteDeletionAuthority === 'adminAndAuthor' && t('security_setting.admin_and_author')}
+                    </span>
                     <span className="bs-caret pull-right">
                       <span className="caret" />
                     </span>
@@ -167,7 +174,7 @@ class SecuritySetting extends React.Component {
                       key="anyone"
                       role="presentation"
                       type="button"
-                      onClick={() => { adminGeneralSecurityContainer.changePageCompleteDeletionAuthority('anyone') }}
+                      onClick={() => { adminGeneralSecurityContainer.changePageCompleteDeletionAuthority('anyOne') }}
                     >
                       <a role="menuitem">{t('security_setting.anyone')}</a>
                     </li>
@@ -175,7 +182,7 @@ class SecuritySetting extends React.Component {
                       key="admin_only"
                       role="presentation"
                       type="button"
-                      onClick={() => { adminGeneralSecurityContainer.changePageCompleteDeletionAuthority('admin_only') }}
+                      onClick={() => { adminGeneralSecurityContainer.changePageCompleteDeletionAuthority('adminOnly') }}
                     >
                       <a role="menuitem">{t('security_setting.admin_only')}</a>
                     </li>
@@ -183,23 +190,23 @@ class SecuritySetting extends React.Component {
                       key="admin_and_author"
                       role="presentation"
                       type="button"
-                      onClick={() => { adminGeneralSecurityContainer.changePageCompleteDeletionAuthority('admin_and_author') }}
+                      onClick={() => { adminGeneralSecurityContainer.changePageCompleteDeletionAuthority('adminAndAuthor') }}
                     >
                       <a role="menuitem">{t('security_setting.admin_and_author')}</a>
                     </li>
                   </ul>
-                  <p className="help-block small">
-                    {t('security_setting.complete_deletion_explain')}
-                  </p>
                 </div>
+                <p className="help-block small">
+                  {t('security_setting.complete_deletion_explain')}
+                </p>
               </div>
             </div>
           </div>
-          {/* TODO GW-540 */}
-          <div className="form-group">
-            <div className="col-xs-offset-3 col-xs-6">
-              <input type="hidden" name="_csrf" value={this.props.csrf} />
-              <button type="submit" className="btn btn-primary" onClick={this.putSecuritySetting}>{t('Update')}</button>
+          <div className="row my-3">
+            <div className="col-xs-offset-3 col-xs-5">
+              <button type="submit" className="btn btn-primary" disabled={this.state.retrieveError != null} onClick={this.putSecuritySetting}>
+                {t('Update')}
+              </button>
             </div>
           </div>
         </fieldset>

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

@@ -33,7 +33,7 @@ class TwitterSecurityManagement extends React.Component {
     }
     catch (err) {
       toastError(err);
-      this.setState({ retrieveError: err });
+      this.setState({ retrieveError: err.message });
       logger.error(err);
     }
   }
@@ -110,12 +110,6 @@ class TwitterSecurityManagement extends React.Component {
         {adminGeneralSecurityContainer.state.isTwitterEnabled && (
           <React.Fragment>
 
-            {!adminTwitterSecurityContainer.state.isTwitterStrategySetup && (
-              <div className="alert alert-warning">
-                <p>{t('security_setting.setup_not_completed_yet')}</p>
-              </div>
-            )}
-
             <div className="row mb-5">
               <label htmlFor="TwitterConsumerId" className="col-xs-3 text-right">{t('security_setting.clientID')}</label>
               <div className="col-xs-6">

+ 6 - 6
src/client/js/services/AdminGeneralSecurityContainer.js

@@ -21,7 +21,7 @@ export default class AdminGeneralSecurityContainer extends Container {
       isWikiModeForced: false,
       wikiMode: '',
       currentRestrictGuestMode: 'Deny',
-      currentPageCompleteDeletionAuthority: 'anyone',
+      currentPageCompleteDeletionAuthority: 'adminOnly',
       isHideRestrictedByOwner: false,
       isHideRestrictedByGroup: false,
       useOnlyEnvVarsForSomeOptions: false,
@@ -32,7 +32,7 @@ export default class AdminGeneralSecurityContainer extends Container {
       isOidcEnabled: false,
       isBasicEnabled: false,
       isGoogleEnabled: false,
-      isGithubEnabled: false,
+      isGitHubEnabled: false,
       isTwitterEnabled: false,
     };
 
@@ -44,7 +44,7 @@ export default class AdminGeneralSecurityContainer extends Container {
     const { generalSetting, generalAuth } = response.data.securityParams;
     this.onIsWikiModeForced(generalSetting.wikiMode);
     this.setState({
-      currentPageCompleteDeletionAuthority: generalSetting.pageCompleteDeletionAuthority || 'anyone',
+      currentPageCompleteDeletionAuthority: generalSetting.pageCompleteDeletionAuthority || 'anyOne',
       isHideRestrictedByOwner: generalSetting.hideRestrictedByOwner || false,
       isHideRestrictedByGroup: generalSetting.hideRestrictedByGroup || false,
       wikiMode: generalSetting.wikiMode || '',
@@ -54,7 +54,7 @@ export default class AdminGeneralSecurityContainer extends Container {
       isOidcEnabled: generalAuth.isOidcEnabled || false,
       isBasicEnabled: generalAuth.isBasicEnabled || false,
       isGoogleEnabled: generalAuth.isGoogleEnabled || false,
-      isGithubEnabled: generalAuth.isGithubEnabled || false,
+      isGitHubEnabled: generalAuth.isGitHubEnabled || false,
       isTwitterEnabled: generalAuth.isTwitterEnabled || false,
     });
   }
@@ -181,9 +181,9 @@ export default class AdminGeneralSecurityContainer extends Container {
   }
 
   /**
-   * Switch GithubOAuth enabled
+   * Switch GitHubOAuth enabled
    */
-  async switchIsGithubOAuthEnabled() {
+  async switchIsGitHubOAuthEnabled() {
     this.switchAuthentication('isGitHubEnabled', 'github');
   }
 

+ 6 - 8
src/client/js/services/AdminGithubSecurityConatainer.js → src/client/js/services/AdminGitHubSecurityContainer.js

@@ -6,13 +6,13 @@ import { pathUtils } from 'growi-commons';
 import urljoin from 'url-join';
 
 // eslint-disable-next-line no-unused-vars
-const logger = loggerFactory('growi:security:AdminGithubSecurityContainer');
+const logger = loggerFactory('growi:security:AdminGitHubSecurityContainer');
 
 /**
- * Service container for admin security page (GithubSecurityManagement.jsx)
+ * Service container for admin security page (GitHubSecurityManagement.jsx)
  * @extends {Container} unstated Container
  */
-export default class AdminGithubSecurityContainer extends Container {
+export default class AdminGitHubSecurityContainer extends Container {
 
   constructor(appContainer) {
     super();
@@ -21,7 +21,6 @@ export default class AdminGithubSecurityContainer extends Container {
 
     this.state = {
       appSiteUrl: urljoin(pathUtils.removeTrailingSlash(appContainer.config.crowi.url), '/passport/github/callback'),
-      isGitHubStrategySetup: false,
       githubClientId: '',
       githubClientSecret: '',
       isSameUsernameTreatedAsIdenticalUser: true,
@@ -36,7 +35,6 @@ export default class AdminGithubSecurityContainer extends Container {
     const response = await this.appContainer.apiv3.get('/security-setting/');
     const { githubOAuth } = response.data.securityParams;
     this.setState({
-      isGitHubStrategySetup: githubOAuth.isGitHubStrategySetup,
       githubClientId: githubOAuth.githubClientId || '',
       githubClientSecret: githubOAuth.githubClientSecret || '',
       isSameUsernameTreatedAsIdenticalUser: githubOAuth.isSameUsernameTreatedAsIdenticalUser || false,
@@ -47,20 +45,20 @@ export default class AdminGithubSecurityContainer extends Container {
    * Workaround for the mangling in production build to break constructor.name
    */
   static getClassName() {
-    return 'AdminGithubSecurityContainer';
+    return 'AdminGitHubSecurityContainer';
   }
 
   /**
    * Change githubClientId
    */
-  changeGithubClientId(value) {
+  changeGitHubClientId(value) {
     this.setState({ githubClientId: value });
   }
 
   /**
    * Change githubClientSecret
    */
-  changeGithubClientSecret(value) {
+  changeGitHubClientSecret(value) {
     this.setState({ githubClientSecret: value });
   }
 

+ 0 - 2
src/client/js/services/AdminGoogleSecurityContainer.js

@@ -21,7 +21,6 @@ export default class AdminGoogleSecurityContainer extends Container {
 
     this.state = {
       callbackUrl: urljoin(pathUtils.removeTrailingSlash(appContainer.config.crowi.url), '/passport/google/callback'),
-      isGoogleStrategySetup: false,
       googleClientId: '',
       googleClientSecret: '',
       isSameUsernameTreatedAsIdenticalUser: false,
@@ -37,7 +36,6 @@ export default class AdminGoogleSecurityContainer extends Container {
     const response = await this.appContainer.apiv3.get('/security-setting/');
     const { googleOAuth } = response.data.securityParams;
     this.setState({
-      isGoogleStrategySetup: googleOAuth.isGoogleStrategySetup,
       googleClientId: googleOAuth.googleClientId || '',
       googleClientSecret: googleOAuth.googleClientSecret || '',
       isSameUsernameTreatedAsIdenticalUser: googleOAuth.isSameUsernameTreatedAsIdenticalUser || false,

+ 0 - 2
src/client/js/services/AdminTwitterSecurityContainer.js

@@ -21,7 +21,6 @@ export default class AdminTwitterSecurityContainer extends Container {
 
     this.state = {
       callbackUrl: urljoin(pathUtils.removeTrailingSlash(appContainer.config.crowi.url), '/passport/twitter/callback'),
-      isTwitterStrategySetup: false,
       twitterConsumerKey: '',
       twitterConsumerSecret: '',
       isSameUsernameTreatedAsIdenticalUser: false,
@@ -36,7 +35,6 @@ export default class AdminTwitterSecurityContainer extends Container {
     const response = await this.appContainer.apiv3.get('/security-setting/');
     const { twitterOAuth } = response.data.securityParams;
     this.setState({
-      isTwitterStrategySetup: twitterOAuth.isTwitterStrategySetup,
       twitterConsumerKey: twitterOAuth.twitterConsumerKey || '',
       twitterConsumerSecret: twitterOAuth.twitterConsumerSecret || '',
       isSameUsernameTreatedAsIdenticalUser: twitterOAuth.isSameUsernameTreatedAsIdenticalUser || false,

+ 22 - 17
src/server/routes/apiv3/security-setting.js

@@ -13,10 +13,13 @@ const { body } = require('express-validator/check');
 const ErrorV3 = require('../../models/vo/error-apiv3');
 
 const validator = {
-  // TODO correct validator
   generalSetting: [
-    body('restrictGuestMode').isString(),
-    body('pageCompleteDeletionAuthority').isString(),
+    body('restrictGuestMode').isString().isIn([
+      'Deny', 'Readonly',
+    ]),
+    body('pageCompleteDeletionAuthority').isString().isIn([
+      'anyOne', 'adminOnly', 'adminAndAuthor',
+    ]),
     body('hideRestrictedByOwner').isBoolean(),
     body('hideRestrictedByGroup').isBoolean(),
   ],
@@ -27,7 +30,9 @@ const validator = {
     ]),
   ],
   localSetting: [
-    body('registrationMode').isString(),
+    body('registrationMode').isString().isIn([
+      'Open', 'Restricted', 'Closed',
+    ]),
     body('registrationWhiteList').isArray(),
   ],
   ldapAuth: [
@@ -289,7 +294,7 @@ module.exports = (crowi) => {
    *
    *    /_api/v3/security-setting/:
    *      get:
-   *        tags: [SecuritySetting]
+   *        tags: [SecuritySetting, apiv3]
    *        description: Get security paramators
    *        responses:
    *          200:
@@ -323,7 +328,7 @@ module.exports = (crowi) => {
         isOidcEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:isEnabled'),
         isBasicEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-basic:isEnabled'),
         isGoogleOAuthEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-google:isEnabled'),
-        isGithubOAuthEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-github:isEnabled'),
+        isGitHubOAuthEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-github:isEnabled'),
         isTwitterOAuthEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:isEnabled'),
       },
       ldapAuth: {
@@ -400,7 +405,7 @@ module.exports = (crowi) => {
    *
    *    /_api/v3/security-setting/authentication/enabled:
    *      put:
-   *        tags: [SecuritySetting]
+   *        tags: [SecuritySetting, apiv3]
    *        description: Update authentication isEnabled
    *        requestBody:
    *          required: true
@@ -431,7 +436,7 @@ module.exports = (crowi) => {
     setupStrategies = setupStrategies.filter(strategy => strategy !== authId);
 
     if (setupStrategies.length === 0) {
-      return res.apiv3Err(new ErrorV3('Can not turn everything off'));
+      return res.apiv3Err(new ErrorV3('Can not turn everything off'), 405);
     }
 
     const enableParams = { [`security:passport-${authId}:isEnabled`]: isEnabled };
@@ -459,7 +464,7 @@ module.exports = (crowi) => {
    *
    *    /_api/v3/security-setting/general-setting:
    *      put:
-   *        tags: [SecuritySetting]
+   *        tags: [SecuritySetting, apiv3]
    *        description: Update GeneralSetting
    *        requestBody:
    *          required: true
@@ -509,7 +514,7 @@ module.exports = (crowi) => {
    *
    *    /_api/v3/security-setting/local-setting:
    *      put:
-   *        tags: [LocalSetting]
+   *        tags: [LocalSetting, apiv3]
    *        description: Update LocalSetting
    *        requestBody:
    *          required: true
@@ -551,7 +556,7 @@ module.exports = (crowi) => {
    *
    *    /_api/v3/security-setting/ldap:
    *      put:
-   *        tags: [SecuritySetting]
+   *        tags: [SecuritySetting, apiv3]
    *        description: Update LDAP setting
    *        requestBody:
    *          required: true
@@ -614,7 +619,7 @@ module.exports = (crowi) => {
    *
    *    /_api/v3/security-setting/saml:
    *      put:
-   *        tags: [SecuritySetting]
+   *        tags: [SecuritySetting, apiv3]
    *        description: Update SAML setting
    *        requestBody:
    *          required: true
@@ -674,7 +679,7 @@ module.exports = (crowi) => {
    *
    *    /_api/v3/security-setting/oidc:
    *      put:
-   *        tags: [SecuritySetting]
+   *        tags: [SecuritySetting, apiv3]
    *        description: Update OpenID Connect setting
    *        requestBody:
    *          required: true
@@ -733,7 +738,7 @@ module.exports = (crowi) => {
    *
    *    /_api/v3/security-setting/basic:
    *      put:
-   *        tags: [SecuritySetting]
+   *        tags: [SecuritySetting, apiv3]
    *        description: Update basic
    *        requestBody:
    *          required: true
@@ -774,7 +779,7 @@ module.exports = (crowi) => {
    *
    *    /_api/v3/security-setting/google-oauth:
    *      put:
-   *        tags: [SecuritySetting]
+   *        tags: [SecuritySetting, apiv3]
    *        description: Update google OAuth
    *        requestBody:
    *          required: true
@@ -820,7 +825,7 @@ module.exports = (crowi) => {
    *
    *    /_api/v3/security-setting/github-oauth:
    *      put:
-   *        tags: [SecuritySetting]
+   *        tags: [SecuritySetting, apiv3]
    *        description: Update github OAuth
    *        requestBody:
    *          required: true
@@ -868,7 +873,7 @@ module.exports = (crowi) => {
    *
    *    /_api/v3/security-setting/twitter-oauth:
    *      put:
-   *        tags: [SecuritySetting]
+   *        tags: [SecuritySetting, apiv3]
    *        description: Update twitter OAuth
    *        requestBody:
    *          required: true