@strapi/plugin-users-permissions 0.0.0-next.e3b4cdeebf6e9b0cd5575ff80b8a86715d44ce98 → 0.0.0-next.e61eff51f9834ffdef16bdc236aecab5f837723b

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. package/.eslintignore +2 -2
  2. package/.eslintrc +17 -0
  3. package/LICENSE +18 -3
  4. package/admin/src/components/BoundRoute/{index.js → index.jsx} +7 -5
  5. package/admin/src/components/FormModal/Input/{index.js → index.jsx} +38 -34
  6. package/admin/src/components/FormModal/index.jsx +115 -0
  7. package/admin/src/components/Permissions/PermissionRow/{CheckboxWrapper.js → CheckboxWrapper.jsx} +4 -3
  8. package/admin/src/components/Permissions/PermissionRow/{SubCategory.js → SubCategory.jsx} +27 -15
  9. package/admin/src/components/Permissions/PermissionRow/{index.js → index.jsx} +4 -2
  10. package/admin/src/components/Permissions/index.jsx +47 -0
  11. package/admin/src/components/Permissions/reducer.js +1 -1
  12. package/admin/src/components/Policies/{index.js → index.jsx} +10 -7
  13. package/admin/src/components/UsersPermissions/{index.js → index.jsx} +22 -11
  14. package/admin/src/components/UsersPermissions/reducer.js +1 -1
  15. package/admin/src/{permissions.js → constants.js} +1 -3
  16. package/admin/src/contexts/UsersPermissionsContext/{index.js → index.jsx} +1 -0
  17. package/admin/src/index.js +27 -53
  18. package/admin/src/pages/AdvancedSettings/index.jsx +214 -0
  19. package/admin/src/pages/AdvancedSettings/utils/layout.js +20 -35
  20. package/admin/src/pages/AdvancedSettings/utils/schema.js +5 -2
  21. package/admin/src/pages/EmailTemplates/components/EmailForm.jsx +156 -0
  22. package/admin/src/pages/EmailTemplates/components/{EmailTable.js → EmailTable.jsx} +28 -23
  23. package/admin/src/pages/EmailTemplates/index.jsx +148 -0
  24. package/admin/src/pages/EmailTemplates/utils/schema.js +18 -6
  25. package/admin/src/pages/Providers/index.jsx +262 -0
  26. package/admin/src/pages/Providers/utils/forms.js +23 -11
  27. package/admin/src/pages/Roles/constants.js +7 -0
  28. package/admin/src/pages/Roles/hooks/usePlugins.js +78 -0
  29. package/admin/src/pages/Roles/index.jsx +24 -0
  30. package/admin/src/pages/Roles/pages/CreatePage.jsx +194 -0
  31. package/admin/src/pages/Roles/pages/EditPage.jsx +215 -0
  32. package/admin/src/pages/Roles/pages/ListPage/components/TableBody.jsx +119 -0
  33. package/admin/src/pages/Roles/{ListPage/index.js → pages/ListPage/index.jsx} +108 -83
  34. package/admin/src/pluginId.js +2 -2
  35. package/admin/src/translations/en.json +1 -1
  36. package/admin/src/translations/uk.json +41 -4
  37. package/admin/src/translations/zh-Hans.json +80 -80
  38. package/admin/src/utils/index.js +1 -2
  39. package/admin/src/utils/prefixPluginTranslations.js +13 -0
  40. package/dist/admin/chunks/ar-BJwjobLp.js +45 -0
  41. package/dist/admin/chunks/ar-BJwjobLp.js.map +1 -0
  42. package/dist/admin/chunks/ar-G6bUGuUb.mjs +43 -0
  43. package/dist/admin/chunks/ar-G6bUGuUb.mjs.map +1 -0
  44. package/dist/admin/chunks/cs-Bu59JqhG.mjs +49 -0
  45. package/dist/admin/chunks/cs-Bu59JqhG.mjs.map +1 -0
  46. package/dist/admin/chunks/cs-uS_SIEo8.js +51 -0
  47. package/dist/admin/chunks/cs-uS_SIEo8.js.map +1 -0
  48. package/dist/admin/chunks/de-7MVMrqqI.js +63 -0
  49. package/dist/admin/chunks/de-7MVMrqqI.js.map +1 -0
  50. package/dist/admin/chunks/de-B81A69_5.mjs +61 -0
  51. package/dist/admin/chunks/de-B81A69_5.mjs.map +1 -0
  52. package/dist/admin/chunks/dk-BaelzvBE.mjs +85 -0
  53. package/dist/admin/chunks/dk-BaelzvBE.mjs.map +1 -0
  54. package/dist/admin/chunks/dk-DwCLGmy9.js +87 -0
  55. package/dist/admin/chunks/dk-DwCLGmy9.js.map +1 -0
  56. package/dist/admin/chunks/en-BhgCBe7M.mjs +85 -0
  57. package/dist/admin/chunks/en-BhgCBe7M.mjs.map +1 -0
  58. package/dist/admin/chunks/en-DwQjkHi_.js +87 -0
  59. package/dist/admin/chunks/en-DwQjkHi_.js.map +1 -0
  60. package/dist/admin/chunks/es-B0wXmvRj.mjs +85 -0
  61. package/dist/admin/chunks/es-B0wXmvRj.mjs.map +1 -0
  62. package/dist/admin/chunks/es-BOJOedG5.js +87 -0
  63. package/dist/admin/chunks/es-BOJOedG5.js.map +1 -0
  64. package/dist/admin/chunks/fr-BDNWCNs0.js +51 -0
  65. package/dist/admin/chunks/fr-BDNWCNs0.js.map +1 -0
  66. package/dist/admin/chunks/fr-CGYvGUXg.mjs +49 -0
  67. package/dist/admin/chunks/fr-CGYvGUXg.mjs.map +1 -0
  68. package/dist/admin/chunks/id-CNzbwFjA.mjs +61 -0
  69. package/dist/admin/chunks/id-CNzbwFjA.mjs.map +1 -0
  70. package/dist/admin/chunks/id-UqUPykHZ.js +63 -0
  71. package/dist/admin/chunks/id-UqUPykHZ.js.map +1 -0
  72. package/dist/admin/chunks/index--_o6btSC.js +471 -0
  73. package/dist/admin/chunks/index--_o6btSC.js.map +1 -0
  74. package/dist/admin/chunks/index-BBjNJt_G.mjs +448 -0
  75. package/dist/admin/chunks/index-BBjNJt_G.mjs.map +1 -0
  76. package/dist/admin/chunks/index-BgAfLcWs.mjs +1516 -0
  77. package/dist/admin/chunks/index-BgAfLcWs.mjs.map +1 -0
  78. package/dist/admin/chunks/index-CHTUC0LM.mjs +718 -0
  79. package/dist/admin/chunks/index-CHTUC0LM.mjs.map +1 -0
  80. package/dist/admin/chunks/index-CY5JZ38k.mjs +213 -0
  81. package/dist/admin/chunks/index-CY5JZ38k.mjs.map +1 -0
  82. package/dist/admin/chunks/index-Cu1VuLS3.js +741 -0
  83. package/dist/admin/chunks/index-Cu1VuLS3.js.map +1 -0
  84. package/dist/admin/chunks/index-Cy-tPfRk.mjs +279 -0
  85. package/dist/admin/chunks/index-Cy-tPfRk.mjs.map +1 -0
  86. package/dist/admin/chunks/index-DD-Z6c1S.js +217 -0
  87. package/dist/admin/chunks/index-DD-Z6c1S.js.map +1 -0
  88. package/dist/admin/chunks/index-DFnYIqrB.js +301 -0
  89. package/dist/admin/chunks/index-DFnYIqrB.js.map +1 -0
  90. package/dist/admin/chunks/index-DvubCYNe.js +1537 -0
  91. package/dist/admin/chunks/index-DvubCYNe.js.map +1 -0
  92. package/dist/admin/chunks/it-B2H2foTf.mjs +61 -0
  93. package/dist/admin/chunks/it-B2H2foTf.mjs.map +1 -0
  94. package/dist/admin/chunks/it-D5VuyoLU.js +63 -0
  95. package/dist/admin/chunks/it-D5VuyoLU.js.map +1 -0
  96. package/dist/admin/chunks/ja-C0z9d7L9.mjs +47 -0
  97. package/dist/admin/chunks/ja-C0z9d7L9.mjs.map +1 -0
  98. package/dist/admin/chunks/ja-MpqVsCgs.js +49 -0
  99. package/dist/admin/chunks/ja-MpqVsCgs.js.map +1 -0
  100. package/dist/admin/chunks/ko-Bm-grPSc.js +87 -0
  101. package/dist/admin/chunks/ko-Bm-grPSc.js.map +1 -0
  102. package/dist/admin/chunks/ko-CzUgzpeS.mjs +85 -0
  103. package/dist/admin/chunks/ko-CzUgzpeS.mjs.map +1 -0
  104. package/dist/admin/chunks/ms-CCacxjim.mjs +48 -0
  105. package/dist/admin/chunks/ms-CCacxjim.mjs.map +1 -0
  106. package/dist/admin/chunks/ms-D7eyBD5H.js +50 -0
  107. package/dist/admin/chunks/ms-D7eyBD5H.js.map +1 -0
  108. package/dist/admin/chunks/nl-BIOwAQtI.js +49 -0
  109. package/dist/admin/chunks/nl-BIOwAQtI.js.map +1 -0
  110. package/dist/admin/chunks/nl-DDC3nZW-.mjs +47 -0
  111. package/dist/admin/chunks/nl-DDC3nZW-.mjs.map +1 -0
  112. package/dist/admin/chunks/pl-D5BeNrg_.js +87 -0
  113. package/dist/admin/chunks/pl-D5BeNrg_.js.map +1 -0
  114. package/dist/admin/chunks/pl-XkS463rN.mjs +85 -0
  115. package/dist/admin/chunks/pl-XkS463rN.mjs.map +1 -0
  116. package/dist/admin/chunks/pt-BR-8cC7z8Km.mjs +43 -0
  117. package/dist/admin/chunks/pt-BR-8cC7z8Km.mjs.map +1 -0
  118. package/dist/admin/chunks/pt-BR-DxPBzQGx.js +45 -0
  119. package/dist/admin/chunks/pt-BR-DxPBzQGx.js.map +1 -0
  120. package/dist/admin/chunks/pt-DQpEvio8.mjs +47 -0
  121. package/dist/admin/chunks/pt-DQpEvio8.mjs.map +1 -0
  122. package/dist/admin/chunks/pt-kkCwzNvH.js +49 -0
  123. package/dist/admin/chunks/pt-kkCwzNvH.js.map +1 -0
  124. package/dist/admin/chunks/ru-BQ0gHmp3.js +87 -0
  125. package/dist/admin/chunks/ru-BQ0gHmp3.js.map +1 -0
  126. package/dist/admin/chunks/ru-nzL_7Mhg.mjs +85 -0
  127. package/dist/admin/chunks/ru-nzL_7Mhg.mjs.map +1 -0
  128. package/dist/admin/chunks/sk-Ddxc_tZA.mjs +49 -0
  129. package/dist/admin/chunks/sk-Ddxc_tZA.mjs.map +1 -0
  130. package/dist/admin/chunks/sk-nVwAPdYC.js +51 -0
  131. package/dist/admin/chunks/sk-nVwAPdYC.js.map +1 -0
  132. package/dist/admin/chunks/sv-BDfk2A-F.js +87 -0
  133. package/dist/admin/chunks/sv-BDfk2A-F.js.map +1 -0
  134. package/dist/admin/chunks/sv-By3RYpMG.mjs +85 -0
  135. package/dist/admin/chunks/sv-By3RYpMG.mjs.map +1 -0
  136. package/dist/admin/chunks/th-BtTtpHe2.js +61 -0
  137. package/dist/admin/chunks/th-BtTtpHe2.js.map +1 -0
  138. package/dist/admin/chunks/th-COl50vqb.mjs +59 -0
  139. package/dist/admin/chunks/th-COl50vqb.mjs.map +1 -0
  140. package/dist/admin/chunks/tr-80SJU6jg.mjs +84 -0
  141. package/dist/admin/chunks/tr-80SJU6jg.mjs.map +1 -0
  142. package/dist/admin/chunks/tr-Di-Nf7cT.js +86 -0
  143. package/dist/admin/chunks/tr-Di-Nf7cT.js.map +1 -0
  144. package/dist/admin/chunks/uk-DnrIlPwG.mjs +85 -0
  145. package/dist/admin/chunks/uk-DnrIlPwG.mjs.map +1 -0
  146. package/dist/admin/chunks/uk-r5zXTAS7.js +87 -0
  147. package/dist/admin/chunks/uk-r5zXTAS7.js.map +1 -0
  148. package/dist/admin/chunks/vi-69AF03Iv.mjs +49 -0
  149. package/dist/admin/chunks/vi-69AF03Iv.mjs.map +1 -0
  150. package/dist/admin/chunks/vi-D9cCsHsU.js +51 -0
  151. package/dist/admin/chunks/vi-D9cCsHsU.js.map +1 -0
  152. package/dist/admin/chunks/zh-BzSkqxo-.mjs +85 -0
  153. package/dist/admin/chunks/zh-BzSkqxo-.mjs.map +1 -0
  154. package/dist/admin/chunks/zh-BzWgJEzz.js +87 -0
  155. package/dist/admin/chunks/zh-BzWgJEzz.js.map +1 -0
  156. package/dist/admin/chunks/zh-Hans-CKqQbpsM.js +87 -0
  157. package/dist/admin/chunks/zh-Hans-CKqQbpsM.js.map +1 -0
  158. package/dist/admin/chunks/zh-Hans-DmDcSsp7.mjs +85 -0
  159. package/dist/admin/chunks/zh-Hans-DmDcSsp7.mjs.map +1 -0
  160. package/dist/admin/index.js +8 -0
  161. package/dist/admin/index.js.map +1 -0
  162. package/dist/admin/index.mjs +2 -0
  163. package/dist/admin/index.mjs.map +1 -0
  164. package/dist/server/index.js +4766 -0
  165. package/dist/server/index.js.map +1 -0
  166. package/dist/server/index.mjs +4764 -0
  167. package/dist/server/index.mjs.map +1 -0
  168. package/documentation/content-api.yaml +1 -1
  169. package/jest.config.front.js +1 -0
  170. package/package.json +53 -37
  171. package/rollup.config.mjs +52 -0
  172. package/server/bootstrap/index.js +18 -15
  173. package/server/bootstrap/users-permissions-actions.js +6 -0
  174. package/server/config.js +29 -0
  175. package/server/content-types/user/index.js +0 -1
  176. package/server/controllers/auth.js +75 -39
  177. package/server/controllers/content-manager-user.js +28 -30
  178. package/server/controllers/role.js +17 -4
  179. package/server/controllers/user.js +18 -8
  180. package/server/controllers/validation/auth.js +104 -25
  181. package/server/graphql/types/index.js +1 -0
  182. package/server/graphql/types/me.js +1 -0
  183. package/server/graphql/types/user-input.js +20 -0
  184. package/server/middlewares/rateLimit.js +41 -21
  185. package/server/register.js +2 -2
  186. package/server/services/jwt.js +3 -3
  187. package/server/services/permission.js +3 -7
  188. package/server/services/providers-registry.js +469 -261
  189. package/server/services/providers.js +10 -5
  190. package/server/services/role.js +15 -13
  191. package/server/services/user.js +56 -19
  192. package/server/services/users-permissions.js +15 -13
  193. package/server/strategies/users-permissions.js +1 -8
  194. package/server/utils/index.d.ts +2 -1
  195. package/server/utils/sanitize/sanitizers.js +7 -3
  196. package/server/utils/sanitize/visitors/remove-user-relation-from-role-entities.js +2 -2
  197. package/.eslintrc.js +0 -14
  198. package/admin/src/components/FormModal/index.js +0 -123
  199. package/admin/src/components/Permissions/index.js +0 -54
  200. package/admin/src/hooks/index.js +0 -5
  201. package/admin/src/hooks/useFetchRole/index.js +0 -64
  202. package/admin/src/hooks/useFetchRole/reducer.js +0 -31
  203. package/admin/src/hooks/useForm/index.js +0 -67
  204. package/admin/src/hooks/useForm/reducer.js +0 -40
  205. package/admin/src/hooks/usePlugins/index.js +0 -67
  206. package/admin/src/hooks/usePlugins/init.js +0 -5
  207. package/admin/src/hooks/usePlugins/reducer.js +0 -34
  208. package/admin/src/hooks/useRolesList/index.js +0 -62
  209. package/admin/src/hooks/useRolesList/init.js +0 -5
  210. package/admin/src/hooks/useRolesList/reducer.js +0 -31
  211. package/admin/src/pages/AdvancedSettings/index.js +0 -243
  212. package/admin/src/pages/AdvancedSettings/utils/api.js +0 -17
  213. package/admin/src/pages/EmailTemplates/components/EmailForm.js +0 -175
  214. package/admin/src/pages/EmailTemplates/index.js +0 -160
  215. package/admin/src/pages/EmailTemplates/utils/api.js +0 -17
  216. package/admin/src/pages/Providers/index.js +0 -272
  217. package/admin/src/pages/Providers/reducer.js +0 -54
  218. package/admin/src/pages/Providers/utils/api.js +0 -25
  219. package/admin/src/pages/Providers/utils/createProvidersArray.js +0 -21
  220. package/admin/src/pages/Roles/CreatePage/index.js +0 -182
  221. package/admin/src/pages/Roles/CreatePage/utils/schema.js +0 -9
  222. package/admin/src/pages/Roles/EditPage/index.js +0 -194
  223. package/admin/src/pages/Roles/EditPage/utils/schema.js +0 -9
  224. package/admin/src/pages/Roles/ListPage/components/TableBody.js +0 -92
  225. package/admin/src/pages/Roles/ListPage/utils/api.js +0 -31
  226. package/admin/src/pages/Roles/ProtectedCreatePage/index.js +0 -12
  227. package/admin/src/pages/Roles/ProtectedEditPage/index.js +0 -12
  228. package/admin/src/pages/Roles/ProtectedListPage/index.js +0 -15
  229. package/admin/src/pages/Roles/index.js +0 -27
  230. package/admin/src/utils/getRequestURL.js +0 -5
  231. package/server/bootstrap/grant-config.js +0 -131
  232. package/strapi-admin.js +0 -3
  233. package/strapi-server.js +0 -3
