diff --git a/CHANGELOG.md b/CHANGELOG.md
index af36526..c29c491 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,7 @@
* Add `created_at` to event info dialog
* Add signer status to profile page
* Re-work bunker login flow
+* Only protect events if relay authenticates
# 1.2.2
@@ -25,7 +26,7 @@
* Fix sort order of thread comments
* Fix link display when no title is available
-* Fix making profiles non-protected
+* Fix making profiles non-protect
* Replace bunker url with relay claims for notifier auth
* Add push notifications on all platforms
* Add "mark all as read" on desktop
diff --git a/src/app/commands.ts b/src/app/commands.ts
index 9ec577e..63c2e4f 100644
--- a/src/app/commands.ts
+++ b/src/app/commands.ts
@@ -214,10 +214,19 @@ export const setInboxRelayPolicy = (url: string, enabled: boolean) => {
// Relay access
-export const attemptAuth = (url: string) =>
- Pool.get()
- .get(url)
- .auth.attemptAuth(e => signer.get()?.sign(e))
+export const attemptAuth = async (url: string) => {
+ const socket = Pool.get().get(url)
+
+ await socket.auth.attemptAuth(e => signer.get()?.sign(e))
+}
+
+export const canEnforceNip70 = async (url: string) => {
+ const socket = Pool.get().get(url)
+
+ await socket.auth.attemptAuth(e => signer.get()?.sign(e))
+
+ return socket.auth.status !== AuthStatus.None
+}
export const checkRelayAccess = async (url: string, claim = "") => {
const socket = Pool.get().get(url)
@@ -305,26 +314,29 @@ export const attemptRelayAccess = async (url: string, claim = "") => {
// Actions
-export const makeDelete = ({event, tags = []}: {event: TrustedEvent; tags?: string[][]}) => {
+export type DeleteParams = {
+ protect: boolean
+ event: TrustedEvent
+ tags?: string[][]
+}
+
+export const makeDelete = ({protect, event, tags = []}: DeleteParams) => {
const thisTags = [["k", String(event.kind)], ...tagEvent(event), ...tags]
const groupTag = getTag("h", event.tags)
if (groupTag) {
- thisTags.push(PROTECTED, groupTag)
+ thisTags.push(groupTag)
+ }
+
+ if (protect) {
+ thisTags.push(PROTECTED)
}
return makeEvent(DELETE, {tags: thisTags})
}
-export const publishDelete = ({
- relays,
- event,
- tags = [],
-}: {
- relays: string[]
- event: TrustedEvent
- tags?: string[][]
-}) => publishThunk({event: makeDelete({event, tags}), relays})
+export const publishDelete = ({relays, ...params}: DeleteParams & {relays: string[]}) =>
+ publishThunk({event: makeDelete(params), relays})
export type ReportParams = {
event: TrustedEvent
@@ -350,21 +362,24 @@ export const publishReport = ({
publishThunk({event: makeReport({event, reason, content}), relays})
export type ReactionParams = {
+ protect: boolean
event: TrustedEvent
content: string
tags?: string[][]
}
-export const makeReaction = ({content, event, tags: paramTags = []}: ReactionParams) => {
+export const makeReaction = ({protect, content, event, tags: paramTags = []}: ReactionParams) => {
const tags = [...paramTags, ...tagEventForReaction(event)]
-
const groupTag = getTag("h", event.tags)
if (groupTag) {
- tags.push(PROTECTED)
tags.push(groupTag)
}
+ if (protect) {
+ tags.push(PROTECTED)
+ }
+
return makeEvent(REACTION, {content, tags})
}
diff --git a/src/app/components/AlertDelete.svelte b/src/app/components/AlertDelete.svelte
index 6f0830e..ba0878c 100644
--- a/src/app/components/AlertDelete.svelte
+++ b/src/app/components/AlertDelete.svelte
@@ -12,7 +12,10 @@
const {alert}: Props = $props()
const confirm = () => {
- publishDelete({event: alert.event, relays: [NOTIFIER_RELAY], tags: [["p", NOTIFIER_PUBKEY]]})
+ const relays = [NOTIFIER_RELAY]
+ const tags = [["p", NOTIFIER_PUBKEY]]
+
+ publishDelete({event: alert.event, relays, tags, protect: false})
pushToast({message: "Your alert has been deleted!"})
history.back()
}
diff --git a/src/app/components/CalendarEventActions.svelte b/src/app/components/CalendarEventActions.svelte
index 7d71ccd..a932640 100644
--- a/src/app/components/CalendarEventActions.svelte
+++ b/src/app/components/CalendarEventActions.svelte
@@ -8,7 +8,7 @@
import EventActivity from "@app/components/EventActivity.svelte"
import EventActions from "@app/components/EventActions.svelte"
import CalendarEventEdit from "@app/components/CalendarEventEdit.svelte"
- import {publishDelete, publishReaction} from "@app/commands"
+ import {publishDelete, publishReaction, canEnforceNip70} from "@app/commands"
import {makeCalendarPath} from "@app/routes"
import {pushModal} from "@app/modal"
@@ -26,10 +26,11 @@
const editEvent = () => pushModal(CalendarEventEdit, {url, event})
- const deleteReaction = (event: TrustedEvent) => publishDelete({relays: [url], event})
+ const deleteReaction = async (event: TrustedEvent) =>
+ publishDelete({relays: [url], event, protect: await canEnforceNip70(url)})
- const createReaction = (template: EventContent) =>
- publishReaction({...template, event, relays: [url]})
+ const createReaction = async (template: EventContent) =>
+ publishReaction({...template, event, relays: [url], protect: await canEnforceNip70(url)})
diff --git a/src/app/components/CalendarEventForm.svelte b/src/app/components/CalendarEventForm.svelte
index d3cdf41..8cc32e1 100644
--- a/src/app/components/CalendarEventForm.svelte
+++ b/src/app/components/CalendarEventForm.svelte
@@ -16,6 +16,7 @@
import {PROTECTED} from "@app/state"
import {makeEditor} from "@app/editor"
import {pushToast} from "@app/toast"
+ import {canEnforceNip70} from "@app/commands"
type Props = {
url: string
@@ -63,19 +64,22 @@
}
const ed = await editor
- const event = makeEvent(EVENT_TIME, {
- content: ed.getText({blockSeparator: "\n"}).trim(),
- tags: [
- ["d", initialValues?.d || randomId()],
- ["title", title],
- ["location", location || ""],
- ["start", start.toString()],
- ["end", end.toString()],
- ...daysBetween(start, end).map(D => ["D", D.toString()]),
- ...ed.storage.nostr.getEditorTags(),
- PROTECTED,
- ],
- })
+ const content = ed.getText({blockSeparator: "\n"}).trim()
+ const tags = [
+ ["d", initialValues?.d || randomId()],
+ ["title", title],
+ ["location", location || ""],
+ ["start", start.toString()],
+ ["end", end.toString()],
+ ...daysBetween(start, end).map(D => ["D", D.toString()]),
+ ...ed.storage.nostr.getEditorTags(),
+ ]
+
+ if (await canEnforceNip70(url)) {
+ tags.push(PROTECTED)
+ }
+
+ const event = makeEvent(EVENT_TIME, {content, tags})
pushToast({message: "Your event has been saved!"})
publishThunk({event, relays: [url]})
diff --git a/src/app/components/ChannelMessage.svelte b/src/app/components/ChannelMessage.svelte
index 830c9e7..c6a1db4 100644
--- a/src/app/components/ChannelMessage.svelte
+++ b/src/app/components/ChannelMessage.svelte
@@ -16,7 +16,7 @@
import ChannelMessageMenuButton from "@app/components/ChannelMessageMenuButton.svelte"
import ChannelMessageMenuMobile from "@app/components/ChannelMessageMenuMobile.svelte"
import {colors, ENABLE_ZAPS} from "@app/state"
- import {publishDelete, publishReaction} from "@app/commands"
+ import {publishDelete, publishReaction, canEnforceNip70} from "@app/commands"
import {pushModal} from "@app/modal"
interface Props {
@@ -41,10 +41,11 @@
const openProfile = () => pushModal(ProfileDetail, {pubkey: event.pubkey, url})
- const deleteReaction = (event: TrustedEvent) => publishDelete({relays: [url], event})
+ const deleteReaction = async (event: TrustedEvent) =>
+ publishDelete({relays: [url], event, protect: await canEnforceNip70(url)})
- const createReaction = (template: EventContent) =>
- publishReaction({...template, event, relays: [url]})
+ const createReaction = async (template: EventContent) =>
+ publishReaction({...template, event, relays: [url], protect: await canEnforceNip70(url)})
- publishReaction({event, relays: [url], content: emoji.unicode})
+ const onEmoji = async (emoji: NativeEmoji) =>
+ publishReaction({
+ event,
+ relays: [url],
+ content: emoji.unicode,
+ protect: await canEnforceNip70(url),
+ })
diff --git a/src/app/components/ChannelMessageMenuMobile.svelte b/src/app/components/ChannelMessageMenuMobile.svelte
index 10dd013..44be192 100644
--- a/src/app/components/ChannelMessageMenuMobile.svelte
+++ b/src/app/components/ChannelMessageMenuMobile.svelte
@@ -9,7 +9,7 @@
import EventInfo from "@app/components/EventInfo.svelte"
import EventDeleteConfirm from "@app/components/EventDeleteConfirm.svelte"
import {ENABLE_ZAPS} from "@app/state"
- import {publishReaction} from "@app/commands"
+ import {publishReaction, canEnforceNip70} from "@app/commands"
import {pushModal} from "@app/modal"
type Props = {
@@ -20,9 +20,14 @@
const {url, event, reply}: Props = $props()
- const onEmoji = ((event: TrustedEvent, url: string, emoji: NativeEmoji) => {
+ const onEmoji = (async (event: TrustedEvent, url: string, emoji: NativeEmoji) => {
history.back()
- publishReaction({event, relays: [url], content: emoji.unicode})
+ publishReaction({
+ event,
+ relays: [url],
+ content: emoji.unicode,
+ protect: await canEnforceNip70(url),
+ })
}).bind(undefined, event, url)
const showEmojiPicker = () => pushModal(EmojiPicker, {onClick: onEmoji}, {replaceState: true})
diff --git a/src/app/components/ChatMessage.svelte b/src/app/components/ChatMessage.svelte
index 6b67d26..2464025 100644
--- a/src/app/components/ChatMessage.svelte
+++ b/src/app/components/ChatMessage.svelte
@@ -37,10 +37,10 @@
const reply = () => replyTo(event)
const deleteReaction = (event: TrustedEvent) =>
- sendWrapped({template: makeDelete({event}), pubkeys})
+ sendWrapped({template: makeDelete({event, protect: false}), pubkeys})
const createReaction = (template: EventContent) =>
- sendWrapped({template: makeReaction({event, ...template}), pubkeys})
+ sendWrapped({template: makeReaction({event, protect: false, ...template}), pubkeys})
const openProfile = () => pushModal(ProfileDetail, {pubkey: event.pubkey})
diff --git a/src/app/components/ChatMessageEmojiButton.svelte b/src/app/components/ChatMessageEmojiButton.svelte
index 159ef29..3abe04c 100644
--- a/src/app/components/ChatMessageEmojiButton.svelte
+++ b/src/app/components/ChatMessageEmojiButton.svelte
@@ -14,7 +14,7 @@
const {event, pubkeys}: Props = $props()
const onEmoji = (emoji: NativeEmoji) =>
- sendWrapped({template: makeReaction({event, content: emoji.unicode}), pubkeys})
+ sendWrapped({template: makeReaction({event, content: emoji.unicode, protect: false}), pubkeys})
diff --git a/src/app/components/ChatMessageMenuMobile.svelte b/src/app/components/ChatMessageMenuMobile.svelte
index 5d147c7..1b977e2 100644
--- a/src/app/components/ChatMessageMenuMobile.svelte
+++ b/src/app/components/ChatMessageMenuMobile.svelte
@@ -20,7 +20,7 @@
const onEmoji = ((event: TrustedEvent, pubkeys: string[], emoji: NativeEmoji) => {
history.back()
- sendWrapped({template: makeReaction({event, content: emoji.unicode}), pubkeys})
+ sendWrapped({template: makeReaction({event, content: emoji.unicode, protect: false}), pubkeys})
}).bind(undefined, event, pubkeys)
const showEmojiPicker = () => pushModal(EmojiPicker, {onClick: onEmoji}, {replaceState: true})
diff --git a/src/app/components/CommentActions.svelte b/src/app/components/CommentActions.svelte
index faf6ed7..e0b16bf 100644
--- a/src/app/components/CommentActions.svelte
+++ b/src/app/components/CommentActions.svelte
@@ -4,7 +4,7 @@
import ThunkStatusOrDeleted from "@app/components/ThunkStatusOrDeleted.svelte"
import EventActivity from "@app/components/EventActivity.svelte"
import EventActions from "@app/components/EventActions.svelte"
- import {publishDelete, publishReaction} from "@app/commands"
+ import {publishDelete, publishReaction, canEnforceNip70} from "@app/commands"
import {makeThreadPath} from "@app/routes"
interface Props {
@@ -17,10 +17,11 @@
const path = makeThreadPath(url, event.id)
- const deleteReaction = (event: TrustedEvent) => publishDelete({relays: [url], event})
+ const deleteReaction = async (event: TrustedEvent) =>
+ publishDelete({relays: [url], event, protect: await canEnforceNip70(url)})
- const createReaction = (template: EventContent) =>
- publishReaction({...template, event, relays: [url]})
+ const createReaction = async (template: EventContent) =>
+ publishReaction({...template, event, relays: [url], protect: await canEnforceNip70(url)})
diff --git a/src/app/components/EventActions.svelte b/src/app/components/EventActions.svelte
index a608eac..ae9c709 100644
--- a/src/app/components/EventActions.svelte
+++ b/src/app/components/EventActions.svelte
@@ -10,7 +10,7 @@
import EmojiButton from "@lib/components/EmojiButton.svelte"
import EventMenu from "@app/components/EventMenu.svelte"
import {ENABLE_ZAPS} from "@app/state"
- import {publishReaction} from "@app/commands"
+ import {publishReaction, canEnforceNip70} from "@app/commands"
type Props = {
url: string
@@ -26,8 +26,13 @@
const hidePopover = () => popover?.hide()
- const onEmoji = (emoji: NativeEmoji) =>
- publishReaction({event, content: emoji.unicode, relays: [url]})
+ const onEmoji = async (emoji: NativeEmoji) =>
+ publishReaction({
+ event,
+ content: emoji.unicode,
+ relays: [url],
+ protect: await canEnforceNip70(url),
+ })
let popover: Instance | undefined = $state()
diff --git a/src/app/components/EventDeleteConfirm.svelte b/src/app/components/EventDeleteConfirm.svelte
index 5239143..3ee9a95 100644
--- a/src/app/components/EventDeleteConfirm.svelte
+++ b/src/app/components/EventDeleteConfirm.svelte
@@ -1,7 +1,7 @@
diff --git a/src/app/components/GoalCreate.svelte b/src/app/components/GoalCreate.svelte
index b1ae664..b51c3b5 100644
--- a/src/app/components/GoalCreate.svelte
+++ b/src/app/components/GoalCreate.svelte
@@ -13,6 +13,7 @@
import {pushToast} from "@app/toast"
import {PROTECTED} from "@app/state"
import {makeEditor} from "@app/editor"
+ import {canEnforceNip70} from "@app/commands"
const {url} = $props()
@@ -47,9 +48,12 @@
["summary", summary],
["amount", String(amount)],
["relays", url],
- PROTECTED,
]
+ if (await canEnforceNip70(url)) {
+ tags.push(PROTECTED)
+ }
+
publishThunk({
relays: [url],
event: makeEvent(ZAP_GOAL, {content, tags}),
diff --git a/src/app/components/NoteItem.svelte b/src/app/components/NoteItem.svelte
index 50f2ca1..5da4918 100644
--- a/src/app/components/NoteItem.svelte
+++ b/src/app/components/NoteItem.svelte
@@ -6,17 +6,23 @@
import NoteContent from "@app/components/NoteContent.svelte"
import NoteCard from "@app/components/NoteCard.svelte"
import ReactionSummary from "@app/components/ReactionSummary.svelte"
- import {publishDelete, publishReaction} from "@app/commands"
+ import {publishDelete, publishReaction, canEnforceNip70} from "@app/commands"
const {url, event} = $props()
- const deleteReaction = (event: TrustedEvent) => publishDelete({relays: [url], event})
+ const deleteReaction = async (event: TrustedEvent) =>
+ publishDelete({relays: [url], event, protect: await canEnforceNip70(url)})
- const createReaction = (template: EventContent) =>
- publishReaction({...template, event, relays: [url]})
+ const createReaction = async (template: EventContent) =>
+ publishReaction({...template, event, relays: [url], protect: await canEnforceNip70(url)})
- const onEmoji = (emoji: NativeEmoji) =>
- publishReaction({event, content: emoji.unicode, relays: [url]})
+ const onEmoji = async (emoji: NativeEmoji) =>
+ publishReaction({
+ event,
+ content: emoji.unicode,
+ relays: [url],
+ protect: await canEnforceNip70(url),
+ })
diff --git a/src/app/components/ThreadActions.svelte b/src/app/components/ThreadActions.svelte
index fa8e6cc..d26491a 100644
--- a/src/app/components/ThreadActions.svelte
+++ b/src/app/components/ThreadActions.svelte
@@ -4,7 +4,7 @@
import ThunkStatusOrDeleted from "@app/components/ThunkStatusOrDeleted.svelte"
import EventActivity from "@app/components/EventActivity.svelte"
import EventActions from "@app/components/EventActions.svelte"
- import {publishDelete, publishReaction} from "@app/commands"
+ import {publishDelete, publishReaction, canEnforceNip70} from "@app/commands"
import {makeThreadPath} from "@app/routes"
interface Props {
@@ -17,10 +17,11 @@
const path = makeThreadPath(url, event.id)
- const deleteReaction = (event: TrustedEvent) => publishDelete({relays: [url], event})
+ const deleteReaction = async (event: TrustedEvent) =>
+ publishDelete({relays: [url], event, protect: await canEnforceNip70(url)})
- const createReaction = (template: EventContent) =>
- publishReaction({...template, event, relays: [url]})
+ const createReaction = async (template: EventContent) =>
+ publishReaction({...template, event, relays: [url], protect: await canEnforceNip70(url)})
diff --git a/src/app/components/ThreadCreate.svelte b/src/app/components/ThreadCreate.svelte
index c0a77f3..1965b1e 100644
--- a/src/app/components/ThreadCreate.svelte
+++ b/src/app/components/ThreadCreate.svelte
@@ -12,6 +12,7 @@
import {pushToast} from "@app/toast"
import {PROTECTED} from "@app/state"
import {makeEditor} from "@app/editor"
+ import {canEnforceNip70} from "@app/commands"
const {url} = $props()
@@ -41,7 +42,11 @@
})
}
- const tags = [...ed.storage.nostr.getEditorTags(), ["title", title], PROTECTED]
+ const tags = [...ed.storage.nostr.getEditorTags(), ["title", title]]
+
+ if (await canEnforceNip70(url)) {
+ tags.push(PROTECTED)
+ }
publishThunk({
relays: [url],
diff --git a/src/routes/spaces/[relay]/[room]/+page.svelte b/src/routes/spaces/[relay]/[room]/+page.svelte
index aa9b050..d6a1afe 100644
--- a/src/routes/spaces/[relay]/[room]/+page.svelte
+++ b/src/routes/spaces/[relay]/[room]/+page.svelte
@@ -39,7 +39,12 @@
REACTION_KINDS,
} from "@app/state"
import {setChecked, checked} from "@app/notifications"
- import {addRoomMembership, removeRoomMembership, prependParent} from "@app/commands"
+ import {
+ addRoomMembership,
+ canEnforceNip70,
+ removeRoomMembership,
+ prependParent,
+ } from "@app/commands"
import {PROTECTED} from "@app/state"
import {makeFeed} from "@app/requests"
import {popKey} from "@app/implicit"
@@ -101,9 +106,12 @@
share = undefined
}
- const onSubmit = ({content, tags}: EventContent) => {
+ const onSubmit = async ({content, tags}: EventContent) => {
tags.push(["h", room])
- tags.push(PROTECTED)
+
+ if (await canEnforceNip70(url)) {
+ tags.push(PROTECTED)
+ }
let template = {content, tags}
diff --git a/src/routes/spaces/[relay]/chat/+page.svelte b/src/routes/spaces/[relay]/chat/+page.svelte
index dedc858..1d01006 100644
--- a/src/routes/spaces/[relay]/chat/+page.svelte
+++ b/src/routes/spaces/[relay]/chat/+page.svelte
@@ -20,7 +20,7 @@
import ChannelComposeParent from "@app/components/ChannelComposeParent.svelte"
import {userSettingValues, decodeRelay, getEventsForUrl} from "@app/state"
import {setChecked, checked} from "@app/notifications"
- import {prependParent} from "@app/commands"
+ import {prependParent, canEnforceNip70} from "@app/commands"
import {PROTECTED, REACTION_KINDS} from "@app/state"
import {makeFeed} from "@app/requests"
import {popKey} from "@app/implicit"
@@ -43,8 +43,10 @@
share = undefined
}
- const onSubmit = ({content, tags}: EventContent) => {
- tags.push(PROTECTED)
+ const onSubmit = async ({content, tags}: EventContent) => {
+ if (await canEnforceNip70(url)) {
+ tags.push(PROTECTED)
+ }
let template = {content, tags}