71 lines
1.9 KiB
TypeScript
71 lines
1.9 KiB
TypeScript
import { Injectable } from '@nestjs/common';
|
|
import { PrismaService } from '../../prisma/prisma.service';
|
|
|
|
export interface CurrentUser {
|
|
id: string;
|
|
name?: string;
|
|
username?: string;
|
|
roleId: string;
|
|
email?: string;
|
|
}
|
|
|
|
export interface AuthenticatedRequest {
|
|
headers?: Record<string, string | string[] | undefined>;
|
|
currentUser?: CurrentUser | null;
|
|
}
|
|
|
|
@Injectable()
|
|
export class AuthContextService {
|
|
constructor(private readonly prisma: PrismaService) {}
|
|
|
|
async resolveCurrentUser(request: AuthenticatedRequest): Promise<CurrentUser | null> {
|
|
if (request.currentUser !== undefined) return request.currentUser;
|
|
|
|
const userId = headerValue(request, 'x-ftb-user-id') || headerValue(request, 'x-user-id');
|
|
if (!userId) {
|
|
request.currentUser = null;
|
|
return null;
|
|
}
|
|
|
|
const headerUser: CurrentUser = {
|
|
id: userId,
|
|
name: decodeHeader(headerValue(request, 'x-ftb-user-name')),
|
|
username: headerValue(request, 'x-ftb-user-username'),
|
|
roleId: headerValue(request, 'x-ftb-user-role-id') || '',
|
|
email: headerValue(request, 'x-ftb-user-email'),
|
|
};
|
|
|
|
if (headerUser.roleId) {
|
|
request.currentUser = headerUser;
|
|
return headerUser;
|
|
}
|
|
|
|
const row = await this.prisma.user.findUnique({
|
|
where: { id: userId },
|
|
select: { id: true, name: true, username: true, roleId: true, email: true },
|
|
});
|
|
request.currentUser = row ? {
|
|
id: row.id,
|
|
name: row.name,
|
|
username: row.username ?? undefined,
|
|
roleId: row.roleId || 'member',
|
|
email: row.email,
|
|
} : null;
|
|
return request.currentUser;
|
|
}
|
|
}
|
|
|
|
function headerValue(request: AuthenticatedRequest, name: string): string {
|
|
const value = request.headers?.[name] ?? request.headers?.[name.toLowerCase()];
|
|
if (Array.isArray(value)) return value[0] ?? '';
|
|
return value ?? '';
|
|
}
|
|
|
|
function decodeHeader(value: string): string {
|
|
try {
|
|
return decodeURIComponent(value);
|
|
} catch {
|
|
return value;
|
|
}
|
|
}
|