"use strict";
/**
 * Dashboard Authentication Routes
 * Handles login, logout, session check, and setup status.
 */
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveDashboardAccessState = void 0;
const express_1 = require("express");
const bcrypt_1 = __importDefault(require("bcrypt"));
const crypto_1 = __importDefault(require("crypto"));
const auth_middleware_1 = require("../middleware/auth-middleware");
const config_loader_facade_1 = require("../../config/config-loader-facade");
/**
 * Timing-safe string comparison to prevent timing attacks.
 * Returns true if strings match, false otherwise.
 */
function timingSafeEqual(a, b) {
    if (a.length !== b.length) {
        // Still compare to avoid length-based timing leak
        crypto_1.default.timingSafeEqual(Buffer.from(a), Buffer.from(a));
        return false;
    }
    return crypto_1.default.timingSafeEqual(Buffer.from(a), Buffer.from(b));
}
const router = (0, express_1.Router)();
function resolveDashboardAccessState(authConfig, remoteAddress) {
    const isLocalAccess = (0, auth_middleware_1.isLoopbackRemoteAddress)(remoteAddress);
    const authConfigured = Boolean(authConfig.username && authConfig.password_hash);
    if (!authConfig.enabled) {
        return {
            authRequired: false,
            authEnabled: false,
            authConfigured,
            isLocalAccess,
            accessMode: 'open',
        };
    }
    if (authConfigured) {
        return {
            authRequired: true,
            authEnabled: true,
            authConfigured: true,
            isLocalAccess,
            accessMode: 'login',
        };
    }
    return {
        authRequired: true,
        authEnabled: true,
        authConfigured,
        isLocalAccess,
        accessMode: 'setup',
    };
}
exports.resolveDashboardAccessState = resolveDashboardAccessState;
/**
 * POST /api/auth/login
 * Authenticate user with username/password.
 * Rate limited: 5 attempts per 15 minutes.
 */
router.post('/login', auth_middleware_1.loginRateLimiter, async (req, res) => {
    const { username, password } = req.body;
    if (!username || !password) {
        res.status(400).json({ error: 'Username and password required' });
        return;
    }
    const authConfig = (0, config_loader_facade_1.getDashboardAuthConfig)();
    // Check if auth is configured
    if (!authConfig.enabled || !authConfig.username || !authConfig.password_hash) {
        res.status(400).json({ error: 'Authentication not configured' });
        return;
    }
    // Validate bcrypt hash format to prevent bcrypt.compare errors
    const isBcryptHash = /^\$2[aby]?\$\d{2}\$.{53}$/.test(authConfig.password_hash);
    if (!isBcryptHash) {
        res.status(500).json({ error: 'Invalid password hash format in config' });
        return;
    }
    // Verify credentials (timing-safe comparison for username)
    const usernameMatch = timingSafeEqual(username, authConfig.username);
    const passwordMatch = await bcrypt_1.default.compare(password, authConfig.password_hash);
    if (!usernameMatch || !passwordMatch) {
        res.status(401).json({ error: 'Invalid credentials' });
        return;
    }
    // Regenerate session to prevent session fixation, then set auth
    req.session.regenerate((err) => {
        if (err) {
            res.status(500).json({ error: 'Session error' });
            return;
        }
        req.session.authenticated = true;
        req.session.username = username;
        res.json({ success: true, username });
    });
});
/**
 * POST /api/auth/logout
 * Clear session and log out user.
 */
router.post('/logout', (req, res) => {
    req.session.destroy((err) => {
        if (err) {
            res.status(500).json({ error: 'Failed to logout' });
            return;
        }
        res.clearCookie('connect.sid');
        res.json({ success: true });
    });
});
/**
 * GET /api/auth/check
 * Check if user is authenticated and if auth is required.
 */
router.get('/check', (req, res) => {
    const authConfig = (0, config_loader_facade_1.getDashboardAuthConfig)();
    const accessState = resolveDashboardAccessState(authConfig, req.socket.remoteAddress);
    res.json({
        ...accessState,
        authenticated: req.session?.authenticated ?? false,
        username: req.session?.username ?? null,
    });
});
/**
 * GET /api/auth/setup
 * Check if authentication is properly configured.
 */
router.get('/setup', (_req, res) => {
    const authConfig = (0, config_loader_facade_1.getDashboardAuthConfig)();
    res.json({
        enabled: authConfig.enabled,
        configured: !!(authConfig.username && authConfig.password_hash),
        sessionTimeoutHours: authConfig.session_timeout_hours ?? 24,
    });
});
exports.default = router;
//# sourceMappingURL=auth-routes.js.map