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

Merge remote-tracking branch 'origin/master' into support/use-turborepo

Yuki Takei 3 лет назад
Родитель
Сommit
81201eb0d6
66 измененных файлов с 282 добавлено и 212 удалено
  1. 28 1
      CHANGELOG.md
  2. 1 1
      apps/app/docker/README.md
  3. 11 11
      apps/app/package.json
  4. 1 1
      apps/app/public/static/locales/en_US/translation.json
  5. 1 1
      apps/app/public/static/locales/ja_JP/translation.json
  6. 1 1
      apps/app/public/static/locales/zh_CN/translation.json
  7. 6 6
      apps/app/resource/locales/en_US/admin/userInvitation.txt
  8. 5 5
      apps/app/resource/locales/en_US/admin/userResetPassword.txt
  9. 8 8
      apps/app/resource/locales/en_US/admin/userWaitingActivation.txt
  10. 3 3
      apps/app/resource/locales/en_US/notifications/comment.txt
  11. 4 4
      apps/app/resource/locales/en_US/notifications/notActiveUser.txt
  12. 2 2
      apps/app/resource/locales/en_US/notifications/pageCreate.txt
  13. 2 2
      apps/app/resource/locales/en_US/notifications/pageDelete.txt
  14. 2 2
      apps/app/resource/locales/en_US/notifications/pageEdit.txt
  15. 2 2
      apps/app/resource/locales/en_US/notifications/pageLike.txt
  16. 2 2
      apps/app/resource/locales/en_US/notifications/pageMove.txt
  17. 4 4
      apps/app/resource/locales/en_US/notifications/passwordReset.txt
  18. 1 1
      apps/app/resource/locales/en_US/notifications/passwordResetSuccessful.txt
  19. 4 4
      apps/app/resource/locales/en_US/notifications/userActivation.txt
  20. 6 6
      apps/app/resource/locales/ja_JP/admin/userInvitation.txt
  21. 6 5
      apps/app/resource/locales/ja_JP/admin/userResetPassword.txt
  22. 8 8
      apps/app/resource/locales/ja_JP/admin/userWaitingActivation.txt
  23. 4 4
      apps/app/resource/locales/ja_JP/notifications/notActiveUser.txt
  24. 4 4
      apps/app/resource/locales/ja_JP/notifications/passwordReset.txt
  25. 1 1
      apps/app/resource/locales/ja_JP/notifications/passwordResetSuccessful.txt
  26. 4 4
      apps/app/resource/locales/ja_JP/notifications/userActivation.txt
  27. 6 6
      apps/app/resource/locales/zh_CN/admin/userInvitation.txt
  28. 5 5
      apps/app/resource/locales/zh_CN/admin/userResetPassword.txt
  29. 8 8
      apps/app/resource/locales/zh_CN/admin/userWaitingActivation.txt
  30. 3 3
      apps/app/resource/locales/zh_CN/notifications/comment.txt
  31. 4 4
      apps/app/resource/locales/zh_CN/notifications/notActiveUser.txt
  32. 2 2
      apps/app/resource/locales/zh_CN/notifications/pageCreate.txt
  33. 2 2
      apps/app/resource/locales/zh_CN/notifications/pageDelete.txt
  34. 2 2
      apps/app/resource/locales/zh_CN/notifications/pageEdit.txt
  35. 2 2
      apps/app/resource/locales/zh_CN/notifications/pageLike.txt
  36. 2 2
      apps/app/resource/locales/zh_CN/notifications/pageMove.txt
  37. 3 3
      apps/app/resource/locales/zh_CN/notifications/passwordReset.txt
  38. 1 1
      apps/app/resource/locales/zh_CN/notifications/passwordResetSuccessful.txt
  39. 4 4
      apps/app/resource/locales/zh_CN/notifications/userActivation.txt
  40. 8 2
      apps/app/src/client/services/side-effects/page-updated.ts
  41. 1 1
      apps/app/src/components/Admin/Users/PasswordResetModal.jsx
  42. 1 6
      apps/app/src/components/LoginForm.tsx
  43. 6 2
      apps/app/src/components/PageEditor/ConflictDiffModal.tsx
  44. 20 4
      apps/app/src/components/UnsavedAlertDialog.tsx
  45. 3 1
      apps/app/src/interfaces/user.ts
  46. 13 4
      apps/app/src/pages/[[...path]].page.tsx
  47. 4 9
      apps/app/src/server/middlewares/login-required.js
  48. 1 1
      apps/app/src/server/routes/apiv3/index.js
  49. 0 7
      apps/app/src/server/routes/apiv3/users.js
  50. 6 6
      apps/app/src/server/routes/index.js
  51. 17 7
      apps/app/src/server/routes/login-passport.js
  52. 17 0
      apps/app/src/server/util/createRedirectToForUnauthenticated.ts
  53. 1 6
      apps/app/src/stores/editor.tsx
  54. 1 1
      apps/app/test/integration/middlewares/login-required.test.js
  55. 2 2
      apps/slackbot-proxy/package.json
  56. 1 1
      package.json
  57. 1 1
      packages/codemirror-textlint/package.json
  58. 1 1
      packages/core/package.json
  59. 1 1
      packages/hackmd/package.json
  60. 2 2
      packages/presentation/package.json
  61. 1 1
      packages/preset-themes/package.json
  62. 1 1
      packages/remark-drawio/package.json
  63. 1 1
      packages/remark-growi-directive/package.json
  64. 4 4
      packages/remark-lsx/package.json
  65. 1 1
      packages/slack/package.json
  66. 2 2
      packages/ui/package.json

+ 28 - 1
CHANGELOG.md

@@ -1,9 +1,36 @@
 # Changelog
 # Changelog
 
 
-## [Unreleased](https://github.com/weseek/growi/compare/v6.0.6...HEAD)
+## [Unreleased](https://github.com/weseek/growi/compare/v6.0.7...HEAD)
 
 
 *Please do not manually update this file. We've automated the process.*
 *Please do not manually update this file. We've automated the process.*
 
 
