Files
Edu/services/iam/src/graphql/resolvers/user.resolver.ts
SpecialX 6bed673d9f 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
2026-07-14 23:48:16 +08:00

70 lines
1.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* iam User Resolverv2.1 M1
*
* Apollo Federation 子图User Entity
* - @key(fields: "userId") 支持跨子图引用
* - @ResolveReference 使用 DataLoader 批量加载ADR-035
* - Query 入口供 Apollo Router 直接查询
*/
import {
Resolver,
Query,
Args,
ID,
ResolveReference,
ObjectType,
Field,
Directive,
} from "@nestjs/graphql";
import { DataLoaderService, type UserEntity } from "../dataloader.service.js";
/**
* User ObjectTypeFederation @key
* 对应 iam.users 表
*/
@ObjectType()
@Directive(`@key(fields: "userId")`)
export class User {
@Field(() => ID)
userId!: string;
@Field()
email!: string;
@Field()
name!: string;
@Field()
status!: string;
@Field()
dataScope!: string;
}
@Resolver(() => User)
export class UserResolver {
constructor(private readonly loader: DataLoaderService) {}
/**
* Federation Reference Resolver
*
* 当其他子图通过 @key 引用 User 时Router 调用此方法解析。
* 使用 DataLoader 批量加载,消除 N+1 查询ADR-035
*/
@ResolveReference()
async resolveReference(ref: { userId: string }): Promise<UserEntity | null> {
return this.loader.userLoader.load(ref.userId);
}
/**
* Query: user(userId) → User
* 通过 Apollo Router 访问,直连被 RouterAuthGuard 拒绝ADR-036
*/
@Query(() => User, { nullable: true })
async user(
@Args("userId", { type: () => ID }) userId: string,
): Promise<UserEntity | null> {
return this.loader.userLoader.load(userId);
}
}