82 lines
2.1 KiB
TypeScript
82 lines
2.1 KiB
TypeScript
import { Injectable } from '@nestjs/common';
|
|
|
|
import { isPrismaErrorCode, PrismaErrorCode } from '#src/prisma/prisma-error-code';
|
|
import { PrismaService } from '#src/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)
|
|
);
|
|
}
|