feat(security): add granular export controls - Phase 2 + 3 (#38581)

Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
Co-authored-by: codeant-ai-for-open-source[bot] <244253245+codeant-ai-for-open-source[bot]@users.noreply.github.com>
Co-authored-by: Beto Dealmeida <roberto@dealmeida.net>
Co-authored-by: Daniel Vaz Gaspar <danielvazgaspar@gmail.com>
This commit is contained in:
Hugh A. Miles II
2026-04-15 10:24:59 -04:00
committed by GitHub
parent 411f769896
commit b76080e291
24 changed files with 1092 additions and 92 deletions

View File

@@ -17,6 +17,67 @@
* under the License.
*/
import copyTextToClipboard from '@superset-ui/core/utils/copy';
const isSafari = (): boolean => {
const { userAgent } = navigator;
return Boolean(userAgent && /^((?!chrome|android).)*safari/i.test(userAgent));
};
const copyTextWithClipboardApi = async (getText: () => Promise<string>) => {
if (isSafari()) {
try {
const clipboardItem = new ClipboardItem({
'text/plain': getText(),
});
await navigator.clipboard.write([clipboardItem]);
} catch {
const text = await getText();
await navigator.clipboard.writeText(text);
}
} else {
const text = await getText();
await navigator.clipboard.writeText(text);
}
};
const copyTextToClipboard = (getText: () => Promise<string>) =>
copyTextWithClipboardApi(getText).catch(() =>
getText().then(
text =>
new Promise<void>((resolve, reject) => {
const selection: Selection | null = document.getSelection();
if (selection) {
selection.removeAllRanges();
const range = document.createRange();
const span = document.createElement('span');
span.textContent = text;
span.style.position = 'fixed';
span.style.top = '0';
span.style.clip = 'rect(0, 0, 0, 0)';
span.style.whiteSpace = 'pre';
document.body.appendChild(span);
range.selectNode(span);
selection.addRange(range);
try {
if (!document.execCommand('copy')) {
reject();
}
} catch (err) {
reject();
}
document.body.removeChild(span);
if (selection.removeRange) {
selection.removeRange(range);
} else {
selection.removeAllRanges();
}
}
resolve();
}),
),
);
export default copyTextToClipboard;