refactor: move auth persistence into repository (WealthLedger/backend#171)

This commit is contained in:
2026-11-04 22:29:01 +03:00
parent cea77f6d56
commit 61c55256e7
4 changed files with 105 additions and 67 deletions
@@ -0,0 +1,81 @@
import { Injectable } from '@nestjs/common';
import { isPrismaErrorCode, PrismaErrorCode } from '../../../prisma/prisma-error-code';
import { PrismaService } from '../../../prisma/prisma.service';
const EXPECTED_ROTATED_SESSIONS = 1;
@Injectable()
export class AuthRepository {
constructor(private readonly prisma: PrismaService) {}
findUserByEmail(email: string) {
return this.prisma.user.findUnique({ where: { email } });
}
async createUser(data: { email: string; id: string; passwordHash: string }) {
try {
return await this.prisma.user.create({ data });
} catch (error) {
if (isUniqueConstraintError(error)) return null;
throw error;
}
}
findUserById(id: string) {
return this.prisma.user.findUnique({ where: { id } });
}
findSessionWithUser(id: string) {
return this.prisma.session.findUnique({
where: { id },
include: { user: true },
});
}
findSession(id: string) {
return this.prisma.session.findUnique({ where: { id } });
}
deleteSession(id: string) {
return this.prisma.session.delete({ where: { id } });
}
revokeSession(id: string) {
return this.prisma.session.update({
where: { id },
data: { revokedAt: new Date() },
});
}
createSession(userId: string, id: string) {
return this.prisma.session.create({
data: { id, userId, refreshTokenHash: '', expiresAt: new Date() },
});
}
async rotateSession(
id: string,
data: { expiresAt: Date; refreshTokenHash: string },
expectedRefreshTokenHash?: string,
): Promise<boolean> {
if (expectedRefreshTokenHash) {
const updated = await this.prisma.session.updateMany({
where: { id, refreshTokenHash: expectedRefreshTokenHash },
data,
});
return updated.count === EXPECTED_ROTATED_SESSIONS;
}
await this.prisma.session.update({ where: { id }, data });
return true;
}
}
function isUniqueConstraintError(error: unknown): boolean {
return (
typeof error === 'object' &&
error !== null &&
'code' in error &&
isPrismaErrorCode(error.code, PrismaErrorCode.UniqueConstraint)
);
}