0

Im noobs use FeatherJS and I stuck on roles and permissions management in FeatherJS

I have tables contains users, users_role, and roles. Table roles have relationship with two permissions table. I dont save roles to users's table because one user can have more than one role.

enter image description here

I want to save roles.id into params.user, but I don't find the way how to save it. I want it because it's not efficient to query to database if I want to check a permission.

I try using

app.on('login', (authResult: AuthenticationResult, { connection }: Params) => {
    app
      .get('postgresqlClient')
      .select('users_roles.role_id')
      .from('users_roles')
      .where('users_roles.user_id', '=', authResult.user.id)
      .then(function (results) {
        for (const index in results) {
          authResult.user['roles'].push(results[index].role_id)
        }
      })
      .catch((err) => console.log(err))

    if (connection) {
      app.channel('anonymous').leave(connection)
      console.log('An user leave anonymous channel')

      app.channel('authenticated').join(connection)
      app.channel('authenticated')
      console.log('An user authenticated and join authenticated channel')
    }
  })

But it seems not saved into context.

{
  "accessToken": "jwtinhere",
  "authentication": {
    "strategy": "local",
    "payload": {
      "iat": 1675662745,
      "exp": 1675749145,
      "aud": "https://yourdomain.com",
      "sub": "843438ee-69cb-493f-8812-71f0c7462f2f",
      "jti": "dbd0641c-65b2-413c-ae80-52ba5f9c4e89"
    }
  },
  "user": {
    "id": "843438ee-69cb-493f-8812-71f0c7462f2f",
    "full_name": "Super Admin",
    "email": "[email protected]",
    "created_at": "2023-01-31T15:08:06.141Z",
    "updated_at": "2023-01-31T15:08:06.141Z"
  }
}

I want to my roles saved on context, so the result after successfully authentication is

{
  "accessToken": "jwtinhere",
  "authentication": {
    "strategy": "local",
    "payload": {
      "iat": 1675662745,
      "exp": 1675749145,
      "aud": "https://yourdomain.com",
      "sub": "843438ee-69cb-493f-8812-71f0c7462f2f",
      "jti": "dbd0641c-65b2-413c-ae80-52ba5f9c4e89"
    }
  },
  "user": {
    "id": "843438ee-69cb-493f-8812-71f0c7462f2f",
    "full_name": "Super Admin",
    "email": "[email protected]",
    "created_at": "2023-01-31T15:08:06.141Z",
    "updated_at": "2023-01-31T15:08:06.141Z",
    "role": [0,1] // Added Role
  }
}

And I only call context.params.user.role in hook if want to check the user roles. How can I do this? Thanks

1 Answer 1

0

You could include the relation on the entityService (probably the users-service) get method. The authentication service calls the entityService's get method when creating the authentication. If you only need the role.id's, you could map it in the after hooks user the alterItems-hook.

For example create a generic hook 'includeRelation' and call it the before get hook:

include-relation.hook.ts

export function includeRelation(tableName: string, asKey?: string, raw = false) {
  return async (context: HookContext) => {
    checkContext(context, 'before', ['find', 'get']);

    context.params.sequelize = {
      include: {
        model: context.app.get('sequelizeClient').models[tableName],
        as:
          asKey ??
          // convert snake case (table_name) to camel case (tableName)
          tableName
            .split('_')
            .map((name, index) => (index > 0 ? name.charAt(0).toUpperCase() + name.slice(1) : name))
            .join(''),
      },
      raw,
      nest: true,
    };

    return context;
  };
}

user.hooks.ts

export const usersHooks: HooksObject = {
  before: {
    get: [includeRelation('users_roles', 'usersRoles', true)],
  },
};

Check node_modules/@feathersjs/authentication/src/jwt.ts to see how it works.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.