Merge pull request #158 from Snazzah/trusted-links

This commit is contained in:
Paul Makles 2021-09-03 11:18:16 +01:00 committed by GitHub
commit 966daa6c78
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 87 additions and 14 deletions

View file

@ -18,13 +18,15 @@ import { useCallback, useContext } from "preact/hooks";
import { internalEmit } from "../../lib/eventEmitter";
import { getState } from "../../redux";
import { useIntermediate } from "../../context/intermediate/Intermediate";
import { AppContext } from "../../context/revoltjs/RevoltClient";
import { generateEmoji } from "../common/Emoji";
import { emojiDictionary } from "../../assets/emojis";
import { MarkdownProps } from "./Markdown";
import {useIntermediate} from "../../context/intermediate/Intermediate";
// TODO: global.d.ts file for defining globals
declare global {
@ -35,9 +37,9 @@ declare global {
const ALLOWED_ORIGINS = [
location.hostname,
'app.revolt.chat',
'nightly.revolt.chat',
'local.revolt.chat',
"app.revolt.chat",
"nightly.revolt.chat",
"local.revolt.chat",
];
// Handler for code block copy.
@ -176,13 +178,16 @@ export default function Renderer({ content, disallowBigEmoji }: MarkdownProps) {
element.removeAttribute("data-type");
element.removeAttribute("target");
let internal;
let internal,
url: URL | null = null;
const href = element.href;
if (href) {
try {
const url = new URL(href, location.href);
url = new URL(href, location.href);
if (ALLOWED_ORIGINS.includes(url.hostname)) {
if (
ALLOWED_ORIGINS.includes(url.hostname)
) {
internal = true;
element.addEventListener(
"click",
@ -202,12 +207,20 @@ export default function Renderer({ content, disallowBigEmoji }: MarkdownProps) {
if (!internal) {
element.setAttribute("target", "_blank");
element.onclick = (ev) => {
const { trustedLinks } = getState();
if (
!url ||
!trustedLinks.domains?.includes(
url.hostname,
)
) {
ev.preventDefault();
openScreen({
id: "external_link_prompt",
link: href
})
link: href,
});
}
};
}
},
);

View file

@ -1,6 +1,7 @@
import { Text } from "preact-i18n";
import Modal from "../../../components/ui/Modal";
import { dispatch } from "../../../redux";
interface Props {
onClose: () => void;
@ -29,8 +30,23 @@ export function ExternalLinkModal({ onClose, link }: Props) {
confirmation: false,
children: "Cancel",
},
{
onClick: () => {
try {
const url = new URL(link);
dispatch({
type: "TRUSTED_LINKS_ADD_DOMAIN",
domain: url.hostname
});
} catch(e) {}
window.open(link, "_blank");
onClose();
},
plain: true,
children: <Text id="app.special.modals.external_links.trust_domain" />,
}
]}>
<Text id={"app.special.modals.external_links.short"} /> <br />
<Text id="app.special.modals.external_links.short" /> <br />
<a>{link}</a>
</Modal>
);

View file

@ -14,6 +14,7 @@ import { QueuedMessage } from "./reducers/queue";
import { SectionToggle } from "./reducers/section_toggle";
import { Settings } from "./reducers/settings";
import { SyncOptions } from "./reducers/sync";
import { TrustedLinks } from "./reducers/trusted_links";
import { Unreads } from "./reducers/unreads";
export type State = {
@ -29,6 +30,7 @@ export type State = {
lastOpened: LastOpened;
notifications: Notifications;
sectionToggle: SectionToggle;
trustedLinks: TrustedLinks;
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@ -59,6 +61,7 @@ store.subscribe(() => {
lastOpened,
notifications,
sectionToggle,
trustedLinks,
} = store.getState() as State;
localForage.setItem("state", {
@ -74,6 +77,7 @@ store.subscribe(() => {
lastOpened,
notifications,
sectionToggle,
trustedLinks,
});
});

View file

@ -12,6 +12,7 @@ import { sectionToggle, SectionToggleAction } from "./section_toggle";
import { config, ConfigAction } from "./server_config";
import { settings, SettingsAction } from "./settings";
import { sync, SyncAction } from "./sync";
import { trustedLinks, TrustedLinksAction } from "./trusted_links";
import { unreads, UnreadsAction } from "./unreads";
export default combineReducers({
@ -27,6 +28,7 @@ export default combineReducers({
lastOpened,
notifications,
sectionToggle,
trustedLinks,
});
export type Action =
@ -42,4 +44,5 @@ export type Action =
| LastOpenedAction
| NotificationsAction
| SectionToggleAction
| TrustedLinksAction
| { type: "__INIT"; state: State };

View file

@ -0,0 +1,37 @@
export interface TrustedLinks {
domains?: string[];
}
export type TrustedLinksAction =
| { type: undefined }
| {
type: "TRUSTED_LINKS_ADD_DOMAIN";
domain: string;
}
| {
type: "TRUSTED_LINKS_REMOVE_DOMAIN";
domain: string;
};
export function trustedLinks(
state = {} as TrustedLinks,
action: TrustedLinksAction,
): TrustedLinks {
switch (action.type) {
case "TRUSTED_LINKS_ADD_DOMAIN":
return {
...state,
domains: [
...(state.domains ?? []).filter((v) => v !== action.domain),
action.domain,
],
};
case "TRUSTED_LINKS_REMOVE_DOMAIN":
return {
...state,
domains: state.domains?.filter((v) => v !== action.domain),
};
default:
return state;
}
}