79 lines
2.2 KiB
TypeScript
79 lines
2.2 KiB
TypeScript
import { Injectable } from '@nestjs/common';
|
|
import { InjectRepository } from '@nestjs/typeorm';
|
|
import { IsNull, LessThan, Repository } from 'typeorm';
|
|
import { SessionEntity } from '../entities/session.entity';
|
|
|
|
@Injectable()
|
|
export class SessionsRepository {
|
|
constructor(
|
|
@InjectRepository(SessionEntity)
|
|
private readonly repo: Repository<SessionEntity>,
|
|
) {}
|
|
|
|
findActiveById(id: string): Promise<SessionEntity | null> {
|
|
return this.repo.findOne({
|
|
where: { id, revokedAt: IsNull() },
|
|
relations: { user: { roles: { permissions: true }, settings: true } },
|
|
});
|
|
}
|
|
|
|
listForUser(userId: string): Promise<SessionEntity[]> {
|
|
return this.repo.find({ where: { userId }, order: { createdAt: 'DESC' } });
|
|
}
|
|
|
|
listActiveForUser(userId: string): Promise<SessionEntity[]> {
|
|
return this.repo.find({
|
|
where: { userId, revokedAt: IsNull() },
|
|
order: { lastActivityAt: 'DESC' },
|
|
});
|
|
}
|
|
|
|
countActiveForUser(userId: string): Promise<number> {
|
|
return this.repo.count({ where: { userId, revokedAt: IsNull() } });
|
|
}
|
|
|
|
save(session: SessionEntity): Promise<SessionEntity> {
|
|
return this.repo.save(session);
|
|
}
|
|
|
|
async revoke(sessionId: string): Promise<number> {
|
|
const result = await this.repo.update(
|
|
{ id: sessionId, revokedAt: IsNull() },
|
|
{ revokedAt: new Date() },
|
|
);
|
|
return result.affected ?? 0;
|
|
}
|
|
|
|
async revokeForUser(userId: string, sessionId: string): Promise<number> {
|
|
const result = await this.repo.update(
|
|
{ id: sessionId, userId, revokedAt: IsNull() },
|
|
{ revokedAt: new Date() },
|
|
);
|
|
return result.affected ?? 0;
|
|
}
|
|
|
|
async revokeAllForUser(
|
|
userId: string,
|
|
exceptSessionId?: string,
|
|
): Promise<number> {
|
|
const sessions = await this.repo.find({
|
|
where: { userId, revokedAt: IsNull() },
|
|
});
|
|
const now = new Date();
|
|
const targets = sessions.filter(
|
|
(session) => session.id !== exceptSessionId,
|
|
);
|
|
await this.repo.save(
|
|
targets.map((session) => ({ ...session, revokedAt: now })),
|
|
);
|
|
return targets.length;
|
|
}
|
|
|
|
async cleanupExpired(now = new Date()): Promise<void> {
|
|
await this.repo.delete([
|
|
{ expiresAt: LessThan(now) },
|
|
{ absoluteExpiresAt: LessThan(now) },
|
|
]);
|
|
}
|
|
}
|