"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AuthService = void 0; const common_1 = require("@nestjs/common"); const typeorm_1 = require("@nestjs/typeorm"); const typeorm_2 = require("typeorm"); const jwt_1 = require("@nestjs/jwt"); const config_1 = require("@nestjs/config"); const bcrypt = require("bcrypt"); const tenant_entity_1 = require("./entities/tenant.entity"); const user_entity_1 = require("./entities/user.entity"); let AuthService = class AuthService { constructor(tenantRepository, userRepository, jwtService, configService) { this.tenantRepository = tenantRepository; this.userRepository = userRepository; this.jwtService = jwtService; this.configService = configService; } generateSlug(name) { return name .toLowerCase() .normalize('NFD') .replace(/[\u0300-\u036f]/g, '') .replace(/[^a-z0-9]+/g, '-') .replace(/(^-|-$)/g, '') .substring(0, 45) + '-' + Date.now().toString(36).slice(-4); } async register(dto) { const existingTenant = await this.tenantRepository.findOne({ where: { phone: dto.phone }, }); if (existingTenant) { throw new common_1.ConflictException('Este teléfono ya está registrado'); } const pinHash = await bcrypt.hash(dto.pin, 10); const slug = this.generateSlug(dto.name); const tenant = this.tenantRepository.create({ name: dto.name, slug, businessType: dto.businessType, phone: dto.phone, email: dto.email, address: dto.address, city: dto.city, whatsappNumber: dto.whatsapp || dto.phone, subscriptionStatus: 'trial', status: 'active', }); const savedTenant = await this.tenantRepository.save(tenant); const user = this.userRepository.create({ tenantId: savedTenant.id, phone: dto.phone, name: dto.ownerName, pinHash, role: 'owner', status: 'active', }); const savedUser = await this.userRepository.save(user); return this.generateTokens(savedUser, savedTenant); } async login(dto) { const user = await this.userRepository.findOne({ where: { phone: dto.phone }, }); if (!user) { throw new common_1.UnauthorizedException('Teléfono o PIN incorrectos'); } const tenant = await this.tenantRepository.findOne({ where: { id: user.tenantId }, }); if (!tenant) { throw new common_1.UnauthorizedException('Teléfono o PIN incorrectos'); } if (tenant.subscriptionStatus === 'cancelled') { throw new common_1.UnauthorizedException('Tu suscripción ha sido cancelada'); } if (tenant.subscriptionStatus === 'suspended' || tenant.status === 'suspended') { throw new common_1.UnauthorizedException('Tu cuenta está suspendida. Contacta soporte.'); } if (user.status !== 'active') { throw new common_1.UnauthorizedException('Tu cuenta está inactiva'); } if (user.lockedUntil && user.lockedUntil > new Date()) { throw new common_1.UnauthorizedException('Cuenta bloqueada temporalmente. Intenta más tarde.'); } const isValidPin = await bcrypt.compare(dto.pin, user.pinHash); if (!isValidPin) { user.failedAttempts = (user.failedAttempts || 0) + 1; if (user.failedAttempts >= 5) { user.lockedUntil = new Date(Date.now() + 15 * 60 * 1000); } await this.userRepository.save(user); throw new common_1.UnauthorizedException('Teléfono o PIN incorrectos'); } user.failedAttempts = 0; user.lockedUntil = null; user.lastLoginAt = new Date(); await this.userRepository.save(user); return this.generateTokens(user, tenant); } async refreshToken(refreshToken) { try { const payload = this.jwtService.verify(refreshToken, { secret: this.configService.get('JWT_SECRET'), }); const user = await this.userRepository.findOne({ where: { id: payload.sub }, }); if (!user) { throw new common_1.UnauthorizedException('Token inválido'); } const tenant = await this.tenantRepository.findOne({ where: { id: user.tenantId }, }); if (!tenant) { throw new common_1.UnauthorizedException('Token inválido'); } return this.generateTokens(user, tenant); } catch { throw new common_1.UnauthorizedException('Token inválido o expirado'); } } async changePin(userId, currentPin, newPin) { const user = await this.userRepository.findOne({ where: { id: userId }, }); if (!user) { throw new common_1.BadRequestException('Usuario no encontrado'); } const isValidPin = await bcrypt.compare(currentPin, user.pinHash); if (!isValidPin) { throw new common_1.UnauthorizedException('PIN actual incorrecto'); } user.pinHash = await bcrypt.hash(newPin, 10); await this.userRepository.save(user); } generateTokens(user, tenant) { const payload = { sub: user.id, tenantId: tenant.id, phone: user.phone, role: user.role, }; const accessToken = this.jwtService.sign(payload, { expiresIn: this.configService.get('JWT_EXPIRES_IN', '24h'), }); const refreshToken = this.jwtService.sign(payload, { expiresIn: this.configService.get('JWT_REFRESH_EXPIRES_IN', '7d'), }); return { accessToken, refreshToken, user: { id: user.id, name: user.name, role: user.role, phone: user.phone, }, tenant: { id: tenant.id, name: tenant.name, slug: tenant.slug, businessType: tenant.businessType, subscriptionStatus: tenant.subscriptionStatus, }, }; } }; exports.AuthService = AuthService; exports.AuthService = AuthService = __decorate([ (0, common_1.Injectable)(), __param(0, (0, typeorm_1.InjectRepository)(tenant_entity_1.Tenant)), __param(1, (0, typeorm_1.InjectRepository)(user_entity_1.User)), __metadata("design:paramtypes", [typeorm_2.Repository, typeorm_2.Repository, jwt_1.JwtService, config_1.ConfigService]) ], AuthService); //# sourceMappingURL=auth.service.js.map