wa-dev-tools/lib/owner.js
treamz dabc26d70f Sync prod: owner-реестр результатов, общая фабрика лимитов, crash-guard ffmpeg/gs, водяной знак PDF
Незакоммиченная работа сессии 2026-09-05 (уже на проде):
- lib/owner.js — реестр владельцев файлов-результатов, owner-check во всех download-роутах (IDOR)
- lib/limits.js — createLimiter(): skip для админа, ipKeyGenerator (фикс ERR_ERL_KEY_GEN_IPV6)
- video: обработчики 'error' у ffmpeg/ffprobe (spawn ENOENT больше не роняет сервер), таймауты
- pdf: runGhostscript/gsUnavailable, водяной знак с кириллицей (fontkit + TTF)
- снятие лимитов размера/количества для админа в pdf/video
- журнал сессии docs/sessions/2026-09-05-0231.md
2026-09-22 20:37:39 +03:00

59 lines
2.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Реестр владельцев файлов-результатов (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 };