Role-Based Permissions
In this section, we will explore how to define and enforce role-based permissions using Asgardian. Role-based access control (RBAC) allows you to assign permissions to users based on their roles, making it easier to manage access control in your application.
Defining Roles
Roles are a way to group permissions together. You can define roles and assign them to users, and then define rules that apply to these roles.
Basic Role Definition
You can define roles using a simple structure. Typically, roles are defined as strings or objects.
import { createAbility } from '@nordic-ui/asgardian';
const ability = createAbility();
// Define roles
const roles = {
admin: ['create', 'read', 'update', 'delete', 'manage'],
user: ['read'],
};
Assigning Roles to Users
You can assign roles to users based on their user object or context.
Example User Object
const user = {
id: 123,
roles: ['admin'],
};
const anotherUser = {
id: 456,
roles: ['user'],
};
Defining Role-Based Rules
You can define rules that apply to specific roles. This allows you to specify which actions users with certain roles can perform on specific resources.
Basic Role-Based Rule
// Allow admins to perform all actions on all resources
ability.can('manage', 'all', (resource, context) => context.user.roles.includes('admin'));
// Allow users to read posts
ability.can('read', 'Post', (resource, context) => context.user.roles.includes('user'));
Using Role Arrays
You can check for multiple roles in a single rule.
// Allow admins and moderators to create and update posts
ability.can(['create', 'update'], 'Post', (resource, context) =>
context.user.roles.includes('admin') || context.user.roles.includes('moderator'));
Example with Role-Based Permissions
Here is a complete example that demonstrates how to define and check role-based permissions in Asgardian.
Define Roles and Rules
import { createAbility } from '@nordic-ui/asgardian';
const ability = createAbility();
// Define roles
const roles = {
admin: ['create', 'read', 'update', 'delete', 'manage'],
user: ['read'],
moderator: ['create', 'update'],
};
// Define rules based on roles
ability.can('manage', 'all', (resource, context) => context.user.roles.includes('admin'));
ability.can('read', 'Post', (resource, context) => context.user.roles.includes('user'));
ability.can(['create', 'update'], 'Post', (resource, context) =>
context.user.roles.includes('admin') || context.user.roles.includes('moderator'));
ability.can('delete', 'Post', (resource, context) => context.user.roles.includes('admin'));
Check Permissions
const adminUser = {
id: 123,
roles: ['admin'],
};
const userUser = {
id: 456,
roles: ['user'],
};
const moderatorUser = {
id: 789,
roles: ['moderator'],
};
// Check permissions for admin
console.log(ability.isAllowed('manage', 'Post', null, { user: adminUser })); // true
console.log(ability.isAllowed('create', 'Post', null, { user: adminUser })); // true
console.log(ability.isAllowed('read', 'Post', null, { user: adminUser })); // true
console.log(ability.isAllowed('delete', 'Post', null, { user: adminUser })); // true
// Check permissions for user
console.log(ability.isAllowed('manage', 'Post', null, { user: userUser })); // false
console.log(ability.isAllowed('create', 'Post', null, { user: userUser })); // false
console.log(ability.isAllowed('read', 'Post', null, { user: userUser })); // true
console.log(ability.isAllowed('delete', 'Post', null, { user: userUser })); // false
// Check permissions for moderator
console.log(ability.isAllowed('manage', 'Post', null, { user: moderatorUser })); // false
console.log(ability.isAllowed('create', 'Post', null, { user: moderatorUser })); // true
console.log(ability.isAllowed('read', 'Post', null, { user: moderatorUser })); // true
console.log(ability.isAllowed('delete', 'Post', null, { user: moderatorUser })); // false
Advanced Role-Based Permissions
For more complex scenarios, you can combine roles and conditions to enforce fine-grained access control.
Role and Condition Combination
// Allow moderators to update posts only if they are authored by the moderator
ability.can('update', 'Post', (resource, context) =>
context.user.roles.includes('moderator') && resource.authorId === context.user.id);
const post = {
id: 1,
authorId: 789,
};
console.log(ability.isAllowed('update', 'Post', post, { user: moderatorUser })); // true
const differentPost = {
id: 2,
authorId: 456,
};
console.log(ability.isAllowed('update', 'Post', differentPost, { user: moderatorUser })); // false
Summary
In this section, we learned how to define and enforce role-based permissions using Asgardian. Role-based access control allows you to manage user permissions efficiently by grouping them into roles and defining rules that apply to these roles.
For more advanced use cases and best practices, refer to the Advanced Usage section.