|
1 | | -import type { ResourceIdentifier, MonitoringStore, KeyValueStorage } from '@solid/community-server'; |
| 1 | +import type { UmaClient } from '../uma/UmaClient'; |
| 2 | +import type { ResourceIdentifier, MonitoringStore } from '@solid/community-server'; |
2 | 3 | import { AS, getLoggerFor, StaticHandler } from '@solid/community-server'; |
3 | 4 | import { OwnerUtil } from '../util/OwnerUtil'; |
4 | | -import { ResourceDescription } from '@solidlab/uma'; |
5 | | -import type { UmaClient } from '../uma/UmaClient'; |
6 | 5 |
|
7 | 6 | export class ResourceRegistrar extends StaticHandler { |
8 | 7 | protected readonly logger = getLoggerFor(this); |
9 | 8 |
|
10 | 9 | public constructor( |
11 | 10 | protected store: MonitoringStore, |
12 | | - protected umaIdStore: KeyValueStorage<string, string>, |
13 | 11 | protected ownerUtil: OwnerUtil, |
14 | 12 | protected umaClient: UmaClient, |
15 | 13 | ) { |
16 | 14 | super(); |
17 | 15 |
|
18 | 16 | store.on(AS.Create, async (resource: ResourceIdentifier): Promise<void> => { |
19 | | - const owners = await this.ownerUtil.findOwners(resource).catch(() => []); |
20 | | - for (const owner of owners) this.createResource(resource, owner); |
| 17 | + for (const owner of await this.findOwners(resource)) { |
| 18 | + this.umaClient.createResource(resource, await this.findIssuer(owner)); |
| 19 | + } |
21 | 20 | }); |
22 | 21 |
|
23 | 22 | store.on(AS.Delete, async (resource: ResourceIdentifier): Promise<void> => { |
24 | | - const owners = await this.ownerUtil.findOwners(resource).catch(() => []); |
25 | | - for (const owner of owners) this.deleteResource(resource, owner); |
| 23 | + for (const owner of await this.findOwners(resource)) { |
| 24 | + this.umaClient.deleteResource(resource, await this.findIssuer(owner)); |
| 25 | + } |
26 | 26 | }); |
27 | 27 | } |
28 | 28 |
|
29 | | - protected async createResource(resource: ResourceIdentifier, owner: string): Promise<void> { |
30 | | - const issuer = await this.ownerUtil.findIssuer(owner); |
31 | | - |
32 | | - if (!issuer) throw new Error(`Could not find UMA AS for resource owner ${owner}`); |
33 | | - |
34 | | - const { resource_registration_endpoint: endpoint } = await this.umaClient.fetchUmaConfig(issuer); |
35 | | - |
36 | | - const description: ResourceDescription = { |
37 | | - resource_scopes: [ |
38 | | - 'urn:example:css:modes:read', |
39 | | - 'urn:example:css:modes:append', |
40 | | - 'urn:example:css:modes:create', |
41 | | - 'urn:example:css:modes:delete', |
42 | | - 'urn:example:css:modes:write', |
43 | | - ] |
44 | | - }; |
45 | | - |
46 | | - this.logger.info(`Creating resource registration for <${resource.path}> at <${endpoint}>`); |
47 | | - |
48 | | - const request = { |
49 | | - url: endpoint, |
50 | | - method: 'POST', |
51 | | - headers: { |
52 | | - 'Content-Type': 'application/json', |
53 | | - 'Accept': 'application/json', |
54 | | - }, |
55 | | - body: JSON.stringify(description), |
56 | | - }; |
57 | | - |
58 | | - // do not await - registration happens in background to cope with errors etc. |
59 | | - this.umaClient.signedFetch(endpoint, request).then(async resp => { |
60 | | - if (resp.status !== 201) { |
61 | | - throw new Error (`Resource registration request failed. ${await resp.text()}`); |
62 | | - } |
63 | | - |
64 | | - const { _id: umaId } = await resp.json(); |
65 | | - |
66 | | - if (!umaId || typeof umaId !== 'string') { |
67 | | - throw new Error ('Unexpected response from UMA server; no UMA id received.'); |
68 | | - } |
69 | | - |
70 | | - this.umaIdStore.set(resource.path, umaId); |
71 | | - }).catch(error => { |
72 | | - // TODO: Do something useful on error |
73 | | - this.logger.warn( |
74 | | - `Something went wrong during UMA resource registration to create ${resource.path}: ${(error as Error).message}` |
75 | | - ); |
76 | | - }); |
| 29 | + private async findOwners(resource: ResourceIdentifier): Promise<string[]> { |
| 30 | + return await this.ownerUtil.findOwners(resource).catch(() => []); |
77 | 31 | } |
78 | 32 |
|
79 | | - protected async deleteResource(resource: ResourceIdentifier, owner: string): Promise<void> { |
| 33 | + private async findIssuer(owner: string): Promise<string> { |
80 | 34 | const issuer = await this.ownerUtil.findIssuer(owner); |
81 | | - |
82 | 35 | if (!issuer) throw new Error(`Could not find UMA AS for resource owner ${owner}`); |
83 | | - |
84 | | - const { resource_registration_endpoint: endpoint } = await this.umaClient.fetchUmaConfig(issuer); |
85 | | - |
86 | | - this.logger.info(`Deleting resource registration for <${resource.path}> at <${endpoint}>`); |
87 | | - |
88 | | - const umaId = await this.umaIdStore.get(resource.path); |
89 | | - const url = `${endpoint}/${umaId}`; |
90 | | - |
91 | | - const request = { |
92 | | - url, |
93 | | - method: 'DELETE', |
94 | | - headers: {} |
95 | | - }; |
96 | | - |
97 | | - // do not await - registration happens in background to cope with errors etc. |
98 | | - this.umaClient.signedFetch(endpoint, request).then(async _resp => { |
99 | | - if (!umaId) throw new Error('Trying to delete unknown/unregistered resource; no UMA id found.'); |
100 | | - |
101 | | - await this.umaClient.signedFetch(url, request); |
102 | | - }).catch(error => { |
103 | | - // TODO: Do something useful on error |
104 | | - this.logger.warn( |
105 | | - `Something went wrong during UMA resource registration to delete ${resource.path}: ${(error as Error).message}` |
106 | | - ); |
107 | | - }); |
| 36 | + return issuer; |
108 | 37 | } |
109 | 38 | } |
0 commit comments