Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@casl/angular

Package Overview
Dependencies
Maintainers
1
Versions
53
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@casl/angular

Angular module for CASL which makes it easy to add permissions in any Angular application

  • 3.0.5
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
9.3K
decreased by-5.86%
Maintainers
1
Weekly downloads
 
Created
Source

CASL Angular @casl/angular NPM version CASL Documentation CASL Join the chat at https://gitter.im/stalniy-casl/casl

This package allows to integrate @casl/ability into Angular application. So, you can show or hide some components, buttons, etc based on user ability to see them.

Installation

npm install @casl/angular @casl/ability

Getting Started

1. Including module

This package provides AbilityModule module which adds CanPipe to templates and Ability instance to dependency injection container

// app.module.ts

import { NgModule } from '@angular/core'
import { AbilityModule } from '@casl/angular'
// ...

@NgModule({
  imports: [
    ...,
    AbilityModule.forRoot()
  ],
  declarations: [...],
  bootstrap: [...],
})
export class AppModule {}

Note: make sure that you use AbilityModule.forRoot() in your main module (usually it's AppModule) and AbilityModule in children modules (including lazy loaded ones).

2. Defining Abilities

This module provides an empty Ability instance, so you either need to provide your own or update existing one. In case if you want to provide your own, just define it using AbilityBuilder (or whatever way you prefer):

// ability.ts
import { AbilityBuilder } from '@casl/ability'

export const ability = AbilityBuilder.define(can => {
  can('read', 'all')
})

Later in your AppModule add additional provider:

import { AbilityModule } from ....
....
import { Ability } from '@casl/ability'
import { ability } from './ability'

@NgModule({
  imports: [
    ...,
    AbilityModule.forRoot()
  ],
  declarations: [...],
  providers: [
    { provide: Ability, useValue: ability }
  ],
  bootstrap: [...],
})
export class AppModule {}

Alternatively, you can just inject existing instance and update rules. Imagine that we have a Session service which is responsible for user login/logout functionality. Whenever user login, we need to update ability rules with rules which server returns and reset them back on logout. Lets do this:

// session.ts
import { Ability } from '@casl/ability'

export class Session {
  private token: string

  constructor(private ability: Ability) {}

  login(details) {
    return fetch('path/to/api/login', { methods: 'POST', body: JSON.stringify(details) })
      .then(response => response.json())
      .then(session => {
        this.ability.update(session.rules)
        this.token = session.token
       })
  }

  logout() {
    this.token = null
    this.ability.update([])
    // or this.ability.update([{ actions: 'read', subject: 'all' }]) to make everything to be readonly
  }
}

See @casl/ability package for more information on how to define abilities.

3. Check permissions in templates

To check permissions in any template you can use CanPipe:

<div *ngIf="'Post' | can: 'create'">
  <a (click)="createPost()">Add Post</a>
</div>
Performance considerations

Due to open feature in Angular, CanPipe was designed to be impure. This should work pretty fine if you have simple list of rules but may become a bottleneck when you have a lot of them. Don't worry, as there are several strategies which you can pick to make it faster:

  • use memoization (either on Ability#can or on CanPipe#can methods)
  • use immutable objects and overwrite existing pipe to be pure
  • use ChangeDectionStrategy.OnPush on your components whenever possible

To memoize results of CanPipe, you will need to create your own one and change its can method to cache results (this method was specifically designed to be overloaded by child class). Also you will need to clear all memoized results when corresponding Ability instance is updated (see update ability for details). The similar strategy can be applied to Ability class. Don't forget to provide new pipe or Ability class in Dependency injection! For example

import { MemoizedAbility } from './ability'
import { Ability } from '@casl/ability'

@NgModule({
  ...,
  providers: [
    { provide: Ability, useClass: MemoizedAbility }
  ]
})
export class AppModule {}

or if you want to provide custom pipe:

// pure-can.pipe.ts
import { CanPipe } from '@casl/angular'

@Pipe({ name: 'can' })
export class MyCanPipe extends CanPipe {}

// app.module.ts
import { MyCanPipe } from './pure-can.pipe'

@NgModule({
  ...,
  declarations: [
    MyCanPipe
  ]
})
export class AppModule {}

Want to help?

Want to file a bug, contribute some code, or improve documentation? Excellent! Read up on guidelines for contributing

License

MIT License

Keywords

FAQs

Package last updated on 21 Feb 2020

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc