forked from coracle/flotilla
Add authentication policy setting
This commit is contained in:
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,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>
|
||||||
|
|||||||
@@ -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()}
|
||||||
|
|||||||
@@ -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>
|
||||||
Reference in New Issue
Block a user