@akemona-org/strapi-plugin-users-permissions 3.7.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 (143) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +19 -0
  3. package/admin/src/assets/images/logo.svg +1 -0
  4. package/admin/src/components/BaselineAlignement/index.js +33 -0
  5. package/admin/src/components/Bloc/index.js +10 -0
  6. package/admin/src/components/BoundRoute/Components.js +78 -0
  7. package/admin/src/components/BoundRoute/index.js +56 -0
  8. package/admin/src/components/ContainerFluid/index.js +13 -0
  9. package/admin/src/components/FormBloc/index.js +61 -0
  10. package/admin/src/components/IntlInput/index.js +38 -0
  11. package/admin/src/components/ListBaselineAlignment/index.js +8 -0
  12. package/admin/src/components/ListRow/Components.js +74 -0
  13. package/admin/src/components/ListRow/index.js +35 -0
  14. package/admin/src/components/ModalForm/Wrapper.js +12 -0
  15. package/admin/src/components/ModalForm/index.js +59 -0
  16. package/admin/src/components/Permissions/ListWrapper.js +9 -0
  17. package/admin/src/components/Permissions/PermissionRow/BaselineAlignment.js +7 -0
  18. package/admin/src/components/Permissions/PermissionRow/CheckboxWrapper.js +37 -0
  19. package/admin/src/components/Permissions/PermissionRow/RowStyle.js +28 -0
  20. package/admin/src/components/Permissions/PermissionRow/SubCategory/ConditionsButtonWrapper.js +13 -0
  21. package/admin/src/components/Permissions/PermissionRow/SubCategory/PolicyWrapper.js +8 -0
  22. package/admin/src/components/Permissions/PermissionRow/SubCategory/SubCategoryWrapper.js +26 -0
  23. package/admin/src/components/Permissions/PermissionRow/SubCategory/index.js +116 -0
  24. package/admin/src/components/Permissions/PermissionRow/index.js +92 -0
  25. package/admin/src/components/Permissions/index.js +44 -0
  26. package/admin/src/components/Permissions/init.js +14 -0
  27. package/admin/src/components/Permissions/reducer.js +27 -0
  28. package/admin/src/components/Policies/Components.js +26 -0
  29. package/admin/src/components/Policies/index.js +61 -0
  30. package/admin/src/components/PrefixedIcon/index.js +27 -0
  31. package/admin/src/components/Roles/EmptyRole/BaselineAlignment.js +7 -0
  32. package/admin/src/components/Roles/EmptyRole/index.js +27 -0
  33. package/admin/src/components/Roles/RoleListWrapper/index.js +17 -0
  34. package/admin/src/components/Roles/RoleRow/RoleDescription.js +9 -0
  35. package/admin/src/components/Roles/RoleRow/index.js +45 -0
  36. package/admin/src/components/Roles/index.js +3 -0
  37. package/admin/src/components/SizedInput/index.js +24 -0
  38. package/admin/src/components/UsersPermissions/index.js +91 -0
  39. package/admin/src/components/UsersPermissions/init.js +11 -0
  40. package/admin/src/components/UsersPermissions/reducer.js +60 -0
  41. package/admin/src/containers/AdvancedSettings/index.js +218 -0
  42. package/admin/src/containers/AdvancedSettings/reducer.js +65 -0
  43. package/admin/src/containers/AdvancedSettings/utils/form.js +52 -0
  44. package/admin/src/containers/EmailTemplates/CustomTextInput.js +105 -0
  45. package/admin/src/containers/EmailTemplates/Wrapper.js +36 -0
  46. package/admin/src/containers/EmailTemplates/index.js +222 -0
  47. package/admin/src/containers/EmailTemplates/reducer.js +58 -0
  48. package/admin/src/containers/EmailTemplates/utils/forms.js +81 -0
  49. package/admin/src/containers/EmailTemplates/utils/schema.js +25 -0
  50. package/admin/src/containers/Providers/index.js +283 -0
  51. package/admin/src/containers/Providers/reducer.js +54 -0
  52. package/admin/src/containers/Providers/utils/createProvidersArray.js +21 -0
  53. package/admin/src/containers/Providers/utils/forms.js +205 -0
  54. package/admin/src/containers/Roles/CreatePage/index.js +167 -0
  55. package/admin/src/containers/Roles/CreatePage/utils/schema.js +9 -0
  56. package/admin/src/containers/Roles/EditPage/index.js +161 -0
  57. package/admin/src/containers/Roles/EditPage/utils/schema.js +9 -0
  58. package/admin/src/containers/Roles/ListPage/BaselineAlignment.js +8 -0
  59. package/admin/src/containers/Roles/ListPage/index.js +188 -0
  60. package/admin/src/containers/Roles/ProtectedCreatePage/index.js +12 -0
  61. package/admin/src/containers/Roles/ProtectedEditPage/index.js +12 -0
  62. package/admin/src/containers/Roles/ProtectedListPage/index.js +15 -0
  63. package/admin/src/containers/Roles/index.js +35 -0
  64. package/admin/src/contexts/EditPage/index.js +26 -0
  65. package/admin/src/contexts/HomePage/index.js +27 -0
  66. package/admin/src/contexts/UsersPermissionsContext/index.js +17 -0
  67. package/admin/src/hooks/index.js +5 -0
  68. package/admin/src/hooks/useFetchRole/index.js +55 -0
  69. package/admin/src/hooks/useFetchRole/reducer.js +31 -0
  70. package/admin/src/hooks/useForm/index.js +96 -0
  71. package/admin/src/hooks/useForm/reducer.js +59 -0
  72. package/admin/src/hooks/usePlugins/index.js +73 -0
  73. package/admin/src/hooks/usePlugins/init.js +5 -0
  74. package/admin/src/hooks/usePlugins/reducer.js +37 -0
  75. package/admin/src/hooks/useRolesList/index.js +62 -0
  76. package/admin/src/hooks/useRolesList/init.js +5 -0
  77. package/admin/src/hooks/useRolesList/reducer.js +31 -0
  78. package/admin/src/index.js +109 -0
  79. package/admin/src/permissions.js +33 -0
  80. package/admin/src/pluginId.js +5 -0
  81. package/admin/src/translations/ar.json +49 -0
  82. package/admin/src/translations/cs.json +55 -0
  83. package/admin/src/translations/de.json +68 -0
  84. package/admin/src/translations/dk.json +116 -0
  85. package/admin/src/translations/en.json +104 -0
  86. package/admin/src/translations/es.json +70 -0
  87. package/admin/src/translations/fr.json +55 -0
  88. package/admin/src/translations/id.json +69 -0
  89. package/admin/src/translations/index.js +55 -0
  90. package/admin/src/translations/it.json +68 -0
  91. package/admin/src/translations/ja.json +53 -0
  92. package/admin/src/translations/ko.json +55 -0
  93. package/admin/src/translations/ms.json +54 -0
  94. package/admin/src/translations/nl.json +53 -0
  95. package/admin/src/translations/pl.json +55 -0
  96. package/admin/src/translations/pt-BR.json +49 -0
  97. package/admin/src/translations/pt.json +53 -0
  98. package/admin/src/translations/ru.json +68 -0
  99. package/admin/src/translations/sk.json +57 -0
  100. package/admin/src/translations/sv.json +68 -0
  101. package/admin/src/translations/th.json +66 -0
  102. package/admin/src/translations/tr.json +53 -0
  103. package/admin/src/translations/uk.json +54 -0
  104. package/admin/src/translations/vi.json +55 -0
  105. package/admin/src/translations/zh-Hans.json +104 -0
  106. package/admin/src/translations/zh.json +53 -0
  107. package/admin/src/utils/cleanPermissions.js +25 -0
  108. package/admin/src/utils/formatPolicies.js +8 -0
  109. package/admin/src/utils/getRequestURL.js +5 -0
  110. package/admin/src/utils/getTrad.js +5 -0
  111. package/admin/src/utils/index.js +4 -0
  112. package/config/functions/bootstrap.js +234 -0
  113. package/config/layout.js +10 -0
  114. package/config/policies/isAuthenticated.js +9 -0
  115. package/config/policies/permissions.js +93 -0
  116. package/config/policies/rateLimit.js +33 -0
  117. package/config/request.json +6 -0
  118. package/config/routes.json +397 -0
  119. package/config/schema.graphql.js +280 -0
  120. package/config/security.json +5 -0
  121. package/config/users-permissions-actions.js +80 -0
  122. package/controllers/Auth.js +612 -0
  123. package/controllers/User.js +125 -0
  124. package/controllers/UsersPermissions.js +291 -0
  125. package/controllers/user/admin.js +224 -0
  126. package/controllers/user/api.js +173 -0
  127. package/controllers/validation/email-template.js +40 -0
  128. package/documentation/1.0.0/overrides/users-permissions-Role.json +281 -0
  129. package/documentation/1.0.0/overrides/users-permissions-User.json +325 -0
  130. package/middlewares/users-permissions/defaults.json +5 -0
  131. package/middlewares/users-permissions/index.js +40 -0
  132. package/models/Permission.js +7 -0
  133. package/models/Permission.settings.json +43 -0
  134. package/models/Role.js +7 -0
  135. package/models/Role.settings.json +42 -0
  136. package/models/User.config.js +15 -0
  137. package/models/User.js +7 -0
  138. package/models/User.settings.json +62 -0
  139. package/package.json +70 -0
  140. package/services/Jwt.js +65 -0
  141. package/services/Providers.js +596 -0
  142. package/services/User.js +167 -0
  143. package/services/UsersPermissions.js +416 -0
