feat(iam): graphql subgraph with dataloader and router auth guard
- GraphQLModule: Apollo Federation 2 subgraph at /graphql - UserResolver/RoleResolver: @key with @ResolveReference using DataLoader (ADR-035) - DataScopeResolver: ScopeToken for visible class/student IDs (ADR-041) - RouterAuthGuard: validate Router-Authorization header (ADR-036) - DataLoaderService: REQUEST-scoped userLoader + roleLoader - IamRepository.batchFindRoles: batch query for DataLoader - IamService.getVisibleClassIds/getVisibleStudentIds: dataScope calculation - app.module.ts: register PermissionGuard + RouterAuthGuard as APP_GUARD
This commit is contained in:
54
services/iam/src/graphql/resolvers/role.resolver.ts
Normal file
54
services/iam/src/graphql/resolvers/role.resolver.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* iam Role Resolver(v2.1 M1)
|
||||
*
|
||||
* Apollo Federation 子图:Role Entity
|
||||
* - @key(fields: "roleId") 支持跨子图引用
|
||||
* - @ResolveReference 使用 DataLoader 批量加载(ADR-035)
|
||||
*/
|
||||
import {
|
||||
Resolver,
|
||||
Query,
|
||||
Args,
|
||||
ID,
|
||||
ResolveReference,
|
||||
ObjectType,
|
||||
Field,
|
||||
Directive,
|
||||
} from "@nestjs/graphql";
|
||||
import { DataLoaderService, type RoleEntity } from "../dataloader.service.js";
|
||||
|
||||
@ObjectType()
|
||||
@Directive(`@key(fields: "roleId")`)
|
||||
export class Role {
|
||||
@Field(() => ID)
|
||||
roleId!: string;
|
||||
|
||||
@Field()
|
||||
name!: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
description: string | null = null;
|
||||
|
||||
@Field()
|
||||
roleType!: string;
|
||||
|
||||
@Field()
|
||||
level!: number;
|
||||
}
|
||||
|
||||
@Resolver(() => Role)
|
||||
export class RoleResolver {
|
||||
constructor(private readonly loader: DataLoaderService) {}
|
||||
|
||||
@ResolveReference()
|
||||
async resolveReference(ref: { roleId: string }): Promise<RoleEntity | null> {
|
||||
return this.loader.roleLoader.load(ref.roleId);
|
||||
}
|
||||
|
||||
@Query(() => Role, { nullable: true })
|
||||
async role(
|
||||
@Args("roleId", { type: () => ID }) roleId: string,
|
||||
): Promise<RoleEntity | null> {
|
||||
return this.loader.roleLoader.load(roleId);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user