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
package/dist/lib/etag.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helpers for the HTTP `ETag` strong validator that backs conditional writes
|
|
3
|
+
* (the `conditional-writes` feature). A Resource's monotonic `version` is
|
|
4
|
+
* formatted as a quoted strong validator on the wire, and incoming `If-Match` /
|
|
5
|
+
* `If-None-Match` request headers are normalized into write preconditions.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Formats a Resource's monotonic `version` as a quoted strong `ETag` validator
|
|
9
|
+
* (e.g. version 3 to `"3"`). The quotes are part of the on-the-wire value, and
|
|
10
|
+
* `If-Match` comparison is exact-string (strong) comparison.
|
|
11
|
+
* @param version {number}
|
|
12
|
+
* @returns {string}
|
|
13
|
+
*/
|
|
14
|
+
export function formatEtag(version) {
|
|
15
|
+
return `"${version}"`;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Normalizes the `If-Match` / `If-None-Match` request headers into the write
|
|
19
|
+
* preconditions the storage layer evaluates. Only `If-None-Match: *`
|
|
20
|
+
* (create-if-absent) is supported; an `If-Match` value is passed through as the
|
|
21
|
+
* quoted ETag to match. A header that is absent (or, for an array-valued header,
|
|
22
|
+
* not a single string) contributes no precondition.
|
|
23
|
+
* @param headers {object}
|
|
24
|
+
* @param [headers.if-match] {string | string[]}
|
|
25
|
+
* @param [headers.if-none-match] {string | string[]}
|
|
26
|
+
* @returns {{ ifMatch?: string, ifNoneMatch?: boolean }}
|
|
27
|
+
*/
|
|
28
|
+
export function parseWritePreconditions(headers) {
|
|
29
|
+
const ifMatch = headers['if-match'];
|
|
30
|
+
const ifNoneMatch = headers['if-none-match'];
|
|
31
|
+
return {
|
|
32
|
+
...(typeof ifMatch === 'string' && { ifMatch }),
|
|
33
|
+
...(ifNoneMatch === '*' && { ifNoneMatch: true })
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=etag.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"etag.js","sourceRoot":"","sources":["../../src/lib/etag.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,OAAe;IACxC,OAAO,IAAI,OAAO,GAAG,CAAA;AACvB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,uBAAuB,CAAC,OAGvC;IACC,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;IACnC,MAAM,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;IAC5C,OAAO;QACL,GAAG,CAAC,OAAO,OAAO,KAAK,QAAQ,IAAI,EAAE,OAAO,EAAE,CAAC;QAC/C,GAAG,CAAC,WAAW,KAAK,GAAG,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;KAClD,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One top-level entry of the Space being exported, in archive order: a
|
|
3
|
+
* Space-level file (`files` absent) or a Collection directory with its ordered
|
|
4
|
+
* file names.
|
|
5
|
+
*/
|
|
6
|
+
export interface ExportSpaceEntry {
|
|
7
|
+
name: string;
|
|
8
|
+
/** present for a Collection directory: its file names, in archive order */
|
|
9
|
+
files?: string[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Builds the UBC v0.1 manifest object for a Space export. The caller supplies
|
|
13
|
+
* the archive's top-level entries in the order they will be packed (Space-level
|
|
14
|
+
* files interleaved with Collection directories); the manifest mirrors that
|
|
15
|
+
* order.
|
|
16
|
+
* @param options {object}
|
|
17
|
+
* @param options.spaceId {string}
|
|
18
|
+
* @param options.entries {ExportSpaceEntry[]} ordered top-level entries
|
|
19
|
+
* @param [options.revocationFiles] {string[]} ordered file names of the
|
|
20
|
+
* archive's Space-scoped zcap revocation records (`revocations/` entries);
|
|
21
|
+
* omitted from the manifest when the Space has none
|
|
22
|
+
* @returns {object} the manifest document (serialize with `YAML.stringify`)
|
|
23
|
+
*/
|
|
24
|
+
export declare function buildExportManifest({ spaceId, entries, revocationFiles }: {
|
|
25
|
+
spaceId: string;
|
|
26
|
+
entries: ExportSpaceEntry[];
|
|
27
|
+
revocationFiles?: string[];
|
|
28
|
+
}): object;
|
|
29
|
+
//# sourceMappingURL=exportManifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exportManifest.d.ts","sourceRoot":"","sources":["../../src/lib/exportManifest.ts"],"names":[],"mappings":"AAgBA;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;CACjB;AAyBD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,OAAO,EACP,OAAO,EACP,eAAoB,EACrB,EAAE;IACD,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,gBAAgB,EAAE,CAAA;IAC3B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;CAC3B,GAAG,MAAM,CAiCT"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Backend-agnostic builder for the Space-export `manifest.yml` document (UBC
|
|
3
|
+
* v0.1, FEP-6fcd). Both storage backends synthesize the same archive layout --
|
|
4
|
+
* `space/<spaceId>/...` entries in the filesystem backend's on-disk file-name
|
|
5
|
+
* dialect -- so an archive exported from one backend imports into the other;
|
|
6
|
+
* this module is the single home for the manifest that describes it.
|
|
7
|
+
*/
|
|
8
|
+
import { UBC_MANIFEST_URL, SPACE_URL, COLLECTION_URL, RESOURCE_URL, POLICY_URL, META_URL } from '../config.default.js';
|
|
9
|
+
/**
|
|
10
|
+
* Classifies one Collection-dir file name into its manifest entry: the known
|
|
11
|
+
* dot-file kinds and resource representations get a documenting `url`, anything
|
|
12
|
+
* else is listed by bare name.
|
|
13
|
+
* @param fileName {string}
|
|
14
|
+
* @returns {unknown}
|
|
15
|
+
*/
|
|
16
|
+
function collectionManifestEntry(fileName) {
|
|
17
|
+
if (fileName.startsWith('.collection.')) {
|
|
18
|
+
return { [fileName]: { url: COLLECTION_URL } };
|
|
19
|
+
}
|
|
20
|
+
if (fileName.startsWith('.policy.')) {
|
|
21
|
+
return { [fileName]: { url: POLICY_URL } };
|
|
22
|
+
}
|
|
23
|
+
if (fileName.startsWith('.meta.')) {
|
|
24
|
+
return { [fileName]: { url: META_URL } };
|
|
25
|
+
}
|
|
26
|
+
if (fileName.startsWith('r.')) {
|
|
27
|
+
return { [fileName]: { url: RESOURCE_URL } };
|
|
28
|
+
}
|
|
29
|
+
return fileName;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Builds the UBC v0.1 manifest object for a Space export. The caller supplies
|
|
33
|
+
* the archive's top-level entries in the order they will be packed (Space-level
|
|
34
|
+
* files interleaved with Collection directories); the manifest mirrors that
|
|
35
|
+
* order.
|
|
36
|
+
* @param options {object}
|
|
37
|
+
* @param options.spaceId {string}
|
|
38
|
+
* @param options.entries {ExportSpaceEntry[]} ordered top-level entries
|
|
39
|
+
* @param [options.revocationFiles] {string[]} ordered file names of the
|
|
40
|
+
* archive's Space-scoped zcap revocation records (`revocations/` entries);
|
|
41
|
+
* omitted from the manifest when the Space has none
|
|
42
|
+
* @returns {object} the manifest document (serialize with `YAML.stringify`)
|
|
43
|
+
*/
|
|
44
|
+
export function buildExportManifest({ spaceId, entries, revocationFiles = [] }) {
|
|
45
|
+
const spaceContents = [];
|
|
46
|
+
for (const entry of entries) {
|
|
47
|
+
if (entry.files === undefined) {
|
|
48
|
+
// top-level files in space (e.g. .space.<spaceId>.json)
|
|
49
|
+
spaceContents.push(entry.name);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
spaceContents.push({
|
|
53
|
+
[entry.name]: {
|
|
54
|
+
contents: entry.files.map(collectionManifestEntry)
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
'ubc-version': '0.1',
|
|
60
|
+
contents: {
|
|
61
|
+
'manifest.yml': { url: UBC_MANIFEST_URL },
|
|
62
|
+
...(revocationFiles.length > 0 && {
|
|
63
|
+
revocations: { contents: [...revocationFiles] }
|
|
64
|
+
}),
|
|
65
|
+
space: {
|
|
66
|
+
url: SPACE_URL,
|
|
67
|
+
contents: {
|
|
68
|
+
[spaceId]: {
|
|
69
|
+
url: SPACE_URL,
|
|
70
|
+
contents: spaceContents
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=exportManifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exportManifest.js","sourceRoot":"","sources":["../../src/lib/exportManifest.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,gBAAgB,EAChB,SAAS,EACT,cAAc,EACd,YAAY,EACZ,UAAU,EACV,QAAQ,EACT,MAAM,sBAAsB,CAAA;AAa7B;;;;;;GAMG;AACH,SAAS,uBAAuB,CAAC,QAAgB;IAC/C,IAAI,QAAQ,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QACxC,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,cAAc,EAAE,EAAE,CAAA;IAChD,CAAC;IACD,IAAI,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACpC,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,CAAA;IAC5C,CAAC;IACD,IAAI,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClC,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,CAAA;IAC1C,CAAC;IACD,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,YAAY,EAAE,EAAE,CAAA;IAC9C,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAClC,OAAO,EACP,OAAO,EACP,eAAe,GAAG,EAAE,EAKrB;IACC,MAAM,aAAa,GAAc,EAAE,CAAA;IACnC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC9B,wDAAwD;YACxD,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YAC9B,SAAQ;QACV,CAAC;QACD,aAAa,CAAC,IAAI,CAAC;YACjB,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;gBACZ,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,uBAAuB,CAAC;aACnD;SACF,CAAC,CAAA;IACJ,CAAC;IAED,OAAO;QACL,aAAa,EAAE,KAAK;QACpB,QAAQ,EAAE;YACR,cAAc,EAAE,EAAE,GAAG,EAAE,gBAAgB,EAAE;YACzC,GAAG,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,IAAI;gBAChC,WAAW,EAAE,EAAE,QAAQ,EAAE,CAAC,GAAG,eAAe,CAAC,EAAE;aAChD,CAAC;YACF,KAAK,EAAE;gBACL,GAAG,EAAE,SAAS;gBACd,QAAQ,EAAE;oBACR,CAAC,OAAO,CAAC,EAAE;wBACT,GAAG,EAAE,SAAS;wBACd,QAAQ,EAAE,aAAa;qBACxB;iBACF;aACF;SACF;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { Readable } from 'node:stream';
|
|
2
|
+
import type { CollectionDescription, PolicyDocument, RevocationRecord } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* If `fileName` is a metadata sidecar (`.meta.<resourceId>.json`), returns the
|
|
5
|
+
* `<resourceId>` it is keyed by; otherwise undefined.
|
|
6
|
+
* @param fileName {string}
|
|
7
|
+
* @returns {string | undefined}
|
|
8
|
+
*/
|
|
9
|
+
export declare function metaSidecarFileId(fileName: string): string | undefined;
|
|
10
|
+
/** One extracted archive entry, keyed by its archive path. */
|
|
11
|
+
export interface TarEntry {
|
|
12
|
+
type: 'file' | 'directory';
|
|
13
|
+
body?: Buffer;
|
|
14
|
+
}
|
|
15
|
+
/** One resource staged for import by {@link buildImportPlan}. */
|
|
16
|
+
export interface ImportPlanResource {
|
|
17
|
+
fileName: string;
|
|
18
|
+
resourceId: string;
|
|
19
|
+
body: Buffer;
|
|
20
|
+
}
|
|
21
|
+
/** One collection (plus its resources and policies) staged for import. */
|
|
22
|
+
export interface ImportPlanCollection {
|
|
23
|
+
collectionId: string;
|
|
24
|
+
collectionDescription: CollectionDescription;
|
|
25
|
+
/** Collection-level access-control policy, if the archive carries one. */
|
|
26
|
+
collectionPolicy?: PolicyDocument;
|
|
27
|
+
resources: ImportPlanResource[];
|
|
28
|
+
/** Resource-level policies, keyed by resourceId. */
|
|
29
|
+
resourcePolicies: Map<string, PolicyDocument>;
|
|
30
|
+
/** Resource metadata sidecars (raw `.meta.<id>.json` bytes), keyed by resourceId. */
|
|
31
|
+
resourceMetadata: Map<string, Buffer>;
|
|
32
|
+
}
|
|
33
|
+
/** The merge plan produced by {@link buildImportPlan}. */
|
|
34
|
+
export interface ImportPlan {
|
|
35
|
+
/** Space-level access-control policy, if the archive carries one. */
|
|
36
|
+
spacePolicy?: PolicyDocument;
|
|
37
|
+
collections: ImportPlanCollection[];
|
|
38
|
+
/**
|
|
39
|
+
* Space-scoped zcap revocation records the archive carries (top-level
|
|
40
|
+
* `revocations/` entries), restored under the destination Space's scope.
|
|
41
|
+
*/
|
|
42
|
+
revocations: RevocationRecord[];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* @param options {object}
|
|
46
|
+
* @param options.tarStream {Readable}
|
|
47
|
+
* @returns {Promise<Map<string, TarEntry>>}
|
|
48
|
+
*/
|
|
49
|
+
export declare function extractTarEntries(tarStream: Readable): Promise<Map<string, TarEntry>>;
|
|
50
|
+
/**
|
|
51
|
+
* Validates that the archive carries a well-formed UBC v0.1 `manifest.yml`
|
|
52
|
+
* describing a WAS space export. Throws on any problem.
|
|
53
|
+
* @param entries {Map<string, TarEntry>}
|
|
54
|
+
* @returns {void}
|
|
55
|
+
*/
|
|
56
|
+
export declare function validateManifest(entries: Map<string, TarEntry>): void;
|
|
57
|
+
/**
|
|
58
|
+
* Build a merge plan from a WAS space export tarball.
|
|
59
|
+
*
|
|
60
|
+
* Expected archive layout (UBC v0.1, produced by exportSpace):
|
|
61
|
+
* - manifest.yml
|
|
62
|
+
* - revocations/<digest>.json (Space-scoped zcap revocations; optional)
|
|
63
|
+
* - space/
|
|
64
|
+
* - space/<sourceSpaceId>/
|
|
65
|
+
* - space/<sourceSpaceId>/.space.<sourceSpaceId>.json (space metadata; ignored on import)
|
|
66
|
+
* - space/<sourceSpaceId>/.policy.<sourceSpaceId>.json (space-level policy)
|
|
67
|
+
* - space/<sourceSpaceId>/<collectionId>/
|
|
68
|
+
* - space/<sourceSpaceId>/<collectionId>/.collection.<collectionId>.json
|
|
69
|
+
* - space/<sourceSpaceId>/<collectionId>/.policy.<collectionId>.json (collection policy)
|
|
70
|
+
* - space/<sourceSpaceId>/<collectionId>/.policy.<resourceId>.json (resource policy)
|
|
71
|
+
* - space/<sourceSpaceId>/<collectionId>/r.<resourceId>.<encodedContentType>.<ext>
|
|
72
|
+
*
|
|
73
|
+
* The source space id in the path may differ from the import target; collection
|
|
74
|
+
* metadata, r.* resource files, and `.policy.*` policy files are merged into the
|
|
75
|
+
* destination.
|
|
76
|
+
*
|
|
77
|
+
* @param entries {Map<string, TarEntry>}
|
|
78
|
+
* @returns {ImportPlan}
|
|
79
|
+
*/
|
|
80
|
+
export declare function buildImportPlan(entries: Map<string, TarEntry>): ImportPlan;
|
|
81
|
+
//# sourceMappingURL=importTar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"importTar.d.ts","sourceRoot":"","sources":["../../src/lib/importTar.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAI3C,OAAO,KAAK,EACV,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EACjB,MAAM,aAAa,CAAA;AAmCpB;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEtE;AAED,8DAA8D;AAC9D,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,GAAG,WAAW,CAAA;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,iEAAiE;AACjE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,0EAA0E;AAC1E,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,MAAM,CAAA;IACpB,qBAAqB,EAAE,qBAAqB,CAAA;IAC5C,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,cAAc,CAAA;IACjC,SAAS,EAAE,kBAAkB,EAAE,CAAA;IAC/B,oDAAoD;IACpD,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;IAC7C,qFAAqF;IACrF,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACtC;AAED,0DAA0D;AAC1D,MAAM,WAAW,UAAU;IACzB,qEAAqE;IACrE,WAAW,CAAC,EAAE,cAAc,CAAA;IAC5B,WAAW,EAAE,oBAAoB,EAAE,CAAA;IACnC;;;OAGG;IACH,WAAW,EAAE,gBAAgB,EAAE,CAAA;CAChC;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,QAAQ,GAClB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAiChC;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,IAAI,CA6BrE;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,UAAU,CAyI1E"}
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import * as tar from 'tar-stream';
|
|
2
|
+
import YAML from 'yaml';
|
|
3
|
+
import { assertValidId } from './validateId.js';
|
|
4
|
+
import { parseResourceFileName } from './resourceFileName.js';
|
|
5
|
+
import { InvalidImportError } from '../errors.js';
|
|
6
|
+
/** Suffix shared by the description / policy / metadata dot-files. */
|
|
7
|
+
const JSON_SUFFIX = '.json';
|
|
8
|
+
/** Prefix of a policy dot-file (`.policy.<id>.json`). */
|
|
9
|
+
const POLICY_PREFIX = '.policy.';
|
|
10
|
+
/** Prefix of a resource metadata sidecar (`.meta.<id>.json`). */
|
|
11
|
+
const META_PREFIX = '.meta.';
|
|
12
|
+
/**
|
|
13
|
+
* If `fileName` is a dot-file with the given prefix and `.json` suffix, returns
|
|
14
|
+
* the `<id>` between them; otherwise undefined. Uses slice (not split) so ids
|
|
15
|
+
* containing dots (URL-safe `.` is allowed) round-trip correctly.
|
|
16
|
+
* @param fileName {string}
|
|
17
|
+
* @param prefix {string}
|
|
18
|
+
* @returns {string | undefined}
|
|
19
|
+
*/
|
|
20
|
+
function dotFileId(fileName, prefix) {
|
|
21
|
+
if (!fileName.startsWith(prefix) || !fileName.endsWith(JSON_SUFFIX)) {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
const id = fileName.slice(prefix.length, -JSON_SUFFIX.length);
|
|
25
|
+
return id.length > 0 ? id : undefined;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* If `fileName` is a policy dot-file (`.policy.<id>.json`), returns the `<id>`
|
|
29
|
+
* it is keyed by; otherwise undefined.
|
|
30
|
+
* @param fileName {string}
|
|
31
|
+
* @returns {string | undefined}
|
|
32
|
+
*/
|
|
33
|
+
function policyFileId(fileName) {
|
|
34
|
+
return dotFileId(fileName, POLICY_PREFIX);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* If `fileName` is a metadata sidecar (`.meta.<resourceId>.json`), returns the
|
|
38
|
+
* `<resourceId>` it is keyed by; otherwise undefined.
|
|
39
|
+
* @param fileName {string}
|
|
40
|
+
* @returns {string | undefined}
|
|
41
|
+
*/
|
|
42
|
+
export function metaSidecarFileId(fileName) {
|
|
43
|
+
return dotFileId(fileName, META_PREFIX);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* @param options {object}
|
|
47
|
+
* @param options.tarStream {Readable}
|
|
48
|
+
* @returns {Promise<Map<string, TarEntry>>}
|
|
49
|
+
*/
|
|
50
|
+
export async function extractTarEntries(tarStream) {
|
|
51
|
+
const entries = new Map();
|
|
52
|
+
await new Promise((resolve, reject) => {
|
|
53
|
+
const extract = tar.extract();
|
|
54
|
+
extract.on('entry', (header, stream, next) => {
|
|
55
|
+
if (header.type === 'directory') {
|
|
56
|
+
entries.set(header.name, { type: 'directory' });
|
|
57
|
+
stream.resume();
|
|
58
|
+
next();
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const chunks = [];
|
|
62
|
+
stream.on('data', chunk => chunks.push(Buffer.from(chunk)));
|
|
63
|
+
stream.on('end', () => {
|
|
64
|
+
entries.set(header.name, {
|
|
65
|
+
type: 'file',
|
|
66
|
+
body: Buffer.concat(chunks)
|
|
67
|
+
});
|
|
68
|
+
next();
|
|
69
|
+
});
|
|
70
|
+
stream.on('error', reject);
|
|
71
|
+
});
|
|
72
|
+
extract.on('finish', resolve);
|
|
73
|
+
extract.on('error', reject);
|
|
74
|
+
tarStream.on('error', reject);
|
|
75
|
+
tarStream.pipe(extract);
|
|
76
|
+
});
|
|
77
|
+
return entries;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Validates that the archive carries a well-formed UBC v0.1 `manifest.yml`
|
|
81
|
+
* describing a WAS space export. Throws on any problem.
|
|
82
|
+
* @param entries {Map<string, TarEntry>}
|
|
83
|
+
* @returns {void}
|
|
84
|
+
*/
|
|
85
|
+
export function validateManifest(entries) {
|
|
86
|
+
const manifestEntry = entries.get('manifest.yml');
|
|
87
|
+
if (!manifestEntry?.body) {
|
|
88
|
+
throw new InvalidImportError({
|
|
89
|
+
message: 'Archive is missing manifest.yml.'
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
let manifest;
|
|
93
|
+
try {
|
|
94
|
+
manifest = YAML.parse(manifestEntry.body.toString('utf8'));
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
throw new InvalidImportError({
|
|
98
|
+
message: 'Archive manifest.yml is not valid YAML.',
|
|
99
|
+
cause: err
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
if (manifest['ubc-version'] !== '0.1') {
|
|
103
|
+
throw new InvalidImportError({
|
|
104
|
+
message: 'Unsupported archive manifest version.'
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
if (!manifest.contents?.space) {
|
|
108
|
+
throw new InvalidImportError({
|
|
109
|
+
message: 'Archive manifest does not describe a WAS space export.'
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Build a merge plan from a WAS space export tarball.
|
|
115
|
+
*
|
|
116
|
+
* Expected archive layout (UBC v0.1, produced by exportSpace):
|
|
117
|
+
* - manifest.yml
|
|
118
|
+
* - revocations/<digest>.json (Space-scoped zcap revocations; optional)
|
|
119
|
+
* - space/
|
|
120
|
+
* - space/<sourceSpaceId>/
|
|
121
|
+
* - space/<sourceSpaceId>/.space.<sourceSpaceId>.json (space metadata; ignored on import)
|
|
122
|
+
* - space/<sourceSpaceId>/.policy.<sourceSpaceId>.json (space-level policy)
|
|
123
|
+
* - space/<sourceSpaceId>/<collectionId>/
|
|
124
|
+
* - space/<sourceSpaceId>/<collectionId>/.collection.<collectionId>.json
|
|
125
|
+
* - space/<sourceSpaceId>/<collectionId>/.policy.<collectionId>.json (collection policy)
|
|
126
|
+
* - space/<sourceSpaceId>/<collectionId>/.policy.<resourceId>.json (resource policy)
|
|
127
|
+
* - space/<sourceSpaceId>/<collectionId>/r.<resourceId>.<encodedContentType>.<ext>
|
|
128
|
+
*
|
|
129
|
+
* The source space id in the path may differ from the import target; collection
|
|
130
|
+
* metadata, r.* resource files, and `.policy.*` policy files are merged into the
|
|
131
|
+
* destination.
|
|
132
|
+
*
|
|
133
|
+
* @param entries {Map<string, TarEntry>}
|
|
134
|
+
* @returns {ImportPlan}
|
|
135
|
+
*/
|
|
136
|
+
export function buildImportPlan(entries) {
|
|
137
|
+
validateManifest(entries);
|
|
138
|
+
let sourceSpaceId;
|
|
139
|
+
for (const name of entries.keys()) {
|
|
140
|
+
const match = name.match(/^space\/([^/]+)\//);
|
|
141
|
+
if (match) {
|
|
142
|
+
sourceSpaceId = match[1];
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (!sourceSpaceId) {
|
|
147
|
+
throw new InvalidImportError({
|
|
148
|
+
message: 'Archive does not contain space data.'
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
const prefix = `space/${sourceSpaceId}/`;
|
|
152
|
+
// Space-level policy (`.policy.<sourceSpaceId>.json` at the space root).
|
|
153
|
+
const spacePolicyEntry = entries.get(`${prefix}.policy.${sourceSpaceId}.json`);
|
|
154
|
+
const spacePolicy = spacePolicyEntry?.body
|
|
155
|
+
? JSON.parse(spacePolicyEntry.body.toString('utf8'))
|
|
156
|
+
: undefined;
|
|
157
|
+
const collectionIds = new Set();
|
|
158
|
+
for (const name of entries.keys()) {
|
|
159
|
+
if (!name.startsWith(prefix)) {
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
const match = name.slice(prefix.length).match(/^([^/]+)\//);
|
|
163
|
+
if (match?.[1]) {
|
|
164
|
+
// Reject a path-traversal / non-URL-safe id parsed from the archive
|
|
165
|
+
// before it is used to build a destination path.
|
|
166
|
+
assertValidId(match[1], {
|
|
167
|
+
kind: 'collection',
|
|
168
|
+
requestName: 'Import Space'
|
|
169
|
+
});
|
|
170
|
+
collectionIds.add(match[1]);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const collections = [...collectionIds].sort().map(collectionId => {
|
|
174
|
+
const collectionMetaKey = `${prefix}${collectionId}/.collection.${collectionId}.json`;
|
|
175
|
+
const metaEntry = entries.get(collectionMetaKey);
|
|
176
|
+
const collectionDescription = metaEntry?.body
|
|
177
|
+
? JSON.parse(metaEntry.body.toString('utf8'))
|
|
178
|
+
: { id: collectionId, type: ['Collection'], name: collectionId };
|
|
179
|
+
const collectionPrefix = `${prefix}${collectionId}/`;
|
|
180
|
+
const resources = [];
|
|
181
|
+
let collectionPolicy;
|
|
182
|
+
const resourcePolicies = new Map();
|
|
183
|
+
const resourceMetadata = new Map();
|
|
184
|
+
for (const [entryName, entry] of entries) {
|
|
185
|
+
if (!entryName.startsWith(collectionPrefix) ||
|
|
186
|
+
entry.type !== 'file' ||
|
|
187
|
+
!entry.body) {
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
const fileName = entryName.slice(collectionPrefix.length);
|
|
191
|
+
if (fileName.includes('/')) {
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
// Policy dot-files: `.policy.<collectionId>.json` is the Collection policy;
|
|
195
|
+
// `.policy.<resourceId>.json` is a Resource policy keyed by resource id.
|
|
196
|
+
const policyId = policyFileId(fileName);
|
|
197
|
+
if (policyId !== undefined) {
|
|
198
|
+
const policy = JSON.parse(entry.body.toString('utf8'));
|
|
199
|
+
if (policyId === collectionId) {
|
|
200
|
+
collectionPolicy = policy;
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
// Reject a path-traversal / non-URL-safe id parsed from the archive.
|
|
204
|
+
assertValidId(policyId, {
|
|
205
|
+
kind: 'resource',
|
|
206
|
+
requestName: 'Import Space'
|
|
207
|
+
});
|
|
208
|
+
resourcePolicies.set(policyId, policy);
|
|
209
|
+
}
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
// Metadata sidecar (`.meta.<resourceId>.json`): carried as raw bytes,
|
|
213
|
+
// keyed by resourceId. Written alongside a newly-created resource
|
|
214
|
+
// (preserving its timestamps and user-writable `custom`), or -- for a
|
|
215
|
+
// tombstone, whose content file is gone -- on its own as an orphan sidecar
|
|
216
|
+
// (see `importSpace`).
|
|
217
|
+
const metaId = metaSidecarFileId(fileName);
|
|
218
|
+
if (metaId !== undefined) {
|
|
219
|
+
assertValidId(metaId, { kind: 'resource', requestName: 'Import Space' });
|
|
220
|
+
resourceMetadata.set(metaId, entry.body);
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
if (!fileName.startsWith('r.')) {
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
const parts = fileName.split('.');
|
|
227
|
+
if (parts.length < 4 || !parts[1]) {
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
// Decode the dot-escaped id segment (see `fileNameFor`) so a dotted id
|
|
231
|
+
// (e.g. `index.html`) round-trips. The `fileName` is preserved verbatim
|
|
232
|
+
// (the bytes are written under their stored name); only the parsed
|
|
233
|
+
// `resourceId` -- used for dedup, sidecar, and policy keying -- is decoded.
|
|
234
|
+
const { resourceId } = parseResourceFileName(fileName);
|
|
235
|
+
// Reject a path-traversal / non-URL-safe resource id parsed from the
|
|
236
|
+
// archive before its bytes are written to a destination path.
|
|
237
|
+
assertValidId(resourceId, {
|
|
238
|
+
kind: 'resource',
|
|
239
|
+
requestName: 'Import Space'
|
|
240
|
+
});
|
|
241
|
+
resources.push({
|
|
242
|
+
fileName,
|
|
243
|
+
resourceId,
|
|
244
|
+
body: entry.body
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
collectionId,
|
|
249
|
+
collectionDescription,
|
|
250
|
+
collectionPolicy,
|
|
251
|
+
resources,
|
|
252
|
+
resourcePolicies,
|
|
253
|
+
resourceMetadata
|
|
254
|
+
};
|
|
255
|
+
});
|
|
256
|
+
return { spacePolicy, collections, revocations: revocationRecords(entries) };
|
|
257
|
+
}
|
|
258
|
+
/** Prefix of the archive's Space-scoped revocation entries. */
|
|
259
|
+
const REVOCATIONS_PREFIX = 'revocations/';
|
|
260
|
+
/**
|
|
261
|
+
* Parses the archive's Space-scoped zcap revocation records (top-level
|
|
262
|
+
* `revocations/<digest>.json` entries; see `revocationFileName`). Archives
|
|
263
|
+
* from servers that predate revocation export carry none, which yields an
|
|
264
|
+
* empty list. A record that is not JSON or lacks the `(capability.id,
|
|
265
|
+
* meta.delegator)` unique key rejects the import -- the store's file names
|
|
266
|
+
* and uniqueness gate are derived from those fields.
|
|
267
|
+
* @param entries {Map<string, TarEntry>}
|
|
268
|
+
* @returns {RevocationRecord[]}
|
|
269
|
+
*/
|
|
270
|
+
function revocationRecords(entries) {
|
|
271
|
+
const records = [];
|
|
272
|
+
for (const [entryName, entry] of entries) {
|
|
273
|
+
if (!entryName.startsWith(REVOCATIONS_PREFIX) ||
|
|
274
|
+
entry.type !== 'file' ||
|
|
275
|
+
!entry.body ||
|
|
276
|
+
entryName.slice(REVOCATIONS_PREFIX.length).includes('/')) {
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
let record;
|
|
280
|
+
try {
|
|
281
|
+
record = JSON.parse(entry.body.toString('utf8'));
|
|
282
|
+
}
|
|
283
|
+
catch (err) {
|
|
284
|
+
throw new InvalidImportError({
|
|
285
|
+
message: `Archive revocation record "${entryName}" is not valid JSON.`,
|
|
286
|
+
cause: err
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
if (typeof record?.capability?.id !== 'string' ||
|
|
290
|
+
record.capability.id.length === 0 ||
|
|
291
|
+
typeof record?.meta?.delegator !== 'string' ||
|
|
292
|
+
record.meta.delegator.length === 0) {
|
|
293
|
+
throw new InvalidImportError({
|
|
294
|
+
message: `Archive revocation record "${entryName}" is malformed.`
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
records.push(record);
|
|
298
|
+
}
|
|
299
|
+
return records;
|
|
300
|
+
}
|
|
301
|
+
//# sourceMappingURL=importTar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"importTar.js","sourceRoot":"","sources":["../../src/lib/importTar.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helper: true if a content-type denotes JSON -- `application/json` or any
|
|
3
|
+
* `application/<prefix>+json` structured-suffix variant (e.g.
|
|
4
|
+
* `application/ld+json`, `application/vnd.api+json`), each optionally followed
|
|
5
|
+
* by parameters (`; charset=utf-8`). The `json` token is anchored to the end of
|
|
6
|
+
* the media type so non-JSON types that merely begin with `json` --
|
|
7
|
+
* `application/jsonl`, `application/json-seq`, `application/json5` -- are NOT
|
|
8
|
+
* treated as JSON and instead take the binary blob path.
|
|
9
|
+
* @param options {object}
|
|
10
|
+
* @param options.contentType {string}
|
|
11
|
+
* @returns {boolean}
|
|
12
|
+
*/
|
|
13
|
+
export declare function isJson({ contentType }: {
|
|
14
|
+
contentType?: string;
|
|
15
|
+
}): boolean;
|
|
16
|
+
//# sourceMappingURL=isJson.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isJson.d.ts","sourceRoot":"","sources":["../../src/lib/isJson.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,wBAAgB,MAAM,CAAC,EAAE,WAAW,EAAE,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAKzE"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helper: true if a content-type denotes JSON -- `application/json` or any
|
|
3
|
+
* `application/<prefix>+json` structured-suffix variant (e.g.
|
|
4
|
+
* `application/ld+json`, `application/vnd.api+json`), each optionally followed
|
|
5
|
+
* by parameters (`; charset=utf-8`). The `json` token is anchored to the end of
|
|
6
|
+
* the media type so non-JSON types that merely begin with `json` --
|
|
7
|
+
* `application/jsonl`, `application/json-seq`, `application/json5` -- are NOT
|
|
8
|
+
* treated as JSON and instead take the binary blob path.
|
|
9
|
+
* @param options {object}
|
|
10
|
+
* @param options.contentType {string}
|
|
11
|
+
* @returns {boolean}
|
|
12
|
+
*/
|
|
13
|
+
export function isJson({ contentType }) {
|
|
14
|
+
return (typeof contentType === 'string' &&
|
|
15
|
+
/^application\/(?:[^+\s;]+\+)?json\s*(?:;.*)?$/i.test(contentType));
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=isJson.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isJson.js","sourceRoot":"","sources":["../../src/lib/isJson.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,MAAM,CAAC,EAAE,WAAW,EAA4B;IAC9D,OAAO,CACL,OAAO,WAAW,KAAK,QAAQ;QAC/B,gDAAgD,CAAC,IAAI,CAAC,WAAW,CAAC,CACnE,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** The request header carrying the client-declared key-epoch on a content write. */
|
|
2
|
+
export declare const KEY_EPOCH_HEADER = "was-key-epoch";
|
|
3
|
+
/**
|
|
4
|
+
* Parses the OPTIONAL `WAS-Key-Epoch` request header into the epoch stamp for a
|
|
5
|
+
* content write. Resolves `{ epoch: string }` for a non-empty single-valued
|
|
6
|
+
* header, `{ epoch: undefined }` when absent (the content write clears any
|
|
7
|
+
* stored stamp), and throws `invalid-request-body` (400) for an empty or
|
|
8
|
+
* array-valued header.
|
|
9
|
+
* @param options {object}
|
|
10
|
+
* @param options.headers {object} the Fastify request headers
|
|
11
|
+
* @param [options.requestName] {string} request name for the 400 error title
|
|
12
|
+
* @returns {{ epoch?: string }}
|
|
13
|
+
*/
|
|
14
|
+
export declare function parseKeyEpochHeader({ headers, requestName }: {
|
|
15
|
+
headers: Record<string, string | string[] | undefined>;
|
|
16
|
+
requestName?: string;
|
|
17
|
+
}): {
|
|
18
|
+
epoch?: string;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Validates and extracts the OPTIONAL top-level `epoch` member of an Update
|
|
22
|
+
* Resource Metadata (`PUT .../meta`) body. Unlike a content write, a metadata
|
|
23
|
+
* write PRESERVES the stored epoch when the member is omitted (the stamp
|
|
24
|
+
* describes the content write, not the metadata write); a present value must be
|
|
25
|
+
* a non-empty string (400 otherwise). Returns `{ epoch: string }` when supplied,
|
|
26
|
+
* or `{}` when the member is absent (preserve).
|
|
27
|
+
* @param options {object}
|
|
28
|
+
* @param options.body {object} the parsed request body (already known to be an object)
|
|
29
|
+
* @param [options.requestName] {string} request name for the 400 error title
|
|
30
|
+
* @returns {{ epoch?: string }}
|
|
31
|
+
*/
|
|
32
|
+
export declare function parseMetaEpoch({ body, requestName }: {
|
|
33
|
+
body: Record<string, unknown>;
|
|
34
|
+
requestName?: string;
|
|
35
|
+
}): {
|
|
36
|
+
epoch?: string;
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=keyEpoch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyEpoch.d.ts","sourceRoot":"","sources":["../../src/lib/keyEpoch.ts"],"names":[],"mappings":"AAuBA,oFAAoF;AACpF,eAAO,MAAM,gBAAgB,kBAAkB,CAAA;AAE/C;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,OAAO,EACP,WAAW,EACZ,EAAE;IACD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAA;IACtD,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAYrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,WAAW,EACZ,EAAE;IACD,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAarB"}
|