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
48 changes: 24 additions & 24 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ npm start # Start server (http://loc
```bash
npm run runtest # Run full test suite (25+ minutes, requires MongoDB)
npm run runtest -- __tests__/routes_mounted.test.js # Run route mounting tests (30 seconds, no DB needed)
npm run runtest -- routes/__tests__/create.test.js # Run specific test file
npm run runtest -- src/routes/__tests__/create.test.js # Run specific test file
```

**Important:** Use `npm run runtest` (not `npm test`) as it enables experimental VM modules required for ES6 imports in Jest.
Expand All @@ -60,27 +60,27 @@ curl -X POST http://localhost:3001/v1/api/query -H "Content-Type: application/js
The application follows a **layered architecture** with clear separation of concerns:

```
app.js (Express setup, middleware)
src/index.js (Express app setup, middleware)
routes/api-routes.js (route mounting & definitions)
src/routes/api-routes.js (route mounting & definitions)
routes/*.js (individual route handlers with JWT auth)
src/routes/*.js (individual route handlers with JWT auth)
db-controller.js (controller aggregator)
src/routes/db-controller.js (controller aggregator)
controllers/*.js (business logic modules)
src/controllers/*.js (business logic modules)
database/index.js (MongoDB connection & operations)
src/db/index.js (MongoDB connection & operations)
```

### Key Architectural Components

