Skip to content
Merged
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
45 changes: 31 additions & 14 deletions controllers/gog.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ import { newID, isValidID, db } from '../database/index.js'
import utils from '../utils.js'
import { _contextid, ObjectID, getAgentClaim, getPagination, parseDocumentID, idNegotiation } from './utils.js'

// The Gallery of Glosses agents, by RERUM ObjectId. Prod (store) and dev (devstore) mint different
// agents; only the trailing id is compared, so either host spelling matches.
const GOG_PROD_AGENT = "61043ad4ffce846a83e700dd"
const GOG_DEV_AGENT = "5afeebf3e4b0b0d588705d90"
const GOG_AGENTS = [GOG_PROD_AGENT, GOG_DEV_AGENT]

/**
* THIS IS SPECIFICALLY FOR 'Gallery of Glosses'
* Starting from a ManuscriptWitness URI get all WitnessFragment entities that are a part of the Manuscript.
Expand All @@ -30,7 +36,7 @@ const _gog_fragments_from_manuscript = async function (req, res, next) {
const { limit, skip } = getPagination(req.query, 50)
let err = { message: `` }
// This request can only be made my Gallery of Glosses production apps.
if (agentID !== "61043ad4ffce846a83e700dd") {
if (agentID !== GOG_PROD_AGENT) {
err = Object.assign(err, {
message: `Only the Gallery of Glosses can make this request.`,
status: 403
Expand Down Expand Up @@ -161,7 +167,7 @@ const _gog_glosses_from_manuscript = async function (req, res, next) {
const { limit, skip } = getPagination(req.query, 50)
let err = { message: `` }
// This request can only be made my Gallery of Glosses production apps.
if (agentID !== "61043ad4ffce846a83e700dd") {
if (agentID !== GOG_PROD_AGENT) {
err = Object.assign(err, {
message: `Only the Gallery of Glosses can make this request.`,
status: 403
Expand Down Expand Up @@ -303,7 +309,7 @@ const _gog_glosses_from_manuscript = async function (req, res, next) {
}

/**
* Find relevant Annotations targeting a primitive RERUM entity. This is a 'full' expand.
* Find relevant Annotations targeting a primitive RERUM entity. This is a 'full' expand.
* Add the descriptive information in the Annotation bodies to the primitive object.
*
* Anticipate likely Annotation body formats
Expand All @@ -322,16 +328,19 @@ const _gog_glosses_from_manuscript = async function (req, res, next) {
*
* @param primitiveEntity - An existing RERUM object
* @param GENERATOR - A registered RERUM app's User Agent
* @param CREATOR - Some kind of string representing a specific user. Often combined with GENERATOR.
* @param CREATOR - Some kind of string representing a specific user. Often combined with GENERATOR.
* @return the expanded entity object
*
*/
const expand = async function(primitiveEntity, GENERATOR=undefined, CREATOR=undefined){
// An entity is expandable if it carries a URI under either '@id' or 'id'.
if(!primitiveEntity?.["@id"] && !primitiveEntity?.id) return primitiveEntity
const targetId = primitiveEntity["@id"] ?? primitiveEntity.id ?? "unknown"
// '$and' is always present so the GENERATOR and CREATOR blocks below can push into it from
// either branch. 'annoTypeConditions' is always pushed, so it is never the empty Array Mongo rejects.
let queryObj = {
"__rerum.history.next": { $exists: true, $size: 0 }
"__rerum.history.next": { $exists: true, $size: 0 },
"$and": []
}
let targetPatterns = ["target", "target.@id", "target.id"]
let targetConditions = []
Expand All @@ -342,10 +351,10 @@ const expand = async function(primitiveEntity, GENERATOR=undefined, CREATOR=unde
targetConditions.push({ [targetKey]: targetId.replace(/^https?/, "http") })
targetConditions.push({ [targetKey]: targetId.replace(/^https?/, "https") })
}
queryObj["$and"] = [{"$or": targetConditions}, {"$or": annoTypeConditions}]
}
queryObj["$and"].push({"$or": targetConditions}, {"$or": annoTypeConditions})
}
else{
queryObj["$or"] = annoTypeConditions
queryObj["$and"].push({"$or": annoTypeConditions})
queryObj.target = targetId
}

Expand All @@ -358,7 +367,7 @@ const expand = async function(primitiveEntity, GENERATOR=undefined, CREATOR=unde
]
if (GENERATOR.startsWith("http")) {
queryObj["$and"].push({"$or": generatorConditions })
}
}
else{
// It should be a URI, but this can be a fallback.
queryObj["__rerum.generatedBy"] = GENERATOR
Expand All @@ -373,7 +382,7 @@ const expand = async function(primitiveEntity, GENERATOR=undefined, CREATOR=unde
]
if (CREATOR.startsWith("http")) {
queryObj["$and"].push({"$or": creatorConditions })
}
}
else{
// It should be a URI, but this can be a fallback.
queryObj["creator"] = CREATOR
Expand Down Expand Up @@ -429,10 +438,20 @@ const expand = async function(primitiveEntity, GENERATOR=undefined, CREATOR=unde
const expandedId = async function (req, res, next) {
res.set("Content-Type", "application/json; charset=utf-8")
const id = req.params["_id"]
let err = { message: `` }
try {
let match = await db.findOne({ "$or": [{ "_id": id }, { "__rerum.slug": id }] })
if (!match) {
const err = { "message": `No RERUM object with id '${id}'`, "status": 404 }
err = Object.assign(err, { message: `No RERUM object with id '${id}'`, status: 404 })
return next(utils.createExpressError(err))
}
const generator = match.__rerum?.generatedBy
const agentID = generator?.split("/").pop()
if (!GOG_AGENTS.includes(agentID)) {
err = Object.assign(err, {
message: `This request can only be made for Gallery of Glosses generated data.`,
status: 403
})
return next(utils.createExpressError(err))
}
// Same browser-caching policy as GET /v1/id/:_id so this stable URI is cached (24h).
Expand All @@ -441,9 +460,7 @@ const expandedId = async function (req, res, next) {
// No Last-Modified here, unlike GET /v1/id/:_id. It would compare against the root entity
// before expand() merges the targeting Annotations.
res.set("Current-Overwritten-Version", match.__rerum?.isOverwritten ?? "")
// No GENERATOR/CREATOR filter: merge every current targeting Annotation, matching the
// client's historical expand() behavior (its checkMatch is short-circuited to true).
let expanded = await expand(match)
let expanded = await expand(match, generator)
expanded = idNegotiation(expanded)
res.location(_contextid(expanded["@context"]) ? expanded.id : expanded["@id"])
res.json(expanded)
Expand Down
Loading