Assist_Design/apps/bff/src/auth/services/token-blacklist.service.ts
tema 5f7fb483d7 Refactor error handling and type safety across services
- Simplified error handling in TokenBlacklistService by removing unnecessary error variable.
- Enhanced type safety in SimUsageStoreService with improved type assertions and error handling.
- Updated FreebititService to provide clearer error messages and consistent error handling across multiple methods.
- Standardized import statements in WhmcsInvoiceService for better organization and clarity.
- Added missing imports in dev-prep script to ensure proper functionality.
2025-09-09 16:07:48 +09:00

75 lines
2.4 KiB
TypeScript

import { Injectable, Inject } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { Redis } from "ioredis";
import { Logger } from "nestjs-pino";
@Injectable()
export class TokenBlacklistService {
constructor(
@Inject("REDIS_CLIENT") private readonly redis: Redis,
private readonly configService: ConfigService,
@Inject(Logger) private readonly logger: Logger
) {}
async blacklistToken(token: string, _expiresIn?: number): Promise<void> {
// Extract JWT payload to get expiry time
try {
const payload = JSON.parse(Buffer.from(token.split(".")[1] ?? "", "base64").toString()) as {
exp?: number;
};
const expiryTime = (payload.exp ?? 0) * 1000; // Convert to milliseconds
const currentTime = Date.now();
const ttl = Math.max(0, Math.floor((expiryTime - currentTime) / 1000)); // Convert to seconds
if (ttl > 0) {
await this.redis.setex(`blacklist:${token}`, ttl, "1");
}
} catch {
// If we can't parse the token, blacklist it for the default JWT expiry time
try {
const defaultTtl = this.parseJwtExpiry(this.configService.get("JWT_EXPIRES_IN", "7d"));
await this.redis.setex(`blacklist:${token}`, defaultTtl, "1");
} catch (err) {
this.logger.warn(
"Failed to write token to Redis blacklist; proceeding without persistence",
{
error: err instanceof Error ? err.message : String(err),
}
);
}
}
}
async isTokenBlacklisted(token: string): Promise<boolean> {
try {
const result = await this.redis.get(`blacklist:${token}`);
return result !== null;
} catch (err) {
// If Redis is unavailable, treat as not blacklisted to avoid blocking auth
this.logger.warn("Redis unavailable during blacklist check; allowing request", {
error: err instanceof Error ? err.message : String(err),
});
return false;
}
}
private parseJwtExpiry(expiresIn: string): number {
// Convert JWT expiry string to seconds
const unit = expiresIn.slice(-1);
const value = parseInt(expiresIn.slice(0, -1), 10);
switch (unit) {
case "s":
return value;
case "m":
return value * 60;
case "h":
return value * 60 * 60;
case "d":
return value * 24 * 60 * 60;
default:
return 7 * 24 * 60 * 60; // Default 7 days in seconds
}
}
}