chore: strengthen backend eslint profile

This commit is contained in:
2026-09-28 11:04:18 +03:00
parent ca5dbcb382
commit 9b3558f96c
179 changed files with 4485 additions and 2716 deletions
+21 -12
View File
@@ -6,6 +6,7 @@ import {
import { JwtService } from '@nestjs/jwt';
import * as bcrypt from 'bcrypt';
import { createHash, randomUUID } from 'crypto';
import { Session, User } from '../../../../generated/prisma/client';
import { PrismaService } from '../../../prisma/prisma.service';
import { AuthUser, RefreshPayload } from './auth.types';
@@ -16,6 +17,7 @@ const REFRESH_TTL_MS = 604_800_000;
const ACCESS_TTL = '15m';
const REFRESH_TTL = '7d';
const DUMMY_PASSWORD_HASH =
// eslint-disable-next-line sonarjs/no-hardcoded-passwords -- Public dummy bcrypt hash preserves login timing for nonexistent users; it is not a credential.
'$2b$12$Z49BwJsyiUqY0ZozFzt9IeYvjhV4kbeLw9KdxOguT5bfhA1RvPCx6';
@Injectable()
@@ -28,12 +30,13 @@ export class AuthService {
async register(
email: string,
password: string,
): Promise<{ user: AuthUser; accessToken: string; refreshToken: string }> {
): Promise<{ accessToken: string; refreshToken: string; user: AuthUser }> {
const existing = await this.prisma.user.findUnique({
where: { email },
});
if (existing)
if (existing) {
throw new ConflictException({ code: 'EMAIL_ALREADY_REGISTERED' });
}
let user: User;
try {
@@ -45,8 +48,9 @@ export class AuthService {
},
});
} catch (error) {
if (isUniqueConstraintError(error))
if (isUniqueConstraintError(error)) {
throw new ConflictException({ code: 'EMAIL_ALREADY_REGISTERED' });
}
throw error;
}
return this.createSession(user);
@@ -55,7 +59,7 @@ export class AuthService {
async login(
email: string,
password: string,
): Promise<{ user: AuthUser; accessToken: string; refreshToken: string }> {
): Promise<{ accessToken: string; refreshToken: string; user: AuthUser }> {
const user = await this.prisma.user.findUnique({
where: { email },
});
@@ -63,14 +67,15 @@ export class AuthService {
password,
user?.passwordHash ?? DUMMY_PASSWORD_HASH,
);
if (!user || !valid)
if (!user || !valid) {
throw new UnauthorizedException({ code: 'INVALID_CREDENTIALS' });
}
return this.createSession(user);
}
async refresh(
token: string,
): Promise<{ user: AuthUser; accessToken: string; refreshToken: string }> {
): Promise<{ accessToken: string; refreshToken: string; user: AuthUser }> {
let payload: RefreshPayload;
try {
payload = await this.jwt.verifyAsync<RefreshPayload>(token, {
@@ -79,8 +84,9 @@ export class AuthService {
} catch {
throw new UnauthorizedException({ code: 'UNAUTHORIZED' });
}
if (payload.type !== 'refresh')
if (payload.type !== 'refresh') {
throw new UnauthorizedException({ code: 'UNAUTHORIZED' });
}
const session = await this.prisma.session.findUnique({
where: { id: payload.sid },
include: { user: true },
@@ -91,12 +97,14 @@ export class AuthService {
session.revokedAt ||
session.expiresAt <= new Date()
) {
if (session && !session.revokedAt)
if (session && !session.revokedAt) {
await this.prisma.session.delete({ where: { id: session.id } });
}
throw new UnauthorizedException({ code: 'UNAUTHORIZED' });
}
if (session.refreshTokenHash !== this.hash(token))
if (session.refreshTokenHash !== this.hash(token)) {
throw new UnauthorizedException({ code: 'UNAUTHORIZED' });
}
return this.rotateSession(session, session.refreshTokenHash);
}
@@ -138,7 +146,7 @@ export class AuthService {
private async createSession(
user: User,
): Promise<{ user: AuthUser; accessToken: string; refreshToken: string }> {
): Promise<{ accessToken: string; refreshToken: string; user: AuthUser }> {
const session = await this.prisma.session.create({
data: {
id: randomUUID(),
@@ -153,7 +161,7 @@ export class AuthService {
private async rotateSession(
session: Session & { user: User },
expectedRefreshTokenHash?: string,
): Promise<{ user: AuthUser; accessToken: string; refreshToken: string }> {
): Promise<{ accessToken: string; refreshToken: string; user: AuthUser }> {
const refreshToken = await this.jwt.signAsync(
{
sub: session.userId,
@@ -172,8 +180,9 @@ export class AuthService {
where: { id: session.id, refreshTokenHash: expectedRefreshTokenHash },
data,
});
if (updated.count !== 1)
if (updated.count !== 1) {
throw new UnauthorizedException({ code: 'UNAUTHORIZED' });
}
} else {
await this.prisma.session.update({ where: { id: session.id }, data });
}