目录
扩展
warning
本章仅适用于代码优先方法。
Extensions 是一种高级的低级特性,允许您在 类型配置中定义任意数据。 附加自定义元数据到某些字段允许您创建更复杂、通用的解决方案。 例如,使用扩展,您可以定义访问特定字段所需的字段级角色。 这些角色可以在运行时反映,以确定调用者是否具有检索特定字段的足够权限。
添加自定义元数据
要为字段附加自定义元数据,请使用 @nestjs/graphql
包中导出的 @Extensions()
装饰器。
@Field()
@Extensions({ role: Role.ADMIN })
password: string;
在上面的示例中,我们将 role
元数据属性分配为 Role.ADMIN
的值。
Role
是一个简单的 TypeScript 枚举,将我们系统中所有可用的用户角色分组在一起。
请注意,除了在字段上设置元数据之外,
还可以在类级别和方法级别(例如,在查询处理程序上)使用 @Extensions()
装饰器。
使用 自定义元数据
利用自定义元数据的逻辑可以尽可能复杂。 例如,您可以创建一个简单的拦截器,它会存储/记录每个方法调用的事件, 或者一个字段中间件, 它将检索字段所需的角色与调用者权限进行匹配(字段级权限系统)。
出于说明目的,让我们定义一个 checkRoleMiddleware
,
它比较用户角色(在此硬编码)与访问目标字段所需的角色:
export const checkRoleMiddleware: FieldMiddleware = async (
ctx: MiddlewareContext,
next: NextFn,
) => {
const { info } = ctx;
const { extensions } = info.parentType.getFields()[info.fieldName];
/**
* 在实际应用程序中,"userRole" 变量
* 应该代表调用者(用户)的角色(例如,"ctx.user.role")。
*/
const userRole = Role.USER;
if (userRole === extensions.role) {
// 或者只需返回 null 以忽略
throw new ForbiddenException(
`User does not have sufficient permissions to access "${info.fieldName}" field.`,
);
}
return next();
};
有了这个,我们可以为 password
字段注册一个中间件,如下所示:
@Field({ middleware: [checkRoleMiddleware] })
@Extensions({ role: Role.ADMIN })
password: string;