Skip to content

Commit 38c4279

Browse files
authored
fix(web-console): don't use navigator.clipboard in insecure context (#417)
Dont use navigator.clipboard in insecure context
1 parent 1f91e84 commit 38c4279

7 files changed

Lines changed: 32 additions & 15 deletions

File tree

packages/browser-tests/questdb

Submodule questdb updated 80 files

packages/web-console/src/components/CopyButton/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import styled from "styled-components"
33
import { Button } from "@questdb/react-components"
44
import { FileCopy } from "@styled-icons/remix-line"
55
import { CheckboxCircle } from "@styled-icons/remix-fill"
6+
import { copyToClipboard } from "../../utils/copyToClipboard"
67

78
const StyledButton = styled(Button)`
89
padding: 1.2rem 0.6rem;
@@ -28,7 +29,7 @@ export const CopyButton = ({
2829
skin="secondary"
2930
data-hook="copy-value"
3031
onClick={(e) => {
31-
navigator.clipboard.writeText(text)
32+
copyToClipboard(text)
3233
e.stopPropagation()
3334
setCopied(true)
3435
setTimeout(() => setCopied(false), 2000)

packages/web-console/src/js/console/grid.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
* limitations under the License.
2222
*
2323
******************************************************************************/
24+
import { copyToClipboard } from "../../utils/copyToClipboard"
2425

2526
const hashString = (str) => {
2627
let hash = 0
@@ -1703,8 +1704,7 @@ export function grid(rootElement, _paginationFn, id) {
17031704
textToCopy = focusedCell.innerHTML
17041705
}
17051706

1706-
navigator.clipboard
1707-
.writeText(textToCopy)
1707+
copyToClipboard(textToCopy)
17081708
.then(undefined)
17091709

17101710
activeCellPulseClearTimer = setTimeout(() => {

packages/web-console/src/scenes/Result/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import { EventType } from "../../modules/EventBus/types"
5353
import { QuestContext } from "../../providers"
5454
import { QueryInNotification } from "../Editor/Monaco/query-in-notification"
5555
import { NotificationType } from "../../store/Query/types"
56+
import { copyToClipboard } from "../../utils/copyToClipboard"
5657

5758
const Root = styled.div`
5859
display: flex;
@@ -188,8 +189,7 @@ const Result = ({ viewMode }: { viewMode: ResultViewMode }) => {
188189
trigger: (
189190
<PrimaryToggleButton
190191
onClick={() => {
191-
navigator.clipboard
192-
.writeText(gridRef?.current?.getResultAsMarkdown() as string)
192+
copyToClipboard(gridRef?.current?.getResultAsMarkdown() as string)
193193
.then(() => {
194194
setIsCopied(true)
195195
setTimeout(() => setIsCopied(false), 1000)

packages/web-console/src/scenes/Schema/SuspensionDialog/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { ErrorResult } from "../../../utils"
2525
import { Text, Link } from "../../../components"
2626
import { errorWorkarounds } from "../../../utils/errorWorkarounds"
2727
import Joi from "joi"
28+
import { copyToClipboard } from "../../../utils/copyToClipboard"
2829

2930
const StyledDialogContent = styled(Dialog.Content)`
3031
border-color: #723131;
@@ -229,7 +230,7 @@ export const SuspensionDialog = ({
229230
<Button
230231
skin="secondary"
231232
onClick={() => {
232-
navigator.clipboard.writeText(
233+
copyToClipboard(
233234
walTableData.errorMessage ?? "",
234235
)
235236
}}

packages/web-console/src/scenes/Schema/Table/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import { TreeNodeKind } from "../../../components/Tree"
3737
import { SuspensionDialog } from '../SuspensionDialog'
3838
import { FileCopy, Restart } from "@styled-icons/remix-line"
3939
import { TABLES_GROUP_KEY, MATVIEWS_GROUP_KEY } from "../localStorageUtils"
40+
import { copyToClipboard } from "../../../utils/copyToClipboard"
4041

4142
type Props = QuestDB.Table &
4243
Readonly<{
@@ -205,7 +206,7 @@ const Table = ({
205206
}
206207

207208
if (response?.type === QuestDB.Type.DQL && response.data?.[0]?.ddl) {
208-
navigator.clipboard.writeText(response.data[0].ddl)
209+
copyToClipboard(response.data[0].ddl)
209210
dispatch(
210211
actions.query.addNotification({
211212
content: <Text color="foreground">Schema copied to clipboard</Text>,
Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,22 @@
1-
export const copyToClipboard = (text: string) => {
2-
const el = document.createElement("textarea")
3-
el.value = text
4-
document.body.appendChild(el)
5-
el.select()
6-
document.execCommand("copy")
7-
document.body.removeChild(el)
1+
export const copyToClipboard = async (textToCopy: string) => {
2+
if (navigator.clipboard && window.isSecureContext) {
3+
await navigator.clipboard.writeText(textToCopy);
4+
} else {
5+
const textArea = document.createElement("textarea");
6+
textArea.value = textToCopy;
7+
8+
textArea.style.position = "absolute";
9+
textArea.style.left = "-999999px";
10+
11+
document.body.prepend(textArea);
12+
textArea.select();
13+
14+
try {
15+
document.execCommand('copy');
16+
} catch (error) {
17+
console.error(error);
18+
} finally {
19+
textArea.remove();
20+
}
21+
}
822
}

0 commit comments

Comments
 (0)