How to set Strapi user role programmatically?

System Information
  • Strapi Version: 3.6.10
  • Database: MongoDB

I’m using Strapi 3.6.10.

When I create user via http://host:1337/auth/local/register, I’m not able to achieve desirable user’s role. It’s always Authenticated, even if I directly set it to another in my request

{  
    "username": "user",   
    "email": "user@mail.com",  
    "password": "123456789",   
    "role": {   
        "_id": "626eacea45f0a420ccb35094"
    }
}

I’ve also tried using API documented in generated by Documentation plugin Swagger - PUT /users/{id}. But if I send request with new role nothing happens to my user’s entry

For STRAPI v4, that is mostly used now :

If you want a specific role for all new users, I suggest you to edit your default registered user role by going on your StrAPI admin panel, go to Settings > Advanced Settings.

You will be able to edit your “Default role for authenticated users”. It is the default role attributed to new accounts.

If you just want to edit user role, you can do it by updating the concerned user.

You first have to retrieve the id of the role you wanna assign to. For exemple, I want to assign to my user the role author.

// You cannot find your role with its id, because it is what we are looking for,
// so we have to use the `findMany` method, that returns an array
const roles = await strapi.entityService.findMany(
    "plugin::users-permissions.role",
    {
        filters: { type: "author" },
    }
);

// Check if the role has been found
if (!roles || roles.length === 0) {
    // Error handling
}

const authorRole = roles[0];

Now, we have to update our user with the new role.

const user = await strapi.entityService.update(
    "plugin::users-permissions.user",
    ctx.state.user.id,
    {
        data: {
            role: authorRole.id
        }
    }
);

You can create a custom route to put this code into, so the user can first create an account with default role and limited access, and after specify what role he want by calling your custom route, and apply the update.

If you really want to do that directly after user creation, you can take exemple of this forum by creating a global middleware to check if the request is a register, and execute some code after that :

Create a file in src/middlewares/your-custom-middleware.js. It is important that you write your file name in lowercase. Separate your words with hyphens.

// src/middlewares/your-custom-middleware.js
"use strict";

module.exports = () => {
    return async (ctx, next) => {
        // The `next()` call will register your user with the default role
        await next();

        if (ctx.request.url === '/api/auth/local/register' && ctx.response.status === 200) {

            // Now we can apply our logic, but we have to retrieve the user

            const userArray = await strapi.entityService.findMany(
                "plugin::users-permissions.user",
                {
                    filters: { email: ctx.request.body.email }
                }
            );

            if (!userArray || userArray.length === 0) {
                // Handle error, can't find user
            }

            const user = userArray[0];

            const roles = await strapi.entityService.findMany(
                "plugin::users-permissions.role",
                {
                    filters: { type: "author" },
                }
            );

            // Check if the role has been found
            if (!roles || roles.length === 0) {
                // Error handling
            }

            const authorRole = roles[0];

            const updatedUser = await strapi.entityService.update(
                "plugin::users-permissions.user",
                user.id,
                {
                    data: {
                        role: authorRole.id
                    }
                }
            );
        }
    };
};

To finish, you have to register your middleware as global by editing the config/middleware.js file :

module.exports = [
  // The array is pre-populated with internal, built-in middlewares, prefixed by `strapi::`
  'strapi::errors',
  'strapi::security',
  'strapi::cors',
   // ...
  'global::your-custom-middleware'
]

I still cant comprehend why you wouldnt be able to create a user with a role by passing the role id.

Super annoying.