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

Merge branch 'imprv/abolish-old-config-api' into imprv/abolish-old-config-api-customize

mizozobu 6 лет назад
Родитель
Сommit
72f83c0f57
51 измененных файлов с 506 добавлено и 1368 удалено
  1. 4 0
      CHANGES.md
  2. 3 0
      config/migrate.js
  3. 4 5
      package.json
  4. 3 38
      resource/locales/en-US/translation.json
  5. 2 37
      resource/locales/ja/translation.json
  6. 1 0
      src/client/js/components/PageEditor.jsx
  7. 23 16
      src/client/js/components/StaffCredit/Contributor.js
  8. 20 2
      src/client/styles/scss/_staff_credit.scss
  9. 12 0
      src/lib/util/mongoose-utils.js
  10. 3 2
      src/migrations/20180926134048-make-email-unique.js
  11. 11 4
      src/migrations/20180927102719-init-serverurl.js
  12. 6 5
      src/migrations/20181019114028-abolish-page-group-relation.js
  13. 31 0
      src/migrations/20190618055300-abolish-crowi-classic-auth.js
  14. 64 0
      src/migrations/20190618104011-add-config-app-installed.js
  15. 4 12
      src/server/crowi/express-init.js
  16. 3 11
      src/server/crowi/index.js
  17. 0 8
      src/server/form/admin/securityGoogle.js
  18. 0 7
      src/server/form/admin/securityMechanism.js
  19. 0 2
      src/server/form/index.js
  20. 0 2
      src/server/form/register.js
  21. 2 146
      src/server/models/config.js
  22. 1 0
      src/server/models/index.js
  23. 17 14
      src/server/models/user.js
  24. 34 51
      src/server/routes/admin.js
  25. 1 2
      src/server/routes/attachment.js
  26. 12 26
      src/server/routes/index.js
  27. 7 118
      src/server/routes/login.js
  28. 0 67
      src/server/routes/me.js
  29. 2 3
      src/server/routes/page.js
  30. 0 22
      src/server/service/notification.js
  31. 1 1
      src/server/service/slack-notification.js
  32. 0 70
      src/server/util/googleAuth.js
  33. 1 23
      src/server/util/middlewares.js
  34. 10 7
      src/server/util/slack.js
  35. 2 52
      src/server/util/swigFunctions.js
  36. 3 140
      src/server/views/admin/security.html
  37. 1 2
      src/server/views/admin/widget/passport/github.html
  38. 1 2
      src/server/views/admin/widget/passport/google-oauth.html
  39. 1 2
      src/server/views/admin/widget/passport/oidc.html
  40. 1 2
      src/server/views/admin/widget/passport/saml.html
  41. 1 2
      src/server/views/admin/widget/passport/twitter.html
  42. 3 3
      src/server/views/installer.html
  43. 1 1
      src/server/views/invited.html
  44. 2 2
      src/server/views/layout/layout.html
  45. 16 49
      src/server/views/login.html
  46. 0 2
      src/server/views/me/api_token.html
  47. 0 51
      src/server/views/me/index.html
  48. 0 2
      src/server/views/me/password.html
  49. 2 2
      src/server/views/page_presentation.html
  50. 0 7
      src/server/views/widget/alert_breaking_changes.html
  51. 190 346
      yarn.lock

+ 4 - 0
CHANGES.md

@@ -20,11 +20,15 @@
 * Support: Upgrade libs
     * async
     * axios
+    * connect-mongo
     * file-loader
     * googleapis
     * i18next
     * migrate-mongo
     * mini-css-extract-plugin
+    * mongoose
+    * mongoose-gridfs
+    * mongoose-unique-validator
     * null-loader
 
 ## 3.4.7

+ 3 - 0
config/migrate.js

@@ -5,6 +5,8 @@
  * @author Yuki Takei <yuki@weseek.co.jp>
  */
 
