@strapi/plugin-users-permissions 4.3.2-alpha.0 → 4.3.4
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/documentation/content-api.yaml +35 -0
- package/package.json +4 -4
- package/server/controllers/auth.js +31 -0
- package/server/controllers/validation/auth.js +12 -0
- package/server/graphql/mutations/auth/change-password.js +41 -0
- package/server/graphql/mutations/index.js +1 -0
- package/server/graphql/resolvers-configs.js +5 -0
- package/server/routes/content-api/auth.js +9 -0
- package/server/services/user.js +0 -7
- package/server/services/users-permissions.js +1 -0
|
@@ -185,6 +185,41 @@ paths:
|
|
|
185
185
|
schema:
|
|
186
186
|
$ref: '#/components/schemas/Error'
|
|
187
187
|
|
|
188
|
+
/auth/change-password:
|
|
189
|
+
post:
|
|
190
|
+
tags:
|
|
191
|
+
- Users-Permissions - Auth
|
|
192
|
+
summary: Update user's own password
|
|
193
|
+
requestBody:
|
|
194
|
+
required: true
|
|
195
|
+
content:
|
|
196
|
+
application/json:
|
|
197
|
+
schema:
|
|
198
|
+
type: object
|
|
199
|
+
properties:
|
|
200
|
+
password:
|
|
201
|
+
required: true
|
|
202
|
+
type: string
|
|
203
|
+
currentPassword:
|
|
204
|
+
required: true
|
|
205
|
+
type: string
|
|
206
|
+
passwordConfirmation:
|
|
207
|
+
required: true
|
|
208
|
+
type: string
|
|
209
|
+
responses:
|
|
210
|
+
200:
|
|
211
|
+
description: Returns a jwt token and user info
|
|
212
|
+
content:
|
|
213
|
+
application/json:
|
|
214
|
+
schema:
|
|
215
|
+
$ref: '#/components/schemas/Users-Permissions-UserRegistration'
|
|
216
|
+
default:
|
|
217
|
+
description: Error
|
|
218
|
+
content:
|
|
219
|
+
application/json:
|
|
220
|
+
schema:
|
|
221
|
+
$ref: '#/components/schemas/Error'
|
|
222
|
+
|
|
188
223
|
/auth/email-confirmation:
|
|
189
224
|
get:
|
|
190
225
|
tags:
|
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.4",
|
|
4
4
|
"description": "Protect your API with a full-authentication process based on JWT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -27,8 +27,8 @@
|
|
|
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.4",
|
|
31
|
+
"@strapi/utils": "4.3.4",
|
|
32
32
|
"bcryptjs": "2.4.3",
|
|
33
33
|
"grant-koa": "5.4.8",
|
|
34
34
|
"jsonwebtoken": "^8.1.0",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"required": true,
|
|
60
60
|
"kind": "plugin"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "28a2a00db8234ffcf644661c4c8092aa82f8c119"
|
|
63
63
|
}
|
|
@@ -18,6 +18,7 @@ const {
|
|
|
18
18
|
validateForgotPasswordBody,
|
|
19
19
|
validateResetPasswordBody,
|
|
20
20
|
validateEmailConfirmationBody,
|
|
21
|
+
validateChangePasswordBody,
|
|
21
22
|
} = require('./validation/auth');
|
|
22
23
|
|
|
23
24
|
const { getAbsoluteAdminUrl, getAbsoluteServerUrl, sanitize } = utils;
|
|
@@ -104,6 +105,36 @@ module.exports = {
|
|
|
104
105
|
}
|
|
105
106
|
},
|
|
106
107
|
|
|
108
|
+
async changePassword(ctx) {
|
|
109
|
+
if (!ctx.state.user) {
|
|
110
|
+
throw new ApplicationError('You must be authenticated to reset your password');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const { currentPassword, password } = await validateChangePasswordBody(ctx.request.body);
|
|
114
|
+
|
|
115
|
+
const user = await strapi.entityService.findOne(
|
|
116
|
+
'plugin::users-permissions.user',
|
|
117
|
+
ctx.state.user.id
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
const validPassword = await getService('user').validatePassword(currentPassword, user.password);
|
|
121
|
+
|
|
122
|
+
if (!validPassword) {
|
|
123
|
+
throw new ValidationError('The provided current password is invalid');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (currentPassword === password) {
|
|
127
|
+
throw new ValidationError('Your new password must be different than your current password');
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
await getService('user').edit(user.id, { password });
|
|
131
|
+
|
|
132
|
+
ctx.send({
|
|
133
|
+
jwt: getService('jwt').issue({ id: user.id }),
|
|
134
|
+
user: await sanitizeUser(user, ctx),
|
|
135
|
+
});
|
|
136
|
+
},
|
|
137
|
+
|
|
107
138
|
async resetPassword(ctx) {
|
|
108
139
|
const { password, passwordConfirmation, code } = await validateResetPasswordBody(
|
|
109
140
|
ctx.request.body
|
|
@@ -44,6 +44,17 @@ const resetPasswordSchema = yup
|
|
|
44
44
|
})
|
|
45
45
|
.noUnknown();
|
|
46
46
|
|
|
47
|
+
const changePasswordSchema = yup
|
|
48
|
+
.object({
|
|
49
|
+
password: yup.string().required(),
|
|
50
|
+
passwordConfirmation: yup
|
|
51
|
+
.string()
|
|
52
|
+
.required()
|
|
53
|
+
.oneOf([yup.ref('password')], 'Passwords do not match'),
|
|
54
|
+
currentPassword: yup.string().required(),
|
|
55
|
+
})
|
|
56
|
+
.noUnknown();
|
|
57
|
+
|
|
47
58
|
module.exports = {
|
|
48
59
|
validateCallbackBody: validateYupSchema(callbackSchema),
|
|
49
60
|
validateRegisterBody: validateYupSchema(registerSchema),
|
|
@@ -51,4 +62,5 @@ module.exports = {
|
|
|
51
62
|
validateEmailConfirmationBody: validateYupSchema(validateEmailConfirmationSchema),
|
|
52
63
|
validateForgotPasswordBody: validateYupSchema(forgotPasswordSchema),
|
|
53
64
|
validateResetPasswordBody: validateYupSchema(resetPasswordSchema),
|
|
65
|
+
validateChangePasswordBody: validateYupSchema(changePasswordSchema),
|
|
54
66
|
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { toPlainObject } = require('lodash/fp');
|
|
4
|
+
|
|
5
|
+
const { checkBadRequest } = require('../../utils');
|
|
6
|
+
|
|
7
|
+
module.exports = ({ nexus, strapi }) => {
|
|
8
|
+
const { nonNull } = nexus;
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
type: 'UsersPermissionsLoginPayload',
|
|
12
|
+
|
|
13
|
+
args: {
|
|
14
|
+
currentPassword: nonNull('String'),
|
|
15
|
+
password: nonNull('String'),
|
|
16
|
+
passwordConfirmation: nonNull('String'),
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
description: 'Change user password. Confirm with the current password.',
|
|
20
|
+
|
|
21
|
+
async resolve(parent, args, context) {
|
|
22
|
+
const { koaContext } = context;
|
|
23
|
+
|
|
24
|
+
koaContext.request.body = toPlainObject(args);
|
|
25
|
+
|
|
26
|
+
await strapi
|
|
27
|
+
.plugin('users-permissions')
|
|
28
|
+
.controller('auth')
|
|
29
|
+
.changePassword(koaContext);
|
|
30
|
+
|
|
31
|
+
const output = koaContext.body;
|
|
32
|
+
|
|
33
|
+
checkBadRequest(output);
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
user: output.user || output,
|
|
37
|
+
jwt: output.jwt,
|
|
38
|
+
};
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
};
|
|
@@ -25,6 +25,7 @@ module.exports = context => {
|
|
|
25
25
|
register: require('./auth/register'),
|
|
26
26
|
forgotPassword: require('./auth/forgot-password'),
|
|
27
27
|
resetPassword: require('./auth/reset-password'),
|
|
28
|
+
changePassword: require('./auth/change-password'),
|
|
28
29
|
emailConfirmation: require('./auth/email-confirmation'),
|
|
29
30
|
};
|
|
30
31
|
|
|
@@ -23,6 +23,11 @@ module.exports = ({ strapi }) => {
|
|
|
23
23
|
'Mutation.forgotPassword': { auth: false },
|
|
24
24
|
'Mutation.resetPassword': { auth: false },
|
|
25
25
|
'Mutation.emailConfirmation': { auth: false },
|
|
26
|
+
'Mutation.changePassword': {
|
|
27
|
+
auth: {
|
|
28
|
+
scope: 'plugin::users-permissions.auth.changePassword',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
26
31
|
|
|
27
32
|
// Scoped auth for replaced CRUD operations
|
|
28
33
|
// Role
|
package/server/services/user.js
CHANGED
|
@@ -87,13 +87,6 @@ module.exports = ({ strapi }) => ({
|
|
|
87
87
|
async remove(params) {
|
|
88
88
|
return strapi.query('plugin::users-permissions.user').delete({ where: params });
|
|
89
89
|
},
|
|
90
|
-
isHashed(password) {
|
|
91
|
-
if (typeof password !== 'string' || !password) {
|
|
92
|
-
return false;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return password.split('$').length === 4;
|
|
96
|
-
},
|
|
97
90
|
|
|
98
91
|
validatePassword(password, hash) {
|
|
99
92
|
return bcrypt.compare(password, hash);
|
|
@@ -15,6 +15,7 @@ const DEFAULT_PERMISSIONS = [
|
|
|
15
15
|
{ action: 'plugin::users-permissions.auth.emailConfirmation', roleType: 'public' },
|
|
16
16
|
{ action: 'plugin::users-permissions.auth.sendEmailConfirmation', roleType: 'public' },
|
|
17
17
|
{ action: 'plugin::users-permissions.user.me', roleType: 'authenticated' },
|
|
18
|
+
{ action: 'plugin::users-permissions.auth.changePassword', roleType: 'authenticated' },
|
|
18
19
|
];
|
|
19
20
|
|
|
20
21
|
const transformRoutePrefixFor = pluginName => route => {
|