@@ -93,7 +93,7 @@ paths:
93
93
  required: true
94
94
  responses:
95
95
  200:
96
- description: Successfull registration
96
+ description: Successful registration
97
97
  content:
98
98
  application/json:
99
99
  schema:
@@ -3,4 +3,5 @@
3
3
  module.exports = {
4
4
  preset: '../../../jest-preset.front.js',
5
5
  displayName: 'Users & Permissions plugin',
6
+ setupFilesAfterEnv: ['./admin/src/tests/setup.js'],
6
7
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/plugin-users-permissions",
3
- "version": "0.0.0-next.e3b4cdeebf6e9b0cd5575ff80b8a86715d44ce98",
3
+ "version": "0.0.0-next.e61eff51f9834ffdef16bdc236aecab5f837723b",
4
4
  "description": "Protect your API with a full-authentication process based on JWT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -19,58 +19,75 @@
19
19
  "url": "https://strapi.io"
20
20
  }
21
21
  ],
22
+ "exports": {
23
+ "./strapi-admin": {
24
+ "source": "./admin/src/index.js",
25
+ "import": "./dist/admin/index.mjs",
26
+ "require": "./dist/admin/index.js",
27
+ "default": "./dist/admin/index.js"
28
+ },
29
+ "./strapi-server": {
30
+ "source": "./server/index.js",
31
+ "import": "./dist/server/index.mjs",
32
+ "require": "./dist/server/index.js",
33
+ "default": "./dist/server/index.js"
34
+ },
35
+ "./package.json": "./package.json"
36
+ },
22
37
  "scripts": {
23
- "test:unit": "run -T jest",
24
- "test:unit:watch": "run -T jest --watch",
38
+ "build": "run -T npm-run-all clean build:code",
39
+ "build:code": "run -T rollup -c",
40
+ "clean": "run -T rimraf dist",
41
+ "lint": "run -T eslint .",
25
42
  "test:front": "run -T cross-env IS_EE=true jest --config ./jest.config.front.js",
26
- "test:front:watch": "run -T cross-env IS_EE=true jest --config ./jest.config.front.js --watchAll",
27
43
  "test:front:ce": "run -T cross-env IS_EE=false jest --config ./jest.config.front.js",
44
+ "test:front:watch": "run -T cross-env IS_EE=true jest --config ./jest.config.front.js --watchAll",
28
45
  "test:front:watch:ce": "run -T cross-env IS_EE=false jest --config ./jest.config.front.js --watchAll",
29
- "lint": "run -T eslint ."
46
+ "test:unit": "run -T jest",
47
+ "test:unit:watch": "run -T jest --watch",
48
+ "watch": "run -T rollup -c -w"
30
49
  },
