@strapi/plugin-users-permissions 4.3.0-beta.1 → 4.3.1
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.
- package/admin/src/pages/AdvancedSettings/utils/layout.js +2 -2
- package/admin/src/translations/en.json +1 -1
- package/admin/src/translations/pl.json +44 -7
- package/documentation/content-api.yaml +813 -0
- package/package.json +7 -7
- package/server/controllers/auth.js +170 -233
- package/server/controllers/user.js +6 -4
- package/server/controllers/validation/auth.js +31 -6
- package/server/register.js +12 -0
- package/server/routes/content-api/user.js +0 -1
- package/server/services/index.js +2 -0
- package/server/services/providers-registry.js +301 -0
- package/server/services/providers.js +62 -70
- package/server/services/users-permissions.js +6 -7
- package/server/utils/index.d.ts +1 -1
- package/documentation/1.0.0/overrides/users-permissions-Role.json +0 -281
- package/documentation/1.0.0/overrides/users-permissions-User.json +0 -325
- package/server/services/providers-list.js +0 -277
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@strapi/plugin-users-permissions",
|
|
3
|
-
"version": "4.3.
|
|
3
|
+
"version": "4.3.1",
|
|
4
4
|
"description": "Protect your API with a full-authentication process based on JWT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -27,18 +27,18 @@
|
|
|
27
27
|
"test:front:watch:ce": "cross-env IS_EE=false jest --config ./jest.config.front.js --watchAll"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@strapi/helper-plugin": "4.3.
|
|
31
|
-
"@strapi/utils": "4.3.
|
|
30
|
+
"@strapi/helper-plugin": "4.3.1",
|
|
31
|
+
"@strapi/utils": "4.3.1",
|
|
32
32
|
"bcryptjs": "2.4.3",
|
|
33
33
|
"grant-koa": "5.4.8",
|
|
34
34
|
"jsonwebtoken": "^8.1.0",
|
|
35
|
-
"koa2-ratelimit": "^
|
|
35
|
+
"koa2-ratelimit": "^1.1.1",
|
|
36
36
|
"lodash": "4.17.21",
|
|
37
37
|
"purest": "4.0.2",
|
|
38
38
|
"react": "^17.0.2",
|
|
39
39
|
"react-dom": "^17.0.2",
|
|
40
40
|
"react-intl": "5.20.2",
|
|
41
|
-
"react-redux": "7.2.
|
|
41
|
+
"react-redux": "7.2.8",
|
|
42
42
|
"react-router": "^5.2.0",
|
|
43
43
|
"react-router-dom": "5.2.0",
|
|
44
44
|
"redux-saga": "^0.16.0",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"url-join": "4.0.1"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"koa": "^2.13.
|
|
49
|
+
"koa": "^2.13.4"
|
|
50
50
|
},
|
|
51
51
|
"engines": {
|
|
52
52
|
"node": ">=14.19.1 <=16.x.x",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"required": true,
|
|
60
60
|
"kind": "plugin"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "1eab2fb08c7a4d3d40a5a7ff3b2f137ce0afcf8a"
|
|
63
63
|
}
|
|
@@ -15,13 +15,14 @@ const {
|
|
|
15
15
|
validateCallbackBody,
|
|
16
16
|
validateRegisterBody,
|
|
17
17
|
validateSendEmailConfirmationBody,
|
|
18
|
+
validateForgotPasswordBody,
|
|
19
|
+
validateResetPasswordBody,
|
|
20
|
+
validateEmailConfirmationBody,
|
|
18
21
|
} = require('./validation/auth');
|
|
19
22
|
|
|
20
23
|
const { getAbsoluteAdminUrl, getAbsoluteServerUrl, sanitize } = utils;
|
|
21
24
|
const { ApplicationError, ValidationError } = utils.errors;
|
|
22
25
|
|
|
23
|
-
const emailRegExp = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
|
24
|
-
|
|
25
26
|
const sanitizeUser = (user, ctx) => {
|
|
26
27
|
const { auth } = ctx.state;
|
|
27
28
|
const userSchema = strapi.getModel('plugin::users-permissions.user');
|
|
@@ -35,49 +36,33 @@ module.exports = {
|
|
|
35
36
|
const params = ctx.request.body;
|
|
36
37
|
|
|
37
38
|
const store = strapi.store({ type: 'plugin', name: 'users-permissions' });
|
|
39
|
+
const grantSettings = await store.get({ key: 'grant' });
|
|
38
40
|
|
|
39
|
-
|
|
40
|
-
if (!_.get(await store.get({ key: 'grant' }), 'email.enabled')) {
|
|
41
|
-
throw new ApplicationError('This provider is disabled');
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
await validateCallbackBody(params);
|
|
41
|
+
const grantProvider = provider === 'local' ? 'email' : provider;
|
|
45
42
|
|
|
46
|
-
|
|
43
|
+
if (!_.get(grantSettings, [grantProvider, 'enabled'])) {
|
|
44
|
+
throw new ApplicationError('This provider is disabled');
|
|
45
|
+
}
|
|
47
46
|
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
if (provider === 'local') {
|
|
48
|
+
await validateCallbackBody(params);
|
|
50
49
|
|
|
51
|
-
|
|
52
|
-
if (isEmail) {
|
|
53
|
-
query.email = params.identifier.toLowerCase();
|
|
54
|
-
} else {
|
|
55
|
-
query.username = params.identifier;
|
|
56
|
-
}
|
|
50
|
+
const { identifier } = params;
|
|
57
51
|
|
|
58
52
|
// Check if the user exists.
|
|
59
|
-
const user = await strapi.query('plugin::users-permissions.user').findOne({
|
|
53
|
+
const user = await strapi.query('plugin::users-permissions.user').findOne({
|
|
54
|
+
where: {
|
|
55
|
+
provider,
|
|
56
|
+
$or: [{ email: identifier.toLowerCase() }, { username: identifier }],
|
|
57
|
+
},
|
|
58
|
+
});
|
|
60
59
|
|
|
61
60
|
if (!user) {
|
|
62
61
|
throw new ValidationError('Invalid identifier or password');
|
|
63
62
|
}
|
|
64
63
|
|
|
65
|
-
if (
|
|
66
|
-
_.get(await store.get({ key: 'advanced' }), 'email_confirmation') &&
|
|
67
|
-
user.confirmed !== true
|
|
68
|
-
) {
|
|
69
|
-
throw new ApplicationError('Your account email is not confirmed');
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (user.blocked === true) {
|
|
73
|
-
throw new ApplicationError('Your account has been blocked by an administrator');
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// The user never authenticated with the `local` provider.
|
|
77
64
|
if (!user.password) {
|
|
78
|
-
throw new
|
|
79
|
-
'This user never set a local password, please login with the provider used during account creation'
|
|
80
|
-
);
|
|
65
|
+
throw new ValidationError('Invalid identifier or password');
|
|
81
66
|
}
|
|
82
67
|
|
|
83
68
|
const validPassword = await getService('user').validatePassword(
|
|
@@ -87,67 +72,65 @@ module.exports = {
|
|
|
87
72
|
|
|
88
73
|
if (!validPassword) {
|
|
89
74
|
throw new ValidationError('Invalid identifier or password');
|
|
90
|
-
} else {
|
|
91
|
-
ctx.send({
|
|
92
|
-
jwt: getService('jwt').issue({
|
|
93
|
-
id: user.id,
|
|
94
|
-
}),
|
|
95
|
-
user: await sanitizeUser(user, ctx),
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
} else {
|
|
99
|
-
if (!_.get(await store.get({ key: 'grant' }), [provider, 'enabled'])) {
|
|
100
|
-
throw new ApplicationError('This provider is disabled');
|
|
101
75
|
}
|
|
102
76
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const user = await getService('providers').connect(provider, ctx.query);
|
|
106
|
-
ctx.send({
|
|
107
|
-
jwt: getService('jwt').issue({ id: user.id }),
|
|
108
|
-
user: await sanitizeUser(user, ctx),
|
|
109
|
-
});
|
|
110
|
-
} catch (error) {
|
|
111
|
-
throw new ApplicationError(error.message);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
},
|
|
77
|
+
const advancedSettings = await store.get({ key: 'advanced' });
|
|
78
|
+
const requiresConfirmation = _.get(advancedSettings, 'email_confirmation');
|
|
115
79
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if (
|
|
120
|
-
params.password &&
|
|
121
|
-
params.passwordConfirmation &&
|
|
122
|
-
params.password === params.passwordConfirmation &&
|
|
123
|
-
params.code
|
|
124
|
-
) {
|
|
125
|
-
const user = await strapi
|
|
126
|
-
.query('plugin::users-permissions.user')
|
|
127
|
-
.findOne({ where: { resetPasswordToken: `${params.code}` } });
|
|
80
|
+
if (requiresConfirmation && user.confirmed !== true) {
|
|
81
|
+
throw new ApplicationError('Your account email is not confirmed');
|
|
82
|
+
}
|
|
128
83
|
|
|
129
|
-
if (
|
|
130
|
-
throw new
|
|
84
|
+
if (user.blocked === true) {
|
|
85
|
+
throw new ApplicationError('Your account has been blocked by an administrator');
|
|
131
86
|
}
|
|
132
87
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
88
|
+
return ctx.send({
|
|
89
|
+
jwt: getService('jwt').issue({ id: user.id }),
|
|
90
|
+
user: await sanitizeUser(user, ctx),
|
|
136
91
|
});
|
|
137
|
-
|
|
138
|
-
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Connect the user with the third-party provider.
|
|
95
|
+
try {
|
|
96
|
+
const user = await getService('providers').connect(provider, ctx.query);
|
|
97
|
+
|
|
98
|
+
return ctx.send({
|
|
139
99
|
jwt: getService('jwt').issue({ id: user.id }),
|
|
140
100
|
user: await sanitizeUser(user, ctx),
|
|
141
101
|
});
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
102
|
+
} catch (error) {
|
|
103
|
+
throw new ApplicationError(error.message);
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
async resetPassword(ctx) {
|
|
108
|
+
const { password, passwordConfirmation, code } = await validateResetPasswordBody(
|
|
109
|
+
ctx.request.body
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
if (password !== passwordConfirmation) {
|
|
147
113
|
throw new ValidationError('Passwords do not match');
|
|
148
|
-
} else {
|
|
149
|
-
throw new ValidationError('Incorrect params provided');
|
|
150
114
|
}
|
|
115
|
+
|
|
116
|
+
const user = await strapi
|
|
117
|
+
.query('plugin::users-permissions.user')
|
|
118
|
+
.findOne({ where: { resetPasswordToken: code } });
|
|
119
|
+
|
|
120
|
+
if (!user) {
|
|
121
|
+
throw new ValidationError('Incorrect code provided');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
await getService('user').edit(user.id, {
|
|
125
|
+
resetPasswordToken: null,
|
|
126
|
+
password,
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// Update the user.
|
|
130
|
+
ctx.send({
|
|
131
|
+
jwt: getService('jwt').issue({ id: user.id }),
|
|
132
|
+
user: await sanitizeUser(user, ctx),
|
|
133
|
+
});
|
|
151
134
|
},
|
|
152
135
|
|
|
153
136
|
async connect(ctx, next) {
|
|
@@ -189,87 +172,66 @@ module.exports = {
|
|
|
189
172
|
},
|
|
190
173
|
|
|
191
174
|
async forgotPassword(ctx) {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
// Check if the provided email is valid or not.
|
|
195
|
-
const isEmail = emailRegExp.test(email);
|
|
196
|
-
|
|
197
|
-
if (isEmail) {
|
|
198
|
-
email = email.toLowerCase();
|
|
199
|
-
} else {
|
|
200
|
-
throw new ValidationError('Please provide a valid email address');
|
|
201
|
-
}
|
|
175
|
+
const { email } = await validateForgotPasswordBody(ctx.request.body);
|
|
202
176
|
|
|
203
177
|
const pluginStore = await strapi.store({ type: 'plugin', name: 'users-permissions' });
|
|
204
178
|
|
|
179
|
+
const emailSettings = await pluginStore.get({ key: 'email' });
|
|
180
|
+
const advancedSettings = await pluginStore.get({ key: 'advanced' });
|
|
181
|
+
|
|
205
182
|
// Find the user by email.
|
|
206
183
|
const user = await strapi
|
|
207
184
|
.query('plugin::users-permissions.user')
|
|
208
185
|
.findOne({ where: { email: email.toLowerCase() } });
|
|
209
186
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
throw new ApplicationError('This email does not exist');
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
// User blocked
|
|
216
|
-
if (user.blocked) {
|
|
217
|
-
throw new ApplicationError('This user is disabled');
|
|
187
|
+
if (!user || user.blocked) {
|
|
188
|
+
return ctx.send({ ok: true });
|
|
218
189
|
}
|
|
219
190
|
|
|
220
191
|
// Generate random token.
|
|
192
|
+
const userInfo = await sanitizeUser(user, ctx);
|
|
193
|
+
|
|
221
194
|
const resetPasswordToken = crypto.randomBytes(64).toString('hex');
|
|
222
195
|
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
196
|
+
const resetPasswordSettings = _.get(emailSettings, 'reset_password.options', {});
|
|
197
|
+
const emailBody = await getService('users-permissions').template(
|
|
198
|
+
resetPasswordSettings.message,
|
|
199
|
+
{
|
|
200
|
+
URL: advancedSettings.email_reset_password,
|
|
201
|
+
SERVER_URL: getAbsoluteServerUrl(strapi.config),
|
|
202
|
+
ADMIN_URL: getAbsoluteAdminUrl(strapi.config),
|
|
203
|
+
USER: userInfo,
|
|
204
|
+
TOKEN: resetPasswordToken,
|
|
228
205
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
const advanced = await pluginStore.get({
|
|
232
|
-
key: 'advanced',
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
const userInfo = await sanitizeUser(user, ctx);
|
|
236
|
-
|
|
237
|
-
settings.message = await getService('users-permissions').template(settings.message, {
|
|
238
|
-
URL: advanced.email_reset_password,
|
|
239
|
-
SERVER_URL: getAbsoluteServerUrl(strapi.config),
|
|
240
|
-
ADMIN_URL: getAbsoluteAdminUrl(strapi.config),
|
|
241
|
-
USER: userInfo,
|
|
242
|
-
TOKEN: resetPasswordToken,
|
|
243
|
-
});
|
|
206
|
+
);
|
|
244
207
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
208
|
+
const emailObject = await getService('users-permissions').template(
|
|
209
|
+
resetPasswordSettings.object,
|
|
210
|
+
{
|
|
211
|
+
USER: userInfo,
|
|
212
|
+
}
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
const emailToSend = {
|
|
216
|
+
to: user.email,
|
|
217
|
+
from:
|
|
218
|
+
resetPasswordSettings.from.email || resetPasswordSettings.from.name
|
|
219
|
+
? `${resetPasswordSettings.from.name} <${resetPasswordSettings.from.email}>`
|
|
220
|
+
: undefined,
|
|
221
|
+
replyTo: resetPasswordSettings.response_email,
|
|
222
|
+
subject: emailObject,
|
|
223
|
+
text: emailBody,
|
|
224
|
+
html: emailBody,
|
|
225
|
+
};
|
|
248
226
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
await strapi
|
|
252
|
-
.plugin('email')
|
|
253
|
-
.service('email')
|
|
254
|
-
.send({
|
|
255
|
-
to: user.email,
|
|
256
|
-
from:
|
|
257
|
-
settings.from.email || settings.from.name
|
|
258
|
-
? `${settings.from.name} <${settings.from.email}>`
|
|
259
|
-
: undefined,
|
|
260
|
-
replyTo: settings.response_email,
|
|
261
|
-
subject: settings.object,
|
|
262
|
-
text: settings.message,
|
|
263
|
-
html: settings.message,
|
|
264
|
-
});
|
|
265
|
-
} catch (err) {
|
|
266
|
-
throw new ApplicationError(err.message);
|
|
267
|
-
}
|
|
227
|
+
// NOTE: Update the user before sending the email so an Admin can generate the link if the email fails
|
|
228
|
+
await getService('user').edit(user.id, { resetPasswordToken });
|
|
268
229
|
|
|
269
|
-
//
|
|
230
|
+
// Send an email to the user.
|
|
270
231
|
await strapi
|
|
271
|
-
.
|
|
272
|
-
.
|
|
232
|
+
.plugin('email')
|
|
233
|
+
.service('email')
|
|
234
|
+
.send(emailToSend);
|
|
273
235
|
|
|
274
236
|
ctx.send({ ok: true });
|
|
275
237
|
},
|
|
@@ -277,29 +239,25 @@ module.exports = {
|
|
|
277
239
|
async register(ctx) {
|
|
278
240
|
const pluginStore = await strapi.store({ type: 'plugin', name: 'users-permissions' });
|
|
279
241
|
|
|
280
|
-
const settings = await pluginStore.get({
|
|
281
|
-
key: 'advanced',
|
|
282
|
-
});
|
|
242
|
+
const settings = await pluginStore.get({ key: 'advanced' });
|
|
283
243
|
|
|
284
244
|
if (!settings.allow_register) {
|
|
285
245
|
throw new ApplicationError('Register action is currently disabled');
|
|
286
246
|
}
|
|
287
247
|
|
|
288
248
|
const params = {
|
|
289
|
-
..._.omit(ctx.request.body, [
|
|
249
|
+
..._.omit(ctx.request.body, [
|
|
250
|
+
'confirmed',
|
|
251
|
+
'blocked',
|
|
252
|
+
'confirmationToken',
|
|
253
|
+
'resetPasswordToken',
|
|
254
|
+
'provider',
|
|
255
|
+
]),
|
|
290
256
|
provider: 'local',
|
|
291
257
|
};
|
|
292
258
|
|
|
293
259
|
await validateRegisterBody(params);
|
|
294
260
|
|
|
295
|
-
// Throw an error if the password selected by the user
|
|
296
|
-
// contains more than three times the symbol '$'.
|
|
297
|
-
if (getService('user').isHashed(params.password)) {
|
|
298
|
-
throw new ValidationError(
|
|
299
|
-
'Your password cannot contain more than three times the symbol `$`'
|
|
300
|
-
);
|
|
301
|
-
}
|
|
302
|
-
|
|
303
261
|
const role = await strapi
|
|
304
262
|
.query('plugin::users-permissions.role')
|
|
305
263
|
.findOne({ where: { type: settings.default_role } });
|
|
@@ -308,80 +266,75 @@ module.exports = {
|
|
|
308
266
|
throw new ApplicationError('Impossible to find the default role');
|
|
309
267
|
}
|
|
310
268
|
|
|
311
|
-
|
|
312
|
-
const isEmail = emailRegExp.test(params.email);
|
|
313
|
-
|
|
314
|
-
if (isEmail) {
|
|
315
|
-
params.email = params.email.toLowerCase();
|
|
316
|
-
} else {
|
|
317
|
-
throw new ValidationError('Please provide a valid email address');
|
|
318
|
-
}
|
|
269
|
+
const { email, username, provider } = params;
|
|
319
270
|
|
|
320
|
-
|
|
271
|
+
const identifierFilter = {
|
|
272
|
+
$or: [
|
|
273
|
+
{ email: email.toLowerCase() },
|
|
274
|
+
{ username: email.toLowerCase() },
|
|
275
|
+
{ username },
|
|
276
|
+
{ email: username },
|
|
277
|
+
],
|
|
278
|
+
};
|
|
321
279
|
|
|
322
|
-
const
|
|
323
|
-
where: {
|
|
280
|
+
const conflictingUserCount = await strapi.query('plugin::users-permissions.user').count({
|
|
281
|
+
where: { ...identifierFilter, provider },
|
|
324
282
|
});
|
|
325
283
|
|
|
326
|
-
if (
|
|
327
|
-
throw new ApplicationError('Email
|
|
284
|
+
if (conflictingUserCount > 0) {
|
|
285
|
+
throw new ApplicationError('Email or Username are already taken');
|
|
328
286
|
}
|
|
329
287
|
|
|
330
|
-
if (
|
|
331
|
-
|
|
332
|
-
|
|
288
|
+
if (settings.unique_email) {
|
|
289
|
+
const conflictingUserCount = await strapi.query('plugin::users-permissions.user').count({
|
|
290
|
+
where: { ...identifierFilter },
|
|
291
|
+
});
|
|
333
292
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
params.confirmed = true;
|
|
293
|
+
if (conflictingUserCount > 0) {
|
|
294
|
+
throw new ApplicationError('Email or Username are already taken');
|
|
337
295
|
}
|
|
296
|
+
}
|
|
338
297
|
|
|
339
|
-
|
|
298
|
+
let newUser = {
|
|
299
|
+
...params,
|
|
300
|
+
role: role.id,
|
|
301
|
+
email: email.toLowerCase(),
|
|
302
|
+
username,
|
|
303
|
+
confirmed: !settings.email_confirmation,
|
|
304
|
+
};
|
|
340
305
|
|
|
341
|
-
|
|
306
|
+
const user = await getService('user').add(newUser);
|
|
342
307
|
|
|
343
|
-
|
|
344
|
-
try {
|
|
345
|
-
await getService('user').sendConfirmationEmail(sanitizedUser);
|
|
346
|
-
} catch (err) {
|
|
347
|
-
throw new ApplicationError(err.message);
|
|
348
|
-
}
|
|
308
|
+
const sanitizedUser = await sanitizeUser(user, ctx);
|
|
349
309
|
|
|
350
|
-
|
|
310
|
+
if (settings.email_confirmation) {
|
|
311
|
+
try {
|
|
312
|
+
await getService('user').sendConfirmationEmail(sanitizedUser);
|
|
313
|
+
} catch (err) {
|
|
314
|
+
throw new ApplicationError(err.message);
|
|
351
315
|
}
|
|
352
316
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
return ctx.send({
|
|
356
|
-
jwt,
|
|
357
|
-
user: sanitizedUser,
|
|
358
|
-
});
|
|
359
|
-
} catch (err) {
|
|
360
|
-
if (_.includes(err.message, 'username')) {
|
|
361
|
-
throw new ApplicationError('Username already taken');
|
|
362
|
-
} else if (_.includes(err.message, 'email')) {
|
|
363
|
-
throw new ApplicationError('Email already taken');
|
|
364
|
-
} else {
|
|
365
|
-
strapi.log.error(err);
|
|
366
|
-
throw new ApplicationError('An error occurred during account creation');
|
|
367
|
-
}
|
|
317
|
+
return ctx.send({ user: sanitizedUser });
|
|
368
318
|
}
|
|
319
|
+
|
|
320
|
+
const jwt = getService('jwt').issue(_.pick(user, ['id']));
|
|
321
|
+
|
|
322
|
+
return ctx.send({
|
|
323
|
+
jwt,
|
|
324
|
+
user: sanitizedUser,
|
|
325
|
+
});
|
|
369
326
|
},
|
|
370
327
|
|
|
371
328
|
async emailConfirmation(ctx, next, returnUser) {
|
|
372
|
-
const { confirmation: confirmationToken } = ctx.query;
|
|
329
|
+
const { confirmation: confirmationToken } = await validateEmailConfirmationBody(ctx.query);
|
|
373
330
|
|
|
374
331
|
const userService = getService('user');
|
|
375
332
|
const jwtService = getService('jwt');
|
|
376
333
|
|
|
377
|
-
if (_.isEmpty(confirmationToken)) {
|
|
378
|
-
throw new ValidationError('token.invalid');
|
|
379
|
-
}
|
|
380
|
-
|
|
381
334
|
const [user] = await userService.fetchAll({ filters: { confirmationToken } });
|
|
382
335
|
|
|
383
336
|
if (!user) {
|
|
384
|
-
throw new ValidationError('token
|
|
337
|
+
throw new ValidationError('Invalid token');
|
|
385
338
|
}
|
|
386
339
|
|
|
387
340
|
await userService.edit(user.id, { confirmed: true, confirmationToken: null });
|
|
@@ -401,45 +354,29 @@ module.exports = {
|
|
|
401
354
|
},
|
|
402
355
|
|
|
403
356
|
async sendEmailConfirmation(ctx) {
|
|
404
|
-
const
|
|
405
|
-
|
|
406
|
-
await validateSendEmailConfirmationBody(params);
|
|
407
|
-
|
|
408
|
-
const isEmail = emailRegExp.test(params.email);
|
|
409
|
-
|
|
410
|
-
if (isEmail) {
|
|
411
|
-
params.email = params.email.toLowerCase();
|
|
412
|
-
} else {
|
|
413
|
-
throw new ValidationError('wrong.email');
|
|
414
|
-
}
|
|
357
|
+
const { email } = await validateSendEmailConfirmationBody(ctx.request.body);
|
|
415
358
|
|
|
416
359
|
const user = await strapi.query('plugin::users-permissions.user').findOne({
|
|
417
|
-
where: { email:
|
|
360
|
+
where: { email: email.toLowerCase() },
|
|
418
361
|
});
|
|
419
362
|
|
|
420
363
|
if (!user) {
|
|
421
|
-
return ctx.send({
|
|
422
|
-
email: params.email,
|
|
423
|
-
sent: true,
|
|
424
|
-
});
|
|
364
|
+
return ctx.send({ email, sent: true });
|
|
425
365
|
}
|
|
426
366
|
|
|
427
367
|
if (user.confirmed) {
|
|
428
|
-
throw new ApplicationError('
|
|
368
|
+
throw new ApplicationError('Already confirmed');
|
|
429
369
|
}
|
|
430
370
|
|
|
431
371
|
if (user.blocked) {
|
|
432
|
-
throw new ApplicationError('blocked
|
|
372
|
+
throw new ApplicationError('User blocked');
|
|
433
373
|
}
|
|
434
374
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
} catch (err) {
|
|
442
|
-
throw new ApplicationError(err.message);
|
|
443
|
-
}
|
|
375
|
+
await getService('user').sendConfirmationEmail(user);
|
|
376
|
+
|
|
377
|
+
ctx.send({
|
|
378
|
+
email: user.email,
|
|
379
|
+
sent: true,
|
|
380
|
+
});
|
|
444
381
|
},
|
|
445
382
|
};
|
|
@@ -55,11 +55,10 @@ module.exports = {
|
|
|
55
55
|
|
|
56
56
|
const user = {
|
|
57
57
|
...ctx.request.body,
|
|
58
|
+
email: email.toLowerCase(),
|
|
58
59
|
provider: 'local',
|
|
59
60
|
};
|
|
60
61
|
|
|
61
|
-
user.email = _.toLower(user.email);
|
|
62
|
-
|
|
63
62
|
if (!role) {
|
|
64
63
|
const defaultRole = await strapi
|
|
65
64
|
.query('plugin::users-permissions.role')
|
|
@@ -185,12 +184,15 @@ module.exports = {
|
|
|
185
184
|
* @return {Object|Array}
|
|
186
185
|
*/
|
|
187
186
|
async me(ctx) {
|
|
188
|
-
const
|
|
187
|
+
const authUser = ctx.state.user;
|
|
188
|
+
const { query } = ctx;
|
|
189
189
|
|
|
190
|
-
if (!
|
|
190
|
+
if (!authUser) {
|
|
191
191
|
return ctx.unauthorized();
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
+
const user = await getService('user').fetch(authUser.id, query);
|
|
195
|
+
|
|
194
196
|
ctx.body = await sanitizeOutput(user, ctx);
|
|
195
197
|
},
|
|
196
198
|
};
|
|
@@ -2,28 +2,53 @@
|
|
|
2
2
|
|
|
3
3
|
const { yup, validateYupSchema } = require('@strapi/utils');
|
|
4
4
|
|
|
5
|
-
const
|
|
5
|
+
const callbackSchema = yup.object({
|
|
6
6
|
identifier: yup.string().required(),
|
|
7
7
|
password: yup.string().required(),
|
|
8
8
|
});
|
|
9
9
|
|
|
10
|
-
const
|
|
10
|
+
const registerSchema = yup.object({
|
|
11
11
|
email: yup
|
|
12
12
|
.string()
|
|
13
13
|
.email()
|
|
14
14
|
.required(),
|
|
15
|
+
username: yup.string().required(),
|
|
15
16
|
password: yup.string().required(),
|
|
16
17
|
});
|
|
17
18
|
|
|
18
|
-
const
|
|
19
|
+
const sendEmailConfirmationSchema = yup.object({
|
|
19
20
|
email: yup
|
|
20
21
|
.string()
|
|
21
22
|
.email()
|
|
22
23
|
.required(),
|
|
23
24
|
});
|
|
24
25
|
|
|
26
|
+
const validateEmailConfirmationSchema = yup.object({
|
|
27
|
+
confirmation: yup.string().required(),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const forgotPasswordSchema = yup
|
|
31
|
+
.object({
|
|
32
|
+
email: yup
|
|
33
|
+
.string()
|
|
34
|
+
.email()
|
|
35
|
+
.required(),
|
|
36
|
+
})
|
|
37
|
+
.noUnknown();
|
|
38
|
+
|
|
39
|
+
const resetPasswordSchema = yup
|
|
40
|
+
.object({
|
|
41
|
+
password: yup.string().required(),
|
|
42
|
+
passwordConfirmation: yup.string().required(),
|
|
43
|
+
code: yup.string().required(),
|
|
44
|
+
})
|
|
45
|
+
.noUnknown();
|
|
46
|
+
|
|
25
47
|
module.exports = {
|
|
26
|
-
validateCallbackBody: validateYupSchema(
|
|
27
|
-
validateRegisterBody: validateYupSchema(
|
|
28
|
-
validateSendEmailConfirmationBody: validateYupSchema(
|
|
48
|
+
validateCallbackBody: validateYupSchema(callbackSchema),
|
|
49
|
+
validateRegisterBody: validateYupSchema(registerSchema),
|
|
50
|
+
validateSendEmailConfirmationBody: validateYupSchema(sendEmailConfirmationSchema),
|
|
51
|
+
validateEmailConfirmationBody: validateYupSchema(validateEmailConfirmationSchema),
|
|
52
|
+
validateForgotPasswordBody: validateYupSchema(forgotPasswordSchema),
|
|
53
|
+
validateResetPasswordBody: validateYupSchema(resetPasswordSchema),
|
|
29
54
|
};
|