Files
formularios_api/src/qr/qr-token.service.ts
T
evenegas 12080aa83e qr
2025-10-06 13:49:22 -06:00

136 lines
4.1 KiB
TypeScript

import { Injectable, UnauthorizedException } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { ConfigService } from '@nestjs/config';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Asistencia } from 'src/asistencia/entities/asistencia.entity';
import { Cuestionario } from 'src/cuestionario/entities/cuestionario.entity';
import { Evento } from 'src/evento/entities/evento.entity';
@Injectable()
export class QrTokenService {
constructor(
private jwtService: JwtService,
private configService: ConfigService,
@InjectRepository(Asistencia)
private readonly asistenciaRepository: Repository<Asistencia>,
@InjectRepository(Cuestionario)
private readonly cuestionarioRepository: Repository<Cuestionario>,
@InjectRepository(Evento)
private readonly eventoREpo: Repository<Evento>,
) {}
/**
* Genera un token JWT específico para el QR de asistencia
* @param id_participante ID del participante
* @param id_evento ID del evento
* @param id_cuestionario ID del cuestionario
* @returns Token JWT codificado
*/
generateQrToken(
id_participante: number,
id_evento: number,
id_cuestionario: number,
fecha_fin: Date,
): string {
const payload = {
id_participante,
id_evento,
id_cuestionario,
type: 'qr_asistencia',
iat: Math.floor(Date.now() / 1000),
};
// Usar una clave secreta específica para QR o la misma que JWT general
const secret =
this.configService.get<string>('QR_JWT_SECRET') ||
this.configService.get<string>('JWT_SECRET', 'tu_clave_secreta');
console.log("fecha de caducidad:",fecha_fin);
// Convert fecha_fin to seconds from now for expiresIn
const expiresInSeconds = Math.floor((fecha_fin.getTime() - Date.now()) / 1000);
console.log("expiresInSeconds:",expiresInSeconds);
console.log("Caducidad token: ", Math.floor((fecha_fin.getTime() - Date.now()) / 1000));
return this.jwtService.sign(payload, {
secret,
expiresIn: expiresInSeconds > 0 ? expiresInSeconds : 3600, // El QR puede ser válido por 30 días
});
}
/**
* Valida y decodifica un token de QR
* @param token Token JWT a validar
* @returns Datos decodificados del token o null si es inválido
*/
async validateQrToken(token: string): Promise<{
id_participante
: number;
id_evento: number;
id_cuestionario: number;
type: string;
iat: number;
exp?: number;
} | null >{
try {
const secret =
this.configService.get<string>('QR_JWT_SECRET') ||
this.configService.get<string>('JWT_SECRET', 'tu_clave_secreta');
console.log(secret)
const decoded = this.jwtService.verify(token, { secret });
//console.log("fecha fin:", fecha_fin2.fecha_fin);
console.log("este es el token", decoded);
const fecha_fin2 = await this.eventoREpo.findOne({
where: { id_evento:decoded.id_evento },
});
if (!fecha_fin2) {
throw new UnauthorizedException('Evento no encontrado');
}
const fechaFinEvento = new Date(fecha_fin2.fecha_fin); // UTC
const now = new Date();
console.log(fechaFinEvento.getTime())
console.log(now.getTime)
if (fechaFinEvento.getTime() < now.getTime()) {
throw new Error('El evento ha finalizado');
}
// Verificar que sea un token de tipo QR de asistencia
if (decoded.type !== 'qr_asistencia') {
return null;
}
return {
id_participante: decoded.id_participante,
id_evento: decoded.id_evento,
id_cuestionario: decoded.id_cuestionario,
type: decoded.type,
iat: decoded.iat,
};
} catch (error) {
console.error('Error validando token QR:', error.message);
return null;
}
}
/**
* Verifica si un token QR es válido y no ha expirado
* @param token Token a verificar
* @returns true si es válido, false si no
*/
isTokenValid(token: string): boolean {
const decoded = this.validateQrToken(token);
return decoded !== null;
}
}