Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion extension/chrome/elements/add_pubkey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ View.run(class AddPubkeyView extends View {
for (const missingPubkeyEmail of this.missingPubkeyEmails) {
Xss.sanitizeAppend('select.email', `<option value="${Xss.escape(missingPubkeyEmail)}">${Xss.escape(missingPubkeyEmail)}</option>`);
}
for (const contact of await ContactStore.search(undefined, { has_pgp: true })) {
for (const contact of await ContactStore.search(undefined, { hasPgp: true })) {
Xss.sanitizeAppend('select.copy_from_email', `<option value="${Xss.escape(contact.email)}">${Xss.escape(contact.email)}</option>`);
}
this.fetchKeyUi.handleOnPaste($('.pubkey'));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ export class ComposeRecipientsModule extends ViewModule<ComposeView> {
const recipientsHasPgp: RecipientElement[] = [];
for (const recipient of noPgpRecipients) {
const [contact] = await ContactStore.get(undefined, [recipient.email]);
if (contact && contact.has_pgp) {
if (contact && contact.hasPgp) {
$(recipient.element).removeClass('no_pgp').find('i').remove();
clearInterval(this.addedPubkeyDbLookupInterval);
recipientsHasPgp.push(recipient);
Expand Down Expand Up @@ -584,16 +584,16 @@ export class ComposeRecipientsModule extends ViewModule<ComposeView> {
this.view.errModule.debug(`renderSearchRes len: ${contacts.length}`);
// have pgp on top, no pgp bottom. Sort each groups by last use
const sortedContacts = contacts.sort((a: ContactPreview, b: ContactPreview) => {
if (a.has_pgp && !b.has_pgp) {
if (a.hasPgp && !b.hasPgp) {
return -1;
}
if (!a.has_pgp && b.has_pgp) {
if (!a.hasPgp && b.hasPgp) {
return 1;
}
if ((a.last_use || 0) > (b.last_use || 0)) {
if ((a.lastUse || 0) > (b.lastUse || 0)) {
return -1;
}
if ((a.last_use || 0) < (b.last_use || 0)) {
if ((a.lastUse || 0) < (b.lastUse || 0)) {
return 1;
}
return 0;
Expand All @@ -603,7 +603,7 @@ export class ComposeRecipientsModule extends ViewModule<ComposeView> {
let ulHtml = '';
for (const contact of renderableContacts) {
ulHtml += `<li class="select_contact" email="${Xss.escape(contact.email.replace(/<\/?b>/g, ''))}">`;
if (contact.has_pgp) {
if (contact.hasPgp) {
ulHtml += '<img class="lock-icon" src="/img/svgs/locked-icon-green.svg" />';
} else {
ulHtml += '<img class="lock-icon" src="/img/svgs/locked-icon-gray.svg" />';
Expand Down Expand Up @@ -835,7 +835,7 @@ export class ComposeRecipientsModule extends ViewModule<ComposeView> {
'you an updated public key.' + this.recipientKeyIdText(contact));
} else if (contact.pubkey) {
recipient.status = RecipientStatus.HAS_PGP;
$(el).addClass("has_pgp");
$(el).addClass('has_pgp');
Xss.sanitizePrepend(el, '<img class="lock-icon" src="/img/svgs/locked-icon.svg" />');
$(el).attr('title', 'Does use encryption' + this.recipientKeyIdText(contact));
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export class ComposeSendBtnModule extends ViewModule<ComposeView> {
return; // user has canceled the pass phrase dialog, or didn't respond to it in time
}
}
await ContactStore.update(undefined, Array.prototype.concat.apply([], Object.values(newMsgData.recipients)), { last_use: Date.now() });
await ContactStore.update(undefined, Array.prototype.concat.apply([], Object.values(newMsgData.recipients)), { lastUse: Date.now() });
const msgObj = await GeneralMailFormatter.processNewMsg(this.view, newMsgData, senderKi, signingPrv);
await this.finalizeSendableMsg(msgObj, senderKi);
await this.doSendMsg(msgObj);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export class ComposeStorageModule extends ViewModule<ComposeView> {
const emailsWithoutPubkeys = [];
for (const i of contacts.keys()) {
const contact = contacts[i];
if (contact && contact.has_pgp && contact.pubkey) {
if (contact && contact.hasPgp && contact.pubkey) {
armoredPubkeys.push({ pubkey: contact.pubkey, email: contact.email, isMine: false });
} else if (contact && this.ksLookupsByEmail[contact.email]) {
armoredPubkeys.push({ pubkey: this.ksLookupsByEmail[contact.email], email: contact.email, isMine: false });
Expand All @@ -88,7 +88,7 @@ export class ComposeStorageModule extends ViewModule<ComposeView> {

public lookupPubkeyFromDbOrKeyserverAndUpdateDbIfneeded = async (email: string, name: string | undefined): Promise<Contact | "fail"> => {
const [storedContact] = await ContactStore.get(undefined, [email]);
if (storedContact && storedContact.has_pgp && storedContact.pubkey) {
if (storedContact && storedContact.hasPgp && storedContact.pubkey) {
// Potentially check if pubkey was updated - async. By the time user finishes composing, newer version would have been updated in db.
// If sender didn't pull a particular pubkey for a long time and it has since expired, but there actually is a newer version on attester, this may unnecessarily show "bad pubkey",
// -> until next time user tries to pull it. This could be fixed by attempting to fix up the rendered recipient inside the async function below.
Expand Down Expand Up @@ -132,7 +132,7 @@ export class ComposeStorageModule extends ViewModule<ComposeView> {
if (!contact.pubkey || !contact.fingerprint) {
return;
}
const lastCheckOverWeekAgoOrNever = !contact.pubkey_last_check || new Date(contact.pubkey_last_check).getTime() < Date.now() - (1000 * 60 * 60 * 24 * 7);
const lastCheckOverWeekAgoOrNever = !contact.pubkeyLastCheck || new Date(contact.pubkeyLastCheck).getTime() < Date.now() - (1000 * 60 * 60 * 24 * 7);
const isExpired = contact.expiresOn && contact.expiresOn < Date.now();
if (lastCheckOverWeekAgoOrNever || isExpired) {
const { pubkey: fetchedPubkeyArmored } = await this.view.pubLookup.lookupFingerprint(contact.fingerprint);
Expand All @@ -142,7 +142,7 @@ export class ComposeStorageModule extends ViewModule<ComposeView> {
// the fetched pubkey has at least the same or newer signature
// the "same or newer" was due to a bug we encountered earlier where keys were badly recorded in db
// sometime in Oct 2020 we could turn the ">=" back to ">" above
await ContactStore.update(undefined, contact.email, { pubkey: fetchedPubkey, last_use: Date.now(), pubkey_last_check: Date.now() });
await ContactStore.update(undefined, contact.email, { pubkey: fetchedPubkey, lastUse: Date.now(), pubkeyLastCheck: Date.now() });
const [updatedPubkey] = await ContactStore.get(undefined, [contact.email]);
if (!updatedPubkey) {
throw new Error("Cannot retrieve Contact right after updating it");
Expand All @@ -152,7 +152,7 @@ export class ComposeStorageModule extends ViewModule<ComposeView> {
}
}
}
await ContactStore.update(undefined, contact.email, { pubkey: contact.pubkey, pubkey_last_check: Date.now() });
await ContactStore.update(undefined, contact.email, { pubkey: contact.pubkey, pubkeyLastCheck: Date.now() });
// we checked for newer key and it did not result in updating the key, don't check again for another week
} catch (e) {
ApiErr.reportIfSignificant(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class SignedMsgMailFormatter extends BaseMailFormatter {
newMsg.plaintext = newMsg.plaintext.split('\n').map(l => l.replace(/\s+$/g, '')).join('\n').trim();
const signedData = await MsgUtil.sign(signingPrv, newMsg.plaintext);
const allContacts = [...newMsg.recipients.to || [], ...newMsg.recipients.cc || [], ...newMsg.recipients.bcc || []];
ContactStore.update(undefined, allContacts, { last_use: Date.now() }).catch(Catch.reportErr);
ContactStore.update(undefined, allContacts, { lastUse: Date.now() }).catch(Catch.reportErr);
return await SendableMsg.createPgpInline(this.acctEmail, this.headers(newMsg), signedData, attachments);
}
// pgp/mime detached signature - it must be signed later, while being mime-encoded
Expand Down
2 changes: 1 addition & 1 deletion extension/chrome/elements/pgp_pubkey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ View.run(class PgpPubkeyView extends View {
} else {
const [contact] = await ContactStore.get(undefined, [String($('.input_email').val())]);
$('.action_add_contact')
.text(contact?.has_pgp ? 'update key' : `import ${this.isExpired ? 'expired ' : ''}key`)
.text(contact?.hasPgp ? 'update key' : `import ${this.isExpired ? 'expired ' : ''}key`)
.css('background-color', this.isExpired ? '#989898' : '');
}
}
Expand Down
6 changes: 3 additions & 3 deletions extension/chrome/settings/modules/contacts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ View.run(class ContactsView extends View {
// --- PRIVATE

private loadAndRenderContactList = async () => {
this.contacts = await ContactStore.search(undefined, { has_pgp: true, limit: 500, substring: String($('.input-search-contacts').val()) });
this.contacts = await ContactStore.search(undefined, { hasPgp: true, limit: 500, substring: String($('.input-search-contacts').val()) });
let lineActionsHtml = '&nbsp;&nbsp;<a href="#" class="action_export_all">export all</a>&nbsp;&nbsp;' +
'&nbsp;&nbsp;<a href="#" class="action_view_bulk_import" data-test="action-show-import-public-keys-form">import public keys</a>&nbsp;&nbsp;';
if (this.orgRules.getCustomSksPubkeyServer()) {
Expand Down Expand Up @@ -109,7 +109,7 @@ View.run(class ContactsView extends View {
}

private actionExportAllKeysHandler = async () => {
const allArmoredPublicKeys = (await ContactStore.searchPubkeys(undefined, { has_pgp: true })).map(a => a!.trim()).join('\n');
const allArmoredPublicKeys = (await ContactStore.searchPubkeys(undefined, { hasPgp: true })).map(a => a!.trim()).join('\n');
const exportFile = new Attachment({ name: 'public-keys-export.asc', type: 'application/pgp-keys', data: Buf.fromUtfStr(allArmoredPublicKeys) });
Browser.saveToDownloads(exportFile);
}
Expand Down Expand Up @@ -152,7 +152,7 @@ View.run(class ContactsView extends View {
try {
// parse will throw if the key is not recognized
const pubkey = await KeyUtil.parse(armoredPubkey);
await ContactStore.update(undefined, email, { pubkey, last_use: Date.now() });
await ContactStore.update(undefined, email, { pubkey, lastUse: Date.now() });
await this.loadAndRenderContactList();
} catch (e) {
await Ui.modal.warning('Cannot recognize a valid public key, please try again. Let us know at human@flowcrypt.com if you need help.');
Expand Down
4 changes: 2 additions & 2 deletions extension/js/background_page/migrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ const moveContactsBatchToEmailsAndPubkeys = async (db: IDBDatabase, count?: numb
update: {
name: entry.name,
pubkey,
last_use: entry.last_use,
pubkey_last_check: pubkey ? entry.pubkey_last_check : undefined
lastUse: entry.last_use,
pubkeyLastCheck: pubkey ? entry.pubkey_last_check : undefined
} as ContactUpdate
};
}));
Expand Down
6 changes: 3 additions & 3 deletions extension/js/common/core/crypto/key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ export type Contact = {
email: string;
name: string | null;
pubkey: Key | undefined;
has_pgp: 0 | 1;
hasPgp: 0 | 1;
fingerprint: string | null;
last_use: number | null;
pubkey_last_check: number | null;
lastUse: number | null;
pubkeyLastCheck: number | null;
expiresOn: number | null;
};

Expand Down
60 changes: 30 additions & 30 deletions extension/js/common/platform/store/contact-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,18 @@ export type ContactV4 = {
export type ContactPreview = {
email: string;
name: string | null;
has_pgp: 0 | 1;
last_use: number | null;
hasPgp: 0 | 1;
lastUse: number | null;
};

export type ContactUpdate = {
name?: string | null;
last_use?: number | null;
lastUse?: number | null;
pubkey?: Key;
pubkey_last_check?: number | null; // when non-null, `pubkey` must be supplied
pubkeyLastCheck?: number | null; // when non-null, `pubkey` must be supplied
};

type DbContactFilter = { has_pgp?: boolean, substring?: string, limit?: number };
type DbContactFilter = { hasPgp?: boolean, substring?: string, limit?: number };

/**
* Store of contacts and their public keys
Expand All @@ -69,7 +69,7 @@ export class ContactStore extends AbstractStore {

// static [f: string]: Function; // https://github.com/Microsoft/TypeScript/issues/6480

private static dbQueryKeys = ['limit', 'substring', 'has_pgp'];
private static dbQueryKeys = ['limit', 'substring', 'hasPgp'];

public static dbOpen = async (): Promise<IDBDatabase> => {
return await new Promise((resolve, reject) => {
Expand Down Expand Up @@ -104,7 +104,7 @@ export class ContactStore extends AbstractStore {
if (!validEmail) {
throw new Error(`Cannot handle the contact because email is not valid: ${email}`);
}
return { email: validEmail, name: name || null, has_pgp: 0, last_use: null };
return { email: validEmail, name: name || null, hasPgp: 0, lastUse: null };
}

public static obj = async ({ email, name, pubkey, lastUse, lastCheck }: DbContactObjArg): Promise<Contact> => {
Expand All @@ -120,10 +120,10 @@ export class ContactStore extends AbstractStore {
email: validEmail,
name: name || null,
pubkey: undefined,
has_pgp: 0, // number because we use it for sorting
hasPgp: 0, // number because we use it for sorting
fingerprint: null,
last_use: lastUse || null,
pubkey_last_check: null,
lastUse: lastUse || null,
pubkeyLastCheck: null,
expiresOn: null
};
}
Expand All @@ -132,9 +132,9 @@ export class ContactStore extends AbstractStore {
email: validEmail,
name: name || null,
pubkey: pk,
has_pgp: 1, // number because we use it for sorting
last_use: lastUse || null,
pubkey_last_check: lastCheck || null,
hasPgp: 1, // number because we use it for sorting
lastUse: lastUse || null,
pubkeyLastCheck: lastCheck || null,
...ContactStore.getKeyAttributes(pk)
};
}
Expand Down Expand Up @@ -245,7 +245,7 @@ export class ContactStore extends AbstractStore {
}

public static updateTx = (tx: IDBTransaction, email: string, update: ContactUpdate) => {
if (update.pubkey && !update.pubkey_last_check) {
if (update.pubkey && !update.pubkeyLastCheck) {
const req = tx.objectStore('pubkeys').get(update.pubkey.id);
ContactStore.setReqPipe(req, (pubkey: Pubkey) => ContactStore.updateTxPhase2(tx, email, update, pubkey));
} else {
Expand Down Expand Up @@ -277,13 +277,13 @@ export class ContactStore extends AbstractStore {
// todo: will we benefit anything when not saving pubkey if it isn't modified?
pubkeyEntity = {
fingerprint: update.pubkey.id,
lastCheck: DateUtility.asNumber(update.pubkey_last_check ?? existingPubkey?.lastCheck),
lastCheck: DateUtility.asNumber(update.pubkeyLastCheck ?? existingPubkey?.lastCheck),
expiresOn: keyAttrs.expiresOn,
longids: update.pubkey.allIds.map(id => OpenPGPKey.fingerprintToLongid(id)),
armoredKey: KeyUtil.armor(update.pubkey)
} as Pubkey;
} else if (update.pubkey_last_check) {
Catch.report(`Wrongly updating pubkey_last_check without specifying pubkey for ${email} - ignoring`);
} else if (update.pubkeyLastCheck) {
Catch.report(`Wrongly updating pubkeyLastCheck without specifying pubkey for ${email} - ignoring`);
}
const req = tx.objectStore('emails').get(email);
ContactStore.setReqPipe(req, (emailEntity: Email) => {
Expand All @@ -298,8 +298,8 @@ export class ContactStore extends AbstractStore {
if (Object.keys(update).includes('name')) {
emailEntity.name = update.name ?? null;
}
if (Object.keys(update).includes('last_use')) {
emailEntity.lastUse = DateUtility.asNumber(update.last_use);
if (Object.keys(update).includes('lastUse')) {
emailEntity.lastUse = DateUtility.asNumber(update.lastUse);
}
ContactStore.updateSearchable(emailEntity);
tx.objectStore('emails').put(emailEntity);
Expand Down Expand Up @@ -341,23 +341,23 @@ export class ContactStore extends AbstractStore {
}
}
query.substring = ContactStore.normalizeString(query.substring || '');
if (typeof query.has_pgp === 'undefined' && query.substring) {
const resultsWithPgp = await ContactStore.rawSearch(db, { substring: query.substring, limit: query.limit, has_pgp: true });
if (typeof query.hasPgp === 'undefined' && query.substring) {
const resultsWithPgp = await ContactStore.rawSearch(db, { substring: query.substring, limit: query.limit, hasPgp: true });
if (query.limit && resultsWithPgp.length === query.limit) {
return resultsWithPgp;
} else {
const limit = query.limit ? query.limit - resultsWithPgp.length : undefined;
const resultsWithoutPgp = await ContactStore.rawSearch(db, { substring: query.substring, limit, has_pgp: false });
const resultsWithoutPgp = await ContactStore.rawSearch(db, { substring: query.substring, limit, hasPgp: false });
return resultsWithPgp.concat(resultsWithoutPgp);
}
}
const emails = db.transaction(['emails'], 'readonly').objectStore('emails');
const raw: Email[] = await new Promise((resolve, reject) => {
let search: IDBRequest;
if (typeof query.has_pgp === 'undefined') { // any query.has_pgp value
search = emails.openCursor(); // no substring, already covered in `typeof query.has_pgp === 'undefined' && query.substring` above
} else { // specific query.has_pgp value
const indexRange = ContactStore.dbIndexRange(query.has_pgp, query.substring ?? '');
if (typeof query.hasPgp === 'undefined') { // any query.hasPgp value
search = emails.openCursor(); // no substring, already covered in `typeof query.hasPgp === 'undefined' && query.substring` above
} else { // specific query.hasPgp value
const indexRange = ContactStore.dbIndexRange(query.hasPgp, query.substring ?? '');
// To find all the index keys starting with a certain sequence of characters (e.g. 'abc')
// we use a range with inclusive lower boundary and exclusive upper boundary
// ['t:abc', 't:abd) or ['f:abc', 'f:abd'), so that any key having an arbitrary tail of
Expand Down Expand Up @@ -490,14 +490,14 @@ export class ContactStore extends AbstractStore {
email: email.email,
name: email.name,
pubkey: key,
has_pgp: key ? 1 : 0,
last_use: email.lastUse,
pubkey_last_check: lastCheck,
hasPgp: key ? 1 : 0,
lastUse: email.lastUse,
pubkeyLastCheck: lastCheck,
...ContactStore.getKeyAttributes(key)
};
}

private static toContactPreview = (result: Email): ContactPreview => {
return { email: result.email, name: result.name, has_pgp: result.fingerprints.length > 0 ? 1 : 0, last_use: result.lastUse };
return { email: result.email, name: result.name, hasPgp: result.fingerprints.length > 0 ? 1 : 0, lastUse: result.lastUse };
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,7 @@ export class GmailElementReplacer implements WebmailElementReplacer {
}
} catch (e) {
ApiErr.reportIfSignificant(e);
// this is a low-importance request, so evaluate has_pgp as false on errors
// this is a low-importance request, so evaluate hasPgp as false on errors
// this way faulty requests wouldn't unnecessarily repeat and overwhelm Attester
this.recipientHasPgpCache[email] = false;
everyoneUsesEncryption = false;
Expand Down
Loading