化学文摘社
此软件包允许集成 @casl/ability 与 角质 应用。 它提供腐烂的 AblePipe, (中文(简体) ), AblePurePipe 新建 AbilityService 财务报告和审定财务报表 AbilityServiceSignal 转到Angular模板,这样就可以根据用户查看它们的能力显示或隐藏组件,按钮等.
安装
npm install @casl/angular @casl/ability
# or
yarn add @casl/angular @casl/ability
# or
pnpm add @casl/angular @casl/ability
配置应用程序
要将管道添加到应用程序的模板中, 您需要导入所需的管道
import { NgModule } from '@angular/core';
import { AblePipe } from '@casl/angular';
import { createMongoAbility, Ability } from '@casl/ability';
@NgModule({
imports: [
// other modules
AblePipe
],
providers: [
{ provide: Ability, useValue: createMongoAbility() }
]
// other properties
})
export class AppModule {}
读取 CASL 和类型脚本 获取更多细节
MongoAbility类型配置.
更新能力实例
需要权限检查支持的应用程序大多有类似的东西 AuthService 或者说 LoginService 或者说 Session 服务(按您的意愿命名),负责用户登录/登录功能。 每次用户登录(和登录),我们需要更新 Ability 以新规则为例.
让我们想象一下,服务器返回的用户在登录上有一个角色:
import { Ability, AbilityBuilder } from '@casl/ability';
import { Injectable } from '@angular/core';
@Injectable({ provideIn: 'root' })
export class Session {
#token: string
constructor(@Inject(Ability) private ability: MongoAbility) {}
login(details) {
const params = { method: 'POST', body: JSON.stringify(details) };
return fetch('path/to/api/login', params)
.then(response => response.json())
.then((session) => {
this.updateAbility(session.user);
this.#token = session.token;
});
}
private updateAbility(user) {
const { can, rules } = new AbilityBuilder(createMongoAbility);
if (user.role === 'admin') {
can('manage', 'all');
} else {
can('read', 'all');
}
this.ability.update(rules);
}
logout() {
this.#token = null;
this.ability.update([]);
}
}
见 定义规则 获取更多关于如何定义的信息
Ability。 。 。 .
那就用这个 Session 服务于 LoginComponent数字 :
import { Component } from '@angular/core';
import { Session } from '../services/Session';
@Component({
selector: 'login-form',
template: `
<form (ngSubmit)="login()">
<input type="email" [(ngModel)]="email" />
<input type="password" [(ngModel)]="password" />
<button type="submit">Login</button>
</form>
`
})
export class LoginForm {
email: string;
password: string;
constructor(private session: Session) {}
login() {
const { email, password } = this;
return this.session.login({ email, password });
}
}
使用 AbilityService 在模板中检查权限
AbilityService 是提供 ability$ 可见. DI中提供的可观察到的注射剂 Ability 并每次修改规则时发出。 这样可以高效使用权限检查,特别是在我们使用的情况下 ChangeDetectionStrategy.OnPush。 。 。 .
让我们先看看它如何用于任何组件:
@Component({
selector: 'my-home',
template: `
@if (ability$ | async as ability) {
<h1>Home Page</h1>
@if (ability.can('create', 'Post')) {
<button>Create Post</button>
}
}
`
})
export class HomeComponent {
readonly ability$: Observable<AppAbility>;
constructor(abilityService: AbilityService<AppAbility>) {
this.ability$ = abilityService.ability$;
}
}
也可以安全地在里面使用 *ngFor 和其他指示。 如果我们用 ChangeDetectionStrategy.OnPush,这将给我们更多的业绩改进,因为 ability.can(...) ⊿τ惠璶碞ぃ穦.
这种方法从绩效角度来说是行之有效的,因为它每个组件只产生单一订阅(而不是每一次核对) ablePure 并且不需要我们的部件使用 Default 或者说 OnPush 战略.
如何使用管道进行许可检查
信号支持
@casl/angular的最新版本也支持新版本 signal在您的应用中使用它,而不是 AbilityService 使用情况 AbilityServiceSignal数字 :
import { AbilityServiceSignal } from '@casl/angular';
import { AppAbility } from './AppAbility';
@Component({
selector: 'my-home',
template: `
<h1>Home Page</h1>
@if (can('create', 'Post')) {
<button>Create Post</button>
}
`
})
export class HomeComponent {
private readonly abilityService = inject<AbilityServiceSignal<AppAbility>>(AbilityServiceSignal);
protected readonly can = this.abilityService.can;
}
解释权限检查 whyCan 财务报告和审定财务报表 whyCannot
AbilityServiceSignal whyCan 财务报告和审定财务报表 whyCannot 方法有助于回答为什么允许或界定行动的问题:
const abilityService = inject<AbilityServiceSignal<AppAbility>>(AbilityServiceSignal);
abilityService.update([
{ action: 'create', subject: 'Post', reason: 'You can create posts' },
{
inverted: true,
action: 'delete',
subject: 'Post',
reason: 'Only administrators can delete posts'
}
]);
abilityService.whyCan('create', 'Post'); // { reason: 'You can create posts' }
abilityService.whyCan('delete', 'Post'); // null
abilityService.whyCannot('delete', 'Post'); // { reason: 'Only administrators can delete posts' }
abilityService.whyCan('update', 'Post'); // null
abilityService.whyCannot('update', 'Post'); // { reason: undefined }
abilityService.whyCannot('create', 'Post'); // null
将这些方法显示为模板,与 can 像这样使用它们:
@if (whyCannot('delete', 'Post'); as forbidden) {
<span>{{ forbidden.reason || 'You cannot delete posts' }}</span>
} @else {
<button (click)="deletePost()">Delete Post</button>
}
无故匹配倒置规则返回对象 reason: undefined 当方法的条件得到满足时。 即便没有任何解释,这仍然使否认真相.
创建权限信号 defer* 方法
这个 defer* 方法返回计算出的信号。 每个参数(动作,主题,或可选字段)都可以是一个平面值或信号. 返回的信号在能力规则或任何信号参数发生变化时会重新计算.
一次创建这些信号, 例如在组件字段初始化器中, 在模板中读取 :
import { Component, inject, input } from '@angular/core';
import { AbilityServiceSignal } from '@casl/angular';
import type { AppAbility } from './AppAbility';
@Component({
selector: 'post-action',
template: `
@if (whyCannotPerformAction(); as forbidden) {
<p>{{ forbidden.reason || 'This action is forbidden' }}</p>
} @else {
<button>Perform action</button>
}
`
})
export class PostActionComponent {
private readonly abilityService = inject<AbilityServiceSignal<AppAbility>>(AbilityServiceSignal);
readonly action = input.required<'create' | 'delete'>();
protected readonly whyCannotPerformAction = this.abilityService.deferWhyCannot(this.action, 'Post');
}
例如,由父母提供动作 <post-action [action]="'delete'" />。当输入更改时,权限信号更新.
传递信号本身( P)this.action跟踪其变化。 传递其当前值( E)this.action()将这一参数固定在创建延迟检查时的数值上。 这个 deferWhy* 方法保存 null 和缺失的理由行为 why* 方法; 使用 deferCan 或者说 deferCannot 您只需检查布尔权限即可.
使用管道检查模板中的权限( 已过期)
检查您可以使用的任何模板的权限 AblePipe数字 :
@if ('create' | able: 'Post') {
<a (click)="createPost()">Add Post</a>
}
类型脚本支持
这个软件包是用 TypeScript 写的, 这样可以警告您使用错误 .
在Angular app中使用应用程序特定能力可能有点乏味,因为你到处注射 Ability 您需要导入其通用参数:
import { Ability } from '@casl/ability';
import { Component } from '@angular/core';
import { AppAbilities } from '../services/AppAbility';
@Component({
selector: 'todo-item'
})
export class TodoItem {
constructor(
private ability: Ability<AppAbilities>
) {}
}
为了让生活变得容易,你可以使用 AbilityClass<TAbility> 类以使用伴星对象模式:
import { Ability, AbilityClass } from '@casl/ability';
type Actions = 'create' | 'read' | 'update' | 'delete';
type Subjects = 'Article' | 'User';
export type AppAbility = MongoAbility<[Actions, Subjects]>;
export const AppAbility = Ability as AbilityClass<AppAbility>;
使用 AppAbility 在你的应用程序中 :
import { NgModule } from '@angular/core';
import { AppAbility } from './services/AppAbility';
@NgModule({
// other configuration
providers: [
{ provide: AppAbility, useValue: createMongoAbility() },
]
})
export class AppModule {}
想帮忙吗?
想要提交错误, 提供一些代码, 还是改进文档 ? 不错! 阅读指南 捐款。 。 。 .
如果你想帮助我们 维持我们的社区和项目,考虑 成为开放集体的出资人
见 支助CASL 详情