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

Merge branch 'master' into feat/display-plugin-cards-dynamically

jam411 3 лет назад
Родитель
Сommit
8bc53366cb
39 измененных файлов с 175 добавлено и 840 удалено
  1. 0 1
      packages/app/_obsolete/src/client/nologin.jsx
  2. 0 1
      packages/app/package.json
  3. 0 15
      packages/app/public/static/locales/en_US/admin.json
  4. 2 2
      packages/app/public/static/locales/en_US/translation.json
  5. 0 15
      packages/app/public/static/locales/ja_JP/admin.json
  6. 2 2
      packages/app/public/static/locales/ja_JP/translation.json
  7. 0 15
      packages/app/public/static/locales/zh_CN/admin.json
  8. 2 2
      packages/app/public/static/locales/zh_CN/translation.json
  9. 0 9
      packages/app/src/client/services/AdminGeneralSecurityContainer.js
  10. 0 104
      packages/app/src/client/services/AdminTwitterSecurityContainer.js
  11. 2 2
      packages/app/src/components/Admin/Security/FacebookSecuritySetting.jsx
  12. 8 17
      packages/app/src/components/Admin/Security/SecurityManagementContents.jsx
  13. 0 41
      packages/app/src/components/Admin/Security/TwitterSecuritySetting.jsx
  14. 0 223
      packages/app/src/components/Admin/Security/TwitterSecuritySettingContents.jsx
  15. 1 1
      packages/app/src/components/CompleteUserRegistration.tsx
  16. 0 4
      packages/app/src/components/Layout/NoLoginLayout.module.scss
  17. 12 3
      packages/app/src/components/LoginForm.tsx
  18. 2 8
      packages/app/src/components/Me/AssociateModal.tsx
  19. 0 25
      packages/app/src/components/PageEditor/OptionsSelector.tsx
  20. 2 3
      packages/app/src/components/PageEditorByHackmd.tsx
  21. 0 12
      packages/app/src/interfaces/activity.ts
  22. 0 1
      packages/app/src/interfaces/editor-settings.ts
  23. 0 1
      packages/app/src/migrations/20180927102719-init-serverurl.js
  24. 0 3
      packages/app/src/pages/admin/security.page.tsx
  25. 133 0
      packages/app/src/pages/login/error/[message].page.tsx
  26. 4 6
      packages/app/src/pages/login/index.page.tsx
  27. 0 1
      packages/app/src/server/crowi/index.js
  28. 0 5
      packages/app/src/server/models/config.ts
  29. 0 1
      packages/app/src/server/models/editor-settings.ts
  30. 2 3
      packages/app/src/server/routes/apiv3/personal-setting.js
  31. 1 81
      packages/app/src/server/routes/apiv3/security-setting.js
  32. 1 3
      packages/app/src/server/routes/index.js
  33. 1 46
      packages/app/src/server/routes/login-passport.js
  34. 0 18
      packages/app/src/server/routes/login.js
  35. 0 18
      packages/app/src/server/service/config-loader.ts
  36. 0 59
      packages/app/src/server/service/passport.ts
  37. 0 1
      packages/app/src/server/views/login.html
  38. 0 62
      packages/app/src/server/views/login/error.html
  39. 0 26
      yarn.lock

+ 0 - 1
packages/app/_obsolete/src/client/nologin.jsx

@@ -49,7 +49,6 @@ if (loginFormElem) {
     google: loginFormElem.dataset.isGoogleAuthEnabled === 'true',
     github: loginFormElem.dataset.isGithubAuthEnabled === 'true',
     facebook: loginFormElem.dataset.isFacebookAuthEnabled === 'true',
-    twitter: loginFormElem.dataset.isTwitterAuthEnabled === 'true',
     saml: loginFormElem.dataset.isSamlAuthEnabled === 'true',
     oidc: loginFormElem.dataset.isOidcAuthEnabled === 'true',
   };

+ 0 - 1
packages/app/package.json

@@ -148,7 +148,6 @@
     "passport-ldapauth": "^3.0.1",
     "passport-local": "^1.0.0",
     "passport-saml": "^3.2.0",
-    "passport-twitter": "^1.0.4",
     "rate-limiter-flexible": "^2.3.7",
     "react": "^18.2.0",
     "react-bootstrap-typeahead": "^5.2.2",

+ 0 - 15
packages/app/public/static/locales/en_US/admin.json

@@ -174,16 +174,6 @@
       "Facebook": {
         "name": "Facebook OAuth"
       },
-      "Twitter": {
-        "enable_twitter": "Enable Twitter OAuth",
-        "name": "Twitter OAuth",
-        "register_1": "Access {{link}}",
-        "register_2": "Sign in Twitter",
-        "register_3": "Create Credentials → OAuth client ID → Select \"Web application\"",
-        "register_4": "Register your OAuth App with one of Authorized redirect URIs as <code>{{url}}</code>",
-        "register_5": "Copy and paste your ClientID and Client Secret above",
-        "updated_twitter": "Succeeded to update Twitter OAuth setting"
-      },
       "GitHub": {
         "enable_github": "Enable GitHub OAuth",
         "name": "GitHub OAuth",
@@ -207,7 +197,6 @@
       "how_to": {
         "google": "How to configure Google OAuth?",
         "github": "How to configure GitHub OAuth?",
-        "twitter": "How to configure Twitter OAuth?",
         "oidc": "How to configure OIDC?"
       }
     },
@@ -881,7 +870,6 @@
     "USER_LOGIN_WITH_LDAP": "Login with LDAP",
     "USER_LOGIN_WITH_GOOGLE": "Login with Google",
     "USER_LOGIN_WITH_GITHUB": "Login with GitHub",
-    "USER_LOGIN_WITH_TWITTER": "Login with Twitter",
     "USER_LOGIN_WITH_OIDC": "Login with OIDC",
     "USER_LOGIN_WITH_SAML": "Login with SAML",
     "USER_LOGIN_FAILURE": "Login failure",
@@ -967,9 +955,6 @@
     "ADMIN_AUTH_GITHUB_ENABLED": "Enable GitHub auth",
     "ADMIN_AUTH_GITHUB_DISABLED": "Disable GitHub auth",
     "ADMIN_AUTH_GITHUB_UPDATE": "Update GitHub auth settings",
-    "ADMIN_AUTH_TWITTER_ENABLED": "Enable Twitter auth",
-    "ADMIN_AUTH_TWITTER_DISABLED": "Disable Twitter auth",
-    "ADMIN_AUTH_TWITTER_UPDATE": "Update Twitter auth settings",
     "ADMIN_MARKDOWN_LINE_BREAK_UPDATE": "Update Link Break settings",
     "ADMIN_MARKDOWN_INDENT_UPDATE": "Update Indent settings",
     "ADMIN_MARKDOWN_PRESENTATION_UPDATE": "Update Presentation setting",

+ 2 - 2
packages/app/public/static/locales/en_US/translation.json

@@ -605,8 +605,8 @@
     }
   },
   "login": {
-    "Sign in error": "Login error",
-    "Registration successful": "Registration successful. Please wait for administrator approval.",
+    "sign_in_error": "Login error",
+    "registration_successful": "registration_successful. Please wait for administrator approval.",
     "Setup": "Setup",
     "enabled_ldap_has_configuration_problem":"LDAP is enabled but the configuration has something wrong.",
     "set_env_var_for_logs": "(Please set the environment variables <code>DEBUG=crowi:service:PassportService</code> to get the logs)"

+ 0 - 15
packages/app/public/static/locales/ja_JP/admin.json

@@ -182,16 +182,6 @@
       "Facebook": {
         "name": "Facebook OAuth"
       },
-      "Twitter": {
-        "enable_twitter": "Twitter OAuth を有効にする",
-        "name": "Twitter OAuth",
-        "register_1": "{{link}} へアクセス",
-        "register_2": "Twitterにサインイン",
-        "register_3": "Create New Appをクリック &rightarrow; Application Detailsの各項目を入力",
-        "register_4": "Create your Twitter Applicationで作成",
-        "register_5": "上記フォームにクライアントIDとクライアントシークレットを入力",
-        "updated_twitter": "Twitter OAuth を更新しました"
-      },
       "GitHub": {
         "enable_github": "GitHub OAuth を有効にする",
         "name": "GitHub OAuth",
@@ -215,7 +205,6 @@
       "how_to": {
         "google": "Google OAuth の設定方法",
         "github": "GitHub OAuth の設定方法",
-        "twitter": "Twitter OAuth の設定方法",
         "oidc": "OIDC の設定方法"
       }
     },
@@ -889,7 +878,6 @@
     "USER_LOGIN_WITH_LDAP": "LDAP 認証でログイン",
     "USER_LOGIN_WITH_GOOGLE": "Google 認証でログイン",
     "USER_LOGIN_WITH_GITHUB": "GitHub 認証でログイン",
-    "USER_LOGIN_WITH_TWITTER": "Twitter 認証でログイン",
     "USER_LOGIN_WITH_OIDC": "OIDC 認証でログイン",
     "USER_LOGIN_WITH_SAML": "SAML 認証でログイン",
     "USER_LOGIN_FAILURE": "ログイン失敗",
@@ -975,9 +963,6 @@
     "ADMIN_AUTH_GITHUB_ENABLED": "GitHub 認証の有効",
     "ADMIN_AUTH_GITHUB_DISABLED": "GitHub 認証の無効",
     "ADMIN_AUTH_GITHUB_UPDATE": "GitHub 認証設定の更新",
-    "ADMIN_AUTH_TWITTER_ENABLED": "Twitter 認証の有効",
-    "ADMIN_AUTH_TWITTER_DISABLED": "Twitter 認証の無効",
-    "ADMIN_AUTH_TWITTER_UPDATE": "Twitter 認証設定の更新",
     "ADMIN_MARKDOWN_LINE_BREAK_UPDATE": "Line Break 設定の更新",
     "ADMIN_MARKDOWN_INDENT_UPDATE": "インデント設定の更新",
     "ADMIN_MARKDOWN_PRESENTATION_UPDATE": "プレゼンテーション設定の更新",

+ 2 - 2
packages/app/public/static/locales/ja_JP/translation.json

@@ -604,8 +604,8 @@
     }
   },
   "login": {
-    "Sign in error": "ログインエラー",
-    "Registration successful": "登録が完了しました。管理者の承認をお待ちください。",
+    "sign_in_error": "ログインエラー",
+    "registration_successful": "登録が完了しました。管理者の承認をお待ちください。",
     "Setup": "セットアップ",
     "enabled_ldap_has_configuration_problem":"LDAPは有効ですが、設定に問題があります。",
     "set_env_var_for_logs": "(ログを取得するためには、環境変数 <code>DEBUG=crowi:service:PassportService</code> を設定してください。)"

+ 0 - 15
packages/app/public/static/locales/zh_CN/admin.json

@@ -182,16 +182,6 @@
 			"Facebook": {
 				"name": "Facebook OAuth"
 			},
-			"Twitter": {
-				"enable_twitter": "Enable Twitter OAuth",
-				"name": "Twitter OAuth",
-				"register_1": "Access {{link}}",
-				"register_2": "Sign in Twitter",
-				"register_3": "Create Credentials &rightarrow; OAuth client ID &rightarrow; Select \"Web application\"",
-				"register_4": "Register your OAuth App with one of Authorized redirect URIs as <code>{{url}}</code>",
-				"register_5": "Copy and paste your ClientID and Client Secret above",
-				"updated_twitter": "Succeeded to update Twitter OAuth setting"
-			},
 			"GitHub": {
 				"enable_github": "Enable GitHub OAuth",
 				"name": "GitHub OAuth",
@@ -215,7 +205,6 @@
 			"how_to": {
 				"google": "How to configure Google OAuth?",
 				"github": "How to configure GitHub OAuth?",
-				"twitter": "How to configure Twitter OAuth?",
 				"oidc": "How to configure OIDC?"
 			}
 		},
@@ -889,7 +878,6 @@
     "USER_LOGIN_WITH_LDAP": "使用 LDAP 登录",
     "USER_LOGIN_WITH_GOOGLE": "用谷歌登录",
     "USER_LOGIN_WITH_GITHUB": "使用 GitHub 登录",
-    "USER_LOGIN_WITH_TWITTER": "使用 Twitter 登录",
     "USER_LOGIN_WITH_OIDC": "使用 OIDC 登录",
     "USER_LOGIN_WITH_SAML": "使用 SAML 登录",
     "USER_LOGIN_FAILURE": "登录失败",
@@ -975,9 +963,6 @@
     "ADMIN_AUTH_GITHUB_ENABLED": "启用 GitHub 身份验证",
     "ADMIN_AUTH_GITHUB_DISABLED": "禁用 GitHub 身份验证",
     "ADMIN_AUTH_GITHUB_UPDATE": "更新 GitHub 授权设置",
-    "ADMIN_AUTH_TWITTER_ENABLED": "启用 Twitter 身份验证",
-    "ADMIN_AUTH_TWITTER_DISABLED": "禁用 Twitter 身份验证",
-    "ADMIN_AUTH_TWITTER_UPDATE": "更新 Twitter 授权设置",
     "ADMIN_MARKDOWN_LINE_BREAK_UPDATE": "更新链接中断设置",
     "ADMIN_MARKDOWN_INDENT_UPDATE": "更新缩进设置",
     "ADMIN_MARKDOWN_PRESENTATION_UPDATE": "更新演示设置",

+ 2 - 2
packages/app/public/static/locales/zh_CN/translation.json

@@ -609,8 +609,8 @@
     }
   },
 	"login": {
-		"Sign in error": "登录错误",
-		"Registration successful": "注册成功。请等待管理员批准",
+		"sign_in_error": "登录错误",
+		"registration_successful": "注册成功。请等待管理员批准",
 		"Setup": "安装程序",
     "enabled_ldap_has_configuration_problem":"启用了LDAP,但配置有问题。",
     "set_env_var_for_logs": "(请设置环境变量 <code>DEBUG=crowi:service:PassportService</code> 以获得日志。)"

+ 0 - 9
packages/app/src/client/services/AdminGeneralSecurityContainer.js

@@ -44,7 +44,6 @@ export default class AdminGeneralSecurityContainer extends Container {
       isOidcEnabled: false,
       isGoogleEnabled: false,
       isGitHubEnabled: false,
-      isTwitterEnabled: false,
       setupStrategies: [],
       disableLinkSharing: false,
       shareLinks: [],
@@ -83,7 +82,6 @@ export default class AdminGeneralSecurityContainer extends Container {
       isOidcEnabled: generalAuth.isOidcEnabled,
       isGoogleEnabled: generalAuth.isGoogleEnabled,
       isGitHubEnabled: generalAuth.isGitHubEnabled,
-      isTwitterEnabled: generalAuth.isTwitterEnabled,
     });
   }
 
@@ -330,11 +328,4 @@ export default class AdminGeneralSecurityContainer extends Container {
     this.switchAuthentication('isGitHubEnabled', 'github');
   }
 
-  /**
-   * Switch TwitterOAuth enabled
-   */
-  async switchIsTwitterOAuthEnabled() {
-    this.switchAuthentication('isTwitterEnabled', 'twitter');
-  }
-
 }

+ 0 - 104
packages/app/src/client/services/AdminTwitterSecurityContainer.js

@@ -1,104 +0,0 @@
-import { isServer, pathUtils } from '@growi/core';
-import { Container } from 'unstated';
-import urljoin from 'url-join';
-
-import loggerFactory from '~/utils/logger';
-import { removeNullPropertyFromObject } from '~/utils/object-utils';
-
-import { apiv3Get, apiv3Put } from '../util/apiv3-client';
-
-const logger = loggerFactory('growi:security:AdminTwitterSecurityContainer');
-
-/**
- * Service container for admin security page (TwitterSecurityManagement.jsx)
- * @extends {Container} unstated Container
- */
-export default class AdminTwitterSecurityContainer extends Container {
-
-  constructor(appContainer) {
-    super();
-
-    if (isServer()) {
-      return;
-    }
-
-    this.appContainer = appContainer;
-
-    this.state = {
-      twitterConsumerKey: '',
-      twitterConsumerSecret: '',
-      isSameUsernameTreatedAsIdenticalUser: false,
-    };
-
-    this.updateTwitterSetting = this.updateTwitterSetting.bind(this);
-  }
-
-  /**
-   * retrieve security data
-   */
-  async retrieveSecurityData() {
-    try {
-      const response = await apiv3Get('/security-setting/');
-      const { twitterOAuth } = response.data.securityParams;
-      this.setState({
-        twitterConsumerKey: twitterOAuth.twitterConsumerKey,
-        twitterConsumerSecret: twitterOAuth.twitterConsumerSecret,
-        isSameUsernameTreatedAsIdenticalUser: twitterOAuth.isSameUsernameTreatedAsIdenticalUser,
-      });
-    }
-    catch (err) {
-      this.setState({ retrieveError: err });
-      logger.error(err);
-      throw new Error('Failed to fetch data');
-    }
-  }
-
-  /**
-   * Workaround for the mangling in production build to break constructor.name
-   */
-  static getClassName() {
-    return 'AdminTwitterSecurityContainer';
-  }
-
-  /**
-   * Change twitterConsumerKey
-   */
-  changeTwitterConsumerKey(value) {
-    this.setState({ twitterConsumerKey: value });
-  }
-
-  /**
-   * Change twitterConsumerSecret
-   */
-  changeTwitterConsumerSecret(value) {
-    this.setState({ twitterConsumerSecret: value });
-  }
-
-  /**
-   * Switch isSameUsernameTreatedAsIdenticalUser
-   */
-  switchIsSameUsernameTreatedAsIdenticalUser() {
-    this.setState({ isSameUsernameTreatedAsIdenticalUser: !this.state.isSameUsernameTreatedAsIdenticalUser });
-  }
-
-  /**
-   * Update twitterSetting
-   */
-  async updateTwitterSetting() {
-    const { twitterConsumerKey, twitterConsumerSecret, isSameUsernameTreatedAsIdenticalUser } = this.state;
-
-    let requestParams = { twitterConsumerKey, twitterConsumerSecret, isSameUsernameTreatedAsIdenticalUser };
-
-    requestParams = await removeNullPropertyFromObject(requestParams);
-    const response = await apiv3Put('/security-setting/twitter-oauth', requestParams);
-    const { securitySettingParams } = response.data;
-
-    this.setState({
-      twitterConsumerKey: securitySettingParams.twitterConsumerKey,
-      twitterConsumerSecret: securitySettingParams.twitterConsumerSecret,
-      isSameUsernameTreatedAsIdenticalUser: securitySettingParams.isSameUsernameTreatedAsIdenticalUser,
-    });
-    return response;
-  }
-
-}

