Skip to content

Commit a732dd6

Browse files
Merge branch 'main' into auto-lock-configuration-page
2 parents cb6e9b6 + af7b8c5 commit a732dd6

14 files changed

Lines changed: 3363 additions & 3016 deletions

File tree

.github/workflows/lint.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Lint check
2+
3+
on:
4+
push:
5+
branches: [ main, dev ]
6+
pull_request:
7+
branches: [ main, dev ]
8+
9+
permissions:
10+
contents: read
11+
packages: read
12+
13+
jobs:
14+
lint:
15+
runs-on: ubuntu-latest
16+
17+
steps:
18+
- name: Checkout code
19+
uses: actions/checkout@v4
20+
with:
21+
submodules: recursive
22+
23+
- name: Setup Node.js
24+
uses: actions/setup-node@v4
25+
with:
26+
node-version: "22.x"
27+
28+
- name: Install dependencies
29+
run: npm ci
30+
31+
- name: Run ESLint
32+
run: npm run lint

.github/workflows/test.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Test check
2+
3+
on:
4+
push:
5+
branches: [ main, dev ]
6+
pull_request:
7+
branches: [ main, dev ]
8+
9+
permissions:
10+
contents: read
11+
packages: read
12+
13+
jobs:
14+
test:
15+
runs-on: ubuntu-latest
16+
17+
steps:
18+
- name: Checkout code
19+
uses: actions/checkout@v4
20+
with:
21+
submodules: recursive
22+
23+
- name: Setup Node.js
24+
uses: actions/setup-node@v4
25+
with:
26+
node-version: "22.x"
27+
28+
- name: Install dependencies
29+
run: npm ci
30+
31+
- name: Run tests
32+
run: npm test

.husky/pre-commit

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
npm run lint

package-lock.json

Lines changed: 3213 additions & 2951 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
"@lingui/babel-plugin-lingui-macro": "5.1.2",
6464
"@lingui/cli": "5.1.2",
6565
"@testing-library/jest-dom": "6.6.3",
66-
"@testing-library/react": "16.2.0",
66+
"@testing-library/react": "15.0.7",
6767
"@vitejs/plugin-react": "4.3.4",
6868
"babel-jest": "29.7.0",
6969
"husky": "9.1.7",
@@ -74,4 +74,4 @@
7474
"prettier-plugin-tailwindcss": "0.6.11",
7575
"vite": "6.3.1"
7676
}
77-
}
77+
}

src/action/containers/FolderDropDown/index.jsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,18 @@ export const FolderDropdown = ({
4242
icon: FolderIcon
4343
})
4444
} else {
45-
mappedFolders.unshift({ name: t`All`, type: ALL, icon: FolderIcon })
45+
mappedFolders.unshift({
46+
name: t`All Items`,
47+
type: ALL,
48+
icon: FolderIcon
49+
})
4650
}
4751
}
4852

4953
return mappedFolders
5054
}, [folders, selectedFolder])
5155

52-
const defaultName = type === 'select' ? t`No Folder` : t`All`
56+
const defaultName = type === 'select' ? t`No Folder` : t`All Items`
5357

5458
const name = selectedFolder ? selectedFolder : defaultName
5559
const icon = selectedFolder ? FolderIcon : undefined

src/action/pages/WelcomePage/LoadVault/index.jsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,17 +66,25 @@ export const LoadVault = () => {
6666
<>
6767
<CardWelcome>
6868
<WelcomeCardHeader
69-
title={t`Loading an existing vault`}
69+
title={t`Import an existing vault`}
7070
onBack={() =>
7171
navigate('welcome', {
7272
params: { state: NAVIGATION_ROUTES.VAULTS }
7373
})
7474
}
7575
/>
7676

77+
<p className="text-white-mode1 text-center text-[14px]">
78+
<Trans>
79+
Using PearPass on your other device, use "Add Device" to generate a
80+
QR or connection code to pair your account. This method keeps your
81+
account secure.
82+
</Trans>
83+
</p>
84+
7785
<input
7886
className="border-grey100-mode1 text-grey100-mode1 w-full rounded-[10px] border-[1px] bg-transparent px-[20px] py-[12px] focus:outline-none"
79-
placeholder={t`Insert your code vault...`}
87+
placeholder={t`Enter your vault code…`}
8088
value={inviteCode}
8189
onChange={handleChange}
8290
/>
@@ -91,7 +99,7 @@ export const LoadVault = () => {
9199
</ButtonSecondary>
92100
) : (
93101
<ButtonPrimary onClick={handleLoadVault} disabled={isLoading}>
94-
<Trans>Confirm</Trans>
102+
<Trans>Import vault</Trans>
95103
</ButtonPrimary>
96104
)}
97105
</div>

src/background/index.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ import './nativeMessaging' // Initialize native messaging handler
22
import { MESSAGES, ALARMS } from './constants'
33
import { secureChannel } from './secureChannel'
44
import * as CredentialGenerator from './utils/credentialGenerator'
5+
import { validateSender } from './utils/validateSender'
56
import { ERROR_CODES } from '../shared/constants/nativeMessaging'
7+
import {
8+
MESSAGE_TYPES,
9+
SECURE_MESSAGE_TYPES
10+
} from '../shared/services/messageBridge'
611
import { arrayBufferToBase64Url } from '../shared/utils/arrayBufferToBase64Url'
712
import { base64UrlToArrayBuffer } from '../shared/utils/base64UrlToArrayBuffer'
813
import { logger } from '../shared/utils/logger'
9-
import { validateSender } from './utils/validateSender'
10-
import { MESSAGE_TYPES, SECURE_MESSAGE_TYPES } from '../shared/services/messageBridge'
1114

