@strapi/admin 4.7.2-exp.175f7ac70ee76d6c825e4429e15fc85ee78d23bb → 4.8.0

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 (171) hide show
  1. package/admin/src/content-manager/components/ComponentInitializer/index.js +1 -1
  2. package/admin/src/content-manager/components/EditViewDataManagerProvider/index.js +3 -31
  3. package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +65 -134
  4. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/findAllAndReplace.js +85 -0
  5. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/index.js +1 -2
  6. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/schema.js +7 -1
  7. package/admin/src/content-manager/components/NonRepeatableComponent/index.js +1 -1
  8. package/admin/src/content-manager/components/RelationInput/RelationInput.js +1 -2
  9. package/admin/src/content-manager/components/RelationInputDataManager/RelationInputDataManager.js +39 -33
  10. package/admin/src/content-manager/hooks/useRelation/useRelation.js +2 -2
  11. package/admin/src/content-manager/pages/EditView/Header/index.js +1 -1
  12. package/admin/src/content-manager/utils/createDefaultForm.js +0 -8
  13. package/admin/src/pages/AuthPage/components/Register/index.js +1 -1
  14. package/admin/src/pages/SettingsPage/components/Tokens/FormHead/index.js +1 -0
  15. package/admin/src/pages/SettingsPage/components/Tokens/Table/index.js +2 -2
  16. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/schema.js +1 -1
  17. package/admin/src/pages/SettingsPage/pages/Roles/CreatePage/index.js +266 -4
  18. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ConditionsModal/ActionRow/index.js +1 -2
  19. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/Collapse/index.js +2 -3
  20. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/CollapsePropertyMatrix/ActionRow/index.js +2 -3
  21. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/CollapsePropertyMatrix/SubActionRow/index.js +2 -3
  22. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/GlobalActions/index.js +9 -4
  23. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/PluginsAndSettings/SubCategory/index.js +3 -7
  24. package/admin/src/pages/SettingsPage/pages/Roles/ListPage/index.js +303 -124
  25. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/schema.js +1 -1
  26. package/admin/src/pages/SettingsPage/utils/defaultRoutes.js +18 -10
  27. package/admin/src/translations/ca.json +7 -13
  28. package/admin/src/translations/de.json +0 -6
  29. package/admin/src/translations/dk.json +0 -6
  30. package/admin/src/translations/en.json +0 -6
  31. package/admin/src/translations/es.json +0 -6
  32. package/admin/src/translations/eu.json +165 -171
  33. package/admin/src/translations/fr.json +0 -6
  34. package/admin/src/translations/gu.json +0 -6
  35. package/admin/src/translations/he.json +0 -6
  36. package/admin/src/translations/hi.json +0 -6
  37. package/admin/src/translations/hu.json +0 -6
  38. package/admin/src/translations/id.json +0 -6
  39. package/admin/src/translations/it.json +0 -6
  40. package/admin/src/translations/ja.json +0 -6
  41. package/admin/src/translations/ko.json +0 -6
  42. package/admin/src/translations/ml.json +0 -6
  43. package/admin/src/translations/nl.json +0 -6
  44. package/admin/src/translations/no.json +0 -6
  45. package/admin/src/translations/pl.json +0 -6
  46. package/admin/src/translations/pt-BR.json +0 -6
  47. package/admin/src/translations/ru.json +0 -6
  48. package/admin/src/translations/sa.json +0 -6
  49. package/admin/src/translations/sk.json +0 -6
  50. package/admin/src/translations/sv.json +0 -6
  51. package/admin/src/translations/th.json +0 -6
  52. package/admin/src/translations/tr.json +0 -6
  53. package/admin/src/translations/zh-Hans.json +0 -6
  54. package/admin/src/translations/zh.json +0 -6
  55. package/build/{4649.daa290f6.chunk.js → 4649.33220ac3.chunk.js} +2 -2
  56. package/build/{6891.ef7464be.chunk.js → 7112.2bf13da3.chunk.js} +6 -6
  57. package/build/7259.3675c199.chunk.js +1 -0
  58. package/build/{3094.1cac9087.chunk.js → 8580.0aa21940.chunk.js} +5 -5
  59. package/build/{Admin-authenticatedApp.25bdcdc0.chunk.js → Admin-authenticatedApp.5abacdd4.chunk.js} +4 -4
  60. package/build/Admin_settingsPage.caf3b9ab.chunk.js +9 -0
  61. package/build/{admin-app.d9d96db4.chunk.js → admin-app.4b313104.chunk.js} +2 -2
  62. package/build/admin-edit-roles-page.3b196317.chunk.js +216 -0
  63. package/build/{admin-edit-users.48031e30.chunk.js → admin-edit-users.af3b0f15.chunk.js} +1 -1
  64. package/build/admin-roles-list.0ad504a7.chunk.js +2 -0
  65. package/build/{admin-users.77b4188a.chunk.js → admin-users.af8c3123.chunk.js} +1 -1
  66. package/build/api-tokens-list-page.93f24348.chunk.js +16 -0
  67. package/build/ca-json.43e14418.chunk.js +1 -0
  68. package/build/content-manager.84afc839.chunk.js +1139 -0
  69. package/build/{content-type-builder.cdd117c3.chunk.js → content-type-builder.55dac849.chunk.js} +1 -1
  70. package/build/de-json.fcac7381.chunk.js +1 -0
  71. package/build/dk-json.e34cad0d.chunk.js +1 -0
  72. package/build/{en-json.e688dfe2.chunk.js → en-json.01a88a30.chunk.js} +1 -1
  73. package/build/es-json.715b6fd8.chunk.js +1 -0
  74. package/build/eu-json.fb17c8f9.chunk.js +1 -0
  75. package/build/fr-json.f66c3211.chunk.js +1 -0
  76. package/build/gu-json.4d667d0c.chunk.js +1 -0
  77. package/build/{he-json.f0de8cdb.chunk.js → he-json.3cf0b48a.chunk.js} +1 -1
  78. package/build/{hi-json.14a17920.chunk.js → hi-json.323be97d.chunk.js} +1 -1
  79. package/build/{hu-json.33172d09.chunk.js → hu-json.fe71e6c8.chunk.js} +1 -1
  80. package/build/id-json.41e07c46.chunk.js +1 -0
  81. package/build/index.html +1 -1
  82. package/build/it-json.bfe27ed8.chunk.js +1 -0
  83. package/build/ja-json.81b6d1e3.chunk.js +1 -0
  84. package/build/ko-json.4539f4ba.chunk.js +1 -0
  85. package/build/main.5b92c1d6.js +3809 -0
  86. package/build/{ml-json.3e69969b.chunk.js → ml-json.8988e374.chunk.js} +1 -1
  87. package/build/{nl-json.641782d5.chunk.js → nl-json.98345913.chunk.js} +1 -1
  88. package/build/{no-json.9b3cd181.chunk.js → no-json.19a2dbfa.chunk.js} +1 -1
  89. package/build/pl-json.59a5dab3.chunk.js +1 -0
  90. package/build/pt-BR-json.9410688b.chunk.js +1 -0
  91. package/build/{ru-json.c4a4f50b.chunk.js → ru-json.6a01cea6.chunk.js} +1 -1
  92. package/build/runtime~main.0bf1f619.js +2 -0
  93. package/build/sa-json.6359a11c.chunk.js +1 -0
  94. package/build/sk-json.2374f129.chunk.js +1 -0
  95. package/build/{sv-json.207afc0d.chunk.js → sv-json.ae6e71ea.chunk.js} +1 -1
  96. package/build/th-json.5f659396.chunk.js +1 -0
  97. package/build/{tr-json.f1a0d19d.chunk.js → tr-json.bac5dbd3.chunk.js} +1 -1
  98. package/build/transfer-tokens-list-page.ce37354b.chunk.js +16 -0
  99. package/build/zh-Hans-json.4c9706a6.chunk.js +1 -0
  100. package/build/{zh-json.085a34f4.chunk.js → zh-json.3529f1e5.chunk.js} +1 -1
  101. package/ee/server/controllers/index.js +0 -1
  102. package/ee/server/controllers/role.js +0 -39
  103. package/ee/server/controllers/user.js +1 -35
  104. package/ee/server/routes/index.js +0 -49
  105. package/ee/server/validation/role.js +28 -20
  106. package/package.json +13 -13
  107. package/server/bootstrap.js +0 -1
  108. package/server/controllers/api-token.js +4 -2
  109. package/server/controllers/permission.js +2 -4
  110. package/server/controllers/role.js +70 -23
  111. package/server/controllers/transfer/runner.js +5 -3
  112. package/server/domain/user.js +3 -0
  113. package/server/routes/roles.js +48 -0
  114. package/server/services/permission/permissions-manager/sanitize.js +2 -2
  115. package/server/services/permission/queries.js +1 -74
  116. package/server/strategies/data-transfer.js +3 -1
  117. package/server/validation/permission.js +1 -82
  118. package/server/validation/role.js +44 -0
  119. package/admin/src/assets/images/hot-air-balloon.png +0 -0
  120. package/admin/src/assets/images/upgrade-details.png +0 -0
  121. package/admin/src/components/UpgradePlanModal/index.js +0 -123
  122. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/findLeafByPathAndReplace.js +0 -51
  123. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/recursivelyFindPathsBasedOnCondition.js +0 -79
  124. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ConditionsModal/ActionRow/utils/constants.js +0 -3
  125. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/Collapse/utils/constants.js +0 -3
  126. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/CollapsePropertyMatrix/ActionRow/utils/constants.js +0 -3
  127. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/CollapsePropertyMatrix/SubActionRow/utils/constants.js +0 -3
  128. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/GlobalActions/utils/constants.js +0 -3
  129. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/PluginsAndSettings/SubCategory/utils/constants.js +0 -3
  130. package/build/617f9c948fa79e6d73bd.png +0 -0
  131. package/build/6d21938306785f176538.png +0 -0
  132. package/build/7259.63e91b59.chunk.js +0 -1
  133. package/build/Admin_settingsPage.6814a96e.chunk.js +0 -177
  134. package/build/admin-edit-roles-page.bf130aaf.chunk.js +0 -1
  135. package/build/api-tokens-list-page.149903c8.chunk.js +0 -16
  136. package/build/ca-json.59c4502c.chunk.js +0 -1
  137. package/build/content-manager.d792c194.chunk.js +0 -1139
  138. package/build/de-json.dbc2cf1b.chunk.js +0 -1
  139. package/build/dk-json.52f67b15.chunk.js +0 -1
  140. package/build/es-json.c40c57dd.chunk.js +0 -1
  141. package/build/eu-json.6702a0d2.chunk.js +0 -1
  142. package/build/fr-json.ea9ec573.chunk.js +0 -1
  143. package/build/gu-json.94f0d242.chunk.js +0 -1
  144. package/build/id-json.e0d83d41.chunk.js +0 -1
  145. package/build/it-json.8be59205.chunk.js +0 -1
  146. package/build/ja-json.3008b720.chunk.js +0 -1
  147. package/build/ko-json.7d2f95b1.chunk.js +0 -1
  148. package/build/main.64fe0c37.js +0 -3928
  149. package/build/pl-json.05814145.chunk.js +0 -1
  150. package/build/pt-BR-json.d72350de.chunk.js +0 -1
  151. package/build/runtime~main.122b5a09.js +0 -2
  152. package/build/sa-json.e5e7ccaf.chunk.js +0 -1
  153. package/build/sk-json.3529b8aa.chunk.js +0 -1
  154. package/build/th-json.f664b96d.chunk.js +0 -1
  155. package/build/transfer-tokens-list-page.c6f8039a.chunk.js +0 -16
  156. package/build/zh-Hans-json.993d085f.chunk.js +0 -1
  157. package/ee/admin/pages/SettingsPage/pages/Roles/CreatePage/index.js +0 -270
  158. package/ee/admin/pages/SettingsPage/pages/Roles/EditPage/components/ConditionsModal/ActionRow/utils/constants.js +0 -3
  159. package/ee/admin/pages/SettingsPage/pages/Roles/EditPage/components/ConditionsModal/ConditionsSelect/MenuList/utils/constants.js +0 -3
  160. package/ee/admin/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/Collapse/utils/constants.js +0 -3
  161. package/ee/admin/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/CollapsePropertyMatrix/ActionRow/utils/constants.js +0 -3
  162. package/ee/admin/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/CollapsePropertyMatrix/SubActionRow/utils/constants.js +0 -3
  163. package/ee/admin/pages/SettingsPage/pages/Roles/EditPage/components/GlobalActions/utils/constants.js +0 -3
  164. package/ee/admin/pages/SettingsPage/pages/Roles/EditPage/components/PluginsAndSettings/SubCategory/utils/constants.js +0 -3
  165. package/ee/admin/pages/SettingsPage/pages/Roles/ListPage/index.js +0 -376
  166. package/ee/admin/pages/SettingsPage/pages/Roles/ProtectedListPage/index.js +0 -12
  167. package/ee/server/controllers/permission.js +0 -21
  168. package/ee/server/validation/permission.js +0 -8
  169. package/server/domain/role.js +0 -29
  170. /package/{ee/admin → admin/src}/pages/SettingsPage/pages/Roles/CreatePage/utils/schema.js +0 -0
  171. /package/{ee/admin → admin/src}/pages/SettingsPage/pages/Roles/ListPage/reducer.js +0 -0