31
50
  "dependencies": {
32
- "@strapi/design-system": "1.7.5",
33
- "@strapi/helper-plugin": "0.0.0-next.e3b4cdeebf6e9b0cd5575ff80b8a86715d44ce98",
34
- "@strapi/icons": "1.7.5",
35
- "@strapi/utils": "0.0.0-next.e3b4cdeebf6e9b0cd5575ff80b8a86715d44ce98",
51
+ "@strapi/design-system": "2.0.0-rc.18",
52
+ "@strapi/icons": "2.0.0-rc.18",
53
+ "@strapi/utils": "0.0.0-next.e61eff51f9834ffdef16bdc236aecab5f837723b",
36
54
  "bcryptjs": "2.4.3",
37
- "formik": "2.2.9",
38
- "grant-koa": "5.4.8",
39
- "immer": "9.0.19",
55
+ "formik": "2.4.5",
56
+ "grant": "^5.4.8",
57
+ "immer": "9.0.21",
40
58
  "jsonwebtoken": "9.0.0",
41
59
  "jwk-to-pem": "2.0.5",
42
- "koa": "^2.13.4",
43
- "koa2-ratelimit": "^1.1.2",
60
+ "koa": "2.15.2",
61
+ "koa2-ratelimit": "^1.1.3",
44
62
  "lodash": "4.17.21",
45
- "prop-types": "^15.7.2",
63
+ "prop-types": "^15.8.1",
46
64
  "purest": "4.0.2",
47
- "react-intl": "6.4.1",
48
- "react-query": "3.24.3",
49
- "react-redux": "8.0.5",
65
+ "react-intl": "6.6.2",
66
+ "react-query": "3.39.3",
67
+ "react-redux": "8.1.3",
50
68
  "url-join": "4.0.1",
51
- "yup": "^0.32.9"
69
+ "yup": "0.32.9"
52
70
  },
