npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@iamjs/core

v2.0.15

Published

This package contains the core logic and interfaces for the authorization library with End-to-end typesafety

Downloads

86

Readme

@iamjs/core

Overview

iamjs is a powerful and flexible library for implementing role-based access control (RBAC) in JavaScript applications. The core package (@iamjs/core) provides essential functionality for managing roles, permissions, and authorization in your application. With iamjs, you can easily define complex permission structures, manage user roles, and enforce access control throughout your application.

Table of Contents

Installation

You can install the iamjs core library using your preferred package manager:

npm install @iamjs/core
# or
yarn add @iamjs/core
# or
pnpm add @iamjs/core
# or
bun add @iamjs/core

Key Concepts

  • Role: A set of permissions that can be assigned to users. Roles define what actions a user can perform on various resources.
  • Resource: An entity in your application that actions can be performed on (e.g., 'user', 'post', 'comment').
  • Action: An operation that can be performed on a resource (e.g., 'create', 'read', 'update', 'delete', 'list').
  • Permission: A combination of a resource and allowed actions. Permissions can be base permissions (CRUD operations) or custom permissions specific to your application.
  • Schema: A collection of roles that defines the overall authorization structure of your application.

Usage

Creating Roles

Create new roles using the Role class. You can define base permissions using CRUD notation and add custom permissions as needed.

import { Role } from '@iamjs/core';

// Create a basic user role
const userRole = new Role({
  name: 'user',
  description: 'Standard user with limited permissions',
  config: {
    user: {
      base: '-r--l', // Can only read and list users
      custom: { 
        updateOwnProfile: true 
      }
    },
    post: {
      base: 'crud-', // Can create, read, update, but not delete posts
      custom: { 
        publish: true,
        unpublish: true
      }
    },
    comment: {
      base: 'crudl', // Full access to comments
      custom: {
        report: true
      }
    }
  }
});

// Create an admin role with full permissions
const adminRole = new Role({
  name: 'admin',
  description: 'Administrator with full access',
  config: {
    user: {
      base: 'crudl',
      custom: { 
        ban: true,
        unban: true
      }
    },
    post: {
      base: 'crudl',
      custom: { 
        publish: true,
        unpublish: true,
        feature: true
      }
    },
    comment: {
      base: 'crudl',
      custom: {
        delete: true,
        restore: true
      }
    }
  }
});

In these examples, we've created two roles: a user role with limited permissions and an admin role with full access. The base permissions use CRUD notation (Create, Read, Update, Delete, List), where a dash (-) indicates the absence of that permission.

Managing Permissions

You can extend or update role permissions using the add and update methods:

// Add a new resource to the user role
const extendedUserRole = userRole.add({
  resource: 'category',
  permissions: {
    base: '-r--l', // Users can only read and list categories
    custom: { 
      subscribe: true,
      unsubscribe: true
    }
  }
});

// Update existing permissions for the admin role
const updatedAdminRole = adminRole.update({
  resource: 'user',
  permissions: {
    base: 'crudl',
    custom: { 
      ban: true,
      unban: true,
      promoteToModerator: true // New custom permission
    }
  }
});

// Remove a resource from a role
const reducedUserRole = userRole.remove({
  resource: 'comment'
});

These methods allow you to dynamically adjust permissions as your application evolves.

Checking Permissions

The Role class provides several methods to check permissions:

// Check if a role can perform a specific action on a resource
console.log(userRole.can('post', 'create')); // true
console.log(userRole.can('user', 'delete')); // false

// Check if a role cannot perform a specific action
console.log(userRole.cannot('user', 'ban')); // true

// Check if a role can perform any of the specified actions
console.log(userRole.canAny('post', ['create', 'delete'])); // true

// Check if a role can perform all of the specified actions
console.log(userRole.canAll('post', ['create', 'read', 'update', 'delete'])); // false

These methods make it easy to implement fine-grained access control in your application logic.

Authorization Management

Use the AuthManager class for centralized authorization management:

import { AuthManager, Schema } from '@iamjs/core';

// Create a schema with multiple roles
const schema = new Schema({ 
  roles: { 
    user: userRole, 
    admin: adminRole,
    moderator: moderatorRole // Assuming you've defined this role
  } 
});

