From 89dda8fe8224a3955882c668dc2c0a019dc3df43 Mon Sep 17 00:00:00 2001 From: Paul Makles Date: Fri, 17 Dec 2021 10:20:55 +0000 Subject: [PATCH] feat(mobx): migrate trusted links --- package.json | 1 + src/context/intermediate/Intermediate.tsx | 8 +++-- .../modals/ExternalLinkPrompt.tsx | 9 +++-- src/mobx/stores/Settings.ts | 5 +++ src/mobx/stores/helpers/SAudio.ts | 8 ++--- src/mobx/stores/helpers/SSecurity.ts | 33 +++++++++++++++++++ yarn.lock | 5 +++ 7 files changed, 57 insertions(+), 12 deletions(-) create mode 100644 src/mobx/stores/helpers/SSecurity.ts diff --git a/package.json b/package.json index bebf161a..6f14588c 100644 --- a/package.json +++ b/package.json @@ -146,6 +146,7 @@ "revolt.js": "5.1.0-alpha.15", "rimraf": "^3.0.2", "sass": "^1.35.1", + "shade-blend-color": "^1.0.0", "styled-components": "^5.3.0", "typescript": "^4.4.2", "ulid": "^2.3.0", diff --git a/src/context/intermediate/Intermediate.tsx b/src/context/intermediate/Intermediate.tsx index 252e44da..3e001a09 100644 --- a/src/context/intermediate/Intermediate.tsx +++ b/src/context/intermediate/Intermediate.tsx @@ -15,7 +15,7 @@ import { useContext, useEffect, useMemo, useState } from "preact/hooks"; import { internalSubscribe } from "../../lib/eventEmitter"; import { determineLink } from "../../lib/links"; -import { getState } from "../../redux"; +import { useApplicationState } from "../../mobx/State"; import { Action } from "../../components/ui/Modal"; @@ -132,6 +132,7 @@ interface Props { export default function Intermediate(props: Props) { const [screen, openScreen] = useState({ id: "none" }); + const settings = useApplicationState().settings; const history = useHistory(); const value = { @@ -154,10 +155,11 @@ export default function Intermediate(props: Props) { return true; } case "external": { - const { trustedLinks } = getState(); if ( !trusted && - !trustedLinks.domains?.includes(link.url.hostname) + !settings.security.isTrustedOrigin( + link.url.hostname, + ) ) { openScreen({ id: "external_link_prompt", diff --git a/src/context/intermediate/modals/ExternalLinkPrompt.tsx b/src/context/intermediate/modals/ExternalLinkPrompt.tsx index 5b416c15..42f73f28 100644 --- a/src/context/intermediate/modals/ExternalLinkPrompt.tsx +++ b/src/context/intermediate/modals/ExternalLinkPrompt.tsx @@ -1,5 +1,6 @@ import { Text } from "preact-i18n"; +import { useApplicationState } from "../../../mobx/State"; import { dispatch } from "../../../redux"; import Modal from "../../../components/ui/Modal"; @@ -13,6 +14,7 @@ interface Props { export function ExternalLinkModal({ onClose, link }: Props) { const { openLink } = useIntermediate(); + const settings = useApplicationState().settings; return ( { try { const url = new URL(link); - dispatch({ - type: "TRUSTED_LINKS_ADD_DOMAIN", - domain: url.hostname, - }); + settings.security.addTrustedOrigin(url.hostname); } catch (e) {} - openLink(link); + openLink(link, true); onClose(); }, plain: true, diff --git a/src/mobx/stores/Settings.ts b/src/mobx/stores/Settings.ts index 9701cb12..f2be8dee 100644 --- a/src/mobx/stores/Settings.ts +++ b/src/mobx/stores/Settings.ts @@ -9,6 +9,7 @@ import { EmojiPack } from "../../components/common/Emoji"; import Persistent from "../interfaces/Persistent"; import Store from "../interfaces/Store"; import SAudio, { SoundOptions } from "./helpers/SAudio"; +import SSecurity from "./helpers/SSecurity"; import STheme from "./helpers/STheme"; interface ISettings { @@ -24,6 +25,8 @@ interface ISettings { "appearance:theme:font": Fonts; "appearance:theme:monoFont": MonospaceFonts; "appearance:theme:css": string; + + "security:trustedOrigins": string[]; } /** @@ -34,6 +37,7 @@ export default class Settings implements Store, Persistent { theme: STheme; sounds: SAudio; + security: SSecurity; /** * Construct new Settings store. @@ -44,6 +48,7 @@ export default class Settings implements Store, Persistent { this.theme = new STheme(this); this.sounds = new SAudio(this); + this.security = new SSecurity(this); } get id() { diff --git a/src/mobx/stores/helpers/SAudio.ts b/src/mobx/stores/helpers/SAudio.ts index 517d1212..fdc4b504 100644 --- a/src/mobx/stores/helpers/SAudio.ts +++ b/src/mobx/stores/helpers/SAudio.ts @@ -1,10 +1,10 @@ import { makeAutoObservable, computed, action } from "mobx"; +import call_join from "../../../assets/sounds/call_join.mp3"; +import call_leave from "../../../assets/sounds/call_leave.mp3"; +import message from "../../../assets/sounds/message.mp3"; +import outbound from "../../../assets/sounds/outbound.mp3"; import Settings from "../Settings"; -import call_join from "./call_join.mp3"; -import call_leave from "./call_leave.mp3"; -import message from "./message.mp3"; -import outbound from "./outbound.mp3"; export type Sounds = "message" | "outbound" | "call_join" | "call_leave"; diff --git a/src/mobx/stores/helpers/SSecurity.ts b/src/mobx/stores/helpers/SSecurity.ts new file mode 100644 index 00000000..41d0ed01 --- /dev/null +++ b/src/mobx/stores/helpers/SSecurity.ts @@ -0,0 +1,33 @@ +import { makeAutoObservable, computed, action } from "mobx"; + +import Settings from "../Settings"; + +/** + * Helper class for changing security options. + */ +export default class SSecurity { + private settings: Settings; + + /** + * Construct a new security helper. + * @param settings Settings parent class + */ + constructor(settings: Settings) { + this.settings = settings; + makeAutoObservable(this); + } + + @action addTrustedOrigin(origin: string) { + this.settings.set("security:trustedOrigins", [ + ...(this.settings.get("security:trustedOrigins") ?? []).filter( + (x) => x !== origin, + ), + origin, + ]); + } + + @computed isTrustedOrigin(origin: string) { + console.log(this.settings.get("security:trustedOrigins"), origin); + return this.settings.get("security:trustedOrigins")?.includes(origin); + } +} diff --git a/yarn.lock b/yarn.lock index 8e8c79f9..a538d37b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3877,6 +3877,11 @@ serialize-javascript@^4.0.0: dependencies: randombytes "^2.1.0" +shade-blend-color@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shade-blend-color/-/shade-blend-color-1.0.0.tgz#cfa10d3673a22ba31d552a0e793b708bc24be0bc" + integrity sha512-Tnp/ppF5h3YhPCpeHiZJ2DRnvmo4luu9qpMhuksCT+QInIXJ9alA3Vd9klfEi+RY8Oh7MaK5vzH/qcLo892L1g== + shallowequal@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8"