@strapi/plugin-users-permissions 4.0.0-next.9 → 4.0.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 (177) hide show
  1. package/admin/src/components/BoundRoute/getMethodColor.js +41 -0
  2. package/admin/src/components/BoundRoute/index.js +40 -24
  3. package/admin/src/components/FormModal/Input/index.js +121 -0
  4. package/admin/src/components/FormModal/index.js +123 -0
  5. package/admin/src/components/Permissions/PermissionRow/CheckboxWrapper.js +19 -26
  6. package/admin/src/components/Permissions/PermissionRow/SubCategory.js +118 -0
  7. package/admin/src/components/Permissions/PermissionRow/index.js +9 -48
  8. package/admin/src/components/Permissions/index.js +36 -24
  9. package/admin/src/components/Permissions/init.js +1 -6
  10. package/admin/src/components/Policies/index.js +46 -47
  11. package/admin/src/components/UsersPermissions/index.js +29 -26
  12. package/admin/src/components/UsersPermissions/init.js +1 -2
  13. package/admin/src/hooks/useFetchRole/index.js +17 -7
  14. package/admin/src/hooks/useForm/index.js +3 -29
  15. package/admin/src/hooks/useForm/reducer.js +2 -21
  16. package/admin/src/hooks/usePlugins/index.js +12 -21
  17. package/admin/src/hooks/usePlugins/reducer.js +0 -3
  18. package/admin/src/index.js +0 -8
  19. package/admin/src/pages/AdvancedSettings/index.js +203 -193
  20. package/admin/src/pages/AdvancedSettings/utils/api.js +13 -0
  21. package/admin/src/pages/AdvancedSettings/utils/layout.js +96 -0
  22. package/admin/src/pages/AdvancedSettings/utils/schema.js +22 -0
  23. package/admin/src/pages/EmailTemplates/components/EmailForm.js +173 -0
  24. package/admin/src/pages/EmailTemplates/components/EmailTable.js +116 -0
  25. package/admin/src/pages/EmailTemplates/index.js +117 -197
  26. package/admin/src/pages/EmailTemplates/utils/api.js +13 -0
  27. package/admin/src/pages/Providers/index.js +206 -221
  28. package/admin/src/pages/Providers/utils/api.js +21 -0
  29. package/admin/src/pages/Providers/utils/forms.js +168 -126
  30. package/admin/src/pages/Roles/CreatePage/index.js +155 -147
  31. package/admin/src/pages/Roles/EditPage/index.js +162 -134
  32. package/admin/src/pages/Roles/ListPage/components/TableBody.js +96 -0
  33. package/admin/src/pages/Roles/ListPage/index.js +176 -156
  34. package/admin/src/pages/Roles/ListPage/utils/api.js +28 -0
  35. package/admin/src/translations/ar.json +0 -8
  36. package/admin/src/translations/cs.json +0 -8
  37. package/admin/src/translations/de.json +0 -8
  38. package/admin/src/translations/dk.json +0 -8
  39. package/admin/src/translations/en.json +33 -12
  40. package/admin/src/translations/es.json +0 -8
  41. package/admin/src/translations/fr.json +0 -8
  42. package/admin/src/translations/id.json +0 -8
  43. package/admin/src/translations/it.json +0 -8
  44. package/admin/src/translations/ja.json +0 -8
  45. package/admin/src/translations/ko.json +0 -8
  46. package/admin/src/translations/ms.json +0 -8
  47. package/admin/src/translations/nl.json +0 -8
  48. package/admin/src/translations/pl.json +0 -8
  49. package/admin/src/translations/pt-BR.json +0 -8
  50. package/admin/src/translations/pt.json +0 -8
  51. package/admin/src/translations/ru.json +0 -8
  52. package/admin/src/translations/sk.json +0 -8
  53. package/admin/src/translations/sv.json +0 -8
  54. package/admin/src/translations/th.json +0 -8
  55. package/admin/src/translations/tr.json +0 -8
  56. package/admin/src/translations/uk.json +0 -8
  57. package/admin/src/translations/vi.json +0 -8
  58. package/admin/src/translations/zh-Hans.json +5 -14
  59. package/admin/src/translations/zh.json +0 -8
  60. package/admin/src/utils/axiosInstance.js +36 -0
  61. package/admin/src/utils/formatPluginName.js +26 -0
  62. package/admin/src/utils/index.js +1 -0
  63. package/documentation/1.0.0/overrides/users-permissions-Role.json +6 -6
  64. package/documentation/1.0.0/overrides/users-permissions-User.json +7 -7
  65. package/package.json +30 -31
  66. package/server/bootstrap/index.js +19 -21
  67. package/server/config.js +3 -3
  68. package/server/content-types/index.js +3 -3
  69. package/server/content-types/permission/index.js +30 -3
  70. package/server/content-types/role/index.js +47 -3
  71. package/server/content-types/user/index.js +65 -4
  72. package/server/controllers/auth.js +81 -244
  73. package/server/controllers/content-manager-user.js +183 -0
  74. package/server/controllers/index.js +12 -6
  75. package/server/controllers/permissions.js +26 -0
  76. package/server/controllers/role.js +77 -0
  77. package/server/controllers/settings.js +85 -0
  78. package/server/controllers/user.js +118 -44
  79. package/server/controllers/validation/auth.js +29 -0
  80. package/server/controllers/validation/user.js +38 -0
  81. package/server/graphql/index.js +44 -0
  82. package/server/graphql/mutations/auth/email-confirmation.js +39 -0
  83. package/server/graphql/mutations/auth/forgot-password.js +38 -0
  84. package/server/graphql/mutations/auth/login.js +38 -0
  85. package/server/graphql/mutations/auth/register.js +39 -0
  86. package/server/graphql/mutations/auth/reset-password.js +41 -0
  87. package/server/graphql/mutations/crud/role/create-role.js +37 -0
  88. package/server/graphql/mutations/crud/role/delete-role.js +28 -0
  89. package/server/graphql/mutations/crud/role/update-role.js +38 -0
  90. package/server/graphql/mutations/crud/user/create-user.js +48 -0
  91. package/server/graphql/mutations/crud/user/delete-user.js +42 -0
  92. package/server/graphql/mutations/crud/user/update-user.js +49 -0
  93. package/server/graphql/mutations/index.js +42 -0
  94. package/server/graphql/queries/index.js +13 -0
  95. package/server/graphql/queries/me.js +17 -0
  96. package/server/graphql/resolvers-configs.js +37 -0
  97. package/server/graphql/types/create-role-payload.js +11 -0
  98. package/server/graphql/types/delete-role-payload.js +11 -0
  99. package/server/graphql/types/index.js +21 -0
  100. package/server/graphql/types/login-input.js +13 -0
  101. package/server/graphql/types/login-payload.js +12 -0
  102. package/server/graphql/types/me-role.js +14 -0
  103. package/server/graphql/types/me.js +16 -0
  104. package/server/graphql/types/password-payload.js +11 -0
  105. package/server/graphql/types/register-input.js +13 -0
  106. package/server/graphql/types/update-role-payload.js +11 -0
  107. package/server/graphql/utils.js +27 -0
  108. package/server/index.js +21 -0
  109. package/server/middlewares/index.js +2 -2
  110. package/server/{policies → middlewares}/rateLimit.js +3 -7
  111. package/server/register.js +11 -0
  112. package/server/routes/admin/index.js +10 -0
  113. package/server/routes/admin/permissions.js +20 -0
  114. package/server/routes/admin/role.js +79 -0
  115. package/server/routes/admin/settings.js +95 -0
  116. package/server/routes/content-api/auth.js +73 -0
  117. package/server/routes/content-api/index.js +11 -0
  118. package/server/routes/content-api/permissions.js +9 -0
  119. package/server/routes/content-api/role.js +29 -0
  120. package/server/routes/content-api/user.js +61 -0
  121. package/server/routes/index.js +4 -428
  122. package/server/services/index.js +10 -8
  123. package/server/services/jwt.js +9 -17
  124. package/server/services/providers.js +32 -33
  125. package/server/services/role.js +177 -0
  126. package/server/services/user.js +9 -15
  127. package/server/services/users-permissions.js +140 -338
  128. package/server/strategies/users-permissions.js +123 -0
  129. package/server/utils/index.d.ts +2 -0
  130. package/strapi-admin.js +3 -0
  131. package/strapi-server.js +1 -19
  132. package/admin/src/assets/images/logo.svg +0 -1
  133. package/admin/src/components/BaselineAlignement/index.js +0 -33
  134. package/admin/src/components/Bloc/index.js +0 -10
  135. package/admin/src/components/BoundRoute/Components.js +0 -78
  136. package/admin/src/components/ContainerFluid/index.js +0 -13
  137. package/admin/src/components/FormBloc/index.js +0 -61
  138. package/admin/src/components/IntlInput/index.js +0 -38
  139. package/admin/src/components/ListBaselineAlignment/index.js +0 -8
  140. package/admin/src/components/ListRow/Components.js +0 -74
  141. package/admin/src/components/ListRow/index.js +0 -35
  142. package/admin/src/components/ModalForm/Wrapper.js +0 -12
  143. package/admin/src/components/ModalForm/index.js +0 -59
  144. package/admin/src/components/Permissions/ListWrapper.js +0 -9
  145. package/admin/src/components/Permissions/PermissionRow/BaselineAlignment.js +0 -7
  146. package/admin/src/components/Permissions/PermissionRow/RowStyle.js +0 -28
  147. package/admin/src/components/Permissions/PermissionRow/SubCategory/ConditionsButtonWrapper.js +0 -13
  148. package/admin/src/components/Permissions/PermissionRow/SubCategory/PolicyWrapper.js +0 -8
  149. package/admin/src/components/Permissions/PermissionRow/SubCategory/SubCategoryWrapper.js +0 -26
  150. package/admin/src/components/Permissions/PermissionRow/SubCategory/index.js +0 -116
  151. package/admin/src/components/Policies/Components.js +0 -26
  152. package/admin/src/components/PrefixedIcon/index.js +0 -27
  153. package/admin/src/components/Roles/EmptyRole/BaselineAlignment.js +0 -7
  154. package/admin/src/components/Roles/EmptyRole/index.js +0 -27
  155. package/admin/src/components/Roles/RoleListWrapper/index.js +0 -17
  156. package/admin/src/components/Roles/RoleRow/RoleDescription.js +0 -9
  157. package/admin/src/components/Roles/RoleRow/index.js +0 -45
  158. package/admin/src/components/Roles/index.js +0 -3
  159. package/admin/src/components/SizedInput/index.js +0 -24
  160. package/admin/src/pages/AdvancedSettings/reducer.js +0 -65
  161. package/admin/src/pages/AdvancedSettings/utils/form.js +0 -52
  162. package/admin/src/pages/EmailTemplates/CustomTextInput.js +0 -105
  163. package/admin/src/pages/EmailTemplates/Wrapper.js +0 -36
  164. package/admin/src/pages/EmailTemplates/reducer.js +0 -58
  165. package/admin/src/pages/EmailTemplates/utils/forms.js +0 -81
  166. package/admin/src/pages/Roles/ListPage/BaselineAlignment.js +0 -8
  167. package/server/content-types/permission/schema.json +0 -48
  168. package/server/content-types/role/schema.json +0 -46
  169. package/server/content-types/user/schema.json +0 -66
  170. package/server/controllers/user/admin.js +0 -230
  171. package/server/controllers/user/api.js +0 -174
  172. package/server/controllers/users-permissions.js +0 -271
  173. package/server/middlewares/users-permissions.js +0 -44
  174. package/server/policies/index.js +0 -11
  175. package/server/policies/isAuthenticated.js +0 -9
  176. package/server/policies/permissions.js +0 -94
  177. package/server/schema.graphql.js +0 -317