+require('module-alias/register');
+
 function getMongoUri(env) {
   return env.MONGOLAB_URI // for B.C.
     || env.MONGODB_URI // MONGOLAB changes their env name
@@ -15,6 +17,7 @@ function getMongoUri(env) {
 
 const mongoUri = getMongoUri(process.env);
 const match = mongoUri.match(/^(.+)\/([^/]+)$/);
+
 module.exports = {
   mongoUri,
   mongodb: {

+ 4 - 5
package.json

@@ -70,7 +70,7 @@
     "//": "see https://github.com/parshap/check-node-version/issues/35",
     "check-node-version": "=3.3.0",
     "connect-flash": "~0.1.1",
-    "connect-mongo": "^2.0.1",
+    "connect-mongo": "^3.0.0",
     "connect-redis": "^3.3.0",
     "cookie-parser": "^1.4.3",
     "cross-env": "^5.0.5",
@@ -88,7 +88,6 @@
     "express-session": "^1.16.1",
     "express-validator": "^5.3.1",
     "express-webpack-assets": "^0.1.0",
-    "googleapis": "^40.0.0",
     "graceful-fs": "^4.1.11",
     "growi-commons": "^4.0.1",
     "helmet": "^3.13.0",
@@ -101,10 +100,10 @@
     "migrate-mongo": "^6.0.0",
     "mkdirp": "~0.5.1",
     "module-alias": "^2.0.6",
-    "mongoose": "^5.4.4",
-    "mongoose-gridfs": "^1.0.1",
+    "mongoose": "^5.6.0",
+    "mongoose-gridfs": "^1.2.2",
     "mongoose-paginate": "^5.0.3",
-    "mongoose-unique-validator": "^2.0.2",
+    "mongoose-unique-validator": "^2.0.3",
     "multer": "~1.4.0",
     "multer-autoreap": "^1.0.3",
     "nodemailer": "^6.0.0",

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

@@ -81,9 +81,7 @@
   "Delete this image?": "Delete this image?",
   "Updated": "Updated",
   "Upload new image": "Upload new image",
-  "Google Setting": "Google Setting",
   "Connected": "Connected",
-  "Disconnect": "Disconnect",
   "Show": "Show",
   "Hide": "Hide",
   "Disclose E-mail": "Disclose E-mail",
@@ -124,7 +122,6 @@
   "Reselect the group": "Reselect the group",
   "Shareable link": "Shareable link",
   "The whitelist of registration permission E-mail address": "The whitelist of registration permission E-mail address",
-  "Selecting authentication mechanism": "Selecting authentication mechanism",
   "Add tags for this page": "Add tags for this page",
   "Edit tags for this page": "Edit tags for this page",
   "You have no tag, You can set tags on pages": "You have no tag, You can set tags on pages",
@@ -149,15 +146,13 @@
   },
 
   "breaking_changes": {
-    "v346_passport_is_not_enabled": "Crowi Classic Authentication mechanism currently in use will <strong>no longer be supported</strong> in the near future. Switch to Passport from %s",
     "v346_using_basic_auth": "Basic Authentication currently in use will <strong>no longer be available</strong> in the near future. Remove settings from %s"
   },
 
   "page_register": {
     "notice": {
       "restricted": "Admin approval required.",
-      "restricted_defail": "Once the admin approves your sign up, you'll be able to access this wiki.",
-      "google_account_continue": "Enter your user ID, name and password to continue."
+      "restricted_defail": "Once the admin approves your sign up, you'll be able to access this wiki."
     },
     "form_help": {
       "email": "You must have email address which listed below to sign up to this wiki.",
@@ -169,11 +164,7 @@
   "page_me": {
     "form_help": {
       "profile_image1": "Image upload settings not completed.",
-      "profile_image2": "Set up AWS or enable local uploads.",
-      "google_connect1": "With Google Connect, you can sign in with your Google Account.",
-      "google_connect2": "Only Google Apps accounts with the following email addresses are connectable Google accounts:",
-      "google_disconnect1": "If you disconnect your Google account, you will be unable to sign in using Google Authentication",
-      "google_disconnect2": "After disconnecting your Google account, you can sign in normally using your email and password"
+      "profile_image2": "Set up AWS or enable local uploads."
     }
   },
   "page_me_apitoken": {
@@ -445,7 +436,6 @@
 		"Guest users access": "Guest users access",
 		"Register limitation": "Register limitation",
 		"The whitelist of registration permission E-mail address": "The whitelist of registration permission E-mail address",
-		"Selecting authentication mechanism": "Selecting authentication mechanism",
 		"common_authentication": "If you set the basic authentication, common authentication is applied on the whole page.",
 		"without_encryption": "Please be noted that your ID and Password will be sent wihtout encryption.",
 		"basic_acl_disable": "Because of Public Wiki  setting, basic authentication can not be used.",
@@ -460,33 +450,8 @@
     "page_listing_2": "Page listing/searching<br>restricted by User Group",
     "page_listing_2_desc": "Show pages that are restricted by User Group when listing/searching",
 
-		"Authentication mechanism settings": "Authentication mechanism settings",
-    "note": "Note",
-    "require_server_restart_change_auth": "Restarting the server is required if you switch the auth mechanism.",
-    "auth_mechanism": "authentication mechanism",
-    "recommended": "Recommended",
-    "username_email_password": "Username, Email and Password authentication",
+		"Authentication mechanism settings": "Authentication Mechanism Settings",
     "alert_siteUrl_is_not_set": "'Site URL' is NOT set. Set it from the %s",
-    "ldap_auth": "LDAP authentication",
-    "saml_auth": "SAML authentication",
-    "google_auth2": "Google OAuth authentication",
-    "google_auth2_by_crowi_desc": "However, this feature does not create new users, butit only makes it possible to login to the existing user who set up the association.",
-    "facebook_auth2": "Facebook OAuth authentication",
-    "twitter_auth2": "Twitter OAuth authentication",
-    "github_auth2": "GitHub OAuth authentication",
-    "crowi_auth": "Crowi classic authentication mechanism",
-		"require_server_restart": "Restarting the server is required.",
-		"server_on_passport_auth": "The server is running with Passport authentication mechanism.",
-		"server_on_crowi_auth": "The server is running with official Crowi authentication mechanism.",
-		"google_setting": "Google Setting",
-    "connect_api_manager": "You can use your Google account to sign up and login after creating OAuth2 ClientId at <a href=\"https://console.cloud.google.com/apis/credentials\" target=\"_blank\">API Manager on Google Cloud Platform</a>",
-		"access_api_manager": "Access <a href=\"%s\" target=\"_blank\">%s</a>",
-		"create_project": "Create Project if no projects have been created.",
-		"create_auth_to_oauth": "\"Create credentials\" -> \"OAuth clientID\"",
-		"select_webapp": "Select \"Web Application\"",
-    "change_redirect_url": "Enter <code>https://${crowi.host}/google/callback</code> <br>(where <code>${crowi.host}</code> is your host name) for \"Authorized redirect URIs\".",
-    "clientID": "Client ID",
-    "client_secret": "Client Secret",
     "xss_prevent_setting":"Prevent XSS(Cross Site Scripting)",
     "xss_prevent_setting_link":"Go to Markdown settings",
     "callback_URL": "Callback URL",

+ 2 - 37
resource/locales/ja/translation.json

@@ -81,9 +81,7 @@
   "Delete this image?": "削除してよろしいですか?",
   "Updated": "更新しました",
   "Upload new image": "新しい画像をアップロード",
-  "Google Setting": "Google設定",
   "Connected": "接続されています",
-  "Disconnect": "接続を解除",
   "Show": "公開",
   "Hide": "非公開",
   "Disclose E-mail": "メールアドレスの公開",
@@ -124,7 +122,6 @@
   "Reselect the group": "グループの再選択",
   "Shareable link": "このページの共有用URL",
   "The whitelist of registration permission E-mail address": "登録許可メールアドレスの<br>ホワイトリスト",
-  "Selecting authentication mechanism": "認証機構選択",
   "Add tags for this page": "タグを付ける",
   "Edit tags for this page": "タグを編集する",
   "You have no tag, You can set tags on pages": "使用中のタグがありません",
@@ -149,15 +146,13 @@
   },
 
   "breaking_changes": {
-    "v346_passport_is_not_enabled": "現在利用中の Crowi Classic Authentication mechanism は、近い将来<strong>サポートされなくなります</strong>。%s から Passport に切り替えてください。",
     "v346_using_basic_auth": "現在利用中の Basic 認証機能は、近い将来<strong>廃止されます</strong>。%s から設定を削除してください。"
   },
 
   "page_register": {
     "notice": {
        "restricted": "この Wiki への新規登録は制限されています。",
-       "restricted_defail": "利用を開始するには、新規登録後、管理者による承認が必要です。",
-       "google_account_continue": "ユーザーID、名前、パスワードを決めて登録を継続してください。"
+       "restricted_defail": "利用を開始するには、新規登録後、管理者による承認が必要です。"
     },
     "form_help": {
       "email": "この Wiki では以下のメールアドレスのみ登録可能です。",
@@ -169,11 +164,7 @@
   "page_me": {
     "form_help": {
       "profile_image1": "画像をアップロードをするための設定がされていません。",
-      "profile_image2": "アップロードできるようにするには、AWS またはローカルアップロードの設定をしてください。",
-      "google_connect1": "Googleコネクトをすると、Googleアカウントでログイン可能になります。",
-      "google_connect2": "コネクト可能なGoogleアカウントは、以下のメールアドレスの発行できるGoogle Appsアカウントに限られます。",
-      "google_disconnect1": "接続を解除すると、Googleでログインができなくなります。",
-      "google_disconnect2": "解除後はメールアドレスとパスワードでログインすることができます。"
+      "profile_image2": "アップロードできるようにするには、AWS またはローカルアップロードの設定をしてください。"
     }
   },
   "page_me_apitoken": {
@@ -445,7 +436,6 @@
     "Guest users access": "ゲストユーザーのアクセス",
     "Register limitation": "登録の制限",
     "The whitelist of registration permission E-mail address": "登録許可メールアドレスの<br>ホワイトリスト",
-    "Selecting authentication mechanism": "認証機構選択",
     "common_authentication": "Basic認証を設定すると、ページ全体に共通の認証がかかります。",
     "without_encryption": "IDとパスワードは暗号化されずに送信されるのでご注意下さい。",
     "basic_acl_disable": "Public Wiki の設定のため、Basic認証は利用できません。",
@@ -461,32 +451,7 @@
     "page_listing_2_desc": "ページのリスト表示や検索結果において、特定グループにのみ閲覧制限をしているページをアクセス権のないユーザーにも表示します。",
 
     "Authentication mechanism settings":"認証機構設定",
-    "note": "メモ",
-    "require_server_restart_change_auth": "認証機構の変更後はサーバーを再起動してください。",
-    "auth_mechanism": "認証機構",
-    "recommended": "推奨",
-    "username_email_password": "ユーザー名、Eメール、パスワードでの認証",
     "alert_siteUrl_is_not_set": "'サイトURL' が設定されていません。%s から設定してください。",
-    "ldap_auth": "LDAP 認証",
-    "saml_auth": "SAML 認証",
-    "google_auth2": "Google OAuth 認証",
-    "google_auth2_by_crowi_desc": "ただし、この機能では新たなユーザーは作成されず、関連付け設定を行った既存ユーザーをログインできるようにするだけです。",
-    "facebook_auth2": "Facebook OAuth 認証",
-    "twitter_auth2": "Twitter OAuth 認証",
-    "github_auth2": "GitHub OAuth 認証",
-    "crowi_auth": "Crowi Classic OAuth 認証",
-    "require_server_restart": "サーバーを再起動してください。",
-    "server_on_passport_auth": "Passport 認証機構でサーバーが稼働しています。",
-    "server_on_crowi_auth": "Crowi Classic 認証機構でサーバーが稼働しています。",
-    "google_setting": "Google 設定",
-    "connect_api_manager": "Google Cloud Platform の <a href=\"https://console.cloud.google.com/apis/credentials\" target=\"_blank\">API Manager</a>から OAuth2 Client ID を作成すると、Google アカウントにコネクトして登録やログインが可能になります。",
-    "access_api_manager": "<a href=\"%s\" target=\"_blank\">%s</a> へアクセス",
-    "create_project": "プロジェクトを作成していない場合は作成してください",
-    "create_auth_to_oauth": "「認証情報を作成」-> OAuthクライアントID",
-    "select_webapp": "「ウェブアプリケーション」を選択",
-    "change_redirect_url": "承認済みのリダイレクトURLに、 <code>https://${crowi.host}/google/callback</code> を入力<br>(<code>${crowi.host}</code>は環境に合わせて変更してください)",
-    "clientID": "クライアントID",
-    "client_secret": "クライアントシークレット",
     "xss_prevent_setting":"XSS(Cross Site Scripting)対策設定",
     "xss_prevent_setting_link":"マークダウン設定ページに移動",
     "callback_URL": "コールバックURL",

+ 1 - 0
src/client/js/components/PageEditor.jsx

@@ -162,6 +162,7 @@ class PageEditor extends React.Component {
       // when if created newly
       if (res.pageCreated) {
         logger.info('Page is created', res.pageCreated._id);
+        pageContainer.updateStateAfterSave(res.page);
       }
     }
     catch (e) {

+ 23 - 16
src/client/js/components/StaffCredit/Contributor.js

@@ -39,6 +39,7 @@ const contributors = [
       {
         additionalClass: 'col-md-4 my-4',
         members: [
+          { name: 'inductor' },
           { name: 'shield-9' },
           { name: 'yaodingyd' },
           { name: 'hitochan777' },
@@ -47,7 +48,6 @@ const contributors = [
           { name: 'nt-7' },
           { name: 'hideo54' },
           { name: 'wadahiro' },
-          { name: 'fumitti' },
         ],
       },
       {
@@ -60,6 +60,7 @@ const contributors = [
       {
         additionalClass: 'col-md-4 my-4',
         members: [
+          { name: 'fumitti' },
           { name: 'fmy' },
           { name: 'yaamai' },
           { name: 'ta2yak' },
@@ -72,21 +73,21 @@ const contributors = [
       },
     ],
   },
-  // {
-  //   sectionName: 'VALNERABILITY HUNTER',
-  //   additionalClass: '',
-  //   memberGroups: [
-  //     {
-  //       additionalClass: 'col-md-6 my-4',
-  //       members: [
-  //         { name: 'Yoshinori Hayashi' },
-  //         { name: 'Kanta Nishitani' },
-  //         { name: 'Takashi Yoneuchi' },
-  //         { position: 'DeCurret', name: 'Yusuke Tanomogi' },
-  //       ],
-  //     },
-  //   ],
-  // },
+  {
+    sectionName: 'VULNERABILITY HUNTER',
+    additionalClass: '',
+    memberGroups: [
+      {
+        additionalClass: 'col-md-6 my-4',
+        members: [
+          { name: 'Yoshinori Hayashi' },
+          { name: 'Kanta Nishitani' },
+          { position: 'The University of Tokyo', name: 'Takashi Yoneuchi' },
+          { position: 'DeCurret', name: 'Yusuke Tanomogi' },
+        ],
+      },
+    ],
+  },
   {
     sectionName: 'SPECIAL THANKS',
     additionalClass: '',
@@ -99,6 +100,12 @@ const contributors = [
           { name: 'JPCERT/CC' },
         ],
       },
+      {
+        additionalClass: 'col-md-12 staff-credit-mt-10',
+        members: [
+          { name: 'AND YOU' },
+        ],
+      },
     ],
   },
 ];

+ 20 - 2
src/client/styles/scss/_staff_credit.scss

@@ -1,5 +1,21 @@
 // Staff Credit
 #staff-credit {
+  // see https://css-tricks.com/old-timey-terminal-styling/
+  @mixin old-timey-terminal-styling() {
+    text-shadow: 0 0 10px #c8c8c8;
+    background-color: black;
+    background-image: radial-gradient(rgba(50, 100, 100, 0.75), black 120%);
+    &::after {
+      position: absolute;
+      top: 0;
+      left: 0;
+      width: 100vw;
+      height: 100vh;
+      content: '';
+      background: repeating-linear-gradient(0deg, rgba(black, 0.15), rgba(black, 0.15) 2px, transparent 2px, transparent 4px);
+    }
+  }
+
   font-family: 'Press Start 2P', $basefont1;
   color: white;
 
@@ -13,8 +29,9 @@
     color: white;
   }
 
-  $credit-length: -200em;
+  $credit-length: -240em;
 
+  // see https://css-tricks.com/old-timey-terminal-styling/
   .credit-curtain {
     position: fixed;
     top: 10vh;
@@ -22,7 +39,8 @@
     width: 80vw;
     height: 80vh;
     overflow-y: hidden;
-    background-color: black;
+
+    @include old-timey-terminal-styling();
   }
 
   .credit-body {

+ 12 - 0
src/lib/util/mongoose-utils.js

@@ -0,0 +1,12 @@
+const mongoose = require('mongoose');
+
+const getModelSafely = (modelName) => {
+  if (mongoose.modelNames().includes(modelName)) {
+    return mongoose.model(modelName);
+  }
+  return null;
+};
+
+module.exports = {
+  getModelSafely,
+};

+ 3 - 2
src/migrations/20180926134048-make-email-unique.js

@@ -1,16 +1,17 @@
-require('module-alias/register');
 const logger = require('@alias/logger')('growi:migrate:make-email-unique');
 
 const mongoose = require('mongoose');
 const config = require('@root/config/migrate');
 
+const { getModelSafely } = require('@commons/util/mongoose-utils');
+
 module.exports = {
 
   async up(db, next) {
     logger.info('Start migration');
     mongoose.connect(config.mongoUri, config.mongodb.options);
 
-    const User = require('@server/models/user')();
+    const User = getModelSafely('User') || require('@server/models/user')();
 
     // get all users who has 'deleted@deleted' email
     const users = await User.find({ email: 'deleted@deleted' });

+ 11 - 4
src/migrations/20180927102719-init-serverurl.js

@@ -1,11 +1,12 @@
 
 
-require('module-alias/register');
 const logger = require('@alias/logger')('growi:migrate:init-serverurl');
 
 const mongoose = require('mongoose');
 const config = require('@root/config/migrate');
 
+const { getModelSafely } = require('@commons/util/mongoose-utils');
+
 /**
  * check all values of the array are equal
  * @see https://stackoverflow.com/a/35568895
@@ -22,7 +23,7 @@ module.exports = {
     logger.info('Apply migration');
     mongoose.connect(config.mongoUri, config.mongodb.options);
 
-    const Config = require('@server/models/config')();
+    const Config = getModelSafely('Config') || require('@server/models/config')();
 
     // find 'app:siteUrl'
     const siteUrlConfig = await Config.findOne({
@@ -66,7 +67,13 @@ module.exports = {
     }
 
     if (siteUrl != null) {
-      await Config.findOneAndUpdateByNsAndKey('crowi', 'app:siteUrl', siteUrl);
+      const ns = 'crowi';
+      const key = 'app:siteUrl';
+      await Config.findOneAndUpdate(
+        { ns, key },
+        { ns, key, value: JSON.stringify(siteUrl) },
+        { upsert: true },
+      );
       logger.info('Migration has successfully applied');
     }
   },
@@ -75,7 +82,7 @@ module.exports = {
     logger.info('Undo migration');
     mongoose.connect(config.mongoUri, config.mongodb.options);
 
-    const Config = require('@server/models/config')();
+    const Config = getModelSafely('Config') || require('@server/models/config')();
 
     // remote 'app:siteUrl'
     await Config.findOneAndDelete({

+ 6 - 5
src/migrations/20181019114028-abolish-page-group-relation.js

@@ -1,9 +1,10 @@
-require('module-alias/register');
 const logger = require('@alias/logger')('growi:migrate:abolish-page-group-relation');
 
 const mongoose = require('mongoose');
 const config = require('@root/config/migrate');
 
+const { getModelSafely } = require('@commons/util/mongoose-utils');
+
 
 async function isCollectionExists(db, collectionName) {
   const collections = await db.listCollections({ name: collectionName }).toArray();
@@ -37,8 +38,8 @@ module.exports = {
       return;
     }
 
-    const Page = require('@server/models/page')();
-    const UserGroup = require('@server/models/user-group')();
+    const Page = getModelSafely('Page') || require('@server/models/page');
+    const UserGroup = getModelSafely('UserGroup') || require('@server/models/user-group')();
 
     // retrieve all documents from 'pagegrouprelations'
     const relations = await db.collection('pagegrouprelations').find().toArray();
@@ -74,8 +75,8 @@ module.exports = {
     logger.info('Undo migration');
     mongoose.connect(config.mongoUri, config.mongodb.options);
 
-    const Page = require('@server/models/page')();
-    const UserGroup = require('@server/models/user-group')();
+    const Page = getModelSafely('Page') || require('@server/models/page');
+    const UserGroup = getModelSafely('UserGroup') || require('@server/models/user-group')();
 
     // retrieve all Page documents which granted by UserGroup
     const relatedPages = await Page.find({ grant: Page.GRANT_USER_GROUP });

+ 31 - 0
src/migrations/20190618055300-abolish-crowi-classic-auth.js

@@ -0,0 +1,31 @@
+const logger = require('@alias/logger')('growi:migrate:make-email-unique');
+
+const mongoose = require('mongoose');
+const config = require('@root/config/migrate');
+
+const { getModelSafely } = require('@commons/util/mongoose-utils');
+
+
+module.exports = {
+  async up(db, next) {
+    logger.info('Start migration');
+    mongoose.connect(config.mongoUri, config.mongodb.options);
+
+    const Config = getModelSafely('Config') || require('@server/models/config')();
+
+    // enable passport and delete configs for crowi classic auth
+    await Promise.all([
+      Config.findOneAndUpdateByNsAndKey('crowi', 'security:isEnabledPassport', true),
+      Config.deleteOne({ ns: 'crowi', key: 'google:clientId' }),
+      Config.deleteOne({ ns: 'crowi', key: 'google:clientSecret' }),
+    ]);
+
+    logger.info('Migration has successfully terminated');
+    next();
+  },
+
+  down(db, next) {
+    // do not rollback
+    next();
+  },
+};

+ 64 - 0
src/migrations/20190618104011-add-config-app-installed.js

@@ -0,0 +1,64 @@
+const logger = require('@alias/logger')('growi:migrate:add-config-app-installed');
+
+const mongoose = require('mongoose');
+const config = require('@root/config/migrate');
+
+const { getModelSafely } = require('@commons/util/mongoose-utils');
+
+
+/**
+ * BEFORE
+ *   - Config document { ns: 'crowi', key: 'app:installed' } does not exist
+ * AFTER
+ *   - Config document { ns: 'crowi', key: 'app:installed' } is created
+ *     - value will be true if one or more users exist
+ *     - value will be false if no users exist
+ */
+module.exports = {
+
+  async up(db) {
+    logger.info('Apply migration');
+    mongoose.connect(config.mongoUri, config.mongodb.options);
+
+    const Config = getModelSafely('Config') || require('@server/models/config')();
+    const User = getModelSafely('User') || require('@server/models/user')();
+
+    // find 'app:siteUrl'
+    const appInstalled = await Config.findOne({
+      ns: 'crowi',
+      key: 'app:installed',
+    });
+    // exit if exists
+    if (appInstalled != null) {
+      logger.info('\'app:appInstalled\' is already exists. This migration terminates without any changes.');
+      return;
+    }
+
+    const userCount = await User.count();
+
+    if (userCount > 0) {
+      await Config.create({
+        ns: 'crowi',
+        key: 'app:installed',
+        value: true,
+      });
+    }
+
+    logger.info('Migration has successfully applied');
+  },
+
+  async down(db) {
+    logger.info('Undo migration');
+    mongoose.connect(config.mongoUri, config.mongodb.options);
+
+    const Config = getModelSafely('Config') || require('@server/models/config')();
+
+    // remote 'app:siteUrl'
+    await Config.findOneAndDelete({
+      ns: 'crowi',
+      key: 'app:installed',
+    });
+
+    logger.info('Migration has successfully undoed');
+  },
+};

+ 4 - 12
src/server/crowi/express-init.js

@@ -139,11 +139,9 @@ module.exports = function(crowi, app) {
   });
 
   // passport
-  if (getConfig('crowi', 'security:isEnabledPassport')) {
-    debug('initialize Passport');
-    app.use(passport.initialize());
-    app.use(passport.session());
-  }
+  debug('initialize Passport');
+  app.use(passport.initialize());
+  app.use(passport.session());
 
   app.use(flash());
 
@@ -154,13 +152,7 @@ module.exports = function(crowi, app) {
 
   app.use(middlewares.csrfKeyGenerator());
 
-  // switch loginChecker
-  if (getConfig('crowi', 'security:isEnabledPassport')) {
-    app.use(middlewares.loginCheckerForPassport);
-  }
-  else {
-    app.use(middlewares.loginChecker);
-  }
+  app.use(middlewares.loginCheckerForPassport);
 
   app.use(i18nMiddleware.handle(i18next));
 };

+ 3 - 11
src/server/crowi/index.js

@@ -82,9 +82,11 @@ Crowi.prototype.init = async function() {
 
   // customizeService depends on AppService and XssService
   // passportService depends on appService
+  // slack depends on setUpSlacklNotification
   await Promise.all([
     this.setUpApp(),
     this.setUpXss(),
+    this.setUpSlacklNotification(),
   ]);
 
   await Promise.all([
@@ -95,7 +97,6 @@ Crowi.prototype.init = async function() {
     this.setupSlack(),
     this.setupCsrf(),
     this.setUpGlobalNotification(),
-    this.setUpSlacklNotification(),
     this.setUpFileUpload(),
     this.setUpAcl(),
     this.setUpCustomize(),
@@ -212,8 +213,6 @@ Crowi.prototype.setupSessionConfig = function() {
 // };
 
 Crowi.prototype.setupConfigManager = async function() {
-  this.model('Config', require('../models/config')(this));
-
   const ConfigManager = require('../service/config-manager');
   this.configManager = new ConfigManager(this.model('Config'));
   return this.configManager.loadConfigs();
@@ -269,11 +268,6 @@ Crowi.prototype.getRestQiitaAPIService = function() {
 };
 
 Crowi.prototype.setupPassport = function() {
-  if (!this.configManager.getConfig('crowi', 'security:isEnabledPassport')) {
-    // disabled
-    return;
-  }
-
   debug('Passport is enabled');
 
   // initialize service
@@ -327,11 +321,9 @@ Crowi.prototype.setupMailer = function() {
 
 Crowi.prototype.setupSlack = function() {
   const self = this;
-  const config = this.getConfig();
-  const Config = this.model('Config');
 
   return new Promise(((resolve, reject) => {
-    if (Config.hasSlackConfig(config)) {
+    if (this.slackNotificationService.hasSlackConfig()) {
       self.slack = require('../util/slack')(self);
     }
 

+ 0 - 8
src/server/form/admin/securityGoogle.js

@@ -1,8 +0,0 @@
-const form = require('express-form');
-
-const field = form.field;
-
-module.exports = form(
-  field('settingForm[google:clientId]').trim().is(/^[\da-z\-.]+$/),
-  field('settingForm[google:clientSecret]').trim().is(/^[\da-zA-Z\-_]+$/),
-);

+ 0 - 7
src/server/form/admin/securityMechanism.js

@@ -1,7 +0,0 @@
-const form = require('express-form');
-
-const field = form.field;
-
-module.exports = form(
-  field('settingForm[security:isEnabledPassport]').trim().toBooleanStrict(),
-);

+ 0 - 2
src/server/form/index.js

@@ -19,8 +19,6 @@ module.exports = {
     importerQiita: require('./admin/importerQiita'),
     plugin: require('./admin/plugin'),
     securityGeneral: require('./admin/securityGeneral'),
-    securityGoogle: require('./admin/securityGoogle'),
-    securityMechanism: require('./admin/securityMechanism'),
     securityPassportLdap: require('./admin/securityPassportLdap'),
     securityPassportSaml: require('./admin/securityPassportSaml'),
     securityPassportGoogle: require('./admin/securityPassportGoogle'),

+ 0 - 2
src/server/form/register.js

@@ -7,7 +7,5 @@ module.exports = form(
   field('registerForm.name').required(),
   field('registerForm.email').required(),
   field('registerForm.password').required().is(/^[\x20-\x7F]{6,}$/),
-  field('registerForm.googleId'),
-  field('registerForm.googleImage'),
   field('registerForm[app:globalLang]'),
 );

+ 2 - 146
src/server/models/config.js

@@ -6,7 +6,6 @@
 module.exports = function(crowi) {
   const mongoose = require('mongoose');
   const debug = require('debug')('growi:models:config');
-  const recommendedWhitelist = require('@commons/service/xss/recommended-whitelist');
 
   const SECURITY_RESTRICT_GUEST_MODE_DENY = 'Deny';
   const SECURITY_RESTRICT_GUEST_MODE_READONLY = 'Readonly';
@@ -14,8 +13,6 @@ module.exports = function(crowi) {
   const SECURITY_REGISTRATION_MODE_RESTRICTED = 'Resricted';
   const SECURITY_REGISTRATION_MODE_CLOSED = 'Closed';
 
-  let Config;
-
   const configSchema = new mongoose.Schema({
     ns: { type: String, required: true, index: true },
     key: { type: String, required: true, index: true },
@@ -64,7 +61,6 @@ module.exports = function(crowi) {
       'security:list-policy:hideRestrictedByOwner' : false,
       'security:list-policy:hideRestrictedByGroup' : false,
 
-      'security:isEnabledPassport' : true,
       'security:passport-ldap:isEnabled' : false,
       'security:passport-ldap:serverUrl' : undefined,
       'security:passport-ldap:isUserBind' : undefined,
@@ -144,16 +140,6 @@ module.exports = function(crowi) {
     };
   }
 
-  function getValueForMarkdownNS(config, key) {
-    crowi.configManager.getConfig('markdown', key);
-    // // return the default value if undefined
-    // if (undefined === config.markdown || undefined === config.markdown[key]) {
-    //   return getDefaultMarkdownConfigs()[key];
-    // }
-
-    // return config.markdown[key];
-  }
-
   /**
    * It is deprecated to use this for anything other than AppService#isDBInitialized.
    */
@@ -262,9 +248,6 @@ module.exports = function(crowi) {
     );
   };
 
-  configSchema.statics.getConfig = function(callback) {
-  };
-
   // configSchema.statics.loadAllConfig = function(callback) {
   //   const Config = this;
 
@@ -292,133 +275,6 @@ module.exports = function(crowi) {
   //     });
   // };
 
-  configSchema.statics.isGuestAllowedToRead = function(config) {
-    // return true if puclic wiki mode
-    if (crowi.aclService.getIsPublicWikiOnly()) {
-      return true;
-    }
-
-    const restrictGuestMode = crowi.configManager.getConfig('crowi', 'security:restrictGuestMode');
-    // return false if undefined
-    if (undefined === config.crowi || undefined === restrictGuestMode) {
-      return false;
-    }
-
-    return SECURITY_RESTRICT_GUEST_MODE_READONLY === restrictGuestMode;
-  };
-
-  configSchema.statics.isEnabledLinebreaks = function(config) {
-    const key = 'markdown:isEnabledLinebreaks';
-    return getValueForMarkdownNS(config, key);
-  };
-
-  configSchema.statics.isEnabledLinebreaksInComments = function(config) {
-    const key = 'markdown:isEnabledLinebreaksInComments';
-    return getValueForMarkdownNS(config, key);
-  };
-  configSchema.statics.isPublicWikiOnly = function(config) {
-    const publicWikiOnly = process.env.PUBLIC_WIKI_ONLY;
-    if (publicWikiOnly === 'true' || publicWikiOnly === 1) {
-      return true;
-    }
-    return false;
-  };
-
-  configSchema.statics.pageBreakSeparator = function(config) {
-    const key = 'markdown:presentation:pageBreakSeparator';
-    return getValueForMarkdownNS(config, key);
-  };
-
-  configSchema.statics.pageBreakCustomSeparator = function(config) {
-    const key = 'markdown:presentation:pageBreakCustomSeparator';
-    return getValueForMarkdownNS(config, key);
-  };
-
-  configSchema.statics.isEnabledXssPrevention = function(config) {
-    const key = 'markdown:xss:isEnabledPrevention';
-    return getValueForMarkdownNS(config, key);
-  };
-
-  configSchema.statics.xssOption = function(config) {
-    const key = 'markdown:xss:option';
-    return getValueForMarkdownNS(config, key);
-  };
-
-  configSchema.statics.tagWhiteList = function(config) {
-    const key = 'markdown:xss:tagWhiteList';
-
-    if (this.isEnabledXssPrevention(config)) {
-      switch (this.xssOption(config)) {
-        case 1: // ignore all: use default option
-          return [];
-
-        case 2: // recommended
-          return recommendedWhitelist.tags;
-
-        case 3: // custom white list
-          return config.markdown[key];
-
-        default:
-          return [];
-      }
-    }
-    else {
-      return [];
-    }
-  };
-
-  configSchema.statics.attrWhiteList = function(config) {
-    const key = 'markdown:xss:attrWhiteList';
-
-    if (this.isEnabledXssPrevention(config)) {
-      switch (this.xssOption(config)) {
-        case 1: // ignore all: use default option
-          return [];
-
-        case 2: // recommended
-          return recommendedWhitelist.attrs;
-
-        case 3: // custom white list
-          return config.markdown[key];
-
-        default:
-          return [];
-      }
-    }
-    else {
-      return [];
-    }
-  };
-
-  configSchema.statics.hasSlackConfig = function(config) {
-    return Config.hasSlackToken(config) || Config.hasSlackIwhUrl(config);
-  };
-
-  /**
-   * for Slack Incoming Webhooks
-   */
-  configSchema.statics.hasSlackIwhUrl = function(config) {
-    if (!config.notification) {
-      return false;
-    }
-    return (!!config.notification['slack:incomingWebhookUrl']);
-  };
-
-  configSchema.statics.isIncomingWebhookPrioritized = function(config) {
-    if (!config.notification) {
-      return false;
-    }
-    return (!!config.notification['slack:isIncomingWebhookPrioritized']);
-  };
-
-  configSchema.statics.hasSlackToken = function(config) {
-    if (!config.notification) {
-      return false;
-    }
-
-    return (!!config.notification['slack:token']);
-  };
-
   configSchema.statics.getLocalconfig = function() { // CONF.RF: これも別のメソッドにする
     const env = process.env;
 
@@ -441,7 +297,7 @@ module.exports = function(crowi) {
       attrWhiteList: crowi.xssService.getAttrWhiteList(),
       highlightJsStyleBorder: crowi.configManager.getConfig('crowi', 'customize:highlightJsStyleBorder'),
       isSavedStatesOfTabChanges: crowi.configManager.getConfig('crowi', 'customize:isSavedStatesOfTabChanges'),
-      hasSlackConfig: crowi.configManager.getConfig('crowi', 'customize:behavior'),
+      hasSlackConfig: crowi.slackNotificationService.hasSlackConfig(),
       env: {
         PLANTUML_URI: env.PLANTUML_URI || null,
         BLOCKDIAG_URI: env.BLOCKDIAG_URI || null,
@@ -483,7 +339,7 @@ module.exports = function(crowi) {
   }
   */
 
-  Config = mongoose.model('Config', configSchema);
+  const Config = mongoose.model('Config', configSchema);
   Config.SECURITY_REGISTRATION_MODE_OPEN = SECURITY_REGISTRATION_MODE_OPEN;
   Config.SECURITY_REGISTRATION_MODE_RESTRICTED = SECURITY_REGISTRATION_MODE_RESTRICTED;
   Config.SECURITY_REGISTRATION_MODE_CLOSED = SECURITY_REGISTRATION_MODE_CLOSED;

+ 1 - 0
src/server/models/index.js

@@ -1,4 +1,5 @@
 module.exports = {
+  Config: require('./Config'),
   Page: require('./page'),
   PageTagRelation: require('./page-tag-relation'),
   User: require('./user'),

+ 17 - 14
src/server/models/user.js

@@ -79,16 +79,16 @@ module.exports = function(crowi) {
     validateCrowi();
 
     const Config = crowi.model('Config');
+    const configManager = crowi.configManager;
 
-
-    const config = crowi.getConfig();
-
-    if (!config.crowi) {
+    const isInstalled = configManager.getConfig('crowi', 'app:installed');
+    if (!isInstalled) {
       return STATUS_ACTIVE; // is this ok?
     }
 
     // status decided depends on registrationMode
-    switch (config.crowi['security:registrationMode']) {
+    const registrationMode = configManager.getConfig('crowi', 'security:registrationMode');
+    switch (registrationMode) {
       case Config.SECURITY_REGISTRATION_MODE_OPEN:
         return STATUS_ACTIVE;
       case Config.SECURITY_REGISTRATION_MODE_RESTRICTED:
@@ -620,12 +620,12 @@ module.exports = function(crowi) {
   userSchema.statics.createUsersByInvitation = function(emailList, toSendEmail, callback) {
     validateCrowi();
 
+    const configManager = crowi.configManager;
+
     const User = this;
     const createdUserList = [];
-    const Config = crowi.model('Config');
-    const config = crowi.getConfig();
-
     const mailer = crowi.getMailer();
+
     if (!Array.isArray(emailList)) {
       debug('emailList is not array');
     }
@@ -665,7 +665,7 @@ module.exports = function(crowi) {
           newUser.createdAt = Date.now();
           newUser.status = STATUS_INVITED;
 
-          const globalLang = Config.globalLang(config);
+          const globalLang = configManager.getConfig('crowi', 'app:globalLang');
           if (globalLang != null) {
             newUser.lang = globalLang;
           }
@@ -698,6 +698,8 @@ module.exports = function(crowi) {
         }
 
         if (toSendEmail) {
+          const appTitle = crowi.appService.getAppTitle();
+
           // TODO: メール送信部分のロジックをサービス化する
           async.each(
             createdUserList,
@@ -706,15 +708,17 @@ module.exports = function(crowi) {
                 return next();
               }
 
+              const appTitle = crowi.appService.getAppTitle();
+
               mailer.send({
                 to: user.email,
-                subject: `Invitation to ${Config.appTitle(config)}`,
+                subject: `Invitation to ${appTitle}`,
                 template: path.join(crowi.localeDir, 'en-US/admin/userInvitation.txt'),
                 vars: {
                   email: user.email,
                   password: user.password,
                   url: crowi.appService.getSiteUrl(),
-                  appTitle: Config.appTitle(config),
+                  appTitle,
                 },
               },
               (err, s) => {
@@ -759,9 +763,8 @@ module.exports = function(crowi) {
       newUser.setPassword(password);
     }
 
-    const Config = crowi.model('Config');
-    const config = crowi.getConfig();
-    const globalLang = Config.globalLang(config);
+    const configManager = crowi.configManager;
+    const globalLang = configManager.getConfig('crowi', 'app:globalLang');
     if (globalLang != null) {
       newUser.lang = globalLang;
     }

+ 34 - 51
src/server/routes/admin.js

@@ -14,7 +14,7 @@ module.exports = function(crowi, app) {
   const GlobalNotificationMailSetting = models.GlobalNotificationMailSetting;
   const GlobalNotificationSlackSetting = models.GlobalNotificationSlackSetting; // eslint-disable-line no-unused-vars
 
-  const { configManager } = crowi;
+  const { configManager, aclService, slackNotificationService } = crowi;
 
   const recommendedWhitelist = require('@commons/service/xss/recommended-whitelist');
   const PluginUtils = require('../plugins/plugin-utils');
@@ -106,7 +106,7 @@ module.exports = function(crowi, app) {
   actions.security = {};
   actions.security.index = function(req, res) {
     const settingForm = configManager.getConfigByPrefix('crowi', 'security:');
-    const isAclEnabled = crowi.aclService.getIsPublicWikiOnly();
+    const isAclEnabled = aclService.getIsPublicWikiOnly();
 
     return res.render('admin/security', { settingForm, isAclEnabled });
   };
@@ -114,7 +114,7 @@ module.exports = function(crowi, app) {
   // app.get('/admin/markdown'                  , admin.markdown.index);
   actions.markdown = {};
   actions.markdown.index = function(req, res) {
-    const markdownSetting = configManager.getConfigByPrefix('crowi', 'markdown:');
+    const markdownSetting = configManager.getConfigByPrefix('markdown', 'markdown:');
 
     return res.render('admin/markdown', {
       markdownSetting,
@@ -123,66 +123,54 @@ module.exports = function(crowi, app) {
   };
 
   // app.post('/admin/markdown/lineBreaksSetting' , admin.markdown.lineBreaksSetting);
-  actions.markdown.lineBreaksSetting = function(req, res) {
+  actions.markdown.lineBreaksSetting = async function(req, res) {
     const markdownSetting = req.form.markdownSetting;
 
-    req.session.markdownSetting = markdownSetting;
     if (req.form.isValid) {
-      Config.updateNamespaceByArray('markdown', markdownSetting, (err, config) => {
-        Config.updateConfigCache('markdown', config);
-        req.session.markdownSetting = null;
-        req.flash('successMessage', ['Successfully updated!']);
-        return res.redirect('/admin/markdown');
-      });
+      await configManager.updateConfigsInTheSameNamespace('markdown', markdownSetting);
+      req.flash('successMessage', ['Successfully updated!']);
     }
     else {
       req.flash('errorMessage', req.form.errors);
-      return res.redirect('/admin/markdown');
     }
+
+    return res.redirect('/admin/markdown');
   };
 
   // app.post('/admin/markdown/presentationSetting' , admin.markdown.presentationSetting);
-  actions.markdown.presentationSetting = function(req, res) {
-    const presentationSetting = req.form.markdownSetting;
+  actions.markdown.presentationSetting = async function(req, res) {
+    const markdownSetting = req.form.markdownSetting;
 
-    req.session.markdownSetting = presentationSetting;
     if (req.form.isValid) {
-      Config.updateNamespaceByArray('markdown', presentationSetting, (err, config) => {
-        Config.updateConfigCache('markdown', config);
-        req.session.markdownSetting = null;
-        req.flash('successMessage', ['Successfully updated!']);
-        return res.redirect('/admin/markdown');
-      });
+      await configManager.updateConfigsInTheSameNamespace('markdown', markdownSetting);
+      req.flash('successMessage', ['Successfully updated!']);
     }
     else {
       req.flash('errorMessage', req.form.errors);
-      return res.redirect('/admin/markdown');
     }
+
+    return res.redirect('/admin/markdown');
   };
 
   // app.post('/admin/markdown/xss-setting' , admin.markdown.xssSetting);
-  actions.markdown.xssSetting = function(req, res) {
+  actions.markdown.xssSetting = async function(req, res) {
     const xssSetting = req.form.markdownSetting;
 
-    xssSetting['markdown:xss:tagWhiteList'] = stringToArray(xssSetting['markdown:xss:tagWhiteList']);
-    xssSetting['markdown:xss:attrWhiteList'] = stringToArray(xssSetting['markdown:xss:attrWhiteList']);
+    xssSetting['markdown:xss:tagWhiteList'] = csvToArray(xssSetting['markdown:xss:tagWhiteList']);
+    xssSetting['markdown:xss:attrWhiteList'] = csvToArray(xssSetting['markdown:xss:attrWhiteList']);
 
-    req.session.markdownSetting = xssSetting;
     if (req.form.isValid) {
-      Config.updateNamespaceByArray('markdown', xssSetting, (err, config) => {
-        Config.updateConfigCache('markdown', config);
-        req.session.xssSetting = null;
-        req.flash('successMessage', ['Successfully updated!']);
-        return res.redirect('/admin/markdown');
-      });
+      await configManager.updateConfigsInTheSameNamespace('markdown', xssSetting);
+      req.flash('successMessage', ['Successfully updated!']);
     }
     else {
       req.flash('errorMessage', req.form.errors);
-      return res.redirect('/admin/markdown');
     }
+
+    return res.redirect('/admin/markdown');
   };
 
-  const stringToArray = (string) => {
+  const csvToArray = (string) => {
     const array = string.split(',');
     return array.map((item) => { return item.trim() });
   };
@@ -216,13 +204,12 @@ module.exports = function(crowi, app) {
   // app.get('/admin/notification'               , admin.notification.index);
   actions.notification = {};
   actions.notification.index = async(req, res) => {
-    const config = crowi.getConfig();
     const UpdatePost = crowi.model('UpdatePost');
     let slackSetting = configManager.getConfigByPrefix('notification', 'slack:');
-    const hasSlackIwhUrl = Config.hasSlackIwhUrl(config);
-    const hasSlackToken = Config.hasSlackToken(config);
+    const hasSlackIwhUrl = !!configManager.getConfig('notification', 'slack:incomingWebhookUrl');
+    const hasSlackToken = !!configManager.getConfig('notification', 'slack:token');
 
-    if (!Config.hasSlackIwhUrl(req.config)) {
+    if (!hasSlackIwhUrl) {
       slackSetting['slack:incomingWebhookUrl'] = '';
     }
 
@@ -270,7 +257,7 @@ module.exports = function(crowi, app) {
   actions.notification.slackAuth = function(req, res) {
     const code = req.query.code;
 
-    if (!code || !Config.hasSlackConfig(req.config)) {
+    if (!code || !slackNotificationService.hasSlackConfig()) {
       return res.redirect('/admin/notification');
     }
 
@@ -298,18 +285,16 @@ module.exports = function(crowi, app) {
   };
 
   // app.post('/admin/notification/slackIwhSetting' , admin.notification.slackIwhSetting);
-  actions.notification.slackIwhSetting = function(req, res) {
+  actions.notification.slackIwhSetting = async function(req, res) {
     const slackIwhSetting = req.form.slackIwhSetting;
 
     if (req.form.isValid) {
-      Config.updateNamespaceByArray('notification', slackIwhSetting, (err, config) => {
-        Config.updateConfigCache('notification', config);
-        req.flash('successMessage', ['Successfully Updated!']);
+      await configManager.updateConfigsInTheSameNamespace('notification', slackIwhSetting);
+      req.flash('successMessage', ['Successfully Updated!']);
 
-        // Re-setup
-        crowi.setupSlack().then(() => {
-          return res.redirect('/admin/notification#slack-incoming-webhooks');
-        });
+      // Re-setup
+      crowi.setupSlack().then(() => {
+        return res.redirect('/admin/notification#slack-incoming-webhooks');
       });
     }
     else {
@@ -650,7 +635,7 @@ module.exports = function(crowi, app) {
   actions.userGroup = {};
   actions.userGroup.index = function(req, res) {
     const page = parseInt(req.query.page) || 1;
-    const isAclEnabled = !Config.isPublicWikiOnly(req.config);
+    const isAclEnabled = aclService.getIsPublicWikiOnly();
     const renderVar = {
       userGroups: [],
       userGroupRelations: new Map(),
@@ -914,9 +899,7 @@ module.exports = function(crowi, app) {
     }
 
     const form = req.form.settingForm;
-    const config = crowi.getConfig();
-    const isPublicWikiOnly = Config.isPublicWikiOnly(config);
-    if (isPublicWikiOnly) {
+    if (aclService.getIsPublicWikiOnly()) {
       const basicName = form['security:basicName'];
       const basicSecret = form['security:basicSecret'];
       if (basicName !== '' || basicSecret !== '') {

+ 1 - 2
src/server/routes/attachment.js

@@ -3,7 +3,6 @@
 
 const logger = require('@alias/logger')('growi:routes:attachment');
 
-const path = require('path');
 const fs = require('fs');
 
 const ApiResponse = require('../util/apiResponse');
@@ -234,7 +233,7 @@ module.exports = function(crowi, app) {
     if (pageId == null) {
       logger.debug('Create page before file upload');
 
-      page = await Page.create(path, `# ${path}`, req.user, { grant: Page.GRANT_OWNER });
+      page = await Page.create(pagePath, `# ${pagePath}`, req.user, { grant: Page.GRANT_OWNER });
       pageCreated = true;
       pageId = page._id;
     }

+ 12 - 26
src/server/routes/index.js

@@ -22,11 +22,12 @@ module.exports = function(crowi, app) {
   const revision = require('./revision')(crowi, app);
   const search = require('./search')(crowi, app);
   const hackmd = require('./hackmd')(crowi, app);
-  const loginRequired = middlewares.loginRequired;
-  const adminRequired = middlewares.adminRequired;
-  const accessTokenParser = middlewares.accessTokenParser;
-  const csrf = middlewares.csrfVerify;
-  const { configManager } = crowi;
+  const {
+    loginRequired,
+    adminRequired,
+    accessTokenParser,
+    csrfVerify: csrf,
+  } = middlewares;
 
   /* eslint-disable max-len, comma-spacing, no-multi-spaces */
 
@@ -39,21 +40,11 @@ module.exports = function(crowi, app) {
   app.get('/login'                   , middlewares.applicationInstalled    , login.login);
   app.get('/login/invited'           , login.invited);
   app.post('/login/activateInvited'  , form.invited                         , csrf, login.invited);
-
-  // switch POST /login route
-  if (configManager.getConfig('crowi', 'security:isEnabledPassport')) {
-    app.post('/login'                , form.login                           , csrf, loginPassport.loginWithLocal, loginPassport.loginWithLdap, loginPassport.loginFailure);
-    app.post('/_api/login/testLdap'  , loginRequired() , form.login , loginPassport.testLdapCredentials);
-  }
-  else {
-    app.post('/login'                , form.login                           , csrf, login.login);
-  }
+  app.post('/login'                  , form.login                           , csrf, loginPassport.loginWithLocal, loginPassport.loginWithLdap, loginPassport.loginFailure);
+  app.post('/_api/login/testLdap'    , loginRequired() , form.login , loginPassport.testLdapCredentials);
 
   app.post('/register'               , form.register                        , csrf, login.register);
   app.get('/register'                , middlewares.applicationInstalled    , login.register);
-  app.post('/register/google'        , login.registerGoogle);
-  app.get('/google/callback'         , login.googleCallback);
-  app.get('/login/google'            , login.loginGoogle);
   app.get('/logout'                  , logout.logout);
 
   app.get('/admin'                          , loginRequired() , adminRequired , admin.index);
@@ -67,8 +58,6 @@ module.exports = function(crowi, app) {
   // security admin
   app.get('/admin/security'                     , loginRequired() , adminRequired , admin.security.index);
   app.post('/_api/admin/security/general'       , loginRequired() , adminRequired , form.admin.securityGeneral, admin.api.securitySetting);
-  app.post('/_api/admin/security/google'        , loginRequired() , adminRequired , csrf, form.admin.securityGoogle, admin.api.securitySetting);
-  app.post('/_api/admin/security/mechanism'     , loginRequired() , adminRequired , csrf, form.admin.securityMechanism, admin.api.securitySetting);
   app.post('/_api/admin/security/passport-ldap' , loginRequired() , adminRequired , csrf, form.admin.securityPassportLdap, admin.api.securityPassportLdapSetting);
   app.post('/_api/admin/security/passport-saml' , loginRequired() , adminRequired , csrf, form.admin.securityPassportSaml, admin.api.securityPassportSamlSetting);
 
@@ -163,16 +152,13 @@ module.exports = function(crowi, app) {
   app.get('/me/apiToken'              , loginRequired() , me.apiToken);
   app.post('/me'                      , loginRequired() , csrf , form.me.user , me.index);
   // external-accounts
-  if (configManager.getConfig('crowi', 'security:isEnabledPassport')) {
-    app.get('/me/external-accounts'                         , loginRequired() , me.externalAccounts.list);
-    app.post('/me/external-accounts/disassociate'           , loginRequired() , me.externalAccounts.disassociate);
-    app.post('/me/external-accounts/associateLdap'          , loginRequired() , form.login , me.externalAccounts.associateLdap);
-  }
+  app.get('/me/external-accounts'                         , loginRequired() , me.externalAccounts.list);
+  app.post('/me/external-accounts/disassociate'           , loginRequired() , me.externalAccounts.disassociate);
+  app.post('/me/external-accounts/associateLdap'          , loginRequired() , form.login , me.externalAccounts.associateLdap);
+
   app.post('/me/password'             , form.me.password          , loginRequired() , me.password);
   app.post('/me/imagetype'            , form.me.imagetype         , loginRequired() , me.imagetype);
   app.post('/me/apiToken'             , form.me.apiToken          , loginRequired() , me.apiToken);
-  app.post('/me/auth/google'          , loginRequired() , me.authGoogle);
-  app.get('/me/auth/google/callback' , loginRequired() , me.authGoogleCallback);
 
   app.get('/:id([0-9a-z]{24})'       , loginRequired(false) , page.redirector);
   app.get('/_r/:id([0-9a-z]{24})'    , loginRequired(false) , page.redirector); // alias

+ 7 - 118
src/server/routes/login.js

@@ -15,9 +15,6 @@ module.exports = function(crowi, app) {
 
   const actions = {};
 
-  const clearGoogleSession = function(req) {
-    req.session.googleAuthCode = req.session.googleId = req.session.googleEmail = req.session.googleName = req.session.googleImage = null;
-  };
   const loginSuccess = function(req, res, userData) {
     req.user = req.session.user = userData;
 
@@ -32,8 +29,6 @@ module.exports = function(crowi, app) {
       return res.redirect('/me/password');
     }
 
-    clearGoogleSession(req);
-
     const jumpTo = req.session.jumpTo;
     if (jumpTo) {
       req.session.jumpTo = null;
@@ -60,16 +55,6 @@ module.exports = function(crowi, app) {
     return res.redirect('/login');
   };
 
-  actions.googleCallback = function(req, res) {
-    const nextAction = req.session.googleCallbackAction || '/login';
-    debug('googleCallback.nextAction', nextAction);
-    req.session.googleAuthCode = req.query.code || '';
-    debug('google auth code', req.query.code);
-
-
-    return res.redirect(nextAction);
-  };
-
   actions.error = function(req, res) {
     const reason = req.params.reason;
 
@@ -114,43 +99,7 @@ module.exports = function(crowi, app) {
     }
   };
 
-  actions.loginGoogle = function(req, res) {
-    const googleAuth = require('../util/googleAuth')(crowi);
-    const code = req.session.googleAuthCode || null;
-
-    if (!code) {
-      googleAuth.createAuthUrl(req, (err, redirectUrl) => {
-        if (err) {
-          // TODO
-        }
-
-        req.session.googleCallbackAction = '/login/google';
-        return res.redirect(redirectUrl);
-      });
-    }
-    else {
-      googleAuth.handleCallback(req, (err, tokenInfo) => {
-        debug('handleCallback', err, tokenInfo);
-        if (err) {
-          return loginFailure(req, res);
-        }
-
-        const googleId = tokenInfo.user_id;
-        User.findUserByGoogleId(googleId, (err, userData) => {
-          debug('findUserByGoogleId', err, userData);
-          if (!userData) {
-            clearGoogleSession(req);
-            return loginFailure(req, res);
-          }
-          return loginSuccess(req, res, userData);
-        });
-      });
-    }
-  };
-
   actions.register = function(req, res) {
-    const googleAuth = require('../util/googleAuth')(crowi);
-
     // redirect to '/' if both of these are true:
     //  1. user has logged in
     //  2. req.user is not username/email string (which is set by basic-auth-connect)
@@ -170,8 +119,6 @@ module.exports = function(crowi, app) {
       const username = registerForm.username;
       const email = registerForm.email;
       const password = registerForm.password;
-      var googleId = registerForm.googleId || null;
-      var googleImage = registerForm.googleImage || null;
 
       // email と username の unique チェックする
       User.isRegisterable(email, username, (isRegisterable, errOn) => {
@@ -238,81 +185,23 @@ module.exports = function(crowi, app) {
             });
           }
 
-          if (googleId) {
-            userData.updateGoogleId(googleId, (err, userData) => {
-              if (err) { // TODO
-              }
-              return loginSuccess(req, res, userData);
-            });
-          }
-          else {
-            // add a flash message to inform the user that processing was successful -- 2017.09.23 Yuki Takei
-            // cz. loginSuccess method doesn't work on it's own when using passport
-            //      because `req.login()` prepared by passport is not called.
-            req.flash('successMessage', `The user '${userData.username}' is successfully created.`);
 
-            return loginSuccess(req, res, userData);
-          }
+          // add a flash message to inform the user that processing was successful -- 2017.09.23 Yuki Takei
+          // cz. loginSuccess method doesn't work on it's own when using passport
+          //      because `req.login()` prepared by passport is not called.
+          req.flash('successMessage', `The user '${userData.username}' is successfully created.`);
+
+          return loginSuccess(req, res, userData);
         });
       });
     }
     else { // method GET of form is not valid
       debug('session is', req.session);
       const isRegistering = true;
-      // google callback を受ける可能性もある
-      const code = req.session.googleAuthCode || null;
-      var googleId = req.session.googleId || null;
-      let googleEmail = req.session.googleEmail || null;
-      let googleName = req.session.googleName || null;
-      var googleImage = req.session.googleImage || null;
-
-      debug('register. if code', code);
-      // callback 経由で reigster にアクセスしてきた時最初だけこの if に入る
-      // code から email などを取得したらそれを session にいれて code は消去
-      if (code) {
-        googleAuth.handleCallback(req, (err, tokenInfo) => {
-          debug('tokenInfo on register GET', tokenInfo);
-          req.session.googleAuthCode = null;
-
-          if (err) {
-            req.flash('registerWarningMessage', 'Error on connectiong Google');
-            return res.redirect('/login?register=1'); // TODO Handling
-          }
-
-          req.session.googleId = googleId = tokenInfo.user_id;
-          req.session.googleEmail = googleEmail = tokenInfo.email;
-          req.session.googleName = googleName = tokenInfo.name;
-          req.session.googleImage = googleImage = tokenInfo.picture;
-
-          if (!User.isEmailValid(googleEmail)) {
-            req.flash('registerWarningMessage', 'このメールアドレスのGoogleアカウントはコネクトできません。');
-            return res.redirect('/login?register=1');
-          }
-          return res.render('login', {
-            isRegistering, googleId, googleEmail, googleName, googleImage,
-          });
-        });
-      }
-      else {
-        return res.render('login', {
-          isRegistering, googleId, googleEmail, googleName, googleImage,
-        });
-      }
+      return res.render('login', { isRegistering });
     }
   };
 
-  actions.registerGoogle = function(req, res) {
-    const googleAuth = require('../util/googleAuth')(crowi);
-    googleAuth.createAuthUrl(req, (err, redirectUrl) => {
-      if (err) {
-        // TODO
-      }
-
-      req.session.googleCallbackAction = '/register';
-      return res.redirect(redirectUrl);
-    });
-  };
-
   actions.invited = async function(req, res) {
     if (!req.user) {
       return res.redirect('/login');

+ 0 - 67
src/server/routes/me.js

@@ -309,72 +309,5 @@ module.exports = function(crowi, app) {
     });
   };
 
-  actions.authGoogle = function(req, res) {
-    const googleAuth = require('../util/googleAuth')(crowi);
-
-    const userData = req.user;
-
-    const toDisconnect = !!req.body.disconnectGoogle;
-    const toConnect = !!req.body.connectGoogle;
-    if (toDisconnect) {
-      userData.deleteGoogleId((err, userData) => {
-        req.flash('successMessage', 'Disconnected from Google account');
-
-        return res.redirect('/me');
-      });
-    }
-    else if (toConnect) {
-      googleAuth.createAuthUrl(req, (err, redirectUrl) => {
-        if (err) {
-          // TODO
-        }
-
-        req.session.googleCallbackAction = '/me/auth/google/callback';
-        return res.redirect(redirectUrl);
-      });
-    }
-    else {
-      return res.redirect('/me');
-    }
-  };
-
-  actions.authGoogleCallback = function(req, res) {
-    const googleAuth = require('../util/googleAuth')(crowi);
-    const userData = req.user;
-
-    googleAuth.handleCallback(req, (err, tokenInfo) => {
-      if (err) {
-        req.flash('warningMessage.auth.google', err.message); // FIXME: show library error message directly
-        return res.redirect('/me'); // TODO Handling
-      }
-
-      const googleId = tokenInfo.user_id;
-      const googleEmail = tokenInfo.email;
-      if (!User.isEmailValid(googleEmail)) {
-        req.flash('warningMessage.auth.google', 'You can\'t connect with this  Google\'s account');
-        return res.redirect('/me');
-      }
-
-      User.findUserByGoogleId(googleId, (err, googleUser) => {
-        if (!err && googleUser) {
-          req.flash('warningMessage.auth.google', 'This Google\'s account is connected by another user');
-          return res.redirect('/me');
-        }
-
-        userData.updateGoogleId(googleId, (err, userData) => {
-          if (err) {
-            debug('Failed to updateGoogleId', err);
-            req.flash('warningMessage.auth.google', 'Failed to connect Google Account');
-            return res.redirect('/me');
-          }
-
-          // TODO if err
-          req.flash('successMessage', 'Connected with Google');
-          return res.redirect('/me');
-        });
-      });
-    });
-  };
-
   return actions;
 };

+ 2 - 3
src/server/routes/page.js

@@ -8,7 +8,6 @@ module.exports = function(crowi, app) {
 
   const Page = crowi.model('Page');
   const User = crowi.model('User');
-  const Config = crowi.model('Config');
   const config = crowi.getConfig();
   const Bookmark = crowi.model('Bookmark');
   const PageTagRelation = crowi.model('PageTagRelation');
@@ -17,7 +16,7 @@ module.exports = function(crowi, app) {
   const ApiResponse = require('../util/apiResponse');
   const getToday = require('../util/getToday');
 
-  const configManager = crowi.configManager;
+  const { configManager, slackNotificationService } = crowi;
   const interceptorManager = crowi.getInterceptorManager();
   const globalNotificationService = crowi.getGlobalNotificationService();
 
@@ -99,7 +98,7 @@ module.exports = function(crowi, app) {
         logger.error('Error occured in updating slack channels: ', err);
       });
 
-    if (Config.hasSlackConfig(config)) {
+    if (slackNotificationService.hasSlackConfig(config)) {
       const promises = slackChannels.split(',').map((chan) => {
         return crowi.slack.postPage(page, user, chan, updateOrCreate, previousRevision);
       });

+ 0 - 22
src/server/service/notification.js

@@ -1,22 +0,0 @@
-
-
-function Notification(crowi) {
-  this.crowi = crowi;
-  this.config = crowi.getConfig();
-}
-
-Notification.prototype.hasSlackConfig = function() {
-  if (!this.config.notification.slack) {
-    return false;
-  }
-
-  // var config = ;
-};
-
-Notification.prototype.noitfyByEmail = function() {
-};
-
-Notification.prototype.noitfyByChat = function() {
-};
-
-module.exports = Notification;

+ 1 - 1
src/server/service/slack-notification.js

@@ -12,7 +12,7 @@ class SlackNotificationService {
     let hasSlackToken = false;
     let hasSlackIwhUrl = false;
 
-    if (this.configObject.notification) {
+    if (this.configManager.configObject.notification) {
       hasSlackToken = !!this.configManager.getConfig('notification', 'slack:token');
       hasSlackIwhUrl = !!this.configManager.getConfig('notification', 'slack:incomingWebhookUrl');
     }

+ 0 - 70
src/server/util/googleAuth.js

@@ -1,70 +0,0 @@
-const debug = require('debug')('growi:lib:googleAuth');
-const urljoin = require('url-join');
-const { GoogleApis } = require('googleapis');
-
-/**
- * googleAuth utility
- */
-
-module.exports = function(crowi) {
-  const google = new GoogleApis();
-  const config = crowi.getConfig();
-
-  const lib = {};
-  function createOauth2Client(url) {
-    return new google.auth.OAuth2(
-      config.crowi['google:clientId'],
-      config.crowi['google:clientSecret'],
-      url,
-    );
-  }
-
-  lib.createAuthUrl = function(req, callback) {
-    const callbackUrl = urljoin(crowi.appService.getSiteUrl(), '/google/callback');
-    const oauth2Client = createOauth2Client(callbackUrl);
-    google.options({ auth: oauth2Client });
-
-    const redirectUrl = oauth2Client.generateAuthUrl({
-      access_type: 'offline',
-      scope: ['profile', 'email'],
-    });
-
-    callback(null, redirectUrl);
-  };
-
-  lib.handleCallback = function(req, callback) {
-    const callbackUrl = urljoin(crowi.appService.getSiteUrl(), '/google/callback');
-    const oauth2Client = createOauth2Client(callbackUrl);
-    google.options({ auth: oauth2Client });
-
-    const code = req.session.googleAuthCode || null;
-
-    if (!code) {
-      return callback(new Error('No code exists.'), null);
-    }
-
-    debug('Request googleToken by auth code', code);
-    oauth2Client.getToken(code, (err, tokens) => {
-      debug('Result of google.getToken()', err, tokens);
-      if (err) {
-        return callback(new Error('[googleAuth.handleCallback] Error to get token.'), null);
-      }
-
-      oauth2Client.credentials = tokens;
-
-      const oauth2 = google.oauth2('v2');
-      oauth2.userinfo.get({}, (err, response) => {
-        debug('Response of oauth2.userinfo.get', err, response);
-        if (err) {
-          return callback(new Error('[googleAuth.handleCallback] Error while proceccing userinfo.get.'), null);
-        }
-
-        const data = response.data;
-        data.user_id = data.id; // This is for B.C. (tokeninfo をつかっている前提のコードに対してのもの)
-        return callback(null, data);
-      });
-    });
-  };
-
-  return lib;
-};

+ 1 - 23
src/server/util/middlewares.js

@@ -21,26 +21,6 @@ module.exports = (crowi, app) => {
     };
   };
 
-  middlewares.loginChecker = async function(req, res, next) {
-    const User = crowi.model('User');
-    let user = null;
-
-    try {
-      // session に user object が入ってる
-      if (req.session.user && '_id' in req.session.user) {
-        user = await User.findById(req.session.user._id).populate(User.IMAGE_POPULATION);
-      }
-
-      req.user = user;
-      req.session.user = user;
-      res.locals.user = req.user;
-      next();
-    }
-    catch (err) {
-      next(err);
-    }
-  };
-
   middlewares.loginCheckerForPassport = function(req, res, next) {
     res.locals.user = req.user;
     next();
@@ -208,15 +188,13 @@ module.exports = (crowi, app) => {
    * @param {boolean} isStrictly whethere strictly restricted (default true)
    */
   middlewares.loginRequired = function(isStrictly = true) {
-    const isGuestAllowedToRead = crowi.aclService.getIsGuestAllowedToRead();
-
     return function(req, res, next) {
       const User = crowi.model('User');
 
       // when the route is not strictly restricted
       if (!isStrictly) {
         // when allowed to read
-        if (isGuestAllowedToRead) {
+        if (crowi.aclService.getIsGuestAllowedToRead()) {
           return next();
         }
       }

+ 10 - 7
src/server/util/slack.js

@@ -11,6 +11,7 @@ module.exports = function(crowi) {
   const config = crowi.getConfig();
   const Config = crowi.model('Config');
   const Slack = require('slack-node');
+  const { configManager } = crowi;
 
   const slack = {};
 
@@ -107,6 +108,7 @@ module.exports = function(crowi) {
   };
 
   const prepareSlackMessageForPage = function(page, user, channel, updateType, previousRevision) {
+    const appTitle = crowi.appService.getAppTitle();
     const url = crowi.appService.getSiteUrl();
     let body = page.revision.body;
 
@@ -133,7 +135,7 @@ module.exports = function(crowi) {
 
     const message = {
       channel: `#${channel}`,
-      username: Config.appTitle(config),
+      username: appTitle,
       text: getSlackMessageTextForPage(page.path, page.id, user, updateType),
       attachments: [attachment],
     };
@@ -142,6 +144,7 @@ module.exports = function(crowi) {
   };
 
   const prepareSlackMessageForComment = function(comment, user, channel, path) {
+    const appTitle = crowi.appService.getAppTitle();
     const url = crowi.appService.getSiteUrl();
     const body = prepareAttachmentTextForComment(comment);
 
@@ -159,7 +162,7 @@ module.exports = function(crowi) {
 
     const message = {
       channel: `#${channel}`,
-      username: Config.appTitle(config),
+      username: appTitle,
       text: getSlackMessageTextForComment(path, String(comment.page), user),
       attachments: [attachment],
     };
@@ -205,23 +208,23 @@ module.exports = function(crowi) {
 
   const slackPost = (messageObj) => {
     // when incoming Webhooks is prioritized
-    if (Config.isIncomingWebhookPrioritized(config)) {
-      if (Config.hasSlackIwhUrl(config)) {
+    if (configManager.getConfig('notification', 'slack:isIncomingWebhookPrioritized')) {
+      if (configManager.getConfig('notification', 'slack:incomingWebhookUrl')) {
         debug('posting message with IncomingWebhook');
         return postWithIwh(messageObj);
       }
-      if (Config.hasSlackToken(config)) {
+      if (configManager.getConfig('notification', 'slack:token')) {
         debug('posting message with Web API');
         return postWithWebApi(messageObj);
       }
     }
     // else
     else {
-      if (Config.hasSlackToken(config)) {
+      if (configManager.getConfig('notification', 'slack:token')) {
         debug('posting message with Web API');
         return postWithWebApi(messageObj);
       }
-      if (Config.hasSlackIwhUrl(config)) {
+      if (configManager.getConfig('notification', 'slack:incomingWebhookUrl')) {
         debug('posting message with IncomingWebhook');
         return postWithIwh(messageObj);
       }

+ 2 - 52
src/server/util/swigFunctions.js

@@ -2,7 +2,6 @@ module.exports = function(crowi, app, req, locals) {
   const debug = require('debug')('growi:lib:swigFunctions');
   const stringWidth = require('string-width');
   const Page = crowi.model('Page');
-  const Config = crowi.model('Config');
   const User = crowi.model('User');
   const {
     configManager,
@@ -91,21 +90,12 @@ module.exports = function(crowi, app, req, locals) {
     return cdnResourcesService.getHighlightJsStyleTag(styleName);
   };
 
-  /**
-   * return true if local strategy has been setup successfully
-   *  used whether restarting the server needed
-   */
-  locals.isPassportLocalStrategySetup = function() {
-    return passportService != null && passportService.isLocalStrategySetup;
-  };
-
   /**
    * return true if enabled and strategy has been setup successfully
    */
   locals.isLdapSetup = function() {
     return (
-      configManager.getConfig('crowi', 'security:isEnabledPassport')
-      && configManager.getConfig('crowi', 'security:passport-ldap:isEnabled')
+      configManager.getConfig('crowi', 'security:passport-ldap:isEnabled')
       && passportService.isLdapStrategySetup
     );
   };
@@ -115,35 +105,15 @@ module.exports = function(crowi, app, req, locals) {
    */
   locals.isLdapSetupFailed = function() {
     return (
-      configManager.getConfig('crowi', 'security:isEnabledPassport')
-      && configManager.getConfig('crowi', 'security:passport-ldap:isEnabled')
+      configManager.getConfig('crowi', 'security:passport-ldap:isEnabled')
       && !passportService.isLdapStrategySetup
     );
   };
 
   locals.getSamlMissingMandatoryConfigKeys = function() {
-    // return an empty array if Passport is not enabled
-    // because crowi.passportService is null.
-    if (!configManager.getConfig('crowi', 'security:isEnabledPassport')) {
-      return [];
-    }
-
     return crowi.passportService.getSamlMissingMandatoryConfigKeys();
   };
 
-  locals.googleLoginEnabled = function() {
-    // return false if Passport is enabled
-    // because official crowi mechanism is not used.
-    if (configManager.getConfig('crowi', 'security:isEnabledPassport')) {
-      return false;
-    }
-
-    return (
-      configManager.getConfig('crowi', 'google:clientId')
-      && configManager.getConfig('crowi', 'google:clientSecret')
-    );
-  };
-
   locals.searchConfigured = function() {
     if (crowi.getSearcher()) {
       return true;
@@ -155,26 +125,6 @@ module.exports = function(crowi, app, req, locals) {
     return process.env.HACKMD_URI != null;
   };
 
-  locals.isEnabledLinebreaks = function() {
-    const config = crowi.getConfig();
-    return Config.isEnabledLinebreaks(config);
-  };
-
-  locals.isEnabledLinebreaksInComments = function() {
-    const config = crowi.getConfig();
-    return Config.isEnabledLinebreaksInComments(config);
-  };
-
-  locals.pageBreakSeparator = function() {
-    const config = crowi.getConfig();
-    return Config.pageBreakSeparator(config);
-  };
-
-  locals.pageBreakCustomSeparator = function() {
-    const config = crowi.getConfig();
-    return Config.pageBreakCustomSeparator(config);
-  };
-
   locals.customCss = function() {
     const customizeService = crowi.customizeService;
     return customizeService.getCustomCss();

+ 3 - 140
src/server/views/admin/security.html

@@ -156,139 +156,16 @@
         </div>
        </div>
 
-      <form action="/_api/admin/security/mechanism" method="post" class="form-horizontal mt-5" id="mechanismSetting" role="form">
-        <fieldset>
-          <legend class="alert-anchor">{{ t('Selecting authentication mechanism') }}</legend>
-          <p class="alert alert-info"><b>{{ t("security_setting.note") }}: </b>{{ t("security_setting.require_server_restart_change_auth") }}</p>
-          <div class="form-group">
-            <div class="col-xs-6">
-              <h4>
-                <div class="radio radio-primary">
-                  <input type="radio" id="radioPassportAuthMech" name="settingForm[security:isEnabledPassport]" value="true"
-                      {% if true === settingForm['security:isEnabledPassport'] %}checked="checked"{% endif %}>
-                  <label for="radioPassportAuthMech">
-                    <a href="http://passportjs.org/" target="_blank">
-                      <img src="/images/admin/security/passport-logo.svg" class="passport-logo"> Passport
-                    </a> {{ t("security_setting.auth_mechanism") }} <small class="text-success">({{ t("security_setting.recommended") }})</small>
-                  </label>
-                </div>
-              </h4>
-              <ul>
-                <li>{{ t("security_setting.username_email_password") }}</li>
-                <li>{{ t("security_setting.ldap_auth") }}</li>
-                <li>{{ t("security_setting.saml_auth") }}</li>
-                <li>{{ t("security_setting.google_auth2") }}</li>
-                <li>{{ t("security_setting.github_auth2") }}</li>
-                <li>{{ t("security_setting.twitter_auth2") }}</li>
-                <li class="text-muted">(TBD) <del>{{ t("security_setting.facebook_auth2") }}</del></li>
-              </ul>
-            </div>
-            <div class="col-xs-6">
-              <h4>
-                <div class="radio radio-primary">
-                  <input type="radio" id="radioCrowiAuthMech" name="settingForm[security:isEnabledPassport]" value="false"
-                      {% if !settingForm['security:isEnabledPassport'] %}checked="checked"{% endif %}>
-                  <label for="radioCrowiAuthMech">
-                    Crowi Classic {{ t("security_setting.auth_mechanism") }}
-                  </label>
-                </div>
-              </h4>
-              <ul>
-                <li>{{ t("security_setting.username_email_password") }}</li>
-                <li class="text-muted">
-                  {{ t("security_setting.google_auth2") }}
-                  <ul><li>{{ t("security_setting.google_auth2_by_crowi_desc") }}</li></ul>
-                </li>
-              </ul>
-            </div>
-          </div>
-
-          <div class="form-group">
-            <div class="col-xs-offset-5 col-xs-6">
-              <input type="hidden" name="_csrf" value="{{ csrf() }}">
-              <button type="submit" class="btn btn-primary">{{ t('Update') }}</button>
-            </div>
-          </div>
-        </fieldset>
-      </form>
-
 
       <div class="auth-mechanism-configurations m-t-10">
 
         <legend>{{ t('security_setting.Authentication mechanism settings') }}</legend>
 
-        {% set isOfficialConfigurationVisible = !getConfig('crowi', 'security:isEnabledPassport') %}
-        <div class="official-crowi-auth-settings" {% if !isOfficialConfigurationVisible %}style="display: none;"{% endif %}>
-          {% set isRestartingServerNeeded = isPassportLocalStrategySetup() %}
-          <p class="alert alert-warning"
-              {% if !isRestartingServerNeeded %}style="display: none;"{% endif %}>
-            <b>
-              <i class="icon-exclamation" aria-hidden="true"></i>
-              {{ t("security_setting.require_server_restart") }}
-            </b>
-            {{ t("security_setting.server_on_passport_auth") }}
-          </p>
-
-          <form action="/_api/admin/security/google" method="post" class="form-horizontal" id="googleSetting" role="form"
-              {% if isRestartingServerNeeded %}style="opacity: 0.4;"{% endif %}>
-
-            <fieldset>
-              <h4>{{ t("security_setting.google_setting") }}</h4>
-              <p class="well alert-anchor">
-                {{ t("security_setting.connect_api_manager") }}
-              </p>
-
-              <ol class="help-block">
-                <li>{{ t("security_setting.access_api_manager", "https://console.cloud.google.com/apis/credentials", "API Manager") }}</li>
-                <li>{{ t("security_setting.create_project") }}</li>
-                <li>{{ t("security_setting.create_auth_to_oauth") }}</li>
-                <ol>
-                  <li>{{ t("security_setting.select_webapp") }}</li>
-                  <li>{{ t("security_setting.change_redirect_url") }}</li>
-                </ol>
-              </ol>
-
-              <div class="form-group">
-                <label for="settingForm[google:clientId]" class="col-xs-3 control-label">{{ t("security_setting.clientID") }}</label>
-                <div class="col-xs-6">
-                  <input class="form-control" type="text" name="settingForm[google:clientId]" value="{{ settingForm['google:clientId'] }}">
-                </div>
-              </div>
-
-              <div class="form-group">
-                <label for="settingForm[google:clientSecret]" class="col-xs-3 control-label">{{ t("security_setting.client_secret") }}</label>
-                <div class="col-xs-6">
-                  <input class="form-control" type="text" name="settingForm[google:clientSecret]" value="{{ settingForm['google:clientSecret'] }}">
-                </div>
-              </div>
-
-              <div class="form-group">
-                <div class="col-xs-offset-3 col-xs-6">
-                  <input type="hidden" name="_csrf" value="{{ csrf() }}">
-                  <button type="submit" class="btn btn-primary">{{ t('Update') }}</button>
-                </div>
-              </div>
-
-            </fieldset>
-          </form>
-        </div>
-
         {#
          # passport settings nav
          #}
-        {% set isPassportConfigurationVisible = settingForm['security:isEnabledPassport'] %}
-        <div class="passport-settings" {% if !isPassportConfigurationVisible %}style="display: none;"{% endif %}>
-
-          {% set isRestartingServerNeeded = !isPassportLocalStrategySetup() %}
-          <p class="alert alert-warning"
-              {% if !isRestartingServerNeeded %}style="display: none;"{% endif %}>
-            <b>
-              <i class="icon-exclamation" aria-hidden="true"></i>
-              {{ t("security_setting.require_server_restart") }}
-            </b>
-            {{ t("security_setting.server_on_crowi_auth") }}
-          </p>
-          <ul class="nav nav-tabs" role="tablist" {% if isRestartingServerNeeded %}style="opacity: 0.4;"{% endif %}>
+        <div class="passport-settings">
+          <ul class="nav nav-tabs" role="tablist">
             <li class="active">
               <a href="#passport-ldap" data-toggle="tab" role="tab"><i class="fa fa-sitemap"></i> LDAP</a>
             </li>
@@ -312,7 +189,7 @@
             </li>
           </ul>
 
-          <div class="tab-content p-t-10" {% if isRestartingServerNeeded %}style="opacity: 0.4;"{% endif %}>
+          <div class="tab-content p-t-10">
             <div id="passport-ldap" class="tab-pane active" role="tabpanel" >
               {% include './widget/passport/ldap.html' with { settingForm: settingForm } %}
             </div>
@@ -397,20 +274,6 @@
         return false;
       });
     });
-
-    // switch display according to on / off of radio buttons
-    $('input[name="settingForm[security:isEnabledPassport]"]:radio').change(function() {
-      const isEnabledPassport = ($(this).val() === "true");
-
-      if (isEnabledPassport) {
-        $('.official-crowi-auth-settings').hide(400);
-        $('.passport-settings').show(400);
-      }
-      else {
-        $('.official-crowi-auth-settings').show(400);
-        $('.passport-settings').hide(400);
-      }
-    });
   </script>
 </div>
 {% endblock content_main %}

+ 1 - 2
src/server/views/admin/widget/passport/github.html

@@ -1,5 +1,4 @@
-<form action="/_api/admin/security/passport-github" method="post" class="form-horizontal passportStrategy" id="githubSetting" role="form"
-    {% if isRestartingServerNeeded %}style="opacity: 0.4;"{% endif %}>
+<form action="/_api/admin/security/passport-github" method="post" class="form-horizontal passportStrategy" id="githubSetting" role="form">
   <legend class="alert-anchor">{{ t("security_setting.OAuth.GitHub.name") }} {{ t("security_setting.configuration") }}</legend>
 
   {% set nameForIsGitHubEnabled = "settingForm[security:passport-github:isEnabled]" %}

+ 1 - 2
src/server/views/admin/widget/passport/google-oauth.html

@@ -1,5 +1,4 @@
-<form action="/_api/admin/security/passport-google" method="post" class="form-horizontal passportStrategy" id="googleSetting" role="form"
-    {% if isRestartingServerNeeded %}style="opacity: 0.4;"{% endif %}>
+<form action="/_api/admin/security/passport-google" method="post" class="form-horizontal passportStrategy" id="googleSetting" role="form">
   <legend class="alert-anchor">{{ t("security_setting.OAuth.Google.name") }} {{ t("security_setting.configuration") }}</legend>
 
   {% set nameForIsGoogleEnabled = "settingForm[security:passport-google:isEnabled]" %}

+ 1 - 2
src/server/views/admin/widget/passport/oidc.html

@@ -1,5 +1,4 @@
-<form action="/_api/admin/security/passport-oidc" method="post" class="form-horizontal passportStrategy" id="oidcSetting" role="form"
-    {% if isRestartingServerNeeded %}style="opacity: 0.4;"{% endif %}>
+<form action="/_api/admin/security/passport-oidc" method="post" class="form-horizontal passportStrategy" id="oidcSetting" role="form">
   <legend class="alert-anchor">{{ t("security_setting.OAuth.OIDC.name") }} {{ t("security_setting.configuration") }}</legend>
 
   {% set nameForIsOIDCEnabled = "settingForm[security:passport-oidc:isEnabled]" %}

+ 1 - 2
src/server/views/admin/widget/passport/saml.html

@@ -1,5 +1,4 @@
-<form action="/_api/admin/security/passport-saml" method="post" class="form-horizontal passportStrategy" id="samlSetting" role="form"
-    {% if isRestartingServerNeeded %}style="opacity: 0.4;"{% endif %}>
+<form action="/_api/admin/security/passport-saml" method="post" class="form-horizontal passportStrategy" id="samlSetting" role="form">
   <legend class="alert-anchor">{{ t("security_setting.SAML.name") }} {{ t("security_setting.configuration") }}</legend>
 
   {% set nameForIsSamlEnabled = "settingForm[security:passport-saml:isEnabled]" %}

+ 1 - 2
src/server/views/admin/widget/passport/twitter.html

@@ -1,5 +1,4 @@
-<form action="/_api/admin/security/passport-twitter" method="post" class="form-horizontal passportStrategy" id="twitterSetting" role="form"
-    {% if isRestartingServerNeeded %}style="opacity: 0.4;"{% endif %}>
+<form action="/_api/admin/security/passport-twitter" method="post" class="form-horizontal passportStrategy" id="twitterSetting" role="form">
   <legend class="alert-anchor">{{ t("security_setting.OAuth.Twitter.name") }} {{ t("security_setting.configuration") }}</legend>
 
   {% set nameForIsTwitterEnabled = "settingForm[security:passport-twitter:isEnabled]" %}

+ 3 - 3
src/server/views/installer.html

@@ -10,7 +10,7 @@
 
   <meta name="viewport" content="width=device-width,initial-scale=1">
 
-  <meta name="apple-mobile-web-app-title" content="{{ appService.appTitle() }}">
+  <meta name="apple-mobile-web-app-title" content="{{ appService.getAppTitle() }}">
 
   {% include './widget/headers/favicon.html' %}
   {% include './widget/headers/ie11-polyfills.html' %}
@@ -69,8 +69,8 @@
 
         <div id='installer-form'
           data-user-name="{{ req.body.registerForm.username }}"
-          data-name="{{ googleName|default(req.body.registerForm.name) }}"
-          data-email="{{ googleEmail|default(req.body.registerForm.email) }}"
+          data-name="{{ req.body.registerForm.name }}"
+          data-email="{{ req.body.registerForm.email }}"
           data-csrf="{{ csrf() }}">
         </div>
 

+ 1 - 1
src/server/views/invited.html

@@ -73,7 +73,7 @@
 
         <div class="input-group">
           <span class="input-group-addon"><i class="icon-tag"></i></span>
-          <input type="text" class="form-control" placeholder="{{ t('Name') }}" name="invitedForm[name]" value="{{ googleName|default(req.body.invitedForm.name) }}" required>
+          <input type="text" class="form-control" placeholder="{{ t('Name') }}" name="invitedForm[name]" value="{{ req.body.invitedForm.name }}" required>
         </div>
 
 

+ 2 - 2
src/server/views/layout/layout.html

@@ -10,7 +10,7 @@
 
   <meta name="viewport" content="width=device-width,initial-scale=1">
 
-  <meta name="apple-mobile-web-app-title" content="{{ appService.appTitle() }}">
+  <meta name="apple-mobile-web-app-title" content="{{ appService.getAppTitle() }}">
 
   {{ customHeader() }}
 
@@ -86,7 +86,7 @@
             <div class="logo-mark">{% include '../widget/logo.html' %}</div>
           </b>
           <span class="hidden-xs" style="color: black">
-            {% set appTitle = appService.appTitle() %}
+            {% set appTitle = appService.getAppTitle() %}
             {% set appTitleFontSize = getAppTitleFontSize(appTitle) %}
             <span class="logo-text">
               <svg xmlns="http://www.w3.org/2000/svg">

+ 16 - 49
src/server/views/login.html

@@ -27,7 +27,7 @@
   <div class="row">
     <div class="login-header col-sm-offset-4 col-sm-4">
       <div class="logo">{% include 'widget/logo.html' %}</div>
-      <h1>{{ appService.appTitle() }}</h1>
+      <h1>{{ appService.getAppTitle() }}</h1>
 
       <div class="login-form-errors">
         {% if isLdapSetupFailed() %}
@@ -100,7 +100,7 @@
       </div>
     </div>
 
-    <div class="login-dialog p-b-10 col-sm-offset-4 col-sm-4 flipper {% if req.query.register or req.body.registerForm or isRegistering or googleId %}to-flip{% endif %}" id="login-dialog">
+    <div class="login-dialog p-b-10 col-sm-offset-4 col-sm-4 flipper {% if req.query.register or req.body.registerForm or isRegistering %}to-flip{% endif %}" id="login-dialog">
 
       <div class="front">
         <form role="form" action="/login" method="post">
@@ -130,35 +130,19 @@
           </div>
         </form>
 
-        {% if googleLoginEnabled() %}
-        <hr>
-
-        <div class="input-group m-t-15 m-b-10 mx-auto">
-          <form role="form" action="/login/google" method="get">
-            <input type="hidden" name="_csrf" value="{{ csrf() }}">
-            <button type="submit" class="fcbtn btn btn-danger btn-1b btn-login-oauth" id="google">
-              <span class="btn-label"><i class="icon-social-google"></i></span>
-              {{ t('Sign in') }}
-            </button>
-            <div class="small text-right">by Google Account</div>
-          </form>
-        </div>
-        {% endif %}
         {% if (
-          getConfig('crowi', 'security:isEnabledPassport') && (
-            getConfig('crowi', 'security:passport-google:isEnabled') ||
-            getConfig('crowi', 'security:passport-github:isEnabled') ||
-            getConfig('crowi', 'security:passport-facebook:isEnabled') ||
-            getConfig('crowi', 'security:passport-twitter:isEnabled')||
-            getConfig('crowi', 'security:passport-oidc:isEnabled') ||
-            getConfig('crowi', 'security:passport-saml:isEnabled')
-          )
+          getConfig('crowi', 'security:passport-google:isEnabled') ||
+          getConfig('crowi', 'security:passport-github:isEnabled') ||
+          getConfig('crowi', 'security:passport-facebook:isEnabled') ||
+          getConfig('crowi', 'security:passport-twitter:isEnabled')||
+          getConfig('crowi', 'security:passport-oidc:isEnabled') ||
+          getConfig('crowi', 'security:passport-saml:isEnabled')
         ) %}
         <hr class="mb-1">
         <div class="collapse collapse-oauth collapse-anchor">
           <div class="spacer"></div>
           <div class="d-flex flex-row justify-content-between flex-wrap">
-            {% if getConfig('crowi', 'security:isEnabledPassport') && getConfig('crowi', 'security:passport-google:isEnabled') %}
+            {% if getConfig('crowi', 'security:passport-google:isEnabled') %}
             <form role="form" action="/passport/google" class="d-inline-flex flex-column">
               <button type="submit" class="fcbtn btn btn-1b btn-login-oauth d-flex" id="google">
                 <span class="btn-label"><i class="fa fa-google"></i></span>
@@ -167,7 +151,7 @@
               <div class="small text-right">by Google Account</div>
             </form>
             {% endif %}
-            {% if getConfig('crowi', 'security:isEnabledPassport') && getConfig('crowi', 'security:passport-github:isEnabled') %}
+            {% if getConfig('crowi', 'security:passport-github:isEnabled') %}
             <form role="form" action="/passport/github" class="d-inline-flex flex-column">
               <input type="hidden" name="_csrf" value="{{ csrf() }}">
               <button type="submit" class="fcbtn btn btn-1b btn-login-oauth d-inline-flex" id="github">
@@ -177,7 +161,7 @@
               <div class="small text-right">by GitHub Account</div>
             </form>
             {% endif %}
-            {% if getConfig('crowi', 'security:isEnabledPassport') && getConfig('crowi', 'security:passport-facebook:isEnabled') %}
+            {% if getConfig('crowi', 'security:passport-facebook:isEnabled') %}
             <form role="form" action="/passport/facebook" class="d-inline-flex flex-column">
               <input type="hidden" name="_csrf" value="{{ csrf() }}">
               <button type="submit" class="fcbtn btn btn-1b btn-login-oauth d-inline-flex" id="facebook">
@@ -187,7 +171,7 @@
               <div class="small text-right">by Facebook Account</div>
             </form>
             {% endif %}
-            {% if getConfig('crowi', 'security:isEnabledPassport') && getConfig('crowi', 'security:passport-twitter:isEnabled') %}
+            {% if getConfig('crowi', 'security:passport-twitter:isEnabled') %}
             <form role="form" action="/passport/twitter" class="d-inline-flex flex-column">
               <input type="hidden" name="_csrf" value="{{ csrf() }}">
               <button type="submit" class="fcbtn btn btn-1b btn-login-oauth d-inline-flex" id="twitter">
@@ -197,7 +181,7 @@
               <div class="small text-right">by Twitter Account</div>
             </form>
             {% endif %}
-            {% if getConfig('crowi', 'security:isEnabledPassport') && getConfig('crowi', 'security:passport-oidc:isEnabled') %}
+            {% if getConfig('crowi', 'security:passport-oidc:isEnabled') %}
             <form role="form" action="/passport/oidc" class="d-inline-flex flex-column">
               <input type="hidden" name="_csrf" value="{{ csrf() }}">
               <button type="submit" class="fcbtn btn btn-1b btn-login-oauth d-inline-flex" id="oidc">
@@ -207,7 +191,7 @@
               <div class="small text-right">{{ getConfig('crowi', 'security:passport-oidc:providerName') || "OpenID Connect" }}</div>
             </form>
             {% endif %}
-            {% if getConfig('crowi', 'security:isEnabledPassport') && getConfig('crowi', 'security:passport-saml:isEnabled') %}
+            {% if getConfig('crowi', 'security:passport-saml:isEnabled') %}
             <form role="form" action="/passport/saml" class="d-inline-flex flex-column">
               <input type="hidden" name="_csrf" value="{{ csrf() }}">
               <button type="submit" class="fcbtn btn btn-1b btn-login-oauth d-inline-flex" id="saml">
@@ -265,21 +249,7 @@
         </p>
         {% endif %}
 
-        {% if googleId %}
-        <div class="google-info alert alert-info">
-          {% if googleImage %}
-          <p class="text-center">
-            <img src="{{ googleImage }}" class="img-circle img-circle-lg">
-          </p>
-          {% endif %}
-          <code>{{ googleEmail }}</code> {{ t('page_register with this Google Account') }}<br>
-          {{ t('page_register.notice.google_account_continue') }}
-        </div>
-        {% endif %}
-
         <form role="form" method="post" action="/register" id="register-form">
-          <input type="hidden" class="form-control" name="registerForm[googleId]" value="{{ googleId|default(req.body.registerForm.googleId) }}">
-
           <div class="input-group" id="input-group-username">
             <span class="input-group-addon"><i class="icon-user"></i></span>
             <input type="text" class="form-control" placeholder="{{ t('User ID') }}" name="registerForm[username]" value="{{ req.body.registerForm.username }}" required>
@@ -290,12 +260,12 @@
 
           <div class="input-group">
             <span class="input-group-addon"><i class="icon-tag"></i></span>
-            <input type="text" class="form-control" placeholder="{{ t('Name') }}" name="registerForm[name]" value="{{ googleName|default(req.body.registerForm.name) }}" required>
+            <input type="text" class="form-control" placeholder="{{ t('Name') }}" name="registerForm[name]" value="{{ req.body.registerForm.name }}" required>
           </div>
 
           <div class="input-group">
             <span class="input-group-addon"><i class="icon-envelope"></i></span>
-            <input type="email" class="form-control" placeholder="{{ t('Email') }}" name="registerForm[email]" value="{{ googleEmail|default(req.body.registerForm.email) }}" required>
+            <input type="email" class="form-control" placeholder="{{ t('Email') }}" name="registerForm[email]" value="{{ req.body.registerForm.email }}" required>
           </div>
           {% if config.crowi['security:registrationWhiteList'] && config.crowi['security:registrationWhiteList'].length %}
           <p class="help-block">
@@ -313,9 +283,6 @@
             <input type="password" class="form-control" placeholder="{{ t('Password') }}" name="registerForm[password]" required>
           </div>
 
-          {% if googleImage %}
-            <input type="hidden" name="registerForm[googleImage]" value="{{ googleImage }}">
-          {% endif  %}
           <input type="hidden" name="_csrf" value="{{ csrf() }}">
 
           <div class="input-group m-t-30 m-b-20 d-flex justify-content-center">

+ 0 - 2
src/server/views/me/api_token.html

@@ -17,9 +17,7 @@
 
   <ul class="nav nav-tabs">
     <li><a href="/me"><i class="icon-user"></i> {{ t('User Information') }}</a></li>
-    {% if getConfig('crowi', 'security:isEnabledPassport') %}
     <li><a href="/me/external-accounts"><i class="icon-share-alt"></i> {{ t('External Accounts') }}</a></li>
-    {% endif %}
     <li><a href="/me/password"><i class="icon-lock"></i> {{ t('Password Settings') }}</a></li>
     <li class="active"><a href="/me/apiToken"><i class="icon-paper-plane"></i> {{ t('API Settings') }}</a></li>
   </ul>

+ 0 - 51
src/server/views/me/index.html

@@ -15,9 +15,7 @@
 
   <ul class="nav nav-tabs">
     <li class="active"><a href="/me"><i class="icon-user"></i> {{ t('User Information') }}</a></li>
-    {% if getConfig('crowi', 'security:isEnabledPassport') %}
     <li><a href="/me/external-accounts"><i class="icon-share-alt"></i> {{ t('External Accounts') }}</a></li>
-    {% endif %}
     <li><a href="/me/password"><i class="icon-lock"></i> {{ t('Password Settings') }}</a></li>
     <li><a href="/me/apiToken"><i class="icon-paper-plane"></i> {{ t('API Settings') }}</a></li>
   </ul>
@@ -263,55 +261,6 @@
     });
   </script>
 
-  {% if googleLoginEnabled() %}
-  <div class="form-box">
-    <legend>{{ t('Google Setting') }}</legend>
-    <form action="/me/auth/google" method="post" class="form-horizontal col-sm-12" role="form">
-      <fieldset>
-        {% set wmessage = req.flash('warningMessage.auth.google') %}
-        {% if wmessage.length %}
-        <div class="alert alert-danger">
-          {{ wmessage }}
-        </div>
-        {% endif %}
-
-        <div class="form-group">
-        {% if user.googleId %}
-        <div>
-          <p>
-            <input type="submit" name="disconnectGoogle" class="btn btn-default" value="{{ t('Disconnect') }}">
-          </p>
-          <p class="help-block">
-            {{ t('page_me.form_help.google_disconnect1') }}<br>
-            {{ t('page_me.form_help.google_disconnect2') }}
-          </p>
-        </div>
-        {% else %}
-        <div>
-          <div class="text-center">
-            <input type="submit" name="connectGoogle" class="btn btn-google" value="Googleコネクト">
-          </div>
-          <p class="help-block">
-            {{ t('page_me.form_help.google_connect1') }}<br>
-          </p>
-          {% if config.crowi['security:registrationWhiteList'] && config.crowi['security:registrationWhiteList'].length %}
-          <p class="help-block">
-            {{ t('page_register.form_help.email') }}<br>
-            {{ t('page_me.form_help.google_connect2') }}
-          </p>
-          <ul>
-            {% for em in config.crowi['security:registrationWhiteList'] %}
-            <li><code>{{ em }}</code></li>
-            {% endfor %}
-          </ul>
-          {% endif %}
-        </div>
-        {% endif %}
-      </fieldset>
-    </form>
-  </div>
-  {% endif %}
-
   </div> {# end of .tab-contents #}
 
   {#

+ 0 - 2
src/server/views/me/password.html

@@ -15,9 +15,7 @@
 
   <ul class="nav nav-tabs">
     <li><a href="/me"><i class="icon-user"></i> {{ t('User Information') }}</a></li>
-    {% if getConfig('crowi', 'security:isEnabledPassport') %}
     <li><a href="/me/external-accounts"><i class="icon-share-alt"></i> {{ t('External Accounts') }}</a></li>
-    {% endif %}
     <li class="active"><a href="/me/password"><i class="icon-lock"></i> {{ t('Password Settings') }}</a></li>
     <li><a href="/me/apiToken"><i class="icon-paper-plane"></i> {{ t('API Settings') }}</a></li>
   </ul>

+ 2 - 2
src/server/views/page_presentation.html

@@ -41,8 +41,8 @@
   <body>
     <div class="reveal">
       <div class="slides">
-        {% set pageBreakSeparator = pageBreakSeparator()|default(1) %}
-        {% set pageBreakCustomSeparator = pageBreakCustomSeparator()|default('') %}
+        {% set pageBreakSeparator = getConfig('markdown', 'markdown:presentation:pageBreakSeparator') | default(1) %}
+        {% set pageBreakCustomSeparator = getConfig('markdown', 'markdown:presentation:pageBreakCustomSeparator') | default('') %}
 
         {% if 3 === pageBreakSeparator %}
           {% set dataSeparator = pageBreakCustomSeparator %}

+ 0 - 7
src/server/views/widget/alert_breaking_changes.html

@@ -1,12 +1,5 @@
 {# Added in v3.4.6 }
 
-{% if getConfig('crowi', 'security:isEnabledPassport') !== true %}
-<div class="myadmin-alert alert alert-warning mb-0">
-  <i class="icon-exclamation"></i>
-  {{ t("breaking_changes.v346_passport_is_not_enabled", '<a href="/admin/security">' + t('Security settings') + '<i class="icon-login"></i></a>') }}
-</div>
-{% endif %}
-
 {% if getConfig('crowi', 'security:basicName') || getConfig('crowi', 'security:basicSecret') %}
 <div class="myadmin-alert alert alert-warning mb-0">
   <i class="icon-exclamation"></i>

Разница между файлами не показана из-за своего большого размера
+ 190 - 346
yarn.lock


Некоторые файлы не были показаны из-за большого количества измененных файлов