openvibers/openvibe.deals Commits
API: a moderator-removed deal answers 410 like its page instead of serving its title, description and link; moderators still read it
Changes
@@@ -69,7 +69,15 @@ function createApi(ctx) {return { sort: req.query.sort === 'new' ? 'new' : 'hot', page, total: listings.countActive(), offers: rows.map((o) => publication.offerDto(publication.offerView(o))) };}));-- router.get('/offers/:id', run((req) => offerOut(reads.mustFind(req.params.id))));++ // A removed deal answers like its page (410, reason only); moderators still read the whole record.++ router.get('/offers/:id', run((req) => {++ const offer = reads.mustFind(req.params.id);++ const root = reads.root(offer);++ if (root.status === 'disabled' && !access.isModerator(req.viewer)) {++ throw new ApiError(410, 'offer.disabled', 'This deal was removed by moderators', { id: root.id, slug: root.slug, status: 'disabled', reason: root.disabled_reason });++ }++ return offerOut(offer);++ }));router.get('/offers/:id/hotness', run((req) => {const root = reads.root(reads.mustFind(req.params.id));@@@ -129,6 +129,12 @@ const { boot, check, done, robotsOf, jsonLd, HOUR } = require('./helpers/boot');assert.strictEqual(thread.visibility, 'hidden', 'the disabled deal\'s discussion is hidden too');assert.strictEqual((await t.get(`/d/${target.slug}`)).status, 410);assert.strictEqual((await t.get(`/d/${target.slug}.json`)).status, 410);++ for (const id of [target.id, target.slug]) {++ const api = await t.get(`/api/v1/offers/${id}`);++ assert.strictEqual(api.status, 410, 'the API does not serve a removed deal either');++ assert.ok(!api.text.includes('Drone Pro'), 'no title, description or link of a removed deal');++ }++ assert.strictEqual((await t.get(`/api/v1/offers/${target.id}`, { as: t.mod })).status, 200, 'moderators still read it');assert.ok(!(await t.get('/feed.xml')).text.includes(target.slug));assert.ok(t.events('deals.index_document.deleted').some((e) => e.payload.id === target.id));const en = await t.get(`/mod/offers/${target.slug}/enable`, { as: t.mod, form: {} });
@@ -69,7 +69,15 @@ function createApi(ctx) {
@@ -69,7 +69,15 @@ function createApi(ctx) {
return { sort: req.query.sort === 'new' ? 'new' : 'hot', page, total: listings.countActive(), offers: rows.map((o) => publication.offerDto(publication.offerView(o))) };
return { sort: req.query.sort === 'new' ? 'new' : 'hot', page, total: listings.countActive(), offers: rows.map((o) => publication.offerDto(publication.offerView(o))) };
}));
}));
- router.get('/offers/:id', run((req) => offerOut(reads.mustFind(req.params.id))));
+ // A removed deal answers like its page (410, reason only); moderators still read the whole record.
+ router.get('/offers/:id', run((req) => {
+ const offer = reads.mustFind(req.params.id);
+ const root = reads.root(offer);
+ if (root.status === 'disabled' && !access.isModerator(req.viewer)) {
+ throw new ApiError(410, 'offer.disabled', 'This deal was removed by moderators', { id: root.id, slug: root.slug, status: 'disabled', reason: root.disabled_reason });
+ }
+ return offerOut(offer);
+ }));
router.get('/offers/:id/hotness', run((req) => {
router.get('/offers/:id/hotness', run((req) => {
const root = reads.root(reads.mustFind(req.params.id));
const root = reads.root(reads.mustFind(req.params.id));
@@ -129,6 +129,12 @@ const { boot, check, done, robotsOf, jsonLd, HOUR } = require('./helpers/boot');
@@ -129,6 +129,12 @@ const { boot, check, done, robotsOf, jsonLd, HOUR } = require('./helpers/boot');
assert.strictEqual(thread.visibility, 'hidden', 'the disabled deal\'s discussion is hidden too');
assert.strictEqual(thread.visibility, 'hidden', 'the disabled deal\'s discussion is hidden too');
assert.strictEqual((await t.get(`/d/${target.slug}`)).status, 410);
assert.strictEqual((await t.get(`/d/${target.slug}`)).status, 410);
assert.strictEqual((await t.get(`/d/${target.slug}.json`)).status, 410);
assert.strictEqual((await t.get(`/d/${target.slug}.json`)).status, 410);
+ for (const id of [target.id, target.slug]) {
+ const api = await t.get(`/api/v1/offers/${id}`);
+ assert.strictEqual(api.status, 410, 'the API does not serve a removed deal either');
+ assert.ok(!api.text.includes('Drone Pro'), 'no title, description or link of a removed deal');
+ }
+ assert.strictEqual((await t.get(`/api/v1/offers/${target.id}`, { as: t.mod })).status, 200, 'moderators still read it');
assert.ok(!(await t.get('/feed.xml')).text.includes(target.slug));
assert.ok(!(await t.get('/feed.xml')).text.includes(target.slug));
assert.ok(t.events('deals.index_document.deleted').some((e) => e.payload.id === target.id));
assert.ok(t.events('deals.index_document.deleted').some((e) => e.payload.id === target.id));
const en = await t.get(`/mod/offers/${target.slug}/enable`, { as: t.mod, form: {} });
const en = await t.get(`/mod/offers/${target.slug}/enable`, { as: t.mod, form: {} });