@@ -1,346 +1,198 @@
1
1
  'use strict';
2
2
 
3
3
  const _ = require('lodash');
4
- const request = require('request');
4
+ const { filter, map, pipe, prop } = require('lodash/fp');
5
+
5
6
  const { getService } = require('../utils');
6
7
 
7
8
  const DEFAULT_PERMISSIONS = [
8
- { action: 'admincallback', controller: 'auth', type: 'users-permissions', roleType: 'public' },
9
- { action: 'adminregister', controller: 'auth', type: 'users-permissions', roleType: 'public' },
10
- { action: 'callback', controller: 'auth', type: 'users-permissions', roleType: 'public' },
11
- { action: 'connect', controller: 'auth', type: 'users-permissions', roleType: null },
12
- { action: 'forgotpassword', controller: 'auth', type: 'users-permissions', roleType: 'public' },
13
- { action: 'resetpassword', controller: 'auth', type: 'users-permissions', roleType: 'public' },
14
- { action: 'register', controller: 'auth', type: 'users-permissions', roleType: 'public' },
15
- {
16
- action: 'emailconfirmation',
17
- controller: 'auth',
18
- type: 'users-permissions',
19
- roleType: 'public',
20
- },
21
- { action: 'me', controller: 'user', type: 'users-permissions', roleType: null },
9
+ { action: 'plugin::users-permissions.auth.admincallback', roleType: 'public' },
10
+ { action: 'plugin::users-permissions.auth.adminregister', roleType: 'public' },
11
+ { action: 'plugin::users-permissions.auth.callback', roleType: 'public' },
12
+ { action: 'plugin::users-permissions.auth.connect', roleType: null },
13
+ { action: 'plugin::users-permissions.auth.forgotpassword', roleType: 'public' },
14
+ { action: 'plugin::users-permissions.auth.resetpassword', roleType: 'public' },
15
+ { action: 'plugin::users-permissions.auth.register', roleType: 'public' },
16
+ { action: 'plugin::users-permissions.auth.emailconfirmation', roleType: 'public' },
17
+ { action: 'plugin::users-permissions.user.me', roleType: null },
22
18
  ];
