strapi-server.js 3.78 KB
const utils = require("@strapi/utils");

const _ = require("lodash");
const { sanitize } = utils;
const { ApplicationError } = utils.errors;
const {
  validateRegisterBody,
} = require("@strapi/plugin-users-permissions/server/controllers/validation/auth");

const sanitizeUser = (user, ctx) => {
  const { auth } = ctx.state;
  const userSchema = strapi.getModel("plugin::users-permissions.user");

  return sanitize.contentAPI.output(user, userSchema, { auth });
};

const userPermissionExtension = (plugin) => {
  /** Example of overriding and adding a new endpoint, check the section where we have registered this as a route below. */
  plugin.controllers.user.updateMe = (ctx) => {
    ctx.params.id = ctx.state.user.id;
    return plugin.controllers.user.update(ctx);
  };

  /** Example of overriding an existing route. */
  plugin.controllers.auth.register = async (ctx) => {

    const pluginStore = await strapi.store({
      type: "plugin",
      name: "users-permissions",
    });

    const settings = await pluginStore.get({ key: "advanced" });

    if (!settings.allow_register) {
      throw new ApplicationError("Register action is currently disabled");
    }

    const params = {
      ..._.omit(ctx.request.body, [
        "confirmed",
        "blocked",
        "confirmationToken",
        "resetPasswordToken",
        "provider",
      ]),
      provider: "local",
    };

    await validateRegisterBody(params);

    // We have added the ability to choose the role.
    // This is the customisation that we wanted to do to make this possible
    const newUserRole = params?.role ? params?.role : settings.default_role;

    // the query was also changed to apply a query on "name" rather than the default "type".
    const role = await strapi
      .query("plugin::users-permissions.role")
      .findOne({ where: { name: newUserRole } });

    if (!role) {
      throw new ApplicationError("Impossible to find the default role");
    }

    // @ts-ignore
    const { email, username, provider } = params;

    const identifierFilter = {
      $or: [
        { email: email.toLowerCase() },
        { username: email.toLowerCase() },
        { username },
        { email: username },
      ],
    };

    const conflictingUserCount = await strapi
      .query("plugin::users-permissions.user")
      .count({
        where: { ...identifierFilter, provider },
      });

    if (conflictingUserCount > 0) {
      throw new ApplicationError("Email or Username are already taken");
    }

    if (settings.unique_email) {
      const conflictingUserCount = await strapi
        .query("plugin::users-permissions.user")
        .count({
          where: { ...identifierFilter },
        });

      if (conflictingUserCount > 0) {
        throw new ApplicationError("Email or Username are already taken");
      }
    }

    let newUser = {
      ...params,
      role: role.id,
      email: email.toLowerCase(),
      username,
      confirmed: !settings.email_confirmation,
    };

    const user = await strapi
      .plugin("users-permissions")
      .service("user")
      .add(newUser);

    const sanitizedUser = await sanitizeUser(user, ctx);

    if (settings.email_confirmation) {
      try {
        await strapi
          .plugin("users-permissions")
          .service("user")
          .sendConfirmationEmail(sanitizedUser);
      } catch (err) {
        throw new ApplicationError(err.message);
      }

      return ctx.send({ user: sanitizedUser });
    }

    const jwt = strapi
      .plugin("users-permissions")
      .service("jwt")
      .issue(_.pick(user, ["id"]));

    return ctx.send({
      jwt,
      user: sanitizedUser,
    });
  };

  plugin.routes["content-api"].routes.push({
    method: "PUT",
    path: "/users/me",
    handler: "user.updateMe",
  });

  return plugin;
};

module.exports = userPermissionExtension;