From 0d394bbc3b0a0e338a534a8ab1c15398e8d5e5c9 Mon Sep 17 00:00:00 2001
From: Jon Staab
Date: Thu, 10 Oct 2024 14:33:50 -0700
Subject: [PATCH] Validate space connection before joining
---
src/app/commands.ts | 67 +++++++++++++------
src/app/components/ChannelThread.svelte | 4 +-
.../components/ChatMessageEmojiButton.svelte | 12 ++--
src/app/components/ChatStart.svelte | 12 ++--
src/app/components/EventCreate.svelte | 18 ++---
src/app/components/LogOut.svelte | 10 ++-
src/app/components/RoomCreate.svelte | 5 +-
src/app/components/SpaceCheck.svelte | 66 ++++++++++++++++++
src/app/components/SpaceCreate.svelte | 5 +-
src/app/components/SpaceCreateExternal.svelte | 5 +-
src/app/components/SpaceExit.svelte | 14 ++--
src/app/components/SpaceInviteAccept.svelte | 24 +++----
src/app/components/SpaceJoin.svelte | 5 +-
src/app/components/ThreadCreate.svelte | 18 ++---
src/lib/components/ModalFooter.svelte | 3 +
src/routes/discover/+page.svelte | 16 +++--
src/routes/settings/profile/+page.svelte | 4 +-
.../spaces/[nrelay]/[[room]]/+page.svelte | 4 +-
18 files changed, 204 insertions(+), 88 deletions(-)
create mode 100644 src/app/components/SpaceCheck.svelte
create mode 100644 src/lib/components/ModalFooter.svelte
diff --git a/src/app/commands.ts b/src/app/commands.ts
index 1e4ffde5..ce4bef9c 100644
--- a/src/app/commands.ts
+++ b/src/app/commands.ts
@@ -19,12 +19,12 @@ import {
} from "@welshman/util"
import type {TrustedEvent, EventTemplate} from "@welshman/util"
import type {SubscribeRequestWithHandlers} from "@welshman/net"
+import {PublishStatus, AuthStatus, ConnectionStatus} from "@welshman/net"
import {Nip59, stamp} from "@welshman/signer"
import {
pubkey,
signer,
repository,
- makeThunk,
publishThunk,
loadProfile,
loadInboxRelaySelections,
@@ -40,6 +40,7 @@ import {
userRelaySelections,
userInboxRelaySelections,
nip44EncryptToSelf,
+ loadRelay,
} from "@welshman/app"
import {tagRoom, userMembership, MEMBERSHIPS, INDEXER_RELAYS, loadMembership} from "@app/state"
@@ -112,7 +113,7 @@ export const broadcastUserData = async (relays: string[]) => {
for (const event of events) {
if (isSignedEvent(event)) {
- await publishThunk(makeThunk({event, relays}))
+ await publishThunk({event, relays})
}
}
}
@@ -186,18 +187,46 @@ export const setInboxRelayPolicy = (url: string, enabled: boolean) => {
}
}
-export const joinRelay = async (url: string, claim?: string) => {
- if (claim) {
- await publishThunk(
- makeThunk({
- event: createEvent(28934, {tags: [["claim", claim]]}),
- relays: [url],
- }),
- )
+// Relay access
+
+export const requestRelayAccess = (url: string, claim = "") =>
+ publishThunk({
+ event: createEvent(28934, {tags: [["claim", claim]]}),
+ relays: [url],
+ })
+
+export const attemptRelayAccess = async (url: string, claim = "") => {
+ const relay = await loadRelay(url)
+
+ // Make sure the relay has a profile
+ if (!relay?.profile) {
+ return "Sorry, we weren't able to find that relay."
}
- await setRelayPolicy(url, true, true)
- await broadcastUserData([url])
+ const connection = ctx.net.pool.get(url)
+
+ // Check connection status
+ await connection.ensureConnected()
+
+ if (![ConnectionStatus.Ok, ConnectionStatus.Slow].includes(connection.meta.getStatus())) {
+ return `Failed to connect: "${connection.meta.getDescription()}"`
+ }
+
+ // Attempt to publish a join request
+ const result = await requestRelayAccess(url, claim)
+
+ if (result[url].status !== PublishStatus.Success) {
+ const message = result[url].message?.replace(/^.*: /, '') || "join request rejected"
+
+ return `Failed to join relay: ${message}`
+ }
+
+ // Check auth status
+ await connection.ensureAuth()
+
+ if (![AuthStatus.Ok, AuthStatus.Pending].includes(connection.meta.authStatus)) {
+ return `Failed to authenticate: "${connection.meta.authStatus}"`
+ }
}
// Actions
@@ -213,12 +242,10 @@ export const sendWrapped = async ({
await Promise.all(
uniq(pubkeys).map(async recipient => {
- return publishThunk(
- makeThunk({
- event: await nip59.wrap(recipient, stamp(template)),
- relays: ctx.app.router.PublishMessage(recipient).getUrls(),
- }),
- )
+ return publishThunk({
+ event: await nip59.wrap(recipient, stamp(template)),
+ relays: ctx.app.router.PublishMessage(recipient).getUrls(),
+ })
}),
)
}
@@ -247,10 +274,10 @@ export const publishReaction = ({
event: TrustedEvent
content: string
tags?: string[][]
-}) => publishThunk(makeThunk({event: makeReaction({event, content, tags}), relays}))
+}) => publishThunk({event: makeReaction({event, content, tags}), relays})
export const makeDelete = ({event}: {event: TrustedEvent}) =>
createEvent(DELETE, {tags: [["k", String(event.kind)], ...tagEvent(event)]})
export const publishDelete = ({relays, event}: {relays: string[]; event: TrustedEvent}) =>
- publishThunk(makeThunk({event: makeDelete({event}), relays}))
+ publishThunk({event: makeDelete({event}), relays})
diff --git a/src/app/components/ChannelThread.svelte b/src/app/components/ChannelThread.svelte
index a38860b4..110cc318 100644
--- a/src/app/components/ChannelThread.svelte
+++ b/src/app/components/ChannelThread.svelte
@@ -2,7 +2,7 @@
import {sortBy, append} from "@welshman/lib"
import {createEvent} from "@welshman/util"
import type {EventContent, TrustedEvent} from "@welshman/util"
- import {repository, makeThunk, publishThunk} from "@welshman/app"
+ import {repository, publishThunk} from "@welshman/app"
import {deriveEvents} from "@welshman/store"
import ChannelMessage from "@app/components/ChannelMessage.svelte"
import ChannelCompose from "@app/components/ChannelCompose.svelte"
@@ -39,7 +39,7 @@
const reply = createEvent(REPLY, {content, tags: append(tagRoom(room, url), tags)})
- publishThunk(makeThunk({event: reply, relays: [url]}))
+ publishThunk({event: reply, relays: [url]})
}
diff --git a/src/app/components/ChatMessageEmojiButton.svelte b/src/app/components/ChatMessageEmojiButton.svelte
index 065522f1..d2c62a7b 100644
--- a/src/app/components/ChatMessageEmojiButton.svelte
+++ b/src/app/components/ChatMessageEmojiButton.svelte
@@ -4,7 +4,7 @@
import {ctx, uniq, between} from "@welshman/lib"
import {Nip59} from "@welshman/signer"
import type {TrustedEvent} from "@welshman/util"
- import {makeThunk, signer, publishThunk} from "@welshman/app"
+ import {signer, publishThunk} from "@welshman/app"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import Tippy from "@lib/components/Tippy.svelte"
@@ -23,12 +23,10 @@
for (const recipient of uniq(pubkeys)) {
const rumor = await nip59.wrap(recipient, template)
- publishThunk(
- makeThunk({
- event: rumor.wrap,
- relays: ctx.app.router.PublishMessage(recipient).getUrls(),
- }),
- )
+ publishThunk({
+ event: rumor.wrap,
+ relays: ctx.app.router.PublishMessage(recipient).getUrls(),
+ })
}
popover.hide()
diff --git a/src/app/components/ChatStart.svelte b/src/app/components/ChatStart.svelte
index 952f165f..80246cef 100644
--- a/src/app/components/ChatStart.svelte
+++ b/src/app/components/ChatStart.svelte
@@ -3,6 +3,8 @@
import Field from "@lib/components/Field.svelte"
import Button from "@lib/components/Button.svelte"
import Icon from "@lib/components/Icon.svelte"
+ import ModalHeader from "@lib/components/ModalHeader.svelte"
+ import ModalFooter from "@lib/components/ModalFooter.svelte"
import ProfileMultiSelect from "@app/components/ProfileMultiSelect.svelte"
import {makeChatPath} from "@app/routes"
@@ -16,15 +18,17 @@
diff --git a/src/app/components/EventCreate.svelte b/src/app/components/EventCreate.svelte
index 2e28c5fd..37f32ee8 100644
--- a/src/app/components/EventCreate.svelte
+++ b/src/app/components/EventCreate.svelte
@@ -5,10 +5,12 @@
import {createEditor, type Editor, EditorContent} from "svelte-tiptap"
import {randomId} from "@welshman/lib"
import {createEvent, EVENT_DATE, EVENT_TIME} from "@welshman/util"
- import {publishThunk, makeThunk, dateToSeconds} from "@welshman/app"
+ import {publishThunk, dateToSeconds} from "@welshman/app"
import Icon from "@lib/components/Icon.svelte"
import Field from "@lib/components/Field.svelte"
import Button from "@lib/components/Button.svelte"
+ import ModalHeader from "@lib/components/ModalHeader.svelte"
+ import ModalFooter from "@lib/components/ModalFooter.svelte"
import DateTimeInput from "@lib/components/DateTimeInput.svelte"
import {getPubkeyHints} from "@app/commands"
import {getEditorOptions, addFile, uploadFiles, getEditorTags} from "@lib/editor"
@@ -51,7 +53,7 @@
],
})
- publishThunk(makeThunk({event, relays: [url]}))
+ publishThunk({event, relays: [url]})
clearModal()
}
@@ -68,10 +70,10 @@
diff --git a/src/app/components/LogOut.svelte b/src/app/components/LogOut.svelte
index 484142be..a766be48 100644
--- a/src/app/components/LogOut.svelte
+++ b/src/app/components/LogOut.svelte
@@ -3,6 +3,8 @@
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte"
+ import ModalHeader from "@lib/components/ModalHeader.svelte"
+ import ModalFooter from "@lib/components/ModalFooter.svelte"
const back = () => history.back()
@@ -23,8 +25,10 @@
diff --git a/src/app/components/RoomCreate.svelte b/src/app/components/RoomCreate.svelte
index 1446c038..241e76e5 100644
--- a/src/app/components/RoomCreate.svelte
+++ b/src/app/components/RoomCreate.svelte
@@ -6,6 +6,7 @@
import Button from "@lib/components/Button.svelte"
import Icon from "@lib/components/Icon.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte"
+ import ModalFooter from '@lib/components/ModalFooter.svelte'
import {addRoomMembership} from "@app/commands"
import {makeSpacePath} from "@app/routes"
@@ -46,7 +47,7 @@
-
+
-
+
diff --git a/src/app/components/SpaceCheck.svelte b/src/app/components/SpaceCheck.svelte
new file mode 100644
index 00000000..66571906
--- /dev/null
+++ b/src/app/components/SpaceCheck.svelte
@@ -0,0 +1,66 @@
+
+
+
diff --git a/src/app/components/SpaceCreate.svelte b/src/app/components/SpaceCreate.svelte
index 011b1304..4e63f090 100644
--- a/src/app/components/SpaceCreate.svelte
+++ b/src/app/components/SpaceCreate.svelte
@@ -4,6 +4,7 @@
import Field from "@lib/components/Field.svelte"
import Icon from "@lib/components/Icon.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte"
+ import ModalFooter from "@lib/components/ModalFooter.svelte"
import InfoRelay from "@app/components/InfoRelay.svelte"
import SpaceCreateFinish from "@app/components/SpaceCreateFinish.svelte"
import {pushModal} from "@app/modal"
@@ -43,7 +44,7 @@
-
+
-
+
diff --git a/src/app/components/SpaceCreateExternal.svelte b/src/app/components/SpaceCreateExternal.svelte
index ff8dfca6..c385322b 100644
--- a/src/app/components/SpaceCreateExternal.svelte
+++ b/src/app/components/SpaceCreateExternal.svelte
@@ -3,6 +3,7 @@
import Link from "@lib/components/Link.svelte"
import Icon from "@lib/components/Icon.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte"
+ import ModalFooter from "@lib/components/ModalFooter.svelte"
import SpaceInviteAccept from "@app/components/SpaceInviteAccept.svelte"
import {pushModal} from "@app/modal"
@@ -27,7 +28,7 @@
Once you've created a relay of your own, come back here to link Flotilla with your new relay.
-
+
-
+
diff --git a/src/app/components/SpaceExit.svelte b/src/app/components/SpaceExit.svelte
index c6e810ea..ce1b68b7 100644
--- a/src/app/components/SpaceExit.svelte
+++ b/src/app/components/SpaceExit.svelte
@@ -4,6 +4,8 @@
import Spinner from "@lib/components/Spinner.svelte"
import Button from "@lib/components/Button.svelte"
import Icon from "@lib/components/Icon.svelte"
+ import ModalHeader from "@lib/components/ModalHeader.svelte"
+ import ModalFooter from "@lib/components/ModalFooter.svelte"
import {removeSpaceMembership} from "@app/commands"
export let url
@@ -26,11 +28,13 @@
diff --git a/src/app/components/SpaceInviteAccept.svelte b/src/app/components/SpaceInviteAccept.svelte
index 30b004f9..3a6dc225 100644
--- a/src/app/components/SpaceInviteAccept.svelte
+++ b/src/app/components/SpaceInviteAccept.svelte
@@ -1,6 +1,6 @@