Files
portalweb-api/src/auth/strategies/jwt-strategy.ts

93 lines
3.0 KiB
TypeScript

import { Inject, Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { ConfigService } from '@nestjs/config';
import { JwtPayload } from '../models/jwt-payload.model';
import { UserRepository } from '../../auth/users/UserRepository';
import { RedisClientToken } from '../../core/configs/cache/redis-client.adapter.provider';
import { IRedisClient } from '../../core/configs/cache/IRedisClient';
import { TokenBlacklistService } from '../services/token-blacklist.service';
import { SessionManagementService } from '../services/session-management.service';
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(
@Inject(RedisClientToken) private readonly redis: IRedisClient,
private readonly userRepository: UserRepository,
private readonly configService: ConfigService,
private readonly tokenBlacklistService: TokenBlacklistService,
private readonly sessionManagementService: SessionManagementService,
) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: configService.get<string>('jwtSecret'),
});
}
async validate(payload: JwtPayload, req: any) {
if (!payload?.id || !payload?.sessionId) {
throw new UnauthorizedException('Payload inválido ou incompleto');
}
const token = req.headers?.authorization?.replace('Bearer ', '');
if (token && (await this.tokenBlacklistService.isBlacklisted(token))) {
throw new UnauthorizedException('Token foi invalidado');
}
const sessionKey = this.buildSessionKey(payload.id, payload.sessionId);
const cachedUser = await this.redis.get<any>(sessionKey);
if (cachedUser) {
const isSessionActive =
await this.sessionManagementService.isSessionActive(
payload.id,
payload.sessionId,
);
if (!isSessionActive) {
throw new UnauthorizedException('Sessão expirada ou inválida');
}
return {
id: cachedUser.id,
sellerId: cachedUser.sellerId,
storeId: cachedUser.storeId,
username: cachedUser.username,
email: cachedUser.email,
name: cachedUser.name,
sessionId: payload.sessionId,
};
}
const user = await this.userRepository.findById(payload.id);
if (!user || user.situacao === 'I' || user.dataDesligamento) {
throw new UnauthorizedException('Usuário inválido ou inativo');
}
if (user.situacao === 'B') {
throw new UnauthorizedException(
'Usuário bloqueado, acesso não permitido',
);
}
const userData = {
id: user.id,
sellerId: user.sellerId,
storeId: user.storeId,
username: user.name,
email: user.email,
name: user.name,
sessionId: payload.sessionId,
};
await this.redis.set(sessionKey, userData, 60 * 60 * 8);
return userData;
}
private buildSessionKey(userId: number, sessionId: string): string {
return `auth:sessions:${userId}:${sessionId}`;
}
}