From 51646b2d226b1e6340228214070eb0d40132d31c Mon Sep 17 00:00:00 2001 From: Perry Mitchell Date: Tue, 26 Mar 2024 21:35:19 +0200 Subject: [PATCH 1/6] Update locust, fix recognitions --- package-lock.json | 14 +++++++------- package.json | 2 +- source/tab/services/formDetection.ts | 1 + 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 360146e2..9f0dfaaf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "@blueprintjs/icons": "^4.16.0", "@blueprintjs/popover2": "^1.14.11", "@buttercup/channel-queue": "^1.4.0", - "@buttercup/locust": "^2.2.0", + "@buttercup/locust": "^2.2.1", "@buttercup/ui": "^6.2.2", "@types/chrome": "^0.0.251", "@types/ms": "^0.7.34", @@ -2059,9 +2059,9 @@ } }, "node_modules/@buttercup/locust": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@buttercup/locust/-/locust-2.2.0.tgz", - "integrity": "sha512-weT3huHJNwK+sTr/0TRUrRgpw1TE/sZ6DM8hoieURT818/HVITMpuMe5qwWtYrJIOISyY25tAKPKkp1KBImgyA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@buttercup/locust/-/locust-2.2.1.tgz", + "integrity": "sha512-tBOCS8bfuG2fGByTPR5V0EhQGieq4ewRHnfKlwzFsF3ZUKzc6/OvzKeH8JlmCnj90Y8nj4G3DDipMnbdv93a9g==", "dev": true, "dependencies": { "eventemitter3": "^5.0.1", @@ -16234,9 +16234,9 @@ } }, "@buttercup/locust": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@buttercup/locust/-/locust-2.2.0.tgz", - "integrity": "sha512-weT3huHJNwK+sTr/0TRUrRgpw1TE/sZ6DM8hoieURT818/HVITMpuMe5qwWtYrJIOISyY25tAKPKkp1KBImgyA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@buttercup/locust/-/locust-2.2.1.tgz", + "integrity": "sha512-tBOCS8bfuG2fGByTPR5V0EhQGieq4ewRHnfKlwzFsF3ZUKzc6/OvzKeH8JlmCnj90Y8nj4G3DDipMnbdv93a9g==", "dev": true, "requires": { "eventemitter3": "^5.0.1", diff --git a/package.json b/package.json index 9e3217bb..e4bb0578 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "@blueprintjs/icons": "^4.16.0", "@blueprintjs/popover2": "^1.14.11", "@buttercup/channel-queue": "^1.4.0", - "@buttercup/locust": "^2.2.0", + "@buttercup/locust": "^2.2.1", "@buttercup/ui": "^6.2.2", "@types/chrome": "^0.0.251", "@types/ms": "^0.7.34", diff --git a/source/tab/services/formDetection.ts b/source/tab/services/formDetection.ts index 5668dda4..c35039ca 100644 --- a/source/tab/services/formDetection.ts +++ b/source/tab/services/formDetection.ts @@ -33,6 +33,7 @@ export function waitAndAttachLaunchButtons( ) { onIdentifiedTarget((loginTarget: LoginTarget) => { const { otpField, usernameField, passwordField } = loginTarget; + console.log("FOUND TARGET", loginTarget); if (otpField) { attachLaunchButton(otpField, (el) => onInputActivate(el, loginTarget, InputType.OTP)); } From 697dc6663357216047560a74878d35810c8b15fc Mon Sep 17 00:00:00 2001 From: Perry Mitchell Date: Wed, 27 Mar 2024 08:41:30 +0200 Subject: [PATCH 2/6] Add entry info popup dialog --- source/background/services/cryptoKeys.ts | 15 ++- .../components/entries/EntryInfoDialog.tsx | 97 +++++++++++++++++++ source/popup/components/entries/EntryItem.tsx | 18 +++- .../components/entries/EntryItemList.tsx | 5 +- source/popup/components/otps/OTPItem.tsx | 2 - source/popup/components/pages/EntriesPage.tsx | 76 ++++++++------- source/shared/i18n/translations/en.json | 3 + source/shared/library/version.ts | 2 +- 8 files changed, 174 insertions(+), 44 deletions(-) create mode 100644 source/popup/components/entries/EntryInfoDialog.tsx diff --git a/source/background/services/cryptoKeys.ts b/source/background/services/cryptoKeys.ts index 8b6d2fb5..ec180cbc 100644 --- a/source/background/services/cryptoKeys.ts +++ b/source/background/services/cryptoKeys.ts @@ -52,8 +52,12 @@ export async function deriveSecretKey(privateKey: CryptoKey, publicKey: CryptoKe } async function exportECDHKey(key: CryptoKey): Promise { - const exported = await window.crypto.subtle.exportKey("jwk", key); - return JSON.stringify(exported); + try { + const exported = await window.crypto.subtle.exportKey("jwk", key); + return JSON.stringify(exported); + } catch (err) { + throw new Layerr(err, "Failed exporting ECDH key"); + } } export async function generateKeys(): Promise { @@ -73,7 +77,12 @@ export async function generateKeys(): Promise { } export async function importECDHKey(key: string): Promise { - const jwk = JSON.parse(key) as JsonWebKey; + let jwk: JsonWebKey; + try { + jwk = JSON.parse(key) as JsonWebKey; + } catch (err) { + throw new Layerr(err, "Failed importing ECDH key"); + } const usages: Array = jwk.key_ops && jwk.key_ops.includes("deriveKey") ? ["deriveKey"] : []; return window.crypto.subtle.importKey( "jwk", diff --git a/source/popup/components/entries/EntryInfoDialog.tsx b/source/popup/components/entries/EntryInfoDialog.tsx new file mode 100644 index 00000000..5053efac --- /dev/null +++ b/source/popup/components/entries/EntryInfoDialog.tsx @@ -0,0 +1,97 @@ +import React, { useMemo } from "react"; +import { Button, Classes, Dialog, DialogBody } from "@blueprintjs/core"; +import { SearchResult } from "buttercup"; +import cn from "classnames"; +import styled from "styled-components"; + +interface EntryInfoDialogProps { + entry: SearchResult | null; + onClose: () => void; +} + +interface EntryProperty { + key: string; + sensitive: boolean; + title: string; + value: string; +} + +const InfoDialog = styled(Dialog)` + max-width: 90%; +`; +const InfoDialogBody = styled(DialogBody)` + display: flex; + flex-direction: row; + justify-content: stretch; + align-items: flex-start; + overflow-x: hidden; +`; +const InfoTable = styled.table` + table-layout: fixed; + width: 100%; +`; +const ValueInput = styled.input` + width: 100%; +`; + +export function EntryInfoDialog(props: EntryInfoDialogProps) { + const { entry, onClose } = props; + const properties = useMemo(() => entry ? orderProperties(entry.properties) : [], [entry]); + return ( + + + + + {properties.map(property => ( + + + {property.title}
+ + + + ))} + +
+
+
+ ); +} + +function orderProperties(properties: Record): Array { + const working = { ...properties }; + delete working["title"]; + const output: Array = []; + if (working["username"]) { + output.push({ + key: "username", + sensitive: false, + title: "Username", + value: properties["username"] + }); + delete working["username"]; + } + if (working["password"]) { + output.push({ + key: "password", + sensitive: true, + title: "Password", + value: properties["password"] + }); + delete working["password"]; + } + for (const prop in working) { + output.push({ + key: prop, + sensitive: false, + title: prop, + value: working[prop] + }); + } + return output; +} diff --git a/source/popup/components/entries/EntryItem.tsx b/source/popup/components/entries/EntryItem.tsx index cd5d4c59..3053c228 100644 --- a/source/popup/components/entries/EntryItem.tsx +++ b/source/popup/components/entries/EntryItem.tsx @@ -14,6 +14,7 @@ interface EntryItemProps { fetchIcons: boolean; onAutoClick: () => void; onClick: () => void; + onInfoClick: () => void; } const CenteredText = styled(Text)` @@ -66,7 +67,8 @@ export function EntryItem(props: EntryItemProps) { entry, fetchIcons, onAutoClick, - onClick + onClick, + onInfoClick } = props; const { source: popupSource } = useContext(LaunchContext); const entryDomain = useMemo(() => { @@ -91,6 +93,11 @@ export function EntryItem(props: EntryItemProps) { }, [onAutoClick] ); + const handleEntryInfoClick = useCallback((evt: MouseEvent) => { + evt.preventDefault(); + evt.stopPropagation(); + onInfoClick(); + }, [onInfoClick]); return ( @@ -119,6 +126,15 @@ export function EntryItem(props: EntryItemProps) { onClick={handleEntryLoginClick} /> + +