This commit is contained in:
2026-09-29 19:48:29 +02:00
parent 92609a00af
commit ed42b1595c
9 changed files with 760 additions and 227 deletions
+62
View File
@@ -2200,6 +2200,68 @@ export default router => {
});
});
// Bulk visibility for the mod/admin selection bar: same levels and side effects as /item/visibility
group.post(/\/items\/bulk-visibility$/, lib.loggedin, async (req, res) => {
const isModOrAdmin = !!(req.session?.admin || req.session?.is_moderator);
if (!isModOrAdmin) {
return res.json({ success: false, msg: 'Bulk selection is only available to administrators and moderators' }, 403);
}
if (cfg.enable_private_uploads === false && !req.session.admin) {
return res.json({ success: false, msg: 'Private uploads feature disabled' }, 403);
}
const visibility = parseInt(req.body?.visibility ?? req.post?.visibility, 10);
if (isNaN(visibility) || ![0, 1, 2, 3].includes(visibility)) {
return res.json({ success: false, msg: 'Invalid visibility' }, 400);
}
const rawIds = req.body?.item_ids || req.post?.item_ids;
if (!Array.isArray(rawIds) || rawIds.length === 0) {
return res.json({ success: false, msg: 'No items selected' }, 400);
}
const itemIds = [...new Set(rawIds.map(id => +id).filter(id => Number.isInteger(id) && id > 0))].slice(0, 500);
if (itemIds.length === 0) {
return res.json({ success: false, msg: 'Invalid item IDs' }, 400);
}
try {
const items = await db`
SELECT id, dest, username, COALESCE(visibility, 0) AS visibility
FROM items
WHERE id = ANY(${itemIds}::int[]) AND active = true AND is_deleted = false
`;
const changed = items.filter(it => it.visibility !== visibility);
if (changed.length === 0) {
return res.json({ success: true, updated: 0, visibility, msg: 'Nothing to change' });
}
await db`UPDATE items SET visibility = ${visibility} WHERE id = ANY(${changed.map(it => it.id)}::int[])`;
for (const it of changed) {
if (visibility === 2) {
addPrivateItem(it.id, it.dest, it.username);
removeUnavailableItem(it.id, it.dest);
} else if (visibility === 3) {
addUnavailableItem(it.id, it.dest, it.username);
removePrivateItem(it.id, it.dest);
} else {
removePrivateItem(it.id, it.dest);
removeUnavailableItem(it.id, it.dest);
}
}
f0cklib.clearCountCache();
await audit.log(req.session.id, 'bulk_set_visibility', 'items', null, {
item_ids: changed.map(it => it.id),
visibility
}).catch(() => {});
return res.json({ success: true, updated: changed.length, item_ids: changed.map(it => it.id), visibility });
} catch (err) {
console.error('[BULK VISIBILITY]', err);
return res.json({ success: false, msg: 'Failed to update visibility' }, 500);
}
});
group.post(/\/items\/(?<id>[0-9]+)\/rethumb$/, lib.registeredUser, async (req, res) => {
const itemid = +req.params.id;
if (!itemid) return res.json({ success: false, msg: 'No itemid provided' }, 400);