Skip to content

Commit

Permalink
Merge branch 'master' into dependabot/npm_and_yarn/npm-deps-b6e8bdffb5
Browse files Browse the repository at this point in the history
# Conflicts:
#	extension/js/common/ui/key-import-ui.ts
  • Loading branch information
sosnovsky committed Sep 16, 2024
2 parents 26651a4 + d64cc98 commit f53253a
Show file tree
Hide file tree
Showing 15 changed files with 558 additions and 304 deletions.
71 changes: 71 additions & 0 deletions extension/chrome/elements/shared/create_key.template.htm
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<div id="step_2a_manual_create" class="manual">
<div class="line left">
Choose pass phrase to protect your encrypted emails. <a href="#" data-swal-page="/chrome/texts/passphrase_help.htm">choosing secure pass phrases</a>
</div>
<div class="line left">
<input
class="input_password"
type="text"
placeholder="Pass phrase"
style="margin-bottom: 0"
id="step_2a_manual_create_input_password"
data-test="input-step2bmanualcreate-passphrase-1"
maxlength="256"
/>
</div>
<div class="line left">
<input
class="input_password2"
type="text"
placeholder="Repeat pass phrase"
id="step_2a_manual_create_input_password2"
data-test="input-step2bmanualcreate-passphrase-2"
maxlength="256"
/>
</div>

<div class="line left">
<label class="input_passphrase_save_label hidden" data-test="input-step2bmanualcreate-save-passphrase-label">
<input type="checkbox" class="input_passphrase_save" data-test="input-step2bmanualcreate-save-passphrase" value="" name="check" />
Remember the pass phrase after closing the browser
</label>
</div>
<div class="line left remove_if_backup_not_allowed">
<label data-test="input-step2bmanualcreate-backup-inbox">
<input type="checkbox" class="input_backup_inbox" value="" name="check" checked="" />
Back up encrypted private key in inbox (recommended)
</label>
</div>

<div class="line left remove_if_pubkey_submitting_not_user_configurable">
<label data-test="input-step2bmanualcreate-submit-pubkey">
<input type="checkbox" class="input_submit_key" value="" name="check" checked="" />
Submit corresponding pubkey to FlowCrypt Attester (recommended)
</label>
</div>
<div class="line left display_none remove_if_pubkey_submitting_not_user_configurable also_submit_alias_key_view">
<label>
<input type="checkbox" class="input_submit_all" disabled="disabled" />
<span>
Also submit the same pubkey for:
<br /><span class="addresses"></span>
</span>
</label>
</div>

<div class="line left">
<label>
Encryption key type:
<select class="key_type" data-test="input-step2bmanualcreate-key-type">
<option value="curve25519">ECC Curve25519</option>
<option value="rsa2048">RSA 2048bit</option>
<option value="rsa3072">RSA 3072bit</option>
<option value="rsa4096">RSA 4096bit</option>
</select>
</label>
</div>

