/** * Реестр владельцев файлов-результатов (RESULTS_DIR). * Имена результатов строятся из времени и потому угадываемы, поэтому скачивание * проверяется по владельцу, а не по знанию имени. * Живёт в той же SQLite, что и очередь задач, — переживает рестарт сервиса. */ const { db } = require('./queue'); db.exec(` CREATE TABLE IF NOT EXISTS file_owners ( filename TEXT PRIMARY KEY, user_id TEXT, display_name TEXT, created_at INTEGER NOT NULL ) `); const stmts = { claim: db.prepare(`INSERT OR REPLACE INTO file_owners (filename, user_id, display_name, created_at) VALUES (?, ?, ?, ?)`), get: db.prepare(`SELECT user_id, display_name FROM file_owners WHERE filename = ?`), cleanup: db.prepare(`DELETE FROM file_owners WHERE created_at < ?`), }; function claim(filename, userId, displayName) { try { stmts.claim.run(String(filename), userId != null ? String(userId) : null, displayName ? String(displayName) : null, Date.now()); } catch {} } // Записи живут дольше самих файлов (24 часа против 30 минут), поэтому // отсутствие записи означает чужой/просроченный файл — доступ закрыт. function isOwner(filename, userId) { try { const row = stmts.get.get(String(filename)); if (!row || userId == null) return false; return String(row.user_id) === String(userId); } catch { return false; } } function displayName(filename) { try { const row = stmts.get.get(String(filename)); return (row && row.display_name) || null; } catch { return null; } } function cleanup() { try { stmts.cleanup.run(Date.now() - 24 * 3600 * 1000); } catch {} } setInterval(cleanup, 3600 * 1000); module.exports = { claim, isOwner, displayName, cleanup };