mirror of
https://github.com/ancsemi/Haven.git
synced 2026-11-01 19:46:21 +00:00
64 lines
3.1 KiB
JavaScript
64 lines
3.1 KiB
JavaScript
'use strict';
|
|
|
|
// Deleting a message takes its files with it, but only the author's own
|
|
// attachments that nothing else uses. Naming someone else's avatar, emoji or
|
|
// attachment in your own message and deleting it must leave that file alone.
|
|
|
|
const assert = require('node:assert/strict');
|
|
const test = require('node:test');
|
|
const Database = require('better-sqlite3');
|
|
|
|
const { releasableUploads } = require('../src/socketHandlers/helpers');
|
|
|
|
function fixture() {
|
|
const db = new Database(':memory:');
|
|
db.exec(`
|
|
CREATE TABLE upload_ownership (rel_path TEXT PRIMARY KEY, user_id INTEGER, bytes INTEGER, scope TEXT);
|
|
CREATE TABLE messages (id INTEGER PRIMARY KEY, content TEXT, is_archived INTEGER DEFAULT 0);
|
|
CREATE TABLE users (id INTEGER PRIMARY KEY, avatar TEXT, border TEXT);
|
|
CREATE TABLE user_personas (id INTEGER PRIMARY KEY, avatar TEXT);
|
|
CREATE TABLE webhooks (id INTEGER PRIMARY KEY, avatar_url TEXT);
|
|
CREATE TABLE roles (id INTEGER PRIMARY KEY, icon TEXT);
|
|
CREATE TABLE server_settings (key TEXT PRIMARY KEY, value TEXT);
|
|
CREATE TABLE custom_sounds (id INTEGER PRIMARY KEY, filename TEXT);
|
|
CREATE TABLE custom_emojis (id INTEGER PRIMARY KEY, filename TEXT);
|
|
CREATE TABLE stickers (id INTEGER PRIMARY KEY, filename TEXT);
|
|
`);
|
|
const own = db.prepare('INSERT INTO upload_ownership (rel_path, user_id, bytes, scope) VALUES (?, ?, 0, ?)');
|
|
own.run('mine.png', 1, 'channel');
|
|
own.run('mine-dm.bin', 1, 'dm');
|
|
own.run('theirs.png', 2, 'channel');
|
|
own.run('my-avatar.png', 1, 'profile');
|
|
own.run('reposted.png', 1, 'channel');
|
|
own.run('icon.png', 1, 'channel');
|
|
own.run('boop.mp3', 1, 'channel');
|
|
db.prepare('INSERT INTO messages (content) VALUES (?)').run('look again /uploads/reposted.png');
|
|
db.prepare('INSERT INTO roles (icon) VALUES (?)').run('/uploads/icon.png');
|
|
db.prepare('INSERT INTO custom_sounds (filename) VALUES (?)').run('boop.mp3');
|
|
return db;
|
|
}
|
|
|
|
test('only the author\'s own, unused attachments are released', () => {
|
|
const db = fixture();
|
|
const out = releasableUploads(db, [
|
|
'mine.png', 'mine-dm.bin', 'theirs.png', 'my-avatar.png', 'reposted.png', 'icon.png', 'boop.mp3', 'unknown-legacy.png',
|
|
], [1]);
|
|
assert.deepEqual(out.sort(), ['mine-dm.bin', 'mine.png']);
|
|
});
|
|
|
|
test('someone else\'s file is never released, whoever deletes', () => {
|
|
const db = fixture();
|
|
assert.deepEqual(releasableUploads(db, ['theirs.png'], [1]), []);
|
|
assert.deepEqual(releasableUploads(db, ['theirs.png'], [2]), ['theirs.png']);
|
|
assert.deepEqual(releasableUploads(db, ['theirs.png'], [null, undefined]), []);
|
|
});
|
|
|
|
test('a protected message keeps its files, even one posted after the deleted message', () => {
|
|
const db = fixture();
|
|
const sent = db.prepare('INSERT INTO messages (content) VALUES (?)').run('/uploads/mine.png').lastInsertRowid;
|
|
db.prepare('INSERT INTO messages (content, is_archived) VALUES (?, 1)').run('evidence /uploads/mine.png');
|
|
assert.deepEqual(releasableUploads(db, ['mine.png'], [1], { ignoreMessagesAfter: sent }), []);
|
|
db.prepare('UPDATE messages SET is_archived = 0').run();
|
|
assert.deepEqual(releasableUploads(db, ['mine.png'], [1], { ignoreMessagesAfter: sent }), ['mine.png']);
|
|
});
|