Add authentication policy setting

This commit is contained in:
Jon Staab
2026-01-16 13:49:35 -08:00
parent 87bb62b359
commit b3f1d8464b
7 changed files with 122 additions and 39 deletions
+1
View File
@@ -16,6 +16,7 @@
* Improve space join flow * Improve space join flow
* Fix opening images in fullscreen dialog * Fix opening images in fullscreen dialog
* Add support for blocked relays * Add support for blocked relays
* Add authentication policy setting
# 1.6.2 # 1.6.2
+8 -1
View File
@@ -263,12 +263,18 @@ export const MESSAGE_KINDS = [...CONTENT_KINDS, MESSAGE]
export const SETTINGS = "flotilla/settings" export const SETTINGS = "flotilla/settings"
export enum RelayAuthMode {
Aggressive = "aggressive",
Conservative = "conservative",
}
export type SettingsValues = { export type SettingsValues = {
show_media: boolean show_media: boolean
hide_sensitive: boolean hide_sensitive: boolean
trusted_relays: string[] trusted_relays: string[]
report_usage: boolean report_usage: boolean
report_errors: boolean report_errors: boolean
relay_auth: RelayAuthMode
send_delay: number send_delay: number
font_size: number font_size: number
play_notification_sound: boolean play_notification_sound: boolean
@@ -280,12 +286,13 @@ export type Settings = {
values: SettingsValues values: SettingsValues
} }
export const defaultSettings = { export const defaultSettings: SettingsValues = {
show_media: true, show_media: true,
hide_sensitive: true, hide_sensitive: true,
trusted_relays: [], trusted_relays: [],
report_usage: true, report_usage: true,
report_errors: true, report_errors: true,
relay_auth: RelayAuthMode.Conservative,
send_delay: 0, send_delay: 0,
font_size: 1.1, font_size: 1.1,
play_notification_sound: true, play_notification_sound: true,
+21 -2
View File
@@ -1,4 +1,5 @@
import {on, always, call, dissoc, assoc, uniq} from "@welshman/lib" import {get} from "svelte/store"
import {on, call, dissoc, assoc, uniq} from "@welshman/lib"
import {RelayMode} from "@welshman/util" import {RelayMode} from "@welshman/util"
import type {Socket, RelayMessage, ClientMessage} from "@welshman/net" import type {Socket, RelayMessage, ClientMessage} from "@welshman/net"
import { import {
@@ -20,9 +21,27 @@ import {
getSetting, getSetting,
relaysPendingTrust, relaysPendingTrust,
relaysMostlyRestricted, relaysMostlyRestricted,
RelayAuthMode,
NOTIFIER_RELAY,
userSpaceUrls,
} from "@app/core/state" } from "@app/core/state"
export const authPolicy = makeSocketPolicyAuth({sign, shouldAuth: always(true)}) export const authPolicy = makeSocketPolicyAuth({
sign,
shouldAuth: (socket: Socket) => {
const $pubkey = pubkey.get()
const mode = getSetting<RelayAuthMode>("relay_auth")
if (!$pubkey) return false
if (socket.url === NOTIFIER_RELAY) return true
if (mode === RelayAuthMode.Aggressive) return true
if (get(userSpaceUrls).includes(socket.url)) return true
if (getPubkeyRelays($pubkey).includes(socket.url)) return true
if (getPubkeyRelays($pubkey, RelayMode.Messaging).includes(socket.url)) return true
return false
},
})
export const blockPolicy = (socket: Socket) => { export const blockPolicy = (socket: Socket) => {
const previousOpen = socket.open const previousOpen = socket.open
+4 -4
View File
@@ -9,14 +9,14 @@
const {...props}: Props = $props() const {...props}: Props = $props()
</script> </script>
<div class="grid grid-cols-1 gap-2 lg:grid-cols-3 {props.class}"> <div class="grid grid-cols-1 gap-6 lg:grid-cols-5 {props.class} items-start">
<label class="flex items-center gap-2 font-bold"> <label class="flex items-center gap-2 font-bold lg:col-span-2">
{@render props.label?.()} {@render props.label?.()}
</label> </label>
<div class="col-span-2 flex items-center gap-2"> <div class="col-span-2 flex items-center gap-2 lg:col-span-3">
{@render props.input?.()} {@render props.input?.()}
</div> </div>
<p class="flex-end text-sm opacity-70 lg:col-span-3"> <p class="flex-end text-sm opacity-50 lg:col-span-5">
{#if props.info} {#if props.info}
{@render props.info?.()} {@render props.info?.()}
{/if} {/if}
+8 -2
View File
@@ -8,6 +8,7 @@
import InfoSquare from "@assets/icons/info-square.svg?dataurl" import InfoSquare from "@assets/icons/info-square.svg?dataurl"
import Exit from "@assets/icons/logout-3.svg?dataurl" import Exit from "@assets/icons/logout-3.svg?dataurl"
import GalleryMinimalistic from "@assets/icons/gallery-minimalistic.svg?dataurl" import GalleryMinimalistic from "@assets/icons/gallery-minimalistic.svg?dataurl"
import Shield from "@assets/icons/shield-minimalistic.svg?dataurl"
import Bell from "@assets/icons/bell.svg?dataurl" import Bell from "@assets/icons/bell.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Page from "@lib/components/Page.svelte" import Page from "@lib/components/Page.svelte"
@@ -60,16 +61,21 @@
</SecondaryNavItem> </SecondaryNavItem>
</div> </div>
<div in:fly|local={{delay: 250}}> <div in:fly|local={{delay: 250}}>
<SecondaryNavItem href="/settings/privacy">
<Icon icon={Shield} /> Privacy
</SecondaryNavItem>
</div>
<div in:fly|local={{delay: 300}}>
<SecondaryNavItem onclick={toggleTheme}> <SecondaryNavItem onclick={toggleTheme}>
<Icon icon={Moon} /> Theme <Icon icon={Moon} /> Theme
</SecondaryNavItem> </SecondaryNavItem>
</div> </div>
<div in:fly|local={{delay: 300}}> <div in:fly|local={{delay: 350}}>
<SecondaryNavItem href="/settings/about"> <SecondaryNavItem href="/settings/about">
<Icon icon={InfoSquare} /> About <Icon icon={InfoSquare} /> About
</SecondaryNavItem> </SecondaryNavItem>
</div> </div>
<div in:fly|local={{delay: 350}}> <div in:fly|local={{delay: 400}}>
<SecondaryNavItem class="text-error hover:text-error" onclick={logout}> <SecondaryNavItem class="text-error hover:text-error" onclick={logout}>
<Icon icon={Exit} /> Log Out <Icon icon={Exit} /> Log Out
</SecondaryNavItem> </SecondaryNavItem>
-30
View File
@@ -87,36 +87,6 @@
</div> </div>
{/snippet} {/snippet}
</Field> </Field>
<strong class="text-lg">Privacy Settings</strong>
<FieldInline>
{#snippet label()}
<p>Report errors?</p>
{/snippet}
{#snippet input()}
<input
type="checkbox"
class="toggle toggle-primary"
bind:checked={settings.report_errors} />
{/snippet}
{#snippet info()}
<p>
Allow {PLATFORM_NAME} to send error reports to help improve the app.
</p>
{/snippet}
</FieldInline>
<FieldInline>
{#snippet label()}
<p>Report usage?</p>
{/snippet}
{#snippet input()}
<input type="checkbox" class="toggle toggle-primary" bind:checked={settings.report_usage} />
{/snippet}
{#snippet info()}
<p>
Allow {PLATFORM_NAME} to collect anonymous usage data.
</p>
{/snippet}
</FieldInline>
<strong class="text-lg">Editor Settings</strong> <strong class="text-lg">Editor Settings</strong>
<FieldInline> <FieldInline>
{#snippet label()} {#snippet label()}
+80
View File
@@ -0,0 +1,80 @@
<script lang="ts">
import {preventDefault} from "@lib/html"
import FieldInline from "@lib/components/FieldInline.svelte"
import Button from "@lib/components/Button.svelte"
import {pushToast} from "@app/util/toast"
import {PLATFORM_NAME, RelayAuthMode, userSettingsValues} from "@app/core/state"
import {publishSettings} from "@app/core/commands"
const reset = () => {
settings = {...$userSettingsValues}
}
const onAuthModeChange = (e: any) => {
settings.auth_mode = e.target.checked ? RelayAuthMode.Aggressive : RelayAuthMode.Conservative
}
const onsubmit = preventDefault(async () => {
await publishSettings($state.snapshot(settings))
pushToast({message: "Your settings have been saved!"})
})
let settings = $state({...$userSettingsValues})
</script>
<form class="content column gap-4" {onsubmit}>
<div class="card2 bg-alt col-4 shadow-md">
<strong class="text-lg">Privacy Settings</strong>
<FieldInline>
{#snippet label()}
<p>Authenticate with unknown relays?</p>
{/snippet}
{#snippet input()}
<input
type="checkbox"
class="toggle toggle-primary"
onchange={onAuthModeChange}
checked={settings.auth_mode === RelayAuthMode.Aggressive} />
{/snippet}
{#snippet info()}
<p>
Controls whether {PLATFORM_NAME} will identify you to relays not in your lists.
</p>
{/snippet}
</FieldInline>
<FieldInline>
{#snippet label()}
<p>Report errors?</p>
{/snippet}
{#snippet input()}
<input
type="checkbox"
class="toggle toggle-primary"
bind:checked={settings.report_errors} />
{/snippet}
{#snippet info()}
<p>
Allow {PLATFORM_NAME} to send error reports to help improve the app.
</p>
{/snippet}
</FieldInline>
<FieldInline>
{#snippet label()}
<p>Report usage?</p>
{/snippet}
{#snippet input()}
<input type="checkbox" class="toggle toggle-primary" bind:checked={settings.report_usage} />
{/snippet}
{#snippet info()}
<p>
Allow {PLATFORM_NAME} to collect anonymous usage data.
</p>
{/snippet}
</FieldInline>
<div class="mt-4 flex flex-row items-center justify-between gap-4">
<Button class="btn btn-neutral" onclick={reset}>Discard Changes</Button>
<Button type="submit" class="btn btn-primary">Save Changes</Button>
</div>
</div>
</form>