fix: C-7 webhook tenant lookup, C-5 full tax calc §15, M-2/M-3/M-4/M-8/L-7/L-8/L-9 gap fixes
This commit is contained in:
@@ -6,6 +6,8 @@ import { AuthController } from "./auth.controller";
|
||||
import { AuthService } from "./auth.service";
|
||||
import { JwtStrategy } from "./jwt.strategy";
|
||||
import { WarehousesModule } from "../warehouses/warehouses.module";
|
||||
import { NotificationsModule } from "../notifications/notifications.module";
|
||||
import { IntegrationsModule } from "../integrations/integrations.module";
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -19,6 +21,8 @@ import { WarehousesModule } from "../warehouses/warehouses.module";
|
||||
}),
|
||||
}),
|
||||
WarehousesModule,
|
||||
NotificationsModule,
|
||||
IntegrationsModule,
|
||||
],
|
||||
controllers: [AuthController],
|
||||
providers: [AuthService, JwtStrategy],
|
||||
|
||||
@@ -5,11 +5,13 @@ import { JwtService } from "@nestjs/jwt";
|
||||
import { ConfigService } from "@nestjs/config";
|
||||
import { PrismaService } from "../prisma/prisma.service";
|
||||
import { WarehousesService } from "../warehouses/warehouses.service";
|
||||
import { NotificationsService } from "../notifications/notifications.service";
|
||||
import { IntegrationsService, INTEGRATION_CATALOG } from "../integrations/integrations.service";
|
||||
import { generateSuiteCode } from "../common/utils/suite-code.util";
|
||||
import { RegisterDto, LoginDto } from "./dto/auth.dto";
|
||||
import * as bcrypt from "bcrypt";
|
||||
import * as crypto from "crypto";
|
||||
import { TOTP, generateSecret, generateURI, verify as totpVerify } from "otplib";
|
||||
import { generateSecret, generateURI, verify as totpVerify } from "otplib";
|
||||
|
||||
const TENANT_SLUG = "moraworld";
|
||||
const BCRYPT_ROUNDS = 10;
|
||||
@@ -21,6 +23,8 @@ export class AuthService {
|
||||
private jwt: JwtService,
|
||||
private config: ConfigService,
|
||||
private warehouses: WarehousesService,
|
||||
private notifications: NotificationsService,
|
||||
private integrations: IntegrationsService,
|
||||
) {}
|
||||
|
||||
/** Builds the suite address from the default warehouse in DB, falls back to env vars */
|
||||
@@ -70,6 +74,24 @@ export class AuthService {
|
||||
|
||||
await this.audit(tenant.id, user.id, "USER_REGISTER", "User", user.id);
|
||||
|
||||
// L-7: Auto-seed integration keys vacías (idempotente)
|
||||
try {
|
||||
await Promise.all(
|
||||
INTEGRATION_CATALOG.map(cat =>
|
||||
this.prisma.client.integration.upsert({
|
||||
where: { tenantId_key: { tenantId: tenant.id, key: cat.key } },
|
||||
create: { tenantId: tenant.id, key: cat.key, label: cat.label, group: cat.group ?? null, isActive: false },
|
||||
update: {},
|
||||
})
|
||||
)
|
||||
);
|
||||
} catch { /* non-blocking */ }
|
||||
|
||||
// L-8: Auto-seed notification templates (idempotente)
|
||||
try {
|
||||
await this.notifications.seedDefaultTemplates(tenant.id);
|
||||
} catch { /* non-blocking */ }
|
||||
|
||||
const tokens = await this.generateTokens(user.id, user.email, user.role, tenant.id);
|
||||
return {
|
||||
user: this.sanitizeUser(user),
|
||||
@@ -100,6 +122,7 @@ export class AuthService {
|
||||
}
|
||||
|
||||
// MFA
|
||||
const PRIVILEGED_ROLES = ["ADMIN_EMPRESA", "SUPER_ADMIN", "OPERADOR_BODEGA", "AGENTE_ADUANERO"];
|
||||
if (user.mfaEnabled) {
|
||||
if (!dto.totpCode) return { requiresMfa: true, userId: user.id };
|
||||
const ok = totpVerify({ token: dto.totpCode, secret: user.mfaSecret! });
|
||||
@@ -107,6 +130,9 @@ export class AuthService {
|
||||
await this.audit(tenant.id, user.id, "MFA_FAILED", "User", user.id);
|
||||
throw new UnauthorizedException("Código MFA inválido.");
|
||||
}
|
||||
} else if (PRIVILEGED_ROLES.includes(user.role)) {
|
||||
// M-8: MFA obligatorio para roles privilegiados — forzar setup antes del primer acceso
|
||||
return { requiresMfaSetup: true, userId: user.id };
|
||||
}
|
||||
|
||||
await this.prisma.client.user.update({
|
||||
|
||||
Reference in New Issue
Block a user