Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions api/dependencies/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion api/dependencies/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dc-api-dependencies",
"version": "2.9.3",
"version": "2.9.4",
"description": "NUL Digital Collections API Dependencies",
"repository": "https://github.com/nulib/dc-api-v2",
"author": "nulib",
Expand Down
4 changes: 2 additions & 2 deletions api/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion api/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dc-api-build",
"version": "2.9.3",
"version": "2.9.4",
"description": "NUL Digital Collections API Build Environment",
"repository": "https://github.com/nulib/dc-api-v2",
"author": "nulib",
Expand Down
104 changes: 80 additions & 24 deletions api/src/api/request/pipeline.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,57 @@
const sortJson = require("sort-json");
const { defaultSearchSize } = require("../../environment");

function filterFor(query, event) {
const matchTheQuery = query;
const beUnpublished = { term: { published: false } };
const beRestricted = { term: { visibility: "Private" } };
function filterFor(event) {
const publishedValues = event.userToken.can("read:Unpublished")
? [true, false]
: [true];
const userVisibility = new Set(
event.userToken.can("read:Private")
? ["Private", "Institution", "Public"]
: ["Institution", "Public"]
);
const requestVisibility = event?.queryStringParameters?.visibility
?.split(",")
?.map((v) => v[0].toUpperCase() + v.slice(1)) || [
"Private",
"Institution",
"Public",
];
const visibilityValues = requestVisibility.filter((v) =>
userVisibility.has(v)
);

let filter = { must: [matchTheQuery], must_not: [] };

if (!event.userToken.can("read:Unpublished")) {
filter.must_not.push(beUnpublished);
}
return [
{ terms: { published: publishedValues } },
{ terms: { visibility: visibilityValues } },
];
}

if (!event.userToken.can("read:Private")) {
filter.must_not.push(beRestricted);
function addFilter(query, filter) {
let result = { ...query };
if (result.bool) {
result.bool.filter ||= [];
result.bool.filter.push(...filter);
} else if (result.neural) {
const boolFilter = { bool: { filter: filter } };
if (result.neural.filter) {
boolFilter.bool.filter.push(result.neural.filter);
}
const neuralField = Object.keys(result.neural)[0];
result.neural[neuralField].filter = boolFilter;
} else if (result.hybrid) {
result.hybrid.queries = result.hybrid.queries.map((subQuery) =>
addFilter(subQuery, filter)
);
} else {
result = {
bool: {
must: [result],
filter: filter,
},
};
}

return { bool: filter };
return result;
}

module.exports = class RequestPipeline {
Expand All @@ -33,23 +68,44 @@ module.exports = class RequestPipeline {
// - Add `track_total_hits` to search context (so we can get accurate hits.total.value)

authFilter(event) {
if (this.searchContext.query?.hybrid?.queries) {
this.searchContext.query = {
hybrid: {
queries: this.searchContext.query.hybrid.queries.map((query) =>
filterFor(query, event)
),
},
};
} else {
this.searchContext.query = filterFor(this.searchContext.query, event);
}
this.searchContext.query = addFilter(
this.searchContext.query,
filterFor(event)
);
this.searchContext.track_total_hits = true;
return this;
}

addNeuralModelId() {
const neuralModelId = process.env.OPENSEARCH_MODEL_ID;
if (!neuralModelId) return this;

const recursivelyAddNeuralModelId = (query) => {
if (Array.isArray(query)) {
for (const subQuery of query) {
recursivelyAddNeuralModelId(subQuery);
}
}

if (typeof query !== "object" || query === null) return this;

for (const key in query) {
if (key === "neural") {
const [field] = Object.keys(query.neural);
query.neural[field].model_id ||= neuralModelId;
} else {
recursivelyAddNeuralModelId(query[key]);
}
}
};

recursivelyAddNeuralModelId(this.searchContext.query);

return this;
}

toJson() {
this.addNeuralModelId();
return JSON.stringify(sortJson(this.searchContext));
}
};
1 change: 1 addition & 0 deletions api/src/handlers/get-collection-by-id.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const getIiifCollectionById = async (event) => {
return await doSearch(event, {
includeToken: false,
parameterOverrides,
defaultSort: [{ accession_number: "asc" }],
});
};

Expand Down
4 changes: 4 additions & 0 deletions api/src/handlers/search-runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ const doSearch = async (event, searchParams = {}) => {
return invalidRequest(error.message);
}

if (!searchContext.sort && searchParams.defaultSort) {
searchContext.sort = searchParams.defaultSort;
}

if (!validModels(models, format)) {
return invalidRequest(`Invalid models requested: ${models}`);
}
Expand Down
4 changes: 2 additions & 2 deletions api/src/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion api/src/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dc-api",
"version": "2.9.3",
"version": "2.9.4",
"description": "NUL Digital Collections API",
"repository": "https://github.com/nulib/dc-api-v2",
"author": "nulib",
Expand Down
2 changes: 2 additions & 0 deletions api/test/integration/get-collection-by-id.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ describe("Retrieve collection by id", () => {
it("returns a single collection as a IIIF collection", async () => {
const originalQuery = {
query: { query_string: { query: "collection.id:1234" } },
sort: [{ accession_number: "asc" }],
};
const authQuery = new RequestPipeline(originalQuery)
.authFilter(helpers.preprocess({}))
Expand Down Expand Up @@ -141,6 +142,7 @@ describe("Retrieve collection by id", () => {

const originalQuery = {
query: { query_string: { query: "collection.id:1234" } },
sort: [{ accession_number: "asc" }],
};

let preProcessedEvent = helpers.preprocess(event);
Expand Down
Loading
Loading