@@ -20,38 +20,46 @@ const rolesDeleteSchema = yup
20
20
  .of(yup.strapiID())
21
21
  .min(1)
22
22
  .required()
23
- .test('roles-deletion-checks', 'Roles deletion checks have failed', async function (ids) {
24
- try {
25
- await strapi.admin.services.role.checkRolesIdForDeletion(ids);
23
+ .test(
24
+ 'roles-deletion-checks',
25
+ 'Roles deletion checks have failed',
26
+ async function rolesDeletionChecks(ids) {
27
+ try {
28
+ await strapi.admin.services.role.checkRolesIdForDeletion(ids);
26
29
 
27
- if (features.isEnabled('sso')) {
28
- await strapi.admin.services.role.ssoCheckRolesIdForDeletion(ids);
30
+ if (features.isEnabled('sso')) {
31
+ await strapi.admin.services.role.ssoCheckRolesIdForDeletion(ids);
32
+ }
33
+ } catch (e) {
34
+ return this.createError({ path: 'ids', message: e.message });
29
35
  }
30
- } catch (e) {
31
- return this.createError({ path: 'ids', message: e.message });
32
- }
33
36
 
34
- return true;
35
- }),
37
+ return true;
38
+ }
39
+ ),
36
40
  })
37
41
  .noUnknown();