23
19
 
24
- const isEnabledByDefault = (permission, role) => {
25
- return DEFAULT_PERMISSIONS.some(
26
- defaultPerm =>
27
- (defaultPerm.action === null || permission.action === defaultPerm.action) &&
28
- (defaultPerm.controller === null || permission.controller === defaultPerm.controller) &&
29
- (defaultPerm.type === null || permission.type === defaultPerm.type) &&
30
- (defaultPerm.roleType === null || role.type === defaultPerm.roleType)
31
- );
20
+ const transformRoutePrefixFor = pluginName => route => {
21
+ const prefix = route.config && route.config.prefix;
22
+ const path = prefix !== undefined ? `${prefix}${route.path}` : `/${pluginName}${route.path}`;
23
+
24
+ return {
25
+ ...route,
26
+ path,
27
+ };
32
28
  };
33
29
 
34
30
  module.exports = ({ strapi }) => ({
35
- async createRole(params) {
36
- if (!params.type) {
37
- params.type = _.snakeCase(_.deburr(_.toLower(params.name)));
38
- }
31
+ getActions({ defaultEnable = false } = {}) {
32
+ const actionMap = {};
39
33
 
40
- const role = await strapi
41
- .query('plugin::users-permissions.role')
42
- .create({ data: _.omit(params, ['users', 'permissions']) });
34
+ const isContentApi = action => {
35
+ if (!_.has(action, Symbol.for('__type__'))) {
36
+ return false;
37
+ }
43
38
 
44
- const arrayOfPromises = Object.keys(params.permissions || {}).reduce((acc, type) => {
45
- Object.keys(params.permissions[type].controllers).forEach(controller => {
46
- Object.keys(params.permissions[type].controllers[controller]).forEach(action => {
47
- acc.push(
48
- strapi.query('plugin::users-permissions.permission').create({
49
- data: {
50
- role: role.id,
51
- type,
52
- controller,
53
- action: action.toLowerCase(),
54
- ...params.permissions[type].controllers[controller][action],
55
- },
56
- })
57
- );
58
- });
59
- });
39
+ return action[Symbol.for('__type__')].includes('content-api');
40
+ };
60
41
 
61
- return acc;
62
- }, []);
63
-
64
- // Use Content Manager business logic to handle relation.
65
- if (params.users && params.users.length > 0)
66
- arrayOfPromises.push(
67
- strapi.query('plugin::users-permissions.role').update({
68
- where: {
69
- id: role.id,
70
- },
71
- data: { users: params.users },
72
- })
73
- );
42
+ _.forEach(strapi.api, (api, apiName) => {
43
+ const controllers = _.reduce(
44
+ api.controllers,
45
+ (acc, controller, controllerName) => {
46
+ const contentApiActions = _.pickBy(controller, isContentApi);
74
47
 
75
- return await Promise.all(arrayOfPromises);
76
- },
77
-
78
- async deleteRole(roleID, publicRoleID) {
79
- const role = await strapi
80
- .query('plugin::users-permissions.role')
81
- .findOne({ where: { id: roleID }, populate: ['users', 'permissions'] });
48
+ if (_.isEmpty(contentApiActions)) {
49
+ return acc;
50
+ }
82
51
 
83
- if (!role) {
84
- throw new Error('Cannot find this role');
85
- }
52
+ acc[controllerName] = _.mapValues(contentApiActions, () => {
53
+ return {
54
+ enabled: defaultEnable,
55
+ policy: '',
56
+ };
57
+ });
86
58
 
87
- // Move users to guest role.
88
- const arrayOfPromises = role.users.reduce((acc, user) => {
89
- acc.push(
90
- strapi.query('plugin::users-permissions.user').update({
91
- where: {
92
- id: user.id,
93
- },
94
- data: {
95
- role: publicRoleID,
96
- },
97
- })
59
+ return acc;
60
+ },
61
+ {}
98
62
  );
99
63
 
100
- return acc;
101
- }, []);
102
-
103
- // Remove permissions related to this role.
104
- role.permissions.forEach(permission => {
105
- arrayOfPromises.push(
106
- strapi.query('plugin::users-permissions.permission').delete({
107
- where: { id: permission.id },
108
- })
109
- );
64
+ if (!_.isEmpty(controllers)) {
65
+ actionMap[`api::${apiName}`] = { controllers };
66
+ }
110
67
  });
111
68
 
112
- // Delete the role.
113
- arrayOfPromises.push(
114
- strapi.query('plugin::users-permissions.role').delete({ where: { id: roleID } })
115
- );
69
+ _.forEach(strapi.plugins, (plugin, pluginName) => {
70
+ const controllers = _.reduce(
71
+ plugin.controllers,
72
+ (acc, controller, controllerName) => {
73
+ const contentApiActions = _.pickBy(controller, isContentApi);
116
74
 
117
- return await Promise.all(arrayOfPromises);
118
- },
119
-
120
- getPlugins(lang = 'en') {
121
- return new Promise(resolve => {
122
- request(
123
- {
124
- uri: `https://marketplace.strapi.io/plugins?lang=${lang}`,
125
- json: true,
126
- timeout: 3000,
127
- headers: {
128
- 'cache-control': 'max-age=3600',
129
- },
130
- },
131
- (err, response, body) => {
132
- if (err || response.statusCode !== 200) {
133
- return resolve([]);
75
+ if (_.isEmpty(contentApiActions)) {
76
+ return acc;
134
77
  }
135
78
 
136
- resolve(body);
137
- }
138
- );
139
- });
140
- },
141
-
142
- getActions() {
143
- const generateActions = data =>
144
- Object.keys(data).reduce((acc, key) => {
145
- if (_.isFunction(data[key])) {
146
- acc[key] = { enabled: false, policy: '' };
147
- }
148
-
149
- return acc;
150
- }, {});
151
-
152
- const appControllers = Object.keys(strapi.api || {})
153
- .filter(key => !!strapi.api[key].controllers)
154
- .reduce(
155
- (acc, key) => {
156
- Object.keys(strapi.api[key].controllers).forEach(controller => {
157
- acc.controllers[controller] = generateActions(strapi.api[key].controllers[controller]);
79
+ acc[controllerName] = _.mapValues(contentApiActions, () => {
80
+ return {
81
+ enabled: defaultEnable,
82
+ policy: '',
83
+ };
158
84
  });
159
85
 
160
86
  return acc;
161
87
  },
162
- { controllers: {} }
88
+ {}
163
89
  );
164
90
 
165
- const pluginsPermissions = Object.keys(strapi.plugins).reduce((acc, key) => {
166
- const initialState = {
167
- controllers: {},
168
- };
169
-
170
- const pluginControllers = strapi.plugin(key).controllers;
171
- acc[key] = Object.keys(pluginControllers).reduce((obj, k) => {
172
- obj.controllers[k] = generateActions(pluginControllers[k]);
173
-
174
- return obj;
175
- }, initialState);
176
-
177
- return acc;
178
- }, {});
179
-
180
- const permissions = {
181
- application: {
182
- controllers: appControllers.controllers,
183
- },
184
- };
91
+ if (!_.isEmpty(controllers)) {
92
+ actionMap[`plugin::${pluginName}`] = { controllers };
93
+ }
94
+ });
185
95
 
186
- return _.merge(permissions, pluginsPermissions);
96
+ return actionMap;
187
97
  },
188
98
 
189
- async getRole(roleID, plugins) {
190
- const role = await strapi
191
- .query('plugin::users-permissions.role')
192
- .findOne({ where: { id: roleID }, populate: ['permissions'] });
99
+ async getRoutes() {
100
+ const routesMap = {};
193
101
 
194
- if (!role) {
195
- throw new Error('Cannot find this role');
196
- }
102
+ _.forEach(strapi.api, (api, apiName) => {
103
+ const routes = _.flatMap(api.routes, route => {
104
+ if (_.has(route, 'routes')) {
105
+ return route.routes;
106
+ }
197
107
 
198
- // Group by `type`.
199
- const permissions = role.permissions.reduce((acc, permission) => {
200
- _.set(acc, `${permission.type}.controllers.${permission.controller}.${permission.action}`, {
201
- enabled: _.toNumber(permission.enabled) == true,
202
- policy: permission.policy,
203
- });
108
+ return route;
109
+ }).filter(route => route.info.type === 'content-api');
204
110
 
205
- if (permission.type !== 'application' && !acc[permission.type].information) {
206
- acc[permission.type].information =
207
- plugins.find(plugin => plugin.id === permission.type) || {};
111
+ if (routes.length === 0) {
112
+ return;
208
113
  }
209
114
 
210
- return acc;
211
- }, {});
212
-
213
- return {
214
- ...role,
215
- permissions,
216
- };
217
- },
218
-
219
- async getRoles() {
220
- const roles = await strapi.query('plugin::users-permissions.role').findMany({ sort: ['name'] });
221
-
222
- for (let i = 0; i < roles.length; ++i) {
223
- roles[i].nb_users = await strapi
224
- .query('plugin::users-permissions.user')
225
- .count({ where: { role: { id: roles[i].id } } });
226
- }
115
+ routesMap[`api::${apiName}`] = routes.map(route => ({
116
+ ...route,
117
+ path: `/api${route.path}`,
118
+ }));
119
+ });
227
120
 
228
- return roles;
229
- },
121
+ _.forEach(strapi.plugins, (plugin, pluginName) => {
122
+ const transformPrefix = transformRoutePrefixFor(pluginName);
230
123
 
231
- async getRoutes() {
232
- const routes = Object.keys(strapi.api || {}).reduce((acc, current) => {
233
- return acc.concat(_.get(strapi.api[current].config, 'routes', []));
234
- }, []);
235
- const pluginsRoutes = Object.keys(strapi.plugins).reduce((acc, current) => {
236
- const routes = strapi.plugin(current).routes.reduce((acc, curr) => {
237
- const prefix = curr.config.prefix;
238
- const path = prefix !== undefined ? `${prefix}${curr.path}` : `/${current}${curr.path}`;
239
- _.set(curr, 'path', path);
124
+ const routes = _.flatMap(plugin.routes, route => {
125
+ if (_.has(route, 'routes')) {
126
+ return route.routes.map(transformPrefix);
127
+ }
240
128
 
241
- return acc.concat(curr);
242
- }, []);
129
+ return transformPrefix(route);
130
+ }).filter(route => route.info.type === 'content-api');
243
131
 
244
- acc[current] = routes;
132
+ if (routes.length === 0) {
133
+ return;
134
+ }
245
135
 
246
- return acc;
247
- }, {});
136
+ routesMap[`plugin::${pluginName}`] = routes.map(route => ({
137
+ ...route,
138
+ path: `/api${route.path}`,
139
+ }));
140
+ });
248
141
 
249
- return _.merge({ application: routes }, pluginsRoutes);
142
+ return routesMap;
250
143
  },
251
144
 
252
- async updatePermissions() {
145
+ async syncPermissions() {
253
146
  const roles = await strapi.query('plugin::users-permissions.role').findMany();
147
+ const dbPermissions = await strapi.query('plugin::users-permissions.permission').findMany();
254
148
 
255
- const rolesMap = _.keyBy(roles, 'id');
256
-
257
- const dbPermissions = await strapi
258
- .query('plugin::users-permissions.permission')
259
- .findMany({ populate: ['role'] });
260
-
261
- let permissionsFoundInDB = dbPermissions.map(permission => {
262
- const { type, controller, action, role } = permission;
263
- return `${type}.${controller}.${action}.${role.id}`;
264
- });
149
+ const permissionsFoundInDB = _.uniq(_.map(dbPermissions, 'action'));
265
150
 
266
- permissionsFoundInDB = _.uniq(permissionsFoundInDB);
267
-
268
- // Aggregate first level actions.
269
- const appActions = Object.keys(strapi.api || {}).reduce((acc, api) => {
270
- Object.keys(_.get(strapi.api[api], 'controllers', {})).forEach(controller => {
271
- const actions = Object.keys(strapi.api[api].controllers[controller])
272
- .filter(action => _.isFunction(strapi.api[api].controllers[controller][action]))
273
- .map(action => `application.${controller}.${action.toLowerCase()}`);
274
-
275
- acc = acc.concat(actions);
151
+ const appActions = _.flatMap(strapi.api, (api, apiName) => {
152
+ return _.flatMap(api.controllers, (controller, controllerName) => {
153
+ return _.keys(controller).map(actionName => {
154
+ return `api::${apiName}.${controllerName}.${actionName}`;
155
+ });
276
156
  });
157
+ });
277
158
 
278
- return acc;
279
- }, []);
280
-
281
- // Aggregate plugins' actions.
282
- const pluginsActions = Object.keys(strapi.plugins).reduce((acc, plugin) => {
283
- const pluginControllers = strapi.plugin(plugin).controllers;
284
-
285
- Object.keys(pluginControllers).forEach(controller => {
286
- const controllerActions = pluginControllers[controller];
287
-
288
- const actions = Object.keys(controllerActions)
289
- .filter(action => _.isFunction(controllerActions[action]))
290
- .map(action => `${plugin}.${controller}.${action.toLowerCase()}`);
291
-
292
- acc = acc.concat(actions);
159
+ const pluginsActions = _.flatMap(strapi.plugins, (plugin, pluginName) => {
160
+ return _.flatMap(plugin.controllers, (controller, controllerName) => {
161
+ return _.keys(controller).map(actionName => {
162
+ return `plugin::${pluginName}.${controllerName}.${actionName}`;
163
+ });
293
164
  });
165
+ });
294
166
 
295
- return acc;
296
- }, []);
297
-
298
- const actionsFoundInFiles = appActions.concat(pluginsActions);
167
+ const allActions = [...appActions, ...pluginsActions];
299
168
 
300
- const permissionsFoundInFiles = [];
169
+ const toDelete = _.difference(permissionsFoundInDB, allActions);
301
170
 
302
- for (const role of roles) {
303
- actionsFoundInFiles.forEach(action => {
304
- permissionsFoundInFiles.push(`${action}.${role.id}`);
305
- });
306
- }
307
-
308
- // Compare to know if actions have been added or removed from controllers.
309
- if (!_.isEqual(permissionsFoundInDB.sort(), permissionsFoundInFiles.sort())) {
310
- const splitted = str => {
311
- const [type, controller, action, roleId] = str.split('.');
312
-
313
- return { type, controller, action, roleId };
314
- };
315
-
316
- // We have to know the difference to add or remove the permissions entries in the database.
317
- const toRemove = _.difference(permissionsFoundInDB, permissionsFoundInFiles).map(splitted);
318
- const toAdd = _.difference(permissionsFoundInFiles, permissionsFoundInDB).map(splitted);
319
-
320
- const query = strapi.query('plugin::users-permissions.permission');
321
-
322
- // Execute request to update entries in database for each role.
323
- await Promise.all(
324
- toAdd.map(permission => {
325
- return query.create({
326
- data: {
327
- type: permission.type,
328
- controller: permission.controller,
329
- action: permission.action,
330
- enabled: isEnabledByDefault(permission, rolesMap[permission.roleId]),
331
- policy: '',
332
- role: permission.roleId,
333
- },
334
- });
335
- })
336
- );
171
+ await Promise.all(
172
+ toDelete.map(action => {
173
+ return strapi.query('plugin::users-permissions.permission').delete({ where: { action } });
174
+ })
175
+ );
337
176
 
338
- await Promise.all(
339
- toRemove.map(permission => {
340
- const { type, controller, action, roleId } = permission;
341
- return query.delete({ where: { type, controller, action, role: { id: roleId } } });
342
- })
343
- );
177
+ if (permissionsFoundInDB.length === 0) {
178
+ // create default permissions
179
+ for (const role of roles) {
180
+ const toCreate = pipe(
181
+ filter(({ roleType }) => roleType === role.type || roleType === null),
182
+ map(prop('action'))
183
+ )(DEFAULT_PERMISSIONS);
184
+
185
+ await Promise.all(
186
+ toCreate.map(action => {
187
+ return strapi.query('plugin::users-permissions.permission').create({
188
+ data: {
189
+ action,
190
+ role: role.id,
191
+ },
192
+ });
193
+ })
194
+ );
195
+ }
344
196
  }
345
197
  },
346
198
 
@@ -365,57 +217,7 @@ module.exports = ({ strapi }) => ({
365
217
  });
366
218
  }
367
219
 
368
- return getService('users-permissions').updatePermissions();
369
- },
370
-
371
- async updateRole(roleID, body) {
372
- const [role, authenticated] = await Promise.all([
373
- this.getRole(roleID, []),
374
- strapi.query('plugin::users-permissions.role').findOne({ where: { type: 'authenticated' } }),
375
- ]);
376
-
377
- await strapi.query('plugin::users-permissions.role').update({
378
- where: { id: roleID },
379
- data: _.pick(body, ['name', 'description']),
380
- });
381
-
382
- await Promise.all(
383
- Object.keys(body.permissions || {}).reduce((acc, type) => {
384
- Object.keys(body.permissions[type].controllers).forEach(controller => {
385
- Object.keys(body.permissions[type].controllers[controller]).forEach(action => {
386
- const bodyAction = body.permissions[type].controllers[controller][action];
387
- const currentAction = _.get(
388
- role.permissions,
389
- `${type}.controllers.${controller}.${action}`,
390
- {}
391
- );
392
-
393
- if (!_.isEqual(bodyAction, currentAction)) {
394
- acc.push(
395
- strapi.query('plugin::users-permissions.permission').update({
396
- where: {
397
- role: roleID,
398
- type,
399
- controller,
400
- action: action.toLowerCase(),
401
- },
402
- data: bodyAction,
403
- })
404
- );
405
- }
406
- });
407
- });
408
-
409
- return acc;
410
- }, [])
411
- );
412
-
413
- // Add user to this role.
414
- const newUsers = _.differenceBy(body.users, role.users, 'id');
415
- await Promise.all(newUsers.map(user => this.updateUserRole(user, roleID)));
416
-
417
- const oldUsers = _.differenceBy(role.users, body.users, 'id');
418
- await Promise.all(oldUsers.map(user => this.updateUserRole(user, authenticated.id)));
220
+ return getService('users-permissions').syncPermissions();
419
221
  },
420
222
 
421
223
  async updateUserRole(user, role) {
@@ -0,0 +1,123 @@
1
+ 'use strict';
2
+
3
+ const { castArray, map } = require('lodash/fp');
4
+ const { ForbiddenError, UnauthorizedError } = require('@strapi/utils').errors;
5
+
6
+ const { getService } = require('../utils');
7
+
8
+ const getAdvancedSettings = () => {
9
+ return strapi.store({ type: 'plugin', name: 'users-permissions' }).get({ key: 'advanced' });
10
+ };
11
+
12
+ const authenticate = async ctx => {
13
+ try {
14
+ const token = await getService('jwt').getToken(ctx);
15
+
16
+ if (token) {
17
+ const { id } = token;
18
+
19
+ if (id === undefined) {
20
+ return { authenticated: false };
21
+ }
22
+
23
+ // fetch authenticated user
24
+ const user = await getService('user').fetchAuthenticatedUser(id);
25
+
26
+ if (!user) {
27
+ return { error: 'Invalid credentials' };
28
+ }
29
+
30
+ const advancedSettings = await getAdvancedSettings();
31
+
32
+ if (advancedSettings.email_confirmation && !user.confirmed) {
33
+ return { error: 'Invalid credentials' };
34
+ }
35
+
36
+ if (user.blocked) {
37
+ return { error: 'Invalid credentials' };
38
+ }
39
+
40
+ ctx.state.user = user;
41
+
42
+ return {
43
+ authenticated: true,
44
+ credentials: user,
45
+ };
46
+ }
47
+
48
+ const publicPermissions = await strapi.query('plugin::users-permissions.permission').findMany({
49
+ where: {
50
+ role: { type: 'public' },
51
+ },
52
+ });
53
+
54
+ if (publicPermissions.length === 0) {
55
+ return { authenticated: false };
56
+ }
57
+
58
+ return {
59
+ authenticated: true,
60
+ credentials: null,
61
+ };
62
+ } catch (err) {
63
+ return { authenticated: false };
64
+ }
65
+ };
66
+
67
+ const verify = async (auth, config) => {
68
+ const { credentials: user } = auth;
69
+
70
+ // public accesss
71
+ if (!user) {
72
+ // test against public role
73
+ const publicPermissions = await strapi.query('plugin::users-permissions.permission').findMany({
74
+ where: {
75
+ role: { type: 'public' },
76
+ },
77
+ });
78
+
79
+ const allowedActions = map('action', publicPermissions);
80
+
81
+ // A non authenticated user cannot access routes that do not have a scope
82
+ if (!config.scope) {
83
+ throw new UnauthorizedError();
84
+ }
85
+
86
+ const isAllowed = castArray(config.scope).every(scope => allowedActions.includes(scope));
87
+
88
+ if (!isAllowed) {
89
+ throw new ForbiddenError();
90
+ }
91
+
92
+ return;
93
+ }
94
+
95
+ const permissions = await strapi.query('plugin::users-permissions.permission').findMany({
96
+ where: { role: user.role.id },
97
+ });
98
+
99
+ const allowedActions = map('action', permissions);
100
+
101
+ // An authenticated user can access non scoped routes
102
+ if (!config.scope) {
103
+ return;
104
+ }
105
+
106
+ const isAllowed = castArray(config.scope).every(scope => allowedActions.includes(scope));
107
+
108
+ if (!isAllowed) {
109
+ throw new ForbiddenError();
110
+ }
111
+
112
+ // TODO: if we need to keep policies for u&p execution
113
+ // Execute the policies.
114
+ // if (permission.policy) {
115
+ // return await strapi.plugin('users-permissions').policy(permission.policy)(ctx, next);
116
+ // }
117
+ };
118
+
119
+ module.exports = {
120
+ name: 'users-permissions',
121
+ authenticate,
122
+ verify,
123
+ };
@@ -1,11 +1,13 @@
1
1
  import * as usersPermissions from '../services/users-permissions';
2
2
  import * as user from '../services/user';
3
+ import * as role from '../services/role';
3
4
  import * as jwt from '../services/jwt';
4
5
  import * as providers from '../services/providers';
5
6
 
6
7
 
7
8
  type S = {
8
9
  ['users-permissions']: typeof usersPermissions;
10
+ ['role']: typeof role;
9
11
  user: typeof user;
10
12
  jwt: typeof jwt;
11
13
  providers: typeof providers;