Files
edr-platform/apps/edr-passenger-api/src/common/interceptors/session-activity.interceptor.ts

47 lines
1.7 KiB
TypeScript

import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { InjectDataSource } from '@nestjs/typeorm';
import { DataSource } from 'typeorm';
import { ConfigService } from '@nestjs/config';
@Injectable()
export class SessionActivityInterceptor implements NestInterceptor {
private readonly inactivityMinutes: number;
constructor(
@InjectDataSource() private readonly dataSource: DataSource,
private readonly config: ConfigService,
) {
this.inactivityMinutes = parseInt(this.config.get<string>('SESSION_INACTIVITY_MINUTES') || '30', 10);
}
async intercept(context: ExecutionContext, next: CallHandler): Promise<Observable<any>> {
const request = context.switchToHttp().getRequest();
const response = context.switchToHttp().getResponse();
const sessionId: string | undefined = request.user?.sessionId;
if (sessionId) {
const rows = await this.dataSource.query<Array<{ expiry_time: Date }>>(
`SELECT expiry_time FROM iam.sessions WHERE id = $1 AND status = 'ACTIVE' LIMIT 1`,
[sessionId],
);
if (rows.length) {
const minutesLeft = (rows[0].expiry_time.getTime() - Date.now()) / 60000;
if (minutesLeft < this.inactivityMinutes * 0.2) {
response.setHeader('X-Session-Expiry-Warning', Math.floor(minutesLeft).toString());
}
// Extend session on every authenticated request
await this.dataSource.query(
`UPDATE iam.sessions SET expiry_time = NOW() + ($1 * INTERVAL '1 minute') WHERE id = $2 AND status = 'ACTIVE'`,
[this.inactivityMinutes, sessionId],
);
}
}
return next.handle().pipe(tap(() => {}));
}
}