Skip to content

Commit beb9c14

Browse files
feat: publish keys for UMA and packaging (#30)
1 parent 3136367 commit beb9c14

File tree

8 files changed

+232
-6
lines changed

8 files changed

+232
-6
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
"koreografeye": "^0.4.8",
7979
"shx": "^0.3.3",
8080
"ts-jest": "^29.1.1",
81-
"ts-node": "^10.9.1",
81+
"ts-node": "^10.9.2",
8282
"typescript": "^5.2.2"
8383
},
8484
"resolutions": {

packages/css/config/default.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
"import": [
77
"css:config/app/main/default.json",
88
"css:config/app/variables/default.json",
9-
"css:config/http/handler/default.json",
109
"css:config/http/middleware/default.json",
1110
"css:config/http/notifications/all.json",
1211
"css:config/http/server-factory/http.json",
@@ -29,6 +28,7 @@
2928
"css:config/util/resource-locker/memory.json",
3029
"css:config/util/variables/default.json",
3130
"uma-css:config/uma/default.json",
31+
"uma-css:config/http/handler/default.json",
3232
"uma-css:config/ldp/authentication/uma.json",
3333
"uma-css:config/ldp/authorization/uma.json",
3434
"uma-css:config/ldp/handler/uma.json",
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{
2+
"@context": [
3+
"https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^7.0.0/components/context.jsonld",
4+
"https://linkedsoftwaredependencies.org/bundles/npm/@solidlab/uma-css/^0.0.0/components/context.jsonld"
5+
],
6+
"import": [
7+
"css:config/http/handler/handlers/storage-description.json"
8+
],
9+
"@graph": [
10+
{
11+
"comment": "These are all the handlers a request will go through until it is handled.",
12+
"@id": "urn:solid-server:default:HttpHandler",
13+
"@type": "SequenceHandler",
14+
"handlers": [
15+
{
16+
"@id": "urn:solid-server:default:Middleware"
17+
},
18+
{
19+
"@id": "urn:solid-server:default:BaseHttpHandler",
20+
"@type": "WaterfallHandler",
21+
"handlers": [
22+
{
23+
"@id": "urn:solid-server:default:JwksHandler",
24+
"@type": "JwksHandler",
25+
"path": "/.well-known/jwks.json",
26+
"generator": {
27+
"@id": "urn:solid-server:default:JwkGenerator"
28+
}
29+
},
30+
{
31+
"@id": "urn:solid-server:default:StaticAssetHandler"
32+
},
33+
{
34+
"@id": "urn:solid-server:default:StaticAssetHandler"
35+
},
36+
{
37+
"@id": "urn:solid-server:default:OidcHandler"
38+
},
39+
{
40+
"@id": "urn:solid-server:default:NotificationHttpHandler"
41+
},
42+
{
43+
"@id": "urn:solid-server:default:StorageDescriptionHandler"
44+
},
45+
{
46+
"@id": "urn:solid-server:default:AuthResourceHttpHandler"
47+
},
48+
{
49+
"@id": "urn:solid-server:default:IdentityProviderHandler"
50+
},
51+
{
52+
"@id": "urn:solid-server:default:LdpHandler"
53+
}
54+
]
55+
}
56+
]
57+
}
58+
]
59+
}

packages/css/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
"@solidlab/uma": "workspace:^",
6868
"componentsjs": "^5.4.2",
6969
"cross-fetch": "^4.0.0",
70-
"jose": "^4.15.4",
70+
"jose": "^5.2.2",
7171
"n3": "^1.17.2"
7272
},
7373
"devDependencies": {

packages/css/src/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ export * from './identity/interaction/account/util/LoginStorage';
1111

1212
export * from './init/SeededAccountInitializer';
1313

14+
export * from './server/description/AccountSettingsStorageDescriber';
15+
16+
export * from './server/middleware/JwksHandler';
17+
1418
export * from './storage/keyvalue/IndexedStorage';
1519

1620
export * from './uma/ResourceRegistrar';
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import type { NamedNode, Quad, Quad_Object, Term } from '@rdfjs/types';
2+
import { DataFactory } from 'n3';
3+
import { stringToTerm } from 'rdf-string';
4+
import type { PodStore, ResourceIdentifier } from '@solid/community-server';
5+
import { StorageDescriber } from '@solid/community-server';
6+
import quad = DataFactory.quad;
7+
import namedNode = DataFactory.namedNode;
8+
import type { AccountStore, AccountSettings } from '../../identity/interaction/account/util/AccountStore';
9+
10+
/**
11+
* Adds triples to the storage description resource, based on the settings of
12+
* the account that created the storage.
13+
*
14+
* The resource identifier of the storage is used as subject.
15+
*/
16+
export class AccountSettingsStorageDescriber extends StorageDescriber {
17+
private readonly terms: ReadonlyMap<NamedNode, keyof AccountSettings>;
18+
19+
public constructor(
20+
private podStore: PodStore,
21+
private accountStore: AccountStore,
22+
terms: Record<string, keyof AccountSettings>,
23+
) {
24+
super();
25+
26+
const termMap = new Map<NamedNode, keyof AccountSettings>();
27+
for (const [ predicate, settingsKey ] of Object.entries(terms)) {
28+
29+
const predTerm = stringToTerm(predicate);
30+
if (predTerm.termType !== 'NamedNode') {
31+
throw new Error('Predicate needs to be a named node.');
32+
}
33+
34+
termMap.set(predTerm, settingsKey);
35+
}
36+
37+
this.terms = termMap;
38+
}
39+
40+
public async handle(target: ResourceIdentifier): Promise<Quad[]> {
41+
const subject = namedNode(target.path);
42+
const pod = await this.podStore.findByBaseUrl(target.path);
43+
if (!pod) throw new Error(`Cannot find pod for storage path ${target.path}`);
44+
45+
const quads: Quad[] = [];
46+
for await (const quad of this.generateTriples(subject, pod.accountId)) {
47+
quads.push(quad);
48+
}
49+
50+
return quads;
51+
}
52+
53+
private async* generateTriples(subject: NamedNode, account: string): AsyncGenerator<Quad> {
54+
55+
for (const [ predicate, settingsKey ] of this.terms.entries()) {
56+
57+
const settingsValue = await this.accountStore.getSetting(account, settingsKey);
58+
if (settingsValue === undefined) continue;
59+
60+
const objects = (Array.isArray(settingsValue) ? settingsValue : [ settingsValue ]).map((value): Quad_Object => {
61+
let term: Term;
62+
63+
try {
64+
term = stringToTerm(`${value}`);
65+
} catch {
66+
term = stringToTerm(`"${value}"`);
67+
}
68+
69+
return term as Quad_Object;
70+
});
71+
72+
for (const object of objects) {
73+
yield quad(subject, predicate, object);
74+
}
75+
}
76+
}
77+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import type { HttpHandlerInput } from '@solid/community-server';
2+
import { HttpHandler, JwkGenerator, MethodNotAllowedHttpError, NotImplementedHttpError } from '@solid/community-server';
3+
4+
export class JwksHandler extends HttpHandler {
5+
6+
constructor(
7+
private path: string,
8+
private generator: JwkGenerator,
9+
) {
10+
super();
11+
}
12+
13+
public async canHandle({ request }: HttpHandlerInput): Promise<void> {
14+
const { method, url } = request;
15+
16+
if (!['GET', 'HEAD'].includes(method ?? '')) {
17+
throw new MethodNotAllowedHttpError(
18+
method ? [ method ] : undefined,
19+
`Only GET or HEAD requests can target the storage description.`
20+
);
21+
}
22+
23+
if (url !== this.path) throw new NotImplementedHttpError(`This handler is not configured for ${url}`);
24+
}
25+
26+
27+
public async handle({ request, response }: HttpHandlerInput): Promise<void> {
28+
const key = await this.generator.getPublicKey();
29+
30+
response.writeHead(200, {
31+
'content-type': 'application/json',
32+
});
33+
34+
if (request.method === 'HEAD') {
35+
response.end();
36+
return;
37+
}
38+
39+
response.end(JSON.stringify({ keys: [ key ] }));
40+
}
41+
}

yarn.lock

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4136,7 +4136,7 @@ __metadata:
41364136
"@types/node": "npm:^18.18.11"
41374137
componentsjs: "npm:^5.4.2"
41384138
cross-fetch: "npm:^4.0.0"
4139-
jose: "npm:^4.15.4"
4139+
jose: "npm:^5.2.2"
41404140
n3: "npm:^1.17.2"
41414141
languageName: unknown
41424142
linkType: soft
@@ -4181,7 +4181,7 @@ __metadata:
41814181
koreografeye: "npm:^0.4.8"
41824182
shx: "npm:^0.3.3"
41834183
ts-jest: "npm:^29.1.1"
4184-
ts-node: "npm:^10.9.1"
4184+
ts-node: "npm:^10.9.2"
41854185
typescript: "npm:^5.2.2"
41864186
languageName: unknown
41874187
linkType: soft
@@ -7990,7 +7990,7 @@ __metadata:
79907990
languageName: node
79917991
linkType: hard
79927992

7993-
"jose@npm:^4.15.2, jose@npm:^4.15.4, jose@npm:^4.5.1, jose@npm:^4.7.0":
7993+
"jose@npm:^4.15.2, jose@npm:^4.5.1, jose@npm:^4.7.0":
79947994
version: 4.15.4
79957995
resolution: "jose@npm:4.15.4"
79967996
checksum: 10c0/ce8b29f84d6172a566b12b599dafa82f3bef0f16278bb76d562490ac1516fcc14017b05a39d20ffad25ed504f4996d4af4c9d3e0273d95b2d5559bf6d1112bc0
@@ -8004,6 +8004,13 @@ __metadata:
80048004
languageName: node
80058005
linkType: hard
80068006

8007+
"jose@npm:^5.2.2":
8008+
version: 5.2.2
8009+
resolution: "jose@npm:5.2.2"
8010+
checksum: 10c0/f6a439d41fa36e1c0a3a1554c1955ba656f37a7fc5e353bdcbda144cc9210fe513cc1b0480ec5bd5de50c0ec23714c82d82ae89f1b906656b683aa35ae075b68
8011+
languageName: node
8012+
linkType: hard
8013+
80078014
"js-tokens@npm:^4.0.0":
80088015
version: 4.0.0
80098016
resolution: "js-tokens@npm:4.0.0"
@@ -10792,6 +10799,44 @@ __metadata:
1079210799
languageName: node
1079310800
linkType: hard
1079410801

10802+
"ts-node@npm:^10.9.2":
10803+
version: 10.9.2
10804+
resolution: "ts-node@npm:10.9.2"
10805+
dependencies:
10806+
"@cspotcode/source-map-support": "npm:^0.8.0"
10807+
"@tsconfig/node10": "npm:^1.0.7"
10808+
"@tsconfig/node12": "npm:^1.0.7"
10809+
"@tsconfig/node14": "npm:^1.0.0"
10810+
"@tsconfig/node16": "npm:^1.0.2"
10811+
acorn: "npm:^8.4.1"
10812+
acorn-walk: "npm:^8.1.1"
10813+
arg: "npm:^4.1.0"
10814+
create-require: "npm:^1.1.0"
10815+
diff: "npm:^4.0.1"
10816+
make-error: "npm:^1.1.1"
10817+
v8-compile-cache-lib: "npm:^3.0.1"
10818+
yn: "npm:3.1.1"
10819+
peerDependencies:
10820+
"@swc/core": ">=1.2.50"
10821+
"@swc/wasm": ">=1.2.50"
10822+
"@types/node": "*"
10823+
typescript: ">=2.7"
10824+
peerDependenciesMeta:
10825+
"@swc/core":
10826+
optional: true
10827+
"@swc/wasm":
10828+
optional: true
10829+
bin:
10830+
ts-node: dist/bin.js
10831+
ts-node-cwd: dist/bin-cwd.js
10832+
ts-node-esm: dist/bin-esm.js
10833+
ts-node-script: dist/bin-script.js
10834+
ts-node-transpile-only: dist/bin-transpile.js
10835+
ts-script: dist/bin-script-deprecated.js
10836+
checksum: 10c0/5f29938489f96982a25ba650b64218e83a3357d76f7bede80195c65ab44ad279c8357264639b7abdd5d7e75fc269a83daa0e9c62fd8637a3def67254ecc9ddc2
10837+
languageName: node
10838+
linkType: hard
10839+
1079510840
"tslib@npm:^1.8.1":
1079610841
version: 1.14.1
1079710842
resolution: "tslib@npm:1.14.1"

0 commit comments

Comments
 (0)