Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
tpluscode committed Mar 29, 2024
1 parent 7d877ee commit be2cfa6
Show file tree
Hide file tree
Showing 112 changed files with 18,317 additions and 9,238 deletions.
2 changes: 1 addition & 1 deletion .lando.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ services:
- '47671:47671'
environment:
TS_NODE_TRANSPILE_ONLY: "true"
DEBUG: conduit*,hydra*,hydra-box*,labyrinth*,SPARQL,-labyrinth:request:headers
DEBUG: conduit*,hydra*,kopflos*,labyrinth*,SPARQL,-labyrinth:request:headers
AUTH_JWKS_URI: http://auth/keys
AUTH_ISSUER: https://auth.labyrinth.lndo.site
AUTH_AUDIENCE: conduit
Expand Down
11 changes: 5 additions & 6 deletions apps/conduit/lib/resource.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { acl, dash, owl, rdf, sh, vcard } from '@tpluscode/rdf-ns-builders'
import { BeforeSave } from '@hydrofoil/knossos/lib/resource'
import TermSet from '@rdfjs/term-set'
import { BeforeSave } from '@hydrofoil/knossos/lib/resource.js'
import type { Handler } from '@hydrofoil/knossos-events'
import { GraphPointer } from 'clownface'
import $rdf from 'rdf-ext'
import $rdf from '@zazuko/env-node'
import type { GraphPointer } from 'clownface'
import error from 'http-errors'

