/**
 * Authentication & Session Management
 * User authentication for 4Runr OS with session management
 */
import * as fs from 'fs';
import * as path from 'path';
import * as os from 'os';
const SESSION_DURATION = 2 * 60 * 60 * 1000; // 2 hours (like AWS)
const SESSION_FILE = path.join(os.homedir(), '.4runr', 'session.json');
/**
 * Get config directory
 */
function getConfigDir() {
    const configDir = path.join(os.homedir(), '.4runr');
    if (!fs.existsSync(configDir)) {
        fs.mkdirSync(configDir, { recursive: true });
    }
    return configDir;
}
/**
 * Save session to file (ENCRYPTED)
 */
export function saveSession(session) {
    try {
        getConfigDir(); // Ensure directory exists
        // SECURITY: Encrypt session data before saving
        const { encryptJson } = require('./security/encryption.js');
        const encrypted = encryptJson(session);
        // SECURITY: Set restrictive file permissions (Unix/Linux)
        // This prevents other users from reading the session file
        fs.writeFileSync(SESSION_FILE, encrypted, { encoding: 'utf-8', mode: 0o600 });
    }
    catch (error) {
        console.error(`Failed to save session: ${error.message}`);
    }
}
/**
 * Load session from file (ENCRYPTED + VALIDATED)
 */
export function loadSession() {
    try {
        if (!fs.existsSync(SESSION_FILE)) {
            return null;
        }
        const encrypted = fs.readFileSync(SESSION_FILE, 'utf-8');
        // Try to decrypt (handles both encrypted and legacy unencrypted)
        let session;
        try {
            const { decryptJson, isEncrypted } = require('./security/encryption.js');
            const { validateUserSession } = require('./security/validation.js');
            if (isEncrypted(encrypted)) {
                // New encrypted format
                const decrypted = decryptJson(encrypted);
                // SECURITY: Validate structure
                const validation = validateUserSession(decrypted);
                if (!validation.valid || !validation.data) {
                    console.error(`Invalid session data: ${validation.error}`);
                    clearSession();
                    return null;
                }
                session = validation.data;
            }
            else {
                // Legacy unencrypted format - parse and re-encrypt
                const parsed = JSON.parse(encrypted);
                const validation = validateUserSession(parsed);
                if (!validation.valid || !validation.data) {
                    console.error(`Invalid session data: ${validation.error}`);
                    clearSession();
                    return null;
                }
                session = validation.data;
                // Re-save with encryption
                saveSession(session);
            }
        }
        catch (decryptError) {
            // Fallback to unencrypted (legacy)
            const parsed = JSON.parse(encrypted);
            const { validateUserSession } = require('./security/validation.js');
            const validation = validateUserSession(parsed);
            if (!validation.valid || !validation.data) {
                throw new Error(validation.error);
            }
            session = validation.data;
        }
        // Check if session is expired
        if (Date.now() > session.expiresAt) {
            clearSession();
            return null;
        }
        return session;
    }
    catch (error) {
        console.error(`Failed to load session: ${error.message}`);
        return null;
    }
}
/**
 * Clear session file
 */
export function clearSession() {
    try {
        if (fs.existsSync(SESSION_FILE)) {
            fs.unlinkSync(SESSION_FILE);
        }
    }
    catch (error) {
        console.error(`Failed to clear session: ${error.message}`);
    }
}
/**
 * Update session activity timestamp
 */
export function updateActivity(session) {
    session.lastActivityAt = Date.now();
    saveSession(session);
}
/**
 * Check if session is still valid
 */
export function isSessionValid(session) {
    if (!session)
        return false;
    return Date.now() < session.expiresAt;
}
/**
 * Get time remaining in session (in minutes)
 */
export function getSessionTimeRemaining(session) {
    if (!session)
        return 0;
    const remaining = session.expiresAt - Date.now();
    return Math.max(0, Math.floor(remaining / 1000 / 60));
}
/**
 * Create a new session for a user
 */
export function createSession(username, gatewayUrl) {
    const now = Date.now();
    const session = {
        username,
        loggedInAt: now,
        lastActivityAt: now,
        expiresAt: now + SESSION_DURATION,
        gatewayUrl,
    };
    saveSession(session);
    return session;
}
/**
 * Validate username to prevent path traversal attacks
 */
function validateUsername(username) {
    // Only allow alphanumeric, underscore, hyphen
    if (!/^[a-zA-Z0-9_-]+$/.test(username)) {
        throw new Error('Invalid username. Only letters, numbers, underscores, and hyphens are allowed.');
    }
    // Check for path traversal attempts
    if (username.includes('..') || username.includes('/') || username.includes('\\')) {
        throw new Error('Invalid username. Path traversal attempts are not allowed.');
    }
    // Limit length
    if (username.length < 1 || username.length > 64) {
        throw new Error('Username must be between 1 and 64 characters.');
    }
}
/**
 * Get user-specific config directory
 */
export function getUserConfigDir(username) {
    // SECURITY: Validate username to prevent path traversal
    validateUsername(username);
    const userDir = path.join(getConfigDir(), 'users', username);
    // SECURITY: Verify the resolved path is within the expected directory
    const configDir = getConfigDir();
    const expectedBase = path.join(configDir, 'users');
    if (!userDir.startsWith(expectedBase)) {
        throw new Error('Invalid username: path traversal detected.');
    }
    if (!fs.existsSync(userDir)) {
        fs.mkdirSync(userDir, { recursive: true });
    }
    return userDir;
}
/**
 * Get user-specific agents file path
 */
export function getUserAgentsPath(username) {
    return path.join(getUserConfigDir(username), 'agents.json');
}
/**
 * Get user-specific chats file path
 */
export function getUserChatsPath(username) {
    return path.join(getUserConfigDir(username), 'chats.json');
}
/**
 * Get user-specific tools file path
 */
export function getUserToolsPath(username) {
    return path.join(getUserConfigDir(username), 'tools.json');
}
//# sourceMappingURL=auth.js.map