1215
const { SCHEDULE_CLIPBOARD_CLEAR, CLEAR_CLIPBOARD_NOW } = MESSAGES
1316
const { CLEAR_CLIPBOARD } = ALARMS
@@ -71,7 +74,6 @@ chrome.alarms.onAlarm.addListener(async (alarm) => {
7174
})
7275

7376
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
74-
7577
const sensitiveTypes = [
7678
...Object.values(SECURE_MESSAGE_TYPES),
7779
MESSAGE_TYPES.READY_FOR_PASSKEY_PAYLOAD,
@@ -80,7 +82,7 @@ chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
8082

8183
if (sensitiveTypes.includes(msg.type)) {
8284
if (!validateSender(sender, 'extension-page')) {
83-
sendResponse({ success: false, error: 'Unauthorized' });
85+
sendResponse({ success: false, error: 'Unauthorized' })
8486
return
8587
}
8688
}
@@ -168,7 +170,7 @@ chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
168170
}
169171

170172
if (msg.type === MESSAGE_TYPES.GET_IDENTITY) {
171-
; (async () => {
173+
;(async () => {
172174
try {
173175
const { pairingToken } = msg
174176
if (!pairingToken) {
@@ -193,7 +195,7 @@ chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
193195
}
194196

195197
if (msg.type === MESSAGE_TYPES.CONFIRM_PAIR) {
196-
; (async () => {
198+
;(async () => {
197199
try {
198200
await secureChannel.pinIdentity(msg.identity)
199201
const handshake = await secureChannel.beginHandshake()
@@ -227,7 +229,7 @@ chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
227229
}
228230

229231
if (msg.type === MESSAGE_TYPES.CHECK_PAIRED) {
230-
; (async () => {
232+
;(async () => {
231233
try {
232234
const paired = await secureChannel.isPaired()
233235
sendResponse({ paired })
@@ -250,7 +252,7 @@ chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
250252
}
251253

252254
if (msg.type === SCHEDULE_CLIPBOARD_CLEAR) {
253-
; (async () => {
255+
;(async () => {
254256
await chrome.alarms.clear(CLEAR_CLIPBOARD)
255257
const when = Date.now() + msg.delayMs
256258
await chrome.alarms.create(CLEAR_CLIPBOARD, { when })

src/background/senderValidation.test.js

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,48 +4,48 @@ const EXTENSION_ID = 'mcajgeipojjbbmnhidnmohfncdkdoack'
44
const EXTENSION_URL = `chrome-extension://${EXTENSION_ID}/`
55

66
global.chrome = {
7-
runtime: {
8-
getURL: (path) => `${EXTENSION_URL}${path}`
9-
}
7+
runtime: {
8+
getURL: (path) => `${EXTENSION_URL}${path}`
9+
}
1010
}
1111

1212
describe('validateSender', () => {
13-
describe('extension-page context', () => {
14-
it('allows messages from own extension pages', () => {
15-
const sender = { url: `chrome-extension://${EXTENSION_ID}/popup.html` }
16-
expect(validateSender(sender, 'extension-page')).toBe(true)
17-
})
18-
19-
it('blocks messages from other extensions', () => {
20-
const sender = { url: 'chrome-extension://other-id/popup.html' }
21-
expect(validateSender(sender, 'extension-page')).toBeFalsy()
22-
})
23-
24-
it('blocks messages with undefined url', () => {
25-
const sender = { url: undefined }
26-
expect(validateSender(sender, 'extension-page')).toBeFalsy()
27-
})
13+
describe('extension-page context', () => {
14+
it('allows messages from own extension pages', () => {
15+
const sender = { url: `chrome-extension://${EXTENSION_ID}/popup.html` }
16+
expect(validateSender(sender, 'extension-page')).toBe(true)
2817
})
2918

30-
describe('content-script context', () => {
31-
it('allows messages with valid tab id', () => {
32-
const sender = { tab: { id: 123 } }
33-
expect(validateSender(sender, 'content-script')).toBe(true)
34-
})
19+
it('blocks messages from other extensions', () => {
20+
const sender = { url: 'chrome-extension://other-id/popup.html' }
21+
expect(validateSender(sender, 'extension-page')).toBeFalsy()
22+
})
23+
24+
it('blocks messages with undefined url', () => {
25+
const sender = { url: undefined }
26+
expect(validateSender(sender, 'extension-page')).toBeFalsy()
27+
})
28+
})
3529

36-
it('blocks messages without tab context', () => {
37-
const sender = { url: 'chrome-extension://id/popup.html' }
38-
expect(validateSender(sender, 'content-script')).toBe(false)
39-
})
30+
describe('content-script context', () => {
31+
it('allows messages with valid tab id', () => {
32+
const sender = { tab: { id: 123 } }
33+
expect(validateSender(sender, 'content-script')).toBe(true)
4034
})
4135

42-
describe('default behavior', () => {
43-
it('allows any message for "any" context', () => {
44-
expect(validateSender({}, 'any')).toBe(true)
45-
})
36+
it('blocks messages without tab context', () => {
37+
const sender = { url: 'chrome-extension://id/popup.html' }
38+
expect(validateSender(sender, 'content-script')).toBe(false)
39+
})
40+
})
41+
42+
describe('default behavior', () => {
43+
it('allows any message for "any" context', () => {
44+
expect(validateSender({}, 'any')).toBe(true)
45+
})
4646

47-
it('blocks unknown context types', () => {
48-
expect(validateSender({}, 'unknown')).toBe(false)
49-
})
47+
it('blocks unknown context types', () => {
48+
expect(validateSender({}, 'unknown')).toBe(false)
5049
})
50+
})
5151
})

0 commit comments

Comments
 (0)