mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-29 00:42:30 +00:00
141 lines
6.1 KiB
JavaScript
141 lines
6.1 KiB
JavaScript
// Real storage helper + SDK wrapper; only SDK classes and S3 transport are fake.
|
|
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { registerHooks } from "node:module";
|
|
|
|
const commandNames = ["S3Client", "HeadBucketCommand", "CreateBucketCommand", "GetBucketCorsCommand", "PutBucketCorsCommand"];
|
|
const hooks = registerHooks({
|
|
resolve(specifier, context, nextResolve) {
|
|
if (specifier.startsWith("https://esm.sh/@aws-sdk/client-s3@")) {
|
|
return { url: "offline:storage-cors-sdk", shortCircuit: true };
|
|
}
|
|
if (/^https?:/.test(specifier)) throw new Error("Network forbidden in CORS fixtures");
|
|
return nextResolve(specifier, context);
|
|
},
|
|
load(url, context, nextLoad) {
|
|
if (url === "offline:storage-cors-sdk") {
|
|
return { format: "module", shortCircuit: true, source: commandNames.map(name =>
|
|
`export class ${name} { constructor(input) { this.input = input; } }`
|
|
).join("\n") };
|
|
}
|
|
return nextLoad(url, context);
|
|
},
|
|
});
|
|
// The full runner disables network imports globally. Our hook supplies the SDK locally.
|
|
globalThis.__BITVID_DISABLE_NETWORK_IMPORTS__ = false;
|
|
const { ensureS3SdkLoaded } = await import("../js/storage/s3-client.js");
|
|
await ensureS3SdkLoaded();
|
|
const { ensureBucketCors } = await import("../js/storage/s3-multipart.js");
|
|
hooks.deregister();
|
|
globalThis.__BITVID_DISABLE_NETWORK_IMPORTS__ = true;
|
|
|
|
const first = "https://first.example.invalid";
|
|
const second = "https://second.example.invalid";
|
|
const third = "https://third.example.invalid";
|
|
const custom = { ID: "read-only", AllowedOrigins: [first], AllowedMethods: ["GET"], AllowedHeaders: ["Range"], ExposeHeaders: ["ETag"], MaxAgeSeconds: 75 };
|
|
const defaults = origins => ({ AllowedHeaders: ["*"], AllowedMethods: ["GET", "HEAD", "PUT", "POST", "DELETE", "OPTIONS"], AllowedOrigins: origins, ExposeHeaders: ["ETag", "Content-Length", "Content-Range", "Accept-Ranges"], MaxAgeSeconds: 3600 });
|
|
function transport(rules, readError) {
|
|
return {
|
|
policy: rules === null ? null : { CORSRules: structuredClone(rules) }, puts: 0, calls: [],
|
|
async send(command) {
|
|
const name = command.constructor.name;
|
|
this.calls.push(name);
|
|
assert.equal(command.input.Bucket, "offline-bucket");
|
|
if (name === "HeadBucketCommand") return {};
|
|
if (name === "GetBucketCorsCommand") {
|
|
if (readError) throw readError;
|
|
if (this.policy === null) throw Object.assign(new Error("No policy"), { name: "NoSuchCORSConfiguration" });
|
|
return structuredClone(this.policy);
|
|
}
|
|
if (name === "PutBucketCorsCommand") {
|
|
this.puts++;
|
|
this.policy = structuredClone(command.input.CORSConfiguration);
|
|
return {};
|
|
}
|
|
throw new Error(`Unexpected command ${name}`);
|
|
},
|
|
};
|
|
}
|
|
const ensure = (s3, origins) => ensureBucketCors({ s3, bucket: "offline-bucket", origins });
|
|
|
|
test("adding a second origin preserves the complete existing custom policy", async () => {
|
|
const s3 = transport([custom]);
|
|
await ensure(s3, [second]);
|
|
assert.deepEqual(s3.policy, { CORSRules: [custom, defaults([second])] });
|
|
assert.equal(s3.puts, 1);
|
|
});
|
|
|
|
test("wildcard and multiple custom rules keep their fields and order", async () => {
|
|
const wildcard = { ...custom, ID: "wildcard", AllowedOrigins: ["*"], AllowedHeaders: ["X-Custom"], AllowedMethods: ["HEAD"], ExtraField: "preserve" };
|
|
const s3 = transport([wildcard, custom]);
|
|
await ensure(s3, [second]);
|
|
assert.deepEqual(s3.policy, { CORSRules: [wildcard, custom, defaults([second])] });
|
|
});
|
|
|
|
test("duplicate origins and repeated calls are idempotent without another PUT", async () => {
|
|
const s3 = transport([custom]);
|
|
await ensure(s3, [second, second, null, ""]);
|
|
const once = structuredClone(s3.policy);
|
|
assert.deepEqual(once, { CORSRules: [custom, defaults([second])] });
|
|
await ensure(s3, [second, second]);
|
|
assert.deepEqual(s3.policy, once);
|
|
assert.equal(s3.puts, 1);
|
|
});
|
|
|
|
test("equivalent default rules cover origins across rules regardless of array order", async () => {
|
|
const existing = [defaults([first]), { ...defaults([second]), AllowedMethods: [...defaults([]).AllowedMethods].reverse() }];
|
|
const s3 = transport(existing);
|
|
await ensure(s3, [first, second]);
|
|
assert.deepEqual(s3.policy, { CORSRules: existing });
|
|
assert.equal(s3.puts, 0);
|
|
});
|
|
|
|
test("similar rules with different non-origin permissions do not cover a new request", async () => {
|
|
for (const override of [
|
|
{ AllowedMethods: ["GET"] },
|
|
{ AllowedHeaders: ["Range"] },
|
|
{ ExposeHeaders: ["ETag"] },
|
|
{ MaxAgeSeconds: 75 },
|
|
{ ExtraField: "preserve" },
|
|
]) {
|
|
const existing = { ...defaults([second]), ...override };
|
|
const s3 = transport([existing]);
|
|
await ensure(s3, [second]);
|
|
assert.deepEqual(s3.policy, { CORSRules: [existing, defaults([second])] });
|
|
assert.equal(s3.puts, 1);
|
|
}
|
|
});
|
|
|
|
test("only uncovered origins receive a separate rule", async () => {
|
|
const existing = [defaults([first]), custom];
|
|
const s3 = transport(existing);
|
|
await ensure(s3, [first, second, third]);
|
|
assert.deepEqual(s3.policy, { CORSRules: [...existing, defaults([second, third])] });
|
|
});
|
|
|
|
test("an explicit absent policy creates defaults and then skips repeated writes", async () => {
|
|
const s3 = transport(null);
|
|
await ensure(s3, [first]);
|
|
assert.deepEqual(s3.policy, { CORSRules: [defaults([first])] });
|
|
await ensure(s3, [first]);
|
|
assert.equal(s3.puts, 1);
|
|
});
|
|
|
|
test("all other policy read failures reject unchanged without PUT", async () => {
|
|
for (const error of [Object.assign(new Error("Denied"), { name: "AccessDenied" }), Object.assign(new Error("Not found"), { name: "NoSuchBucket", $metadata: { httpStatusCode: 404 } }), new Error("Transport failed")]) {
|
|
const s3 = transport([custom], error);
|
|
await assert.rejects(ensure(s3, [second]), actual => actual === error);
|
|
assert.deepEqual(s3.policy, { CORSRules: [custom] });
|
|
assert.equal(s3.puts, 0);
|
|
}
|
|
});
|
|
|
|
test("empty or missing origins perform no IO and preserve policy", async () => {
|
|
for (const origins of [[], undefined, [null, "", false]]) {
|
|
const s3 = transport([custom]);
|
|
await ensure(s3, origins);
|
|
assert.deepEqual(s3.calls, []);
|
|
assert.deepEqual(s3.policy, { CORSRules: [custom] });
|
|
}
|
|
});
|