feat: harden sessions and track downstream acknowledgements

This commit is contained in:
hectorzhao
2026-07-14 14:18:43 +08:00
parent 3d37adcc9f
commit 8c03663f24
43 changed files with 1733 additions and 150 deletions
+15 -3
View File
@@ -1,6 +1,7 @@
import { randomUUID } from 'node:crypto';
import { BadRequestException, Injectable, UnauthorizedException } from '@nestjs/common';
import { hashPassword, UsersService } from '../users/users.service';
import { SessionService } from './session.service';
export interface LoginDto {
login: string;
@@ -21,7 +22,7 @@ const anonymousFailures = new Map<string, { count: number; lockedUntil?: number
@Injectable()
export class AuthService {
constructor(private readonly users: UsersService) {}
constructor(private readonly users: UsersService, private readonly sessions: SessionService) {}
createCaptcha() {
const left = Math.floor(10 + Math.random() * 40);
@@ -76,9 +77,9 @@ export class AuthService {
await this.users.recordLoginSuccess(user.id);
anonymousFailures.delete(login);
const { token, record } = await this.sessions.create(user.id, portal, user.sessionVersion ?? 0);
return {
accessToken: `dev-token:${user.id}:${user.sessionVersion ?? 0}`,
tokenType: 'Bearer',
sessionToken: token,
portal,
user: {
id: user.id,
@@ -90,9 +91,20 @@ export class AuthService {
displayName: user.displayName,
roles: roleCodes,
},
...this.sessions.publicSession(record),
};
}
async unlock(token: string, userId: string, password: string) {
await this.users.verifyCurrentPassword(userId, password);
return this.sessions.unlock(token);
}
async reauthenticate(token: string, userId: string, password: string) {
await this.users.verifyCurrentPassword(userId, password);
return this.sessions.markReauthenticated(token);
}
private verifyCaptcha(captchaId?: string, captchaText?: string) {
const record = captchaId ? captchaStore.get(captchaId) : undefined;
captchaStore.delete(captchaId ?? '');