mirror of
https://github.com/block/buzz.git
synced 2026-11-01 23:11:58 +00:00
Fix production relay onboarding safety
Co-authored-by: npub1cl47vfhsqpqy9pwndphpm36vcp7vvz5h2js4qpqm5yewzj7nutkq7xyw8c <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz> Signed-off-by: npub1cl47vfhsqpqy9pwndphpm36vcp7vvz5h2js4qpqm5yewzj7nutkq7xyw8c <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
This commit is contained in:
parent
12293366fd
commit
dc8d7b824f
@@ -54,6 +54,8 @@ test("signed-build relay defaults auto-connect during first-run onboarding", ()
|
||||
);
|
||||
assert.equal(shouldAutoConnectDefaultRelay("ws://localhost:3000"), false);
|
||||
assert.equal(shouldAutoConnectDefaultRelay("ws://127.0.0.1:3000"), false);
|
||||
assert.equal(shouldAutoConnectDefaultRelay("ws://[::1]:3000"), false);
|
||||
assert.equal(shouldAutoConnectDefaultRelay("ws://0.0.0.0:3000"), false);
|
||||
assert.equal(shouldAutoConnectDefaultRelay("not a valid relay"), false);
|
||||
});
|
||||
|
||||
|
||||
@@ -81,8 +81,11 @@ export function loadCommunities(): Community[] {
|
||||
}
|
||||
}
|
||||
|
||||
export function saveCommunities(communities: Community[]): void {
|
||||
setLocalStorageItemWithRecovery(COMMUNITIES_KEY, JSON.stringify(communities));
|
||||
export function saveCommunities(communities: Community[]): boolean {
|
||||
return setLocalStorageItemWithRecovery(
|
||||
COMMUNITIES_KEY,
|
||||
JSON.stringify(communities),
|
||||
);
|
||||
}
|
||||
|
||||
export function clearCommunityStorage(storage: Storage = localStorage): void {
|
||||
@@ -97,8 +100,8 @@ export function loadActiveCommunityId(): string | null {
|
||||
return localStorage.getItem(ACTIVE_COMMUNITY_KEY);
|
||||
}
|
||||
|
||||
export function saveActiveCommunityId(id: string): void {
|
||||
setLocalStorageItemWithRecovery(ACTIVE_COMMUNITY_KEY, id);
|
||||
export function saveActiveCommunityId(id: string): boolean {
|
||||
return setLocalStorageItemWithRecovery(ACTIVE_COMMUNITY_KEY, id);
|
||||
}
|
||||
|
||||
export function normalizeRelayUrl(url: string): string {
|
||||
@@ -111,7 +114,9 @@ export function normalizeRelayUrl(url: string): string {
|
||||
export function shouldAutoConnectDefaultRelay(relayUrl: string): boolean {
|
||||
try {
|
||||
const parsed = new URL(normalizeRelayUrl(relayUrl));
|
||||
return parsed.hostname !== "localhost" && parsed.hostname !== "127.0.0.1";
|
||||
return !["localhost", "127.0.0.1", "[::1]", "0.0.0.0"].includes(
|
||||
parsed.hostname,
|
||||
);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
@@ -145,7 +150,7 @@ export function initFirstCommunity(
|
||||
relayUrl: string,
|
||||
pubkey: string,
|
||||
name?: string,
|
||||
): Community {
|
||||
): Community | null {
|
||||
const normalizedUrl = normalizeRelayUrl(relayUrl);
|
||||
const trimmedName = name?.trim();
|
||||
const community: Community = {
|
||||
@@ -155,7 +160,16 @@ export function initFirstCommunity(
|
||||
pubkey,
|
||||
addedAt: new Date().toISOString(),
|
||||
};
|
||||
saveCommunities([community]);
|
||||
saveActiveCommunityId(community.id);
|
||||
const didSaveCommunities = saveCommunities([community]);
|
||||
const didSaveActiveCommunity =
|
||||
didSaveCommunities && saveActiveCommunityId(community.id);
|
||||
|
||||
// The quota-recovery helper reports failure instead of throwing. Do not let
|
||||
// callers reload unless both writes landed; otherwise first launch can loop.
|
||||
if (!didSaveCommunities || !didSaveActiveCommunity) {
|
||||
clearCommunityStorage();
|
||||
return null;
|
||||
}
|
||||
|
||||
return community;
|
||||
}
|
||||
|
||||
@@ -107,9 +107,20 @@ export function useCommunityInit(
|
||||
) {
|
||||
const identity = await getIdentity();
|
||||
if (cancelled) return;
|
||||
initFirstCommunity(defaultRelayUrl, identity.pubkey);
|
||||
if (!cancelled) {
|
||||
const community = initFirstCommunity(
|
||||
defaultRelayUrl,
|
||||
identity.pubkey,
|
||||
);
|
||||
if (community && !cancelled) {
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
if (!cancelled) {
|
||||
setResult({
|
||||
isReady: false,
|
||||
needsSetup: true,
|
||||
defaultRelayUrl,
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -571,7 +571,7 @@ test("first-community choices route join, create, owner, and member intents", as
|
||||
);
|
||||
}, BLANK_TYLER_IDENTITY.pubkey);
|
||||
await installMockBridge(page, undefined, {
|
||||
relayWsUrl: "wss://default.example.com",
|
||||
relayWsUrl: "ws://localhost:3000",
|
||||
skipOnboardingSeed: true,
|
||||
skipCommunitySeed: true,
|
||||
});
|
||||
@@ -657,7 +657,7 @@ test("first-community owner can connect an existing hosted community", async ({
|
||||
],
|
||||
},
|
||||
{
|
||||
relayWsUrl: "wss://default.example.com",
|
||||
relayWsUrl: "ws://localhost:3000",
|
||||
skipOnboardingSeed: true,
|
||||
skipCommunitySeed: true,
|
||||
},
|
||||
@@ -715,7 +715,7 @@ test("first-community owner can create and connect a hosted community", async ({
|
||||
page,
|
||||
{},
|
||||
{
|
||||
relayWsUrl: "wss://default.example.com",
|
||||
relayWsUrl: "ws://localhost:3000",
|
||||
skipOnboardingSeed: true,
|
||||
skipCommunitySeed: true,
|
||||
},
|
||||
@@ -789,7 +789,7 @@ test("hosted community address line stays within the card for a long name", asyn
|
||||
page,
|
||||
{},
|
||||
{
|
||||
relayWsUrl: "wss://default.example.com",
|
||||
relayWsUrl: "ws://localhost:3000",
|
||||
skipOnboardingSeed: true,
|
||||
skipCommunitySeed: true,
|
||||
},
|
||||
@@ -860,7 +860,7 @@ test("first-community reports a created community without a relay address", asyn
|
||||
},
|
||||
},
|
||||
{
|
||||
relayWsUrl: "wss://default.example.com",
|
||||
relayWsUrl: "ws://localhost:3000",
|
||||
skipOnboardingSeed: true,
|
||||
skipCommunitySeed: true,
|
||||
},
|
||||
@@ -891,7 +891,7 @@ test("first-community X cancels a pending sign-in", async ({ page }) => {
|
||||
page,
|
||||
{ builderlabLoginDelayMs: 5_000 },
|
||||
{
|
||||
relayWsUrl: "wss://default.example.com",
|
||||
relayWsUrl: "ws://localhost:3000",
|
||||
skipOnboardingSeed: true,
|
||||
skipCommunitySeed: true,
|
||||
},
|
||||
@@ -933,7 +933,7 @@ test("first-community owner can replace a mismatched account identity", async ({
|
||||
builderlabIdentity: { pubkey_hex: "f".repeat(64) },
|
||||
},
|
||||
{
|
||||
relayWsUrl: "wss://default.example.com",
|
||||
relayWsUrl: "ws://localhost:3000",
|
||||
skipOnboardingSeed: true,
|
||||
skipCommunitySeed: true,
|
||||
},
|
||||
@@ -983,7 +983,7 @@ test("first-community explains when the local identity belongs to another accoun
|
||||
builderlabBindError: { code: "pubkey_already_bound" },
|
||||
},
|
||||
{
|
||||
relayWsUrl: "wss://default.example.com",
|
||||
relayWsUrl: "ws://localhost:3000",
|
||||
skipOnboardingSeed: true,
|
||||
skipCommunitySeed: true,
|
||||
},
|
||||
@@ -1024,7 +1024,7 @@ test("back clears Builderlab auth before returning to first-community choices",
|
||||
builderlabIdentity: { pubkey_hex: BLANK_TYLER_IDENTITY.pubkey },
|
||||
},
|
||||
{
|
||||
relayWsUrl: "wss://default.example.com",
|
||||
relayWsUrl: "ws://localhost:3000",
|
||||
skipOnboardingSeed: true,
|
||||
skipCommunitySeed: true,
|
||||
},
|
||||
@@ -1112,7 +1112,7 @@ test("first-community direct join reaches profile", async ({ page }) => {
|
||||
);
|
||||
}, BLANK_TYLER_IDENTITY.pubkey);
|
||||
await installMockBridge(page, undefined, {
|
||||
relayWsUrl: "wss://onboarding.communities.buzz.xyz",
|
||||
relayWsUrl: "ws://localhost:3000",
|
||||
skipOnboardingSeed: true,
|
||||
skipCommunitySeed: true,
|
||||
});
|
||||
@@ -1167,7 +1167,7 @@ test("first-community direct join cancel returns to request access", async ({
|
||||
page,
|
||||
{ applyCommunityDelayMs: 5_000 },
|
||||
{
|
||||
relayWsUrl: "wss://onboarding.communities.buzz.xyz",
|
||||
relayWsUrl: "ws://localhost:3000",
|
||||
skipOnboardingSeed: true,
|
||||
skipCommunitySeed: true,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user