mirror of
https://github.com/owncast/owncast.git
synced 2024-11-22 21:03:19 +03:00
Add noreferrer automatically to link tags. Closes #1941
This commit is contained in:
parent
b08393295f
commit
8fc922588b
2 changed files with 53 additions and 1 deletions
|
@ -1,6 +1,7 @@
|
|||
import { Layout } from 'antd';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import Head from 'next/head';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import {
|
||||
ClientConfigStore,
|
||||
isChatAvailableSelector,
|
||||
|
@ -11,6 +12,7 @@ import { Content, Header } from '../ui';
|
|||
import { ClientConfig } from '../../interfaces/client-config.model';
|
||||
import { DisplayableError } from '../../types/displayable-error';
|
||||
import FatalErrorStateModal from '../modals/FatalErrorModal';
|
||||
import setupNoLinkReferrer from '../../utils/no-link-referrer';
|
||||
|
||||
function Main() {
|
||||
const clientConfig = useRecoilValue<ClientConfig>(clientConfigStateAtom);
|
||||
|
@ -18,6 +20,12 @@ function Main() {
|
|||
const isChatAvailable = useRecoilValue<boolean>(isChatAvailableSelector);
|
||||
const fatalError = useRecoilValue<DisplayableError>(fatalErrorStateAtom);
|
||||
|
||||
const layoutRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
setupNoLinkReferrer(layoutRef.current);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
|
@ -80,7 +88,7 @@ function Main() {
|
|||
</Head>
|
||||
|
||||
<ClientConfigStore />
|
||||
<Layout>
|
||||
<Layout ref={layoutRef}>
|
||||
<Header name={title || name} chatAvailable={isChatAvailable} />
|
||||
<Content />
|
||||
{fatalError && (
|
||||
|
|
44
web/utils/no-link-referrer.ts
Normal file
44
web/utils/no-link-referrer.ts
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
Due to Owncast's goal of being private by default, we don't want any external
|
||||
links to leak the instance of Owncast as a referrer.
|
||||
This observer attempts to catch any anchor tags and automatically add the
|
||||
noopener and noreferrer attributes to them so the instance of Owncast isn't
|
||||
passed along in the headers.
|
||||
|
||||
This should should be fired somewhere relatively high level in the DOM and live
|
||||
for the entirety of the page.
|
||||
*/
|
||||
|
||||
/* eslint-disable no-restricted-syntax */
|
||||
export default function setupNoLinkReferrer(observationRoot: HTMLElement): void {
|
||||
// Options for the observer (which mutations to observe)
|
||||
const config = { attributes: false, childList: true, subtree: true };
|
||||
|
||||
const addNoReferrer = (node: Element): void => {
|
||||
node.setAttribute('rel', 'noopener noreferrer ');
|
||||
};
|
||||
|
||||
// Callback function to execute when mutations are observed
|
||||
// eslint-disable-next-line func-names
|
||||
const callback = function (mutationList) {
|
||||
for (const mutation of mutationList) {
|
||||
for (const node of mutation.addedNodes) {
|
||||
// we track only elements, skip other nodes (e.g. text nodes)
|
||||
// eslint-disable-next-line no-continue
|
||||
if (!(node instanceof HTMLElement)) continue;
|
||||
|
||||
if (node.tagName.toLowerCase() === 'a') {
|
||||
addNoReferrer(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
observationRoot.querySelectorAll('a').forEach(anchor => addNoReferrer(anchor));
|
||||
|
||||
// Create an observer instance linked to the callback function
|
||||
const observer = new MutationObserver(callback);
|
||||
|
||||
// Start observing the target node for configured mutations
|
||||
observer.observe(observationRoot, config);
|
||||
}
|
Loading…
Reference in a new issue