// Initialize the AuthManager with the schema
const auth = new AuthManager(schema);

// Check authorization for different scenarios
console.log(auth.authorize({
  role: 'user',
  actions: ['read', 'create'],
  resources: 'post'
})); // true

console.log(auth.authorize({
  role: 'user',
  actions: ['delete'],
  resources: 'post'
})); // false

console.log(auth.authorize({
  role: 'admin',
  actions: ['ban'],
  resources: 'user'
})); // true

// Check multiple resources at once
console.log(auth.authorize({
  role: 'moderator',
  actions: ['update', 'delete'],
  resources: ['post', 'comment'],
  strict: true // Requires permission for all specified resources
})); // Depends on moderator role definition

The AuthManager provides a convenient way to check permissions across different roles and resources in your application.

API Reference

Role Class

  • constructor(options: RoleOptions)
  • add(options: AddOptions): Role
  • update(options: UpdateOptions): Role
  • remove(options: RemoveOptions): Role
  • can(resource: string, action: string): boolean
  • cannot(resource: string, action: string): boolean
  • canAny(resource: string, actions: string[]): boolean
  • canAll(resource: string, actions: string[]): boolean
  • toObject(): object
  • toJSON(): string
  • static fromObject(obj: object): Role
  • static fromJSON(json: string): Role
  • static from(data: any, transform: Function): Role

AuthManager Class

  • constructor(schema: Schema)
  • authorize(request: AuthorizationRequest): boolean

Schema Class

  • constructor(options: SchemaOptions)
  • getRole(name: string): Role | undefined
  • hasRole(name: string): boolean
  • addRole(role: Role): void
  • removeRole(name: string): void

Advanced Usage

Serialization and Deserialization

Convert roles to and from different formats for storage or transmission:

// Convert a role to JSON
const jsonString = userRole.toJSON();
console.log(jsonString);
// {"name":"user","description":"Standard user with limited permissions","config":{"user":{"base":"-r--l","custom":{"updateOwnProfile":true}},...}}

// Create a role from JSON
const recreatedUserRole = Role.fromJSON(jsonString);

// Convert a role to a plain object
const objectRepresentation = adminRole.toObject();
console.log(objectRepresentation);
// {name: "admin", description: "Administrator with full access", config: {...}}

// Create a role from an object
const recreatedAdminRole = Role.fromObject(objectRepresentation);

Custom Data Transformations

Use the from method for creating roles from custom data sources, such as encrypted data:

import crypto from 'crypto';
import { Role, GetRoleConfig } from '@iamjs/core';

// Assume we have these encryption functions defined
const encrypt = (data: string) => { /* ... */ };
const decrypt = (data: string) => { /* ... */ };

// Encrypt role data for storage
const encryptedRoleData = encrypt(userRole.toJSON());

// Later, recreate the role from encrypted data
const decryptedRole = Role.from(encryptedRoleData, (data) => {
  const decrypted = decrypt(data);
  return Role.fromJSON(decrypted).toObject() as GetRoleConfig<typeof userRole>;
});

console.log(decryptedRole.can('post', 'create')); // true

This approach allows you to securely store and transmit role data while maintaining the ability to recreate functional Role instances.

Best Practices

  1. Granular Permissions: Define permissions at a granular level to allow for fine-tuned access control.
  2. Hierarchical Roles: Consider implementing role hierarchies (e.g., admin > moderator > user) to simplify permission management.
  3. Regular Audits: Periodically review and audit your role definitions to ensure they align with your application's security requirements.
  4. Dynamic Role Assignment: Implement systems to dynamically assign and revoke roles based on user actions or system events.
  5. Principle of Least Privilege: Always start with the minimum necessary permissions and add more as needed.
  6. Consistent Naming: Use consistent naming conventions for resources and actions across your application.
  7. Documentation: Keep your role definitions and permission structures well-documented for easier maintenance and onboarding.

Contributing

We welcome contributions to iamjs! If you'd like to contribute, please follow these steps:

  1. Fork the repository
  2. Create a new branch for your feature or bug fix
  3. Make your changes and write tests if applicable
  4. Submit a pull request with a clear description of your changes

Please see our Contributing Guide for more detailed information.

License

iamjs is released under the MIT License. See the LICENSE file for more details.