@@ -0,0 +1,125 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * User.js controller
5
+ *
6
+ * @description: A set of functions called "actions" for managing `User`.
7
+ */
8
+
9
+ const _ = require('lodash');
10
+ const { sanitizeEntity } = require('@akemona-org/strapi-utils');
11
+ const adminUserController = require('./user/admin');
12
+ const apiUserController = require('./user/api');
13
+
14
+ const sanitizeUser = (user) =>
15
+ sanitizeEntity(user, {
16
+ model: strapi.query('user', 'users-permissions').model,
17
+ });
18
+
19
+ const resolveController = (ctx) => {
20
+ const {
21
+ state: { isAuthenticatedAdmin },
22
+ } = ctx;
23
+
24
+ return isAuthenticatedAdmin ? adminUserController : apiUserController;
25
+ };
26
+
27
+ const resolveControllerMethod = (method) => (ctx) => {
28
+ const controller = resolveController(ctx);
29
+ const callbackFn = controller[method];
30
+
31
+ if (!_.isFunction(callbackFn)) {
32
+ return ctx.notFound();
33
+ }
34
+
35
+ return callbackFn(ctx);
36
+ };
37
+
38
+ module.exports = {
39
+ create: resolveControllerMethod('create'),
40
+ update: resolveControllerMethod('update'),
41
+
42
+ /**
43
+ * Retrieve user records.
44
+ * @return {Object|Array}
45
+ */
46
+ async find(ctx, next, { populate } = {}) {
47
+ let users;
48
+
49
+ if (_.has(ctx.query, '_q')) {
50
+ // use core strapi query to search for users
51
+ users = await strapi.query('user', 'users-permissions').search(ctx.query, populate);
52
+ } else {
53
+ users = await strapi.plugins['users-permissions'].services.user.fetchAll(ctx.query, populate);
54
+ }
55
+
56
+ ctx.body = users.map(sanitizeUser);
57
+ },
58
+
59
+ /**
60
+ * Retrieve a user record.
61
+ * @return {Object}
62
+ */
63
+ async findOne(ctx) {
64
+ const { id } = ctx.params;
65
+ let data = await strapi.plugins['users-permissions'].services.user.fetch({
66
+ id,
67
+ });
68
+
69
+ if (data) {
70
+ data = sanitizeUser(data);
71
+ }
72
+
73
+ // Send 200 `ok`
74
+ ctx.body = data;
75
+ },
76
+
77
+ /**
78
+ * Retrieve user count.
79
+ * @return {Number}
80
+ */
81
+ async count(ctx) {
82
+ if (_.has(ctx.query, '_q')) {
83
+ return await strapi.plugins['users-permissions'].services.user.countSearch(ctx.query);
84
+ }
85
+ ctx.body = await strapi.plugins['users-permissions'].services.user.count(ctx.query);
86
+ },
87
+
88
+ /**
89
+ * Destroy a/an user record.
90
+ * @return {Object}
91
+ */
92
+ async destroy(ctx) {
93
+ const { id } = ctx.params;
94
+ const data = await strapi.plugins['users-permissions'].services.user.remove({ id });
95
+ ctx.send(sanitizeUser(data));
96
+ },
97
+
98
+ async destroyAll(ctx) {
99
+ const {
100
+ request: { query },
101
+ } = ctx;
102
+
103
+ const toRemove = Object.values(_.omit(query, 'source'));
104
+ const { primaryKey } = strapi.query('user', 'users-permissions');
105
+ const finalQuery = { [`${primaryKey}_in`]: toRemove, _limit: 100 };
106
+
107
+ const data = await strapi.plugins['users-permissions'].services.user.removeAll(finalQuery);
108
+
109
+ ctx.send(data);
110
+ },
111
+
112
+ /**
113
+ * Retrieve authenticated user.
114
+ * @return {Object|Array}
115
+ */
116
+ async me(ctx) {
117
+ const user = ctx.state.user;
118
+
119
+ if (!user) {
120
+ return ctx.badRequest(null, [{ messages: [{ id: 'No authorization header was found' }] }]);
121
+ }
122
+
123
+ ctx.body = sanitizeUser(user);
124
+ },
125
+ };
@@ -0,0 +1,291 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * UsersPermissions.js controller
5
+ *
6
+ * @description: A set of functions called "actions" of the `users-permissions` plugin.
7
+ */
8
+
9
+ const _ = require('lodash');
10
+ const { isValidEmailTemplate } = require('./validation/email-template');
11
+
12
+ module.exports = {
13
+ /**
14
+ * Default action.
15
+ *
16
+ * @return {Object}
17
+ */
18
+ async createRole(ctx) {
19
+ if (_.isEmpty(ctx.request.body)) {
20
+ return ctx.badRequest(null, [{ messages: [{ id: 'Cannot be empty' }] }]);
21
+ }
22
+
23
+ try {
24
+ await strapi.plugins['users-permissions'].services.userspermissions.createRole(
25
+ ctx.request.body
26
+ );
27
+
28
+ ctx.send({ ok: true });
29
+ } catch (err) {
30
+ strapi.log.error(err);
31
+ ctx.badRequest(null, [{ messages: [{ id: 'An error occured' }] }]);
32
+ }
33
+ },
34
+
35
+ async deleteRole(ctx) {
36
+ // Fetch public role.
37
+ const publicRole = await strapi.query('role', 'users-permissions').findOne({ type: 'public' });
38
+
39
+ const publicRoleID = publicRole.id;
40
+
41
+ const roleID = ctx.params.role;
42
+
43
+ if (!roleID) {
44
+ return ctx.badRequest(null, [{ messages: [{ id: 'Bad request' }] }]);
45
+ }
46
+
47
+ // Prevent from removing the public role.
48
+ if (roleID.toString() === publicRoleID.toString()) {
49
+ return ctx.badRequest(null, [{ messages: [{ id: 'Unauthorized' }] }]);
50
+ }
51
+
52
+ try {
53
+ await strapi.plugins['users-permissions'].services.userspermissions.deleteRole(
54
+ roleID,
55
+ publicRoleID
56
+ );
57
+
58
+ ctx.send({ ok: true });
59
+ } catch (err) {
60
+ strapi.log.error(err);
61
+ ctx.badRequest(null, [{ messages: [{ id: 'Bad request' }] }]);
62
+ }
63
+ },
64
+
65
+ async getPermissions(ctx) {
66
+ try {
67
+ const permissions = await strapi.plugins[
68
+ 'users-permissions'
69
+ ].services.userspermissions.getActions();
70
+
71
+ ctx.send({ permissions });
72
+ } catch (err) {
73
+ ctx.badRequest(null, [{ message: [{ id: 'Not Found' }] }]);
74
+ }
75
+ },
76
+
77
+ async getPolicies(ctx) {
78
+ ctx.send({
79
+ policies: _.without(
80
+ _.keys(strapi.plugins['users-permissions'].config.policies),
81
+ 'permissions'
82
+ ),
83
+ });
84
+ },
85
+
86
+ async getRole(ctx) {
87
+ const { id } = ctx.params;
88
+ const { lang } = ctx.query;
89
+ const plugins = await strapi.plugins['users-permissions'].services.userspermissions.getPlugins(
90
+ lang
91
+ );
92
+ const role = await strapi.plugins['users-permissions'].services.userspermissions.getRole(
93
+ id,
94
+ plugins
95
+ );
96
+
97
+ if (_.isEmpty(role)) {
98
+ return ctx.badRequest(null, [{ messages: [{ id: `Role don't exist` }] }]);
99
+ }
100
+
101
+ ctx.send({ role });
102
+ },
103
+
104
+ async getRoles(ctx) {
105
+ try {
106
+ const roles = await strapi.plugins['users-permissions'].services.userspermissions.getRoles();
107
+
108
+ ctx.send({ roles });
109
+ } catch (err) {
110
+ ctx.badRequest(null, [{ messages: [{ id: 'Not found' }] }]);
111
+ }
112
+ },
113
+
114
+ async getRoutes(ctx) {
115
+ try {
116
+ const routes = await strapi.plugins[
117
+ 'users-permissions'
118
+ ].services.userspermissions.getRoutes();
119
+
120
+ ctx.send({ routes });
121
+ } catch (err) {
122
+ ctx.badRequest(null, [{ messages: [{ id: 'Not found' }] }]);
123
+ }
124
+ },
125
+
126
+ async index(ctx) {
127
+ // Send 200 `ok`
128
+ ctx.send({ message: 'ok' });
129
+ },
130
+
131
+ async searchUsers(ctx) {
132
+ const { id } = ctx.params;
133
+
134
+ const data = await strapi.query('user', 'users-permissions').custom(searchQueries)({
135
+ id,
136
+ });
137
+
138
+ ctx.send(data);
139
+ },
140
+
141
+ async updateRole(ctx) {
142
+ const roleID = ctx.params.role;
143
+
144
+ if (_.isEmpty(ctx.request.body)) {
145
+ return ctx.badRequest(null, [{ messages: [{ id: 'Bad request' }] }]);
146
+ }
147
+
148
+ try {
149
+ await strapi.plugins['users-permissions'].services.userspermissions.updateRole(
150
+ roleID,
151
+ ctx.request.body
152
+ );
153
+
154
+ ctx.send({ ok: true });
155
+ } catch (err) {
156
+ strapi.log.error(err);
157
+ ctx.badRequest(null, [{ messages: [{ id: 'An error occurred' }] }]);
158
+ }
159
+ },
160
+
161
+ async getEmailTemplate(ctx) {
162
+ ctx.send(
163
+ await strapi
164
+ .store({
165
+ environment: '',
166
+ type: 'plugin',
167
+ name: 'users-permissions',
168
+ key: 'email',
169
+ })
170
+ .get()
171
+ );
172
+ },
173
+
174
+ async updateEmailTemplate(ctx) {
175
+ if (_.isEmpty(ctx.request.body)) {
176
+ return ctx.badRequest(null, [{ messages: [{ id: 'Cannot be empty' }] }]);
177
+ }
178
+
179
+ const emailTemplates = ctx.request.body['email-templates'];
180
+
181
+ for (let key in emailTemplates) {
182
+ const template = emailTemplates[key].options.message;
183
+
184
+ if (!isValidEmailTemplate(template)) {
185
+ return ctx.badRequest(null, [{ messages: [{ id: 'Invalid template' }] }]);
186
+ }
187
+ }
188
+
189
+ await strapi
190
+ .store({
191
+ environment: '',
192
+ type: 'plugin',
193
+ name: 'users-permissions',
194
+ key: 'email',
195
+ })
196
+ .set({ value: emailTemplates });
197
+
198
+ ctx.send({ ok: true });
199
+ },
200
+
201
+ async getAdvancedSettings(ctx) {
202
+ ctx.send({
203
+ settings: await strapi
204
+ .store({
205
+ environment: '',
206
+ type: 'plugin',
207
+ name: 'users-permissions',
208
+ key: 'advanced',
209
+ })
210
+ .get(),
211
+ roles: await strapi.plugins['users-permissions'].services.userspermissions.getRoles(),
212
+ });
213
+ },
214
+
215
+ async updateAdvancedSettings(ctx) {
216
+ if (_.isEmpty(ctx.request.body)) {
217
+ return ctx.badRequest(null, [{ messages: [{ id: 'Cannot be empty' }] }]);
218
+ }
219
+
220
+ await strapi
221
+ .store({
222
+ environment: '',
223
+ type: 'plugin',
224
+ name: 'users-permissions',
225
+ key: 'advanced',
226
+ })
227
+ .set({ value: ctx.request.body });
228
+
229
+ ctx.send({ ok: true });
230
+ },
231
+
232
+ async getProviders(ctx) {
233
+ const providers = await strapi
234
+ .store({
235
+ environment: '',
236
+ type: 'plugin',
237
+ name: 'users-permissions',
238
+ key: 'grant',
239
+ })
240
+ .get();
241
+
242
+ for (const provider in providers) {
243
+ if (provider !== 'email') {
244
+ providers[provider].redirectUri = strapi.plugins[
245
+ 'users-permissions'
246
+ ].services.providers.buildRedirectUri(provider);
247
+ }
248
+ }
249
+
250
+ ctx.send(providers);
251
+ },
252
+
253
+ async updateProviders(ctx) {
254
+ if (_.isEmpty(ctx.request.body)) {
255
+ return ctx.badRequest(null, [{ messages: [{ id: 'Cannot be empty' }] }]);
256
+ }
257
+
258
+ await strapi
259
+ .store({
260
+ environment: '',
261
+ type: 'plugin',
262
+ name: 'users-permissions',
263
+ key: 'grant',
264
+ })
265
+ .set({ value: ctx.request.body.providers });
266
+
267
+ ctx.send({ ok: true });
268
+ },
269
+ };
270
+
271
+ const searchQueries = {
272
+ bookshelf({ model }) {
273
+ return ({ id }) => {
274
+ return model
275
+ .query(function(qb) {
276
+ qb.where('username', 'LIKE', `%${id}%`).orWhere('email', 'LIKE', `%${id}%`);
277
+ })
278
+ .fetchAll()
279
+ .then(results => results.toJSON());
280
+ };
281
+ },
282
+ mongoose({ model }) {
283
+ return ({ id }) => {
284
+ const re = new RegExp(id);
285
+
286
+ return model.find({
287
+ $or: [{ username: re }, { email: re }],
288
+ });
289
+ };
290
+ },
291
+ };
@@ -0,0 +1,224 @@
1
+ 'use strict';
2
+
3
+ const _ = require('lodash');
4
+
5
+ const { contentTypes: contentTypesUtils } = require('@akemona-org/strapi-utils');
6
+
7
+ const { UPDATED_BY_ATTRIBUTE, CREATED_BY_ATTRIBUTE } = contentTypesUtils.constants;
8
+
9
+ const formatError = (error) => [
10
+ { messages: [{ id: error.id, message: error.message, field: error.field }] },
11
+ ];
12
+
13
+ const userModel = 'plugins::users-permissions.user';
14
+ const ACTIONS = {
15
+ read: 'plugins::content-manager.explorer.read',
16
+ create: 'plugins::content-manager.explorer.create',
17
+ edit: 'plugins::content-manager.explorer.update',
18
+ delete: 'plugins::content-manager.explorer.delete',
19
+ };
20
+
21
+ const findEntityAndCheckPermissions = async (ability, action, model, id) => {
22
+ const entity = await strapi.query('user', 'users-permissions').findOne({ id });
23
+
24
+ if (_.isNil(entity)) {
25
+ throw strapi.errors.notFound();
26
+ }
27
+
28
+ const pm = strapi.admin.services.permission.createPermissionsManager({ ability, action, model });
29
+
30
+ const roles = _.has(entity, `${CREATED_BY_ATTRIBUTE}.id`)
31
+ ? await strapi.query('role', 'admin').find({ 'users.id': entity[CREATED_BY_ATTRIBUTE].id }, [])
32
+ : [];
33
+ const entityWithRoles = _.set(_.cloneDeep(entity), `${CREATED_BY_ATTRIBUTE}.roles`, roles);
34
+
35
+ if (pm.ability.cannot(pm.action, pm.toSubject(entityWithRoles))) {
36
+ throw strapi.errors.forbidden();
37
+ }
38
+
39
+ return { pm, entity };
40
+ };
41
+
42
+ module.exports = {
43
+ /**
44
+ * Create a/an user record.
45
+ * @return {Object}
46
+ */
47
+ async create(ctx) {
48
+ const {
49
+ request: { body },
50
+ state: { userAbility, admin },
51
+ } = ctx;
52
+ const { email, username, password } = body;
53
+
54
+ const pm = strapi.admin.services.permission.createPermissionsManager({
55
+ ability: userAbility,
56
+ action: ACTIONS.create,
57
+ model: userModel,
58
+ });
59
+
60
+ if (!pm.isAllowed) {
61
+ throw strapi.errors.forbidden();
62
+ }
63
+
64
+ const sanitizedBody = pm.pickPermittedFieldsOf(body, { subject: userModel });
65
+
66
+ const advanced = await strapi
67
+ .store({
68
+ environment: '',
69
+ type: 'plugin',
70
+ name: 'users-permissions',
71
+ key: 'advanced',
72
+ })
73
+ .get();
74
+
75
+ if (!email) return ctx.badRequest('missing.email');
76
+ if (!username) return ctx.badRequest('missing.username');
77
+ if (!password) return ctx.badRequest('missing.password');
78
+
79
+ const userWithSameUsername = await strapi
80
+ .query('user', 'users-permissions')
81
+ .findOne({ username });
82
+
83
+ if (userWithSameUsername) {
84
+ return ctx.badRequest(
85
+ null,
86
+ formatError({
87
+ id: 'Auth.form.error.username.taken',
88
+ message: 'Username already taken.',
89
+ field: ['username'],
90
+ })
91
+ );
92
+ }
93
+
94
+ if (advanced.unique_email) {
95
+ const userWithSameEmail = await strapi
96
+ .query('user', 'users-permissions')
97
+ .findOne({ email: email.toLowerCase() });
98
+
99
+ if (userWithSameEmail) {
100
+ return ctx.badRequest(
101
+ null,
102
+
103
+ formatError({
104
+ id: 'Auth.form.error.email.taken',
105
+ message: 'Email already taken.',
106
+ field: ['email'],
107
+ })
108
+ );
109
+ }
110
+ }
111
+
112
+ const user = {
113
+ ...sanitizedBody,
114
+ provider: 'local',
115
+ [CREATED_BY_ATTRIBUTE]: admin.id,
116
+ [UPDATED_BY_ATTRIBUTE]: admin.id,
117
+ };
118
+
119
+ user.email = user.email.toLowerCase();
120
+
121
+ if (!user.role) {
122
+ const defaultRole = await strapi
123
+ .query('role', 'users-permissions')
124
+ .findOne({ type: advanced.default_role }, []);
125
+
126
+ user.role = defaultRole.id;
127
+ }
128
+
129
+ try {
130
+ const data = await strapi.plugins['users-permissions'].services.user.add(user);
131
+
132
+ ctx.created(pm.sanitize(data, { action: ACTIONS.read }));
133
+ } catch (error) {
134
+ ctx.badRequest(null, formatError(error));
135
+ }
136
+ },
137
+ /**
138
+ * Update a/an user record.
139
+ * @return {Object}
140
+ */
141
+
142
+ async update(ctx) {
143
+ const advancedConfigs = await strapi
144
+ .store({
145
+ environment: '',
146
+ type: 'plugin',
147
+ name: 'users-permissions',
148
+ key: 'advanced',
149
+ })
150
+ .get();
151
+
152
+ const {
153
+ params: { id },
154
+ request: { body },
155
+ state: { userAbility, admin },
156
+ } = ctx;
157
+ const { email, username, password } = body;
158
+
159
+ const { pm, entity: user } = await findEntityAndCheckPermissions(
160
+ userAbility,
161
+ ACTIONS.edit,
162
+ userModel,
163
+ id
164
+ );
165
+
166
+ if (_.has(body, 'email') && !email) {
167
+ return ctx.badRequest('email.notNull');
168
+ }
169
+
170
+ if (_.has(body, 'username') && !username) {
171
+ return ctx.badRequest('username.notNull');
172
+ }
173
+
174
+ if (_.has(body, 'password') && !password && user.provider === 'local') {
175
+ return ctx.badRequest('password.notNull');
176
+ }
177
+
178
+ if (_.has(body, 'username')) {
179
+ const userWithSameUsername = await strapi
180
+ .query('user', 'users-permissions')
181
+ .findOne({ username });
182
+
183
+ if (userWithSameUsername && userWithSameUsername.id != id) {
184
+ return ctx.badRequest(
185
+ null,
186
+ formatError({
187
+ id: 'Auth.form.error.username.taken',
188
+ message: 'username.alreadyTaken.',
189
+ field: ['username'],
190
+ })
191
+ );
192
+ }
193
+ }
194
+
195
+ if (_.has(body, 'email') && advancedConfigs.unique_email) {
196
+ const userWithSameEmail = await strapi
197
+ .query('user', 'users-permissions')
198
+ .findOne({ email: email.toLowerCase() });
199
+
200
+ if (userWithSameEmail && userWithSameEmail.id != id) {
201
+ return ctx.badRequest(
202
+ null,
203
+ formatError({
204
+ id: 'Auth.form.error.email.taken',
205
+ message: 'Email already taken',
206
+ field: ['email'],
207
+ })
208
+ );
209
+ }
210
+ body.email = body.email.toLowerCase();
211
+ }
212
+
213
+ const sanitizedData = pm.pickPermittedFieldsOf(body, { subject: pm.toSubject(user) });
214
+ const updateData = _.omit({ ...sanitizedData, updated_by: admin.id }, 'created_by');
215
+
216
+ if (_.has(body, 'password') && password === user.password) {
217
+ delete updateData.password;
218
+ }
219
+
220
+ const data = await strapi.plugins['users-permissions'].services.user.edit({ id }, updateData);
221
+
222
+ ctx.body = pm.sanitize(data, { action: ACTIONS.read });
223
+ },
224
+ };