diff --git a/extension/chrome/settings/modules/add_key.htm b/extension/chrome/settings/modules/add_key.htm index ed83aad4edc..770a105099c 100644 --- a/extension/chrome/settings/modules/add_key.htm +++ b/extension/chrome/settings/modules/add_key.htm @@ -50,7 +50,7 @@

Add Private Key

diff --git a/extension/chrome/settings/modules/add_key.ts b/extension/chrome/settings/modules/add_key.ts index 5d4aa834b71..b2f45cc94e8 100644 --- a/extension/chrome/settings/modules/add_key.ts +++ b/extension/chrome/settings/modules/add_key.ts @@ -16,6 +16,8 @@ import { initPassphraseToggle } from '../../../js/common/ui/passphrase-ui.js'; import { PassphraseStore } from '../../../js/common/platform/store/passphrase-store.js'; import { KeyStore } from '../../../js/common/platform/store/key-store.js'; import { UnexpectedKeyTypeError } from '../../../js/common/core/crypto/key.js'; +import { OrgRules } from '../../../js/common/org-rules.js'; +import { StorageType } from '../../../js/common/platform/store/abstract-store.js'; View.run(class AddKeyView extends View { @@ -23,6 +25,7 @@ View.run(class AddKeyView extends View { private readonly parentTabId: string; private readonly keyImportUi = new KeyImportUi({ rejectKnown: true }); private readonly gmail: Gmail; + private orgRules!: OrgRules; constructor() { super(); @@ -33,6 +36,10 @@ View.run(class AddKeyView extends View { } public render = async () => { + this.orgRules = await OrgRules.newInstance(this.acctEmail); + if (!this.orgRules.forbidStoringPassPhrase()) { + $('.input_passphrase_save').prop('checked', true).prop('disabled', false); + } await initPassphraseToggle(['input_passphrase']); this.keyImportUi.initPrvImportSrcForm(this.acctEmail, this.parentTabId); Xss.sanitizeRender('#spinner_container', Ui.spinner('green') + ' loading..'); @@ -76,8 +83,8 @@ View.run(class AddKeyView extends View { const checked = await this.keyImportUi.checkPrv(this.acctEmail, String($('.input_private_key').val()), String($('.input_passphrase').val())); if (checked) { await KeyStore.add(this.acctEmail, checked.encrypted); // resulting new_key checked above - await PassphraseStore.set($('.input_passphrase_save').prop('checked') ? 'local' : 'session', this.acctEmail, - checked.fingerprint, checked.passphrase); + const storageType: StorageType = ($('.input_passphrase_save').prop('checked') && !this.orgRules.forbidStoringPassPhrase()) ? 'local' : 'session'; + await PassphraseStore.set(storageType, this.acctEmail, checked.fingerprint, checked.passphrase); BrowserMsg.send.reload(this.parentTabId, { advanced: true }); } } catch (e) { diff --git a/test/source/tests/flaky.ts b/test/source/tests/flaky.ts index 2484dbee4e9..55dc0ec413f 100644 --- a/test/source/tests/flaky.ts +++ b/test/source/tests/flaky.ts @@ -76,7 +76,8 @@ export const defineFlakyTests = (testVariant: TestVariant, testWithBrowser: Test ava.default('standalone - different send from, new signed message, verification in mock', testWithBrowser('compatibility', async (t, browser) => { const key = Config.key('flowcryptcompatibility.from.address'); - await SettingsPageRecipe.addKeyTest(t, browser, 'flowcrypt.compatibility@gmail.com', key.armored!, key.passphrase!); + await SettingsPageRecipe.addKeyTest(t, browser, 'flowcrypt.compatibility@gmail.com', key.armored!, key.passphrase!, + { isSavePassphraseChecked: true, isSavePassphraseDisabled: false }); const composePage = await ComposePageRecipe.openStandalone(t, browser, 'compatibility'); await composePage.selectOption('@input-from', 'flowcryptcompatibility@gmail.com'); await ComposePageRecipe.fillMsg(composePage, { to: 'human@flowcrypt.com' }, 'New Signed Message (Mock Test)', { encrypt: false }); diff --git a/test/source/tests/page-recipe/settings-page-recipe.ts b/test/source/tests/page-recipe/settings-page-recipe.ts index 09ca797e605..bbac65d3226 100644 --- a/test/source/tests/page-recipe/settings-page-recipe.ts +++ b/test/source/tests/page-recipe/settings-page-recipe.ts @@ -11,6 +11,11 @@ import { TestUrls } from '../../browser/test-urls'; import { Xss } from '../../platform/xss'; import { KeyUtil } from '../../core/crypto/key'; +export type SavePassphraseChecks = { + isSavePassphraseDisabled?: boolean | undefined, + isSavePassphraseChecked?: boolean | undefined +}; + export class SettingsPageRecipe extends PageRecipe { public static ready = async (settingsPage: ControllablePage) => { @@ -105,12 +110,18 @@ export class SettingsPageRecipe extends PageRecipe { await settingsPage.waitTillGone('@dialog'); } - public static addKeyTest = async (t: AvaContext, browser: BrowserHandle, acctEmail: string, armoredPrvKey: string, passphrase: string) => { + public static addKeyTest = async (t: AvaContext, browser: BrowserHandle, acctEmail: string, armoredPrvKey: string, passphrase: string, checks: SavePassphraseChecks = {}) => { const addPrvPage = await browser.newPage(t, `/chrome/settings/modules/add_key.htm?acctEmail=${Xss.escape(acctEmail)}&parent_tab_id=0`); await addPrvPage.waitAndClick('#source_paste'); await addPrvPage.waitAndType('.input_private_key', armoredPrvKey); await addPrvPage.waitAndClick('#toggle_input_passphrase'); await addPrvPage.waitAndType('#input_passphrase', passphrase); + if (checks.isSavePassphraseDisabled !== undefined) { + expect(await PageRecipe.isElementDisabled(await addPrvPage.waitAny('@input-save-passphrase'))).to.equal(checks.isSavePassphraseDisabled); + } + if (checks.isSavePassphraseChecked !== undefined) { + expect(await PageRecipe.isElementChecked(await addPrvPage.waitAny('@input-save-passphrase'))).to.equal(checks.isSavePassphraseChecked); + } await addPrvPage.waitAndClick('.action_add_private_key', { delay: 1 }); await addPrvPage.waitTillGone('.swal2-container'); // dialog closed await Util.sleep(1); diff --git a/test/source/tests/page-recipe/setup-page-recipe.ts b/test/source/tests/page-recipe/setup-page-recipe.ts index c45222b328e..2ee47bc3872 100644 --- a/test/source/tests/page-recipe/setup-page-recipe.ts +++ b/test/source/tests/page-recipe/setup-page-recipe.ts @@ -4,7 +4,7 @@ import { Config, Util } from '../../util'; import { ControllablePage } from '../../browser'; import { PageRecipe } from './abstract-page-recipe'; -import { SettingsPageRecipe } from './settings-page-recipe'; +import { SavePassphraseChecks, SettingsPageRecipe } from './settings-page-recipe'; import { expect } from 'chai'; type ManualEnterOpts = { @@ -22,11 +22,6 @@ type ManualEnterOpts = { key?: { title: string, passphrase: string, armored: string | null, longid: string | null, filePath?: string } }; -type ManualEnterChecks = { - isSavePassphraseDisabled?: boolean | undefined, - isSavePassphraseChecked?: boolean | undefined -}; - type CreateKeyOpts = { key?: { passphrase: string }, usedPgpBefore?: boolean, @@ -34,11 +29,6 @@ type CreateKeyOpts = { enforcedAlgo?: string | boolean, }; -type CreateKeyChecks = { - isSavePassphraseDisabled?: boolean | undefined, - isSavePassphraseChecked?: boolean | undefined -}; - export class SetupPageRecipe extends PageRecipe { public static createKey = async ( @@ -46,7 +36,7 @@ export class SetupPageRecipe extends PageRecipe { keyTitle: string, backup: 'none' | 'email' | 'file' | 'disabled', { usedPgpBefore = false, submitPubkey = false, enforcedAlgo = false, key }: CreateKeyOpts = {}, - checks: CreateKeyChecks = {} + checks: SavePassphraseChecks = {} ) => { await SetupPageRecipe.createBegin(settingsPage, keyTitle, { key, usedPgpBefore }); if (enforcedAlgo) { @@ -108,7 +98,7 @@ export class SetupPageRecipe extends PageRecipe { noPubSubmitRule = false, key, }: ManualEnterOpts = {}, - checks: ManualEnterChecks = {} + checks: SavePassphraseChecks = {} ) { if (!noPrvCreateOrgRule) { if (usedPgpBefore) { diff --git a/test/source/tests/settings.ts b/test/source/tests/settings.ts index 4df274b1000..7cc65c1f66a 100644 --- a/test/source/tests/settings.ts +++ b/test/source/tests/settings.ts @@ -424,7 +424,8 @@ export let defineSettingsTests = (testVariant: TestVariant, testWithBrowser: Tes })); ava.default('settings - add unprotected key', testWithBrowser('ci.tests.gmail', async (t, browser) => { - await SettingsPageRecipe.addKeyTest(t, browser, 'ci.tests.gmail@flowcrypt.test', testConstants.unprotectedPrvKey, 'this is a new passphrase to protect previously unprotected key'); + await SettingsPageRecipe.addKeyTest(t, browser, 'ci.tests.gmail@flowcrypt.test', testConstants.unprotectedPrvKey, 'this is a new passphrase to protect previously unprotected key', + { isSavePassphraseChecked: true, isSavePassphraseDisabled: false }); })); ava.default('settings - error modal when page parameter invalid', testWithBrowser('ci.tests.gmail', async (t, browser) => { @@ -448,7 +449,8 @@ export let defineSettingsTests = (testVariant: TestVariant, testWithBrowser: Tes }, { isSavePassphraseChecked: false, isSavePassphraseDisabled: false }); await settingsPage1.close(); - await SettingsPageRecipe.addKeyTest(t, browser, acctEmail, testConstants.testKeyMultiple98acfa1eadab5b92, '1234'); + await SettingsPageRecipe.addKeyTest(t, browser, acctEmail, testConstants.testKeyMultiple98acfa1eadab5b92, '1234', + { isSavePassphraseChecked: true, isSavePassphraseDisabled: false }); const settingsPage = await browser.newPage(t, TestUrls.extensionSettings(acctEmail)); await SettingsPageRecipe.toggleScreen(settingsPage, 'additional'); @@ -579,6 +581,24 @@ export let defineSettingsTests = (testVariant: TestVariant, testWithBrowser: Tes await settingsPage.close(); })); + ava.default('settings - adding a key honors FORBID_STORING_PASS_PHRASE OrgRule', testWithBrowser(undefined, async (t, browser) => { + const { acctEmail, settingsPage } = await BrowserRecipe.setUpFcForbidPpStoringAcct(t, browser); + const { cryptup_userforbidstoringpassphraseorgruleflowcrypttest_passphrase_B8F687BCDE14435A: savedPassphrase1, + cryptup_userforbidstoringpassphraseorgruleflowcrypttest_keys: keys1 } + = await settingsPage.getFromLocalStorage(['cryptup_userforbidstoringpassphraseorgruleflowcrypttest_passphrase_B8F687BCDE14435A', + 'cryptup_userforbidstoringpassphraseorgruleflowcrypttest_keys']); + expect((keys1 as KeyInfo[])[0].longid).to.equal('B8F687BCDE14435A'); + expect(savedPassphrase1).to.be.an('undefined'); + await SettingsPageRecipe.addKeyTest(t, browser, acctEmail, testConstants.testKeyMultiple98acfa1eadab5b92, '1234', + { isSavePassphraseChecked: false, isSavePassphraseDisabled: true }); + const { cryptup_userforbidstoringpassphraseorgruleflowcrypttest_passphrase_98ACFA1EADAB5B92: savedPassphrase2, + cryptup_userforbidstoringpassphraseorgruleflowcrypttest_keys: keys2 } + = await settingsPage.getFromLocalStorage(['cryptup_userforbidstoringpassphraseorgruleflowcrypttest_passphrase_98ACFA1EADAB5B92', + 'cryptup_userforbidstoringpassphraseorgruleflowcrypttest_keys']); + expect((keys2 as KeyInfo[]).map(ki => ki.longid)).to.include.members(['B8F687BCDE14435A', '98ACFA1EADAB5B92']); + expect(savedPassphrase2).to.be.an('undefined'); + })); + ava.todo('settings - change passphrase - mismatch curent pp'); ava.todo('settings - change passphrase - mismatch new pp');