1.add smoke test and modify code to make it work

This commit is contained in:
Kent Wang
2025-01-24 16:16:57 +08:00
parent 2a008959e0
commit b5f77f0379
11 changed files with 521 additions and 4 deletions

View File

@@ -0,0 +1,271 @@
_type: export
__export_format: 4
__export_date: 2025-01-24T07:58:39.196Z
__export_source: insomnia.desktop.app:v10.3.1-beta.0
resources:
- _id: req_d6152608f4ca49aaadce1b379bf52fac
parentId: wrk_37e3ee9c2ce7468493378fa5e525b4b1
modified: 1737705511624
created: 1737705423707
url: localhost:4010/
name: normal
description: ""
method: GET
body:
mimeType: text/plain
text: |-
{{ _.vault.foo }}
{{ _.vault.hello }}
parameters: []
headers:
- name: Content-Type
value: text/plain
- name: User-Agent
value: insomnia/10.3.1-beta.0
authentication: {}
metaSortKey: -1737705423707
isPrivate: false
pathParameters: []
settingStoreCookies: true
settingSendCookies: true
settingDisableRenderRequestBody: false
settingEncodeUrl: true
settingRebuildPath: true
settingFollowRedirects: global
_type: request
- _id: wrk_37e3ee9c2ce7468493378fa5e525b4b1
parentId: null
modified: 1737705410863
created: 1737705410863
name: Vault Collection
description: ""
scope: collection
_type: workspace
- _id: req_1c9ef3a2afae47d1bd960ae23de09750
parentId: wrk_37e3ee9c2ce7468493378fa5e525b4b1
modified: 1737617845875
created: 1734948333857
url: localhost:4010/
name: legacy-array-vault
description: ""
method: GET
body:
mimeType: text/plain
text: |-
{{ _.vault.secret }}
{{ _.vault[0] }}
parameters:
- id: pair_74f9877885a84128b4d5afc0dfc77945
name: ""
value: ""
description: ""
disabled: false
headers:
- name: Content-Type
value: text/plain
- name: User-Agent
value: insomnia/10.2.1-beta.1
authentication:
type: apikey
disabled: false
key: ""
value: ""
addTo: header
preRequestScript: |-
console.log('pre');
console.log(insomnia.variables.get('vault')[1]);
console.log(insomnia.vault.get('foo'));
metaSortKey: -1734948333857
isPrivate: false
pathParameters: []
afterResponseScript: |-
console.log('after');
console.log(insomnia.vault.get('hello'));
settingStoreCookies: true
settingSendCookies: true
settingDisableRenderRequestBody: false
settingEncodeUrl: true
settingRebuildPath: true
settingFollowRedirects: global
_type: request
- _id: req_2a150b45acb242cfa2db04d929a11085
parentId: wrk_37e3ee9c2ce7468493378fa5e525b4b1
modified: 1737617920254
created: 1737617896390
url: localhost:4010/
name: legacy-invalid-vault
description: ""
method: GET
body:
mimeType: text/plain
text: ""
parameters:
- id: pair_74f9877885a84128b4d5afc0dfc77945
name: ""
value: ""
description: ""
disabled: false
headers:
- name: Content-Type
value: text/plain
- name: User-Agent
value: insomnia/10.2.1-beta.1
authentication:
type: apikey
disabled: false
key: ""
value: ""
addTo: header
metaSortKey: -1731983168815.5
isPrivate: false
pathParameters: []
settingStoreCookies: true
settingSendCookies: true
settingDisableRenderRequestBody: false
settingEncodeUrl: true
settingRebuildPath: true
settingFollowRedirects: global
_type: request
- _id: req_fb7fb8d4345f471fb53d03b069737a07
parentId: wrk_37e3ee9c2ce7468493378fa5e525b4b1
modified: 1737617874271
created: 1737617856040
url: localhost:4010/
name: legacy-object-vault
description: ""
method: GET
body:
mimeType: text/plain
text: |-
{{ _.vault.secret }}
{{ _.vault.v1 }}
parameters:
- id: pair_74f9877885a84128b4d5afc0dfc77945
name: ""
value: ""
description: ""
disabled: false
headers:
- name: Content-Type
value: text/plain
- name: User-Agent
value: insomnia/10.2.1-beta.1
authentication:
type: apikey
disabled: false
key: ""
value: ""
addTo: header
preRequestScript: |-
console.log('pre');
console.log(insomnia.variables.get('vault').v2)
console.log(insomnia.vault.get('foo'));
metaSortKey: -1729018003774
isPrivate: false
pathParameters: []
afterResponseScript: |-
console.log('after');
console.log(insomnia.vault.get('hello'));
settingStoreCookies: true
settingSendCookies: true
settingDisableRenderRequestBody: false
settingEncodeUrl: true
settingRebuildPath: true
settingFollowRedirects: global
_type: request
- _id: env_40681941450149a4a41f2dcbc22ec616
parentId: wrk_37e3ee9c2ce7468493378fa5e525b4b1
modified: 1737618683836
created: 1732861968102
name: Base Environment1
data:
a_hello: test
"": ""
dataPropertyOrder:
"&":
- a_hello
- ""
color: null
isPrivate: false
metaSortKey: 1732861968102
environmentType: kv
kvPairData:
- id: envPair_62a7e9c0cdb949e0abf15e0fe4b1e8d3
name: a_hello
value: test
type: str
enabled: true
- id: envPair_e479dfc1d364470eb3cd717e277953c9
name: ""
value: ""
type: str
enabled: true
_type: environment
- _id: jar_51eb1ce9f9e74e7684c8114098b1aa33
parentId: wrk_37e3ee9c2ce7468493378fa5e525b4b1
modified: 1737618683835
created: 1734948168939
name: Default Jar
cookies: []
_type: cookie_jar
- _id: env_7ace551350dc40cbbb8302234ec0af0a
parentId: env_40681941450149a4a41f2dcbc22ec616
modified: 1737618683836
created: 1736745679348
name: base with vault
data:
vault: hello
dataPropertyOrder:
"&":
- vault
color: null
isPrivate: false
metaSortKey: 1736745679348
environmentType: kv
kvPairData:
- id: envPair_4bcd80eeb9c544c8a5cca0a1a6a85ffc
name: vault
value: hello
type: str
enabled: true
_type: environment
- _id: env_fce7e052bb99440a9019a162afea7f85
parentId: env_40681941450149a4a41f2dcbc22ec616
modified: 1737617847199
created: 1736745692249
name: legacy vault value array
data:
vault:
- vault_array_a
- vault_array_b
- vault_array_c
dataPropertyOrder:
"&":
- vault
color: null
isPrivate: false
metaSortKey: 1736745679398
environmentType: json
kvPairData: []
_type: environment
- _id: env_9214888ae2dc497e87a7f8f8edaf19f2
parentId: env_40681941450149a4a41f2dcbc22ec616
modified: 1737617875350
created: 1737617352406
name: legacy vault value object
data:
vault:
v1: secv1
v2: secv2
dataPropertyOrder:
"&":
- vault
"&~|vault":
- v1
- v2
color: null
isPrivate: false
metaSortKey: 1736881902959
environmentType: json
kvPairData: []
_type: environment

