gpt4 book ai didi

javascript - NestJs 基于用户属性和策略的 CASL 授权守卫

转载 作者:行者123 更新时间:2023-12-04 15:11:41 42 4
gpt4 key购买 nike

我正在尝试在 NestJS 和 CASL 中为列表/获取端点实现一个基于通用策略的防护。
我正在关注这里的文档 https://docs.nestjs.com/security/authorization#integrating-casl .
一个用户可以是多个组的一部分。我需要检查 ArticleBooks拥有 groupId 的实体匹配任何用户组。并且仅当用户的组列表匹配 Article.id 时才允许用户阅读它们和 Books.id但是我无法得到它似乎正在工作

// User Object - from request.user after decoded from AuthGuard('jwt')

user = {
groups: ['department-1', 'department-2']

}
// Article Entity
export class Article extends UUIDBase {
@Column({ nullable: false })
groupId: string

@Column({ nullable: true })
description: string

@Column({ nullable: true })
name: string
}
// Books Entity
export class Books extends UUIDBase {
@Column({ nullable: false })
groupId: string

@Column({ nullable: true })
description: string

@Column({ nullable: true })
name: string

@Column({ nullable: true })
description: string
}
// CASL-ability.factory.ts
type Subjects = typeof Articles | typeof User | Articles | User | 'all'

export type AppAbility = Ability<[Action, Subjects]>

@Injectable()
export class CaslAbilityFactory {
createForUser(user: any) {
const { can, build } = new AbilityBuilder<Ability<[Action, Subjects]>>(
Ability as AbilityClass<AppAbility>,
)

console.log('USER IS ADMIN', user.groups)
if (user.groups.includes(Groups.ADMIN)) {
can(Action.Manage, 'all') // read-write access to everything
} else {
can(Action.Read, 'all') // read-only access to everything
}

return build()
}
}
// @CheckPolicies decorator
interface IPolicyHandler {
handle(ability: AppAbility): boolean
}

type PolicyHandlerCallback = (ability: AppAbility, can?, user?) => boolean

export declare type PolicyHandler = IPolicyHandler | PolicyHandlerCallback

import { SetMetadata } from '@nestjs/common'

export const CHECK_POLICIES_KEY = 'check_policy'
export const CheckPolicies: any = (...handlers: PolicyHandler[]) =>
SetMetadata(CHECK_POLICIES_KEY, handlers)
// PoliciesGuard.ts

@Injectable()
export class PoliciesGuard implements CanActivate {
constructor(
private reflector: Reflector,
private caslAbilityFactory: CaslAbilityFactory,
) {}

async canActivate(context: ExecutionContext): Promise<boolean> {
const policyHandlers =
this.reflector.get<PolicyHandler[]>(
CHECK_POLICIES_KEY,
context.getHandler(),
) || []

const { user } = context.switchToHttp().getRequest()
const ability = this.caslAbilityFactory.createForUser(user)

return policyHandlers.every(handler =>
this.execPolicyHandler(handler, ability),
)
}

private execPolicyHandler(handler: PolicyHandler, ability: AppAbility) {
if (typeof handler === 'function') {
return handler(ability)
}
return handler.handle(ability)
}
}
我在文章 Controller 中像这样使用它
@ApiTags('Articles')
@Controller('Articles')
@UseGuards(AuthGuard('jwt'))
export class ArticlesController {
constructor(public service: ArticlesService) {}
@Get('/articles/:id')
@UseGuards(PoliciesGuard)
@CheckPolicies((ability: AppAbility) => {
ability.can(Action.Read, Articles)
})
async listArticles(@Query() query, @Param() param) {
return this.service.listArticles(query, param)
}

@Get('/articles/:id')
@UseGuards(PoliciesGuard)
@CheckPolicies((ability: AppAbility) => {
ability.can(Action.Read, Articles)
})
async getArticle(@Param() params, @Query() query) {
return this.service.getArticle(params, query)
}

我在 Books Controller 中像这样使用它
@ApiTags('Books')
@Controller('Books')
@UseGuards(AuthGuard('jwt'))
export class BooksController {
constructor(public service: BooksService) {}
@Get('/books/:id')
@UseGuards(PoliciesGuard)
@CheckPolicies((ability: AppAbility) => {
ability.can(Action.Read, Books)
})
async listBooks(@Query() query, @Param() param, @Body() body) {
return this.service.listBooks(query, param, body)
}

@Get('/books/:id')
@UseGuards(PoliciesGuard)
@CheckPolicies((ability: AppAbility) => {
ability.can(Action.Read, Books)
})
async getBooks(@Param() params, @Query() query) {
return this.service.getBooks(params, query)
}

最佳答案

尝试改变@CheckPolicies((ability: AppAbility) => {ability.can(Action.Read, Books)})通过在 ability.can... 之前添加返回或删除括号。
有了你所拥有的,该策略处理程序总是返回 undefined ,所以它总是给你一个 Unauthorized .

关于javascript - NestJs 基于用户属性和策略的 CASL 授权守卫,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65125367/

42 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com