Skip to Content
DocumentationRules and Conditions

Rules and Conditions

In this section, we will explore how to define rules and use conditions in Asgardian to manage user permissions effectively.

Defining Basic Rules

Rules in Asgardian are defined using the can and cannot methods. These methods allow you to specify actions, resources, and optional conditions.

Basic can Rule

The can method is used to define permissions that a user can perform.

import { createAbility } from '@nordic-ui/asgardian'; const ability = createAbility(); // Allow reading posts ability.can('read', 'Post');

Basic cannot Rule

The cannot method is used to define permissions that a user cannot perform.

// Disallow deleting posts ability.cannot('delete', 'Post');

Multiple Actions

You can define multiple actions in a single rule using an array.

// Allow creating, updating, and deleting posts ability.can(['create', 'update', 'delete'], 'Post');

All Actions

To define all actions in a single rule, use the 'manage' keyword.

// Allow managing all actions ability.can('manage', 'Post');

Multiple Resources

You can define multiple resources in a single rule using an array.

// Allow creating posts and comments ability.can('create', ['Post', 'Comment']);

All Resources

To define a rule that applies to all resources, use the 'all' keyword.

// Allow managing all resources ability.can('manage', 'all');

Using Conditions

Conditions allow you to specify more granular rules based on specific criteria. You can use objects to define conditions. Asgardian will check the resource object against the condition object.

// Allow reading only published posts ability.can('read', 'Post', { published: true }); const publishedPost = { published: true }; const draftPost = { published: false }; console.log(ability.isAllowed('read', 'Post', publishedPost)); // true console.log(ability.isAllowed('read', 'Post', draftPost)); // false

Combining Rules

You can combine multiple rules to create complex permission structures.

Combining can and cannot

You can mix can and cannot rules to define specific permissions.

// Allow reading posts and disallow deleting posts ability .can('read', 'Post') .cannot('delete', 'Post'); const canReadPost = ability.isAllowed('read', 'Post'); console.log(canReadPost); // true const canDeletePost = ability.isAllowed('delete', 'Post'); console.log(canDeletePost); // false

Advanced Conditions

For advanced use cases, you can create more sophisticated permission rules by combining multiple conditions and rules.

Multiple Conditions

You can specify multiple conditions that must all be met:

const ability = createAbility() // Allow managing posts only if both conditions are met ability.can('manage', 'Post', { authorId: 123, published: true }) // All conditions must match ability.isAllowed('manage', 'Post', { authorId: 123, published: true }) // true ability.isAllowed('manage', 'Post', { authorId: 123, published: false }) // false ability.isAllowed('manage', 'Post', { authorId: 456, published: true }) // false

Combining Rules

You can create complex permission structures by chaining multiple rules:

const ability = createAbility() .can('read', 'Post') .can(['read', 'create'], 'Comment') .cannot('update', 'Comment') // Check permissions ability.isAllowed('read', 'Post') // true ability.isAllowed('delete', 'Post') // false ability.isAllowed('read', 'Comment') // true ability.isAllowed('create', 'Comment') // true ability.isAllowed('update', 'Comment') // false

Rule Precedence

Rules are evaluated in order, with later rules taking precedence over earlier ones. It’s recommended to follow the principle of least privilege by:

  1. Starting with restrictive permissions
  2. Adding specific allowances where needed
  3. Using cannot rules as safety guards
const ability = createAbility() // ❌ Bad practice: Starting with broad permissions ability .can('manage', 'all') .cannot('delete', 'Comment') // Trying to restrict after the fact // ✅ Good practice: Start restrictive, add specific permissions ability .can('read', 'Post', { published: true }) // Allow reading published posts .can(['create', 'update'], 'Post', { authorId: 123 }) // Allow authors to manage their own posts .cannot('delete', 'Post') // Ensure deletion is never allowed, regardless of other rules // Even better: Be explicit about all permissions const userAbility = createAbility() // Post permissions .can('read', 'Post', { published: true }) .can('create', 'Post') .can('update', 'Post', { authorId: 123 }) // Comment permissions .can('read', 'Comment') .can('create', 'Comment', { authenticated: true }) .cannot('delete', 'Comment') // Extra safety guard

Using Operators

For more complex conditions, you can use operators:

import { operators } from '@nordic-ui/asgardian' const ability = createAbility() ability.can('read', 'Post', { status: operators.or('published', 'archived'), views: operators.gt(1000), tags: operators.includesAll(['important', 'featured']) })

Summary

In this section, we explored how to create advanced permission rules using multiple conditions, role-based access control, and rule combinations. While the library doesn’t support dynamic context evaluation directly, you can achieve complex permission structures through careful rule composition and condition combinations.

Last updated on