38
42
 
39
43
  const roleDeleteSchema = yup
40
44
  .strapiID()
41
45
  .required()
42
- .test('no-admin-single-delete', 'Role deletion checks have failed', async function (id) {
43
- try {
44
- await strapi.admin.services.role.checkRolesIdForDeletion([id]);
46
+ .test(
47
+ 'no-admin-single-delete',
48
+ 'Role deletion checks have failed',
49
+ async function noAdminSingleDelete(id) {
50
+ try {
51
+ await strapi.admin.services.role.checkRolesIdForDeletion([id]);
45
52
 
46
- if (features.isEnabled('sso')) {
47
- await strapi.admin.services.role.ssoCheckRolesIdForDeletion([id]);
53
+ if (features.isEnabled('sso')) {
54
+ await strapi.admin.services.role.ssoCheckRolesIdForDeletion([id]);
55
+ }
56
+ } catch (e) {
57
+ return this.createError({ path: 'id', message: e.message });
48
58
  }
49
- } catch (e) {
50
- return this.createError({ path: 'id', message: e.message });
51
- }
52
59
 
53
- return true;
54
- });
60
+ return true;
61
+ }
62
+ );
55
63
 
56
64
  module.exports = {
57
65
  validateRoleCreateInput: validateYupSchema(roleCreateSchema),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/admin",
3
- "version": "4.7.2-exp.175f7ac70ee76d6c825e4429e15fc85ee78d23bb",
3
+ "version": "4.8.0",
4
4
  "description": "Strapi Admin",
5
5
  "repository": {
6
6
  "type": "git",
@@ -46,21 +46,21 @@
46
46
  "@casl/ability": "^5.4.3",
47
47
  "@fingerprintjs/fingerprintjs": "3.3.6",
48
48
  "@pmmmwh/react-refresh-webpack-plugin": "0.5.10",
49
- "@strapi/babel-plugin-switch-ee-ce": "4.7.2-exp.175f7ac70ee76d6c825e4429e15fc85ee78d23bb",
50
- "@strapi/data-transfer": "4.7.2-exp.175f7ac70ee76d6c825e4429e15fc85ee78d23bb",
51
- "@strapi/design-system": "1.6.3",
52
- "@strapi/helper-plugin": "4.7.2-exp.175f7ac70ee76d6c825e4429e15fc85ee78d23bb",
53
- "@strapi/icons": "1.6.3",
54
- "@strapi/permissions": "4.7.2-exp.175f7ac70ee76d6c825e4429e15fc85ee78d23bb",
55
- "@strapi/provider-audit-logs-local": "4.7.2-exp.175f7ac70ee76d6c825e4429e15fc85ee78d23bb",
56
- "@strapi/typescript-utils": "4.7.2-exp.175f7ac70ee76d6c825e4429e15fc85ee78d23bb",
57
- "@strapi/utils": "4.7.2-exp.175f7ac70ee76d6c825e4429e15fc85ee78d23bb",
49
+ "@strapi/babel-plugin-switch-ee-ce": "4.8.0",
50
+ "@strapi/data-transfer": "4.8.0",
51
+ "@strapi/design-system": "1.6.5",
52
+ "@strapi/helper-plugin": "4.8.0",
53
+ "@strapi/icons": "1.6.5",
54
+ "@strapi/permissions": "4.8.0",
55
+ "@strapi/provider-audit-logs-local": "4.8.0",
56
+ "@strapi/typescript-utils": "4.8.0",
57
+ "@strapi/utils": "4.8.0",
58
58
  "axios": "1.2.2",
59
59
  "babel-loader": "^9.1.2",
60
60
  "babel-plugin-styled-components": "2.0.2",
61
61
  "bcryptjs": "2.4.3",
62
62
  "browserslist-to-esbuild": "1.2.0",
63
- "chalk": "^4.1.1",
63
+ "chalk": "^4.1.2",
64
64
  "chokidar": "^3.5.1",
65
65
  "codemirror5": "npm:codemirror@^5.65.11",
66
66
  "cross-env": "^7.0.3",
@@ -121,7 +121,7 @@
121
121
  "react-redux": "8.0.5",
122
122
  "react-refresh": "0.14.0",
123
123
  "react-router-dom": "5.3.4",
124
- "react-select": "5.6.0",
124
+ "react-select": "5.7.0",
125
125
  "react-window": "1.8.7",
126
126
  "redux": "^4.2.1",
127
127
  "reselect": "^4.1.7",
@@ -166,5 +166,5 @@
166
166
  }
167
167
  }
168
168
  },
