mirror of
				https://github.com/strapi/strapi.git
				synced 2025-11-04 03:43:34 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			186 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			186 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
'use strict';
 | 
						|
 | 
						|
/**
 | 
						|
 * User.js service
 | 
						|
 *
 | 
						|
 * @description: A set of functions similar to controller's actions to avoid code duplication.
 | 
						|
 */
 | 
						|
 | 
						|
const crypto = require('crypto');
 | 
						|
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';
 | 
						|
 | 
						|
module.exports = ({ strapi }) => ({
 | 
						|
  /**
 | 
						|
   * Promise to count users
 | 
						|
   *
 | 
						|
   * @return {Promise}
 | 
						|
   */
 | 
						|
 | 
						|
  count(params) {
 | 
						|
    return strapi.db.query(USER_MODEL_UID).count({ where: params });
 | 
						|
  },
 | 
						|
 | 
						|
  /**
 | 
						|
   * 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',
 | 
						|
   *
 | 
						|
   * @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.
 | 
						|
   * @return {Promise}
 | 
						|
   */
 | 
						|
  async add(values) {
 | 
						|
    return strapi.db.query(USER_MODEL_UID).create({
 | 
						|
      data: await this.ensureHashedPasswords(values),
 | 
						|
      populate: ['role'],
 | 
						|
    });
 | 
						|
  },
 | 
						|
 | 
						|
  /**
 | 
						|
   * Promise to edit a/an user.
 | 
						|
   * @param {string} userId
 | 
						|
   * @param {object} params
 | 
						|
   * @return {Promise}
 | 
						|
   */
 | 
						|
  async edit(userId, params = {}) {
 | 
						|
    return strapi.db.query(USER_MODEL_UID).update({
 | 
						|
      where: { id: userId },
 | 
						|
      data: await this.ensureHashedPasswords(params),
 | 
						|
      populate: ['role'],
 | 
						|
    });
 | 
						|
  },
 | 
						|
 | 
						|
  /**
 | 
						|
   * Promise to fetch a/an user.
 | 
						|
   * @return {Promise}
 | 
						|
   */
 | 
						|
  fetch(id, params) {
 | 
						|
    const query = strapi.get('query-params').transform(USER_MODEL_UID, params ?? {});
 | 
						|
 | 
						|
    return strapi.db.query(USER_MODEL_UID).findOne({
 | 
						|
      ...query,
 | 
						|
      where: {
 | 
						|
        $and: [{ id }, query.where || {}],
 | 
						|
      },
 | 
						|
    });
 | 
						|
  },
 | 
						|
 | 
						|
  /**
 | 
						|
   * Promise to fetch authenticated user.
 | 
						|
   * @return {Promise}
 | 
						|
   */
 | 
						|
  fetchAuthenticatedUser(id) {
 | 
						|
    return strapi.db.query(USER_MODEL_UID).findOne({ where: { id }, populate: ['role'] });
 | 
						|
  },
 | 
						|
 | 
						|
  /**
 | 
						|
   * Promise to fetch all users.
 | 
						|
   * @return {Promise}
 | 
						|
   */
 | 
						|
  fetchAll(params) {
 | 
						|
    const query = strapi.get('query-params').transform(USER_MODEL_UID, params ?? {});
 | 
						|
 | 
						|
    return strapi.db.query(USER_MODEL_UID).findMany(query);
 | 
						|
  },
 | 
						|
 | 
						|
  /**
 | 
						|
   * Promise to remove a/an user.
 | 
						|
   * @return {Promise}
 | 
						|
   */
 | 
						|
  async remove(params) {
 | 
						|
    return strapi.db.query(USER_MODEL_UID).delete({ where: params });
 | 
						|
  },
 | 
						|
 | 
						|
  validatePassword(password, hash) {
 | 
						|
    return bcrypt.compare(password, hash);
 | 
						|
  },
 | 
						|
 | 
						|
  async sendConfirmationEmail(user) {
 | 
						|
    const userPermissionService = getService('users-permissions');
 | 
						|
    const pluginStore = await strapi.store({ type: 'plugin', name: 'users-permissions' });
 | 
						|
    const userSchema = strapi.getModel(USER_MODEL_UID);
 | 
						|
 | 
						|
    const settings = await pluginStore
 | 
						|
      .get({ key: 'email' })
 | 
						|
      .then((storeEmail) => storeEmail.email_confirmation.options);
 | 
						|
 | 
						|
    // Sanitize the template's user information
 | 
						|
    const sanitizedUserInfo = await sanitize.sanitizers.defaultSanitizeOutput(
 | 
						|
      {
 | 
						|
        schema: userSchema,
 | 
						|
        getModel: strapi.getModel.bind(strapi),
 | 
						|
      },
 | 
						|
      user
 | 
						|
    );
 | 
						|
 | 
						|
    const confirmationToken = crypto.randomBytes(20).toString('hex');
 | 
						|
 | 
						|
    await this.edit(user.id, { confirmationToken });
 | 
						|
 | 
						|
    const apiPrefix = strapi.config.get('api.rest.prefix');
 | 
						|
 | 
						|
    try {
 | 
						|
      settings.message = await userPermissionService.template(settings.message, {
 | 
						|
        URL: urlJoin(
 | 
						|
          strapi.config.get('server.absoluteUrl'),
 | 
						|
          apiPrefix,
 | 
						|
          '/auth/email-confirmation'
 | 
						|
        ),
 | 
						|
        SERVER_URL: strapi.config.get('server.absoluteUrl'),
 | 
						|
        ADMIN_URL: strapi.config.get('admin.absoluteUrl'),
 | 
						|
        USER: sanitizedUserInfo,
 | 
						|
        CODE: confirmationToken,
 | 
						|
      });
 | 
						|
 | 
						|
      settings.object = await userPermissionService.template(settings.object, {
 | 
						|
        USER: sanitizedUserInfo,
 | 
						|
      });
 | 
						|
    } catch {
 | 
						|
      strapi.log.error(
 | 
						|
        '[plugin::users-permissions.sendConfirmationEmail]: Failed to generate a template for "user confirmation email". Please make sure your email template is valid and does not contain invalid characters or patterns'
 | 
						|
      );
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    // Send an email to the user.
 | 
						|
    await strapi
 | 
						|
      .plugin('email')
 | 
						|
      .service('email')
 | 
						|
      .send({
 | 
						|
        to: user.email,
 | 
						|
        from:
 | 
						|
          settings.from.email && settings.from.name
 | 
						|
            ? `${settings.from.name} <${settings.from.email}>`
 | 
						|
            : undefined,
 | 
						|
        replyTo: settings.response_email,
 | 
						|
        subject: settings.object,
 | 
						|
        text: settings.message,
 | 
						|
        html: settings.message,
 | 
						|
      });
 | 
						|
  },
 | 
						|
});
 |