Skip to content
Open
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
89 changes: 31 additions & 58 deletions controllers/history.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,35 +16,7 @@ import { _contextid, ObjectID, createExpressError, getAgentClaim, parseDocumentI
* @throws java.lang.Exception
* @respond JSONArray to the response out for parsing by the client application.
*/
const since = async function (req, res, next) {
res.set("Content-Type", "application/json; charset=utf-8")
let id = req.params["_id"]
let obj
try {
obj = await db.findOne({"$or":[{"_id": id}, {"__rerum.slug": id}]})
} catch (error) {
next(createExpressError(error))
return
}
if (null === obj) {
let err = {
message: `Cannot produce a history. There is no object in the database with id '${id}'. Check the URL.`,
status: 404
}
next(createExpressError(err))
return
}
let all = await getAllVersions(obj)
.catch(error => {
console.error(error)
return []
})
let descendants = getAllDescendants(all, obj, [])
descendants =
descendants.map(o => idNegotiation(o))
res.set(configureLDHeadersFor(descendants))
res.json(descendants)
}
const since = (req, res, next) => getVersionHistory(req, res, next, getAllDescendants)

/**
* Public facing servlet action to find all upstream versions of an object. This is the action the user hits with the API.
Expand All @@ -53,35 +25,7 @@ const since = async function (req, res, next) {
* @respond JSONArray to the response out for parsing by the client application.
* @throws Exception
*/
const history = async function (req, res, next) {
res.set("Content-Type", "application/json; charset=utf-8")
let id = req.params["_id"]
let obj
try {
obj = await db.findOne({"$or":[{"_id": id}, {"__rerum.slug": id}]})
} catch (error) {
next(createExpressError(error))
return
}
if (null === obj) {
let err = {
message: `Cannot produce a history. There is no object in the database with id '${id}'. Check the URL.`,
status: 404
}
next(createExpressError(err))
return
}
let all = await getAllVersions(obj)
.catch(error => {
console.error(error)
return []
})
let ancestors = getAllAncestors(all, obj, [])
ancestors =
ancestors.map(o => idNegotiation(o))
res.set(configureLDHeadersFor(ancestors))
res.json(ancestors)
}
const history = (req, res, next) => getVersionHistory(req, res, next, getAllAncestors)

/**
* Allow for HEAD requests by @id via the RERUM getByID pattern /v1/id/
Expand Down Expand Up @@ -210,4 +154,33 @@ const historyHeadRequest = async function (req, res, next) {
res.sendStatus(200)
}

const getVersionHistory = async (req, res, next, versionGetter) => {
res.set("Content-Type", "application/json; charset=utf-8")
let id = req.params["_id"]
let obj
try {
obj = await db.findOne({"$or":[{"_id": id}, {"__rerum.slug": id}]})
} catch (error) {
next(createExpressError(error))
return
}
if (null === obj) {
let err = {
message: `Cannot produce a history. There is no object in the database with id '${id}'. Check the URL.`,
status: 404
}
next(createExpressError(err))
return
}
let all = await getAllVersions(obj)
.catch(error => {
console.error(error)
return []
})
let versions = versionGetter(all, obj, [])
versions = versions.map(o => idNegotiation(o))
res.set(configureLDHeadersFor(versions))
res.json(versions)
}

export { since, history, idHeadRequest, queryHeadRequest, sinceHeadRequest, historyHeadRequest }
12 changes: 10 additions & 2 deletions routes/__tests__/history.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,22 @@ import { jest } from "@jest/globals"
// Only real way to test an express route is to mount it and call it so that we can use the req, res, next.
import express from "express"
import request from "supertest"
import rateLimit from "express-rate-limit"
import controller from '../../db-controller.js'

const routeTester = new express()
routeTester.use(express.json())
routeTester.use(express.urlencoded({ extended: false }))

const historyLimiter = rateLimit({
windowMs: 60 * 1000,
max: 100,
standardHeaders: true,
legacyHeaders: false
})

// Mount our own /history route without auth that will use controller.history
routeTester.use("/history/:_id", controller.history)
routeTester.get("/history/:_id", historyLimiter, controller.history)

it("'/history/:id' route functions", async () => {

Expand All @@ -27,4 +35,4 @@ it("'/history/:id' route functions", async () => {
expect(response.headers["allow"]).toBeTruthy()
expect(response.headers["link"]).toBeTruthy()
expect(Array.isArray(response.body)).toBe(true)
})
})
13 changes: 11 additions & 2 deletions routes/__tests__/since.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,30 @@ import { jest } from "@jest/globals"
// Only real way to test an express route is to mount it and call it so that we can use the req, res, next.
import express from "express"
import request from "supertest"
import rateLimit from "express-rate-limit"
import controller from '../../db-controller.js'

const routeTester = new express()
routeTester.use(express.json())
routeTester.use(express.urlencoded({ extended: false }))

// Mount our own /create route without auth that will use controller.history
routeTester.use("/since/:_id", controller.since)
const sinceLimiter = rateLimit({
windowMs: 60 * 1000,
max: 100,
standardHeaders: true,
legacyHeaders: false
})

// Mount our own /since route without auth that will use controller.since
routeTester.get("/since/:_id", sinceLimiter, controller.since)

it("'/since/:id' route functions", async () => {
const response = await request(routeTester)
.get("/since/11111")
.set("Content-Type", "application/json")
.then(resp => resp)
.catch(err => err)

expect(response.statusCode).toBe(200)
expect(response.headers["content-length"]).toBeTruthy()
expect(response.headers["content-type"]).toBeTruthy()
Expand Down
13 changes: 11 additions & 2 deletions routes/history.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import express from 'express'
import rateLimit from 'express-rate-limit'

const router = express.Router()
//This controller will handle all MongoDB interactions.
import controller from '../db-controller.js'

const historyLimiter = rateLimit({
windowMs: 60 * 1000,
max: 100,
standardHeaders: true,
legacyHeaders: false
})

router.route('/:_id')
.get(controller.history)
.head(controller.historyHeadRequest)
.get(historyLimiter, controller.history)
.head(historyLimiter, controller.historyHeadRequest)
.all((req, res, next) => {
res.statusMessage = 'Improper request method, please use GET.'
res.status(405)
Expand Down
15 changes: 12 additions & 3 deletions routes/since.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
import express from 'express'
import rateLimit from 'express-rate-limit'

const router = express.Router()
//This controller will handle all MongoDB interactions.
import controller from '../db-controller.js'

const sinceLimiter = rateLimit({
windowMs: 60 * 1000,
max: 100,
standardHeaders: true,
legacyHeaders: false
})

router.route('/:_id')
.get(controller.since)
.head(controller.sinceHeadRequest)
.get(sinceLimiter, controller.since)
.head(sinceLimiter, controller.sinceHeadRequest)
.all((req, res, next) => {
res.statusMessage = 'Improper request method, please use GET.'
res.status(405)
next(res)
})

export default router
export default router
Loading