<div class="line left">
<button class="button longer gray action_proceed_private" data-test="input-step2bmanualcreate-create-and-save">CREATE AND SAVE</button>
</div>
</div>
6 changes: 4 additions & 2 deletions extension/chrome/settings/index.htm
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,13 @@ <h1 class="text-center">FlowCrypt Settings</h1>
<div class="row my-keys-row" data-test="container-settings-keys-list">
<div class="settings-border">
<div class="row abs-row">
<div class="col-12" style="padding-left: 0">
<div class="col-12 flex" style="padding-left: 0">
<img src="/img/svgs/key-icon.svg" class="key-icon" alt="key icon" />
<span class="my-keys-copy">My Keys</span>
<span class="text-right keys-link-top-right-container">
<a href="#" class="show_settings_page add_key" data-test="action-open-add-key-page" page="/chrome/settings/modules/add_key.htm">Add Key</a>
<a href="#" class="show_settings_page my_key_link add_key" data-test="action-open-add-key-page" page="/chrome/settings/modules/add_key.htm"
>Add Key</a
>
</span>
</div>
</div>
Expand Down
19 changes: 17 additions & 2 deletions extension/chrome/settings/modules/add_key.htm
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,12 @@
<div class="line">
<h1>Add Private Key <span id="spinner_container"></span></h1>
</div>
<div class="line">
<div class="line" id="add_key_option_container">
<ul style="list-style: none; margin-left: 0; padding-left: 0" class="source_selector display_none">
<li>
<input type="radio" name="source" id="source_generate" data-test="source-generate" value="generate" />
<label for="source_generate"> Generate new key </label>
</li>
<li>
<input type="radio" name="source" id="source_backup" value="backup" />
<label for="source_backup"> Load from backup </label>
Expand All @@ -37,6 +41,10 @@ <h1>Add Private Key <span id="spinner_container"></span></h1>
</li>
</ul>
</div>
<div class="source_generate_container display_none">
<div id="generate-key-container"></div>
<div id="backup-template-container"></div>
</div>
<div class="source_file_container display_none">
<a href="#" id="fineuploader_button" class="display_none">file</a>
<div class="line display_none" id="fineuploader"></div>
Expand All @@ -55,7 +63,7 @@ <h1>Add Private Key <span id="spinner_container"></span></h1>
</div>
<div class="line">
<label class="input_passphrase_save_label hidden" data-test="input-save-passphrase-label">
<input type="checkbox" value="" name="check" class="input_passphrase_save" data-test="input-save-passphrase" />
<input type="checkbox" value="" name="check" class="import_input_passphrase_save" data-test="input-save-passphrase" />
Remember the pass phrase after closing the browser
</label>
</div>
Expand All @@ -76,6 +84,13 @@ <h1>Add Private Key <span id="spinner_container"></span></h1>
<script src="/lib/openpgp.js"></script>
<script src="/lib/forge.js"></script>
<script src="/lib/zxcvbn.js"></script>
<script src="/lib/emailjs/punycode.js"></script>
<script src="/lib/emailjs/emailjs-stringencoding.js"></script>
<script src="/lib/emailjs/emailjs-mime-codec.js"></script>
<script src="/lib/emailjs/emailjs-mime-types.js"></script>
<script src="/lib/emailjs/emailjs-addressparser.js"></script>
<script src="/lib/emailjs/emailjs-mime-builder.js"></script>
<script src="/lib/emailjs/emailjs-mime-parser.js"></script>
<script src="add_key.js" type="module"></script>
</body>
</html>
187 changes: 96 additions & 91 deletions extension/chrome/settings/modules/add_key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,109 +17,114 @@ import { ClientConfiguration } from '../../../js/common/client-configuration.js'
import { AcctStore } from '../../../js/common/platform/store/acct-store.js';
import { saveKeysAndPassPhrase, setPassphraseForPrvs } from '../../../js/common/helpers.js';
import { KeyErrors } from '../../elements/shared/key_errors.js';
import { AddKeyGenerateModule } from './add_key_generate_module.js';