169
- "gitHead": "175f7ac70ee76d6c825e4429e15fc85ee78d23bb"
169
+ "gitHead": "e239e408f99c9e61e6d02b38f01632ce67412f2a"
170
170
  }
@@ -85,7 +85,6 @@ module.exports = async () => {
85
85
  await roleService.resetSuperAdminPermissions();
86
86
  await roleService.displayWarningIfNoSuperAdmin();
87
87
 
88
- await permissionService.ensureBoundPermissionsInDatabase();
89
88
  await permissionService.cleanPermissionsInDatabase();
90
89
 
91
90
  await userService.displayWarningIfUsersDontHaveRole();
@@ -1,7 +1,9 @@
1
1
  'use strict';
2
2
 
3
- const { stringEquals } = require('@strapi/utils/lib');
4
- const { ApplicationError } = require('@strapi/utils').errors;
3
+ const {
4
+ stringEquals,
5
+ errors: { ApplicationError },
6
+ } = require('@strapi/utils');
5
7
  const { trim, has } = require('lodash/fp');
6
8
  const { getService } = require('../utils');
7
9
  const {
@@ -29,11 +29,9 @@ module.exports = {
29
29
  * @param {KoaContext} ctx - koa context
30
30
  */
31
31
  async getAll(ctx) {
32
- const { role: roleId } = ctx.query;
32
+ const { sectionsBuilder, actionProvider, conditionProvider } = getService('permission');
33
33
 
34
- const { sectionsBuilder, conditionProvider } = getService('permission');
35
-
36
- const actions = await getService('action').getAllowedActionsForRole(roleId);
34
+ const actions = actionProvider.values();
37
35
  const conditions = conditionProvider.values();
38
36
  const sections = await sectionsBuilder.build(actions);
39
37
 
@@ -1,12 +1,32 @@
1
1
  'use strict';
2
2
 
3
3
  const { ApplicationError } = require('@strapi/utils').errors;
4
- const { validateRoleUpdateInput } = require('../validation/role');
4
+ const {
5
+ validateRoleUpdateInput,
6
+ validateRoleCreateInput,
7
+ validateRoleDeleteInput,
8
+ validateRolesDeleteInput,
9
+ } = require('../validation/role');
5
10
  const { validatedUpdatePermissionsInput } = require('../validation/permission');
6
- const { EDITOR_CODE, AUTHOR_CODE, SUPER_ADMIN_CODE } = require('../services/constants');
11
+ const { SUPER_ADMIN_CODE } = require('../services/constants');
7
12
  const { getService } = require('../utils');
8
13
 
9
14
  module.exports = {
15
+ /**
16
+ * Create a new role
17
+ * @param {KoaContext} ctx - koa context
18
+ */
19
+ async create(ctx) {
20
+ await validateRoleCreateInput(ctx.request.body);
21
+
22
+ const roleService = getService('role');
23
+
24
+ const role = await roleService.create(ctx.request.body);
25
+ const sanitizedRole = roleService.sanitizeRole(role);
26
+
27
+ ctx.created({ data: sanitizedRole });
28
+ },
29
+
10
30
  /**
11
31
  * Returns on role by id
12
32
  * @param {KoaContext} ctx - koa context
@@ -99,10 +119,10 @@ module.exports = {
99
119
  const { id } = ctx.params;
100
120
  const { body: input } = ctx.request;
101
121
 
102
- const { findOne, assignPermissions } = getService('role');
103
- const { sanitizePermission, actionProvider } = getService('permission');
122
+ const roleService = getService('role');
123
+ const permissionService = getService('permission');
104
124
 
105
- const role = await findOne({ id });
125
+ const role = await roleService.findOne({ id });
106
126
 
107
127
  if (!role) {
108
128
  return ctx.notFound('role.notFound');
@@ -112,30 +132,57 @@ module.exports = {
112
132
  throw new ApplicationError("Super admin permissions can't be edited.");
113
133
  }
114
134
 
115
- await validatedUpdatePermissionsInput(input, role);
135
+ await validatedUpdatePermissionsInput(input);
116
136
 
117
- let permissionsToAssign;
137
+ if (!role) {
138
+ return ctx.notFound('role.notFound');
139
+ }
118
140
 
119
- if ([EDITOR_CODE, AUTHOR_CODE].includes(role.code)) {
120
- permissionsToAssign = input.permissions.map((permission) => {
121
- const action = actionProvider.get(permission.action);
141
+ const permissions = await roleService.assignPermissions(role.id, input.permissions);
122
142
 
123
- if (action.section !== 'contentTypes') {
124
- return permission;
125
- }
143
+ const sanitizedPermissions = permissions.map(permissionService.sanitizePermission);
126
144
 
127
- const conditions = role.code === AUTHOR_CODE ? ['admin::is-creator'] : [];
145
+ ctx.body = {
146
+ data: sanitizedPermissions,
147
+ };
148
+ },
128
149
 
129
- return { ...permission, conditions };
130
- });
131
- } else {
132
- permissionsToAssign = input.permissions;
133
- }
150
+ /**
151
+ * Delete a role
152
+ * @param {KoaContext} ctx - koa context
153
+ */
154
+ async deleteOne(ctx) {
155
+ const { id } = ctx.params;
134
156
 
135
- const permissions = await assignPermissions(role.id, permissionsToAssign);
157
+ await validateRoleDeleteInput(id);
136
158
 
137
- ctx.body = {
138
- data: permissions.map(sanitizePermission),
139
- };
159
+ const roleService = getService('role');
160
+
161
+ const roles = await roleService.deleteByIds([id]);
162
+
163
+ const sanitizedRole = roles.map((role) => roleService.sanitizeRole(role))[0] || null;
164
+
165
+ return ctx.deleted({
166
+ data: sanitizedRole,
167
+ });
168
+ },
169
+
170
+ /**
171
+ * delete several roles
172
+ * @param {KoaContext} ctx - koa context
173
+ */
174
+ async deleteMany(ctx) {
175
+ const { body } = ctx.request;
176
+
177
+ await validateRolesDeleteInput(body);
178
+
179
+ const roleService = getService('role');
180
+
181
+ const roles = await roleService.deleteByIds(body.ids);
182
+ const sanitizedRoles = roles.map(roleService.sanitizeRole);
183
+
184
+ return ctx.deleted({
185
+ data: sanitizedRoles,
186
+ });
140
187
  },
141
188
  };
@@ -1,7 +1,9 @@
1
1
  'use strict';
2
2
 
3
- const { remote } = require('@strapi/data-transfer/lib/strapi');
4
- const { UnauthorizedError } = require('@strapi/utils/lib/errors');
3
+ const { createTransferHandler } = require('@strapi/data-transfer').strapi.remote.handlers;
4
+ const {
5
+ errors: { UnauthorizedError },
6
+ } = require('@strapi/utils');
5
7
 
6
8
  const dataTransferAuthStrategy = require('../../strategies/data-transfer');
7
9
 
@@ -20,5 +22,5 @@ const verify = async (ctx, scope) => {
20
22
  };
21
23
 
22
24
  module.exports = {
23
- connect: remote.handlers.createTransferHandler({ verify }),
25
+ connect: createTransferHandler({ verify }),
24
26
  };
@@ -19,7 +19,10 @@ const hasSuperAdminRole = (user) => {
19
19
  return user.roles.filter((role) => role.code === SUPER_ADMIN_CODE).length > 0;
20
20
  };
21
21
 
22
+ const ADMIN_USER_ALLOWED_FIELDS = ['id', 'firstname', 'lastname', 'username'];
23
+
22
24
  module.exports = {
23
25
  createUser,
24
26
  hasSuperAdminRole,
27
+ ADMIN_USER_ALLOWED_FIELDS,
25
28
  };
@@ -45,6 +45,22 @@ module.exports = [
45
45
  ],
46
46
  },
47
47
  },
48
+ {
49
+ method: 'POST',
50
+ path: '/roles',
51
+ handler: 'role.create',
52
+ config: {
53
+ policies: [
54
+ 'admin::isAuthenticatedAdmin',
55
+ {
56
+ name: 'admin::hasPermissions',
57
+ config: {
58
+ actions: ['admin::roles.create'],
59
+ },
60
+ },
61
+ ],
62
+ },
63
+ },
48
64
  {
49
65
  method: 'PUT',
50
66
  path: '/roles/:id',
@@ -56,4 +72,36 @@ module.exports = [
56
72
  ],
57
73
  },
58
74
  },
75
+ {
76
+ method: 'DELETE',
77
+ path: '/roles/:id',
78
+ handler: 'role.deleteOne',
79
+ config: {
80
+ policies: [
81
+ 'admin::isAuthenticatedAdmin',
82
+ {
83
+ name: 'admin::hasPermissions',
84
+ config: {
85
+ actions: ['admin::roles.delete'],
86
+ },
87
+ },
88
+ ],
89
+ },
90
+ },
91
+ {
92
+ method: 'POST',
93
+ path: '/roles/batch-delete',
94
+ handler: 'role.deleteMany',
95
+ config: {
96
+ policies: [
97
+ 'admin::isAuthenticatedAdmin',
98
+ {
99
+ name: 'admin::hasPermissions',
100
+ config: {
101
+ actions: ['admin::roles.delete'],
102
+ },
103
+ },
104
+ ],
105
+ },
106
+ },
59
107
  ];
