was-teaching-server 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1432 -0
- package/LICENSE +661 -0
- package/README.md +305 -0
- package/common/css/materialize.1.0.0.min.css +13 -0
- package/dist/auth-header-hooks.d.ts +84 -0
- package/dist/auth-header-hooks.d.ts.map +1 -0
- package/dist/auth-header-hooks.js +136 -0
- package/dist/auth-header-hooks.js.map +1 -0
- package/dist/authorize.d.ts +45 -0
- package/dist/authorize.d.ts.map +1 -0
- package/dist/authorize.js +76 -0
- package/dist/authorize.js.map +1 -0
- package/dist/backends/filesystem.d.ts +1179 -0
- package/dist/backends/filesystem.d.ts.map +1 -0
- package/dist/backends/filesystem.js +2727 -0
- package/dist/backends/filesystem.js.map +1 -0
- package/dist/backends/postgres.d.ts +833 -0
- package/dist/backends/postgres.d.ts.map +1 -0
- package/dist/backends/postgres.js +2164 -0
- package/dist/backends/postgres.js.map +1 -0
- package/dist/backends/postgresSchema.d.ts +36 -0
- package/dist/backends/postgresSchema.d.ts.map +1 -0
- package/dist/backends/postgresSchema.js +203 -0
- package/dist/backends/postgresSchema.js.map +1 -0
- package/dist/config.default.d.ts +360 -0
- package/dist/config.default.d.ts.map +1 -0
- package/dist/config.default.js +493 -0
- package/dist/config.default.js.map +1 -0
- package/dist/corsProxy.d.ts +45 -0
- package/dist/corsProxy.d.ts.map +1 -0
- package/dist/corsProxy.js +278 -0
- package/dist/corsProxy.js.map +1 -0
- package/dist/digest.d.ts +45 -0
- package/dist/digest.d.ts.map +1 -0
- package/dist/digest.js +174 -0
- package/dist/digest.js.map +1 -0
- package/dist/errors.d.ts +654 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +960 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/atomicFile.d.ts +61 -0
- package/dist/lib/atomicFile.d.ts.map +1 -0
- package/dist/lib/atomicFile.js +150 -0
- package/dist/lib/atomicFile.js.map +1 -0
- package/dist/lib/backendRegistry.d.ts +59 -0
- package/dist/lib/backendRegistry.d.ts.map +1 -0
- package/dist/lib/backendRegistry.js +92 -0
- package/dist/lib/backendRegistry.js.map +1 -0
- package/dist/lib/backendUsage.d.ts +28 -0
- package/dist/lib/backendUsage.d.ts.map +1 -0
- package/dist/lib/backendUsage.js +55 -0
- package/dist/lib/backendUsage.js.map +1 -0
- package/dist/lib/backends.d.ts +142 -0
- package/dist/lib/backends.d.ts.map +1 -0
- package/dist/lib/backends.js +272 -0
- package/dist/lib/backends.js.map +1 -0
- package/dist/lib/blindedIndex.d.ts +156 -0
- package/dist/lib/blindedIndex.d.ts.map +1 -0
- package/dist/lib/blindedIndex.js +338 -0
- package/dist/lib/blindedIndex.js.map +1 -0
- package/dist/lib/collectionDescription.d.ts +33 -0
- package/dist/lib/collectionDescription.d.ts.map +1 -0
- package/dist/lib/collectionDescription.js +21 -0
- package/dist/lib/collectionDescription.js.map +1 -0
- package/dist/lib/cursor.d.ts +18 -0
- package/dist/lib/cursor.d.ts.map +1 -0
- package/dist/lib/cursor.js +50 -0
- package/dist/lib/cursor.js.map +1 -0
- package/dist/lib/edvEnvelope.d.ts +50 -0
- package/dist/lib/edvEnvelope.d.ts.map +1 -0
- package/dist/lib/edvEnvelope.js +106 -0
- package/dist/lib/edvEnvelope.js.map +1 -0
- package/dist/lib/encryption.d.ts +192 -0
- package/dist/lib/encryption.d.ts.map +1 -0
- package/dist/lib/encryption.js +383 -0
- package/dist/lib/encryption.js.map +1 -0
- package/dist/lib/etag.d.ts +33 -0
- package/dist/lib/etag.d.ts.map +1 -0
- package/dist/lib/etag.js +36 -0
- package/dist/lib/etag.js.map +1 -0
- package/dist/lib/exportManifest.d.ts +29 -0
- package/dist/lib/exportManifest.d.ts.map +1 -0
- package/dist/lib/exportManifest.js +77 -0
- package/dist/lib/exportManifest.js.map +1 -0
- package/dist/lib/importTar.d.ts +81 -0
- package/dist/lib/importTar.d.ts.map +1 -0
- package/dist/lib/importTar.js +301 -0
- package/dist/lib/importTar.js.map +1 -0
- package/dist/lib/isJson.d.ts +16 -0
- package/dist/lib/isJson.d.ts.map +1 -0
- package/dist/lib/isJson.js +17 -0
- package/dist/lib/isJson.js.map +1 -0
- package/dist/lib/keyEpoch.d.ts +38 -0
- package/dist/lib/keyEpoch.d.ts.map +1 -0
- package/dist/lib/keyEpoch.js +75 -0
- package/dist/lib/keyEpoch.js.map +1 -0
- package/dist/lib/keyedMutex.d.ts +28 -0
- package/dist/lib/keyedMutex.d.ts.map +1 -0
- package/dist/lib/keyedMutex.js +45 -0
- package/dist/lib/keyedMutex.js.map +1 -0
- package/dist/lib/kmsModule.d.ts +62 -0
- package/dist/lib/kmsModule.d.ts.map +1 -0
- package/dist/lib/kmsModule.js +327 -0
- package/dist/lib/kmsModule.js.map +1 -0
- package/dist/lib/kmsRecordCipher.d.ts +82 -0
- package/dist/lib/kmsRecordCipher.d.ts.map +1 -0
- package/dist/lib/kmsRecordCipher.js +226 -0
- package/dist/lib/kmsRecordCipher.js.map +1 -0
- package/dist/lib/pagination.d.ts +19 -0
- package/dist/lib/pagination.d.ts.map +1 -0
- package/dist/lib/pagination.js +21 -0
- package/dist/lib/pagination.js.map +1 -0
- package/dist/lib/paths.d.ts +273 -0
- package/dist/lib/paths.d.ts.map +1 -0
- package/dist/lib/paths.js +270 -0
- package/dist/lib/paths.js.map +1 -0
- package/dist/lib/preconditions.d.ts +65 -0
- package/dist/lib/preconditions.d.ts.map +1 -0
- package/dist/lib/preconditions.js +112 -0
- package/dist/lib/preconditions.js.map +1 -0
- package/dist/lib/resourceFileName.d.ts +41 -0
- package/dist/lib/resourceFileName.d.ts.map +1 -0
- package/dist/lib/resourceFileName.js +58 -0
- package/dist/lib/resourceFileName.js.map +1 -0
- package/dist/lib/revocations.d.ts +49 -0
- package/dist/lib/revocations.d.ts.map +1 -0
- package/dist/lib/revocations.js +86 -0
- package/dist/lib/revocations.js.map +1 -0
- package/dist/lib/validateDid.d.ts +19 -0
- package/dist/lib/validateDid.d.ts.map +1 -0
- package/dist/lib/validateDid.js +35 -0
- package/dist/lib/validateDid.js.map +1 -0
- package/dist/lib/validateId.d.ts +66 -0
- package/dist/lib/validateId.d.ts.map +1 -0
- package/dist/lib/validateId.js +126 -0
- package/dist/lib/validateId.js.map +1 -0
- package/dist/plugin.d.ts +115 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +134 -0
- package/dist/plugin.js.map +1 -0
- package/dist/policy.d.ts +78 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +115 -0
- package/dist/policy.js.map +1 -0
- package/dist/provisioning.d.ts +38 -0
- package/dist/provisioning.d.ts.map +1 -0
- package/dist/provisioning.js +72 -0
- package/dist/provisioning.js.map +1 -0
- package/dist/requests/BackendRequest.d.ts +61 -0
- package/dist/requests/BackendRequest.d.ts.map +1 -0
- package/dist/requests/BackendRequest.js +152 -0
- package/dist/requests/BackendRequest.js.map +1 -0
- package/dist/requests/CollectionRequest.d.ts +234 -0
- package/dist/requests/CollectionRequest.d.ts.map +1 -0
- package/dist/requests/CollectionRequest.js +705 -0
- package/dist/requests/CollectionRequest.js.map +1 -0
- package/dist/requests/KeyRequest.d.ts +115 -0
- package/dist/requests/KeyRequest.d.ts.map +1 -0
- package/dist/requests/KeyRequest.js +468 -0
- package/dist/requests/KeyRequest.js.map +1 -0
- package/dist/requests/KeystoreRequest.d.ts +99 -0
- package/dist/requests/KeystoreRequest.d.ts.map +1 -0
- package/dist/requests/KeystoreRequest.js +247 -0
- package/dist/requests/KeystoreRequest.js.map +1 -0
- package/dist/requests/PolicyRequest.d.ts +53 -0
- package/dist/requests/PolicyRequest.d.ts.map +1 -0
- package/dist/requests/PolicyRequest.js +124 -0
- package/dist/requests/PolicyRequest.js.map +1 -0
- package/dist/requests/ResourceRequest.d.ts +134 -0
- package/dist/requests/ResourceRequest.d.ts.map +1 -0
- package/dist/requests/ResourceRequest.js +548 -0
- package/dist/requests/ResourceRequest.js.map +1 -0
- package/dist/requests/RevocationRequest.d.ts +67 -0
- package/dist/requests/RevocationRequest.d.ts.map +1 -0
- package/dist/requests/RevocationRequest.js +187 -0
- package/dist/requests/RevocationRequest.js.map +1 -0
- package/dist/requests/SpaceRequest.d.ts +204 -0
- package/dist/requests/SpaceRequest.d.ts.map +1 -0
- package/dist/requests/SpaceRequest.js +520 -0
- package/dist/requests/SpaceRequest.js.map +1 -0
- package/dist/requests/SpacesRepositoryRequest.d.ts +50 -0
- package/dist/requests/SpacesRepositoryRequest.d.ts.map +1 -0
- package/dist/requests/SpacesRepositoryRequest.js +159 -0
- package/dist/requests/SpacesRepositoryRequest.js.map +1 -0
- package/dist/requests/collectionContext.d.ts +21 -0
- package/dist/requests/collectionContext.d.ts.map +1 -0
- package/dist/requests/collectionContext.js +30 -0
- package/dist/requests/collectionContext.js.map +1 -0
- package/dist/requests/controllerConsent.d.ts +58 -0
- package/dist/requests/controllerConsent.d.ts.map +1 -0
- package/dist/requests/controllerConsent.js +73 -0
- package/dist/requests/controllerConsent.js.map +1 -0
- package/dist/requests/keystoreContext.d.ts +68 -0
- package/dist/requests/keystoreContext.d.ts.map +1 -0
- package/dist/requests/keystoreContext.js +87 -0
- package/dist/requests/keystoreContext.js.map +1 -0
- package/dist/requests/resourceInput.d.ts +19 -0
- package/dist/requests/resourceInput.d.ts.map +1 -0
- package/dist/requests/resourceInput.js +102 -0
- package/dist/requests/resourceInput.js.map +1 -0
- package/dist/requests/spaceContext.d.ts +127 -0
- package/dist/requests/spaceContext.d.ts.map +1 -0
- package/dist/requests/spaceContext.js +201 -0
- package/dist/requests/spaceContext.js.map +1 -0
- package/dist/routes.d.ts +55 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/routes.js +306 -0
- package/dist/routes.js.map +1 -0
- package/dist/server.d.ts +20 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +60 -0
- package/dist/server.js.map +1 -0
- package/dist/start.d.ts +7 -0
- package/dist/start.d.ts.map +1 -0
- package/dist/start.js +61 -0
- package/dist/start.js.map +1 -0
- package/dist/storage.d.ts +29 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +47 -0
- package/dist/storage.js.map +1 -0
- package/dist/types.d.ts +915 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/views/home.hbs +9 -0
- package/dist/views/templates/main.hbs +12 -0
- package/dist/zcap.d.ts +267 -0
- package/dist/zcap.d.ts.map +1 -0
- package/dist/zcap.js +478 -0
- package/dist/zcap.js.map +1 -0
- package/package.json +109 -0
- package/src/auth-header-hooks.ts +163 -0
- package/src/authorize.ts +117 -0
- package/src/backends/filesystem.ts +3626 -0
- package/src/backends/postgres.ts +3073 -0
- package/src/backends/postgresSchema.ts +231 -0
- package/src/config.default.ts +657 -0
- package/src/corsProxy.ts +326 -0
- package/src/declarations.d.ts +28 -0
- package/src/digest.ts +223 -0
- package/src/errors.ts +1122 -0
- package/src/index.ts +21 -0
- package/src/lib/atomicFile.ts +176 -0
- package/src/lib/backendRegistry.ts +139 -0
- package/src/lib/backendUsage.ts +79 -0
- package/src/lib/backends.ts +351 -0
- package/src/lib/blindedIndex.ts +466 -0
- package/src/lib/collectionDescription.ts +43 -0
- package/src/lib/cursor.ts +52 -0
- package/src/lib/edvEnvelope.ts +120 -0
- package/src/lib/encryption.ts +472 -0
- package/src/lib/etag.ts +40 -0
- package/src/lib/exportManifest.ts +115 -0
- package/src/lib/importTar.ts +381 -0
- package/src/lib/isJson.ts +18 -0
- package/src/lib/keyEpoch.ts +89 -0
- package/src/lib/keyedMutex.ts +45 -0
- package/src/lib/kmsModule.ts +451 -0
- package/src/lib/kmsRecordCipher.ts +292 -0
- package/src/lib/pagination.ts +22 -0
- package/src/lib/paths.ts +382 -0
- package/src/lib/preconditions.ts +145 -0
- package/src/lib/resourceFileName.ts +69 -0
- package/src/lib/revocations.ts +116 -0
- package/src/lib/validateDid.ts +41 -0
- package/src/lib/validateId.ts +148 -0
- package/src/plugin.ts +288 -0
- package/src/policy.ts +176 -0
- package/src/provisioning.ts +98 -0
- package/src/requests/BackendRequest.ts +219 -0
- package/src/requests/CollectionRequest.ts +899 -0
- package/src/requests/KeyRequest.ts +617 -0
- package/src/requests/KeystoreRequest.ts +325 -0
- package/src/requests/PolicyRequest.ts +169 -0
- package/src/requests/ResourceRequest.ts +649 -0
- package/src/requests/RevocationRequest.ts +267 -0
- package/src/requests/SpaceRequest.ts +686 -0
- package/src/requests/SpacesRepositoryRequest.ts +194 -0
- package/src/requests/collectionContext.ts +41 -0
- package/src/requests/controllerConsent.ts +108 -0
- package/src/requests/keystoreContext.ts +124 -0
- package/src/requests/resourceInput.ts +118 -0
- package/src/requests/spaceContext.ts +311 -0
- package/src/routes.ts +420 -0
- package/src/server.ts +69 -0
- package/src/start.ts +71 -0
- package/src/storage.ts +60 -0
- package/src/types.ts +1016 -0
- package/src/views/home.hbs +9 -0
- package/src/views/templates/main.hbs +12 -0
- package/src/zcap.ts +657 -0
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single source of truth for the server's relative URL path templates. The route
|
|
3
|
+
* shapes registered in `routes.ts` (the `/spaces` repository, `/space/:spaceId`,
|
|
4
|
+
* `/space/:spaceId/:collectionId`, the `policy` / `linkset` auxiliary resources,
|
|
5
|
+
* and the `export` / `import` actions) are mirrored here as builder functions, so
|
|
6
|
+
* handlers, the policy code, and the storage backends construct the same paths
|
|
7
|
+
* from one place rather than re-deriving them inline (which risks drift from the
|
|
8
|
+
* routes).
|
|
9
|
+
*
|
|
10
|
+
* Builders return the canonical, no-trailing-slash member form by default. The
|
|
11
|
+
* spec assigns distinct meaning to a trailing slash -- it addresses the
|
|
12
|
+
* container / "list-or-add-to" view of a member -- so the container builders take
|
|
13
|
+
* an explicit `trailingSlash` option (or, for the always-container `/spaces/` and
|
|
14
|
+
* `.../collections/`, bake the slash in) rather than leaving the slash to drift
|
|
15
|
+
* across call sites. A leaf Resource has no children, so `resourcePath` has no
|
|
16
|
+
* container form.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* The SpacesRepository container (`/spaces/`) or one of its members
|
|
20
|
+
* (`/spaces/:spaceId`). The member form is used for the `Location` header of a
|
|
21
|
+
* newly created Space; the container form is the `POST`/`GET` target.
|
|
22
|
+
* @param options {object}
|
|
23
|
+
* @param [options.spaceId] {string} when present, the repository member path;
|
|
24
|
+
* otherwise the (trailing-slash) container path
|
|
25
|
+
* @returns {string}
|
|
26
|
+
*/
|
|
27
|
+
export function spacesPath({ spaceId } = {}) {
|
|
28
|
+
return spaceId !== undefined ? `/spaces/${spaceId}` : `/spaces/`;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* `/space/:spaceId` (member) or `/space/:spaceId/` (container -- the
|
|
32
|
+
* "add a Collection" / Space-as-container view) when `trailingSlash` is set.
|
|
33
|
+
* @param options {object}
|
|
34
|
+
* @param options.spaceId {string}
|
|
35
|
+
* @param [options.trailingSlash] {boolean} address the container form
|
|
36
|
+
* @returns {string}
|
|
37
|
+
*/
|
|
38
|
+
export function spacePath({ spaceId, trailingSlash = false }) {
|
|
39
|
+
return `/space/${spaceId}${trailingSlash ? '/' : ''}`;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* `/space/:spaceId/collections/` -- the "List Collections" container path.
|
|
43
|
+
* @param options {object}
|
|
44
|
+
* @param options.spaceId {string}
|
|
45
|
+
* @returns {string}
|
|
46
|
+
*/
|
|
47
|
+
export function collectionsPath({ spaceId }) {
|
|
48
|
+
return `${spacePath({ spaceId })}/collections/`;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* `/space/:spaceId/export` -- the "Export Space" action path.
|
|
52
|
+
* @param options {object}
|
|
53
|
+
* @param options.spaceId {string}
|
|
54
|
+
* @returns {string}
|
|
55
|
+
*/
|
|
56
|
+
export function exportPath({ spaceId }) {
|
|
57
|
+
return `${spacePath({ spaceId })}/export`;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* `/space/:spaceId/import` -- the "Import Space" action path.
|
|
61
|
+
* @param options {object}
|
|
62
|
+
* @param options.spaceId {string}
|
|
63
|
+
* @returns {string}
|
|
64
|
+
*/
|
|
65
|
+
export function importPath({ spaceId }) {
|
|
66
|
+
return `${spacePath({ spaceId })}/import`;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* `/space/:spaceId/:collectionId` (member) or `/space/:spaceId/:collectionId/`
|
|
70
|
+
* (container -- the "add a Resource" / "list items" view) when `trailingSlash`
|
|
71
|
+
* is set.
|
|
72
|
+
* @param options {object}
|
|
73
|
+
* @param options.spaceId {string}
|
|
74
|
+
* @param options.collectionId {string}
|
|
75
|
+
* @param [options.trailingSlash] {boolean} address the container form
|
|
76
|
+
* @returns {string}
|
|
77
|
+
*/
|
|
78
|
+
export function collectionPath({ spaceId, collectionId, trailingSlash = false }) {
|
|
79
|
+
return `/space/${spaceId}/${collectionId}${trailingSlash ? '/' : ''}`;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* `/space/:spaceId/:collectionId/:resourceId`
|
|
83
|
+
* @param options {object}
|
|
84
|
+
* @param options.spaceId {string}
|
|
85
|
+
* @param options.collectionId {string}
|
|
86
|
+
* @param options.resourceId {string}
|
|
87
|
+
* @returns {string}
|
|
88
|
+
*/
|
|
89
|
+
export function resourcePath({ spaceId, collectionId, resourceId }) {
|
|
90
|
+
return `/space/${spaceId}/${collectionId}/${resourceId}`;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The `policy` auxiliary resource path for whichever level the ids address:
|
|
94
|
+
* Space (`spaceId`), Collection (`+ collectionId`), or Resource
|
|
95
|
+
* (`+ collectionId + resourceId`).
|
|
96
|
+
* @param options {object}
|
|
97
|
+
* @param options.spaceId {string}
|
|
98
|
+
* @param [options.collectionId] {string}
|
|
99
|
+
* @param [options.resourceId] {string}
|
|
100
|
+
* @returns {string}
|
|
101
|
+
*/
|
|
102
|
+
export function policyPath({ spaceId, collectionId, resourceId }) {
|
|
103
|
+
if (collectionId !== undefined && resourceId !== undefined) {
|
|
104
|
+
return `${resourcePath({ spaceId, collectionId, resourceId })}/policy`;
|
|
105
|
+
}
|
|
106
|
+
if (collectionId !== undefined) {
|
|
107
|
+
return `${collectionPath({ spaceId, collectionId })}/policy`;
|
|
108
|
+
}
|
|
109
|
+
return `${spacePath({ spaceId })}/policy`;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* `/space/:spaceId/backends` -- the "Space Backends Available" list path.
|
|
113
|
+
* @param options {object}
|
|
114
|
+
* @param options.spaceId {string}
|
|
115
|
+
* @returns {string}
|
|
116
|
+
*/
|
|
117
|
+
export function backendsPath({ spaceId }) {
|
|
118
|
+
return `${spacePath({ spaceId })}/backends`;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* `/space/:spaceId/backends/:backendId` -- a single registered `external`
|
|
122
|
+
* backend record (the `POST` `Location` target, and the `PUT`/`DELETE` member
|
|
123
|
+
* path). Distinct from {@link backendPath}, which is a Collection's *selected*
|
|
124
|
+
* backend resource.
|
|
125
|
+
* @param options {object}
|
|
126
|
+
* @param options.spaceId {string}
|
|
127
|
+
* @param options.backendId {string}
|
|
128
|
+
* @returns {string}
|
|
129
|
+
*/
|
|
130
|
+
export function registeredBackendPath({ spaceId, backendId }) {
|
|
131
|
+
return `${backendsPath({ spaceId })}/${backendId}`;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* `/space/:spaceId/quotas` -- the Space Quota report path (spec "Quotas").
|
|
135
|
+
* @param options {object}
|
|
136
|
+
* @param options.spaceId {string}
|
|
137
|
+
* @returns {string}
|
|
138
|
+
*/
|
|
139
|
+
export function quotasPath({ spaceId }) {
|
|
140
|
+
return `${spacePath({ spaceId })}/quotas`;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* `/space/:spaceId/:collectionId/:resourceId/meta` -- the Resource Metadata
|
|
144
|
+
* (reserved `meta` segment) path. Reserved only at the Resource level, so it
|
|
145
|
+
* takes the full id triple.
|
|
146
|
+
* @param options {object}
|
|
147
|
+
* @param options.spaceId {string}
|
|
148
|
+
* @param options.collectionId {string}
|
|
149
|
+
* @param options.resourceId {string}
|
|
150
|
+
* @returns {string}
|
|
151
|
+
*/
|
|
152
|
+
export function metaPath({ spaceId, collectionId, resourceId }) {
|
|
153
|
+
return `${resourcePath({ spaceId, collectionId, resourceId })}/meta`;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* `/space/:spaceId/:collectionId/backend` -- the "Collection Backend Selected"
|
|
157
|
+
* resource path (reserved `backend` segment at the Resource level).
|
|
158
|
+
* @param options {object}
|
|
159
|
+
* @param options.spaceId {string}
|
|
160
|
+
* @param options.collectionId {string}
|
|
161
|
+
* @returns {string}
|
|
162
|
+
*/
|
|
163
|
+
export function backendPath({ spaceId, collectionId }) {
|
|
164
|
+
return `${collectionPath({ spaceId, collectionId })}/backend`;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* `/space/:spaceId/:collectionId/quota` -- the per-Collection storage quota
|
|
168
|
+
* report path (reserved `quota` segment at the Resource level; spec "Quotas").
|
|
169
|
+
* @param options {object}
|
|
170
|
+
* @param options.spaceId {string}
|
|
171
|
+
* @param options.collectionId {string}
|
|
172
|
+
* @returns {string}
|
|
173
|
+
*/
|
|
174
|
+
export function quotaPath({ spaceId, collectionId }) {
|
|
175
|
+
return `${collectionPath({ spaceId, collectionId })}/quota`;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* `/space/:spaceId/:collectionId/query` -- the reserved `query` endpoint for a
|
|
179
|
+
* Collection (spec "Collection-level reserved endpoints"). The WAS server serves
|
|
180
|
+
* the replication change feed as the `changes` profile of this endpoint.
|
|
181
|
+
* @param options {object}
|
|
182
|
+
* @param options.spaceId {string}
|
|
183
|
+
* @param options.collectionId {string}
|
|
184
|
+
* @returns {string}
|
|
185
|
+
*/
|
|
186
|
+
export function queryPath({ spaceId, collectionId }) {
|
|
187
|
+
return `${collectionPath({ spaceId, collectionId })}/query`;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* The `linkset` discovery resource path for a Space (`spaceId`) or Collection
|
|
191
|
+
* (`+ collectionId`).
|
|
192
|
+
* @param options {object}
|
|
193
|
+
* @param options.spaceId {string}
|
|
194
|
+
* @param [options.collectionId] {string}
|
|
195
|
+
* @returns {string}
|
|
196
|
+
*/
|
|
197
|
+
export function linksetPath({ spaceId, collectionId }) {
|
|
198
|
+
const anchor = collectionId !== undefined
|
|
199
|
+
? collectionPath({ spaceId, collectionId })
|
|
200
|
+
: spacePath({ spaceId });
|
|
201
|
+
return `${anchor}/linkset`;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* `/kms/keystores` -- the WebKMS keystores collection (create/list target; the
|
|
205
|
+
* `/kms` facet) or one of its member keystores
|
|
206
|
+
* (`/kms/keystores/:keystoreId`). Unlike the WAS builders there is no
|
|
207
|
+
* trailing-slash container form: the webkms protocol
|
|
208
|
+
* (`@interop/webkms-client`) posts to the bare collection path.
|
|
209
|
+
* @param options {object}
|
|
210
|
+
* @param [options.keystoreId] {string} the keystore's server-generated local
|
|
211
|
+
* id; when present, the member path, otherwise the collection path
|
|
212
|
+
* @returns {string}
|
|
213
|
+
*/
|
|
214
|
+
export function kmsKeystoresPath({ keystoreId } = {}) {
|
|
215
|
+
return keystoreId !== undefined
|
|
216
|
+
? `/kms/keystores/${keystoreId}`
|
|
217
|
+
: '/kms/keystores';
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* `/kms/keystores/:keystoreId/keys` -- a keystore's keys collection (the
|
|
221
|
+
* `GenerateKeyOperation` target) or one of its member keys
|
|
222
|
+
* (`/kms/keystores/:keystoreId/keys/:keyId`, the key-operation / description
|
|
223
|
+
* target). Like `kmsKeystoresPath`, no trailing-slash form exists: the webkms
|
|
224
|
+
* protocol's URLs are exact.
|
|
225
|
+
* @param options {object}
|
|
226
|
+
* @param options.keystoreId {string} the keystore's local id
|
|
227
|
+
* @param [options.keyId] {string} the key's server-generated local id; when
|
|
228
|
+
* present, the member path, otherwise the collection path
|
|
229
|
+
* @returns {string}
|
|
230
|
+
*/
|
|
231
|
+
export function kmsKeysPath({ keystoreId, keyId }) {
|
|
232
|
+
const keysPath = `${kmsKeystoresPath({ keystoreId })}/keys`;
|
|
233
|
+
return keyId !== undefined ? `${keysPath}/${keyId}` : keysPath;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* `/kms/keystores/:keystoreId/zcaps/revocations/:revocationId` -- a keystore's
|
|
237
|
+
* zcap revocation submission target (POST; the ezcap-express
|
|
238
|
+
* `/zcaps/revocations/` convention). `revocationId` is the *to-be-revoked
|
|
239
|
+
* capability's id*, URL-encoded into the single path segment the route
|
|
240
|
+
* expects -- the same `encodeURIComponent` framing `@interop/webkms-client`'s
|
|
241
|
+
* `revokeCapability` puts on the wire.
|
|
242
|
+
* @param options {object}
|
|
243
|
+
* @param options.keystoreId {string} the keystore's local id
|
|
244
|
+
* @param options.revocationId {string} the to-be-revoked capability's id
|
|
245
|
+
* (raw, un-encoded)
|
|
246
|
+
* @returns {string}
|
|
247
|
+
*/
|
|
248
|
+
export function kmsRevocationsPath({ keystoreId, revocationId }) {
|
|
249
|
+
return (`${kmsKeystoresPath({ keystoreId })}/zcaps/revocations/` +
|
|
250
|
+
encodeURIComponent(revocationId));
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* `/space/:spaceId/zcaps/revocations/:revocationId` -- a Space's zcap
|
|
254
|
+
* revocation submission target (POST), the WAS-route sibling of
|
|
255
|
+
* `kmsRevocationsPath` and the same ezcap-express `/zcaps/revocations/`
|
|
256
|
+
* convention. `revocationId` is the *to-be-revoked capability's id*,
|
|
257
|
+
* URL-encoded into the single path segment the route expects. The `zcaps`
|
|
258
|
+
* segment sits four levels under `/space`, deeper than any Collection or
|
|
259
|
+
* Resource route, so it shadows neither and needs no reserved-id entry.
|
|
260
|
+
* @param options {object}
|
|
261
|
+
* @param options.spaceId {string}
|
|
262
|
+
* @param options.revocationId {string} the to-be-revoked capability's id
|
|
263
|
+
* (raw, un-encoded)
|
|
264
|
+
* @returns {string}
|
|
265
|
+
*/
|
|
266
|
+
export function spaceRevocationsPath({ spaceId, revocationId }) {
|
|
267
|
+
return (`${spacePath({ spaceId })}/zcaps/revocations/` +
|
|
268
|
+
encodeURIComponent(revocationId));
|
|
269
|
+
}
|
|
270
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evaluates a content-write (or delete) precondition against a Resource's
|
|
3
|
+
* current state. Throws `PreconditionFailedError` (412) when it is not met.
|
|
4
|
+
* `ifNoneMatch` (`If-None-Match: *`, create-if-absent) takes precedence over
|
|
5
|
+
* `ifMatch` when both are present (RFC9110): the write proceeds only if the
|
|
6
|
+
* Resource is absent. `ifMatch` (update-if-unchanged) requires the Resource to
|
|
7
|
+
* exist with a current ETag equal to the supplied validator.
|
|
8
|
+
* @param options {object}
|
|
9
|
+
* @param options.resourceId {string} for the error detail
|
|
10
|
+
* @param options.exists {boolean} whether the Resource currently exists (a
|
|
11
|
+
* tombstone counts as "does not exist")
|
|
12
|
+
* @param options.currentVersion {number} the Resource's current content
|
|
13
|
+
* `version` (0 for a legacy Resource without one)
|
|
14
|
+
* @param [options.ifMatch] {string} a quoted ETag (`If-Match`)
|
|
15
|
+
* @param [options.ifNoneMatch] {boolean} `If-None-Match: *` (create-if-absent)
|
|
16
|
+
* @returns {void}
|
|
17
|
+
*/
|
|
18
|
+
export declare function assertWritePrecondition({ resourceId, exists, currentVersion, ifMatch, ifNoneMatch }: {
|
|
19
|
+
resourceId: string;
|
|
20
|
+
exists: boolean;
|
|
21
|
+
currentVersion: number;
|
|
22
|
+
ifMatch?: string;
|
|
23
|
+
ifNoneMatch?: boolean;
|
|
24
|
+
}): void;
|
|
25
|
+
/**
|
|
26
|
+
* Evaluates a Collection Description write precondition against the Collection's
|
|
27
|
+
* current description `version` (the `key-epochs` / conditional-Collection-write
|
|
28
|
+
* feature). Throws `PreconditionFailedError` (412) when the supplied `If-Match`
|
|
29
|
+
* validator does not equal the current description ETag. Only `If-Match`
|
|
30
|
+
* (update-if-unchanged) is supported for Collections; a create through an
|
|
31
|
+
* unconditional PUT is unaffected. MUST be called atomically with the write
|
|
32
|
+
* (under the filesystem backend's per-Collection lock, or inside the Postgres
|
|
33
|
+
* backend's row-locking transaction).
|
|
34
|
+
* @param options {object}
|
|
35
|
+
* @param options.collectionId {string} for the error detail
|
|
36
|
+
* @param options.currentVersion {number} the Collection's current description
|
|
37
|
+
* `version` (0 for a legacy Collection without one, or before its first write)
|
|
38
|
+
* @param [options.ifMatch] {string} a quoted ETag (`If-Match`)
|
|
39
|
+
* @returns {void}
|
|
40
|
+
*/
|
|
41
|
+
export declare function assertCollectionWritePrecondition({ collectionId, currentVersion, ifMatch }: {
|
|
42
|
+
collectionId: string;
|
|
43
|
+
currentVersion: number;
|
|
44
|
+
ifMatch?: string;
|
|
45
|
+
}): void;
|
|
46
|
+
/**
|
|
47
|
+
* Evaluates a metadata-write (`/meta`) precondition against a Resource's
|
|
48
|
+
* current `metaVersion`. Throws `PreconditionFailedError` (412) when it is not
|
|
49
|
+
* met. `If-None-Match: *` means "only if no metadata has been written yet"
|
|
50
|
+
* (`metaVersion` unset); `If-Match` pins the current `metaVersion` ETag.
|
|
51
|
+
* @param options {object}
|
|
52
|
+
* @param options.resourceId {string} for the error detail
|
|
53
|
+
* @param [options.metaVersion] {number} the current `metaVersion`
|
|
54
|
+
* (`undefined` until the first metadata write)
|
|
55
|
+
* @param [options.ifMatch] {string} a quoted ETag (`If-Match`)
|
|
56
|
+
* @param [options.ifNoneMatch] {boolean} `If-None-Match: *`
|
|
57
|
+
* @returns {void}
|
|
58
|
+
*/
|
|
59
|
+
export declare function assertMetaWritePrecondition({ resourceId, metaVersion, ifMatch, ifNoneMatch }: {
|
|
60
|
+
resourceId: string;
|
|
61
|
+
metaVersion?: number;
|
|
62
|
+
ifMatch?: string;
|
|
63
|
+
ifNoneMatch?: boolean;
|
|
64
|
+
}): void;
|
|
65
|
+
//# sourceMappingURL=preconditions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preconditions.d.ts","sourceRoot":"","sources":["../../src/lib/preconditions.ts"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,UAAU,EACV,MAAM,EACN,cAAc,EACd,OAAO,EACP,WAAW,EACZ,EAAE;IACD,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,OAAO,CAAA;IACf,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB,GAAG,IAAI,CA2BP;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iCAAiC,CAAC,EAChD,YAAY,EACZ,cAAc,EACd,OAAO,EACR,EAAE;IACD,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,GAAG,IAAI,CAUP;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,2BAA2B,CAAC,EAC1C,UAAU,EACV,WAAW,EACX,OAAO,EACP,WAAW,EACZ,EAAE;IACD,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB,GAAG,IAAI,CAeP"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Backend-agnostic conditional-write precondition evaluation (the
|
|
3
|
+
* `conditional-writes` feature). Both storage backends evaluate `If-Match` /
|
|
4
|
+
* `If-None-Match` against a Resource's current state through these two
|
|
5
|
+
* helpers, so the 412 semantics cannot drift between them. Callers MUST invoke
|
|
6
|
+
* them atomically with the write that follows (under the filesystem backend's
|
|
7
|
+
* per-Resource lock, or inside the Postgres backend's row-locking
|
|
8
|
+
* transaction).
|
|
9
|
+
*/
|
|
10
|
+
import { PreconditionFailedError } from '../errors.js';
|
|
11
|
+
import { formatEtag } from './etag.js';
|
|
12
|
+
/**
|
|
13
|
+
* Evaluates a content-write (or delete) precondition against a Resource's
|
|
14
|
+
* current state. Throws `PreconditionFailedError` (412) when it is not met.
|
|
15
|
+
* `ifNoneMatch` (`If-None-Match: *`, create-if-absent) takes precedence over
|
|
16
|
+
* `ifMatch` when both are present (RFC9110): the write proceeds only if the
|
|
17
|
+
* Resource is absent. `ifMatch` (update-if-unchanged) requires the Resource to
|
|
18
|
+
* exist with a current ETag equal to the supplied validator.
|
|
19
|
+
* @param options {object}
|
|
20
|
+
* @param options.resourceId {string} for the error detail
|
|
21
|
+
* @param options.exists {boolean} whether the Resource currently exists (a
|
|
22
|
+
* tombstone counts as "does not exist")
|
|
23
|
+
* @param options.currentVersion {number} the Resource's current content
|
|
24
|
+
* `version` (0 for a legacy Resource without one)
|
|
25
|
+
* @param [options.ifMatch] {string} a quoted ETag (`If-Match`)
|
|
26
|
+
* @param [options.ifNoneMatch] {boolean} `If-None-Match: *` (create-if-absent)
|
|
27
|
+
* @returns {void}
|
|
28
|
+
*/
|
|
29
|
+
export function assertWritePrecondition({ resourceId, exists, currentVersion, ifMatch, ifNoneMatch }) {
|
|
30
|
+
if (ifNoneMatch) {
|
|
31
|
+
if (exists) {
|
|
32
|
+
throw new PreconditionFailedError({
|
|
33
|
+
detail: `Resource '${resourceId}' already exists (If-None-Match: *).`
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (ifMatch === undefined) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
// `If-Match` (update-if-unchanged): the Resource must exist and its current
|
|
42
|
+
// ETag must equal the supplied validator.
|
|
43
|
+
if (!exists) {
|
|
44
|
+
throw new PreconditionFailedError({
|
|
45
|
+
detail: `Resource '${resourceId}' does not exist; If-Match cannot be satisfied.`
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
const currentEtag = formatEtag(currentVersion);
|
|
49
|
+
if (currentEtag !== ifMatch) {
|
|
50
|
+
throw new PreconditionFailedError({
|
|
51
|
+
detail: `Resource '${resourceId}' ETag ${currentEtag} does not match If-Match ${ifMatch}.`
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Evaluates a Collection Description write precondition against the Collection's
|
|
57
|
+
* current description `version` (the `key-epochs` / conditional-Collection-write
|
|
58
|
+
* feature). Throws `PreconditionFailedError` (412) when the supplied `If-Match`
|
|
59
|
+
* validator does not equal the current description ETag. Only `If-Match`
|
|
60
|
+
* (update-if-unchanged) is supported for Collections; a create through an
|
|
61
|
+
* unconditional PUT is unaffected. MUST be called atomically with the write
|
|
62
|
+
* (under the filesystem backend's per-Collection lock, or inside the Postgres
|
|
63
|
+
* backend's row-locking transaction).
|
|
64
|
+
* @param options {object}
|
|
65
|
+
* @param options.collectionId {string} for the error detail
|
|
66
|
+
* @param options.currentVersion {number} the Collection's current description
|
|
67
|
+
* `version` (0 for a legacy Collection without one, or before its first write)
|
|
68
|
+
* @param [options.ifMatch] {string} a quoted ETag (`If-Match`)
|
|
69
|
+
* @returns {void}
|
|
70
|
+
*/
|
|
71
|
+
export function assertCollectionWritePrecondition({ collectionId, currentVersion, ifMatch }) {
|
|
72
|
+
if (ifMatch === undefined) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const currentEtag = formatEtag(currentVersion);
|
|
76
|
+
if (currentEtag !== ifMatch) {
|
|
77
|
+
throw new PreconditionFailedError({
|
|
78
|
+
detail: `Collection '${collectionId}' ETag ${currentEtag} does not match If-Match ${ifMatch}.`
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Evaluates a metadata-write (`/meta`) precondition against a Resource's
|
|
84
|
+
* current `metaVersion`. Throws `PreconditionFailedError` (412) when it is not
|
|
85
|
+
* met. `If-None-Match: *` means "only if no metadata has been written yet"
|
|
86
|
+
* (`metaVersion` unset); `If-Match` pins the current `metaVersion` ETag.
|
|
87
|
+
* @param options {object}
|
|
88
|
+
* @param options.resourceId {string} for the error detail
|
|
89
|
+
* @param [options.metaVersion] {number} the current `metaVersion`
|
|
90
|
+
* (`undefined` until the first metadata write)
|
|
91
|
+
* @param [options.ifMatch] {string} a quoted ETag (`If-Match`)
|
|
92
|
+
* @param [options.ifNoneMatch] {boolean} `If-None-Match: *`
|
|
93
|
+
* @returns {void}
|
|
94
|
+
*/
|
|
95
|
+
export function assertMetaWritePrecondition({ resourceId, metaVersion, ifMatch, ifNoneMatch }) {
|
|
96
|
+
if (ifNoneMatch) {
|
|
97
|
+
if (metaVersion !== undefined) {
|
|
98
|
+
throw new PreconditionFailedError({
|
|
99
|
+
detail: `Resource '${resourceId}' metadata already exists (If-None-Match: *).`
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else if (ifMatch !== undefined) {
|
|
104
|
+
const currentEtag = formatEtag(metaVersion ?? 0);
|
|
105
|
+
if (currentEtag !== ifMatch) {
|
|
106
|
+
throw new PreconditionFailedError({
|
|
107
|
+
detail: `Resource '${resourceId}' metadata ETag ${currentEtag} does not match If-Match ${ifMatch}.`
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=preconditions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preconditions.js","sourceRoot":"","sources":["../../src/lib/preconditions.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAA;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAEtC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,uBAAuB,CAAC,EACtC,UAAU,EACV,MAAM,EACN,cAAc,EACd,OAAO,EACP,WAAW,EAOZ;IACC,IAAI,WAAW,EAAE,CAAC;QAChB,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,IAAI,uBAAuB,CAAC;gBAChC,MAAM,EAAE,aAAa,UAAU,sCAAsC;aACtE,CAAC,CAAA;QACJ,CAAC;QACD,OAAM;IACR,CAAC;IAED,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAM;IACR,CAAC;IAED,4EAA4E;IAC5E,0CAA0C;IAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,uBAAuB,CAAC;YAChC,MAAM,EAAE,aAAa,UAAU,iDAAiD;SACjF,CAAC,CAAA;IACJ,CAAC;IACD,MAAM,WAAW,GAAG,UAAU,CAAC,cAAc,CAAC,CAAA;IAC9C,IAAI,WAAW,KAAK,OAAO,EAAE,CAAC;QAC5B,MAAM,IAAI,uBAAuB,CAAC;YAChC,MAAM,EAAE,aAAa,UAAU,UAAU,WAAW,4BAA4B,OAAO,GAAG;SAC3F,CAAC,CAAA;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,iCAAiC,CAAC,EAChD,YAAY,EACZ,cAAc,EACd,OAAO,EAKR;IACC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAM;IACR,CAAC;IACD,MAAM,WAAW,GAAG,UAAU,CAAC,cAAc,CAAC,CAAA;IAC9C,IAAI,WAAW,KAAK,OAAO,EAAE,CAAC;QAC5B,MAAM,IAAI,uBAAuB,CAAC;YAChC,MAAM,EAAE,eAAe,YAAY,UAAU,WAAW,4BAA4B,OAAO,GAAG;SAC/F,CAAC,CAAA;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,2BAA2B,CAAC,EAC1C,UAAU,EACV,WAAW,EACX,OAAO,EACP,WAAW,EAMZ;IACC,IAAI,WAAW,EAAE,CAAC;QAChB,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,IAAI,uBAAuB,CAAC;gBAChC,MAAM,EAAE,aAAa,UAAU,+CAA+C;aAC/E,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;SAAM,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QACjC,MAAM,WAAW,GAAG,UAAU,CAAC,WAAW,IAAI,CAAC,CAAC,CAAA;QAChD,IAAI,WAAW,KAAK,OAAO,EAAE,CAAC;YAC5B,MAAM,IAAI,uBAAuB,CAAC;gBAChC,MAAM,EAAE,aAAa,UAAU,mBAAmB,WAAW,4BAA4B,OAAO,GAAG;aACpG,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Percent-encodes a filename segment so it carries no literal `.`, the
|
|
3
|
+
* structural delimiter of `r.<resourceId>.<encodedContentType>.<ext>`.
|
|
4
|
+
* `encodeURIComponent` leaves `.` unescaped, so escape it explicitly to `%2E`;
|
|
5
|
+
* `decodeURIComponent` reverses both. This keeps resource ids and content-types
|
|
6
|
+
* that legitimately contain dots (e.g. `index.html`, `application/vnd.api+json`)
|
|
7
|
+
* unambiguously parseable -- without it, a dotted id mis-splits and is read back
|
|
8
|
+
* under the wrong id and content-type. For dot-free segments (the common case)
|
|
9
|
+
* the result is byte-identical to the previous `encodeURIComponent`-only scheme.
|
|
10
|
+
* @param segment {string}
|
|
11
|
+
* @returns {string}
|
|
12
|
+
*/
|
|
13
|
+
export declare function encodeFilenameSegment(segment: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Builds the on-disk filename for a resource representation:
|
|
16
|
+
* `r.<resourceId>.<encodedContentType>.<ext>`. Both the `resourceId` and
|
|
17
|
+
* content-type segments are dot-escaped (see {@link encodeFilenameSegment}) so
|
|
18
|
+
* the three `.` separators are the only literal dots.
|
|
19
|
+
* @param options {object}
|
|
20
|
+
* @param options.resourceId {string}
|
|
21
|
+
* @param options.contentType {string}
|
|
22
|
+
* @returns {string}
|
|
23
|
+
*/
|
|
24
|
+
export declare function fileNameFor({ resourceId, contentType }: {
|
|
25
|
+
resourceId: string;
|
|
26
|
+
contentType: string;
|
|
27
|
+
}): string;
|
|
28
|
+
/**
|
|
29
|
+
* Parses an on-disk resource filename (`r.<resourceId>.<encodedContentType>.<ext>`)
|
|
30
|
+
* back into its components, reversing the dot-escaping {@link fileNameFor}
|
|
31
|
+
* applies. Returns the exact stored content-type (decoded from the filename
|
|
32
|
+
* segment, more reliable than `mime.lookup` on the extension), falling back to
|
|
33
|
+
* the spec default `application/octet-stream` if unparseable.
|
|
34
|
+
* @param fileName {string} the basename of the resource file
|
|
35
|
+
* @returns {{ resourceId: string, contentType: string }}
|
|
36
|
+
*/
|
|
37
|
+
export declare function parseResourceFileName(fileName: string): {
|
|
38
|
+
resourceId: string;
|
|
39
|
+
contentType: string;
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=resourceFileName.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resourceFileName.d.ts","sourceRoot":"","sources":["../../src/lib/resourceFileName.ts"],"names":[],"mappings":"AASA;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,EAC1B,UAAU,EACV,WAAW,EACZ,EAAE;IACD,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;CACpB,GAAG,MAAM,CAKT;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG;IACvD,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;CACpB,CAQA"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* On-disk resource-filename codec: the single shared home for encoding a
|
|
3
|
+
* Resource's representation file name (`r.<resourceId>.<encodedContentType>.<ext>`)
|
|
4
|
+
* and decoding it back. Kept low-level (no imports from `src/backends/` or
|
|
5
|
+
* `importTar.ts`) so both the filesystem backend and the tar importer can depend
|
|
6
|
+
* on it without an import cycle.
|
|
7
|
+
*/
|
|
8
|
+
import * as mime from 'mime-types';
|
|
9
|
+
/**
|
|
10
|
+
* Percent-encodes a filename segment so it carries no literal `.`, the
|
|
11
|
+
* structural delimiter of `r.<resourceId>.<encodedContentType>.<ext>`.
|
|
12
|
+
* `encodeURIComponent` leaves `.` unescaped, so escape it explicitly to `%2E`;
|
|
13
|
+
* `decodeURIComponent` reverses both. This keeps resource ids and content-types
|
|
14
|
+
* that legitimately contain dots (e.g. `index.html`, `application/vnd.api+json`)
|
|
15
|
+
* unambiguously parseable -- without it, a dotted id mis-splits and is read back
|
|
16
|
+
* under the wrong id and content-type. For dot-free segments (the common case)
|
|
17
|
+
* the result is byte-identical to the previous `encodeURIComponent`-only scheme.
|
|
18
|
+
* @param segment {string}
|
|
19
|
+
* @returns {string}
|
|
20
|
+
*/
|
|
21
|
+
export function encodeFilenameSegment(segment) {
|
|
22
|
+
return encodeURIComponent(segment).replace(/\./g, '%2E');
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Builds the on-disk filename for a resource representation:
|
|
26
|
+
* `r.<resourceId>.<encodedContentType>.<ext>`. Both the `resourceId` and
|
|
27
|
+
* content-type segments are dot-escaped (see {@link encodeFilenameSegment}) so
|
|
28
|
+
* the three `.` separators are the only literal dots.
|
|
29
|
+
* @param options {object}
|
|
30
|
+
* @param options.resourceId {string}
|
|
31
|
+
* @param options.contentType {string}
|
|
32
|
+
* @returns {string}
|
|
33
|
+
*/
|
|
34
|
+
export function fileNameFor({ resourceId, contentType }) {
|
|
35
|
+
const encodedId = encodeFilenameSegment(resourceId);
|
|
36
|
+
const encodedType = encodeFilenameSegment(contentType);
|
|
37
|
+
const extension = mime.extension(contentType) || 'blob';
|
|
38
|
+
return `r.${encodedId}.${encodedType}.${extension}`;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Parses an on-disk resource filename (`r.<resourceId>.<encodedContentType>.<ext>`)
|
|
42
|
+
* back into its components, reversing the dot-escaping {@link fileNameFor}
|
|
43
|
+
* applies. Returns the exact stored content-type (decoded from the filename
|
|
44
|
+
* segment, more reliable than `mime.lookup` on the extension), falling back to
|
|
45
|
+
* the spec default `application/octet-stream` if unparseable.
|
|
46
|
+
* @param fileName {string} the basename of the resource file
|
|
47
|
+
* @returns {{ resourceId: string, contentType: string }}
|
|
48
|
+
*/
|
|
49
|
+
export function parseResourceFileName(fileName) {
|
|
50
|
+
const [, encodedId, encodedType] = fileName.split('.');
|
|
51
|
+
return {
|
|
52
|
+
resourceId: encodedId ? decodeURIComponent(encodedId) : '',
|
|
53
|
+
contentType: encodedType
|
|
54
|
+
? decodeURIComponent(encodedType)
|
|
55
|
+
: 'application/octet-stream'
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=resourceFileName.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resourceFileName.js","sourceRoot":"","sources":["../../src/lib/resourceFileName.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,IAAI,MAAM,YAAY,CAAA;AAElC;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAe;IACnD,OAAO,kBAAkB,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;AAC1D,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CAAC,EAC1B,UAAU,EACV,WAAW,EAIZ;IACC,MAAM,SAAS,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAA;IACnD,MAAM,WAAW,GAAG,qBAAqB,CAAC,WAAW,CAAC,CAAA;IACtD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,MAAM,CAAA;IACvD,OAAO,KAAK,SAAS,IAAI,WAAW,IAAI,SAAS,EAAE,CAAA;AACrD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAgB;IAIpD,MAAM,CAAC,EAAE,SAAS,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACtD,OAAO;QACL,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE;QAC1D,WAAW,EAAE,WAAW;YACtB,CAAC,CAAC,kBAAkB,CAAC,WAAW,CAAC;YACjC,CAAC,CAAC,0BAA0B;KAC/B,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { CapabilityChainDetails, InspectCapabilityChain } from '@interop/zcap';
|
|
2
|
+
import type { CapabilitySummary, RevocationScope, StorageBackend } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* The file name a revocation record is stored (and archived) under:
|
|
5
|
+
* the `(delegator, capabilityId)` unique key folded into a SHA-256 digest,
|
|
6
|
+
* plus `.json`. Both parts are arbitrary-length URIs, so hashing (rather than
|
|
7
|
+
* encoding) keeps the name fixed-width and filesystem-safe. Shared by the
|
|
8
|
+
* filesystem store and both backends' `exportSpace`, so the same record
|
|
9
|
+
* always lands under the same name.
|
|
10
|
+
* @param options {object}
|
|
11
|
+
* @param options.delegator {string} the revoked capability's delegator
|
|
12
|
+
* @param options.capabilityId {string} the revoked capability's id
|
|
13
|
+
* @returns {string}
|
|
14
|
+
*/
|
|
15
|
+
export declare function revocationFileName({ delegator, capabilityId }: {
|
|
16
|
+
delegator: string;
|
|
17
|
+
capabilityId: string;
|
|
18
|
+
}): string;
|
|
19
|
+
/**
|
|
20
|
+
* Extracts the `(capabilityId, delegator)` lookup pairs from a verified,
|
|
21
|
+
* dereferenced capability chain. The root capability is skipped -- root zcaps
|
|
22
|
+
* cannot be revoked -- and so is any link whose verify result carries no
|
|
23
|
+
* delegator (nothing to key a revocation record on).
|
|
24
|
+
*
|
|
25
|
+
* @param options {object}
|
|
26
|
+
* @param options.capabilityChain {object[]} the dereferenced chain (root to
|
|
27
|
+
* tail)
|
|
28
|
+
* @param options.capabilityChainMeta {object[]} the per-capability verify
|
|
29
|
+
* results (the root's entry has a `null` `verifyResult`)
|
|
30
|
+
* @returns {CapabilitySummary[]}
|
|
31
|
+
*/
|
|
32
|
+
export declare function capabilitySummaries({ capabilityChain, capabilityChainMeta }: CapabilityChainDetails): CapabilitySummary[];
|
|
33
|
+
/**
|
|
34
|
+
* Builds the `inspectCapabilityChain` hook for one scope: valid when no
|
|
35
|
+
* delegated capability in the chain has a stored revocation under that
|
|
36
|
+
* keystore or Space (a chain of just the root has nothing to check, so a bare
|
|
37
|
+
* root invocation never reaches the store).
|
|
38
|
+
*
|
|
39
|
+
* @param options {object}
|
|
40
|
+
* @param options.storage {StorageBackend} supplies the revocation store
|
|
41
|
+
* @param options.scope {RevocationScope} the keystore or Space the lookup is
|
|
42
|
+
* keyed on
|
|
43
|
+
* @returns {InspectCapabilityChain}
|
|
44
|
+
*/
|
|
45
|
+
export declare function revocationChainInspector({ storage, scope }: {
|
|
46
|
+
storage: StorageBackend;
|
|
47
|
+
scope: RevocationScope;
|
|
48
|
+
}): InspectCapabilityChain;
|
|
49
|
+
//# sourceMappingURL=revocations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revocations.d.ts","sourceRoot":"","sources":["../../src/lib/revocations.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,sBAAsB,EACtB,sBAAsB,EACvB,MAAM,eAAe,CAAA;AACtB,OAAO,KAAK,EACV,iBAAiB,EACjB,eAAe,EACf,cAAc,EACf,MAAM,aAAa,CAAA;AAEpB;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,SAAS,EACT,YAAY,EACb,EAAE;IACD,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;CACrB,GAAG,MAAM,CAKT;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,eAAe,EACf,mBAAmB,EACpB,EAAE,sBAAsB,GAAG,iBAAiB,EAAE,CAgB9C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,EACvC,OAAO,EACP,KAAK,EACN,EAAE;IACD,OAAO,EAAE,cAAc,CAAA;IACvB,KAAK,EAAE,eAAe,CAAA;CACvB,GAAG,sBAAsB,CAiBzB"}
|