"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
const express_1 = require("express");
const bcrypt = __importStar(require("bcryptjs"));
const jwt = __importStar(require("jsonwebtoken"));
const config_1 = require("../config");
const auth_1 = require("../auth");
const logger_1 = require("../logger");
const log = (0, logger_1.modLogger)('auth');
const router = (0, express_1.Router)();
// Simple rate limiter for login attempts
const loginAttempts = new Map();
const MAX_LOGIN_ATTEMPTS = 5;
const RATE_LIMIT_WINDOW_MS = 15 * 60 * 1000; // 15 minutes
// Prune expired entries periodically (every 5 min) instead of on every request
setInterval(() => {
    const now = Date.now();
    for (const [key, val] of loginAttempts) {
        if (now > val.resetAt)
            loginAttempts.delete(key);
    }
}, 5 * 60 * 1000).unref();
function isRateLimited(ip) {
    const now = Date.now();
    const entry = loginAttempts.get(ip);
    if (!entry || now > entry.resetAt)
        return false;
    return entry.count >= MAX_LOGIN_ATTEMPTS;
}
function recordFailedLogin(ip) {
    const now = Date.now();
    const entry = loginAttempts.get(ip);
    if (!entry || now > entry.resetAt) {
        loginAttempts.set(ip, { count: 1, resetAt: now + RATE_LIMIT_WINDOW_MS });
    }
    else {
        entry.count++;
    }
}
// GET /api/auth/local-token — returns JWT without credentials (localhost only)
router.get('/local-token', (req, res) => {
    if (!(0, auth_1.isLocalRequest)(req)) {
        res.status(403).json({ error: 'Local access only' });
        return;
    }
    try {
        const token = (0, auth_1.generateLocalToken)();
        res.json({ token });
    }
    catch {
        res.status(500).json({ error: 'Server configuration error' });
    }
});
router.post('/login', async (req, res) => {
    const ip = req.ip || req.socket.remoteAddress || 'unknown';
    if (isRateLimited(ip)) {
        res.status(429).json({ error: 'Too many login attempts. Try again later.' });
        return;
    }
    const { username, password } = req.body;
    if (!username || !password) {
        res.status(400).json({ error: 'Username and password are required' });
        return;
    }
    let config;
    try {
        config = (0, config_1.getConfig)();
    }
    catch (err) {
        res.status(500).json({ error: 'Server configuration error. Run npm run setup first.' });
        return;
    }
    // Check admin user (config.json) and registered users (users.json)
    let passwordHash = null;
    if (username === config.username) {
        passwordHash = config.passwordHash;
    }
    else {
        const registeredUser = (0, config_1.getRegisteredUsers)().find((u) => u.username === username);
        if (registeredUser) {
            passwordHash = registeredUser.passwordHash;
        }
    }
    if (!passwordHash) {
        recordFailedLogin(ip);
        res.status(401).json({ error: 'Invalid credentials' });
        return;
    }
    const valid = await bcrypt.compare(password, passwordHash);
    if (!valid) {
        recordFailedLogin(ip);
        res.status(401).json({ error: 'Invalid credentials' });
        return;
    }
    // Successful login — clear rate limit counter for this IP
    loginAttempts.delete(ip);
    log.info({ user: username, ip }, 'successful login');
    const token = jwt.sign({ username }, config.jwtSecret, { expiresIn: '30d' });
    res.json({ token });
});
exports.default = router;
//# sourceMappingURL=auth.js.map