View File

@@ -0,0 +1,78 @@
_type: export
__export_format: 4
__export_date: 2025-01-23T07:52:47.609Z
__export_source: insomnia.desktop.app:v10.3.1-beta.0
resources:
- _id: wrk_11afcca54849448ca59100f5f31e556b
type: Workspace
parentId: proj_668d3ef4abb1456f9926ee9e0adee62b
modified: 1735021392122
created: 1735021392122
name: Global env with secret vault
description: ""
scope: environment
_type: workspace
- _id: env_214ce88837cd0a36c40a0ea6a84c7c6177663206
type: Environment
parentId: wrk_11afcca54849448ca59100f5f31e556b
modified: 1736751370415
created: 1735021392123
name: Base Environment
data:
from: global env with secert vault
dataPropertyOrder: null
color: null
isPrivate: false
metaSortKey: 1735021392123
environmentType: kv
kvPairData:
- id: envPair_1eefc750fae74ab0870d8e77b31023f6
name: from
value: global env with secert vault
type: str
enabled: true
- id: envPair_c2edecbf93744867acae6b9846c2fb48
name: vault
value: base_vault
type: str
enabled: false
_type: environment
- _id: env_01dcda3f8c3b4ce2b53266538f894137
type: Environment
parentId: env_214ce88837cd0a36c40a0ea6a84c7c6177663206
modified: 1737618683837
created: 1735021423365
name: vault env
data:
__insomnia_vault:
secret: eyJpdiI6ImY2NTAzYmVjMDIyYTE2YzNlNTNkMWY5MiIsInQiOiI3YzgwMGVkZGVhZGZmN2MxMjVmNmVmNzlkODY2NGM0YyIsImFkIjoiIiwiZCI6IjU2YzdlODU0NDA3MjdmOTQifQ==
foo: eyJpdiI6IjA1YjdmMjFlOWY0OGU0ZTY5NmZiNzY3OCIsInQiOiIyOTRmODZkMTc4MTMxMDVmZTc5MWMwMmZjYWU2YjM5MSIsImFkIjoiIiwiZCI6ImJkZGI3MiJ9
hello: eyJpdiI6ImRjNjQwMDNlMWEyOTc1ODhmMTYzNzRhZSIsInQiOiIxNWZmYWQ0MzdlYjdiOTJkOWRiYzMwMWIzNjQyMjJjOCIsImFkIjoiIiwiZCI6Ijc1MmM1MmUyZjkifQ==
dataPropertyOrder:
"&":
- __insomnia_vault
"&~|__insomnia_vault":
- secret
- foo
- hello
color: null
isPrivate: true
metaSortKey: 1735021423366
environmentType: kv
kvPairData:
- id: envPair_81f3c2479f9a48da8f8aaf8a3887554e
name: secret
value: eyJpdiI6ImY2NTAzYmVjMDIyYTE2YzNlNTNkMWY5MiIsInQiOiI3YzgwMGVkZGVhZGZmN2MxMjVmNmVmNzlkODY2NGM0YyIsImFkIjoiIiwiZCI6IjU2YzdlODU0NDA3MjdmOTQifQ==
type: secret
enabled: true
- id: envPair_943d0b39be9347c4abaf9b12f2373278
name: foo
value: eyJpdiI6IjA1YjdmMjFlOWY0OGU0ZTY5NmZiNzY3OCIsInQiOiIyOTRmODZkMTc4MTMxMDVmZTc5MWMwMmZjYWU2YjM5MSIsImFkIjoiIiwiZCI6ImJkZGI3MiJ9
type: secret
enabled: true
- id: envPair_692e1e97b162451da1ab3d9c54d103d9
name: hello
value: eyJpdiI6ImRjNjQwMDNlMWEyOTc1ODhmMTYzNzRhZSIsInQiOiIxNWZmYWQ0MzdlYjdiOTJkOWRiYzMwMWIzNjQyMjJjOCIsImFkIjoiIiwiZCI6Ijc1MmM1MmUyZjkifQ==
type: secret
enabled: true
_type: environment

