fix: u&p service hashes password attributes

This commit is contained in:
Ben Irvin 2024-04-18 15:58:46 +02:00 committed by GitHub
parent 113a853206
commit a7cf7e50ee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 43 additions and 5 deletions

View File

@ -11,6 +11,7 @@ const bcrypt = require('bcryptjs');
const urlJoin = require('url-join');
const { sanitize } = require('@strapi/utils');
const { toNumber, getOr } = require('lodash/fp');
const { getService } = require('../utils');
const USER_MODEL_UID = 'plugin::users-permissions.user';
@ -27,10 +28,26 @@ module.exports = ({ strapi }) => ({
},
/**
* Promise to search count users
* Hashes password fields in the provided values object if they are present.
* It checks each key in the values object against the model's attributes and
* hashes it if the attribute type is 'password',
*
* @return {Promise}
* @param {object} values - The object containing the fields to be hashed.
* @return {object} The values object with hashed password fields if they were present.
*/
async ensureHashedPasswords(values) {
const attributes = strapi.getModel(USER_MODEL_UID).attributes;
for (const key in values) {
if (attributes[key] && attributes[key].type === 'password') {
// Check if a custom encryption.rounds has been set on the password attribute
const rounds = toNumber(getOr(10, 'encryption.rounds', attributes[key]));
values[key] = await bcrypt.hash(values[key], rounds);
}
}
return values;
},
/**
* Promise to add a/an user.
@ -38,7 +55,7 @@ module.exports = ({ strapi }) => ({
*/
async add(values) {
return strapi.db.query(USER_MODEL_UID).create({
data: values,
data: await this.ensureHashedPasswords(values),
populate: ['role'],
});
},
@ -52,7 +69,7 @@ module.exports = ({ strapi }) => ({
async edit(userId, params = {}) {
return strapi.db.query(USER_MODEL_UID).update({
where: { id: userId },
data: params,
data: await this.ensureHashedPasswords(params),
populate: ['role'],
});
},

View File

@ -1,5 +1,7 @@
'use strict';
const bcrypt = require('bcryptjs');
const { createStrapiInstance } = require('api-tests/strapi');
const { createRequest } = require('api-tests/request');
const { createAuthenticatedUser } = require('../utils');
@ -20,7 +22,7 @@ const internals = {
const data = {};
describe.skip('Auth API', () => {
describe('Auth API', () => {
beforeAll(async () => {
strapi = await createStrapiInstance({ bypassAuth: false });
@ -111,6 +113,15 @@ describe.skip('Auth API', () => {
},
});
// check that password was hashed
const user = await strapi.db.query('plugin::users-permissions.user').findOne({
where: {
email: internals.user.email.toLowerCase(),
},
});
expect(bcrypt.compareSync(internals.newPassword, user.password)).toBe(true);
// check results
expect(res.statusCode).toBe(200);
expect(res.body).toMatchObject({
jwt: expect.any(String),

View File

@ -2,6 +2,7 @@
// Test a simple default API with no relations
const bcrypt = require('bcryptjs');
const { createStrapiInstance } = require('api-tests/strapi');
const { createContentAPIRequest } = require('api-tests/request');
@ -73,6 +74,15 @@ describe('Users API', () => {
body: user,
});
// check that password was hashed
const userDb = await strapi.db.query('plugin::users-permissions.user').findOne({
where: {
email: user.email,
},
});
expect(bcrypt.compareSync(user.password, userDb.password)).toBe(true);
expect(res.statusCode).toBe(201);
expect(res.body).toMatchObject({
username: user.username,