53
71
  "devDependencies": {
54
- "@testing-library/dom": "8.19.0",
55
- "@testing-library/react": "12.1.4",
56
- "@testing-library/react-hooks": "8.0.1",
57
- "@testing-library/user-event": "14.4.3",
58
- "history": "^4.9.0",
59
- "msw": "1.2.1",
60
- "react": "^17.0.2",
61
- "react-dom": "^17.0.2",
62
- "react-router-dom": "5.3.4",
63
- "react-test-renderer": "^17.0.2",
64
- "styled-components": "5.3.3"
72
+ "@strapi/strapi": "0.0.0-next.e61eff51f9834ffdef16bdc236aecab5f837723b",
73
+ "@testing-library/dom": "10.1.0",
74
+ "@testing-library/react": "15.0.7",
75
+ "@testing-library/user-event": "14.5.2",
76
+ "msw": "1.3.0",
77
+ "react": "18.3.1",
78
+ "react-dom": "18.3.1",
79
+ "react-router-dom": "6.22.3",
80
+ "styled-components": "6.1.8"
65
81
  },
66
82
  "peerDependencies": {
67
- "react": "^17.0.2",
68
- "react-dom": "^17.0.2",
69
- "react-router-dom": "^5.3.4",
70
- "styled-components": "^5.3.3"
83
+ "@strapi/strapi": "^5.0.0",
84
+ "react": "^17.0.0 || ^18.0.0",
85
+ "react-dom": "^17.0.0 || ^18.0.0",
86
+ "react-router-dom": "^6.0.0",
87
+ "styled-components": "^6.0.0"
71
88
  },