@@ -21,6 +21,7 @@ const {
21
21
 
22
22
  const { contentTypes, traverseEntity, sanitize, pipeAsync, traverse } = require('@strapi/utils');
23
23
  const { removePassword } = require('@strapi/utils/lib/sanitize/visitors');
24
+ const { ADMIN_USER_ALLOWED_FIELDS } = require('../../../domain/user');
24
25
 
25
26
  const {
26
27
  constants,
@@ -39,7 +40,6 @@ const {
39
40
 
40
41
  const COMPONENT_FIELDS = ['__component'];
41
42
  const STATIC_FIELDS = [ID_ATTRIBUTE];
42
- const ADMIN_USER_ALLOWED_FIELDS = ['id', 'firstname', 'lastname', 'username'];
43
43
 
44
44
  module.exports = ({ action, ability, model }) => {
45
45
  const schema = strapi.getModel(model);
@@ -49,7 +49,7 @@ module.exports = ({ action, ability, model }) => {
49
49
  const createSanitizeQuery = (options = {}) => {
50
50
  const { fields } = options;
51
51
 
52
- // TODO: sanitize relations to admin usersin all sanitizers
52
+ // TODO: sanitize relations to admin users in all sanitizers
53
53
  const permittedFields = fields.shouldIncludeAll ? null : getQueryFields(fields.permitted);
54
54
 
55
55
  const sanitizeFilters = pipeAsync(
@@ -1,22 +1,7 @@
1
1
  'use strict';
2
2
 
3
- const {
4
- flatMap,
5
- reject,
6
- isNil,
7
- isArray,
8
- prop,
9
- xor,
10
- eq,
11
- uniq,
12
- map,
13
- difference,
14
- differenceWith,
15
- pipe,
16
- } = require('lodash/fp');
3
+ const { isNil, isArray, prop, xor, eq, map, differenceWith } = require('lodash/fp');
17
4
  const pmap = require('p-map');
18
- const { EDITOR_CODE } = require('../constants');
19
- const { getBoundActionsBySubject, BOUND_ACTIONS_FOR_FIELDS } = require('../../domain/role');
20
5
  const { getService } = require('../../utils');
21
6
  const permissionDomain = require('../../domain/permission/index');
22
7
 
@@ -195,63 +180,6 @@ const cleanPermissionsInDatabase = async () => {
195
180
  }
196
181
  };
197
182
 
198
- const ensureBoundPermissionsInDatabase = async () => {
199
- if (strapi.EE) {
200
- return;
201
- }
202
-
203
- const contentTypes = Object.values(strapi.contentTypes);
204
- const editorRole = await strapi.query('admin::role').findOne({
205
- where: { code: EDITOR_CODE },
206
- });
207
-
208
- if (isNil(editorRole)) {
209
- return;
210
- }
211
-
212
- for (const contentType of contentTypes) {
213
- const boundActions = getBoundActionsBySubject(editorRole, contentType.uid);
214
-
215
- const permissions = await findMany({
216
- where: {
217
- subject: contentType.uid,
218
- action: boundActions,
219
- role: { id: editorRole.id },
220
- },
221
- });
222
-
223
- if (permissions.length === 0) {
224
- return;
225
- }
226
-
227
- const fields = pipe(
228
- flatMap(permissionDomain.getProperty('fields')),
229
- reject(isNil),
230
- uniq
231
- )(permissions);
232
-
233
- // Handle the scenario where permissions are missing
234
- const missingActions = difference(map('action', permissions), boundActions);
235
-
236
- if (missingActions.length > 0) {
237
- const permissions = pipe(
238
- // Create a permission skeleton from the action id
239
- map((action) => ({ action, subject: contentType.uid, role: editorRole.id })),
240
- // Use the permission domain to create a clean permission from the given object
241
- map(permissionDomain.create),
242
- // Adds the fields property if the permission action is eligible
243
- map((permission) =>
244
- BOUND_ACTIONS_FOR_FIELDS.includes(permission.action)
245
- ? permissionDomain.setProperty('fields', fields, permission)
246
- : permission
247
- )
248
- )(missingActions);
249
-
250
- await createMany(permissions);
251
- }
252
- }
253
- };
254
-
255
183
  module.exports = {
256
184
  createMany,
257
185
  findMany,
@@ -259,5 +187,4 @@ module.exports = {
259
187
  deleteByIds,
260
188
  findUserPermissions,
261
189
  cleanPermissionsInDatabase,
262
- ensureBoundPermissionsInDatabase,
263
190
  };
@@ -1,6 +1,8 @@
1
1
  'use strict';
2
2
 
3
- const { UnauthorizedError, ForbiddenError } = require('@strapi/utils/lib/errors');
3
+ const {
4
+ errors: { UnauthorizedError, ForbiddenError },
5
+ } = require('@strapi/utils');
4
6
  const { castArray, isNil } = require('lodash/fp');
5
7
 
6
8
  const { getService } = require('../utils');
@@ -1,83 +1,9 @@
1
1
  'use strict';
2
2
 
3
- const _ = require('lodash');
4
3
  const { yup, validateYupSchema } = require('@strapi/utils');
5
4
  const { getService } = require('../utils');
6
- const { AUTHOR_CODE, PUBLISH_ACTION } = require('../services/constants');
7
- const {
8
- BOUND_ACTIONS_FOR_FIELDS,
9
- BOUND_ACTIONS,
10
- getBoundActionsBySubject,
11
- } = require('../domain/role');
12
5
  const validators = require('./common-validators');
13
6
 
14
- // validatedUpdatePermissionsInput
15
-
16
- const actionFieldsAreEqual = (a, b) => {
17
- const aFields = a.properties.fields || [];
18
- const bFields = b.properties.fields || [];
19
-
20
- return _.isEqual(aFields.sort(), bFields.sort());
21
- };
22
-
23
- const haveSameFieldsAsOtherActions = (a, i, allActions) =>
24
- allActions.slice(i + 1).every((b) => actionFieldsAreEqual(a, b));
25
-
26
- const checkPermissionsAreBound = (role) =>
27
- function (permissions) {
28
- const permsBySubject = _.groupBy(
29
- permissions.filter((perm) => BOUND_ACTIONS.includes(perm.action)),
30
- 'subject'
31
- );
32
-
33
- for (const [subject, perms] of Object.entries(permsBySubject)) {
34
- const boundActions = getBoundActionsBySubject(role, subject);
35
- const missingActions =
36
- _.xor(
37
- perms.map((p) => p.action),
38
- boundActions
39
- ).length !== 0;
40
- if (missingActions) return false;
41
-
42
- const permsBoundByFields = perms.filter((p) => BOUND_ACTIONS_FOR_FIELDS.includes(p.action));
43
- const everyActionsHaveSameFields = _.every(permsBoundByFields, haveSameFieldsAsOtherActions);
44
- if (!everyActionsHaveSameFields) return false;
45
- }
46
-
47
- return true;
48
- };
49
-
50
- const noPublishPermissionForAuthorRole = (role) =>
51
- function (permissions) {
52
- const isAuthor = role.code === AUTHOR_CODE;
53
- const hasPublishPermission = permissions.some((perm) => perm.action === PUBLISH_ACTION);
54
-
55
- return !(isAuthor && hasPublishPermission);
56
- };
57
-
58
- const getUpdatePermissionsSchemas = (role) => [
59
- validators.updatePermissions,
60
- yup.object().shape({ permissions: actionsExistSchema.clone() }),
61
- yup.object().shape({
62
- permissions: yup
63
- .array()
64
- .test(
65
- 'author-no-publish',
66
- 'The author role cannot have the publish permission.',
67
- noPublishPermissionForAuthorRole(role)
68
- ),
69
- }),
70
- yup.object().shape({
71
- permissions: yup
72
- .array()
73
- .test(
74
- 'are-bond',
75
- 'Permissions have to be defined all together for a subject field or not at all',
76
- checkPermissionsAreBound(role)
77
- ),
78
- }),
79
- ];
80
-
81
7
  const checkPermissionsSchema = yup.object().shape({
82
8
  permissions: yup.array().of(
83
9
  yup
@@ -91,13 +17,6 @@ const checkPermissionsSchema = yup.object().shape({
91
17
  ),
92
18
  });
93
19
 
94
- const validatedUpdatePermissionsInput = async (permissions, role) => {
95
- const schemas = getUpdatePermissionsSchemas(role);
96
- for (const schema of schemas) {
97
- await validateYupSchema(schema)(permissions);
98
- }
99
- };
100
-
101
20
  // validatePermissionsExist
102
21
 
103
22
  const checkPermissionsExist = function (permissions) {
@@ -131,7 +50,7 @@ const actionsExistSchema = yup
131
50
  // exports
132
51
 
133
52
  module.exports = {
134
- validatedUpdatePermissionsInput,
53
+ validatedUpdatePermissionsInput: validateYupSchema(validators.updatePermissions),
135
54
  validatePermissionsExist: validateYupSchema(actionsExistSchema),
136
55
  validateCheckPermissionsInput: validateYupSchema(checkPermissionsSchema),
137
56
  };
@@ -2,6 +2,47 @@
2
2
 
3
3
  const { yup, validateYupSchema } = require('@strapi/utils');
4
4
 
5
+ const roleCreateSchema = yup
6
+ .object()
7
+ .shape({
8
+ name: yup.string().min(1).required(),
9
+ description: yup.string().nullable(),
10
+ })
11
+ .noUnknown();
12
+
13
+ const rolesDeleteSchema = yup
14
+ .object()
15
+ .shape({
16
+ ids: yup
17
+ .array()
18
+ .of(yup.strapiID())
19
+ .min(1)
20
+ .required()
21
+ .test('roles-deletion-checks', 'Roles deletion checks have failed', async function (ids) {
22
+ try {
23
+ await strapi.admin.services.role.checkRolesIdForDeletion(ids);
24
+ } catch (e) {
25
+ return this.createError({ path: 'ids', message: e.message });
26
+ }
27
+
28
+ return true;
29
+ }),
30
+ })
31
+ .noUnknown();
32
+
33
+ const roleDeleteSchema = yup
34
+ .strapiID()
35
+ .required()
36
+ .test('no-admin-single-delete', 'Role deletion checks have failed', async function (id) {
37
+ try {
38
+ await strapi.admin.services.role.checkRolesIdForDeletion([id]);
39
+ } catch (e) {
40
+ return this.createError({ path: 'id', message: e.message });
41
+ }
42
+
43
+ return true;
44
+ });
45
+
5
46
  const roleUpdateSchema = yup
6
47
  .object()
7
48
  .shape({
@@ -12,4 +53,7 @@ const roleUpdateSchema = yup
12
53
 
13
54
  module.exports = {
14
55
  validateRoleUpdateInput: validateYupSchema(roleUpdateSchema),
56
+ validateRoleCreateInput: validateYupSchema(roleCreateSchema),
57
+ validateRolesDeleteInput: validateYupSchema(rolesDeleteSchema),
58
+ validateRoleDeleteInput: validateYupSchema(roleDeleteSchema),
15
59
  };