export const guardReadOnlyPredicates: BeforeSave = function ({ after, before, api }): void {
Expand All @@ -15,8 +14,8 @@ export const guardReadOnlyPredicates: BeforeSave = function ({ after, before, ap
.out(sh.path)

for (const prop of readOnlyProps.toArray()) {
const beforeTerms = new TermSet(before.out(prop).terms)
const afterTerms = [...new TermSet(after.out(prop).terms)]
const beforeTerms = $rdf.termSet(before.out(prop).terms)
const afterTerms = [...$rdf.termSet(after.out(prop).terms)]
if (afterTerms.some(term => !beforeTerms.has(term))) {
throw new error.BadRequest(`Cannot modify property ${prop.value}`)
}
Expand Down
17 changes: 9 additions & 8 deletions apps/conduit/middleware/authenticate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ import fetch from 'node-fetch'
import express, { Router } from 'express'
import { expressjwt as jwt, GetVerificationKey } from 'express-jwt'
import jwksRsa from 'jwks-rsa'
import clownface from 'clownface'
import $rdf from 'rdf-ext'
import $rdf from '@zazuko/env-node'
import asyncMiddleware from 'middleware-async'
import { DESCRIBE } from '@tpluscode/sparql-builder'
import { vcard } from '@tpluscode/rdf-ns-builders'
import type { StreamClient } from 'sparql-http-client/StreamClient'
import type StreamClient from 'sparql-http-client/StreamClient.js'
import { Authentication } from '@hydrofoil/knossos'

declare module 'express-serve-static-core' {
Expand All @@ -20,16 +19,17 @@ declare module 'express-serve-static-core' {

const setUser = (client: StreamClient): express.RequestHandler => async (req, res, next) => {
if (req.user?.sub) {
const userQuery = await DESCRIBE`?user`
const userQuery = DESCRIBE`?user`
.WHERE`?user ${vcard.hasUID} "${req.user.sub}"`
.execute(client.query)
.execute(client)
const dataset = await $rdf.dataset().import(userQuery)

const foundUser = clownface({ dataset })
const foundUser = $rdf.clownface({ dataset })
.has(vcard.hasUID, req.user.sub)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
.toArray()[0] as any

req.agent = foundUser || clownface({ dataset: $rdf.dataset() })
req.agent = foundUser || $rdf.clownface()
.namedNode(`urn:user:${req.user.sub}`)
.addOut(vcard.hasUID, req.user.sub)
}
Expand Down Expand Up @@ -67,7 +67,8 @@ const authentication: Authentication = async ({ client }: { client: StreamClient
const response = await fetch(`${process.env.AUTH_ISSUER}/.well-known/openid-configuration`)

if (response.ok) {
const oidcConfig = await response.json()
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const oidcConfig: any = await response.json()
return createJwtHandler(oidcConfig.jwks_uri, client)
}

Expand Down
16 changes: 7 additions & 9 deletions apps/conduit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "@hydrofoil/conduit",
"private": true,
"version": "0.1.55",
"type": "module",
"scripts": {
"resources": "../../packages/knossos/bin/knossos.ts init",
"bootstrap": "run-s bootstrap:*",
Expand All @@ -11,25 +12,22 @@
},
"dependencies": {
"@hydrofoil/knossos": "0.9.11",
"@hydrofoil/talos": "^0.5.1",
"@rdfjs/term-set": "^1.1.0",
"@tpluscode/rdf-ns-builders": "^2.0.0",
"@tpluscode/sparql-builder": "^0.3.23",
"clownface": "^1.5.1",
"@tpluscode/rdf-ns-builders": "^4.3.0",
"@tpluscode/sparql-builder": "^2.0.0",
"@zazuko/env-node": "^2.1.0",
"cors": "^2.8.5",
"express": "^4.18.1",
"express-jwt": "^7.7.0",
"http-errors": "^2.0.0",
"jwks-rsa": "^3.0.0",
"middleware-async": "^1.3.1",
"node-fetch": "^2.6.7",
"rdf-ext": "^1.3.5"
"node-fetch": "^3.3.2"
},
"devDependencies": {
"@hydrofoil/talos": "0.5.1",
"@hydrofoil/talos": "0.6.4",
"@types/express-unless": "^0.5.3",
"@types/jsonwebtoken": "^8.5.9",
"@types/node-fetch": "^2.5.12",
"@types/node-fetch": "^3.0.3",
"npm-run-all": "^4.1.5"
}
}
4 changes: 2 additions & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ The project consists of multiple components, which can be combined according to
> [!TIP]
> Named after the [mythical Cretan maze](https://www.wikidata.org/wiki/Q1091243), home of the [Minotaur](https://www.wikidata.org/wiki/Q129866)
Core server library, which is the foundation for express-based Hydra APIs. It builds upon [hydra-box](https://npm.im/hydra-box) by providing read-only capabilities using a convention-over-configuration approach and core error-handling functionality.
Core server library, which is the foundation for express-based Hydra APIs. It builds upon [@kopflos-cms/core](https://npm.im/@kopflos-cms/core) by providing read-only capabilities using a convention-over-configuration approach and core error-handling functionality.

The core piece missing from `labyrinth` is loading the actual contents of `hydra:ApiDocumentation` which drives client-server interactions. That is to keep the core agnostic of how the API's final functionality is deployed.

Expand All @@ -44,7 +44,7 @@ Other integrated features are:
* all-you-need write handlers for resources and `hydra:Collection` members,
* SHACL validation middleware,
* data-centric eventing via `@hydrofoil/knossos-events`,
* ACL via [hydra-box-web-access-control](https://npm.im/hydra-box-web-access-control)
* ACL via [hydra-web-access-control](https://npm.im/hydra-web-access-control)
* administrative system account access.

### @hydrofoil/minotaur
Expand Down
2 changes: 1 addition & 1 deletion docs/advanced/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ export const draftByDefault: ResourceHook = ({ req, pointer }) => {
### preprocessResource
Use `knossos:preprocessResource` to modify the representation of the current resource loaded by hydra-box.
Use `knossos:preprocessResource` to modify the representation of the current resource loaded by `@kopflos-cms/core`.
> [!WARNING]
> This hook will not modify responses. It should be used to alter the behaviour of the operation handler itself if it performs conditional logic based on stored resource representation.
Expand Down
6 changes: 3 additions & 3 deletions docs/knossos/auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@ import type { MiddlewareFactory } from '@hydrofoil/knossos/configuration'
import auth from 'basic-auth'
import compare from 'tsscmp'
import clownface from 'clownface'
import $rdf from 'rdf-ext'
import $rdf from '@zazuko/env'
import { foaf, rdf } from '@tpluscode/rdf-ns-builders'

const authentication: MiddlewareFactory = () => {
return (req, res, next) => {
const { name, pass } = auth(req)

if (compare(name, 'john') && compare(pass, 'super-secret')) {
req.agent = clownface({ dataset: $rdf.dataset() })
req.agent = $rdf.clownface()
.namedNode($rdf.namedNode(`http://example.com/user/${name}`))
.addOut(rdf.type, foaf.Person)
}
Expand All @@ -65,7 +65,7 @@ export default authentication

## Authorization

To authorize requests, `knossos` uses [Web Access Control](https://www.w3.org/wiki/WebAccessControl) spec via the package [hydra-box-web-access-control](https://npm.im/hydra-box-web-access-control).
To authorize requests, `knossos` uses [Web Access Control](https://www.w3.org/wiki/WebAccessControl) spec via the package [hydra-web-access-control](https://npm.im/hydra-web-access-control).

During request, the `req.agent`, if given, is combined with the identifier and RDF types of the requested resource to query the database for instances of `acl:Authorization`, which grant access.

Expand Down
2 changes: 1 addition & 1 deletion docs/knossos/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Options:
-p, --port <port> Port (default: 8888)
--api <api> Api Documentation path (default: "/api")
--base
--codePath <codePath> Code path for hydra-box (default: ".")
--codePath <codePath> Code path for @kopflos-cms/core (default: ".")
--updateUrl <updateUrl> SPARQL Update Endpoint URL
-n, --name <name> App name (default: "knossos")
--user <user> SPARQL username
Expand Down
2 changes: 1 addition & 1 deletion docs/knossos/collections.md
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ The hypothetical implementation of `lib/article` could cut the title and add a r

```typescript
import type { TransformVariable } from '@hydrofoil/knossos/collection'
import $rdf from 'rdf-ext'
import $rdf from '@zazuko/env'
import URLSlugify from 'url-slugify'

const slugify = new URLSlugify()
Expand Down
6 changes: 3 additions & 3 deletions docs/knossos/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ PREFIX code: <https://code.described.at/>

The `schema:name` can be one of the following:

- `before` - runs before the hydra-box middleware. Use it for example to set up authentication or CORS middlewares
- `before` - runs before the kopflos middleware. Use it for example to set up authentication or CORS middlewares
- `operations` - runs when operation candidates have been selected. It is the last chance to modify the operation which will be invoked
- `resource` - runs after the operation and resource have been selected and set to `req.hydra` and right before the operation middleware is invoked
- `error` - runs when an error is thrown in the request pipeline but before the error response is sent
Expand Down Expand Up @@ -123,7 +123,7 @@ export const customAuth: AuthorizationPatterns =
>
> [Open API docs](/api/interfaces/_hydrofoil_knossos_lib_settings.resourceloaderfactory.html)
At the beginning of every request a [`ResourceLoader`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/hydra-box/index.d.ts#L45-L48)
At the beginning of every request a [`ResourceLoader`](https://github.com/zazuko/kopflos/blob/1cf0916c6630eaf1ee4ce137dbed83de8287af69/index.ts#L36-L39)
is called to determine the basic information about the addressed resource.
The default implementation is [`SparqlQueryLoader` provided by `@hydrofoil/labyrinth`](https://github.com/hypermedia-app/creta/blob/master/packages/labyrinth/lib/loader.ts#L23)

Expand Down Expand Up @@ -242,7 +242,7 @@ Then, add a `overrideLoader` middleware before the middleware which uses the ext
`term`, which must match the `schema:identifier` and a `name`, which will be the key to set in `res.locals`.

```js
import $rdf from 'rdf-ext'
import $rdf from '@zazuko/env'
import { overrideLoader } from '@hydrofoil/knossos/configuration'

const extensionPoint = $rdf.namedNode('urn:override:extensionPoint')
Expand Down
Loading

0 comments on commit be2cfa6

Please sign in to comment.