72
89
  "engines": {
73
- "node": ">=14.19.1 <=18.x.x",
90
+ "node": ">=18.0.0 <=22.x.x",
74
91
  "npm": ">=6.0.0"
75
92
  },
76
93
  "strapi": {
@@ -79,6 +96,5 @@
79
96
  "description": "Protect your API with a full authentication process based on JWT. This plugin comes also with an ACL strategy that allows you to manage the permissions between the groups of users.",
80
97
  "required": true,
81
98
  "kind": "plugin"
82
- },
83
- "gitHead": "e3b4cdeebf6e9b0cd5575ff80b8a86715d44ce98"
99
+ }
84
100
  }
@@ -0,0 +1,52 @@
1
+ import { defineConfig } from 'rollup';
2
+ import path from 'path';
3
+ import { basePlugins } from '../../../rollup.utils.mjs';
4
+
5
+ export default defineConfig([
6
+ {
7
+ input: path.join(import.meta.dirname, 'admin/src/index.js'),
8
+ external: (id) => !path.isAbsolute(id) && !id.startsWith('.'),
9
+ output: [
10
+ {
11
+ dir: path.join(import.meta.dirname, 'dist/admin'),
12
+ entryFileNames: '[name].js',
13
+ chunkFileNames: 'chunks/[name]-[hash].js',
14
+ exports: 'auto',
15
+ format: 'cjs',
16
+ sourcemap: true,
17
+ },
18
+ {
19
+ dir: path.join(import.meta.dirname, 'dist/admin'),
20
+ entryFileNames: '[name].mjs',
21
+ chunkFileNames: 'chunks/[name]-[hash].mjs',
22
+ exports: 'auto',
23
+ format: 'esm',
24
+ sourcemap: true,
25
+ },
26
+ ],
27
+ plugins: [...basePlugins(import.meta.dirname)],
28
+ },
29
+ {
30
+ input: path.join(import.meta.dirname, 'server/index.js'),
31
+ external: (id) => !path.isAbsolute(id) && !id.startsWith('.'),
32
+ output: [
33
+ {
34
+ dir: path.join(import.meta.dirname, 'dist/server'),
35
+ entryFileNames: '[name].js',
36
+ chunkFileNames: 'chunks/[name]-[hash].js',
37
+ exports: 'auto',
38
+ format: 'cjs',
39
+ sourcemap: true,
40
+ },
41
+ {
42
+ dir: path.join(import.meta.dirname, 'dist/server'),
43
+ entryFileNames: '[name].mjs',
44
+ chunkFileNames: 'chunks/[name]-[hash].mjs',
45
+ exports: 'auto',
46
+ format: 'esm',
47
+ sourcemap: true,
48
+ },
49
+ ],
50
+ plugins: [...basePlugins(import.meta.dirname)],
51
+ },
52
+ ]);
@@ -9,23 +9,26 @@
9
9
  */
