From 7e536515c6d87f47e6463596f9100d98cf699bbf Mon Sep 17 00:00:00 2001 From: Ken Sternberg <133134217+kensternberg-authentik@users.noreply.github.com> Date: Thu, 19 Oct 2023 16:26:02 -0700 Subject: [PATCH] web: isolate clipboard handling (#7229) We would like to use the clipboard for more than just the token copy button. This commit enables that by separating the "Write to Clipboard" and "Write to Notifications" routines into separate functions, putting "writeToClipboard" into the utilities collection, and clarifying what happens when a custom presses the TokenCopy button. --- .../TokenCopyButton/ak-token-copy-button.ts | 45 ++++++++----------- web/src/elements/utils/writeToClipboard.ts | 26 +++++++++++ 2 files changed, 45 insertions(+), 26 deletions(-) create mode 100644 web/src/elements/utils/writeToClipboard.ts diff --git a/web/src/elements/buttons/TokenCopyButton/ak-token-copy-button.ts b/web/src/elements/buttons/TokenCopyButton/ak-token-copy-button.ts index d12bb4db6..0b0971614 100644 --- a/web/src/elements/buttons/TokenCopyButton/ak-token-copy-button.ts +++ b/web/src/elements/buttons/TokenCopyButton/ak-token-copy-button.ts @@ -1,12 +1,14 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { MessageLevel } from "@goauthentik/common/messages"; import { showMessage } from "@goauthentik/elements/messages/MessageContainer"; -import { isSafari } from "@goauthentik/elements/utils/isSafari"; +import { writeToClipboard } from "@goauthentik/elements/utils/writeToClipboard"; +import { msg } from "@lit/localize"; import { customElement, property } from "lit/decorators.js"; import { CoreApi, ResponseError, TokenView } from "@goauthentik/api"; +import { APIMessage } from "../../messages/Message"; import BaseTaskButton from "../SpinnerButton/BaseTaskButton"; /** @@ -51,35 +53,26 @@ export class TokenCopyButton extends BaseTaskButton { }); }; - onSuccess(token: unknown) { + async onSuccess(token: unknown) { super.onSuccess(token); if (!isTokenView(token)) { throw new Error(`Unrecognized return from server: ${token}`); } - - // Insecure origins may not have access to the clipboard. Show a message instead. - if (!navigator.clipboard) { - showMessage({ - level: MessageLevel.info, - message: token.key as string, - }); - return; - } - - // Safari only allows navigator.clipboard.write with native clipboard items. - if (isSafari()) { - navigator.clipboard.write([ - new ClipboardItem({ - "text/plain": new Blob([token.key as string], { - type: "text/plain", - }), - }), - ]); - return; - } - - // Default behavior: write the token to the clipboard. - navigator.clipboard.writeText(token.key as string); + const wroteToClipboard = await writeToClipboard(token.key as string); + const info: Pick = wroteToClipboard + ? { + message: msg("The token has been copied to your clipboard"), + } + : { + message: token.key, + description: msg( + "The token was displayed because authentik does not have permission to write to the clipboard", + ), + }; + showMessage({ + level: MessageLevel.info, + ...info, + }); } async onError(error: unknown) { diff --git a/web/src/elements/utils/writeToClipboard.ts b/web/src/elements/utils/writeToClipboard.ts new file mode 100644 index 000000000..bd916c3bb --- /dev/null +++ b/web/src/elements/utils/writeToClipboard.ts @@ -0,0 +1,26 @@ +import { isSafari } from "./isSafari"; + +export async function writeToClipboard(message: string) { + if (!navigator.clipboard) { + return false; + } + + // Safari only allows navigator.clipboard.write with native clipboard items. + try { + if (isSafari()) { + await navigator.clipboard.write([ + new ClipboardItem({ + "text/plain": new Blob([message], { + type: "text/plain", + }), + }), + ]); + } else { + await navigator.clipboard.writeText(message); + } + return true; + } catch (_) { + /* no op */ + } + return false; +}