"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.MfaController = void 0;
const common_1 = require("@nestjs/common");
const core_1 = require("../../core");
const mfa_service_1 = require("../services/mfa.service");
const request_context_1 = require("../../request-context/request-context");
const send_mfa_code_request_dto_1 = require("../dto/requests/send-mfa-code.request.dto");
const verify_totp_setup_request_dto_1 = require("../dto/requests/verify-totp-setup.request.dto");
const swagger_1 = require("@nestjs/swagger");
const auth_constants_1 = require("../../auth.constants");
const auth_guard_1 = require("../guards/auth.guard");
const toggle_mfa_request_dto_1 = require("../dto/requests/toggle-mfa.request.dto");
const mfa_status_response_dto_1 = require("../dto/responses/mfa-status.response.dto");
const auth_config_service_1 = require("../../core/services/auth-config.service");
let MfaController = class MfaController {
    mfaService;
    authConfig;
    constructor(mfaService, authConfig) {
        this.mfaService = mfaService;
        this.authConfig = authConfig;
    }
    getCurrentUserOrThrow() {
        const user = request_context_1.RequestContext.currentUser();
        if (!user) {
            throw new common_1.UnauthorizedException('User not found');
        }
        return user;
    }
    async getStatus() {
        const user = this.getCurrentUserOrThrow();
        const config = this.mfaService.mfaConfig;
        const globallyEnabled = config?.enabled ?? false;
        let verifiedMethods = [];
        let totpDevices = [];
        let hasRecoveryCode = false;
        let isEnabled = false;
        if (globallyEnabled) {
            [verifiedMethods, totpDevices, hasRecoveryCode, isEnabled] = await Promise.all([
                this.mfaService.getVerifiedMethods(user.id),
                this.mfaService.getTotpDevices(user.id),
                this.mfaService.hasRecoveryCode(user.id),
                this.mfaService.isMfaEnabled(user.id),
            ]);
        }
        return {
            isEnabled,
            verifiedMethods,
            configuredMethods: this.mfaService.getAvailableMethods(),
            allowUserToggle: config?.allowUserToggle ?? false,
            allowMethodSelection: config?.allowMethodSelection ?? false,
            totpDevices,
            hasRecoveryCode,
        };
    }
    async toggleMfa(input) {
        const user = this.getCurrentUserOrThrow();
        this.mfaService.requireMfaEnabledForApp(true);
        if (input.enabled) {
            await this.mfaService.enableMFA(user.id);
            return { message: 'MFA enabled successfully' };
        }
        await this.mfaService.disableMFA(user.id);
        return { message: 'MFA disabled successfully' };
    }
    async listDevices() {
        const user = this.getCurrentUserOrThrow();
        this.mfaService.requireMfaEnabledForApp(true);
        return await this.mfaService.getTotpDevices(user.id);
    }
    async removeDevice(deviceId) {
        const user = this.getCurrentUserOrThrow();
        this.mfaService.requireMfaEnabledForApp(true);
        await this.mfaService.removeTotpDevice(deviceId);
        return { message: 'MFA device removed successfully' };
    }
    async sendMfaCode(input) {
        const user = this.getCurrentUserOrThrow();
        await this.mfaService.sendMfaCode(user.id, input.method);
        return { message: 'MFA code sent' };
    }
    async setupTotp() {
        const user = this.getCurrentUserOrThrow();
        const config = this.authConfig.getConfig();
        const appName = config.appName;
        let userEmail = user.email;
        if (!userEmail) {
            const fullUser = await core_1.NestAuthUser.findOne({ where: { id: user.id } });
            userEmail = fullUser?.email || 'User';
        }
        const deviceName = `${appName} : ${userEmail}`;
        const { secret, qrCode } = await this.mfaService.setupTotpDevice(user.id, deviceName);
        return { secret, qrCode };
    }
    async verifyTotpSetup(input) {
        const user = this.getCurrentUserOrThrow();
        const isVerified = await this.mfaService.verifyTotpSetup(user.id, input.secret, input.otp);
        if (!isVerified) {
            throw new common_1.UnauthorizedException({
                message: 'Invalid OTP',
                code: auth_constants_1.INVALID_MFA_EXCEPTION_CODE
            });
        }
        return { message: 'Device setup successfully' };
    }
    async generateRecoveryCodes() {
        const user = this.getCurrentUserOrThrow();
        const code = await this.mfaService.generateRecoveryCode(user.id);
        return { code };
    }
    async resetTotp(code) {
        const user = this.getCurrentUserOrThrow();
        await this.mfaService.resetMfa(user.id, code);
        return { message: 'MFA reset successfully' };
    }
};
exports.MfaController = MfaController;
__decorate([
    (0, swagger_1.ApiOperation)({ summary: 'Get MFA status for the current user' }),
    (0, swagger_1.ApiResponse)({ status: 200, type: mfa_status_response_dto_1.MfaStatusResponseDto }),
    (0, common_1.HttpCode)(200),
    (0, common_1.Get)('status'),
    (0, core_1.SkipMfa)(),
    (0, common_1.UseGuards)(auth_guard_1.NestAuthAuthGuard),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", Promise)
], MfaController.prototype, "getStatus", null);
__decorate([
    (0, swagger_1.ApiOperation)({ summary: 'Enable or disable MFA for the current user' }),
    (0, swagger_1.ApiResponse)({ status: 200, type: core_1.MessageResponseDto }),
    (0, common_1.HttpCode)(200),
    (0, common_1.Post)('toggle'),
    (0, core_1.SkipMfa)(),
    (0, common_1.UseGuards)(auth_guard_1.NestAuthAuthGuard),
    __param(0, (0, common_1.Body)()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [toggle_mfa_request_dto_1.ToggleMfaRequestDto]),
    __metadata("design:returntype", Promise)
], MfaController.prototype, "toggleMfa", null);
__decorate([
    (0, swagger_1.ApiOperation)({ summary: 'List registered MFA devices' }),
    (0, swagger_1.ApiResponse)({ status: 200, type: [mfa_status_response_dto_1.MfaDeviceDto] }),
    (0, common_1.HttpCode)(200),
    (0, common_1.Get)('devices'),
    (0, core_1.SkipMfa)(),
    (0, common_1.UseGuards)(auth_guard_1.NestAuthAuthGuard),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", Promise)
], MfaController.prototype, "listDevices", null);
__decorate([
    (0, swagger_1.ApiOperation)({ summary: 'Remove a registered MFA device' }),
    (0, swagger_1.ApiResponse)({ status: 200, type: core_1.MessageResponseDto }),
    (0, common_1.HttpCode)(200),
    (0, common_1.Delete)('devices/:deviceId'),
    (0, core_1.SkipMfa)(),
    (0, common_1.UseGuards)(auth_guard_1.NestAuthAuthGuard),
    __param(0, (0, common_1.Param)('deviceId')),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", Promise)
], MfaController.prototype, "removeDevice", null);
__decorate([
    (0, swagger_1.ApiOperation)({ summary: 'Send MFA Code' }),
    (0, swagger_1.ApiResponse)({ status: 200, type: core_1.MessageResponseDto }),
    (0, common_1.HttpCode)(200),
    (0, common_1.Post)('send-mfa-code'),
    (0, core_1.SkipMfa)(),
    (0, common_1.UseGuards)(auth_guard_1.NestAuthAuthGuard),
    __param(0, (0, common_1.Body)()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [send_mfa_code_request_dto_1.SendMfaCodeRequestDto]),
    __metadata("design:returntype", Promise)
], MfaController.prototype, "sendMfaCode", null);
__decorate([
    (0, swagger_1.ApiOperation)({ summary: 'Setup TOTP Device' }),
    (0, swagger_1.ApiResponse)({ status: 200, type: core_1.MessageResponseDto }),
    (0, common_1.HttpCode)(200),
    (0, common_1.Post)('setup-totp'),
    (0, core_1.SkipMfa)(),
    (0, common_1.UseGuards)(auth_guard_1.NestAuthAuthGuard),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", Promise)
], MfaController.prototype, "setupTotp", null);
__decorate([
    (0, swagger_1.ApiOperation)({ summary: 'Verify TOTP Setup' }),
    (0, swagger_1.ApiResponse)({ status: 200, type: core_1.MessageResponseDto }),
    (0, common_1.HttpCode)(200),
    (0, common_1.Post)('verify-totp-setup'),
    (0, core_1.SkipMfa)(),
    (0, common_1.UseGuards)(auth_guard_1.NestAuthAuthGuard),
    __param(0, (0, common_1.Body)()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [verify_totp_setup_request_dto_1.VerifyTotpSetupRequestDto]),
    __metadata("design:returntype", Promise)
], MfaController.prototype, "verifyTotpSetup", null);
__decorate([
    (0, swagger_1.ApiOperation)({ summary: 'Generate Recovery Codes' }),
    (0, swagger_1.ApiResponse)({ status: 200, type: core_1.MessageResponseDto }),
    (0, common_1.HttpCode)(200),
    (0, common_1.Post)('generate-recovery-code'),
    (0, core_1.SkipMfa)(),
    (0, common_1.UseGuards)(auth_guard_1.NestAuthAuthGuard),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", Promise)
], MfaController.prototype, "generateRecoveryCodes", null);
__decorate([
    (0, swagger_1.ApiOperation)({ summary: 'Reset TOTP Device' }),
    (0, swagger_1.ApiResponse)({ status: 200, type: core_1.MessageResponseDto }),
    (0, common_1.HttpCode)(200),
    (0, common_1.Post)('reset-totp'),
    (0, core_1.SkipMfa)(),
    (0, common_1.UseGuards)(auth_guard_1.NestAuthAuthGuard),
    __param(0, (0, common_1.Body)('code')),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", Promise)
], MfaController.prototype, "resetTotp", null);
exports.MfaController = MfaController = __decorate([
    (0, common_1.Controller)('auth/mfa'),
    __metadata("design:paramtypes", [mfa_service_1.MfaService,
        auth_config_service_1.AuthConfigService])
], MfaController);
//# sourceMappingURL=mfa.controller.js.map