Fix R2 bucket resolution and add coverage

This commit is contained in:
thePR0M3TH3AN committed 2026-01-26 07:40:23 -05:00
1 parent 88c9041716
commit 16b8656521
2 files changed
+93 -16

No files matched your search

+4 -2
View File
@@ -475,7 +475,8 @@ class R2Service {
// We no longer support automated bucket creation or domain management via API token.
// We assume the user has created the bucket with the correct name and configured the public domain.
const bucketName = settings.bucket || sanitizeBucketName(npub);
const bucketName =
settings.bucket || settings.meta?.bucket || sanitizeBucketName(npub);
// We attempt to ensure the bucket exists and CORS is set up using the S3 keys if possible.
if (accessKeyId && secretAccessKey) {
@@ -574,7 +575,8 @@ class R2Service {
return { success: false, error: "Incomplete credentials or missing public URL." };
}
const bucketName = sanitizeBucketName(npub);
const bucketName =
settings.bucket || settings.meta?.bucket || sanitizeBucketName(npub);
const verifyKey = `.verify-${Date.now()}-${Math.random().toString(36).substring(7)}.txt`;
const verifyContent = "bitvid-verification";
const publicUrl = buildPublicUrl(baseDomain, verifyKey);
+89 -14
View File
@@ -1,16 +1,36 @@
import test from "node:test";
import assert from "node:assert";
import r2Service from "../../js/services/r2Service.js";
import storageService from "../../js/services/storageService.js";
// Ensure localStorage is mocked
import "../../tests/test-helpers/setup-localstorage.mjs";
test("js/services/r2Service.js", async (t) => {
const originalNostrTools = globalThis.window?.NostrTools;
const originalStorageMethods = {
listConnections: storageService.listConnections,
getConnection: storageService.getConnection,
isUnlocked: storageService.isUnlocked,
};
t.beforeEach(async () => {
localStorage.clear();
await r2Service.clearSettings();
});
t.afterEach(() => {
storageService.listConnections = originalStorageMethods.listConnections;
storageService.getConnection = originalStorageMethods.getConnection;
storageService.isUnlocked = originalStorageMethods.isUnlocked;
if (originalNostrTools === undefined) {
delete globalThis.window.NostrTools;
} else {
globalThis.window.NostrTools = originalNostrTools;
}
});
await t.test("Default Settings", () => {
const settings = r2Service.getSettings();
// The actual default settings might contain more fields than we checked.
@@ -31,13 +51,7 @@ test("js/services/r2Service.js", async (t) => {
};
const result = await r2Service.handleCloudflareSettingsSubmit(input);
assert.strictEqual(result, true);
const saved = r2Service.getSettings();
assert.strictEqual(saved.accountId, input.accountId);
assert.strictEqual(saved.accessKeyId, input.accessKeyId);
assert.strictEqual(saved.secretAccessKey, input.secretAccessKey);
assert.strictEqual(saved.baseDomain, input.baseDomain);
assert.strictEqual(result, false);
});
await t.test("handleCloudflareSettingsSubmit - Invalid S3 URL", async () => {
@@ -53,7 +67,7 @@ test("js/services/r2Service.js", async (t) => {
const result = await r2Service.handleCloudflareSettingsSubmit(input);
assert.strictEqual(result, false);
assert.match(status, /entered the S3 API URL/);
assert.match(status, /Legacy settings are disabled/);
cleanup();
});
@@ -74,8 +88,8 @@ test("js/services/r2Service.js", async (t) => {
const npub = "npub1test";
const credentials = {
accountId: "acc123",
accessKeyId: "key123",
secretAccessKey: "secret123",
accessKeyId: "",
secretAccessKey: "",
baseDomain: "https://pub-xxx.r2.dev",
bucket: "custom-bucket",
isLegacy: true,
@@ -87,7 +101,70 @@ test("js/services/r2Service.js", async (t) => {
assert.strictEqual(result.customDomainStatus, "manual");
});
await t.test("resolveConnection - Returns Legacy Settings if no StorageService", async () => {
await t.test("ensureBucketConfigForNpub - Uses Meta Bucket when Missing", async () => {
const npub = "npub1testmeta";
const credentials = {
accountId: "acc456",
accessKeyId: "",
secretAccessKey: "",
baseDomain: "https://pub-meta.r2.dev",
meta: {
bucket: "meta-bucket",
},
isLegacy: false,
};
const result = await r2Service.ensureBucketConfigForNpub(npub, { credentials });
assert.strictEqual(result.entry.bucket, "meta-bucket");
});
await t.test("resolveConnection - Maps meta bucket into settings", async () => {
const npub = "npub1metaresolve";
const pubkeyHex = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd";
globalThis.window.NostrTools = {
nip19: {
decode(value) {
if (value === npub) {
return { type: "npub", data: pubkeyHex };
}
throw new Error("Unexpected npub");
},
},
};
storageService.listConnections = async () => [
{
id: "default",
provider: "cloudflare_r2",
meta: {
defaultForUploads: true,
bucket: "meta-bucket",
publicBaseUrl: "https://pub-meta.r2.dev",
accountId: "acc456",
},
},
];
storageService.isUnlocked = () => true;
storageService.getConnection = async () => ({
provider: "cloudflare_r2",
accountId: "acc456",
accessKeyId: "key456",
secretAccessKey: "secret456",
baseDomain: "https://pub-meta.r2.dev",
publicBaseUrl: "https://pub-meta.r2.dev",
meta: {
bucket: "meta-bucket",
publicBaseUrl: "https://pub-meta.r2.dev",
},
});
const resolved = await r2Service.resolveConnection(npub);
assert.ok(resolved);
assert.strictEqual(resolved.bucket, "meta-bucket");
});
await t.test("resolveConnection - Returns null without StorageService entries", async () => {
const input = {
accountId: "legacyAcc",
accessKeyId: "legacyKey",
@@ -99,8 +176,6 @@ test("js/services/r2Service.js", async (t) => {
const npub = "npub1any";
const resolved = await r2Service.resolveConnection(npub);
assert.ok(resolved);
assert.strictEqual(resolved.accountId, "legacyAcc");
assert.strictEqual(resolved.isLegacy, true);
assert.strictEqual(resolved, null);
});
});