diff --git a/src/inc/routes/apiv2/index.mjs b/src/inc/routes/apiv2/index.mjs index c13720a..06746a2 100644 --- a/src/inc/routes/apiv2/index.mjs +++ b/src/inc/routes/apiv2/index.mjs @@ -710,9 +710,11 @@ export default router => { }; const excludedTags = req.session?.excluded_tags || []; + const isOwnerOrAdmin = req.session && (req.session.admin || req.session.is_moderator); + const visibilityFilter = isOwnerOrAdmin ? db`` : db`and coalesce("items".visibility, 0) = 0`; - const newest = (await db`select max(id) as id from "items"`)[0].id; - const oldest = (await db`select min(id) as id from "items"`)[0].id; + const newest = (await db`select max(id) as id from "items"`)[0]?.id || 0; + const oldest = (await db`select min(id) as id from "items"`)[0]?.id || 0; const modequery = lib.getMode(opt.mode); const rows = (await db` @@ -722,6 +724,7 @@ export default router => { where ${db.unsafe(modequery)} and active = true + ${visibilityFilter} ${excludedTags.length > 0 ? db`and not exists (select 1 from tags_assign where item_id = "items".id and tag_id = any(${excludedTags}::int[]))` : db``} ${opt.older ? db`and id <= ${opt.older}` @@ -737,8 +740,8 @@ export default router => { `).sort((a, b) => b.id - a.id); return res.json({ - atEnd: rows[0].id === newest, - atStart: rows[rows.length - 1].id === oldest, + atEnd: rows.length > 0 && rows[0].id === newest, + atStart: rows.length > 0 && rows[rows.length - 1].id === oldest, success: true, items: rows }, 200); @@ -753,20 +756,6 @@ export default router => { where id = ${+id} and active = true limit 1 `; - const next = await db` - select id - from "items" - where id > ${+id} and active = true - order by id - limit 1 - `; - const prev = await db` - select id - from "items" - where id < ${+id} and active = true - order by id desc - limit 1 - `; if (item.length === 0) { return res.json({ @@ -775,12 +764,41 @@ export default router => { }); } + const actitem = item[0]; + const session = req.session; + const isOwnerOrAdmin = session && ( + session.admin || + session.is_moderator || + (session.user && session.user.toLowerCase() === (actitem.username || '').toLowerCase()) + ); + + // Exclude unlisted (1) and private (2) items from API responses for non-owners/non-admins + if ((actitem.visibility || 0) > 0 && !isOwnerOrAdmin) { + return res.json({ + success: false, + msg: 'no items found' + }); + } + + const next = await db` + select id + from "items" + where id > ${+id} and active = true and coalesce(visibility, 0) = 0 + order by id + limit 1 + `; + const prev = await db` + select id + from "items" + where id < ${+id} and active = true and coalesce(visibility, 0) = 0 + order by id desc + limit 1 + `; + const rows = { - ...item[0], - ...{ - next: next[0]?.id ?? null, - prev: prev[0]?.id ?? null - } + ...actitem, + next: next[0]?.id ?? null, + prev: prev[0]?.id ?? null }; return res.json({