mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-03-17 21:31:43 +01:00
Add "Proactively authenticate to relays" option to privacy settings, defaults to off
Fix automatically disconnecting from authenticated relays
This commit is contained in:
parent
2a2ed1c4af
commit
bbd19d7d99
5
.changeset/rotten-garlics-beg.md
Normal file
5
.changeset/rotten-garlics-beg.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"nostrudel": minor
|
||||
---
|
||||
|
||||
Add "Proactively authenticate to relays" option to privacy settings, defaults to off
|
5
.changeset/swift-trainers-fold.md
Normal file
5
.changeset/swift-trainers-fold.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"nostrudel": patch
|
||||
---
|
||||
|
||||
Fix automatically disconnecting from authenticated relays
|
@ -10,6 +10,7 @@ import { offlineMode } from "../services/offline-mode";
|
||||
import processManager from "../services/process-manager";
|
||||
import signingService from "../services/signing";
|
||||
import accountService from "../services/account";
|
||||
import localSettings from "../services/local-settings";
|
||||
|
||||
export type Notice = {
|
||||
message: string;
|
||||
@ -20,6 +21,8 @@ export type Notice = {
|
||||
export type RelayAuthMode = "always" | "ask" | "never";
|
||||
|
||||
export default class RelayPool {
|
||||
log = logger.extend("RelayPool");
|
||||
|
||||
relays = new Map<string, AbstractRelay>();
|
||||
onRelayCreated = new Subject<AbstractRelay>();
|
||||
onRelayChallenge = new Subject<[AbstractRelay, string]>();
|
||||
@ -35,8 +38,6 @@ export default class RelayPool {
|
||||
|
||||
authenticated = new SuperMap<AbstractRelay, Subject<boolean>>(() => new Subject());
|
||||
|
||||
log = logger.extend("RelayPool");
|
||||
|
||||
getRelay(relayOrUrl: string | URL | AbstractRelay) {
|
||||
if (typeof relayOrUrl === "string") {
|
||||
const safeURL = safeRelayUrl(relayOrUrl);
|
||||
@ -69,10 +70,7 @@ export default class RelayPool {
|
||||
const key = url.toString();
|
||||
if (!this.relays.has(key)) {
|
||||
const r = new AbstractRelay(key, { verifyEvent: verifyEventMethod });
|
||||
r._onauth = (challenge) => {
|
||||
this.onRelayChallenge.next([r, challenge]);
|
||||
this.challenges.get(r).next(challenge);
|
||||
};
|
||||
r._onauth = (challenge) => this.handleRelayChallenge(r, challenge);
|
||||
r.onnotice = (notice) => this.handleRelayNotice(r, notice);
|
||||
|
||||
this.relays.set(key, r);
|
||||
@ -130,7 +128,7 @@ export default class RelayPool {
|
||||
let relay = this.getRelay(relayOrUrl);
|
||||
if (!relay) return;
|
||||
|
||||
const defaultMode = (localStorage.getItem(`default-auth-mode`) as RelayAuthMode) ?? undefined;
|
||||
const defaultMode = localSettings.defaultAuthenticationMode.value;
|
||||
const mode = (localStorage.getItem(this.getRelayAuthStorageKey(relay)) as RelayAuthMode) ?? undefined;
|
||||
|
||||
return mode || defaultMode;
|
||||
@ -189,6 +187,30 @@ export default class RelayPool {
|
||||
return this.authForSubscribe.get(relay).value !== false;
|
||||
}
|
||||
|
||||
private automaticallyAuthenticate(relay: AbstractRelay) {
|
||||
const authMode = this.getRelayAuthMode(relay);
|
||||
// only automatically authenticate if auth mode is set to "always"
|
||||
if (authMode === "always") {
|
||||
const account = accountService.current.value;
|
||||
if (!account) return;
|
||||
|
||||
this.authenticate(relay, (draft) => {
|
||||
return signingService.requestSignature(draft, account);
|
||||
}).then(() => {
|
||||
this.log(`Automatically authenticated to ${relay.url}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private handleRelayChallenge(relay: AbstractRelay, challenge: string) {
|
||||
this.onRelayChallenge.next([relay, challenge]);
|
||||
this.challenges.get(relay).next(challenge);
|
||||
|
||||
if (localSettings.proactivelyAuthenticate.value) {
|
||||
this.automaticallyAuthenticate(relay);
|
||||
}
|
||||
}
|
||||
|
||||
handleRelayNotice(relay: AbstractRelay, message: string) {
|
||||
const subject = this.notices.get(relay);
|
||||
subject.next([...subject.value, { message, date: dayjs().unix(), relay }]);
|
||||
@ -197,18 +219,8 @@ export default class RelayPool {
|
||||
const authForSubscribe = this.authForSubscribe.get(relay);
|
||||
if (!authForSubscribe.value) authForSubscribe.next(true);
|
||||
|
||||
const account = accountService.current.value;
|
||||
if (account) {
|
||||
const authMode = this.getRelayAuthMode(relay);
|
||||
|
||||
if (authMode === "always") {
|
||||
this.authenticate(relay, (draft) => {
|
||||
return signingService.requestSignature(draft, account);
|
||||
}).then(() => {
|
||||
this.log(`Automatically authenticated to ${relay.url}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
// try to authenticate
|
||||
this.automaticallyAuthenticate(relay);
|
||||
}
|
||||
}
|
||||
|
||||
@ -216,6 +228,9 @@ export default class RelayPool {
|
||||
for (const [url, relay] of this.relays) {
|
||||
if (!relay.connected) continue;
|
||||
|
||||
// don't disconnect from authenticated relays
|
||||
if (this.authenticated.get(relay).value) continue;
|
||||
|
||||
let disconnect = true;
|
||||
for (const process of processManager.processes) {
|
||||
if (process.active && process.relays.has(relay)) {
|
||||
|
@ -51,6 +51,10 @@ const addClientTag = new BooleanLocalStorageEntry("add-client-tag", false);
|
||||
const verifyEventMethod = new LocalStorageEntry("verify-event-method", "wasm"); // wasm, internal, none
|
||||
const enableKeyboardShortcuts = new BooleanLocalStorageEntry("enable-keyboard-shortcuts", true);
|
||||
|
||||
// privacy
|
||||
const defaultAuthenticationMode = new LocalStorageEntry("default-relay-auth-mode", "ask"); // ask, always, never
|
||||
const proactivelyAuthenticate = new BooleanLocalStorageEntry("proactively-authenticate", false);
|
||||
|
||||
// display settings
|
||||
const showBrandLogo = new BooleanLocalStorageEntry("show-brand-logo", true);
|
||||
|
||||
@ -66,6 +70,8 @@ const localSettings = {
|
||||
verifyEventMethod,
|
||||
enableKeyboardShortcuts,
|
||||
showBrandLogo,
|
||||
defaultAuthenticationMode,
|
||||
proactivelyAuthenticate,
|
||||
};
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { useLocalStorage } from "react-use";
|
||||
import {
|
||||
Flex,
|
||||
FormControl,
|
||||
@ -18,6 +17,8 @@ import { createRequestProxyUrl } from "../../../helpers/request";
|
||||
import { RelayAuthMode } from "../../../classes/relay-pool";
|
||||
import VerticalPageLayout from "../../../components/vertical-page-layout";
|
||||
import useSettingsForm from "../use-settings-form";
|
||||
import useSubject from "../../../hooks/use-subject";
|
||||
import localSettings from "../../../services/local-settings";
|
||||
|
||||
async function validateInvidiousUrl(url?: string) {
|
||||
if (!url) return true;
|
||||
@ -44,9 +45,8 @@ async function validateRequestProxy(url?: string) {
|
||||
export default function PrivacySettings() {
|
||||
const { register, submit, formState } = useSettingsForm();
|
||||
|
||||
const [defaultAuthMode, setDefaultAuthMode] = useLocalStorage<RelayAuthMode>("default-relay-auth-mode", "ask", {
|
||||
raw: true,
|
||||
});
|
||||
const defaultAuthenticationMode = useSubject(localSettings.defaultAuthenticationMode);
|
||||
const proactivelyAuthenticate = useSubject(localSettings.proactivelyAuthenticate);
|
||||
|
||||
return (
|
||||
<VerticalPageLayout as="form" onSubmit={submit} flex={1}>
|
||||
@ -58,8 +58,8 @@ export default function PrivacySettings() {
|
||||
w="xs"
|
||||
rounded="md"
|
||||
flexShrink={0}
|
||||
value={defaultAuthMode || "ask"}
|
||||
onChange={(e) => setDefaultAuthMode(e.target.value as RelayAuthMode)}
|
||||
value={defaultAuthenticationMode}
|
||||
onChange={(e) => localSettings.defaultAuthenticationMode.next(e.target.value as RelayAuthMode)}
|
||||
>
|
||||
<option value="always">Always authenticate</option>
|
||||
<option value="ask">Ask every time</option>
|
||||
@ -68,6 +68,22 @@ export default function PrivacySettings() {
|
||||
<FormHelperText>How should the app handle relays requesting identification</FormHelperText>
|
||||
</FormControl>
|
||||
|
||||
<FormControl>
|
||||
<Flex alignItems="center">
|
||||
<FormLabel htmlFor="proactivelyAuthenticate" mb="0">
|
||||
Proactively authenticate to relays
|
||||
</FormLabel>
|
||||
<Switch
|
||||
id="proactivelyAuthenticate"
|
||||
isChecked={proactivelyAuthenticate}
|
||||
onChange={(e) => localSettings.proactivelyAuthenticate.next(e.currentTarget.checked)}
|
||||
/>
|
||||
</Flex>
|
||||
<FormHelperText>
|
||||
<span>Authenticate to relays as soon as they send the authentication challenge</span>
|
||||
</FormHelperText>
|
||||
</FormControl>
|
||||
|
||||
<FormControl isInvalid={!!formState.errors.twitterRedirect}>
|
||||
<FormLabel>Nitter instance</FormLabel>
|
||||
<Input
|
||||
|
@ -32,6 +32,8 @@ import useRouteSearchValue from "../../../hooks/use-route-search-value";
|
||||
import processManager from "../../../services/process-manager";
|
||||
import { RelayAuthMode } from "../../../classes/relay-pool";
|
||||
import Timestamp from "../../../components/timestamp";
|
||||
import localSettings from "../../../services/local-settings";
|
||||
import useSubject from "../../../hooks/use-subject";
|
||||
|
||||
function RelayCard({ relay }: { relay: AbstractRelay }) {
|
||||
return (
|
||||
@ -50,11 +52,15 @@ function RelayCard({ relay }: { relay: AbstractRelay }) {
|
||||
function RelayAuthCard({ relay }: { relay: AbstractRelay }) {
|
||||
const { authenticated } = useRelayAuthMethod(relay);
|
||||
|
||||
const defaultMode = useSubject(localSettings.defaultAuthenticationMode);
|
||||
|
||||
const processes = processManager.getRootProcessesForRelay(relay);
|
||||
const [authMode, setAuthMode] = useLocalStorage<RelayAuthMode>(
|
||||
const [authMode, setAuthMode] = useLocalStorage<RelayAuthMode | "">(
|
||||
relayPoolService.getRelayAuthStorageKey(relay),
|
||||
"ask",
|
||||
{ raw: true },
|
||||
"",
|
||||
{
|
||||
raw: true,
|
||||
},
|
||||
);
|
||||
|
||||
return (
|
||||
@ -74,9 +80,10 @@ function RelayAuthCard({ relay }: { relay: AbstractRelay }) {
|
||||
w="auto"
|
||||
rounded="md"
|
||||
flexShrink={0}
|
||||
value={authMode || "ask"}
|
||||
value={authMode}
|
||||
onChange={(e) => setAuthMode(e.target.value as RelayAuthMode)}
|
||||
>
|
||||
<option value="">Default ({defaultMode})</option>
|
||||
<option value="always">Always</option>
|
||||
<option value="ask">Ask</option>
|
||||
<option value="never">Never</option>
|
||||
|
Loading…
x
Reference in New Issue
Block a user