10
10
  const crypto = require('crypto');
11
11
  const _ = require('lodash');
12
- const urljoin = require('url-join');
13
12
  const { getService } = require('../utils');
14
- const getGrantConfig = require('./grant-config');
15
-
16
13
  const usersPermissionsActions = require('./users-permissions-actions');
17
14
 
18
15
  const initGrant = async (pluginStore) => {
19
- const apiPrefix = strapi.config.get('api.rest.prefix');
20
- const baseURL = urljoin(strapi.config.server.url, apiPrefix, 'auth');
16
+ const allProviders = getService('providers-registry').getAll();
17
+
18
+ const grantConfig = Object.entries(allProviders).reduce((acc, [name, provider]) => {
19
+ const { icon, enabled, grantConfig } = provider;
21
20
 
22
- const grantConfig = getGrantConfig(baseURL);
21
+ acc[name] = {
22
+ icon,
23
+ enabled,
24
+ ...grantConfig,
25
+ };
26
+ return acc;
27
+ }, {});
23
28
 
24
29
  const prevGrantConfig = (await pluginStore.get({ key: 'grant' })) || {};
25
- // store grant auth config to db
26
- // when plugin_users-permissions_grant is not existed in db
27
- // or we have added/deleted provider here.
28
- if (!prevGrantConfig || !_.isEqual(_.keys(prevGrantConfig), _.keys(grantConfig))) {
30
+
31
+ if (!prevGrantConfig || !_.isEqual(prevGrantConfig, grantConfig)) {
29
32
  // merge with the previous provider config.
30
33
  _.keys(grantConfig).forEach((key) => {
31
34
  if (key in prevGrantConfig) {
@@ -104,13 +107,13 @@ module.exports = async ({ strapi }) => {
104
107
  await initEmails(pluginStore);
105
108
  await initAdvancedOptions(pluginStore);
106
109
 
107
- await strapi.admin.services.permission.actionProvider.registerMany(
108
- usersPermissionsActions.actions
109
- );
110
+ await strapi
111
+ .service('admin::permission')
112
+ .actionProvider.registerMany(usersPermissionsActions.actions);
110
113
 
111
114
  await getService('users-permissions').initialize();
112
115
 
113
- if (!strapi.config.get('plugin.users-permissions.jwtSecret')) {
116
+ if (!strapi.config.get('plugin::users-permissions.jwtSecret')) {
114
117
  if (process.env.NODE_ENV !== 'development') {
115
118
  throw new Error(
116
119
  `Missing jwtSecret. Please, set configuration variable "jwtSecret" for the users-permissions plugin in config/plugins.js (ex: you can generate one using Node with \`crypto.randomBytes(16).toString('base64')\`).
@@ -120,7 +123,7 @@ For security reasons, prefer storing the secret in an environment variable and r
120
123
 
121
124
  const jwtSecret = crypto.randomBytes(16).toString('base64');
122
125
 
123
- strapi.config.set('plugin.users-permissions.jwtSecret', jwtSecret);
126
+ strapi.config.set('plugin::users-permissions.jwtSecret', jwtSecret);
124
127
 
125
128
  if (!process.env.JWT_SECRET) {
126
129
  const envPath = process.env.ENV_PATH || '.env';
@@ -16,6 +16,12 @@ module.exports = {
16
16
  uid: 'roles.read',
17
17
  subCategory: 'roles',
18
18
  pluginName: 'users-permissions',
19
+ aliases: [
20
+ {
21
+ actionId: 'plugin::content-manager.explorer.read',
22
+ subjects: ['plugin::users-permissions.role'],
23
+ },
24
+ ],
19
25
  },
20
26
  {
21
27
  section: 'plugins',
package/server/config.js CHANGED
@@ -18,6 +18,35 @@ module.exports = {
18
18
  },
19
19
  },
20
20
  },
21
+ callback: {
22
+ validate(callback, provider) {
23
+ let uCallback;
24
+ let uProviderCallback;
25
+
26
+ try {
27
+ uCallback = new URL(callback);
28
+ uProviderCallback = new URL(provider.callback);
29
+ } catch {
30
+ throw new Error('The callback is not a valid URL');
31
+ }
32
+
33
+ // Make sure the different origin matches
34
+ if (uCallback.origin !== uProviderCallback.origin) {
35
+ throw new Error(
36
+ `Forbidden callback provided: origins don't match. Please verify your config.`
37
+ );
38
+ }
39
+
40
+ // Make sure the different pathname matches
41
+ if (uCallback.pathname !== uProviderCallback.pathname) {
42
+ throw new Error(
43
+ `Forbidden callback provided: pathname don't match. Please verify your config.`
44
+ );
45
+ }
46
+
47
+ // NOTE: We're not checking the search parameters on purpose to allow passing different states
48
+ },
49
+ },
21
50
  }),
22
51
  validator() {},
23
52
  };
@@ -12,7 +12,6 @@ module.exports = {
12
12
  displayName: 'User',
13
13
  },
14
14
  options: {
15
- draftAndPublish: false,
16
15
  timestamps: true,
17
16
  },
18
17
  attributes: {
@@ -9,6 +9,7 @@
9
9
  /* eslint-disable no-useless-escape */
10
10
  const crypto = require('crypto');
11
11
  const _ = require('lodash');
12
+ const { concat, compact, isArray } = require('lodash/fp');
12
13
  const utils = require('@strapi/utils');
13
14
  const { getService } = require('../utils');
14
15
  const {
@@ -21,17 +22,16 @@ const {
21
22
  validateChangePasswordBody,
22
23
  } = require('./validation/auth');
23
24
 
24
- const { getAbsoluteAdminUrl, getAbsoluteServerUrl, sanitize } = utils;
25
- const { ApplicationError, ValidationError } = utils.errors;
25
+ const { ApplicationError, ValidationError, ForbiddenError } = utils.errors;
26
26
 
27
27
  const sanitizeUser = (user, ctx) => {
28
28
  const { auth } = ctx.state;
29
29
  const userSchema = strapi.getModel('plugin::users-permissions.user');
30
30
 
31
- return sanitize.contentAPI.output(user, userSchema, { auth });
31
+ return strapi.contentAPI.sanitize.output(user, userSchema, { auth });
32
32
  };
33
33
 
34
- module.exports = {
34
+ module.exports = ({ strapi }) => ({
35
35
  async callback(ctx) {
36
36
  const provider = ctx.params.provider || 'local';
37
37
  const params = ctx.request.body;
@@ -51,7 +51,7 @@ module.exports = {
51
51
  const { identifier } = params;
52
52
 
53
53
  // Check if the user exists.
54
- const user = await strapi.query('plugin::users-permissions.user').findOne({
54
+ const user = await strapi.db.query('plugin::users-permissions.user').findOne({
55
55
  where: {
56
56
  provider,
57
57
  $or: [{ email: identifier.toLowerCase() }, { username: identifier }],
@@ -96,6 +96,10 @@ module.exports = {
96
96
  try {
97
97
  const user = await getService('providers').connect(provider, ctx.query);
98
98
 
99
+ if (user.blocked) {
100
+ throw new ForbiddenError('Your account has been blocked by an administrator');
101
+ }
102
+
99
103
  return ctx.send({
100
104
  jwt: getService('jwt').issue({ id: user.id }),
101
105
  user: await sanitizeUser(user, ctx),
@@ -110,13 +114,17 @@ module.exports = {
110
114
  throw new ApplicationError('You must be authenticated to reset your password');
111
115
  }
112
116
 
113
- const { currentPassword, password } = await validateChangePasswordBody(ctx.request.body);
117
+ const validations = strapi.config.get('plugin::users-permissions.validationRules');
114
118
 
115
- const user = await strapi.entityService.findOne(
116
- 'plugin::users-permissions.user',
117
- ctx.state.user.id
119
+ const { currentPassword, password } = await validateChangePasswordBody(
120
+ ctx.request.body,
121
+ validations
118
122
  );
119
123
 
124
+ const user = await strapi.db
125
+ .query('plugin::users-permissions.user')
126
+ .findOne({ where: { id: ctx.state.user.id } });
127
+
120
128
  const validPassword = await getService('user').validatePassword(currentPassword, user.password);
121
129
 
122
130
  if (!validPassword) {
@@ -136,15 +144,18 @@ module.exports = {
136
144
  },
137
145
 
138
146
  async resetPassword(ctx) {
147
+ const validations = strapi.config.get('plugin::users-permissions.validationRules');
148
+
139
149
  const { password, passwordConfirmation, code } = await validateResetPasswordBody(
140
- ctx.request.body
150
+ ctx.request.body,
151
+ validations
141
152
  );
142
153
 
143
154
  if (password !== passwordConfirmation) {
144
155
  throw new ValidationError('Passwords do not match');
145
156
  }
146
157
 
147
- const user = await strapi
158
+ const user = await strapi.db
148
159
  .query('plugin::users-permissions.user')
149
160
  .findOne({ where: { resetPasswordToken: code } });
150
161
 
@@ -165,7 +176,7 @@ module.exports = {
165
176
  },
166
177
 
167
178
  async connect(ctx, next) {
168
- const grant = require('grant-koa');
179
+ const grant = require('grant').koa();
169
180
 
170
181
  const providers = await strapi
171
182
  .store({ type: 'plugin', name: 'users-permissions', key: 'grant' })
@@ -193,10 +204,28 @@ module.exports = {
193
204
  }
194
205
 
195
206
  // Ability to pass OAuth callback dynamically
196
- grantConfig[provider].callback =
197
- _.get(ctx, 'query.callback') ||
198
- _.get(ctx, 'session.grant.dynamic.callback') ||
199
- grantConfig[provider].callback;
207
+ const queryCustomCallback = _.get(ctx, 'query.callback');
208
+ const dynamicSessionCallback = _.get(ctx, 'session.grant.dynamic.callback');
209
+
210
+ const customCallback = queryCustomCallback ?? dynamicSessionCallback;
211
+
212
+ // The custom callback is validated to make sure it's not redirecting to an unwanted actor.
213
+ if (customCallback !== undefined) {
214
+ try {
215
+ // We're extracting the callback validator from the plugin config since it can be user-customized
216
+ const { validate: validateCallback } = strapi
217
+ .plugin('users-permissions')
218
+ .config('callback');
219
+
220
+ await validateCallback(customCallback, grantConfig[provider]);
221
+
222
+ grantConfig[provider].callback = customCallback;
223
+ } catch (e) {
224
+ throw new ValidationError('Invalid callback URL provided', { callback: customCallback });
225
+ }
226
+ }
227
+
228
+ // Build a valid redirect URI for the current provider
200
229
  grantConfig[provider].redirect_uri = getService('providers').buildRedirectUri(provider);
201
230
 
202
231
  return grant(grantConfig)(ctx, next);
@@ -211,7 +240,7 @@ module.exports = {
211
240
  const advancedSettings = await pluginStore.get({ key: 'advanced' });
212
241
 
213
242
  // Find the user by email.
214
- const user = await strapi
243
+ const user = await strapi.db
215
244
  .query('plugin::users-permissions.user')
216
245
  .findOne({ where: { email: email.toLowerCase() } });
217
246
 
@@ -229,8 +258,8 @@ module.exports = {
229
258
  resetPasswordSettings.message,
230
259
  {
231
260
  URL: advancedSettings.email_reset_password,
232
- SERVER_URL: getAbsoluteServerUrl(strapi.config),
233
- ADMIN_URL: getAbsoluteAdminUrl(strapi.config),
261
+ SERVER_URL: strapi.config.get('server.absoluteUrl'),
262
+ ADMIN_URL: strapi.config.get('admin.absoluteUrl'),
234
263
  USER: userInfo,
235
264
  TOKEN: resetPasswordToken,
236
265
  }
@@ -273,26 +302,32 @@ module.exports = {
273
302
  throw new ApplicationError('Register action is currently disabled');
274
303
  }
275
304
 
305
+ const { register } = strapi.config.get('plugin::users-permissions');
306
+ const alwaysAllowedKeys = ['username', 'password', 'email'];
307
+
308
+ // Note that we intentionally do not filter allowedFields to allow a project to explicitly accept private or other Strapi field on registration
309
+ const allowedKeys = compact(
310
+ concat(alwaysAllowedKeys, isArray(register?.allowedFields) ? register.allowedFields : [])
311
+ );
312
+
313
+ // Check if there are any keys in requestBody that are not in allowedKeys
314
+ const invalidKeys = Object.keys(ctx.request.body).filter((key) => !allowedKeys.includes(key));
315
+
316
+ if (invalidKeys.length > 0) {
317
+ // If there are invalid keys, throw an error
318
+ throw new ValidationError(`Invalid parameters: ${invalidKeys.join(', ')}`);
319
+ }
320
+
276
321
  const params = {
277
- ..._.omit(ctx.request.body, [
278
- 'confirmed',
279
- 'blocked',
280
- 'confirmationToken',
281
- 'resetPasswordToken',
282
- 'provider',
283
- 'id',
284
- 'createdAt',
285
- 'updatedAt',
286
- 'createdBy',
287
- 'updatedBy',
288
- 'role',
289
- ]),
322
+ ..._.pick(ctx.request.body, allowedKeys),
290
323
  provider: 'local',
291
324
  };
292
325
 
293
- await validateRegisterBody(params);
326
+ const validations = strapi.config.get('plugin::users-permissions.validationRules');
294
327
 
295
- const role = await strapi
328
+ await validateRegisterBody(params, validations);
329
+
330
+ const role = await strapi.db
296
331
  .query('plugin::users-permissions.role')
297
332
  .findOne({ where: { type: settings.default_role } });
298
333
 
@@ -311,7 +346,7 @@ module.exports = {
311
346
  ],
312
347
  };
313
348
 
314
- const conflictingUserCount = await strapi.query('plugin::users-permissions.user').count({
349
+ const conflictingUserCount = await strapi.db.query('plugin::users-permissions.user').count({
315
350
  where: { ...identifierFilter, provider },
316
351
  });
317
352
 
@@ -320,7 +355,7 @@ module.exports = {
320
355
  }
321
356
 
322
357
  if (settings.unique_email) {
323
- const conflictingUserCount = await strapi.query('plugin::users-permissions.user').count({
358
+ const conflictingUserCount = await strapi.db.query('plugin::users-permissions.user').count({
324
359
  where: { ...identifierFilter },
325
360
  });
326
361
 
@@ -345,7 +380,8 @@ module.exports = {
345
380
  try {
346
381
  await getService('user').sendConfirmationEmail(sanitizedUser);
347
382
  } catch (err) {
348
- throw new ApplicationError(err.message);
383
+ strapi.log.error(err);
384
+ throw new ApplicationError('Error sending confirmation email');
349
385
  }
350
386
 
351
387
  return ctx.send({ user: sanitizedUser });
@@ -390,7 +426,7 @@ module.exports = {
390
426
  async sendEmailConfirmation(ctx) {
391
427
  const { email } = await validateSendEmailConfirmationBody(ctx.request.body);
392
428
 
393
- const user = await strapi.query('plugin::users-permissions.user').findOne({
429
+ const user = await strapi.db.query('plugin::users-permissions.user').findOne({
394
430
  where: { email: email.toLowerCase() },
395
431
  });
396
432
 
@@ -413,4 +449,4 @@ module.exports = {
413
449
  sent: true,
414
450
  });
415
451
  },
416
- };
452
+ });