View.run(
class AddKeyView extends View {
protected fesUrl?: string;
private readonly acctEmail: string;
private readonly parentTabId: string;
private readonly keyImportUi = new KeyImportUi({ rejectKnown: true });
private readonly gmail: Gmail;
private keyErrors: KeyErrors | undefined;
private clientConfiguration!: ClientConfiguration;
export class AddKeyView extends View {
public readonly acctEmail: string;
public readonly parentTabId: string;
public clientConfiguration!: ClientConfiguration;
public fesUrl?: string;
private readonly keyImportUi = new KeyImportUi({ rejectKnown: true });
private readonly gmail: Gmail;
private keyErrors: KeyErrors | undefined;
private readonly addKeyGenerateModule: AddKeyGenerateModule;

public constructor() {
super();
const uncheckedUrlParams = Url.parse(['acctEmail', 'parentTabId']);
this.acctEmail = Assert.urlParamRequire.string(uncheckedUrlParams, 'acctEmail');
this.parentTabId = Assert.urlParamRequire.string(uncheckedUrlParams, 'parentTabId');
this.gmail = new Gmail(this.acctEmail);
}
public constructor() {
super();
const uncheckedUrlParams = Url.parse(['acctEmail', 'parentTabId']);
this.acctEmail = Assert.urlParamRequire.string(uncheckedUrlParams, 'acctEmail');
this.parentTabId = Assert.urlParamRequire.string(uncheckedUrlParams, 'parentTabId');
this.gmail = new Gmail(this.acctEmail);
this.addKeyGenerateModule = new AddKeyGenerateModule(this);
}

public render = async () => {
const storage = await AcctStore.get(this.acctEmail, ['fesUrl']);
this.fesUrl = storage.fesUrl;
this.clientConfiguration = await ClientConfiguration.newInstance(this.acctEmail);
if (!this.clientConfiguration.forbidStoringPassPhrase()) {
$('.input_passphrase_save_label').removeClass('hidden');
$('.input_passphrase_save').prop('checked', true);
}
if (this.clientConfiguration.usesKeyManager()) {
Xss.sanitizeRender(
'body',
`
public render = async () => {
const storage = await AcctStore.get(this.acctEmail, ['fesUrl']);
this.fesUrl = storage.fesUrl;
this.clientConfiguration = await ClientConfiguration.newInstance(this.acctEmail);
await this.addKeyGenerateModule.initGenerateKeyView();
if (!this.clientConfiguration.forbidStoringPassPhrase()) {
$('.input_passphrase_save_label').removeClass('hidden');
$('.import_input_passphrase_save').prop('checked', true);
}
if (this.clientConfiguration.usesKeyManager()) {
Xss.sanitizeRender(
'body',
`
<br><br>
<div data-test="container-err-text">Please contact your IT staff if you wish to update your keys.</div>
<br><br>
`
);
} else {
$('#content').show();
if (!this.clientConfiguration.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..');
await this.loadAndRenderKeyBackupsOrRenderError();
$('.source_selector').css('display', 'block');
$('#spinner_container').text('');
);
} else {
$('#content').show();
if (!this.clientConfiguration.forbidStoringPassPhrase()) {
$('.import_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..');
await this.loadAndRenderKeyBackupsOrRenderError();
$('.source_selector').css('display', 'block');
$('#spinner_container').text('');
}
};

public setHandlers = () => {
$('.action_add_private_key').on('click', this.setHandlerPrevent('double', this.addPrivateKeyHandler));
$('#input_passphrase').keydown(this.setEnterHandlerThatClicks('.action_add_private_key'));
};
public setHandlers = () => {
$('.action_add_private_key').on('click', this.setHandlerPrevent('double', this.addPrivateKeyHandler));
$('#input_passphrase').keydown(this.setEnterHandlerThatClicks('.action_add_private_key'));
this.addKeyGenerateModule.setHandlers();
};

private loadAndRenderKeyBackupsOrRenderError = async () => {
try {
const backups = await this.gmail.fetchKeyBackups();
if (!backups.longids.backups.length) {
$('label[for=source_backup]').text('Load from backup (no backups found)').css('color', '#AAA');
$('#source_backup').prop('disabled', true);
} else if (backups.longids.backupsNotImported.length) {
$('label[for=source_backup]').text(`Load from backup (${backups.longids.backupsNotImported.length} new to import)`);
} else {
$('label[for=source_backup]').text(`Load from backup (${backups.longids.backups.length} already loaded)`).css('color', '#AAA');
$('#source_backup').prop('disabled', true);
}
} catch (e) {
if (ApiErr.isAuthErr(e)) {
BrowserMsg.send.notificationShowAuthPopupNeeded(this.parentTabId, { acctEmail: this.acctEmail });
}
$('label[for=source_backup]').text('Load from backup (error checking backups)').css('color', '#AAA');
private loadAndRenderKeyBackupsOrRenderError = async () => {
try {
const backups = await this.gmail.fetchKeyBackups();
if (!backups.longids.backups.length) {
$('label[for=source_backup]').text('Load from backup (no backups found)').css('color', '#AAA');
$('#source_backup').prop('disabled', true);
} else if (backups.longids.backupsNotImported.length) {
$('label[for=source_backup]').text(`Load from backup (${backups.longids.backupsNotImported.length} new to import)`);
} else {
$('label[for=source_backup]').text(`Load from backup (${backups.longids.backups.length} already loaded)`).css('color', '#AAA');
$('#source_backup').prop('disabled', true);
}
} catch (e) {
if (ApiErr.isAuthErr(e)) {
BrowserMsg.send.notificationShowAuthPopupNeeded(this.parentTabId, { acctEmail: this.acctEmail });
}
};
$('label[for=source_backup]').text('Load from backup (error checking backups)').css('color', '#AAA');
$('#source_backup').prop('disabled', true);
}
};

private saveKeyAndContinue = async (key: Key) => {
await saveKeysAndPassPhrase(this.acctEmail, [key]); // resulting new_key checked above
/* eslint-disable @typescript-eslint/naming-convention */
await setPassphraseForPrvs(this.clientConfiguration, this.acctEmail, [key], {
passphrase: String($('.input_passphrase').val()),
passphrase_save: !!$('.input_passphrase_save').prop('checked'),
passphrase_ensure_single_copy: false, // we require KeyImportUi to rejectKnown keys
});
/* eslint-enable @typescript-eslint/naming-convention */
BrowserMsg.send.reload(this.parentTabId, { advanced: true });
};
private saveKeyAndContinue = async (key: Key) => {
await saveKeysAndPassPhrase(this.acctEmail, [key]); // resulting new_key checked above
/* eslint-disable @typescript-eslint/naming-convention */
await setPassphraseForPrvs(this.clientConfiguration, this.acctEmail, [key], {
passphrase: String($('.input_passphrase').val()),
passphrase_save: !!$('.import_input_passphrase_save').prop('checked'),
passphrase_ensure_single_copy: false, // we require KeyImportUi to rejectKnown keys
});
/* eslint-enable @typescript-eslint/naming-convention */
BrowserMsg.send.reload(this.parentTabId, { advanced: true });
};

private addPrivateKeyHandler = async (submitBtn: HTMLElement) => {
if (submitBtn.className.includes('gray')) {
await Ui.modal.warning('Please double check the pass phrase input field for any issues.');
return;
}
try {
const checked = await this.keyImportUi.checkPrv(this.acctEmail, String($('.input_private_key').val()), String($('.input_passphrase').val()));
if (checked) {
await this.saveKeyAndContinue(checked.encrypted);
}
} catch (e) {
this.keyErrors = new KeyErrors(this.fesUrl || '', this.acctEmail, this.parentTabId, this.clientConfiguration);
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
await this.keyErrors.handlePrivateKeyError(e, e.encrypted, undefined);
private addPrivateKeyHandler = async (submitBtn: HTMLElement) => {
if (submitBtn.className.includes('gray')) {
await Ui.modal.warning('Please double check the pass phrase input field for any issues.');
return;
}
try {
const checked = await this.keyImportUi.checkPrv(this.acctEmail, String($('.input_private_key').val()), String($('.input_passphrase').val()));
if (checked) {
await this.saveKeyAndContinue(checked.encrypted);
}
};
}
);
} catch (e) {
this.keyErrors = new KeyErrors(this.fesUrl || '', this.acctEmail, this.parentTabId, this.clientConfiguration);
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
await this.keyErrors.handlePrivateKeyError(e, e.encrypted, undefined);
}
};
}

View.run(AddKeyView);
Loading

0 comments on commit f53253a

Please sign in to comment.