+ 2 - 2
packages/app/src/components/Admin/Security/FacebookSecuritySetting.jsx

@@ -31,6 +31,6 @@ FacebookSecurityManagement.propTypes = {
   adminGeneralSecurityContainer: PropTypes.instanceOf(AdminGeneralSecurityContainer).isRequired,
 };
 
-const TwitterSecurityManagementWrapper = withUnstatedContainers(FacebookSecurityManagement, [AdminGeneralSecurityContainer]);
+const FacebookSecurityManagementWrapper = withUnstatedContainers(FacebookSecurityManagement, [AdminGeneralSecurityContainer]);
 
-export default withTranslation()(TwitterSecurityManagementWrapper);
+export default withTranslation()(FacebookSecurityManagementWrapper);

+ 8 - 17
packages/app/src/components/Admin/Security/SecurityManagementContents.jsx

@@ -6,7 +6,7 @@ import { TabContent, TabPane } from 'reactstrap';
 
 import CustomNav from '../../CustomNavigation/CustomNav';
 
-import FacebookSecuritySetting from './FacebookSecuritySetting';
+// import FacebookSecuritySetting from './FacebookSecuritySetting';
 import GitHubSecuritySetting from './GitHubSecuritySetting';
 import GoogleSecuritySetting from './GoogleSecuritySetting';
 import LdapSecuritySetting from './LdapSecuritySetting';
@@ -15,7 +15,6 @@ import OidcSecuritySetting from './OidcSecuritySetting';
 import SamlSecuritySetting from './SamlSecuritySetting';
 import SecuritySetting from './SecuritySetting';
 import ShareLinkSetting from './ShareLinkSetting';
-import TwitterSecuritySetting from './TwitterSecuritySetting';
 
 const SecurityManagementContents = () => {
   const { t } = useTranslation('admin');
@@ -60,16 +59,11 @@ const SecurityManagementContents = () => {
         i18n: 'GitHub',
         index: 5,
       },
-      passport_twitter: {
-        Icon: () => <i className="fa fa-twitter" />,
-        i18n: 'Twitter',
-        index: 6,
-      },
-      passport_facebook: {
-        Icon: () => <i className="fa fa-facebook" />,
-        i18n: '(TBD) Facebook',
-        index: 7,
-      },
+      // passport_facebook: {
+      //   Icon: () => <i className="fa fa-facebook" />,
+      //   i18n: '(TBD) Facebook',
+      //   index: 7,
+      // },
     };
   }, []);
 