+## [v6.0.7](https://github.com/weseek/growi/compare/v6.0.6...v6.0.7) - 2023-02-21
+
+### 💎 Features
+
+- feat: Manage guest ui setting with session (#7401) @yukendev
+- feat: Manage guest sidebar mode with session (#7393) @yukendev
+
+### 🚀 Improvement
+
+- imprv: UnsavedAlertDialog and page transition when next routing (#7400) @miya
+- imprv: PasswordResetModal styles and ejs format (#7404) @jam411
+- imprv: Initialize UserUISettings (#7397) @yuki-takei
+- imprv: Presentation behavior (#7399) @yuki-takei
+
+### 🐛 Bug Fixes
+
+- fix: PageStatusAlert is displayed on unnecessary pages (#7413) @miya
+- fix: PageStatusAlert does not disappear after loading latest revision (#7412) @miya
+- fix: Unable to transition requested page after login (#7402) @miya
+- fix: Page body is blank when opening editor after duplicating page (#7394) @miya
+- fix: Error when pressing the conflict resolution button on PageStatusAlert (#7395) @miya
+- fix: mono-blue subnavigation color (#7398) @ayaka0417
+- imprv: Add send email to user feat to `/reset-password` endpoint v6 (#7356) @jam411
+- fix: Behavior when color schema is forced by GROWI themes (#7391) @yuki-takei
+- fix: Sidebar mode on editor doesn't work in HackMD tab (#7396) @yuki-takei
+- fix: Can't controll slack notification button in comment editor (#7389) @yukendev
+
 ## [v6.0.6](https://github.com/weseek/growi/compare/v6.0.5...v6.0.6) - 2023-02-14
 ## [v6.0.6](https://github.com/weseek/growi/compare/v6.0.5...v6.0.6) - 2023-02-14
 
 
 ### 💎 Features
 ### 💎 Features

+ 1 - 1
apps/app/docker/README.md

@@ -10,7 +10,7 @@ GROWI Official docker image
 Supported tags and respective Dockerfile links
 Supported tags and respective Dockerfile links
 ------------------------------------------------
 ------------------------------------------------
 
 
-* [`6.0.6`, `6.0`, `6`, `latest` (Dockerfile)](https://github.com/weseek/growi/blob/v6.0.6/packages/app/docker/Dockerfile)
+* [`6.0.7`, `6.0`, `6`, `latest` (Dockerfile)](https://github.com/weseek/growi/blob/v6.0.7/packages/app/docker/Dockerfile)
 * [`5.1.7`, `5.1`, `5`](https://github.com/weseek/growi/blob/v5.1.7/packages/app/docker/Dockerfile)
 * [`5.1.7`, `5.1`, `5`](https://github.com/weseek/growi/blob/v5.1.7/packages/app/docker/Dockerfile)
 * [`5.1.7-nocdn`, `5.1-nocdn`, `5-nocdn`](https://github.com/weseek/growi/blob/v5.1.7/packages/app/docker/Dockerfile)
 * [`5.1.7-nocdn`, `5.1-nocdn`, `5-nocdn`](https://github.com/weseek/growi/blob/v5.1.7/packages/app/docker/Dockerfile)
 * [`4.5.23`, `4.5`, `4`, `latest` (Dockerfile)](https://github.com/weseek/growi/blob/v4.5.23/packages/app/docker/Dockerfile)
 * [`4.5.23`, `4.5`, `4`, `latest` (Dockerfile)](https://github.com/weseek/growi/blob/v4.5.23/packages/app/docker/Dockerfile)

+ 11 - 11
apps/app/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@growi/app",
   "name": "@growi/app",
-  "version": "6.0.7-RC.0",
+  "version": "6.0.8-RC.0",
   "license": "MIT",
   "license": "MIT",
   "scripts": {
   "scripts": {
     "//// for production": "",
     "//// for production": "",
@@ -60,14 +60,14 @@
     "@elastic/elasticsearch7": "npm:@elastic/elasticsearch@^7.17.0",
     "@elastic/elasticsearch7": "npm:@elastic/elasticsearch@^7.17.0",
     "@godaddy/terminus": "^4.9.0",
     "@godaddy/terminus": "^4.9.0",
     "@google-cloud/storage": "^5.8.5",
     "@google-cloud/storage": "^5.8.5",
-    "@growi/codemirror-textlint": "^6.0.7-RC.0",
-    "@growi/core": "^6.0.7-RC.0",
-    "@growi/hackmd": "^6.0.7-RC.0",
-    "@growi/preset-themes": "^6.0.7-RC.0",
-    "@growi/remark-drawio": "^6.0.7-RC.0",
-    "@growi/remark-growi-directive": "^6.0.7-RC.0",
-    "@growi/remark-lsx": "^6.0.7-RC.0",
-    "@growi/slack": "^6.0.7-RC.0",
+    "@growi/codemirror-textlint": "^6.0.8-RC.0",
+    "@growi/core": "^6.0.8-RC.0",
+    "@growi/hackmd": "^6.0.8-RC.0",
+    "@growi/preset-themes": "^6.0.8-RC.0",
+    "@growi/remark-drawio": "^6.0.8-RC.0",
+    "@growi/remark-growi-directive": "^6.0.8-RC.0",
+    "@growi/remark-lsx": "^6.0.8-RC.0",
+    "@growi/slack": "^6.0.8-RC.0",
     "@promster/express": "^7.0.6",
     "@promster/express": "^7.0.6",
     "@promster/server": "^7.0.8",
     "@promster/server": "^7.0.8",
     "@slack/web-api": "^6.2.4",
     "@slack/web-api": "^6.2.4",
@@ -196,8 +196,8 @@
     "handsontable": "v7.0.0 or above is no loger MIT lisence."
     "handsontable": "v7.0.0 or above is no loger MIT lisence."
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@growi/presentation": "^6.0.7-RC.0",
-    "@growi/ui": "^6.0.7-RC.0",
+    "@growi/presentation": "^6.0.8-RC.0",
+    "@growi/ui": "^6.0.8-RC.0",
     "@handsontable/react": "=2.1.0",
     "@handsontable/react": "=2.1.0",
     "@icon/themify-icons": "1.0.1-alpha.3",
     "@icon/themify-icons": "1.0.1-alpha.3",
     "@next/bundle-analyzer": "^12.2.3",
     "@next/bundle-analyzer": "^12.2.3",

+ 1 - 1
apps/app/public/static/locales/en_US/translation.json

@@ -328,7 +328,7 @@
     "notice": {
     "notice": {
       "conflict": "Couldn't save the changes you made because someone else was editing this page. Please re-edit the affected section after reloading the page."
       "conflict": "Couldn't save the changes you made because someone else was editing this page. Please re-edit the affected section after reloading the page."
     },
     },
-    "changes_not_saved": "Changes you made may not be saved."
+    "changes_not_saved": "Changes you made may not be saved. Are you sure you want to move?"
   },
   },
   "page_comment": {
   "page_comment": {
     "display_the_page_when_posting_this_comment": "Display the page when posting this comment",
     "display_the_page_when_posting_this_comment": "Display the page when posting this comment",

+ 1 - 1
apps/app/public/static/locales/ja_JP/translation.json

@@ -328,7 +328,7 @@
     "notice": {
     "notice": {
       "conflict": "すでに他の人がこのページを編集していたため保存できませんでした。ページを再読み込み後、自分の編集箇所のみ再度編集してください。"
       "conflict": "すでに他の人がこのページを編集していたため保存できませんでした。ページを再読み込み後、自分の編集箇所のみ再度編集してください。"
     },
     },
-    "changes_not_saved": "変更が保存されていない可能性があります。"
+    "changes_not_saved": "変更が保存されていない可能性があります。本当に移動しますか?"
   },
   },
   "page_comment": {
   "page_comment": {
     "display_the_page_when_posting_this_comment": "投稿時のページを表示する",
     "display_the_page_when_posting_this_comment": "投稿時のページを表示する",

+ 1 - 1
apps/app/public/static/locales/zh_CN/translation.json

@@ -318,7 +318,7 @@
 		"notice": {
 		"notice": {
 			"conflict": "无法保存您所做的更改,因为其他人正在编辑此页。请在重新加载页面后重新编辑受影响的部分。"
 			"conflict": "无法保存您所做的更改,因为其他人正在编辑此页。请在重新加载页面后重新编辑受影响的部分。"
 		},
 		},
-    "changes_not_saved": "您所做的更改可能不会保存。"
+    "changes_not_saved": "您所做的更改可能不会保存。你真的想继续前进吗?"
   },
   },
   "page_comment": {
   "page_comment": {
     "display_the_page_when_posting_this_comment": "Display the page when posting this comment",
     "display_the_page_when_posting_this_comment": "Display the page when posting this comment",

+ 6 - 6
apps/app/resource/locales/en_US/admin/userInvitation.txt

@@ -1,14 +1,14 @@
-Hi, <%- email -%>
+Hi, <%- email %>
 
 
 You are invited to our Wiki, you can log in with following account:
 You are invited to our Wiki, you can log in with following account:
 
 
-Email: <%- email -%>
-Password: <%- password -%>
+Email: <%- email %>
+Password: <%- password %>
 (This password was auto generated. Update required at the first time you logging in)
 (This password was auto generated. Update required at the first time you logging in)
 
 
 We are waiting for you!
 We are waiting for you!
-<%- url -%>
+<%- url %>
 
 
 --
 --
-<%- appTitle -%>
-<%- url -%>
+<%- appTitle %>
+<%- url %>

+ 5 - 5
apps/app/resource/locales/en_US/admin/userResetPassword.txt

@@ -1,11 +1,11 @@
-Hi, <%- email -%>
+Hi, <%- email %>
 
 
 Your password has been reset by the administrator, you can log in with following account:
 Your password has been reset by the administrator, you can log in with following account:
 
 
-Email: <%- email -%>
-New Password: <%- password -%>
+Email: <%- email %>
+New Password: <%- password %>
 (This password was auto generated. Update required at the first time you logging in)
 (This password was auto generated. Update required at the first time you logging in)
 
 
 --
 --
-<%- appTitle -%>
-<%- url -%>
+<%- appTitle %>
+<%- url %>

+ 8 - 8
apps/app/resource/locales/en_US/admin/userWaitingActivation.txt

@@ -1,21 +1,21 @@
-Hi, <%- adminUser.name -%>
+Hi, <%- adminUser.name %>
 
 
-A user registered to <%- appTitle -%>.
+A user registered to <%- appTitle %>.
 
 
 
 
 ====
 ====
 Created user:
 Created user:
 
 
-Name: <%- createdUser.name -%>
-User Name: <%- createdUser.username -%>
-Email: <%- createdUser.email -%>
+Name: <%- createdUser.name %>
+User Name: <%- createdUser.username %>
+Email: <%- createdUser.email %>
 ====
 ====
 
 
 Please do some action with following URL:
 Please do some action with following URL:
-<%- url -%>/admin/users
+<%- url %>/admin/users
 
 
 
 
 --
 --
-<%- appTitle -%>
-<%- url -%>
+<%- appTitle %>
+<%- url %>
 
 

+ 3 - 3
apps/app/resource/locales/en_US/notifications/comment.txt

@@ -1,9 +1,9 @@
-<%- username }} commented on {{ path -%>.
+<%- username %> commented on <%- path %>.
 
 
 ----------------------
 ----------------------
 
 
-<%- comment -%>
+<%- comment %>
 
 
 ----------------------
 ----------------------
 
 
-Growi: <%- appTitle -%>
+Growi: <%- appTitle %>

+ 4 - 4
apps/app/resource/locales/en_US/notifications/notActiveUser.txt

@@ -1,13 +1,13 @@
 Password Reset
 Password Reset
 
 
-Hi, <%- email -%>
+Hi, <%- email %>
 
 
-A request has been received to change the password from <%- appTitle -%>.
+A request has been received to change the password from <%- appTitle %>.
 However, this email is not registerd. Please try again with different email.
 However, this email is not registerd. Please try again with different email.
 
 
 If you did not request a password reset, you can safely ignore this email.
 If you did not request a password reset, you can safely ignore this email.
 
 
 -------------------------------------------------------------------------
 -------------------------------------------------------------------------
 
 
-GROWI: <%- appTitle -%>
-URL: <%- url -%>
+GROWI: <%- appTitle %>
+URL: <%- url %>

+ 2 - 2
apps/app/resource/locales/en_US/notifications/pageCreate.txt

@@ -1,5 +1,5 @@
-<%- username -%> created a new page under <%- path -%>.
+<%- username %> created a new page under <%- path %>.
 
 
 ----------------------
 ----------------------
 
 
-Growi: <%- appTitle -%>
+Growi: <%- appTitle %>

+ 2 - 2
apps/app/resource/locales/en_US/notifications/pageDelete.txt

@@ -1,5 +1,5 @@
-<%- username -%> deleted the page  <%- path -%>.
+<%- username %> deleted the page  <%- path %>.
 
 
 ----------------------
 ----------------------
 
 
-Growi: <%- appTitle -%>
+Growi: <%- appTitle %>

+ 2 - 2
apps/app/resource/locales/en_US/notifications/pageEdit.txt

@@ -1,5 +1,5 @@
-<%- username -%> edited the page <%- path -%>.
+<%- username %> edited the page <%- path %>.
 
 
 ----------------------
 ----------------------
 
 
-Growi: <%- appTitle -%>
+Growi: <%- appTitle %>

+ 2 - 2
apps/app/resource/locales/en_US/notifications/pageLike.txt

@@ -1,5 +1,5 @@
-<%- username -%> liked the page <%- path -%>.
+<%- username %> liked the page <%- path %>.
 
 
 ----------------------
 ----------------------
 
 
-Growi: <%- appTitle -%>
+Growi: <%- appTitle %>

+ 2 - 2
apps/app/resource/locales/en_US/notifications/pageMove.txt

@@ -1,5 +1,5 @@
-<%- username -%> renamed the page <%- oldPath -%> to <%- newPath -%>.
+<%- username %> renamed the page <%- oldPath %> to <%- newPath %>.
 
 
 ----------------------
 ----------------------
 
 
-Growi: <%- appTitle -%>
+Growi: <%- appTitle %>

+ 4 - 4
apps/app/resource/locales/en_US/notifications/passwordReset.txt

@@ -1,12 +1,12 @@
 Password Reset
 Password Reset
 
 
-Hi, <%- email -%>
+Hi, <%- email %>
 
 
-A request has been received to change the password your GROWI (<%- appTitle -%>) account.
+A request has been received to change the password your GROWI (<%- appTitle %>) account.
 To reset your password, click on the link below.
 To reset your password, click on the link below.
 
 
-<%- url -%>
+<%- url %>
 
 
-This link will expire in 10 minutes at  <%- expiredAt -%>.
+This link will expire in 10 minutes at  <%- expiredAt %>.
 
 
 If you did not request a password reset, you can safely ignore this email.
 If you did not request a password reset, you can safely ignore this email.

+ 1 - 1
apps/app/resource/locales/en_US/notifications/passwordResetSuccessful.txt

@@ -1,6 +1,6 @@
 Password Reset Successful
 Password Reset Successful
 
 
-Hi <%- email -%>
+Hi <%- email %>
 
 
 Your password has been successfully reset.
 Your password has been successfully reset.
 Please log in with your new password.
 Please log in with your new password.

+ 4 - 4
apps/app/resource/locales/en_US/notifications/userActivation.txt

@@ -1,12 +1,12 @@
 Account confirmation
 Account confirmation
 
 
-Hi, <%- email -%>
+Hi, <%- email %>
 
 
-An acount has been created in GROWI (<%- appTitle -%>).
+An acount has been created in GROWI (<%- appTitle %>).
 To activate your account, click on the link below.
 To activate your account, click on the link below.
 
 
-<%- url -%>
+<%- url %>
 
 
-This link will expire in 1 hour at  <%- expiredAt -%>.
+This link will expire in 1 hour at  <%- expiredAt %>.
 
 
 If you did not created the account, you can safely ignore this email.
 If you did not created the account, you can safely ignore this email.

+ 6 - 6
apps/app/resource/locales/ja_JP/admin/userInvitation.txt

@@ -1,14 +1,14 @@
-Hi, <%- email -%>
+Hi, <%- email %>
 
 
 You are invited to our Wiki, you can log in with following account:
 You are invited to our Wiki, you can log in with following account:
 
 
-Email: <%- email -%>
-Password: <%- password -%>
+Email: <%- email %>
+Password: <%- password %>
 (This password was auto generated. Update required at the first time you logging in)
 (This password was auto generated. Update required at the first time you logging in)
 
 
 We are waiting for you!
 We are waiting for you!
-<%- url -%>
+<%- url %>
 
 
 --
 --
-<%- appTitle -%>
-<%- url -%>
+<%- appTitle %>
+<%- url %>

+ 6 - 5
apps/app/resource/locales/ja_JP/admin/userResetPassword.txt

@@ -1,11 +1,12 @@
-Hi, <%- email -%>
+Hi, <%- email %>
 
 
 Your password has been reset by the administrator, you can log in with following account:
 Your password has been reset by the administrator, you can log in with following account:
 
 
-Email: <%- email -%>
-New Password: <%- password -%>
+Email: <%- email %>
+New Password: <%- password %>
 (This password was auto generated. Update required at the first time you logging in)
 (This password was auto generated. Update required at the first time you logging in)
 
 
 --
 --
-<%- appTitle -%>
-<%- url -%>
+<%- appTitle %>
+<%- url %>
+

+ 8 - 8
apps/app/resource/locales/ja_JP/admin/userWaitingActivation.txt

@@ -1,21 +1,21 @@
-Hi, <%- adminUser.name -%>
+Hi, <%- adminUser.name %>
 
 
-A user registered to <%- appTitle -%>.
+A user registered to <%- appTitle %>.
 
 
 
 
 ====
 ====
 Created user:
 Created user:
 
 
-Name: <%- createdUser.name -%>
-User Name: <%- createdUser.username -%>
-Email: <%- createdUser.email -%>
+Name: <%- createdUser.name %>
+User Name: <%- createdUser.username %>
+Email: <%- createdUser.email %>
 ====
 ====
 
 
 Please do some action with following URL:
 Please do some action with following URL:
-<%- url -%>/admin/users
+<%- url %>/admin/users
 
 
 
 
 --
 --
-<%- appTitle -%>
-<%- url -%>
+<%- appTitle %>
+<%- url %>
 
 

+ 4 - 4
apps/app/resource/locales/ja_JP/notifications/notActiveUser.txt

@@ -1,13 +1,13 @@
 パスワードリセット
 パスワードリセット
 
 
-こんにちは、 <%- email -%>
+こんにちは、 <%- email %>
 
 
-<%- appTitle -%> からパスワード再設定のリクエストがありましたが、このemailは登録されておりません。
+<%- appTitle %> からパスワード再設定のリクエストがありましたが、このemailは登録されておりません。
 他のemailアドレスで再度お試しください。
 他のemailアドレスで再度お試しください。
 
 
 もしこのリクエストに心当たりがない場合は、このメールを無視してください。
 もしこのリクエストに心当たりがない場合は、このメールを無視してください。
 
 
 -------------------------------------------------------------------------
 -------------------------------------------------------------------------
 
 
-GROWI: <%- appTitle -%>
-URL: <%- url -%>
+GROWI: <%- appTitle %>
+URL: <%- url %>

+ 4 - 4
apps/app/resource/locales/ja_JP/notifications/passwordReset.txt

@@ -1,12 +1,12 @@
 パスワード リセット
 パスワード リセット
 
 
-こんにちは, <%- email -%>
+こんにちは, <%- email %>
 
 
-あなたのGROWI (<%- appTitle -%>) アカウントから、パスワード再設定のリクエストがありました。
+あなたのGROWI (<%- appTitle %>) アカウントから、パスワード再設定のリクエストがありました。
 パスワードをリセットするには、以下のリンクをクリックしてください。
 パスワードをリセットするには、以下のリンクをクリックしてください。
 
 
-<%- url -%>
+<%- url %>
 
 
-このリンクは10分後の <%- expiredAt -%> に失効します。
+このリンクは10分後の <%- expiredAt %> に失効します。
 
 
 もしこのリクエストに心当たりがない場合は、このメールを無視してください。
 もしこのリクエストに心当たりがない場合は、このメールを無視してください。

+ 1 - 1
apps/app/resource/locales/ja_JP/notifications/passwordResetSuccessful.txt

@@ -1,6 +1,6 @@
 パスワードリセットに成功
 パスワードリセットに成功
 
 
-こんにちは、 <%- email -%>
+こんにちは、 <%- email %>
 
 
 あなたのパスワードは正常にリセットされました。
 あなたのパスワードは正常にリセットされました。
 新しいパスワードでログインしてください。
 新しいパスワードでログインしてください。

+ 4 - 4
apps/app/resource/locales/ja_JP/notifications/userActivation.txt

@@ -1,13 +1,13 @@
 仮登録完了のお知らせ
 仮登録完了のお知らせ
 
 
-<%- email -%> さん
+<%- email %> さん
 
 
-GROWI (<%- appTitle -%>) で仮登録が完了いたしました。
+GROWI (<%- appTitle %>) で仮登録が完了いたしました。
 
 
 ご本人様確認のため、下記リンクをクリックし、アカウントの本登録を完了させて下さい。
 ご本人様確認のため、下記リンクをクリックし、アカウントの本登録を完了させて下さい。
 
 
-<%- url -%>
+<%- url %>
 
 
-このリンクは1時間後の <%- expiredAt -%> に失効します。
+このリンクは1時間後の <%- expiredAt %> に失効します。
 
 
 ※当メールの内容に心当たりがない場合は、このメールを無視してください。
 ※当メールの内容に心当たりがない場合は、このメールを無視してください。

+ 6 - 6
apps/app/resource/locales/zh_CN/admin/userInvitation.txt

@@ -1,14 +1,14 @@
-Hi, <%- email -%>
+Hi, <%- email %>
 
 
 You are invited to our Wiki, you can log in with following account:
 You are invited to our Wiki, you can log in with following account:
 
 
-Email: <%- email -%>
-Password: <%- password -%>
+Email: <%- email %>
+Password: <%- password %>
 (This password was auto generated. Update required at the first time you logging in)
 (This password was auto generated. Update required at the first time you logging in)
 
 
 We are waiting for you!
 We are waiting for you!
-<%- url -%>
+<%- url %>
 
 
 --
 --
-<%- appTitle -%>
-<%- url -%>
+<%- appTitle %>
+<%- url %>

+ 5 - 5
apps/app/resource/locales/zh_CN/admin/userResetPassword.txt

@@ -1,11 +1,11 @@
-Hi, <%- email -%>
+Hi, <%- email %>
 
 
 Your password has been reset by the administrator, you can log in with following account:
 Your password has been reset by the administrator, you can log in with following account:
 
 
-Email: <%- email -%>
-New Password: <%- password -%>
+Email: <%- email %>
+New Password: <%- password %>
 (This password was auto generated. Update required at the first time you logging in)
 (This password was auto generated. Update required at the first time you logging in)
 
 
 --
 --
-<%- appTitle -%>
-<%- url -%>
+<%- appTitle %>
+<%- url %>

+ 8 - 8
apps/app/resource/locales/zh_CN/admin/userWaitingActivation.txt

@@ -1,21 +1,21 @@
-Hi, <%- adminUser.name -%>
+Hi, <%- adminUser.name %>
 
 
-A user registered to <%- appTitle -%>.
+A user registered to <%- appTitle %>.
 
 
 
 
 ====
 ====
 Created user:
 Created user:
 
 
-Name: <%- createdUser.name -%>
-User Name: <%- createdUser.username -%>
-Email: <%- createdUser.email -%>
+Name: <%- createdUser.name %>
+User Name: <%- createdUser.username %>
+Email: <%- createdUser.email %>
 ====
 ====
 
 
 Please do some action with following URL:
 Please do some action with following URL:
-<%- url -%>/admin/users
+<%- url %>/admin/users
 
 
 
 
 --
 --
-<%- appTitle -%>
-<%- url -%>
+<%- appTitle %>
+<%- url %>
 
 

+ 3 - 3
apps/app/resource/locales/zh_CN/notifications/comment.txt

@@ -1,9 +1,9 @@
-<%- username -%> commented on <%- path -%>.
+<%- username %> commented on <%- path %>.
 
 
 ----------------------
 ----------------------
 
 
-<%- comment -%>
+<%- comment %>
 
 
 ----------------------
 ----------------------
 
 
-Growi: <%- appTitle -%>
+Growi: <%- appTitle %>

+ 4 - 4
apps/app/resource/locales/zh_CN/notifications/notActiveUser.txt

@@ -1,13 +1,13 @@
 重设密码
 重设密码
 
 
-嗨,<%-电子邮件-%>
+嗨,<%-电子邮件%>
 
 
-已收到来自 <%-appTitle-%> 的更改密码请求。
+已收到来自 <%-appTitle%> 的更改密码请求。
 但是,此电子邮件未注册。请使用其他电子邮件重试。
 但是,此电子邮件未注册。请使用其他电子邮件重试。
 
 
 如果您没有要求重置密码,则可以放心地忽略此电子邮件。
 如果您没有要求重置密码,则可以放心地忽略此电子邮件。
 
 
 -------------------------------------------------------------------------
 -------------------------------------------------------------------------
 
 
-GROWI: <%- appTitle -%>
-URL: <%- url -%>
+GROWI: <%- appTitle %>
+URL: <%- url %>

+ 2 - 2
apps/app/resource/locales/zh_CN/notifications/pageCreate.txt

@@ -1,5 +1,5 @@
-<%- username -%> created a new page under <%- path -%>.
+<%- username %> created a new page under <%- path %>.
 
 
 ----------------------
 ----------------------
 
 
-Growi: <%- appTitle -%>
+Growi: <%- appTitle %>

+ 2 - 2
apps/app/resource/locales/zh_CN/notifications/pageDelete.txt

@@ -1,5 +1,5 @@
-<%- username -%> deleted the page  <%- path -%>.
+<%- username %> deleted the page  <%- path %>.
 
 
 ----------------------
 ----------------------
 
 
-Growi: <%- appTitle -%>
+Growi: <%- appTitle %>

+ 2 - 2
apps/app/resource/locales/zh_CN/notifications/pageEdit.txt

@@ -1,5 +1,5 @@
-<%- username -%> edited the page <%- path -%>.
+<%- username %> edited the page <%- path %>.
 
 
 ----------------------
 ----------------------
 
 
-Growi: <%- appTitle -%>
+Growi: <%- appTitle %>

+ 2 - 2
apps/app/resource/locales/zh_CN/notifications/pageLike.txt

@@ -1,5 +1,5 @@
-<%- username -%> liked the page <%- path -%>.
+<%- username %> liked the page <%- path %>.
 
 
 ----------------------
 ----------------------
 
 
-Growi: <%- appTitle -%>
+Growi: <%- appTitle %>

+ 2 - 2
apps/app/resource/locales/zh_CN/notifications/pageMove.txt

@@ -1,5 +1,5 @@
-<%- username -%> renamed the page <%- oldPath -%> to <%- newPath -%>.
+<%- username %> renamed the page <%- oldPath %> to <%- newPath %>.
 
 
 ----------------------
 ----------------------
 
 
-Growi: <%- appTitle -%>
+Growi: <%- appTitle %>

+ 3 - 3
apps/app/resource/locales/zh_CN/notifications/passwordReset.txt

@@ -1,11 +1,11 @@
 重设密码
 重设密码
 
 
-嗨,<%- email -%>
+嗨,<%- email %>
 
 
-已收到更改您 GROWI (<%-appTitle-%>) 帐户 密码的请求。
+已收到更改您 GROWI (<%-appTitle%>) 帐户 密码的请求。
 要重置密码,请单击下面的链接。
 要重置密码,请单击下面的链接。
 
 
-<%- url -%>
+<%- url %>
 
 
 这个链接在10分钟后的{ expiredAt }}失效。
 这个链接在10分钟后的{ expiredAt }}失效。
 
 

+ 1 - 1
apps/app/resource/locales/zh_CN/notifications/passwordResetSuccessful.txt

@@ -1,6 +1,6 @@
 密码重置成功
 密码重置成功
 
 
-嗨, <%-email-%>
+嗨, <%-email%>
 
 
 您的密码已成功重置。
 您的密码已成功重置。
 请使用您的新密码登录。
 请使用您的新密码登录。

+ 4 - 4
apps/app/resource/locales/zh_CN/notifications/userActivation.txt

@@ -1,12 +1,12 @@
 确认账户创建
 确认账户创建
 
 
-致<%- email -%>,
+致<%- email %>,
 
 
-已使用 GROWI (<%- appTitle -%>) 创建帐户。
+已使用 GROWI (<%- appTitle %>) 创建帐户。
 单击下面的链接以激活您的帐户。
 单击下面的链接以激活您的帐户。
 
 
-<%- url -%>
+<%- url %>
 
 
-这个链接将在1小时后即<%- expiredAt -%>失效。
+这个链接将在1小时后即<%- expiredAt %>失效。
 
 
 如果您尚未创建,请忽略此电子邮件。
 如果您尚未创建,请忽略此电子邮件。

+ 8 - 2
apps/app/src/client/services/side-effects/page-updated.ts

@@ -1,6 +1,7 @@
 import { useCallback, useEffect } from 'react';
 import { useCallback, useEffect } from 'react';
 
 
 import { SocketEventName } from '~/interfaces/websocket';
 import { SocketEventName } from '~/interfaces/websocket';
+import { useCurrentPageId } from '~/stores/context';
 import { useSetRemoteLatestPageData } from '~/stores/remote-latest-page';
 import { useSetRemoteLatestPageData } from '~/stores/remote-latest-page';
 import { useGlobalSocket } from '~/stores/websocket';
 import { useGlobalSocket } from '~/stores/websocket';
 
 
@@ -9,6 +10,7 @@ export const usePageUpdatedEffect = (): void => {
   const { setRemoteLatestPageData } = useSetRemoteLatestPageData();
   const { setRemoteLatestPageData } = useSetRemoteLatestPageData();
 
 
   const { data: socket } = useGlobalSocket();
   const { data: socket } = useGlobalSocket();
+  const { data: currentPageId } = useCurrentPageId();
 
 
   const setLatestRemotePageData = useCallback((data) => {
   const setLatestRemotePageData = useCallback((data) => {
     const { s2cMessagePageUpdated } = data;
     const { s2cMessagePageUpdated } = data;
@@ -21,8 +23,12 @@ export const usePageUpdatedEffect = (): void => {
       revisionIdHackmdSynced: s2cMessagePageUpdated.revisionIdHackmdSynced,
       revisionIdHackmdSynced: s2cMessagePageUpdated.revisionIdHackmdSynced,
       hasDraftOnHackmd: s2cMessagePageUpdated.hasDraftOnHackmd,
       hasDraftOnHackmd: s2cMessagePageUpdated.hasDraftOnHackmd,
     };
     };
-    setRemoteLatestPageData(remoteData);
-  }, [setRemoteLatestPageData]);
+
+    if (currentPageId != null && currentPageId === s2cMessagePageUpdated.pageId) {
+      setRemoteLatestPageData(remoteData);
+    }
+
+  }, [currentPageId, setRemoteLatestPageData]);
 
 
   // listen socket for someone updating this page
   // listen socket for someone updating this page
   useEffect(() => {
   useEffect(() => {

+ 1 - 1
apps/app/src/components/Admin/Users/PasswordResetModal.jsx

@@ -54,7 +54,7 @@ class PasswordResetModal extends React.Component {
 
 
     return (
     return (
       <>
       <>
-        <p className="alert alert-danger">{t('user_management.reset_password_modal.password_reset_message')}</p>
+        <p className="text-danger">{t('user_management.reset_password_modal.password_reset_message')}</p>
         <p>
         <p>
           {t('user_management.reset_password_modal.target_user')}: <code>{userForPasswordResetModal.email}</code>
           {t('user_management.reset_password_modal.target_user')}: <code>{userForPasswordResetModal.email}</code>
         </p>
         </p>

+ 1 - 6
apps/app/src/components/LoginForm.tsx

@@ -2,7 +2,6 @@ import React, {
   useState, useEffect, useCallback,
   useState, useEffect, useCallback,
 } from 'react';
 } from 'react';
 
 
-import { USER_STATUS } from '@growi/core';
 import { useTranslation } from 'next-i18next';
 import { useTranslation } from 'next-i18next';
 import { useRouter } from 'next/router';
 import { useRouter } from 'next/router';
 import ReactCardFlip from 'react-card-flip';
 import ReactCardFlip from 'react-card-flip';
@@ -95,16 +94,12 @@ export const LoginForm = (props: LoginFormProps): JSX.Element => {
 
 
     try {
     try {
       const res = await apiv3Post('/login', { loginForm });
       const res = await apiv3Post('/login', { loginForm });
-      const { redirectTo, userStatus } = res.data;
+      const { redirectTo } = res.data;
 
 
       if (redirectTo != null) {
       if (redirectTo != null) {
         return router.push(redirectTo);
         return router.push(redirectTo);
       }
       }
 
 
-      if (userStatus !== USER_STATUS.ACTIVE) {
-        window.location.href = '/';
-      }
-
       return router.push('/');
       return router.push('/');
     }
     }
     catch (err) {
     catch (err) {

+ 6 - 2
apps/app/src/components/PageEditor/ConflictDiffModal.tsx

@@ -4,7 +4,7 @@ import React, {
 
 
 import { UserPicture } from '@growi/ui';
 import { UserPicture } from '@growi/ui';
 import CodeMirror from 'codemirror/lib/codemirror';
 import CodeMirror from 'codemirror/lib/codemirror';
-import { format } from 'date-fns';
+import { format, parseISO } from 'date-fns';
 import { useTranslation } from 'next-i18next';
 import { useTranslation } from 'next-i18next';
 import {
 import {
   Modal, ModalHeader, ModalBody, ModalFooter,
   Modal, ModalHeader, ModalBody, ModalFooter,
@@ -305,6 +305,10 @@ export const ConflictDiffModal = (props: ConflictDiffModalProps): JSX.Element =>
     return <></>;
     return <></>;
   }
   }
 
 
+  const currentPageCreatedAtFixed = typeof currentPage.updatedAt === 'string'
+    ? parseISO(currentPage.updatedAt)
+    : currentPage.updatedAt;
+
   const request: IRevisionOnConflictWithStringDate = {
   const request: IRevisionOnConflictWithStringDate = {
     revisionId: '',
     revisionId: '',
     revisionBody: props.markdownOnEdit,
     revisionBody: props.markdownOnEdit,
@@ -314,7 +318,7 @@ export const ConflictDiffModal = (props: ConflictDiffModalProps): JSX.Element =>
   const origin: IRevisionOnConflictWithStringDate = {
   const origin: IRevisionOnConflictWithStringDate = {
     revisionId: currentPage?.revision._id,
     revisionId: currentPage?.revision._id,
     revisionBody: currentPage?.revision.body,
     revisionBody: currentPage?.revision.body,
-    createdAt: format(currentPage.updatedAt, 'yyyy/MM/dd HH:mm:ss'),
+    createdAt: format(currentPageCreatedAtFixed, 'yyyy/MM/dd HH:mm:ss'),
     user: currentPage?.lastUpdateUser,
     user: currentPage?.lastUpdateUser,
   };
   };
   const latest: IRevisionOnConflictWithStringDate = {
   const latest: IRevisionOnConflictWithStringDate = {

+ 20 - 4
apps/app/src/components/UnsavedAlertDialog.tsx

@@ -8,7 +8,7 @@ import { useIsEnabledUnsavedWarning } from '~/stores/editor';
 const UnsavedAlertDialog = (): JSX.Element => {
 const UnsavedAlertDialog = (): JSX.Element => {
   const { t } = useTranslation();
   const { t } = useTranslation();
   const router = useRouter();
   const router = useRouter();
-  const { data: isEnabledUnsavedWarning } = useIsEnabledUnsavedWarning();
+  const { data: isEnabledUnsavedWarning, mutate: mutateIsEnabledUnsavedWarning } = useIsEnabledUnsavedWarning();
 
 
   const alertUnsavedWarningByBrowser = useCallback((e) => {
   const alertUnsavedWarningByBrowser = useCallback((e) => {
     if (isEnabledUnsavedWarning) {
     if (isEnabledUnsavedWarning) {
@@ -23,12 +23,20 @@ const UnsavedAlertDialog = (): JSX.Element => {
 
 
   const alertUnsavedWarningByNextRouter = useCallback(() => {
   const alertUnsavedWarningByNextRouter = useCallback(() => {
     if (isEnabledUnsavedWarning) {
     if (isEnabledUnsavedWarning) {
-    // eslint-disable-next-line no-alert
-      window.alert(t('page_edit.changes_not_saved'));
+      // see: https://zenn.dev/qaynam/articles/c4794537a163d2
+      // eslint-disable-next-line no-alert
+      const answer = window.confirm(t('page_edit.changes_not_saved'));
+      if (!answer) {
+      // eslint-disable-next-line no-throw-literal
+        throw 'Abort route';
+      }
     }
     }
-    return;
   }, [isEnabledUnsavedWarning, t]);
   }, [isEnabledUnsavedWarning, t]);
 
 
+  const onRouterChangeComplete = useCallback(() => {
+    mutateIsEnabledUnsavedWarning(false);
+  }, [mutateIsEnabledUnsavedWarning]);
+
   /*
   /*
   * Route changes by Browser
   * Route changes by Browser
   * Example: window.location.href, F5
   * Example: window.location.href, F5
@@ -53,6 +61,14 @@ const UnsavedAlertDialog = (): JSX.Element => {
   }, [alertUnsavedWarningByNextRouter, router.events]);
   }, [alertUnsavedWarningByNextRouter, router.events]);
 
 
 
 
+  useEffect(() => {
+    router.events.on('routeChangeComplete', onRouterChangeComplete);
+    return () => {
+      router.events.off('routeChangeComplete', onRouterChangeComplete);
+    };
+  }, [onRouterChangeComplete, router.events]);
+
+
   return <></>;
   return <></>;
 };
 };
 
 

+ 3 - 1
apps/app/src/interfaces/user.ts

@@ -1,3 +1,5 @@
 export type {
 export type {
-  IUser, IUserGroupRelation, IUserGroup, IUserHasId, IUserGroupHasId, IUserGroupRelationHasId,
+  IUser, IUserGroupRelation, IUserGroup, IUserHasId, IUserGroupHasId, IUserGroupRelationHasId, IUserStatus,
 } from '@growi/core';
 } from '@growi/core';
+
+export { USER_STATUS } from '@growi/core';

+ 13 - 4
apps/app/src/pages/[[...path]].page.tsx

@@ -234,8 +234,6 @@ const Page: NextPageWithLayout<Props> = (props: Props) => {
   const revisionBody = pageWithMeta?.data.revision?.body;
   const revisionBody = pageWithMeta?.data.revision?.body;
 
 
   useCurrentPageId(pageId ?? null);
   useCurrentPageId(pageId ?? null);
-  useRevisionIdHackmdSynced(pageWithMeta?.data.revisionHackmdSynced);
-  useRemoteRevisionId(pageWithMeta?.data.revision?._id);
   usePageIdOnHackmd(pageWithMeta?.data.pageIdOnHackmd);
   usePageIdOnHackmd(pageWithMeta?.data.pageIdOnHackmd);
   useHasDraftOnHackmd(pageWithMeta?.data.hasDraftOnHackmd ?? false);
   useHasDraftOnHackmd(pageWithMeta?.data.hasDraftOnHackmd ?? false);
   useCurrentPathname(props.currentPathname);
   useCurrentPathname(props.currentPathname);
@@ -247,6 +245,9 @@ const Page: NextPageWithLayout<Props> = (props: Props) => {
   const { data: grantData } = useSWRxIsGrantNormalized(pageId);
   const { data: grantData } = useSWRxIsGrantNormalized(pageId);
   const { mutate: mutateSelectedGrant } = useSelectedGrant();
   const { mutate: mutateSelectedGrant } = useSelectedGrant();
 
 
+  const { mutate: mutateRemoteRevisionId } = useRemoteRevisionId();
+  const { mutate: mutateRevisionIdHackmdSynced } = useRevisionIdHackmdSynced();
+
   useSetupGlobalSocket();
   useSetupGlobalSocket();
   useSetupGlobalSocketForPage(pageId);
   useSetupGlobalSocketForPage(pageId);
 
 
@@ -272,9 +273,17 @@ const Page: NextPageWithLayout<Props> = (props: Props) => {
   }, [props.currentPathname, router]);
   }, [props.currentPathname, router]);
 
 
   // initialize mutateEditingMarkdown only once per page
   // initialize mutateEditingMarkdown only once per page
+  // need to include useCurrentPathname not useCurrentPagePath
+  useEffect(() => {
+    if (props.currentPathname != null) {
+      mutateEditingMarkdown(revisionBody);
+    }
+  }, [mutateEditingMarkdown, revisionBody, props.currentPathname]);
+
   useEffect(() => {
   useEffect(() => {
-    mutateEditingMarkdown(revisionBody);
-  }, [mutateEditingMarkdown, revisionBody]);
+    mutateRemoteRevisionId(pageWithMeta?.data.revision?._id);
+    mutateRevisionIdHackmdSynced(pageWithMeta?.data.revisionHackmdSynced);
+  }, [mutateRemoteRevisionId, mutateRevisionIdHackmdSynced, pageWithMeta?.data.revision?._id, pageWithMeta?.data.revisionHackmdSynced]);
 
 
   const title = generateCustomTitleForPage(props, pagePath);
   const title = generateCustomTitleForPage(props, pagePath);
 
 

+ 4 - 9
apps/app/src/server/middlewares/login-required.js

@@ -1,3 +1,4 @@
+import { createRedirectToForUnauthenticated } from '~/server/util/createRedirectToForUnauthenticated';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
 const logger = loggerFactory('growi:middleware:login-required');
 const logger = loggerFactory('growi:middleware:login-required');
@@ -20,15 +21,9 @@ module.exports = (crowi, isGuestAllowed = false, fallback = null) => {
         // Active の人だけ先に進める
         // Active の人だけ先に進める
         return next();
         return next();
       }
       }
-      if (req.user.status === User.STATUS_REGISTERED) {
-        return res.redirect('/login/error/registered');
-      }
-      if (req.user.status === User.STATUS_SUSPENDED) {
-        return res.redirect('/login/error/suspended');
-      }
-      if (req.user.status === User.STATUS_INVITED) {
-        return res.redirect('/invited');
-      }
+
+      const redirectTo = createRedirectToForUnauthenticated(req.user.status) ?? '/login';
+      return res.redirect(redirectTo);
     }
     }
 
 
     // check the route config and ACL
     // check the route config and ACL

+ 1 - 1
apps/app/src/server/routes/apiv3/index.js

@@ -51,7 +51,7 @@ module.exports = (crowi, app) => {
   const loginPassport = require('../login-passport')(crowi, app);
   const loginPassport = require('../login-passport')(crowi, app);
 
 
   routerForAuth.post('/login', applicationInstalled, loginFormValidator.loginRules(), loginFormValidator.loginValidation,
   routerForAuth.post('/login', applicationInstalled, loginFormValidator.loginRules(), loginFormValidator.loginValidation,
-    addActivity, loginPassport.isEnableLoginWithLocalOrLdap, loginPassport.loginWithLocal, loginPassport.loginWithLdap,
+    addActivity, loginPassport.injectRedirectTo, loginPassport.isEnableLoginWithLocalOrLdap, loginPassport.loginWithLocal, loginPassport.loginWithLdap,
     loginPassport.cannotLoginErrorHadnler, loginPassport.loginFailure);
     loginPassport.cannotLoginErrorHadnler, loginPassport.loginFailure);
 
 
   routerForAuth.use('/invited', require('./invited')(crowi));
   routerForAuth.use('/invited', require('./invited')(crowi));

+ 0 - 7
apps/app/src/server/routes/apiv3/users.js

@@ -841,13 +841,6 @@ module.exports = (crowi) => {
    *        responses:
    *        responses:
    *          200:
    *          200:
    *            description: success resrt password
    *            description: success resrt password
-   *            content:
-   *              application/json:
-   *                schema:
-   *                  properties:
-   *                    user:
-   *                      type: object
-   *                      description: Target user
    */
    */
   router.put('/reset-password', loginRequiredStrictly, adminRequired, addActivity, async(req, res) => {
   router.put('/reset-password', loginRequiredStrictly, adminRequired, addActivity, async(req, res) => {
     const { appService, mailService } = crowi;
     const { appService, mailService } = crowi;

+ 6 - 6
apps/app/src/server/routes/index.js

@@ -91,12 +91,12 @@ module.exports = function(crowi, app) {
   // OAuth
   // OAuth
   app.get('/passport/google'                      , loginPassport.loginWithGoogle, loginPassport.loginFailureForExternalAccount);
   app.get('/passport/google'                      , loginPassport.loginWithGoogle, loginPassport.loginFailureForExternalAccount);
   app.get('/passport/github'                      , loginPassport.loginWithGitHub, loginPassport.loginFailureForExternalAccount);
   app.get('/passport/github'                      , loginPassport.loginWithGitHub, loginPassport.loginFailureForExternalAccount);
-  app.get('/passport/oidc'                        , loginPassport.loginWithOidc, loginPassport.loginFailureForExternalAccount);
-  app.get('/passport/saml'                        , loginPassport.loginWithSaml, loginPassport.loginFailureForExternalAccount);
-  app.get('/passport/google/callback'             , loginPassport.loginPassportGoogleCallback   , loginPassport.loginFailureForExternalAccount);
-  app.get('/passport/github/callback'             , loginPassport.loginPassportGitHubCallback   , loginPassport.loginFailureForExternalAccount);
-  app.get('/passport/oidc/callback'               , loginPassport.loginPassportOidcCallback     , loginPassport.loginFailureForExternalAccount);
-  app.post('/passport/saml/callback'              , addActivity, loginPassport.loginPassportSamlCallback, loginPassport.loginFailureForExternalAccount);
+  app.get('/passport/oidc'                        , loginPassport.loginWithOidc,   loginPassport.loginFailureForExternalAccount);
+  app.get('/passport/saml'                        , loginPassport.loginWithSaml,   loginPassport.loginFailureForExternalAccount);
+  app.get('/passport/google/callback'             , loginPassport.injectRedirectTo, loginPassport.loginPassportGoogleCallback   , loginPassport.loginFailureForExternalAccount);
+  app.get('/passport/github/callback'             , loginPassport.injectRedirectTo, loginPassport.loginPassportGitHubCallback   , loginPassport.loginFailureForExternalAccount);
+  app.get('/passport/oidc/callback'               , loginPassport.injectRedirectTo, loginPassport.loginPassportOidcCallback     , loginPassport.loginFailureForExternalAccount);
+  app.post('/passport/saml/callback'              , addActivity, loginPassport.injectRedirectTo, loginPassport.loginPassportSamlCallback, loginPassport.loginFailureForExternalAccount);
 
 
   app.post('/_api/login/testLdap'    , loginRequiredStrictly , loginFormValidator.loginRules() , loginFormValidator.loginValidation , loginPassport.testLdapCredentials);
   app.post('/_api/login/testLdap'    , loginRequiredStrictly , loginFormValidator.loginRules() , loginFormValidator.loginValidation , loginPassport.testLdapCredentials);
 
 

+ 17 - 7
apps/app/src/server/routes/login-passport.js

@@ -6,6 +6,7 @@ import { SupportedAction } from '~/interfaces/activity';
 import { LoginErrorCode } from '~/interfaces/errors/login-error';
 import { LoginErrorCode } from '~/interfaces/errors/login-error';
 import { ExternalAccountLoginError } from '~/models/vo/external-account-login-error';
 import { ExternalAccountLoginError } from '~/models/vo/external-account-login-error';
 import { NullUsernameToBeRegisteredError } from '~/server/models/errors';
 import { NullUsernameToBeRegisteredError } from '~/server/models/errors';
+import { createRedirectToForUnauthenticated } from '~/server/util/createRedirectToForUnauthenticated';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
 
 
@@ -16,7 +17,6 @@ module.exports = function(crowi, app) {
   const logger = loggerFactory('growi:routes:login-passport');
   const logger = loggerFactory('growi:routes:login-passport');
   const passport = require('passport');
   const passport = require('passport');
   const ExternalAccount = crowi.model('ExternalAccount');
   const ExternalAccount = crowi.model('ExternalAccount');
-  const User = crowi.model('User');
   const passportService = crowi.passportService;
   const passportService = crowi.passportService;
 
 
   const activityEvent = crowi.event('activity');
   const activityEvent = crowi.event('activity');
@@ -120,17 +120,26 @@ module.exports = function(crowi, app) {
 
 
     await crowi.activityService.createActivity(parameters);
     await crowi.activityService.createActivity(parameters);
 
 
+    const redirectToForUnauthenticated = createRedirectToForUnauthenticated(req.user.status);
+    const redirectTo = redirectToForUnauthenticated ?? res.locals.redirectTo ?? '/';
+
     if (isExternalAccount) {
     if (isExternalAccount) {
-      return res.redirect('/');
+      return res.redirect(redirectTo);
     }
     }
 
 
-    // check for redirection to '/invited'
-    const redirectTo = req.user.status === User.STATUS_INVITED ? '/invited' : req.session.redirectTo;
+    return res.apiv3({ redirectTo });
+  };
+
+  const injectRedirectTo = (req, res, next) => {
 
 
-    // remove session.redirectTo
-    delete req.session.redirectTo;
+    // Move "req.session.redirectTo" to "res.locals.redirectTo"
+    // Because the session is regenerated when req.login() is called
+    const redirectTo = req.session.redirectTo;
+    if (redirectTo != null) {
+      res.locals.redirectTo = redirectTo;
+    }
 
 
-    return res.apiv3({ redirectTo, userStatus: req.user.status });
+    next();
   };
   };
 
 
   const isEnableLoginWithLocalOrLdap = (req, res, next) => {
   const isEnableLoginWithLocalOrLdap = (req, res, next) => {
@@ -595,6 +604,7 @@ module.exports = function(crowi, app) {
 
 
   return {
   return {
     cannotLoginErrorHadnler,
     cannotLoginErrorHadnler,
+    injectRedirectTo,
     isEnableLoginWithLocalOrLdap,
     isEnableLoginWithLocalOrLdap,
     loginFailure,
     loginFailure,
     loginFailureForExternalAccount,
     loginFailureForExternalAccount,

+ 17 - 0
apps/app/src/server/util/createRedirectToForUnauthenticated.ts

@@ -0,0 +1,17 @@
+import { USER_STATUS } from '~/interfaces/user';
+import type { IUserStatus } from '~/interfaces/user';
+
+export const createRedirectToForUnauthenticated = (userStatus: IUserStatus): string | null => {
+  switch (userStatus) {
+    case USER_STATUS.REGISTERED:
+      return '/login/error/registered';
+    case USER_STATUS.SUSPENDED:
+      return '/login/error/suspended';
+    case USER_STATUS.INVITED:
+      return '/invited';
+    case USER_STATUS.DELETED:
+      return '/login';
+    default:
+      return null;
+  }
+};

+ 1 - 6
apps/app/src/stores/editor.tsx

@@ -10,7 +10,6 @@ import { IEditorSettings } from '~/interfaces/editor-settings';
 import { SlackChannels } from '~/interfaces/user-trigger-notification';
 import { SlackChannels } from '~/interfaces/user-trigger-notification';
 
 
 import {
 import {
-  useCurrentPathname,
   useCurrentUser, useDefaultIndentSize, useIsGuestUser,
   useCurrentUser, useDefaultIndentSize, useIsGuestUser,
 } from './context';
 } from './context';
 // import { localStorageMiddleware } from './middlewares/sync-to-storage';
 // import { localStorageMiddleware } from './middlewares/sync-to-storage';
@@ -19,11 +18,7 @@ import { useStaticSWR } from './use-static-swr';
 
 
 
 
 export const useEditingMarkdown = (initialData?: string): SWRResponse<string, Error> => {
 export const useEditingMarkdown = (initialData?: string): SWRResponse<string, Error> => {
-  // need to include useCurrentPathname not useCurrentPagePath
-  // https://github.com/weseek/growi/pull/7301
-  const { data: currentPagePath } = useCurrentPathname();
-
-  return useStaticSWR(['editingMarkdown', currentPagePath], initialData);
+  return useStaticSWR('editingMarkdown', initialData);
 };
 };
 
 
 
 

+ 1 - 1
apps/app/test/integration/middlewares/login-required.test.js

@@ -286,7 +286,7 @@ describe('loginRequired', () => {
       expect(res.redirect).toHaveBeenCalledTimes(1);
       expect(res.redirect).toHaveBeenCalledTimes(1);
       expect(res.redirect).toHaveBeenCalledWith('/login');
       expect(res.redirect).toHaveBeenCalledWith('/login');
       expect(result).toBe('redirect');
       expect(result).toBe('redirect');
-      expect(req.session.redirectTo).toBe('original url 1');
+      expect(req.session.redirectTo).toBe(undefined);
     });
     });
 
 
   });
   });

+ 2 - 2
apps/slackbot-proxy/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@growi/slackbot-proxy",
   "name": "@growi/slackbot-proxy",
-  "version": "6.0.7-slackbot-proxy.0",
+  "version": "6.0.8-slackbot-proxy.0",
   "license": "MIT",
   "license": "MIT",
   "scripts": {
   "scripts": {
     "build": "yarn tsc && tsc-alias -p tsconfig.build.json",
     "build": "yarn tsc && tsc-alias -p tsconfig.build.json",
@@ -26,7 +26,7 @@
   },
   },
   "dependencies": {
   "dependencies": {
     "@godaddy/terminus": "^4.9.0",
     "@godaddy/terminus": "^4.9.0",
-    "@growi/slack": "^6.0.7-RC.0",
+    "@growi/slack": "^6.0.8-RC.0",
     "@slack/oauth": "^2.0.1",
     "@slack/oauth": "^2.0.1",
     "@slack/web-api": "^6.2.4",
     "@slack/web-api": "^6.2.4",
     "@tsed/common": "^6.43.0",
     "@tsed/common": "^6.43.0",

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "growi",
   "name": "growi",
-  "version": "6.0.7-RC.0",
+  "version": "6.0.8-RC.0",
   "description": "Team collaboration software using markdown",
   "description": "Team collaboration software using markdown",
   "tags": [
   "tags": [
     "wiki",
     "wiki",

+ 1 - 1
packages/codemirror-textlint/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@growi/codemirror-textlint",
   "name": "@growi/codemirror-textlint",
-  "version": "6.0.7-RC.0",
+  "version": "6.0.8-RC.0",
   "license": "MIT",
   "license": "MIT",
   "main": "dist/index.js",
   "main": "dist/index.js",
   "scripts": {
   "scripts": {

+ 1 - 1
packages/core/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@growi/core",
   "name": "@growi/core",
-  "version": "6.0.7-RC.0",
+  "version": "6.0.8-RC.0",
   "description": "GROWI Core Libraries",
   "description": "GROWI Core Libraries",
   "license": "MIT",
   "license": "MIT",
   "keywords": [
   "keywords": [

+ 1 - 1
packages/hackmd/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@growi/hackmd",
   "name": "@growi/hackmd",
-  "version": "6.0.7-RC.0",
+  "version": "6.0.8-RC.0",
   "description": "GROWI js and css files to use hackmd",
   "description": "GROWI js and css files to use hackmd",
   "license": "MIT",
   "license": "MIT",
   "main": "dist/index.js",
   "main": "dist/index.js",

+ 2 - 2
packages/presentation/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@growi/presentation",
   "name": "@growi/presentation",
-  "version": "6.0.7-RC.0",
+  "version": "6.0.8-RC.0",
   "description": "GROWI plugin for presentation",
   "description": "GROWI plugin for presentation",
   "license": "MIT",
   "license": "MIT",
   "keywords": ["growi", "growi-plugin"],
   "keywords": ["growi", "growi-plugin"],
@@ -23,7 +23,7 @@
     "test": ""
     "test": ""
   },
   },
   "dependencies": {
   "dependencies": {
-    "@growi/core": "^6.0.7-RC.0"
+    "@growi/core": "^6.0.8-RC.0"
   },
   },
   "devDependencies": {
   "devDependencies": {
     "@marp-team/marp-core": "^3.4.2",
     "@marp-team/marp-core": "^3.4.2",

+ 1 - 1
packages/preset-themes/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@growi/preset-themes",
   "name": "@growi/preset-themes",
   "description": "GROWI preset themes",
   "description": "GROWI preset themes",
-  "version": "6.0.7-RC.0",
+  "version": "6.0.8-RC.0",
   "license": "MIT",
   "license": "MIT",
   "main": "dist/libs/preset-themes.umd.js",
   "main": "dist/libs/preset-themes.umd.js",
   "module": "dist/libs/preset-themes.mjs",
   "module": "dist/libs/preset-themes.mjs",

+ 1 - 1
packages/remark-drawio/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@growi/remark-drawio",
   "name": "@growi/remark-drawio",
-  "version": "6.0.7-RC.0",
+  "version": "6.0.8-RC.0",
   "description": "remark plugin to draw diagrams with draw.io (diagrams.net)",
   "description": "remark plugin to draw diagrams with draw.io (diagrams.net)",
   "license": "MIT",
   "license": "MIT",
   "keywords": [
   "keywords": [

+ 1 - 1
packages/remark-growi-directive/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@growi/remark-growi-directive",
   "name": "@growi/remark-growi-directive",
-  "version": "6.0.7-RC.0",
+  "version": "6.0.8-RC.0",
   "description": "remark plugin to support GROWI plugin (forked from remark-directive@2.0.1)",
   "description": "remark plugin to support GROWI plugin (forked from remark-directive@2.0.1)",
   "license": "MIT",
   "license": "MIT",
   "keywords": [
   "keywords": [

+ 4 - 4
packages/remark-lsx/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@growi/remark-lsx",
   "name": "@growi/remark-lsx",
-  "version": "6.0.7-RC.0",
+  "version": "6.0.8-RC.0",
   "description": "GROWI plugin to list pages",
   "description": "GROWI plugin to list pages",
   "license": "MIT",
   "license": "MIT",
   "keywords": ["growi", "growi-plugin"],
   "keywords": ["growi", "growi-plugin"],
@@ -20,9 +20,9 @@
     "test": ""
     "test": ""
   },
   },
   "dependencies": {
   "dependencies": {
-    "@growi/core": "^6.0.7-RC.0",
-    "@growi/remark-growi-directive": "^6.0.7-RC.0",
-    "@growi/ui": "^6.0.7-RC.0",
+    "@growi/core": "^6.0.8-RC.0",
+    "@growi/remark-growi-directive": "^6.0.8-RC.0",
+    "@growi/ui": "^6.0.8-RC.0",
     "swr": "^2.0.3"
     "swr": "^2.0.3"
   },
   },
   "devDependencies": {
   "devDependencies": {

+ 1 - 1
packages/slack/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@growi/slack",
   "name": "@growi/slack",
-  "version": "6.0.7-RC.0",
+  "version": "6.0.8-RC.0",
   "license": "MIT",
   "license": "MIT",
   "main": "dist/slack.umd.js",
   "main": "dist/slack.umd.js",
   "module": "dist/slack.mjs",
   "module": "dist/slack.mjs",

+ 2 - 2
packages/ui/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "@growi/ui",
   "name": "@growi/ui",
-  "version": "6.0.7-RC.0",
+  "version": "6.0.8-RC.0",
   "description": "GROWI UI Libraries",
   "description": "GROWI UI Libraries",
   "license": "MIT",
   "license": "MIT",
   "keywords": ["growi"],
   "keywords": ["growi"],
@@ -17,7 +17,7 @@
     "test": "jest --verbose"
     "test": "jest --verbose"
   },
   },
   "dependencies": {
   "dependencies": {
-    "@growi/core": "^6.0.7-RC.0"
+    "@growi/core": "^6.0.8-RC.0"
   },
   },
   "devDependencies": {
   "devDependencies": {
     "eslint-plugin-regex": "^1.8.0",
     "eslint-plugin-regex": "^1.8.0",