**1. Request Flow:**
- Client → Express middleware (CORS, logging, body parsing)
- → Auth middleware (JWT validation via Auth0)
- → Route handlers (routes/*.js)
- → Controllers (controllers/*.js with business logic)
- → Database operations (MongoDB via database/index.js)
- → Auth middleware (JWT validation via Auth0, src/auth/index.js)
- → Route handlers (src/routes/*.js)
- → Controllers (src/controllers/*.js with business logic)
- → Database operations (MongoDB via src/db/index.js)
- → Response with proper Linked Data HTTP headers

**2. Versioning System:**
Expand All @@ -92,8 +92,8 @@ database/index.js (MongoDB connection & operations)
- Released objects are immutable (isReleased !== "")

**3. Controllers Organization:**
The `db-controller.js` is a facade that imports from specialized controller modules:
- `controllers/crud.js`: Core create, query, id operations
The `src/routes/db-controller.js` is a facade that imports from specialized controller modules in `src/controllers/`:
- `controllers/crud.js`: Core create, query, id operations (id() delegates to src/services/crudService.js)
- `controllers/update.js`: PUT/PATCH update operations (putUpdate, patchUpdate, patchSet, patchUnset, overwrite)
- `controllers/delete.js`: Delete operations
- `controllers/history.js`: Version history and since queries, HEAD request handlers
Expand All @@ -105,7 +105,7 @@ The `db-controller.js` is a facade that imports from specialized controller modu

**4. Authentication & Authorization:**
- **Provider:** Auth0 JWT bearer tokens
- **Middleware:** `auth/index.js` with express-oauth2-jwt-bearer
- **Middleware:** `src/auth/index.js` with express-oauth2-jwt-bearer
- **Flow:** checkJwt array includes READONLY check, Auth0 validation, token error handling, user extraction
- **Agent Matching:** Write operations verify `req.user` matches `__rerum.generatedBy`
- **Bot Access:** Special bot tokens (BOT_TOKEN, BOT_AGENT) bypass some checks
Expand All @@ -119,16 +119,16 @@ The `db-controller.js` is a facade that imports from specialized controller modu
### Directory Structure

```
/bin/ Entry point (rerum_v1.js creates HTTP server)
/routes/ Route handlers (one file per endpoint typically)
/controllers/ Business logic organized by domain
/auth/ Authentication middleware and token handling
/database/ MongoDB connection and utilities
/bin/ Entry point (rerum_v1.js creates HTTP server, imports src/index.js)
/src/
index.js Express app setup and middleware configuration
routes/ Route handlers (api-routes.js, home.js, id.js, create.js, etc.)
controllers/ Business logic organized by domain
auth/ Authentication middleware and token handling (Auth0 JWT)
db/ MongoDB connection and utilities
services/ Business/service layer (e.g. crudService.js for id-by-id logic)
utils/ Core utilities (__rerum configuration, header generation), rest.js
/public/ Static files (API.html docs, context.json)
/utils.js Core utilities (__rerum configuration, header generation)
/rest.js REST error handling and messaging
/app.js Express app setup and middleware configuration
/db-controller.js Controller facade exporting all operations
```

## Important Patterns and Conventions
Expand Down Expand Up @@ -205,7 +205,7 @@ BOT_AGENT=your-bot-agent-url
## Testing Notes

- **Route tests** (`__tests__/routes_mounted.test.js`): Work without MongoDB, verify routing and static files
- **Controller tests** (`routes/__tests__/*.test.js`): Require MongoDB connection or will timeout after 5 seconds
- **Controller tests** (`src/routes/__tests__/*.test.js`): Require MongoDB connection or will timeout after 5 seconds
- Tests use experimental VM modules, hence `npm run runtest` instead of `npm test`
- "Jest did not exit" warnings are normal—tests complete successfully despite this
- Most tests expect Auth0 to be configured; mock tokens are used in test environment
Expand Down
4 changes: 2 additions & 2 deletions __tests__/routes_mounted.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
*/

import request from "supertest"
import api_routes from "../routes/api-routes.js"
import app from "../app.js"
import api_routes from "../src/routes/api-routes.js"
import app from "../src/index.js"
import fs from "fs"

let app_stack = app.router.stack
Expand Down
2 changes: 1 addition & 1 deletion bin/rerum_v1.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Module dependencies.
*/

import app from '../app.js'
import app from '../src/index.js'
import debug from 'debug'
debug('rerum_server_nodejs:server')
import http from "http"
Expand Down
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const config = {
collectCoverageFrom: [
//"**/*.js",
"**/db-controller.js",
"**/routes/*.js"
"**/services/*.js"
],

// Indicates which provider should be used to instrument code for coverage
Expand Down
9 changes: 0 additions & 9 deletions routes/index.js

This file was deleted.

File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* If that is what you need, get out of here and go see /auth/__mocks__
*/

import auth from "../../auth/index.js"
import auth from "../index.js"
import httpMocks from "node-mocks-http"

const goodToken = "TODO -- MAKE ME PROGRAMMATICALLY"
Expand Down
File renamed without changes.
9 changes: 9 additions & 0 deletions src/config/__mocks__/index.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
It would be extremely useful to mock Auth0 JWT stuff.
We will need to do some manual mocking to make these functions return the expected responses.
Remember we are using ES6 now, so ignore documentation for other syntaxes.
See https://jestjs.io/docs/es6-class-mocks#manual-mock
See https://jestjs.io/docs/es6-class-mocks#manual-mock-that-is-another-es6-class

Remember that responses are Auth0 Responses and would need to be shaped as such.
See https://zhifei-dev.medium.com/express-typescript-properly-mocking-jwt-verify-in-unit-test-b2dfd2e33
See https://www.npmjs.com/package/oauth2-mock-server
56 changes: 56 additions & 0 deletions src/config/__tests__/token.test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**
* Use this to perform end to end interactions with Auth0 TPEN3 Application.
* The app passes NodeJS Express Request and Response objects which have Bearer Tokens in their headers.
* Those Bearer tokens are pulled from the Request 'Authorization' header.
* The app should be able to verify the token is legitimate and gleam a TPEN3 user from it
*
* Note that in this test we are performing real Auth0 communication.
* There are areas of the app that could benefit from having this communication exist as a mock.
* If that is what you need, get out of here and go see /auth/__mocks__
*/

import auth from "../index.js"
import httpMocks from "node-mocks-http"

const goodToken = "TODO -- MAKE ME PROGRAMMATICALLY"

// A mocked HTTP POST 'create' request with an Authorization header. The token should be a valid one.
const mockRequest_with_token = httpMocks.createRequest({
method: 'POST',
url: '/create',
body: {
hello: 'world'
},
headers: {
"Authorization" : `Bearer ${goodToken}`
}
})

// A mocked HTTP POST 'create' request without an Authorization header (no Bearer token)
const mockRequest_without_token = httpMocks.createRequest({
method: 'POST',
url: '/create',
body: {
hello: 'world'
}
})

// A mocked HTTP response stub
const mockResponse = httpMocks.createResponse()

// A mocked express next() call
const nextFunction = jest.fn()

// REDO
describe('Auth0 Interactions',()=>{

it('reject empty request without headers (INCOMPLETE)',async ()=>{
const resp = await auth.checkJwt[0](mockRequest_without_token,mockResponse,nextFunction)
expect(resp).toBe("token error")
})

it('with "authorization" header (INCOMPLETE)', async () => {
const resp = await auth.checkJwt[0](mockRequest_with_token,mockResponse,nextFunction)
expect(resp).toBe("valid token")
})
})
Loading