@@ -126,12 +120,9 @@ const SecurityManagementContents = () => {
           <TabPane tabId="passport_github">
             {activeComponents.has('passport_github') && <GitHubSecuritySetting />}
           </TabPane>
-          <TabPane tabId="passport_twitter">
-            {activeComponents.has('passport_twitter') && <TwitterSecuritySetting />}
-          </TabPane>
-          <TabPane tabId="passport_facebook">
+          {/* <TabPane tabId="passport_facebook">
             {activeComponents.has('passport_facebook') && <FacebookSecuritySetting />}
-          </TabPane>
+          </TabPane> */}
         </TabContent>
       </div>
     </div>

+ 0 - 41
packages/app/src/components/Admin/Security/TwitterSecuritySetting.jsx

@@ -1,41 +0,0 @@
-import React, { useEffect, useCallback } from 'react';
-
-import PropTypes from 'prop-types';
-
-import AdminTwitterSecurityContainer from '~/client/services/AdminTwitterSecurityContainer';
-import { toastError } from '~/client/util/apiNotification';
-import { toArrayIfNot } from '~/utils/array-utils';
-
-import { withUnstatedContainers } from '../../UnstatedUtils';
-
-import TwitterSecuritySettingContents from './TwitterSecuritySettingContents';
-
-const TwitterSecurityManagement = (props) => {
-  const { adminTwitterSecurityContainer } = props;
-
-  const fetchTwitterSecuritySettingsData = useCallback(async() => {
-    try {
-      await adminTwitterSecurityContainer.retrieveSecurityData();
-    }
-    catch (err) {
-      const errs = toArrayIfNot(err);
-      toastError(errs);
-    }
-  }, [adminTwitterSecurityContainer]);
-
-  useEffect(() => {
-    fetchTwitterSecuritySettingsData();
-  }, [adminTwitterSecurityContainer, fetchTwitterSecuritySettingsData]);
-
-  return <TwitterSecuritySettingContents />;
-};
-
-TwitterSecurityManagement.propTypes = {
-  adminTwitterSecurityContainer: PropTypes.instanceOf(AdminTwitterSecurityContainer).isRequired,
-};
-
-const TwitterSecurityManagementWithUnstatedContainer = withUnstatedContainers(TwitterSecurityManagement, [
-  AdminTwitterSecurityContainer,
-]);
-
-export default TwitterSecurityManagementWithUnstatedContainer;

+ 0 - 223
packages/app/src/components/Admin/Security/TwitterSecuritySettingContents.jsx

@@ -1,223 +0,0 @@
-/* eslint-disable react/no-danger */
-import React from 'react';
-
-import { pathUtils } from '@growi/core';
-import { useTranslation } from 'next-i18next';
-import PropTypes from 'prop-types';
-import urljoin from 'url-join';
-
-
-import AdminGeneralSecurityContainer from '~/client/services/AdminGeneralSecurityContainer';
-import AdminTwitterSecurityContainer from '~/client/services/AdminTwitterSecurityContainer';
-import { toastSuccess, toastError } from '~/client/util/apiNotification';
-import { useSiteUrl } from '~/stores/context';
-
-import { withUnstatedContainers } from '../../UnstatedUtils';
-
-class TwitterSecuritySettingContents extends React.Component {
-
-  constructor(props) {
-    super(props);
-
-    this.onClickSubmit = this.onClickSubmit.bind(this);
-  }
-
-  async onClickSubmit() {
-    const { t, adminTwitterSecurityContainer, adminGeneralSecurityContainer } = this.props;
-
-    try {
-      await adminTwitterSecurityContainer.updateTwitterSetting();
-      await adminGeneralSecurityContainer.retrieveSetupStratedies();
-      toastSuccess(t('security_settings.OAuth.Twitter.updated_twitter'));
-    }
-    catch (err) {
-      toastError(err);
-    }
-  }
-
-  render() {
-    const {
-      t, adminGeneralSecurityContainer, adminTwitterSecurityContainer, siteUrl,
-    } = this.props;
-    const { isTwitterEnabled } = adminGeneralSecurityContainer.state;
-    const twitterCallbackUrl = urljoin(pathUtils.removeTrailingSlash(siteUrl), '/passport/twitter/callback');
-
-    return (
-
-      <React.Fragment>
-
-        <h2 className="alert-anchor border-bottom">
-          {t('security_settings.OAuth.Twitter.name')}
-        </h2>
-
-        {adminTwitterSecurityContainer.state.retrieveError != null && (
-          <div className="alert alert-danger">
-            <p>{t('Error occurred')} : {adminTwitterSecurityContainer.state.retrieveError}</p>
-          </div>
-        )}
-
-        <div className="form-group row">
-          <div className="col-6 offset-3">
-            <div className="custom-control custom-switch custom-checkbox-success">
-              <input
-                id="isTwitterEnabled"
-                className="custom-control-input"
-                type="checkbox"
-                checked={adminGeneralSecurityContainer.state.isTwitterEnabled}
-                onChange={() => { adminGeneralSecurityContainer.switchIsTwitterOAuthEnabled() }}
-              />
-              <label className="custom-control-label" htmlFor="isTwitterEnabled">
-                {t('security_settings.OAuth.Twitter.enable_twitter')}
-              </label>
-            </div>
-            {(!adminGeneralSecurityContainer.state.setupStrategies.includes('twitter') && isTwitterEnabled)
-              && <div className="badge badge-warning">{t('security_settings.setup_is_not_yet_complete')}</div>}
-          </div>
-        </div>
-
-        <div className="row mb-5">
-          <label className="col-md-3 text-md-right py-2">{t('security_settings.callback_URL')}</label>
-          <div className="col-md-6">
-            <input
-              className="form-control"
-              type="text"
-              value={twitterCallbackUrl}
-              readOnly
-            />
-            <p className="form-text text-muted small">{t('security_settings.desc_of_callback_URL', { AuthName: 'OAuth' })}</p>
-            {(siteUrl == null || siteUrl === '') && (
-              <div className="alert alert-danger">
-                <i
-                  className="icon-exclamation"
-                  // eslint-disable-next-line max-len
-                  dangerouslySetInnerHTML={{ __html: t('alert.siteUrl_is_not_set', { link: `<a href="/admin/app">${t('headers.app_settings', { ns: 'commons' })}<i class="icon-login"></i></a>`, ns: 'commons' }) }}
-                />
-              </div>
-            )}
-          </div>
-        </div>
-
-
-        {isTwitterEnabled && (
-          <React.Fragment>
-
-            <h3 className="border-bottom">{t('security_settings.configuration')}</h3>
-
-            <div className="row mb-5">
-              <label htmlFor="TwitterConsumerId" className="col-md-3 text-md-right py-2">{t('security_settings.clientID')}</label>
-              <div className="col-md-6">
-                <input
-                  className="form-control"
-                  type="text"
-                  name="TwitterConsumerId"
-                  defaultValue={adminTwitterSecurityContainer.state.twitterConsumerKey || ''}
-                  onChange={e => adminTwitterSecurityContainer.changeTwitterConsumerKey(e.target.value)}
-                />
-                <p className="form-text text-muted">
-                  <small dangerouslySetInnerHTML={{ __html: t('security_settings.Use env var if empty', { env: 'OAUTH_TWITTER_CONSUMER_KEY' }) }} />
-                </p>
-              </div>
-            </div>
-
-            <div className="row mb-5">
-              <label htmlFor="TwitterConsumerSecret" className="col-md-3 text-md-right py-2">{t('security_settings.client_secret')}</label>
-              <div className="col-md-6">
-                <input
-                  className="form-control"
-                  type="text"
-                  name="TwitterConsumerSecret"
-                  defaultValue={adminTwitterSecurityContainer.state.twitterConsumerSecret || ''}
-                  onChange={e => adminTwitterSecurityContainer.changeTwitterConsumerSecret(e.target.value)}
-                />
-                <p className="form-text text-muted">
-                  <small dangerouslySetInnerHTML={{ __html: t('security_settings.Use env var if empty', { env: 'OAUTH_TWITTER_CONSUMER_SECRET' }) }} />
-                </p>
-              </div>
-            </div>
-
-            <div className="row mb-5">
-              <div className="offset-md-3 col-md-6">
-                <div className="custom-control custom-checkbox custom-checkbox-success">
-                  <input
-                    id="bindByUserNameTwitter"
-                    className="custom-control-input"
-                    type="checkbox"
-                    checked={adminTwitterSecurityContainer.state.isSameUsernameTreatedAsIdenticalUser || false}
-                    onChange={() => { adminTwitterSecurityContainer.switchIsSameUsernameTreatedAsIdenticalUser() }}
-                  />
-                  <label
-                    className="custom-control-label"
-                    htmlFor="bindByUserNameTwitter"
-                    dangerouslySetInnerHTML={{ __html: t('security_settings.Treat email matching as identical') }}
-                  />
-                </div>
-                <p className="form-text text-muted">
-                  <small dangerouslySetInnerHTML={{ __html: t('security_settings.Treat email matching as identical_warn') }} />
-                </p>
-              </div>
-            </div>
-
-            <div className="row my-3">
-              <div className="offset-4 col-5">
-                <button
-                  type="button"
-                  className="btn btn-primary"
-                  disabled={adminTwitterSecurityContainer.state.retrieveError != null}
-                  onClick={this.onClickSubmit}
-                >
-                  {t('Update')}
-                </button>
-              </div>
-            </div>
-
-          </React.Fragment>
-        )}
-
-        <hr />
-
-        <div style={{ minHeight: '300px' }}>
-          <h4>
-            <i className="icon-question" aria-hidden="true"></i>
-            <a href="#collapseHelpForTwitterOauth" data-toggle="collapse"> {t('security_settings.OAuth.how_to.twitter')}</a>
-          </h4>
-          <ol id="collapseHelpForTwitterOauth" className="collapse">
-            {/* eslint-disable-next-line max-len */}
-            <li dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.Twitter.register_1', { link: '<a href="https://apps.twitter.com/" target=_blank>Twitter Application Management</a>' }) }} />
-            <li dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.Twitter.register_2') }} />
-            <li dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.Twitter.register_3') }} />
-            {/* eslint-disable-next-line max-len */}
-            <li dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.Twitter.register_4', { url: adminTwitterSecurityContainer.state.callbackUrl }) }} />
-            <li dangerouslySetInnerHTML={{ __html: t('security_settings.OAuth.Twitter.register_5') }} />
-          </ol>
-        </div>
-
-      </React.Fragment>
-
-
-    );
-  }
-
-}
-
-TwitterSecuritySettingContents.propTypes = {
-  t: PropTypes.func.isRequired, // i18next
-  adminGeneralSecurityContainer: PropTypes.instanceOf(AdminGeneralSecurityContainer).isRequired,
-  adminTwitterSecurityContainer: PropTypes.instanceOf(AdminTwitterSecurityContainer).isRequired,
-  siteUrl: PropTypes.string,
-};
-
-const TwitterSecuritySettingContentsWrapperFC = (props) => {
-  const { t } = useTranslation('admin');
-  const { data: siteUrl } = useSiteUrl();
-  return <TwitterSecuritySettingContents t={t} siteUrl={siteUrl} {...props} />;
-};
-
-/**
- * Wrapper component for using unstated
- */
-const TwitterSecuritySettingContentsWrapper = withUnstatedContainers(TwitterSecuritySettingContentsWrapperFC, [
-  AdminGeneralSecurityContainer,
-  AdminTwitterSecurityContainer,
-]);
-
-export default TwitterSecuritySettingContentsWrapper;

+ 1 - 1
packages/app/src/components/CompleteUserRegistration.tsx

@@ -11,7 +11,7 @@ export const CompleteUserRegistration: FC = () => {
       <div className="row mx-0">
         <div className="col-12 mb-3 text-center">
           <p className="alert alert-success">
-            <span>{t('login.Registration successful')}</span>
+            <span>{t('login.registration_successful')}</span>
           </p>
           {/* If the transition source is "/login", use <a /> tag since the transition will not occur if next/link is used. */}
           <a href='/login'>

+ 0 - 4
packages/app/src/components/Layout/NoLoginLayout.module.scss

@@ -100,10 +100,6 @@
       rgba(#29487d, 0.4),
       $gray-700,
     ),
-    'twitter': (
-      rgba(#1da1f2, 0.4),
-      $gray-700,
-    ),
     'oidc': (
       rgba(#24292e, 0.4),
       $gray-700,

+ 12 - 3
packages/app/src/components/LoginForm.tsx

@@ -2,6 +2,7 @@ import React, {
   useState, useEffect, useCallback,
 } from 'react';
 
+import { USER_STATUS } from '@growi/core';
 import { useTranslation } from 'next-i18next';
 import { useRouter } from 'next/router';
 import ReactCardFlip from 'react-card-flip';
@@ -90,8 +91,17 @@ export const LoginForm = (props: LoginFormProps): JSX.Element => {
 
     try {
       const res = await apiv3Post('/login', { loginForm });
-      const { redirectTo } = res.data;
-      router.push(redirectTo ?? '/');
+      const { redirectTo, userStatus } = res.data;
+
+      if (redirectTo != null) {
+        return router.push(redirectTo);
+      }
+
+      if (userStatus !== USER_STATUS.ACTIVE) {
+        window.location.href = '/';
+      }
+
+      return router.push('/');
     }
     catch (err) {
       const errs = toArrayIfNot(err);
@@ -217,7 +227,6 @@ export const LoginForm = (props: LoginFormProps): JSX.Element => {
       google: 'google',
       github: 'github',
       facebook: 'facebook',
-      twitter: 'twitter',
       oidc: 'openid',
       saml: 'key',
     };

+ 2 - 8
packages/app/src/components/Me/AssociateModal.tsx

@@ -80,18 +80,12 @@ const AssociateModal = (props: Props): JSX.Element => {
             >
               <i className="fa fa-google"></i> (TBD) Google OAuth
             </NavLink>
-            <NavLink
+            {/* <NavLink
               className={activeTab === 4 ? 'active' : ''}
               onClick={() => setActiveTab(4)}
             >
               <i className="fa fa-facebook"></i> (TBD) Facebook
-            </NavLink>
-            <NavLink
-              className={activeTab === 5 ? 'active' : ''}
-              onClick={() => setActiveTab(5)}
-            >
-              <i className="fa fa-twitter"></i> (TBD) Twitter
-            </NavLink>
+            </NavLink> */}
           </Nav>
           <TabContent activeTab={activeTab}>
             <TabPane tabId={1}>

+ 0 - 25
packages/app/src/components/PageEditor/OptionsSelector.tsx

@@ -199,30 +199,6 @@ const ConfigurationDropdown = memo(({ onConfirmEnableTextlint }: ConfigurationDr
     );
   }, [editorSettings, update, t]);
 
-  const renderRealtimeDrawioMenuItem = useCallback(() => {
-    if (editorSettings == null) {
-      return <></>;
-    }
-
-    const isActive = editorSettings.renderDrawioInRealtime;
-
-    const iconClasses = ['text-info'];
-    if (isActive) {
-      iconClasses.push('ti ti-check');
-    }
-    const iconClassName = iconClasses.join(' ');
-
-    return (
-      <DropdownItem toggle={false} onClick={() => update({ renderDrawioInRealtime: !isActive })}>
-        <div className="d-flex justify-content-between">
-          <span className="icon-container"><img src="/images/icons/fx.svg" width="14px" alt="fx"></img></span>
-          <span className="menuitem-label">draw.io Rendering</span>
-          <span className="icon-container"><i className={iconClassName}></i></span>
-        </div>
-      </DropdownItem>
-    );
-  }, [editorSettings, update]);
-
   const renderMarkdownTableAutoFormattingMenuItem = useCallback(() => {
     if (editorSettings == null) {
       return <></>;
@@ -300,7 +276,6 @@ const ConfigurationDropdown = memo(({ onConfirmEnableTextlint }: ConfigurationDr
 
         <DropdownMenu>
           {renderActiveLineMenuItem()}
-          {renderRealtimeDrawioMenuItem()}
           {renderMarkdownTableAutoFormattingMenuItem()}
           {renderIsTextlintEnabledMenuItem()}
           {/* <DropdownItem divider /> */}

+ 2 - 3
packages/app/src/components/PageEditorByHackmd.tsx

@@ -117,8 +117,6 @@ export const PageEditorByHackmd = (): JSX.Element => {
       const markdown = await hackmdEditorRef.current.getValue();
 
       const { page } = await saveOrUpdate(markdown, { pageId, path: currentPagePath || currentPathname, revisionId: revisionIdHackmdSynced }, options);
-      await mutatePageData();
-      await mutateTagsInfo();
 
       if (page == null) {
         return;
@@ -128,6 +126,7 @@ export const PageEditorByHackmd = (): JSX.Element => {
       }
       else {
         updateStateAfterSave?.();
+        mutateIsHackmdDraftUpdatingInRealtime(false);
       }
       setIsInitialized(false);
       mutateEditorMode(EditorMode.View);
@@ -137,7 +136,7 @@ export const PageEditorByHackmd = (): JSX.Element => {
       toastError(error.message);
     }
   // eslint-disable-next-line max-len
-  }, [editorMode, currentPathname, revision, revisionIdHackmdSynced, optionsToSave, saveOrUpdate, pageId, currentPagePath, mutatePageData, mutateTagsInfo, isNotFound, mutateEditorMode, router, updateStateAfterSave]);
+  }, [editorMode, currentPathname, revision, revisionIdHackmdSynced, optionsToSave, saveOrUpdate, pageId, currentPagePath, isNotFound, mutateEditorMode, router, updateStateAfterSave, mutateIsHackmdDraftUpdatingInRealtime]);
 
   // set handler to save and reload Page
   useEffect(() => {

+ 0 - 12
packages/app/src/interfaces/activity.ts

@@ -13,7 +13,6 @@ const ACTION_USER_LOGIN_WITH_LOCAL = 'USER_LOGIN_WITH_LOCAL';
 const ACTION_USER_LOGIN_WITH_LDAP = 'USER_LOGIN_WITH_LDAP';
 const ACTION_USER_LOGIN_WITH_GOOGLE = 'USER_LOGIN_WITH_GOOGLE';
 const ACTION_USER_LOGIN_WITH_GITHUB = 'USER_LOGIN_WITH_GITHUB';
-const ACTION_USER_LOGIN_WITH_TWITTER = 'USER_LOGIN_WITH_TWITTER';
 const ACTION_USER_LOGIN_WITH_OIDC = 'USER_LOGIN_WITH_OIDC';
 const ACTION_USER_LOGIN_WITH_SAML = 'USER_LOGIN_WITH_SAML';
 const ACTION_USER_LOGIN_FAILURE = 'USER_LOGIN_FAILURE';
@@ -99,9 +98,6 @@ const ACTION_ADMIN_AUTH_GOOGLE_UPDATE = 'ADMIN_AUTH_GOOGLE_UPDATE';
 const ACTION_ADMIN_AUTH_GITHUB_ENABLED = 'ADMIN_AUTH_GITHUB_ENABLED';
 const ACTION_ADMIN_AUTH_GITHUB_DISABLED = 'ADMIN_AUTH_GITHUB_DISABLED';
 const ACTION_ADMIN_AUTH_GITHUB_UPDATE = 'ADMIN_AUTH_GITHUB_UPDATE';
-const ACTION_ADMIN_AUTH_TWITTER_ENABLED = 'ADMIN_AUTH_TWITTER_ENABLED';
-const ACTION_ADMIN_AUTH_TWITTER_DISABLED = 'ADMIN_AUTH_TWITTER_DISABLED';
-const ACTION_ADMIN_AUTH_TWITTER_UPDATE = 'ADMIN_AUTH_TWITTER_UPDATE';
 const ACTION_ADMIN_MARKDOWN_LINE_BREAK_UPDATE = 'ADMIN_MARKDOWN_LINE_BREAK_UPDATE';
 const ACTION_ADMIN_MARKDOWN_INDENT_UPDATE = 'ADMIN_MARKDOWN_INDENT_UPDATE';
 const ACTION_ADMIN_MARKDOWN_PRESENTATION_UPDATE = 'ADMIN_MARKDOWN_PRESENTATION_UPDATE';
@@ -192,7 +188,6 @@ export const SupportedAction = {
   ACTION_USER_LOGIN_WITH_LDAP,
   ACTION_USER_LOGIN_WITH_GOOGLE,
   ACTION_USER_LOGIN_WITH_GITHUB,
-  ACTION_USER_LOGIN_WITH_TWITTER,
   ACTION_USER_LOGIN_WITH_OIDC,
   ACTION_USER_LOGIN_WITH_SAML,
   ACTION_USER_LOGIN_FAILURE,
@@ -278,9 +273,6 @@ export const SupportedAction = {
   ACTION_ADMIN_AUTH_GITHUB_ENABLED,
   ACTION_ADMIN_AUTH_GITHUB_DISABLED,
   ACTION_ADMIN_AUTH_GITHUB_UPDATE,
-  ACTION_ADMIN_AUTH_TWITTER_ENABLED,
-  ACTION_ADMIN_AUTH_TWITTER_DISABLED,
-  ACTION_ADMIN_AUTH_TWITTER_UPDATE,
   ACTION_ADMIN_MARKDOWN_LINE_BREAK_UPDATE,
   ACTION_ADMIN_MARKDOWN_INDENT_UPDATE,
   ACTION_ADMIN_MARKDOWN_PRESENTATION_UPDATE,
@@ -372,7 +364,6 @@ export const SmallActionGroup = {
   ACTION_USER_LOGIN_WITH_LDAP,
   ACTION_USER_LOGIN_WITH_GOOGLE,
   ACTION_USER_LOGIN_WITH_GITHUB,
-  ACTION_USER_LOGIN_WITH_TWITTER,
   ACTION_USER_LOGIN_WITH_OIDC,
   ACTION_USER_LOGIN_WITH_SAML,
   ACTION_USER_LOGIN_FAILURE,
@@ -465,9 +456,6 @@ export const LargeActionGroup = {
   ACTION_ADMIN_AUTH_GITHUB_ENABLED,
   ACTION_ADMIN_AUTH_GITHUB_DISABLED,
   ACTION_ADMIN_AUTH_GITHUB_UPDATE,
-  ACTION_ADMIN_AUTH_TWITTER_ENABLED,
-  ACTION_ADMIN_AUTH_TWITTER_DISABLED,
-  ACTION_ADMIN_AUTH_TWITTER_UPDATE,
   ACTION_ADMIN_MARKDOWN_LINE_BREAK_UPDATE,
   ACTION_ADMIN_MARKDOWN_INDENT_UPDATE,
   ACTION_ADMIN_MARKDOWN_PRESENTATION_UPDATE,

+ 0 - 1
packages/app/src/interfaces/editor-settings.ts

@@ -24,7 +24,6 @@ export interface IEditorSettings {
   theme: undefined | string,
   keymapMode: undefined | KeyMapMode,
   styleActiveLine: boolean,
-  renderDrawioInRealtime: boolean,
   autoFormatMarkdownTable: boolean,
   textlintSettings: undefined | ITextlintSettings;
 }

+ 0 - 1
packages/app/src/migrations/20180927102719-init-serverurl.js

@@ -40,7 +40,6 @@ module.exports = {
       $or: [
         { key: 'security:passport-github:callbackUrl' },
         { key: 'security:passport-google:callbackUrl' },
-        { key: 'security:passport-twitter:callbackUrl' },
         { key: 'security:passport-saml:callbackUrl' },
       ],
     });

+ 0 - 3
packages/app/src/pages/admin/security.page.tsx

@@ -14,7 +14,6 @@ import AdminLdapSecurityContainer from '~/client/services/AdminLdapSecurityConta
 import AdminLocalSecurityContainer from '~/client/services/AdminLocalSecurityContainer';
 import AdminOidcSecurityContainer from '~/client/services/AdminOidcSecurityContainer';
 import AdminSamlSecurityContainer from '~/client/services/AdminSamlSecurityContainer';
-import AdminTwitterSecurityContainer from '~/client/services/AdminTwitterSecurityContainer';
 import { CrowiRequest } from '~/interfaces/crowi-request';
 import { CommonProps, generateCustomTitle } from '~/pages/utils/commons';
 import { useCurrentUser, useIsMailerSetup, useSiteUrl } from '~/stores/context';
@@ -52,7 +51,6 @@ const AdminSecuritySettingsPage: NextPage<Props> = (props) => {
       const adminOidcSecurityContainer = new AdminOidcSecurityContainer();
       const adminGoogleSecurityContainer = new AdminGoogleSecurityContainer();
       const adminGitHubSecurityContainer = new AdminGitHubSecurityContainer();
-      const adminTwitterSecurityContainer = new AdminTwitterSecurityContainer();
 
       adminSecurityContainers.push(
         adminGeneralSecurityContainer,
@@ -62,7 +60,6 @@ const AdminSecuritySettingsPage: NextPage<Props> = (props) => {
         adminOidcSecurityContainer,
         adminGoogleSecurityContainer,
         adminGitHubSecurityContainer,
-        adminTwitterSecurityContainer,
       );
     }
   }

+ 133 - 0
packages/app/src/pages/login/error/[message].page.tsx

@@ -0,0 +1,133 @@
+import React from 'react';
+
+import {
+  NextPage, GetServerSideProps, GetServerSidePropsContext,
+} from 'next';
+import { useTranslation } from 'next-i18next';
+import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
+import { useRouter } from 'next/router';
+
+import { NoLoginLayout } from '~/components/Layout/NoLoginLayout';
+import {
+  CommonProps, getServerSideCommonProps, getNextI18NextConfig,
+} from '~/pages/utils/commons';
+
+
+type Props = CommonProps;
+const classNames: string[] = ['login-page'];
+
+const LoginPage: NextPage<CommonProps> = () => {
+
+  const { t } = useTranslation();
+  const router = useRouter();
+  const { message } = router.query;
+
+
+  let loginErrorElm;
+
+  const ApprovalPendingUserError = () => {
+    return (
+      <>
+        <div className="alert alert-warning">
+          <h2>{ t('login.sign_in_error') }</h2>
+        </div>
+        <p>Wait for approved by administrators.</p>
+      </>
+    );
+  };
+
+  const SuspendedUserError = () => {
+    return (
+      <>
+        <div className="alert alert-warning">
+          <h2>{ t('login.sign_in_error') }</h2>
+        </div>
+        <p>This account is suspended.</p>
+      </>
+    );
+  };
+
+  const PasswordResetOrderError = () => {
+    return (
+      <>
+        <div className="alert alert-warning mb-3">
+          <h2>{ t('forgot_password.incorrect_token_or_expired_url') }</h2>
+        </div>
+        <a href="/forgot-password" className="link-switch">
+          <i className="icon-key"></i> { t('forgot_password.forgot_password') }
+        </a>
+      </>
+    );
+  };
+
+  const DefaultLoginError = () => {
+    return (
+      <div className="alert alert-warning">
+        <h2>{ t('login.sign_in_error') }</h2>
+      </div>
+    );
+  };
+
+  switch (message) {
+    case 'registered':
+      loginErrorElm = <ApprovalPendingUserError />;
+      break;
+    case 'suspended':
+      loginErrorElm = <SuspendedUserError />;
+      break;
+    case 'password-reset-order':
+      loginErrorElm = <PasswordResetOrderError />;
+      break;
+    default:
+      loginErrorElm = <DefaultLoginError />;
+  }
+
+
+  return (
+    <NoLoginLayout className={classNames.join(' ')}>
+      <div className="mb-4 login-form-errors text-center">
+        <div className='noLogin-dialog pb-4 mx-auto'>
+          <div className="col-12">
+            {loginErrorElm}
+          </div>
+          {/* If the transition source is "/login", use <a /> tag since the transition will not occur if next/link is used. */}
+          <a href='/login'>
+            <i className="icon-login mr-1" />{t('Sign in is here')}
+          </a>
+        </div>
+      </div>
+    </NoLoginLayout>
+  );
+};
+
+/**
+ * for Server Side Translations
+ * @param context
+ * @param props
+ * @param namespacesRequired
+ */
+async function injectNextI18NextConfigurations(context: GetServerSidePropsContext, props: Props, namespacesRequired?: string[] | undefined): Promise<void> {
+  const nextI18NextConfig = await getNextI18NextConfig(serverSideTranslations, context, namespacesRequired);
+  props._nextI18Next = nextI18NextConfig._nextI18Next;
+}
+
+
+export const getServerSideProps: GetServerSideProps = async(context: GetServerSidePropsContext) => {
+  const result = await getServerSideCommonProps(context);
+
+  // check for presence
+  // see: https://github.com/vercel/next.js/issues/19271#issuecomment-730006862
+  if (!('props' in result)) {
+    throw new Error('invalid getSSP result');
+  }
+
+  const props: Props = result.props as Props;
+
+  await injectNextI18NextConfigurations(context, props, ['translation']);
+
+  return {
+    props,
+  };
+};
+
+export default LoginPage;

+ 4 - 6
packages/app/src/pages/login.page.tsx → packages/app/src/pages/login/index.page.tsx

@@ -11,15 +11,14 @@ import { LoginForm } from '~/components/LoginForm';
 import type { CrowiRequest } from '~/interfaces/crowi-request';
 import { IExternalAccountLoginError, isExternalAccountLoginError } from '~/interfaces/errors/external-account-login-error';
 import type { RegistrationMode } from '~/interfaces/registration-mode';
-
+import {
+  CommonProps, getServerSideCommonProps, generateCustomTitle, getNextI18NextConfig,
+} from '~/pages/utils/commons';
 import {
   useCsrfToken,
   useCurrentPathname,
-} from '../stores/context';
+} from '~/stores/context';
 
-import {
-  CommonProps, getServerSideCommonProps, generateCustomTitle, getNextI18NextConfig,
-} from './utils/commons';
 
 type Props = CommonProps & {
   registrationMode: RegistrationMode,
@@ -89,7 +88,6 @@ function injectEnabledStrategies(context: GetServerSidePropsContext, props: Prop
     google: configManager.getConfig('crowi', 'security:passport-google:isEnabled'),
     github: configManager.getConfig('crowi', 'security:passport-github:isEnabled'),
     facebook: false,
-    twitter: configManager.getConfig('crowi', 'security:passport-twitter:isEnabled'),
     saml: configManager.getConfig('crowi', 'security:passport-saml:isEnabled'),
     oidc: configManager.getConfig('crowi', 'security:passport-oidc:isEnabled'),
   };

+ 0 - 1
packages/app/src/server/crowi/index.js

@@ -356,7 +356,6 @@ Crowi.prototype.setupPassport = async function() {
     this.passportService.setupStrategyById('oidc');
     this.passportService.setupStrategyById('google');
     this.passportService.setupStrategyById('github');
-    this.passportService.setupStrategyById('twitter');
   }
   catch (err) {
     logger.error(err);

+ 0 - 5
packages/app/src/server/models/config.ts

@@ -95,11 +95,6 @@ export const defaultCrowiConfigs: { [key: string]: any } = {
   'security:passport-github:clientSecret': undefined,
   'security:passport-github:isSameUsernameTreatedAsIdenticalUser': false,
 
-  'security:passport-twitter:isEnabled' : false,
-  'security:passport-twitter:consumerKey': undefined,
-  'security:passport-twitter:consumerSecret': undefined,
-  'security:passport-twitter:isSameUsernameTreatedAsIdenticalUser': false,
-
   'security:passport-oidc:isEnabled' : false,
 
   'aws:s3Bucket'          : 'growi',

+ 0 - 1
packages/app/src/server/models/editor-settings.ts

@@ -26,7 +26,6 @@ const editorSettingsSchema = new Schema<EditorSettingsDocument, EditorSettingsMo
   theme: { type: String },
   keymapMode: { type: String },
   styleActiveLine: { type: Boolean, default: false },
-  renderDrawioInRealtime: { type: Boolean, default: true },
   autoFormatMarkdownTable: { type: Boolean, default: true },
   textlintSettings: textlintSettingsSchema,
 });

+ 2 - 3
packages/app/src/server/routes/apiv3/personal-setting.js

@@ -117,7 +117,6 @@ module.exports = (crowi) => {
       body('theme').optional().isString(),
       body('keymapMode').optional().isString(),
       body('styleActiveLine').optional().isBoolean(),
-      body('renderDrawioInRealtime').optional().isBoolean(),
       body('autoFormatMarkdownTable').optional().isBoolean(),
       body('textlintSettings.neverAskBeforeDownloadLargeFiles').optional().isBoolean(),
       body('textlintSettings.textlintRules.*.name').optional().isString(),
@@ -539,12 +538,12 @@ module.exports = (crowi) => {
     const { body } = req;
 
     const {
-      theme, keymapMode, styleActiveLine, renderDrawioInRealtime, autoFormatMarkdownTable,
+      theme, keymapMode, styleActiveLine, autoFormatMarkdownTable,
       textlintSettings,
     } = body;
 
     const document = {
-      theme, keymapMode, styleActiveLine, renderDrawioInRealtime, autoFormatMarkdownTable,
+      theme, keymapMode, styleActiveLine, autoFormatMarkdownTable,
     };
 
     if (textlintSettings != null) {

+ 1 - 81
packages/app/src/server/routes/apiv3/security-setting.js

@@ -34,7 +34,7 @@ const validator = {
   authenticationSetting: [
     body('isEnabled').if(value => value != null).isBoolean(),
     body('authId').isString().isIn([
-      'local', 'ldap', 'saml', 'oidc', 'google', 'github', 'twitter',
+      'local', 'ldap', 'saml', 'oidc', 'google', 'github',
     ]),
   ],
   localSetting: [
@@ -101,11 +101,6 @@ const validator = {
     body('githubClientSecret').if(value => value != null).isString(),
     body('isSameUsernameTreatedAsIdenticalUser').if(value => value != null).isBoolean(),
   ],
-  twitterOAuth: [
-    body('twitterConsumerKey').if(value => value != null).isString(),
-    body('twitterConsumerSecret').if(value => value != null).isString(),
-    body('isSameUsernameTreatedAsIdenticalUser').if(value => value != null).isBoolean(),
-  ],
 };
 
 /**
@@ -312,18 +307,6 @@ const validator = {
  *          isSameUsernameTreatedAsIdenticalUser:
  *            type: boolean
  *            description: local account automatically linked the email matched
- *      TwitterOAuthSetting:
- *        type: object
- *        properties:
- *          twitterConsumerKey:
- *            type: string
- *            description: key of comsumer
- *          twitterConsumerSecret:
- *            type: string
- *            description: password of comsumer
- *          isSameUsernameTreatedAsIdenticalUser:
- *            type: boolean
- *            description: local account automatically linked the email matched
  */
 module.exports = (crowi) => {
   const loginRequiredStrictly = require('../../middlewares/login-required')(crowi);
@@ -391,7 +374,6 @@ module.exports = (crowi) => {
         isOidcEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-oidc:isEnabled'),
         isGoogleEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-google:isEnabled'),
         isGitHubEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-github:isEnabled'),
-        isTwitterEnabled: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:isEnabled'),
       },
       ldapAuth: {
         serverUrl: await crowi.configManager.getConfig('crowi', 'security:passport-ldap:serverUrl'),
@@ -461,11 +443,6 @@ module.exports = (crowi) => {
         githubClientSecret: await crowi.configManager.getConfig('crowi', 'security:passport-github:clientSecret'),
         isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-github:isSameUsernameTreatedAsIdenticalUser'),
       },
-      twitterOAuth: {
-        twitterConsumerKey: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:consumerKey'),
-        twitterConsumerSecret: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:consumerSecret'),
-        isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:isSameUsernameTreatedAsIdenticalUser'),
-      },
     };
     return res.apiv3({ securityParams });
   });
@@ -563,13 +540,6 @@ module.exports = (crowi) => {
           }
           parameters.action = SupportedAction.ACTION_ADMIN_AUTH_GITHUB_DISABLED;
           break;
-        case 'twitter':
-          if (isEnabled) {
-            parameters.action = SupportedAction.ACTION_ADMIN_AUTH_TWITTER_ENABLED;
-            break;
-          }
-          parameters.action = SupportedAction.ACTION_ADMIN_AUTH_TWITTER_DISABLED;
-          break;
       }
       activityEvent.emit('update', res.locals.activity._id, parameters);
       return res.apiv3({ responseParams });
@@ -1177,55 +1147,5 @@ module.exports = (crowi) => {
     }
   });
 
-  /**
-   * @swagger
-   *
-   *    /_api/v3/security-setting/twitter-oauth:
-   *      put:
-   *        tags: [SecuritySetting, apiv3]
-   *        description: Update twitter OAuth
-   *        requestBody:
-   *          required: true
-   *          content:
-   *            application/json:
-   *              schema:
-   *                $ref: '#/components/schemas/TwitterOAuthSetting'
-   *        responses:
-   *          200:
-   *            description: Succeeded to update twitter OAuth
-   *            content:
-   *              application/json:
-   *                schema:
-   *                  $ref: '#/components/schemas/TwitterOAuthSetting'
-   */
-  router.put('/twitter-oauth', loginRequiredStrictly, adminRequired, addActivity, validator.twitterOAuth, apiV3FormValidator, async(req, res) => {
-
-    let requestParams = {
-      'security:passport-twitter:consumerKey': req.body.twitterConsumerKey,
-      'security:passport-twitter:consumerSecret': req.body.twitterConsumerSecret,
-      'security:passport-twitter:isSameUsernameTreatedAsIdenticalUser': req.body.isSameUsernameTreatedAsIdenticalUser,
-    };
-
-    requestParams = removeNullPropertyFromObject(requestParams);
-
-    try {
-      await updateAndReloadStrategySettings('twitter', requestParams);
-
-      const securitySettingParams = {
-        twitterConsumerId: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:consumerKey'),
-        twitterConsumerSecret: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:consumerSecret'),
-        isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-twitter:isSameUsernameTreatedAsIdenticalUser'),
-      };
-      const parameters = { action: SupportedAction.ACTION_ADMIN_AUTH_TWITTER_UPDATE };
-      activityEvent.emit('update', res.locals.activity._id, parameters);
-      return res.apiv3({ securitySettingParams });
-    }
-    catch (err) {
-      const msg = 'Error occurred in updating twitterOAuth';
-      logger.error('Error', err);
-      return res.apiv3Err(new ErrorV3(msg, 'update-twitterOAuth-failed'));
-    }
-  });
-
   return router;
 };

+ 1 - 3
packages/app/src/server/routes/index.js

@@ -76,7 +76,7 @@ module.exports = function(crowi, app) {
 
   app.get('/'                         , applicationInstalled, unavailableWhenMaintenanceMode, loginRequired, autoReconnectToSearch, next.delegateToNext);
 
-  app.get('/login/error/:reason'      , applicationInstalled, login.error);
+  app.get('/login/error/:reason'      , applicationInstalled, next.delegateToNext);
   app.get('/login'                    , applicationInstalled, login.preLogin, next.delegateToNext);
   app.get('/invited'                  , applicationInstalled, next.delegateToNext);
   // app.post('/login'                   , applicationInstalled, loginFormValidator.loginRules(), loginFormValidator.loginValidation, csrfProtection,  addActivity, loginPassport.loginWithLocal, loginPassport.loginWithLdap, loginPassport.loginFailure);
@@ -93,12 +93,10 @@ module.exports = function(crowi, app) {
   // OAuth
   app.get('/passport/google'                      , loginPassport.loginWithGoogle, loginPassport.loginFailureForExternalAccount);
   app.get('/passport/github'                      , loginPassport.loginWithGitHub, loginPassport.loginFailureForExternalAccount);
-  app.get('/passport/twitter'                     , loginPassport.loginWithTwitter, loginPassport.loginFailureForExternalAccount);
   app.get('/passport/oidc'                        , loginPassport.loginWithOidc, loginPassport.loginFailureForExternalAccount);
   app.get('/passport/saml'                        , loginPassport.loginWithSaml, loginPassport.loginFailureForExternalAccount);
   app.get('/passport/google/callback'             , loginPassport.loginPassportGoogleCallback   , loginPassport.loginFailureForExternalAccount);
   app.get('/passport/github/callback'             , loginPassport.loginPassportGitHubCallback   , loginPassport.loginFailureForExternalAccount);
-  app.get('/passport/twitter/callback'            , loginPassport.loginPassportTwitterCallback  , loginPassport.loginFailureForExternalAccount);
   app.get('/passport/oidc/callback'               , loginPassport.loginPassportOidcCallback     , loginPassport.loginFailureForExternalAccount);
   app.post('/passport/saml/callback'              , addActivity, loginPassport.loginPassportSamlCallback, loginPassport.loginFailureForExternalAccount);
 

+ 1 - 46
packages/app/src/server/routes/login-passport.js

@@ -130,7 +130,7 @@ module.exports = function(crowi, app) {
     // remove session.redirectTo
     delete req.session.redirectTo;
 
-    return res.apiv3({ redirectTo });
+    return res.apiv3({ redirectTo, userStatus: req.user.status });
   };
 
   const cannotLoginErrorHadnler = (req, res, next) => {
@@ -471,49 +471,6 @@ module.exports = function(crowi, app) {
     });
   };
 
-  const loginWithTwitter = function(req, res, next) {
-    if (!passportService.isTwitterStrategySetup) {
-      debug('TwitterStrategy has not been set up');
-      const error = new ExternalAccountLoginError('message.strategy_has_not_been_set_up', { strategy: 'TwitterStrategy' });
-      return next(error);
-    }
-
-    passport.authenticate('twitter')(req, res);
-  };
-
-  const loginPassportTwitterCallback = async(req, res, next) => {
-    const providerId = 'twitter';
-    const strategyName = 'twitter';
-
-    let response;
-    try {
-      response = await promisifiedPassportAuthentication(strategyName, req, res);
-    }
-    catch (err) {
-      return next(new ExternalAccountLoginError(err.message));
-    }
-
-    const userInfo = {
-      id: response.id,
-      username: response.username,
-      name: response.displayName,
-    };
-
-    const externalAccount = await getOrCreateUser(req, res, userInfo, providerId);
-    if (!externalAccount) {
-      return next(new ExternalAccountLoginError('message.sign_in_failure'));
-    }
-
-    const user = await externalAccount.getPopulatedUser();
-
-    // login
-    req.logIn(user, async(err) => {
-      if (err) { debug(err.message); return next(new ExternalAccountLoginError(err.message)) }
-
-      return loginSuccessHandler(req, res, user, SupportedAction.ACTION_USER_LOGIN_WITH_TWITTER, true);
-    });
-  };
-
   const loginWithOidc = function(req, res, next) {
     if (!passportService.isOidcStrategySetup) {
       debug('OidcStrategy has not been set up');
@@ -635,12 +592,10 @@ module.exports = function(crowi, app) {
     loginWithLocal,
     loginWithGoogle,
     loginWithGitHub,
-    loginWithTwitter,
     loginWithOidc,
     loginWithSaml,
     loginPassportGoogleCallback,
     loginPassportGitHubCallback,
-    loginPassportTwitterCallback,
     loginPassportOidcCallback,
     loginPassportSamlCallback,
   };

+ 0 - 18
packages/app/src/server/routes/login.js

@@ -82,24 +82,6 @@ module.exports = function(crowi, app) {
     });
   };
 
-  actions.error = function(req, res) {
-    const reason = req.params.reason;
-
-
-    let reasonMessage = '';
-    if (reason === 'suspended') {
-      reasonMessage = 'This account is suspended.';
-    }
-    else if (reason === 'registered') {
-      reasonMessage = 'Wait for approved by administrators.';
-    }
-
-    return res.render('login/error', {
-      reason,
-      reasonMessage,
-    });
-  };
-
   actions.preLogin = function(req, res, next) {
     // user has already logged in
     const { user } = req;

+ 0 - 18
packages/app/src/server/service/config-loader.ts

@@ -127,24 +127,6 @@ const ENV_VAR_NAME_TO_CONFIG_INFO = {
   //   type:    ,
   //   default:
   // },
-  // OAUTH_TWITTER_CONSUMER_KEY: {
-  //   ns:      'crowi',
-  //   key:     'security:passport-twitter:consumerKey',
-  //   type:    ,
-  //   default:
-  // },
-  // OAUTH_TWITTER_CONSUMER_SECRET: {
-  //   ns:      'crowi',
-  //   key:     'security:passport-twitter:consumerSecret',
-  //   type:    ,
-  //   default:
-  // },
-  // OAUTH_TWITTER_CALLBACK_URI: {
-  //   ns:      'crowi',
-  //   key:     'security:passport-twitter:callbackUrl',
-  //   type:    ,
-  //   default:
-  // },
   DRAWIO_URI: {
     ns:      'crowi',
     key:     'app:drawioUri',

+ 0 - 59
packages/app/src/server/service/passport.ts

@@ -10,7 +10,6 @@ import { Strategy as GoogleStrategy } from 'passport-google-oauth20';
 import LdapStrategy from 'passport-ldapauth';
 import { Strategy as LocalStrategy } from 'passport-local';
 import { Profile, Strategy as SamlStrategy, VerifiedCallback } from 'passport-saml';
-import { Strategy as TwitterStrategy } from 'passport-twitter';
 import urljoin from 'url-join';
 
 import loggerFactory from '~/utils/logger';
@@ -60,11 +59,6 @@ class PassportService implements S2sMessageHandlable {
    */
   isGitHubStrategySetup = false;
 
-  /**
-   * the flag whether TwitterStrategy is set up successfully
-   */
-  isTwitterStrategySetup = false;
-
   /**
    * the flag whether OidcStrategy is set up successfully
    */
@@ -117,10 +111,6 @@ class PassportService implements S2sMessageHandlable {
       setup: 'setupGitHubStrategy',
       reset: 'resetGitHubStrategy',
     },
-    twitter: {
-      setup: 'setupTwitterStrategy',
-      reset: 'resetTwitterStrategy',
-    },
   };
 
   constructor(crowi: any) {
@@ -185,7 +175,6 @@ class PassportService implements S2sMessageHandlable {
     if (this.isOidcStrategySetup) { setupStrategies.push('oidc') }
     if (this.isGoogleStrategySetup) { setupStrategies.push('google') }
     if (this.isGitHubStrategySetup) { setupStrategies.push('github') }
-    if (this.isTwitterStrategySetup) { setupStrategies.push('twitter') }
 
     return setupStrategies;
   }
@@ -548,54 +537,6 @@ class PassportService implements S2sMessageHandlable {
     this.isGitHubStrategySetup = false;
   }
 
-  setupTwitterStrategy() {
-
-    this.resetTwitterStrategy();
-
-    const { configManager } = this.crowi;
-    const isTwitterEnabled = configManager.getConfig('crowi', 'security:passport-twitter:isEnabled');
-
-    // when disabled
-    if (!isTwitterEnabled) {
-      return;
-    }
-
-    logger.debug('TwitterStrategy: setting up..');
-    passport.use(
-      new TwitterStrategy(
-        {
-          consumerKey: configManager.getConfig('crowi', 'security:passport-twitter:consumerKey'),
-          consumerSecret: configManager.getConfig('crowi', 'security:passport-twitter:consumerSecret'),
-          callbackURL: (this.crowi.appService.getSiteUrl() != null)
-            ? urljoin(this.crowi.appService.getSiteUrl(), '/passport/twitter/callback') // auto-generated with v3.2.4 and above
-            : configManager.getConfig('crowi', 'security:passport-twitter:callbackUrl'), // DEPRECATED: backward compatible with v3.2.3 and below
-          skipUserProfile: false,
-        },
-        (accessToken, refreshToken, profile, done) => {
-          if (profile) {
-            return done(null, profile);
-          }
-
-          return done(null, false);
-        },
-      ),
-    );
-
-    this.isTwitterStrategySetup = true;
-    logger.debug('TwitterStrategy: setup is done');
-  }
-
-  /**
-   * reset TwitterStrategy
-   *
-   * @memberof PassportService
-   */
-  resetTwitterStrategy() {
-    logger.debug('TwitterStrategy: reset');
-    passport.unuse('twitter');
-    this.isTwitterStrategySetup = false;
-  }
-
   async setupOidcStrategy() {
 
     this.resetOidcStrategy();

+ 0 - 1
packages/app/src/server/views/login.html

@@ -138,7 +138,6 @@
         data-is-google-auth-enabled = "{{ getConfig('crowi', 'security:passport-google:isEnabled') }}"
         data-is-github-auth-enabled = "{{ getConfig('crowi', 'security:passport-github:isEnabled') }}"
         data-is-facebook-auth-enabled = "{{ getConfig('crowi', 'security:passport-facebook:isEnabled') }}"
-        data-is-twitter-auth-enabled = "{{ getConfig('crowi', 'security:passport-twitter:isEnabled') }}"
         data-is-saml-auth-enabled = "{{ getConfig('crowi', 'security:passport-saml:isEnabled') }}"
         data-is-oidc-auth-enabled = "{{ getConfig('crowi', 'security:passport-oidc:isEnabled') }}"
         data-is-basic-auth-enabled = "{{ getConfig('crowi', 'security:passport-basic:isEnabled') }}"

+ 0 - 62
packages/app/src/server/views/login/error.html

@@ -1,62 +0,0 @@
-{% extends '../layout/layout.html' %}
-
-{% block html_base_css %}error nologin{% endblock %}
-
-{% block html_title %}{{ customizeService.generateCustomTitleForFixedPageName(t('login.Setup')) }}{% endblock %}
-
-
-
-{#
- # Remove default contents
- #}
-{% block html_head_loading_legacy %}
-{% endblock %}
-{% block html_head_loading_app %}
-{% endblock %}
-{% block layout_head_nav %}
-{% endblock %}
-{% block sidebar %}
-{% endblock %}
-{% block head_warn_alert_siteurl_undefined %}
-{% endblock %}
-
-
-
-{% block layout_main %}
-
-<div class="main container-fluid">
-
-  <div class="row">
-
-    <div class="login-header offset-sm-4 col-sm-4">
-      <div class="logo">{% include '../widget/logo.html' %}</div>
-      <h1>GROWI</h1>
-
-      <div class="mb-4 login-form-errors text-center">
-        {% if reason === 'registered'%}
-        <div class="alert alert-success">
-          <h2>{{ t('login.Registration successful') }}</h2>
-        </div>
-        {% elseif reason === 'password-reset-order' %}
-        <div class="alert alert-warning mb-3">
-          <h2>{{ t('forgot_password.incorrect_token_or_expired_url') }}</h2>
-        </div>
-          <a href="/forgot-password" class="link-switch">
-            <i class="icon-key"></i> {{ t('forgot_password.forgot_password') }}
-          </a>
-        {% else %}
-        <div class="alert alert-warning">
-            <h2>{{ t('login.Sign in error') }}</h2>
-        </div>
-        {% endif %}
-      </div>
-
-      <p>{{ reasonMessage }}</p>
-    </div>
-
-
-  </div>{# /.row #}
-
-</div>{# /.main #}
-
-{% endblock %}

+ 0 - 26
yarn.lock

@@ -17235,14 +17235,6 @@ passport-local@^1.0.0:
   dependencies:
     passport-strategy "1.x.x"
 
-passport-oauth1@1.x.x:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/passport-oauth1/-/passport-oauth1-1.1.0.tgz#a7de988a211f9cf4687377130ea74df32730c918"
-  dependencies:
-    oauth "0.9.x"
-    passport-strategy "1.x.x"
-    utils-merge "1.x.x"
-
 passport-oauth2@1.x.x:
   version "1.6.1"
   resolved "https://registry.yarnpkg.com/passport-oauth2/-/passport-oauth2-1.6.1.tgz#c5aee8f849ce8bd436c7f81d904a3cd1666f181b"
@@ -17272,13 +17264,6 @@ passport-strategy@1.x.x, passport-strategy@^1.0.0:
   resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4"
   integrity sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=
 
-passport-twitter@^1.0.4:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/passport-twitter/-/passport-twitter-1.0.4.tgz#01a799e1f760bf2de49f2ba5fba32282f18932d7"
-  dependencies:
-    passport-oauth1 "1.x.x"
-    xtraverse "0.1.x"
-
 passport@^0.6.0:
   version "0.6.0"
   resolved "https://registry.yarnpkg.com/passport/-/passport-0.6.0.tgz#e869579fab465b5c0b291e841e6cc95c005fac9d"
@@ -24165,11 +24150,6 @@ xmldoc@^1.2.0:
   dependencies:
     sax "^1.2.4"
 
-xmldom@0.1.x:
-  version "0.1.31"
-  resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.31.tgz#b76c9a1bd9f0a9737e5a72dc37231cf38375e2ff"
-  integrity sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==
-
 xmlhttprequest-ssl@~2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz#91360c86b914e67f44dce769180027c0da618c67"
@@ -24245,12 +24225,6 @@ xtend@~2.1.1:
   dependencies:
     object-keys "~0.4.0"
 
-xtraverse@0.1.x:
-  version "0.1.0"
-  resolved "https://registry.yarnpkg.com/xtraverse/-/xtraverse-0.1.0.tgz#b741bad018ef78d8a9d2e83ade007b3f7959c732"
-  dependencies:
-    xmldom "0.1.x"
-
 "y18n@^3.2.1 || ^4.0.0":
   version "4.0.3"
   resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf"