From 9529a685e1b2ae0707cc32118ac78dd1a9d9065a Mon Sep 17 00:00:00 2001 From: Petr Spac Date: Sat, 11 Mar 2023 19:12:32 +0100 Subject: [PATCH 1/2] remove domCoordinates --- backend/gqlSchemas/authier.graphql | 18 ++++++++---------- backend/models/WebInputElement.ts | 2 -- backend/models/generated/WebInputGQL.ts | 3 --- .../migration.sql | 8 ++++++++ backend/prisma/schema.prisma | 1 - backend/schemas/RootResolver.spec.ts | 7 +------ backend/schemas/RootResolver.ts | 3 +-- shared/generated/graphqlBaseTypes.ts | 11 ++++++++--- web-extension/src/background/backgroundPage.ts | 1 - .../src/background/backgroundSchemas.ts | 4 +--- .../chromeRuntimeListener.codegen.tsx | 3 +-- .../src/background/chromeRuntimeListener.gql | 1 - .../src/background/chromeRuntimeListener.ts | 11 ++--------- .../src/content-script/DOMEventsRecorder.ts | 6 +----- web-extension/src/content-script/autofill.ts | 15 +++------------ .../components/PromptPasswordOption.tsx | 7 ------- .../src/content-script/contentScript.ts | 4 +--- .../content-script/renderLoginCredOption.tsx | 2 -- 18 files changed, 35 insertions(+), 72 deletions(-) create mode 100644 backend/prisma/migrations/20230311175349_rm_coordinates/migration.sql diff --git a/backend/gqlSchemas/authier.graphql b/backend/gqlSchemas/authier.graphql index 5ba11f29b..260bffa70 100755 --- a/backend/gqlSchemas/authier.graphql +++ b/backend/gqlSchemas/authier.graphql @@ -181,7 +181,6 @@ type WebInputGQL { kind: WebInputType! domPath: String! domOrdinal: Int! - domCoordinates: JSON! addedByUserId: String addedByUser: UserGQL UsageEvents: [SecretUsageEventGQL!]! @@ -199,14 +198,6 @@ enum WebInputType { CUSTOM } -""" -The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). -""" -scalar JSON - @specifiedBy( - url: "http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf" - ) - type DecryptionChallengeGQL { id: Int! ipAddress: String! @@ -326,6 +317,14 @@ type DecryptionChallengeForApproval { deviceId: ID! } +""" +The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). +""" +scalar JSON + @specifiedBy( + url: "http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf" + ) + type Mutation { """ you need to be authenticated to call this resolver @@ -597,5 +596,4 @@ input WebInputElement { domOrdinal: NonNegativeInt! url: String! kind: WebInputType! - domCoordinates: JSON! } diff --git a/backend/models/WebInputElement.ts b/backend/models/WebInputElement.ts index a637aa1d3..ee43d073a 100755 --- a/backend/models/WebInputElement.ts +++ b/backend/models/WebInputElement.ts @@ -20,6 +20,4 @@ export class WebInputElement { url: string @Field(() => WebInputTypeGQL) kind: WebInputTypeGQL - @Field(() => GraphQLJSON) - domCoordinates: ICoordinates } diff --git a/backend/models/generated/WebInputGQL.ts b/backend/models/generated/WebInputGQL.ts index 17d5b2844..ba71c0f11 100644 --- a/backend/models/generated/WebInputGQL.ts +++ b/backend/models/generated/WebInputGQL.ts @@ -32,9 +32,6 @@ export class WebInputGQLScalars { @Field(() => Int) domOrdinal: number - @Field(() => GraphQLScalars.JSONResolver) - domCoordinates: Prisma.JsonValue - @Field(() => String, { nullable: true }) addedByUserId: string | null } diff --git a/backend/prisma/migrations/20230311175349_rm_coordinates/migration.sql b/backend/prisma/migrations/20230311175349_rm_coordinates/migration.sql new file mode 100644 index 000000000..15883b792 --- /dev/null +++ b/backend/prisma/migrations/20230311175349_rm_coordinates/migration.sql @@ -0,0 +1,8 @@ +/* + Warnings: + + - You are about to drop the column `domCoordinates` on the `WebInput` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "WebInput" DROP COLUMN "domCoordinates"; diff --git a/backend/prisma/schema.prisma b/backend/prisma/schema.prisma index d101d9bc5..e2606a01b 100755 --- a/backend/prisma/schema.prisma +++ b/backend/prisma/schema.prisma @@ -149,7 +149,6 @@ model WebInput { kind WebInputType domPath String domOrdinal Int @default(0) - domCoordinates Json addedByUser User? @relation(fields: [addedByUserId], references: [id], onDelete: SetNull) addedByUserId String? @db.Uuid UsageEvents SecretUsageEvent[] diff --git a/backend/schemas/RootResolver.spec.ts b/backend/schemas/RootResolver.spec.ts index ed33f9bde..2d6ee07a3 100755 --- a/backend/schemas/RootResolver.spec.ts +++ b/backend/schemas/RootResolver.spec.ts @@ -265,12 +265,7 @@ describe('RootResolver', () => { url: 'https://google.com', kind: WebInputTypeGQL.PASSWORD, domOrdinal: 1, - domPath: 'body', - - domCoordinates: { - x: 2.234, - y: 3.234 - } + domPath: 'body' } ], fakeCtx diff --git a/backend/schemas/RootResolver.ts b/backend/schemas/RootResolver.ts index f996f456f..02a371fdd 100755 --- a/backend/schemas/RootResolver.ts +++ b/backend/schemas/RootResolver.ts @@ -446,8 +446,7 @@ export class RootResolver { host: new URL(webInput.url).host, domPath: webInput.domPath, kind: webInput.kind, - addedByUserId: ctx.jwtPayload.userId, - domCoordinates: webInput.domCoordinates as any // TODO prisma types for JSON fields suck + addedByUserId: ctx.jwtPayload.userId } const input = await ctx.prisma.webInput.upsert({ create: forUpsert, diff --git a/shared/generated/graphqlBaseTypes.ts b/shared/generated/graphqlBaseTypes.ts index 105847ac1..1f5c180bf 100755 --- a/shared/generated/graphqlBaseTypes.ts +++ b/shared/generated/graphqlBaseTypes.ts @@ -201,6 +201,7 @@ export type DeviceQuery = { User: UserGql; UserMaster?: Maybe; createdAt: Scalars['DateTime']; + /** Get all secrets that were change since last device sync */ encryptedSecretsToSync: Array; firebaseToken: Scalars['String']; firstIpAddress: Scalars['String']; @@ -501,7 +502,8 @@ export type UserMutation = { addDeviceSecretEncrypted: Scalars['String']; addEncryptedSecrets: Array; autofill: Scalars['Boolean']; - changeMasterPassword: Scalars['PositiveInt']; + changeEmail: UserQuery; + changeMasterPassword: Scalars['Int']; createCheckoutSession: Scalars['String']; createPortalSession: Scalars['String']; createSecretUsageEvent: SecretUsageEventGqlScalars; @@ -541,6 +543,11 @@ export type UserMutationAddEncryptedSecretsArgs = { }; +export type UserMutationChangeEmailArgs = { + email: Scalars['EmailAddress']; +}; + + export type UserMutationChangeMasterPasswordArgs = { input: ChangeMasterPasswordInput; }; @@ -655,7 +662,6 @@ export type UserQuerySendAuthMessageArgs = { }; export type WebInputElement = { - domCoordinates: Scalars['JSON']; /** The index of the input element on the page (0-based). We are not able to always generate a css selector which matches only one element. Here the domOrdinal comes in and saves the day. */ domOrdinal: Scalars['NonNegativeInt']; domPath: Scalars['String']; @@ -669,7 +675,6 @@ export type WebInputGql = { addedByUser?: Maybe; addedByUserId?: Maybe; createdAt: Scalars['DateTime']; - domCoordinates: Scalars['JSON']; domOrdinal: Scalars['Int']; domPath: Scalars['String']; host: Scalars['String']; diff --git a/web-extension/src/background/backgroundPage.ts b/web-extension/src/background/backgroundPage.ts index 170a54786..41ea9f55a 100755 --- a/web-extension/src/background/backgroundPage.ts +++ b/web-extension/src/background/backgroundPage.ts @@ -49,7 +49,6 @@ export interface ICapturedInput { type: 'input' | 'submit' | 'keydown' kind: WebInputType inputted?: string | undefined - domCoordinates: Coord } export interface ILoginCredentialsFromContentScript { diff --git a/web-extension/src/background/backgroundSchemas.ts b/web-extension/src/background/backgroundSchemas.ts index d60a9231f..2745d1dea 100644 --- a/web-extension/src/background/backgroundSchemas.ts +++ b/web-extension/src/background/backgroundSchemas.ts @@ -13,8 +13,7 @@ export const capturedInputSchema = z.object({ z.literal('keydown') ]), kind: z.nativeEnum(WebInputType), - inputted: z.string().optional(), - domCoordinates: z.object({ x: z.number(), y: z.number() }) + inputted: z.string().optional() }) export const contentScriptContextSchema = z.object({ @@ -45,7 +44,6 @@ export const capturedEventsPayloadSchema = z.object({ }) export const webInputElementSchema = z.object({ - domCoordinates: z.object({ x: z.number(), y: z.number() }), domOrdinal: z.number(), domPath: z.string(), kind: z.nativeEnum(WebInputType), diff --git a/web-extension/src/background/chromeRuntimeListener.codegen.tsx b/web-extension/src/background/chromeRuntimeListener.codegen.tsx index 25be2f340..095410e14 100755 --- a/web-extension/src/background/chromeRuntimeListener.codegen.tsx +++ b/web-extension/src/background/chromeRuntimeListener.codegen.tsx @@ -15,7 +15,7 @@ export type WebInputsForHostQueryVariables = Types.Exact<{ }>; -export type WebInputsForHostQuery = { __typename?: 'Query', webInputs: Array<{ __typename?: 'WebInputGQL', id: number, host: string, url: string, domPath: string, domOrdinal: number, kind: Types.WebInputType, createdAt: string, domCoordinates: any }> }; +export type WebInputsForHostQuery = { __typename?: 'Query', webInputs: Array<{ __typename?: 'WebInputGQL', id: number, host: string, url: string, domPath: string, domOrdinal: number, kind: Types.WebInputType, createdAt: string }> }; export const AddWebInputsDocument = gql` @@ -61,7 +61,6 @@ export const WebInputsForHostDocument = gql` domOrdinal kind createdAt - domCoordinates } } `; diff --git a/web-extension/src/background/chromeRuntimeListener.gql b/web-extension/src/background/chromeRuntimeListener.gql index bb2059e23..a79416bb4 100755 --- a/web-extension/src/background/chromeRuntimeListener.gql +++ b/web-extension/src/background/chromeRuntimeListener.gql @@ -13,6 +13,5 @@ query webInputsForHost($host: String!) { domOrdinal kind createdAt - domCoordinates } } diff --git a/web-extension/src/background/chromeRuntimeListener.ts b/web-extension/src/background/chromeRuntimeListener.ts index 7d7917675..56d9415c9 100755 --- a/web-extension/src/background/chromeRuntimeListener.ts +++ b/web-extension/src/background/chromeRuntimeListener.ts @@ -34,17 +34,12 @@ if (!isRunningInBgPage) { throw new Error('this file should only be imported in the background page') } -interface Coord { - x: number - y: number -} export interface ICapturedInput { cssSelector: string domOrdinal: number type: 'input' | 'submit' | 'keydown' kind: WebInputType inputted?: string | undefined - domCoordinates: Coord } interface ILoginCredentialsFromContentScript { @@ -122,8 +117,7 @@ const appRouter = tc.router({ domPath: captured.cssSelector, kind: captured.kind, url: inputsUrl, - domOrdinal: captured.domOrdinal, - domCoordinates: captured.domCoordinates + domOrdinal: captured.domOrdinal } }) @@ -153,8 +147,7 @@ const appRouter = tc.router({ domPath: captured.cssSelector, kind: captured.kind, url: inputsUrl, - domOrdinal: captured.domOrdinal, - domCoordinates: captured.domCoordinates + domOrdinal: captured.domOrdinal } }) diff --git a/web-extension/src/content-script/DOMEventsRecorder.ts b/web-extension/src/content-script/DOMEventsRecorder.ts index b98512b6a..5bc782864 100755 --- a/web-extension/src/content-script/DOMEventsRecorder.ts +++ b/web-extension/src/content-script/DOMEventsRecorder.ts @@ -116,11 +116,7 @@ export class DOMEventsRecorder { domOrdinal: getSelectorForElement(element).domOrdinal, type, kind: kind as WebInputType, - inputted, - domCoordinates: { - x: rect.x, - y: rect.y - } + inputted } } ) diff --git a/web-extension/src/content-script/autofill.ts b/web-extension/src/content-script/autofill.ts index a7e3b8c6f..5909a08a5 100755 --- a/web-extension/src/content-script/autofill.ts +++ b/web-extension/src/content-script/autofill.ts @@ -32,7 +32,6 @@ type webInput = { domPath: string kind: WebInputType createdAt: string - domCoordinates: Coords } export const autofillEventsDispatched = new Set() @@ -235,13 +234,7 @@ export const autofill = (initState: IInitStateRes, autofillEnabled = false) => { authenticator.generate(totpSecret.totp.secret) ) } - //NOTE: We did not find element by DOM path, so find it by input coords - } else if ( - webInputGql.domCoordinates.x === rect?.x && - webInputGql.domCoordinates.y === rect?.y - ) { - inputEl = document.elementFromPoint(rect?.x, rect?.y) as any - log('el', inputEl) + //NOTE: We did not find element by DOM path } }) .filter((el) => !!el) @@ -418,8 +411,7 @@ export const autofill = (initState: IInitStateRes, autofillEnabled = false) => { domPath: getSelectorForElement(input).css, host: location.host, url: location.href, - kind: WebInputType.PASSWORD, - domCoordinates: getElementCoordinates(input) + kind: WebInputType.PASSWORD }) domRecorder.addInputEvent({ @@ -445,8 +437,7 @@ export const autofill = (initState: IInitStateRes, autofillEnabled = false) => { domPath: getSelectorForElement(inputElsArray[j]).css, host: location.host, url: location.href, - kind: WebInputType.USERNAME, - domCoordinates: getElementCoordinates(input) + kind: WebInputType.USERNAME }) domRecorder.addInputEvent({ diff --git a/web-extension/src/content-script/components/PromptPasswordOption.tsx b/web-extension/src/content-script/components/PromptPasswordOption.tsx index d3ff0bac8..4e6adc3ea 100755 --- a/web-extension/src/content-script/components/PromptPasswordOption.tsx +++ b/web-extension/src/content-script/components/PromptPasswordOption.tsx @@ -22,13 +22,6 @@ export const PromptPasswordOption = (props: PromptPasswordOptionProps) => { } let el = document.querySelector(webInputs[0].domPath) - if (!el) { - el = document.elementFromPoint( - webInputs[0].domCoordinates.x, - webInputs[0].domCoordinates.y - ) - log('el', el) - } const [pos, setPos] = useState(el?.getBoundingClientRect()) let resizeTimer: string | number | NodeJS.Timeout | undefined diff --git a/web-extension/src/content-script/contentScript.ts b/web-extension/src/content-script/contentScript.ts index 2bef5285a..de141135d 100755 --- a/web-extension/src/content-script/contentScript.ts +++ b/web-extension/src/content-script/contentScript.ts @@ -50,7 +50,6 @@ export interface IInitStateRes { domPath: string kind: WebInputType createdAt: string - domCoordinates: Coords }> saveLoginModalsState?: | { @@ -175,8 +174,7 @@ export async function initInputWatch() { domPath: elementSelector.css, domOrdinal: elementSelector.domOrdinal, kind: WebInputType.TOTP, - url: location.href, - domCoordinates: getElementCoordinates(targetElement) + url: location.href } await trpc.addTOTPInput.mutate(webInput) log(`TOTP WebInput added for selector "${elementSelector}"`) diff --git a/web-extension/src/content-script/renderLoginCredOption.tsx b/web-extension/src/content-script/renderLoginCredOption.tsx index 19f119cad..e82ffda0d 100755 --- a/web-extension/src/content-script/renderLoginCredOption.tsx +++ b/web-extension/src/content-script/renderLoginCredOption.tsx @@ -3,7 +3,6 @@ import { ILoginSecret } from '../util/useDeviceState' import { h, render } from 'preact' import { PromptPasswordOption } from './components/PromptPasswordOption' import { WebInputType } from '../../../shared/generated/graphqlBaseTypes' -import { Coords } from './contentScript' // eslint-disable-next-line @typescript-eslint/no-unused-vars const nano = h @@ -20,7 +19,6 @@ export type PromptPasswordOptionProps = { domPath: string kind: WebInputType createdAt: string - domCoordinates: Coords }> } From c5f16e221be9b463b3ac0ea9a932f28a7687218c Mon Sep 17 00:00:00 2001 From: Petr Spac Date: Sat, 11 Mar 2023 21:13:30 +0100 Subject: [PATCH 2/2] fix --- backend/schemas/__snapshots__/RootResolver.spec.ts.snap | 4 ---- 1 file changed, 4 deletions(-) diff --git a/backend/schemas/__snapshots__/RootResolver.spec.ts.snap b/backend/schemas/__snapshots__/RootResolver.spec.ts.snap index 4ecc82df4..752bcf3ee 100644 --- a/backend/schemas/__snapshots__/RootResolver.spec.ts.snap +++ b/backend/schemas/__snapshots__/RootResolver.spec.ts.snap @@ -3,10 +3,6 @@ exports[`RootResolver > addWebInputs > should add to the DB 1`] = ` { "addedByUserId": "811354ee-2834-4321-8a9f-507771d96955", - "domCoordinates": { - "x": 2.234, - "y": 3.234, - }, "domOrdinal": 0, "domPath": "body", "host": "google.com",