2020-05-13 11:46:52 +02:00
|
|
|
'use strict';
|
|
|
|
|
2020-05-18 16:07:37 +02:00
|
|
|
const _ = require('lodash');
|
2020-05-14 10:37:32 +02:00
|
|
|
const { createUser } = require('../domain/user');
|
|
|
|
|
2020-05-28 11:10:49 +02:00
|
|
|
const sanitizeUserRoles = role => _.pick(role, ['id', 'name', 'description']);
|
|
|
|
|
2020-05-18 16:07:37 +02:00
|
|
|
/**
|
|
|
|
* Remove private user fields
|
|
|
|
* @param {Object} user - user to sanitize
|
|
|
|
*/
|
|
|
|
const sanitizeUser = user => {
|
2020-05-27 16:06:15 +02:00
|
|
|
return {
|
|
|
|
..._.omit(user, ['password', 'resetPasswordToken', 'roles']),
|
2020-05-28 11:10:49 +02:00
|
|
|
roles: user.roles && user.roles.map(sanitizeUserRoles),
|
2020-05-27 16:06:15 +02:00
|
|
|
};
|
2020-05-18 16:07:37 +02:00
|
|
|
};
|
|
|
|
|
2020-05-14 10:37:32 +02:00
|
|
|
/**
|
|
|
|
* Create and save a user in database
|
|
|
|
* @param attributes A partial user object
|
|
|
|
* @returns {Promise<user>}
|
|
|
|
*/
|
2020-05-14 11:06:16 +02:00
|
|
|
const create = async attributes => {
|
2020-05-14 18:54:52 +02:00
|
|
|
const user = createUser({
|
|
|
|
registrationToken: strapi.admin.services.token.createToken(),
|
|
|
|
...attributes,
|
|
|
|
});
|
|
|
|
|
2020-05-22 11:15:06 +02:00
|
|
|
// hash password if a new one is sent
|
|
|
|
if (_.has(user, 'password')) {
|
|
|
|
const hashedPassword = await strapi.admin.services.auth.hashPassword(user.password);
|
|
|
|
|
|
|
|
return strapi.query('user', 'admin').create({
|
|
|
|
...user,
|
|
|
|
password: hashedPassword,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-05-14 10:37:32 +02:00
|
|
|
return strapi.query('user', 'admin').create(user);
|
2020-05-14 11:06:16 +02:00
|
|
|
};
|
2020-05-13 11:46:52 +02:00
|
|
|
|
2020-05-18 17:16:49 +02:00
|
|
|
/**
|
|
|
|
* Update a user in database
|
|
|
|
* @param params query params to find the user to update
|
|
|
|
* @param attributes A partial user object
|
|
|
|
* @returns {Promise<user>}
|
|
|
|
*/
|
2020-06-18 18:10:12 +02:00
|
|
|
const updateById = async (id, attributes) => {
|
2020-06-16 16:29:10 +02:00
|
|
|
// Check at least one super admin remains
|
|
|
|
if (_.has(attributes, 'roles')) {
|
2020-06-18 18:10:12 +02:00
|
|
|
const superAdminRole = await strapi.admin.services.role.getSuperAdminWithUsersCount();
|
|
|
|
if (
|
|
|
|
_.get(superAdminRole, 'usersCount') === 1 &&
|
|
|
|
!attributes.roles.map(String).includes(String(superAdminRole.id))
|
|
|
|
) {
|
|
|
|
const userWithAdminRole = await strapi
|
2020-06-16 16:29:10 +02:00
|
|
|
.query('user', 'admin')
|
2020-06-18 18:10:12 +02:00
|
|
|
.findOne({ roles: [superAdminRole.id] });
|
|
|
|
if (String(userWithAdminRole.id) === String(id)) {
|
2020-06-16 16:29:10 +02:00
|
|
|
throw strapi.errors.badRequest(
|
|
|
|
'ValidationError',
|
|
|
|
'You must have at least one user with super admin role.'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-18 19:54:43 +02:00
|
|
|
// hash password if a new one is sent
|
|
|
|
if (_.has(attributes, 'password')) {
|
|
|
|
const hashedPassword = await strapi.admin.services.auth.hashPassword(attributes.password);
|
|
|
|
|
2020-06-18 18:10:12 +02:00
|
|
|
return strapi.query('user', 'admin').update(
|
|
|
|
{ id },
|
|
|
|
{
|
|
|
|
...attributes,
|
|
|
|
password: hashedPassword,
|
|
|
|
}
|
|
|
|
);
|
2020-05-18 19:54:43 +02:00
|
|
|
}
|
|
|
|
|
2020-06-18 18:10:12 +02:00
|
|
|
return strapi.query('user', 'admin').update({ id }, attributes);
|
2020-05-18 17:16:49 +02:00
|
|
|
};
|
|
|
|
|
2020-05-14 10:37:32 +02:00
|
|
|
/**
|
|
|
|
* Check if a user with specific attributes exists in the database
|
|
|
|
* @param attributes A partial user object
|
|
|
|
* @returns {Promise<boolean>}
|
|
|
|
*/
|
2020-05-22 16:09:37 +02:00
|
|
|
const exists = async (attributes = {}) => {
|
2020-05-14 10:37:32 +02:00
|
|
|
return (await strapi.query('user', 'admin').count(attributes)) > 0;
|
2020-05-14 11:06:16 +02:00
|
|
|
};
|
2020-05-13 11:46:52 +02:00
|
|
|
|
2020-05-18 16:07:37 +02:00
|
|
|
/**
|
|
|
|
* Returns a user registration info
|
|
|
|
* @param {string} registrationToken - a user registration token
|
|
|
|
* @returns {Promise<registrationInfo>} - Returns user email, firstname and lastname
|
|
|
|
*/
|
|
|
|
const findRegistrationInfo = async registrationToken => {
|
|
|
|
const user = await strapi.query('user', 'admin').findOne({ registrationToken });
|
|
|
|
|
|
|
|
if (!user) {
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
return _.pick(user, ['email', 'firstname', 'lastname']);
|
|
|
|
};
|
|
|
|
|
2020-05-18 17:16:49 +02:00
|
|
|
/**
|
|
|
|
* Registers a user based on a registrationToken and some informations to update
|
|
|
|
* @param {Object} params
|
2020-05-19 16:10:53 +02:00
|
|
|
* @param {Object} params.registrationToken registration token
|
2020-05-18 17:16:49 +02:00
|
|
|
* @param {Object} params.userInfo user info
|
|
|
|
*/
|
|
|
|
const register = async ({ registrationToken, userInfo }) => {
|
2020-05-19 16:10:53 +02:00
|
|
|
const matchingUser = await strapi.query('user', 'admin').findOne({ registrationToken });
|
2020-05-18 17:16:49 +02:00
|
|
|
|
|
|
|
if (!matchingUser) {
|
|
|
|
throw strapi.errors.badRequest('Invalid registration info');
|
|
|
|
}
|
|
|
|
|
2020-06-18 18:10:12 +02:00
|
|
|
return strapi.admin.services.user.updateById(matchingUser.id, {
|
|
|
|
password: userInfo.password,
|
|
|
|
firstname: userInfo.firstname,
|
|
|
|
lastname: userInfo.lastname,
|
|
|
|
registrationToken: null,
|
|
|
|
isActive: true,
|
|
|
|
});
|
2020-05-19 16:10:53 +02:00
|
|
|
};
|
2020-05-19 10:55:52 +02:00
|
|
|
|
2020-05-28 14:03:48 +02:00
|
|
|
/**
|
|
|
|
* Find one user
|
|
|
|
*/
|
|
|
|
const findOne = async params => {
|
|
|
|
return strapi.query('user', 'admin').findOne(params);
|
|
|
|
};
|
|
|
|
|
2020-05-19 10:55:52 +02:00
|
|
|
/** Find many users (paginated)
|
|
|
|
* @param query
|
|
|
|
* @returns {Promise<user>}
|
|
|
|
*/
|
|
|
|
const findPage = async query => {
|
|
|
|
return strapi.query('user', 'admin').findPage(query);
|
2020-05-18 17:16:49 +02:00
|
|
|
};
|
|
|
|
|
2020-05-19 16:10:53 +02:00
|
|
|
/** Search for many users (paginated)
|
|
|
|
* @param query
|
|
|
|
* @returns {Promise<user>}
|
|
|
|
*/
|
|
|
|
const searchPage = async query => {
|
|
|
|
return strapi.query('user', 'admin').searchPage(query);
|
|
|
|
};
|
|
|
|
|
2020-06-18 11:40:50 +02:00
|
|
|
/** Delete users
|
|
|
|
* @param query
|
|
|
|
* @returns {Promise<user>}
|
|
|
|
*/
|
|
|
|
const deleteFn = async query => {
|
|
|
|
return strapi.query('user', 'admin').delete(query);
|
|
|
|
};
|
|
|
|
|
2020-06-12 18:42:07 +02:00
|
|
|
/** Count the users that don't have any associated roles
|
|
|
|
* @returns {Promise<number>}
|
|
|
|
*/
|
|
|
|
const countUsersWithoutRole = async () => {
|
|
|
|
const userModel = strapi.query('user', 'admin').model;
|
|
|
|
let count;
|
|
|
|
|
|
|
|
if (userModel.orm === 'bookshelf') {
|
2020-06-18 11:40:50 +02:00
|
|
|
count = await strapi.query('user', 'admin').count({ roles_null: true });
|
2020-06-12 18:42:07 +02:00
|
|
|
} else if (userModel.orm === 'mongoose') {
|
2020-06-18 11:40:50 +02:00
|
|
|
count = await strapi.query('user', 'admin').model.countDocuments({
|
|
|
|
$or: [{ roles: { $exists: false } }, { roles: { $size: 0 } }],
|
|
|
|
});
|
2020-06-12 18:42:07 +02:00
|
|
|
} else {
|
2020-06-22 13:00:21 +02:00
|
|
|
const allRoles = await strapi.query('role', 'admin').find({ _limit: -1 });
|
2020-06-12 18:42:07 +02:00
|
|
|
count = await strapi.query('user', 'admin').count({
|
|
|
|
roles_nin: allRoles.map(r => r.id),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return count;
|
|
|
|
};
|
|
|
|
|
2020-06-19 18:54:37 +02:00
|
|
|
/** Assign some roles to several users
|
|
|
|
* @returns {undefined}
|
|
|
|
*/
|
|
|
|
const assignARoleToAll = async roleId => {
|
|
|
|
const userModel = strapi.query('user', 'admin').model;
|
|
|
|
|
|
|
|
if (userModel.orm === 'bookshelf') {
|
2020-06-22 13:00:21 +02:00
|
|
|
const assocTable = userModel.associations.find(a => a.alias === 'roles').tableCollectionName;
|
|
|
|
const userTable = userModel.collectionName;
|
2020-06-19 18:54:37 +02:00
|
|
|
const knex = strapi.connections[userModel.connection];
|
|
|
|
const usersIds = await knex
|
|
|
|
.select(`${userTable}.id`)
|
|
|
|
.from(userTable)
|
|
|
|
.leftJoin(assocTable, `${userTable}.id`, `${assocTable}.user_id`)
|
|
|
|
.where(`${assocTable}.role_id`, null)
|
|
|
|
.pluck(`${userTable}.id`);
|
|
|
|
|
|
|
|
if (usersIds.length > 0) {
|
|
|
|
const newRelations = usersIds.map(userId => ({ user_id: userId, role_id: roleId }));
|
|
|
|
await knex.insert(newRelations).into(assocTable);
|
|
|
|
}
|
|
|
|
} else if (userModel.orm === 'mongoose') {
|
|
|
|
await strapi.query('user', 'admin').model.updateMany({}, { roles: [roleId] });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-05-14 10:37:32 +02:00
|
|
|
module.exports = {
|
|
|
|
create,
|
2020-06-18 18:10:12 +02:00
|
|
|
updateById,
|
2020-05-14 10:37:32 +02:00
|
|
|
exists,
|
2020-05-18 16:07:37 +02:00
|
|
|
findRegistrationInfo,
|
2020-05-18 17:16:49 +02:00
|
|
|
register,
|
2020-05-19 10:55:52 +02:00
|
|
|
sanitizeUser,
|
2020-05-28 14:03:48 +02:00
|
|
|
findOne,
|
2020-05-19 10:55:52 +02:00
|
|
|
findPage,
|
2020-05-19 16:10:53 +02:00
|
|
|
searchPage,
|
2020-06-18 11:40:50 +02:00
|
|
|
delete: deleteFn,
|
2020-06-12 18:42:07 +02:00
|
|
|
countUsersWithoutRole,
|
2020-06-19 18:54:37 +02:00
|
|
|
assignARoleToAll,
|
2020-05-13 11:46:52 +02:00
|
|
|
};
|