From 406ca03736106884ceabb51112ab31389d1e895b Mon Sep 17 00:00:00 2001 From: Karen Shaw Date: Mon, 30 Jan 2023 22:23:59 +0000 Subject: [PATCH] Private collections should be visible from reading room --- src/handlers/get-collection-by-id.js | 11 ++- .../collection-1234-private-published.json | 17 +++++ test/integration/get-collection-by-id.test.js | 76 +++++++++++++++++++ 3 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 test/fixtures/mocks/collection-1234-private-published.json diff --git a/src/handlers/get-collection-by-id.js b/src/handlers/get-collection-by-id.js index a96b1a91..225f6430 100644 --- a/src/handlers/get-collection-by-id.js +++ b/src/handlers/get-collection-by-id.js @@ -3,15 +3,22 @@ const { getCollection } = require("../api/opensearch"); const { doSearch } = require("./search-runner"); const opensearchResponse = require("../api/response/opensearch"); +const getOpts = (event) => { + const allowPrivate = + event.userToken.isReadingRoom() || event.userToken.hasEntitlement(id); + const allowUnpublished = event.userToken.hasEntitlement(id); + return { allowPrivate, allowUnpublished }; +}; + const getCollectionById = async (event) => { const id = event.pathParameters.id; - const esResponse = await getCollection(id); + const esResponse = await getCollection(id, getOpts(event)); return await opensearchResponse.transform(esResponse); }; const getIiifCollectionById = async (event) => { const id = event.pathParameters.id; - const esResponse = await getCollection(id); + const esResponse = await getCollection(id, getOpts(event)); const collection = JSON.parse(esResponse.body)?._source; if (!collection) return { statusCode: 404, body: "Not Found" }; const parameterOverrides = { ...event.queryStringParameters }; diff --git a/test/fixtures/mocks/collection-1234-private-published.json b/test/fixtures/mocks/collection-1234-private-published.json new file mode 100644 index 00000000..cdfa4812 --- /dev/null +++ b/test/fixtures/mocks/collection-1234-private-published.json @@ -0,0 +1,17 @@ +{ + "_index": "dev-dc-v2-collection", + "_type": "_doc", + "_id": "1234", + "_version": 1, + "found": true, + "_source": { + "id": "1234", + "title": "Collection Title", + "api_model": "Collection", + "published": true, + "visibility": "Private", + "representative_image": { + "work_id": "1234" + } + } +} \ No newline at end of file diff --git a/test/integration/get-collection-by-id.test.js b/test/integration/get-collection-by-id.test.js index d90fcfc0..0559954b 100644 --- a/test/integration/get-collection-by-id.test.js +++ b/test/integration/get-collection-by-id.test.js @@ -11,6 +11,10 @@ describe("Retrieve collection by id", () => { const mock = helpers.mockIndex(); describe("GET /collections/{id}", () => { + beforeEach(() => { + process.env.READING_ROOM_IPS = ""; + }); + const { handler } = requireSource("handlers/get-collection-by-id"); it("retrieves a single collection link document", async () => { @@ -46,6 +50,41 @@ describe("Retrieve collection by id", () => { expect(result.statusCode).to.eq(404); }); + it("404's if the collection is private", async () => { + mock + .get("/dc-v2-collection/_doc/1234") + .reply( + 200, + helpers.testFixture("mocks/collection-1234-private-published.json") + ); + + const event = helpers + .mockEvent("GET", "/collections/{id}") + .pathParams({ id: 1234 }) + .render(); + + const result = await handler(event); + expect(result.statusCode).to.eq(404); + }); + + it("200's if the collection is private but the user is in the reading room", async () => { + mock + .get("/dc-v2-collection/_doc/1234") + .reply( + 200, + helpers.testFixture("mocks/collection-1234-private-published.json") + ); + + const event = helpers + .mockEvent("GET", "/collections/{id}") + .pathParams({ id: 1234 }) + .render(); + + process.env.READING_ROOM_IPS = event.requestContext.http.sourceIp; + const result = await handler(event); + expect(result.statusCode).to.eq(200); + }); + it("returns a single collection as a IIIF collection", async () => { const originalQuery = { query: { query_string: { query: "collection.id:1234" } }, @@ -86,5 +125,42 @@ describe("Retrieve collection by id", () => { expect(result.statusCode).to.eq(301); expect(result).to.have.header("location", "/collections"); }); + + it("returns a IIIF collection if the user is in the reading room", async () => { + const originalQuery = { + query: { query_string: { query: "collection.id:1234" } }, + }; + const authQuery = new RequestPipeline(originalQuery) + .authFilter(helpers.preprocess({})) + .toJson(); + + mock + .get("/dc-v2-collection/_doc/1234") + .reply( + 200, + helpers.testFixture("mocks/collection-1234-private-published.json") + ); + mock + .post("/dc-v2-work/_search", authQuery) + .reply(200, helpers.testFixture("mocks/search.json")); + + const event = helpers + .mockEvent("GET", "/collections/{id}") + .pathParams({ id: 1234 }) + .queryParams({ as: "iiif" }) + .render(); + + process.env.READING_ROOM_IPS = event.requestContext.http.sourceIp; + + const result = await handler(event); + expect(result.statusCode).to.eq(200); + expect(result).to.have.header( + "content-type", + /application\/json;.*charset=UTF-8/ + ); + const resultBody = JSON.parse(result.body); + expect(resultBody.type).to.eq("Collection"); + expect(resultBody.label.none[0]).to.eq("Collection Title"); + }); }); });