feat(center): POST /auth/resolve-names
Resolve display names/emails to userIds within a guild node's active members (api-key auth). Used by guild for <@user.name:NAME> translation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -67,4 +67,12 @@ export class AuthController {
|
|||||||
introspect(@Body() body: { token?: string; guildNodeId?: string }) {
|
introspect(@Body() body: { token?: string; guildNodeId?: string }) {
|
||||||
return this.authService.introspectGuildToken(body?.token ?? '', body?.guildNodeId ?? '');
|
return this.authService.introspectGuildToken(body?.token ?? '', body?.guildNodeId ?? '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Post('resolve-names')
|
||||||
|
resolveNames(@Body() body: { guildNodeId?: string; names?: string[] }) {
|
||||||
|
return this.authService.resolveNames(
|
||||||
|
String(body?.guildNodeId ?? ''),
|
||||||
|
Array.isArray(body?.names) ? body.names : [],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -240,6 +240,33 @@ export class AuthService {
|
|||||||
.filter((x) => !!x.email);
|
.filter((x) => !!x.email);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve display names (or emails) to userIds, scoped to a guild node's
|
||||||
|
// active members. Called by guild nodes (api-key auth). Unresolved names
|
||||||
|
// are omitted from the result.
|
||||||
|
async resolveNames(
|
||||||
|
guildNodeId: string,
|
||||||
|
names: string[],
|
||||||
|
): Promise<{ resolved: Record<string, string> }> {
|
||||||
|
const wanted = [...new Set(names.map((n) => String(n ?? '').trim()).filter(Boolean))];
|
||||||
|
if (!guildNodeId || !wanted.length) return { resolved: {} };
|
||||||
|
|
||||||
|
const members = await this.guildUserRepo.find({ where: { guildNodeId, status: 'active' } });
|
||||||
|
const userIds = [...new Set(members.map((m) => m.userId))];
|
||||||
|
if (!userIds.length) return { resolved: {} };
|
||||||
|
|
||||||
|
const users = await this.userRepo
|
||||||
|
.createQueryBuilder('u')
|
||||||
|
.where('u.id IN (:...userIds)', { userIds })
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
const resolved: Record<string, string> = {};
|
||||||
|
for (const name of wanted) {
|
||||||
|
const hit = users.find((u) => u.name === name) ?? users.find((u) => u.email === name);
|
||||||
|
if (hit) resolved[name] = hit.id;
|
||||||
|
}
|
||||||
|
return { resolved };
|
||||||
|
}
|
||||||
|
|
||||||
verifyCenterAccessToken(accessToken: string): jwt.JwtPayload {
|
verifyCenterAccessToken(accessToken: string): jwt.JwtPayload {
|
||||||
try {
|
try {
|
||||||
const payload = jwt.verify(accessToken, process.env.FABRIC_BACKEND_CENTER_JWT_ACCESS_SECRET as string) as jwt.JwtPayload;
|
const payload = jwt.verify(accessToken, process.env.FABRIC_BACKEND_CENTER_JWT_ACCESS_SECRET as string) as jwt.JwtPayload;
|
||||||
|
|||||||
Reference in New Issue
Block a user