View File

@@ -40,6 +40,8 @@ interface EnvOptions {
INSOMNIA_PUBLIC_KEY: string;
INSOMNIA_SECRET_KEY: string;
INSOMNIA_SESSION?: string;
INSOMNIA_VAULT_KEY: string;
INSOMNIA_VAULT_SALT: string;
}
export const test = baseTest.extend<{
@@ -51,6 +53,8 @@ export const test = baseTest.extend<{
publicKey: string;
secretKey: string;
code: string;
vaultKey?: string;
vaultSalt?: string;
session?: {
accountId: string;
id: string;
@@ -81,6 +85,8 @@ export const test = baseTest.extend<{
INSOMNIA_SKIP_ONBOARDING: String(userConfig.skipOnboarding),
INSOMNIA_PUBLIC_KEY: userConfig.publicKey,
INSOMNIA_SECRET_KEY: userConfig.secretKey,
INSOMNIA_VAULT_KEY: userConfig.vaultKey || '',
INSOMNIA_VAULT_SALT: userConfig.vaultSalt || '',
...userConfig.session ? { INSOMNIA_SESSION: JSON.stringify(userConfig.session) } : {},
};
@@ -135,6 +141,8 @@ export const test = baseTest.extend<{
publicKey: 'txb/w8DASTpPQqeHE/hpI3ABKzit+pv5n2We5dbtYRo=',
secretKey: 'Tb1QKsI3wVZxhS8TuQESHB2x7f68PzeTzTMmLpnnFVU=',
code: 'BTxpIfgXY1VgUpoPpqA25RkCPGQ2MAkZsaY6IZ0bamd0WsYQlJM6iy8PV9hEHS1Gk96SBC6%2BM%2FGhv8IaVl1N6V5wdghHwU2sGKGkW%2Fevx1HiqAUsAqIry8aWRqAkc0n3KmW%2B%2F8lyeHCpy5jhsXqMMqXMbZh8dN1q%2ByRe2C6MJS1A706KbPUhI7PRi%2FsmK0TcNT7lgBKKHRVzPTvjpLcjgzSJFL4K%2BEzgY9Ue4gh0gPw89sM9dV%2F2sAlpw0LA7rF06NyoPhA%3D',
vaultKey: 'eyJhbGciOiJBMjU2R0NNIiwiZXh0Ijp0cnVlLCJrIjoiaEoxaW03cjcwV3ltZ3puT3hXcDNTb0ZQS3RBaGMwcmFfd2VQb2Z2b2xRNCIsImtleV9vcHMiOlsiZW5jcnlwdCIsImRlY3J5cHQiXSwia3R5Ijoib2N0In0=',
vaultSalt: 'e619272433fc739d52ff1ba1b45debedfe55cb42685af10a46e2b1285acb7120',
session: {
'id': 'sess_64a477e6b59d43a5a607f84b4f73e3ce',
// Expire in 2077

View File

@@ -0,0 +1,135 @@
import { expect } from '@playwright/test';
import { loadFixture } from '../../playwright/paths';
import { test } from '../../playwright/test';
test.describe('Test Insomnia Vault', async () => {
test('create global private sub environment to store vaults', async ({ page, app }) => {
await page.getByLabel('Create in project').click();
await page.getByLabel('Create', { exact: true }).getByText('Environment').click();
await page.getByRole('button', { name: 'Create', exact: true }).click();
await page.getByTestId('CreateEnvironmentDropdown').click();
await page.getByText('Private environment').click();
// activate created private environment
await page.getByRole('grid', { name: 'Environments' }).getByText('New Environment').click();
const kvTable = await page.getByRole('listbox', { name: 'Environment Key Value Pair' });
// add first secret environment
const firstRow = await kvTable.getByRole('option').first();
await firstRow.getByTestId('OneLineEditor').first().click();
await page.keyboard.type('foo');
await firstRow.getByTestId('OneLineEditor').nth(1).click();
await page.keyboard.type('bar');
await page.waitForTimeout(500);
await firstRow.getByRole('button', { name: 'Type Selection' }).click();
await page.getByRole('menuitemradio', { name: 'Secret' }).click();
await expect(firstRow.locator('.fa-eye-slash')).toBeVisible();
await firstRow.locator('.fa-eye-slash').click();
// test decrypt secret in UI
await expect(firstRow.getByTestId('OneLineEditor').nth(1)).toContainText('bar');
// add second secret environment
await page.getByRole('button', { name: 'Add Row' }).click();
const secondRow = await kvTable.getByRole('option').nth(1);
await secondRow.getByTestId('OneLineEditor').first().click();
await page.keyboard.type('hello');
await secondRow.getByTestId('OneLineEditor').nth(1).click();
await page.keyboard.type('world');
await page.waitForTimeout(500);
await secondRow.getByRole('button', { name: 'Type Selection' }).click();
await page.getByRole('menuitemradio', { name: 'Secret' }).click();
// go back
await page.locator('[data-icon="chevron-left"]').click();
// import request
const requestColText = await loadFixture('vault-collection.yaml');
await app.evaluate(async ({ clipboard }, text) => clipboard.writeText(text), requestColText);
await page.getByLabel('Import').click();
await page.locator('[data-test-id="import-from-clipboard"]').click();
await page.getByRole('button', { name: 'Scan' }).click();
await page.getByRole('dialog').getByRole('button', { name: 'Import' }).click();
await page.getByText('Vault Collection').click();
// activate global private vault environment
await page.getByLabel('Manage Environments').click();
await page.getByPlaceholder('Choose a global environment').click();
await page.getByRole('option', { name: 'New Environment' }).click();
await page.getByRole('option', { name: 'New Environment' }).click();
await page.getByText('Base Environment1').click();
await page.getByTestId('underlay').click();
// activate request
await page.getByTestId('normal').getByLabel('GET normal', { exact: true }).click();
await page.getByRole('button', { name: 'Send' }).click();
await page.getByRole('tab', { name: 'Console' }).click();
await page.getByText('bar').click();
await page.getByText('world').click();
});
test('test vault environment to be applied', async ({ app, page }) => {
// import global environment
const vaultEnvText = await loadFixture('vault-environment.yaml');
await app.evaluate(async ({ clipboard }, text) => clipboard.writeText(text), vaultEnvText);
await page.getByLabel('Import').click();
await page.locator('[data-test-id="import-from-clipboard"]').click();
await page.getByRole('button', { name: 'Scan' }).click();
await page.getByRole('dialog').getByRole('button', { name: 'Import' }).click();
// import request
const requestColText = await loadFixture('vault-collection.yaml');
await app.evaluate(async ({ clipboard }, text) => clipboard.writeText(text), requestColText);
await page.getByLabel('Import').click();
await page.locator('[data-test-id="import-from-clipboard"]').click();
await page.getByRole('button', { name: 'Scan' }).click();
await page.getByRole('dialog').getByRole('button', { name: 'Import' }).click();
await page.getByText('Vault Collection').click();
// allow vault to be accessed by the request
await page.locator('[data-testid="settings-button"]').click();
await page.locator('text=Insomnia Preferences').first().click();
await page.locator('text=Enable vault in scripts').click();
await page.locator('.app').press('Escape');
await page.waitForTimeout(1000);
// activate global private vault environment
await page.getByLabel('Manage Environments').click();
await page.getByPlaceholder('Choose a global environment').click();
await page.getByRole('option', { name: 'Global env with secret vault' }).click();
await page.getByText('vault env').click();
// activate legacy array vault environment
await page.getByText('legacy vault value array').click();
await page.getByTestId('underlay').click();
// activate request
await page.getByTestId('legacy-array-vault').getByLabel('GET legacy-array-vault', { exact: true }).click();
await page.getByRole('button', { name: 'Send' }).click();
await page.getByRole('tab', { name: 'Console' }).click();
await page.getByText('password').click();
await page.getByText('bar').click();
await page.getByText('world').click();
await page.getByText('vault_array_a').click();
await page.getByText('vault_array_b').click();
// activate legacy object vault environment
await page.getByLabel('Manage Environments').click();
await page.getByText('legacy vault value object').click();
await page.getByTestId('underlay').click();
// activate request
await page.getByTestId('legacy-object-vault').getByLabel('GET legacy-object-vault', { exact: true }).click();
await page.getByRole('button', { name: 'Send' }).click();
await page.getByRole('tab', { name: 'Console' }).click();
await page.getByText('secv2').click();
await page.getByText('password').click();
await page.getByText('bar').click();
await page.getByText('world').click();
// activate invalid vault environment
await page.getByLabel('Manage Environments').click();
await page.getByText('base with vault').click();
await page.getByTestId('underlay').click();
// activate request
await page.getByTestId('legacy-invalid-vault').getByLabel('GET legacy-invalid-vault', { exact: true }).click();
await page.getByRole('button', { name: 'Send' }).click(); // Expect to see error message
await expect(page.getByText('Unexpected Request Failure')).toBeVisible();
await expect(page.getByText('vault is a reserved key for insomnia vault')).toBeVisible();
});
});

View File

@@ -156,6 +156,12 @@ export async function setSessionData(
return sessionData;
}
/** Update the session data with vault salt and vault key */
export async function setVaultSessionData(vaultSalt: string, vaultKey: string) {
const userData = await userSession.getOrCreate();
await userSession.update(userData, { vaultSalt, vaultKey });
}
// ~~~~~~~~~~~~~~~~ //
// Helper Functions //
// ~~~~~~~~~~~~~~~~ //

View File

@@ -17,6 +17,8 @@ export const getSkipOnboarding = () => env.INSOMNIA_SKIP_ONBOARDING;
export const getInsomniaSession = () => env.INSOMNIA_SESSION;
export const getInsomniaSecretKey = () => env.INSOMNIA_SECRET_KEY;
export const getInsomniaPublicKey = () => env.INSOMNIA_PUBLIC_KEY;
export const getInsomniaVaultSalt = () => env.INSOMNIA_VAULT_SALT;
export const getInsomniaVaultKey = () => env.INSOMNIA_VAULT_KEY;
export const getAppVersion = () => version;
export const getProductName = () => appConfig.productName;
export const getAppDefaultTheme = () => appConfig.theme;

View File

@@ -71,7 +71,12 @@ const encryptString = (raw: string) => {
const decryptString = (cipherText: string) => {
const buffer = Buffer.from(cipherText, 'hex');
if (safeStorage.isEncryptionAvailable()) {
return safeStorage.decryptString(buffer);
try {
return safeStorage.decryptString(buffer);
} catch (error) {
console.error(`Can not decrypt secret ${error.toString()}`);
return cipherText;
}
}
return cipherText;
};

View File

@@ -70,7 +70,6 @@ export function init(): BaseSettings {
useBulkParametersEditor: false,
validateAuthSSL: true,
validateSSL: true,
vaultSecretCacheDuration: 30,
saveVaultKeyLocally: true,
enableVaultInScripts: false,
};

View File

@@ -373,7 +373,7 @@ export const EnvironmentKVEditor = ({ data, onChange, vaultKey = '', isPrivate =
aria-label='Environment Key Value Pair'
selectionMode='none'
dragAndDropHooks={dragAndDropHooks}
dependencies={[kvPairError, data]}
dependencies={[kvPairError, data, symmetricKey]}
className="p-[--padding-sm] w-full overflow-y-auto h-full"
items={kvPairs}
>

View File

@@ -9,11 +9,13 @@ import {
RouterProvider,
} from 'react-router-dom';
import { migrateFromLocalStorage, type SessionData, setSessionData } from '../account/session';
import { migrateFromLocalStorage, type SessionData, setSessionData, setVaultSessionData } from '../account/session';
import {
ACTIVITY_DEBUG,
ACTIVITY_SPEC,
getInsomniaSession,
getInsomniaVaultKey,
getInsomniaVaultSalt,
getProductName,
getSkipOnboarding,
isDevelopment,
@@ -71,6 +73,8 @@ async function renderApp() {
// Check if there is a Session provided by an env variable and use this
const insomniaSession = getInsomniaSession();
const insomniaVaultKey = getInsomniaVaultKey();
const insomniaVaultSalt = getInsomniaVaultSalt();
if (insomniaSession) {
try {
const session = JSON.parse(insomniaSession) as SessionData;
@@ -84,6 +88,9 @@ async function renderApp() {
session.publicKey,
session.encPrivateKey
);
if (insomniaVaultSalt && insomniaVaultKey) {
await setVaultSessionData(insomniaVaultSalt, insomniaVaultKey);
}
} catch (e) {
console.log('[init] Failed to parse session data', e);
}

View File

@@ -1,4 +1,5 @@
import { getInsomniaVaultKey } from '../common/constants';
import { settings } from '../models';
export const base64encode = (input: string | JsonWebKey) => {
@@ -20,6 +21,11 @@ export const base64decode = (base64Str: string, toObject: boolean) => {
};
export const decryptVaultKeyFromSession = async (vaultKey: string, toJsonWebKey: boolean) => {
if (process.env.PLAYWRIGHT) {
const testVaultKey = getInsomniaVaultKey() || '';
// return vault key from environmet variable directly when running playwright tests
return toJsonWebKey ? base64decode(testVaultKey, true) : testVaultKey;
}
if (vaultKey) {
const decryptedVaultKey = await window.main.secretStorage.decryptString(vaultKey);
if (toJsonWebKey) {