From 3be6e42849fd6350ca0eac64207142d3883996de Mon Sep 17 00:00:00 2001 From: Daniel James Smith Date: Wed, 20 Oct 2021 18:46:56 +0200 Subject: [PATCH 01/50] Update copyright year in .plist files for safari --- src/safari/desktop/Info.plist | 2 +- src/safari/safari/Info.plist | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/safari/desktop/Info.plist b/src/safari/desktop/Info.plist index 201669d037..30b6e9dc58 100644 --- a/src/safari/desktop/Info.plist +++ b/src/safari/desktop/Info.plist @@ -25,7 +25,7 @@ LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) NSHumanReadableCopyright - Copyright © 2020 Bitwarden Inc. All rights reserved. + Copyright © 2021 Bitwarden Inc. All rights reserved. NSMainStoryboardFile Main NSPrincipalClass diff --git a/src/safari/safari/Info.plist b/src/safari/safari/Info.plist index 8f23fb23e0..602262180b 100644 --- a/src/safari/safari/Info.plist +++ b/src/safari/safari/Info.plist @@ -30,7 +30,7 @@ $(PRODUCT_MODULE_NAME).SafariWebExtensionHandler NSHumanReadableCopyright - Copyright © 2020 Bitwarden Inc. All rights reserved. + Copyright © 2021 Bitwarden Inc. All rights reserved. NSHumanReadableDescription A secure and free password manager for all of your devices. SFSafariAppExtensionBundleIdentifiersToReplace From da80904d54cdc56a67d05fe0813733148c46a019 Mon Sep 17 00:00:00 2001 From: Daniel James Smith Date: Thu, 28 Oct 2021 23:21:42 +0200 Subject: [PATCH 02/50] Fill translations and responsively switch them for smaller screens --- src/notification/bar.html | 9 ++++---- src/notification/bar.js | 44 +++++++++++++++++++-------------------- src/notification/bar.scss | 32 ++++++++++++++++++++++++++-- 3 files changed, 55 insertions(+), 30 deletions(-) diff --git a/src/notification/bar.html b/src/notification/bar.html index bc43ed7cc8..43f56c19dd 100644 --- a/src/notification/bar.html +++ b/src/notification/bar.html @@ -1,4 +1,4 @@ - + @@ -24,15 +24,14 @@
- - - + +
- +
diff --git a/src/notification/bar.js b/src/notification/bar.js index fec7ed16f4..6798e789bf 100644 --- a/src/notification/bar.js +++ b/src/notification/bar.js @@ -25,33 +25,31 @@ document.addEventListener('DOMContentLoaded', () => { ? chrome.runtime.getURL('images/icon38_locked.png') : chrome.runtime.getURL('images/icon38.png'); - document.getElementById('close').src = chrome.runtime.getURL('images/close.png'); - document.getElementById('close').alt = i18n.close; - - var closeButton = document.getElementById('close-button'), - body = document.querySelector('body'), - bodyRect = body.getBoundingClientRect(); - - // i18n - body.classList.add('lang-' + lang.slice(0, 2)); - document.getElementById('logo-link').title = i18n.appName; + + var neverButton = document.querySelector('#template-add .never-save'); + neverButton.setAttribute('short-text', i18n.never); + neverButton.setAttribute('full-text', i18n.notificationNeverSave); + + var selectFolder = document.querySelector('#template-add .select-folder'); + selectFolder.setAttribute('aria-label', i18n.folder); + + var addButton = document.querySelector('#template-add .add-save'); + addButton.setAttribute('short-text', i18n.yes); + addButton.setAttribute('full-text', i18n.notificationAddSave); + + var changeButton = document.querySelector('#template-change .change-save'); + changeButton.setAttribute('short-text', i18n.yes); + changeButton.setAttribute('full-text', i18n.notificationChangeSave); + + var closeIcon = document.getElementById('close'); + closeIcon.src = chrome.runtime.getURL('images/close.png'); + closeIcon.alt = i18n.close; + + var closeButton = document.getElementById('close-button') closeButton.title = i18n.close; closeButton.setAttribute('aria-label', i18n.close); - if (bodyRect.width < 768) { - document.querySelector('#template-add .add-save').textContent = i18n.yes; - document.querySelector('#template-add .never-save').textContent = i18n.never; - document.querySelector('#template-add .select-folder').style.display = 'none'; - document.querySelector('#template-change .change-save').textContent = i18n.yes; - } else { - document.querySelector('#template-add .add-save').textContent = i18n.notificationAddSave; - document.querySelector('#template-add .never-save').textContent = i18n.notificationNeverSave; - document.querySelector('#template-add .select-folder').style.display = isVaultLocked ? 'none' : 'initial'; - document.querySelector('#template-add .select-folder').setAttribute('aria-label', i18n.folder); - document.querySelector('#template-change .change-save').textContent = i18n.notificationChangeSave; - } - document.querySelector('#template-add .add-text').textContent = i18n.notificationAddDesc; document.querySelector('#template-change .change-text').textContent = i18n.notificationChangeDesc; diff --git a/src/notification/bar.scss b/src/notification/bar.scss index 6982a3a91f..75603d3b07 100644 --- a/src/notification/bar.scss +++ b/src/notification/bar.scss @@ -1,4 +1,4 @@ -body { +body { background-color: #ffffff; padding: 0; margin: 0; @@ -24,7 +24,6 @@ grid-template-columns: auto max-content; } - .outer-wrapper > *, .inner-wrapper > * { align-self: center; } @@ -77,6 +76,35 @@ button.neutral { } } + +@media screen and (min-width: 768px) { + .never-save::after { + content: attr(full-text); + } + + .add-save::after { + content: attr(full-text); + } + + .change-save::after { + content: attr(full-text); + } +} + +@media screen and (max-width: 768px) { + .never-save::after { + content: attr(short-text); + } + + .add-save::after { + content: attr(short-text); + } + + .change-save::after { + content: attr(short-text); + } +} + @media (print) { body { display: none; From d495ed6c1f87f6dc34d641bf3a3bae7a9c9c603b Mon Sep 17 00:00:00 2001 From: Daniel James Smith Date: Thu, 28 Oct 2021 23:23:00 +0200 Subject: [PATCH 03/50] Handle displaying folder select: small screen vs. un-/locked vault --- src/notification/bar.html | 3 ++- src/notification/bar.js | 1 + src/notification/bar.scss | 9 ++++++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/notification/bar.html b/src/notification/bar.html index 43f56c19dd..1772389c7c 100644 --- a/src/notification/bar.html +++ b/src/notification/bar.html @@ -1,4 +1,4 @@ - + @@ -25,6 +25,7 @@
+
diff --git a/src/notification/bar.js b/src/notification/bar.js index 6798e789bf..338d3546fe 100644 --- a/src/notification/bar.js +++ b/src/notification/bar.js @@ -33,6 +33,7 @@ document.addEventListener('DOMContentLoaded', () => { var selectFolder = document.querySelector('#template-add .select-folder'); selectFolder.setAttribute('aria-label', i18n.folder); + selectFolder.setAttribute('isVaultLocked', isVaultLocked.toString()); var addButton = document.querySelector('#template-add .add-save'); addButton.setAttribute('short-text', i18n.yes); diff --git a/src/notification/bar.scss b/src/notification/bar.scss index 75603d3b07..a5ba203da0 100644 --- a/src/notification/bar.scss +++ b/src/notification/bar.scss @@ -1,4 +1,4 @@ -body { +body { background-color: #ffffff; padding: 0; margin: 0; @@ -76,6 +76,9 @@ button.neutral { } } +.select-folder[isVaultLocked="true"] { + display: none +} @media screen and (min-width: 768px) { .never-save::after { @@ -103,6 +106,10 @@ button.neutral { .change-save::after { content: attr(short-text); } + + .select-folder { + display: none + } } @media (print) { From 0ef7a60ba39dc798b03c39486927e542c3fcb3f4 Mon Sep 17 00:00:00 2001 From: "Patrick H. Lauke" Date: Tue, 2 Nov 2021 17:28:24 +0000 Subject: [PATCH 04/50] Prevent passphrase words from breaking over two lines Closes https://github.com/bitwarden/browser/issues/1096 --- src/popup/scss/misc.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/popup/scss/misc.scss b/src/popup/scss/misc.scss index e61dc028dd..4f73b41d67 100644 --- a/src/popup/scss/misc.scss +++ b/src/popup/scss/misc.scss @@ -146,7 +146,7 @@ p.lead { } .password-wrapper { - word-break: break-all; + overflow-wrap: break-word; white-space: pre-wrap; min-width: 0; } From 2113c709a4ad6b9c4db5c0aa740afecf092ad6d9 Mon Sep 17 00:00:00 2001 From: Thomas Rittson <31796059+eliykat@users.noreply.github.com> Date: Thu, 4 Nov 2021 07:40:42 +1000 Subject: [PATCH 05/50] [Linked fields] Add Linked Field as a custom field type (#1963) * Proof of concept for Linked custom field type * Linked Fields for all cipher types, use dropdown * Fix linked icon alignment * Tweak linked icon alignment and style * Move add-edit custom fields to own component * Disable copy for linked field * Use Field.LinkedId to store linked field info --- jslib | 2 +- src/_locales/en/messages.json | 11 +++++++++++ src/background/main.background.ts | 2 +- src/popup/scss/box.scss | 4 ++++ .../vault/add-edit-custom-fields.component.html | 14 +++++++++++--- src/popup/vault/add-edit.component.html | 3 ++- src/popup/vault/view-custom-fields.component.html | 10 +++++++++- src/services/autofill.service.ts | 14 +++++++++++--- 8 files changed, 50 insertions(+), 10 deletions(-) diff --git a/jslib b/jslib index 24fe836032..2db9e1ce0d 160000 --- a/jslib +++ b/jslib @@ -1 +1 @@ -Subproject commit 24fe836032354d4ec39435776e54dd0995e1b389 +Subproject commit 2db9e1ce0d7a702f07f20ecb916dd8191ff617e1 diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json index af284dde2b..34dce1738f 100644 --- a/src/_locales/en/messages.json +++ b/src/_locales/en/messages.json @@ -983,6 +983,14 @@ "cfTypeBoolean": { "message": "Boolean" }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (tied) to another value." + }, "popup2faCloseMessage": { "message": "Clicking outside the popup window to check your email for your verification code will cause this popup to close. Do you want to open this popup in a new window so that it does not close?" }, @@ -1085,6 +1093,9 @@ "lastName": { "message": "Last Name" }, + "fullName": { + "message": "Full Name" + }, "identityName": { "message": "Identity Name" }, diff --git a/src/background/main.background.ts b/src/background/main.background.ts index e18837ba30..349a2152b1 100644 --- a/src/background/main.background.ts +++ b/src/background/main.background.ts @@ -271,7 +271,7 @@ export default class MainBackground { const message = Object.assign({}, { command: subscriber }, arg); that.runtimeBackground.processMessage(message, that, null); } - }(), this.vaultTimeoutService, this.logService); + }(), this.vaultTimeoutService, this.logService, this.cryptoFunctionService); } async bootstrap() { diff --git a/src/popup/scss/box.scss b/src/popup/scss/box.scss index d3f40f07e8..9503b482a1 100644 --- a/src/popup/scss/box.scss +++ b/src/popup/scss/box.scss @@ -531,6 +531,10 @@ color: themed('mutedColor'); } + &.icon-small { + min-width: 25px; + } + img { border-radius: $border-radius; max-height: 20px; diff --git a/src/popup/vault/add-edit-custom-fields.component.html b/src/popup/vault/add-edit-custom-fields.component.html index 4fe2eae422..aa8262e3f9 100644 --- a/src/popup/vault/add-edit-custom-fields.component.html +++ b/src/popup/vault/add-edit-custom-fields.component.html @@ -16,15 +16,20 @@
- + - + + +
- +
@@ -47,6 +52,9 @@
diff --git a/src/popup/vault/add-edit.component.html b/src/popup/vault/add-edit.component.html index 76f571d15e..6427b0cd21 100644 --- a/src/popup/vault/add-edit.component.html +++ b/src/popup/vault/add-edit.component.html @@ -324,7 +324,8 @@ - + +
{{'ownership' | i18n}} diff --git a/src/popup/vault/view-custom-fields.component.html b/src/popup/vault/view-custom-fields.component.html index 8c3c1853b4..a3ec154475 100644 --- a/src/popup/vault/view-custom-fields.component.html +++ b/src/popup/vault/view-custom-fields.component.html @@ -18,6 +18,13 @@ {{field.value}}
+
+
+ + {{'linkedValue' | i18n}} +
+ {{cipher.linkedFieldI18nKey(field.linkedId) | i18n}} +
diff --git a/src/services/autofill.service.ts b/src/services/autofill.service.ts index 852a7b9638..a5c27ab808 100644 --- a/src/services/autofill.service.ts +++ b/src/services/autofill.service.ts @@ -12,6 +12,7 @@ import { EventType } from 'jslib-common/enums/eventType'; import { FieldType } from 'jslib-common/enums/fieldType'; import { CipherView } from 'jslib-common/models/view/cipherView'; +import { FieldView } from 'jslib-common/models/view/fieldView'; import AutofillField from '../models/autofillField'; import AutofillPageDetails from '../models/autofillPageDetails'; @@ -318,9 +319,16 @@ export default class AutofillService implements AutofillServiceInterface { const matchingIndex = this.findMatchingFieldIndex(field, fieldNames); if (matchingIndex > -1) { - let val = fields[matchingIndex].value; - if (val == null && fields[matchingIndex].type === FieldType.Boolean) { - val = 'false'; + const matchingField: FieldView = fields[matchingIndex]; + let val; + if (matchingField.type === FieldType.Linked) { + // Assumption: Linked Field is not being used to autofill a boolean value + val = options.cipher.linkedFieldValue(matchingField.linkedId); + } else { + val = matchingField.value; + if (val == null && matchingField.type === FieldType.Boolean) { + val = 'false'; + } } filledFields[field.opid] = field; From a1c36147649f7a389c27fc4a51d289bf7db22f65 Mon Sep 17 00:00:00 2001 From: Daniel James Smith Date: Thu, 4 Nov 2021 18:44:38 +0100 Subject: [PATCH 06/50] Simplify text displayed in notificationBar and remove css which modified it --- src/_locales/en/messages.json | 7 ++----- src/notification/bar.html | 6 +++--- src/notification/bar.js | 11 +++-------- src/notification/bar.scss | 26 -------------------------- 4 files changed, 8 insertions(+), 42 deletions(-) diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json index af284dde2b..7d129dd59f 100644 --- a/src/_locales/en/messages.json +++ b/src/_locales/en/messages.json @@ -558,10 +558,7 @@ "message": "Should Bitwarden remember this password for you?" }, "notificationAddSave": { - "message": "Yes, Save Now" - }, - "notificationNeverSave": { - "message": "Never for this website" + "message": "Save" }, "disableChangedPasswordNotification": { "message": "Disable Changed Password Notification" @@ -573,7 +570,7 @@ "message": "Do you want to update this password in Bitwarden?" }, "notificationChangeSave": { - "message": "Yes, Update Now" + "message": "Update" }, "disableContextMenuItem": { "message": "Disable Context Menu Options" diff --git a/src/notification/bar.html b/src/notification/bar.html index 1772389c7c..a03c566f19 100644 --- a/src/notification/bar.html +++ b/src/notification/bar.html @@ -24,15 +24,15 @@
- + - +
- +
diff --git a/src/notification/bar.js b/src/notification/bar.js index 338d3546fe..665f882117 100644 --- a/src/notification/bar.js +++ b/src/notification/bar.js @@ -6,11 +6,9 @@ document.addEventListener('DOMContentLoaded', () => { i18n.appName = chrome.i18n.getMessage('appName'); i18n.close = chrome.i18n.getMessage('close'); - i18n.yes = chrome.i18n.getMessage('yes'); i18n.never = chrome.i18n.getMessage('never'); i18n.folder = chrome.i18n.getMessage('folder'); i18n.notificationAddSave = chrome.i18n.getMessage('notificationAddSave'); - i18n.notificationNeverSave = chrome.i18n.getMessage('notificationNeverSave'); i18n.notificationAddDesc = chrome.i18n.getMessage('notificationAddDesc'); i18n.notificationChangeSave = chrome.i18n.getMessage('notificationChangeSave'); i18n.notificationChangeDesc = chrome.i18n.getMessage('notificationChangeDesc'); @@ -28,20 +26,17 @@ document.addEventListener('DOMContentLoaded', () => { document.getElementById('logo-link').title = i18n.appName; var neverButton = document.querySelector('#template-add .never-save'); - neverButton.setAttribute('short-text', i18n.never); - neverButton.setAttribute('full-text', i18n.notificationNeverSave); + neverButton.textContent = i18n.never; var selectFolder = document.querySelector('#template-add .select-folder'); selectFolder.setAttribute('aria-label', i18n.folder); selectFolder.setAttribute('isVaultLocked', isVaultLocked.toString()); var addButton = document.querySelector('#template-add .add-save'); - addButton.setAttribute('short-text', i18n.yes); - addButton.setAttribute('full-text', i18n.notificationAddSave); + addButton.textContent = i18n.notificationAddSave; var changeButton = document.querySelector('#template-change .change-save'); - changeButton.setAttribute('short-text', i18n.yes); - changeButton.setAttribute('full-text', i18n.notificationChangeSave); + changeButton.textContent = i18n.notificationChangeSave; var closeIcon = document.getElementById('close'); closeIcon.src = chrome.runtime.getURL('images/close.png'); diff --git a/src/notification/bar.scss b/src/notification/bar.scss index a5ba203da0..51b818ea51 100644 --- a/src/notification/bar.scss +++ b/src/notification/bar.scss @@ -80,33 +80,7 @@ button.neutral { display: none } -@media screen and (min-width: 768px) { - .never-save::after { - content: attr(full-text); - } - - .add-save::after { - content: attr(full-text); - } - - .change-save::after { - content: attr(full-text); - } -} - @media screen and (max-width: 768px) { - .never-save::after { - content: attr(short-text); - } - - .add-save::after { - content: attr(short-text); - } - - .change-save::after { - content: attr(short-text); - } - .select-folder { display: none } From 2a0ddb1353936ce3bff695858e2c7a123df043ca Mon Sep 17 00:00:00 2001 From: Joseph Flinn Date: Thu, 4 Nov 2021 13:02:06 -0700 Subject: [PATCH 07/50] Updating the Crowdin update process --- .github/workflows/build.yml | 40 +++++++++++++++++++ .../{crowdin-sync.yml => crowdin-pull.yml} | 0 crowdin.yml | 3 ++ 3 files changed, 43 insertions(+) rename .github/workflows/{crowdin-sync.yml => crowdin-pull.yml} (100%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 79dcc8f98a..40c10a274e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -167,6 +167,41 @@ jobs: if-no-files-found: error + crowdin-push: + name: Crowdin Push + runs-on: ubuntu-20.04 + needs: + - build + env: + _CROWDIN_PROJECT_ID: "268134" + steps: + - name: Checkout repo + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + + - name: Login to Azure + uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a + with: + creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} + + - name: Retrieve secrets + id: retrieve-secrets + uses: Azure/get-keyvault-secrets@80ccd3fafe5662407cc2e55f202ee34bfff8c403 + with: + keyvault: "bitwarden-prod-kv" + secrets: "crowdin-api-token" + + - name: Upload Sources + uses: crowdin/github-action@e39093fd75daae7859c68eded4b43d42ec78d8ea # v1.3.2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} + with: + config: crowdin.yml + crowdin_branch_name: master + upload_sources: true + upload_translations: false + + check-failures: name: Check for failures if: always() @@ -176,6 +211,7 @@ jobs: - setup - locales-test - build + - crowdin-push steps: - name: Check if any job failed if: ${{ (github.ref == 'refs/heads/master') || (github.ref == 'refs/heads/rc') }} @@ -184,6 +220,7 @@ jobs: SETUP_STATUS: ${{ needs.setup.result }} LOCALES_TEST_STATUS: ${{ needs.locales-test.result }} BUILD_STATUS: ${{ needs.build.result }} + CROWDIN_PUSH_STATUS: ${{ needs.crowdin-push.result }} run: | if [ "$CLOC_STATUS" = "failure" ]; then exit 1 @@ -193,7 +230,10 @@ jobs: exit 1 elif [ "$BUILD_STATUS" = "failure" ]; then exit 1 + elif [ "$CROWDIN_PUSH_STATUS" = "failure" ]; then + exit 1 fi + - name: Login to Azure - Prod Subscription uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a if: failure() diff --git a/.github/workflows/crowdin-sync.yml b/.github/workflows/crowdin-pull.yml similarity index 100% rename from .github/workflows/crowdin-sync.yml rename to .github/workflows/crowdin-pull.yml diff --git a/crowdin.yml b/crowdin.yml index 4aa8bb7bad..2d33523535 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -1,7 +1,9 @@ project_id_env: _CROWDIN_PROJECT_ID api_token_env: CROWDIN_API_TOKEN +preserve_hierarchy: true files: - source: /src/_locales/en/messages.json + dest: /src/_locales/en/%original_file_name% translation: /src/_locales/%two_letters_code%/%original_file_name% update_option: update_as_unapproved languages_mapping: @@ -13,6 +15,7 @@ files: en-GB: en_GB en-IN: en_IN - source: /store/locales/en/copy.resx + dest: /store/locales/en/%original_file_name% translation: /store/locales/%two_letters_code%/%original_file_name% update_option: update_as_unapproved languages_mapping: From c97ff022b3cb494399c2e172e8a1b7c2e3504e54 Mon Sep 17 00:00:00 2001 From: Joseph Flinn Date: Thu, 4 Nov 2021 13:04:24 -0700 Subject: [PATCH 08/50] constraining the the crowdin push to the master branch --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 40c10a274e..e79b465d1f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -169,6 +169,7 @@ jobs: crowdin-push: name: Crowdin Push + if: github.ref = 'refs/heads/master' runs-on: ubuntu-20.04 needs: - build From 8c1c0fd832bdcffc78a2301a2424fb91fc43c306 Mon Sep 17 00:00:00 2001 From: Joseph Flinn Date: Thu, 4 Nov 2021 13:04:59 -0700 Subject: [PATCH 09/50] fixing syntax issue --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e79b465d1f..de5b4be582 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -169,7 +169,7 @@ jobs: crowdin-push: name: Crowdin Push - if: github.ref = 'refs/heads/master' + if: github.ref == 'refs/heads/master' runs-on: ubuntu-20.04 needs: - build From a9e523ac9f2fd3aa2c55b998169cd23d0af90c84 Mon Sep 17 00:00:00 2001 From: Joseph Flinn Date: Thu, 4 Nov 2021 13:09:20 -0700 Subject: [PATCH 10/50] scheduling the crowdin pull for every friday --- .github/workflows/crowdin-pull.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/crowdin-pull.yml b/.github/workflows/crowdin-pull.yml index 9d3eaacf90..e534e20379 100644 --- a/.github/workflows/crowdin-pull.yml +++ b/.github/workflows/crowdin-pull.yml @@ -4,8 +4,8 @@ name: Crowdin Sync on: workflow_dispatch: inputs: {} -# schedule: -# - cron: '0 0 * * *' + schedule: + - cron: '0 0 * * 5' jobs: crowdin-sync: From d448c402dc70dd18ffeaa3c88410a508099559b9 Mon Sep 17 00:00:00 2001 From: Daniel James Smith Date: Fri, 5 Nov 2021 14:18:59 +0100 Subject: [PATCH 11/50] Filter ciphers that have password reprompt set when using unlock on autofill via contextMenu --- src/background/contextMenus.background.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/background/contextMenus.background.ts b/src/background/contextMenus.background.ts index 9a29294d4f..f556ae2bff 100644 --- a/src/background/contextMenus.background.ts +++ b/src/background/contextMenus.background.ts @@ -9,6 +9,7 @@ import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.se import { TotpService } from 'jslib-common/abstractions/totp.service'; import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service'; +import { CipherRepromptType } from 'jslib-common/enums/cipherRepromptType'; import { EventType } from 'jslib-common/enums/eventType'; import { CipherView } from 'jslib-common/models/view/cipherView'; import LockedVaultPendingNotificationsItem from './models/lockedVaultPendingNotificationsItem'; @@ -84,7 +85,7 @@ export default class ContextMenusBackground { let cipher: CipherView; if (id === this.noopCommandSuffix) { const ciphers = await this.cipherService.getAllDecryptedForUrl(tab.url); - cipher = ciphers.length > 0 ? ciphers[0] : null; + cipher = ciphers.find(x => x.reprompt === CipherRepromptType.None); } else { const ciphers = await this.cipherService.getAllDecrypted(); cipher = ciphers.find(c => c.id === id); From b38fb3bee074af7a0ec01af01b65846385f117e7 Mon Sep 17 00:00:00 2001 From: Vince Grassia <593223+vgrassia@users.noreply.github.com> Date: Fri, 5 Nov 2021 10:20:43 -0400 Subject: [PATCH 12/50] Fix release workflow to allow releases from 'rc' or 'hotfix' branches only (#2158) --- .github/workflows/release.yml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cc346d5310..1ebe9fa07c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,20 +12,19 @@ jobs: runs-on: ubuntu-20.04 outputs: release-version: ${{ steps.version.outputs.package-version }} + branch-name: ${{ steps.branch.outputs.branch-name }} steps: - name: Branch check run: | - if [[ "$GITHUB_REF" != "refs/heads/release" ]]; then + if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix" ]]; then echo "===================================" - echo "[!] Can only release from the 'release' branch" + echo "[!] Can only release from the 'rc' or 'hotfix' branches" echo "===================================" exit 1 fi - name: Checkout repo uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f - with: - ref: release - name: Check Release Version id: version @@ -42,6 +41,12 @@ jobs: echo "::set-output name=package-version::$version" + - name: Get branch name + id: branch + run: | + BRANCH_NAME=$(basename ${{ github.ref }}) + echo "::set-output name=branch-name::$BRANCH_NAME" + locales-test: name: Locales Test @@ -88,7 +93,7 @@ jobs: with: workflow: build.yml workflow_conclusion: success - branch: release + branch: ${{ needs.setup.outputs.branch-name }} artifacts: 'browser-source-*.zip, dist-chrome-*.zip, dist-opera-*.zip, From f3ed0329a870408144d94e07326467e0efe5d0fd Mon Sep 17 00:00:00 2001 From: Daniel James Smith Date: Tue, 9 Nov 2021 09:43:11 +0100 Subject: [PATCH 13/50] Changed param of arrow function for check of CipherRepromptType --- src/background/contextMenus.background.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/background/contextMenus.background.ts b/src/background/contextMenus.background.ts index f556ae2bff..6852669dc4 100644 --- a/src/background/contextMenus.background.ts +++ b/src/background/contextMenus.background.ts @@ -85,7 +85,7 @@ export default class ContextMenusBackground { let cipher: CipherView; if (id === this.noopCommandSuffix) { const ciphers = await this.cipherService.getAllDecryptedForUrl(tab.url); - cipher = ciphers.find(x => x.reprompt === CipherRepromptType.None); + cipher = ciphers.find(c => c.reprompt === CipherRepromptType.None); } else { const ciphers = await this.cipherService.getAllDecrypted(); cipher = ciphers.find(c => c.id === id); From 0039d4aaea711a56030cecba49ea97070577c12b Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Tue, 9 Nov 2021 12:26:17 -0500 Subject: [PATCH 14/50] url encode data from msg_handler content script (#2170) --- src/background/runtime.background.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/background/runtime.background.ts b/src/background/runtime.background.ts index be8441ea52..41bb287d5f 100644 --- a/src/background/runtime.background.ts +++ b/src/background/runtime.background.ts @@ -138,7 +138,7 @@ export default class RuntimeBackground { try { BrowserApi.createNewTab('popup/index.html?uilocation=popout#/sso?code=' + - msg.code + '&state=' + msg.state); + encodeURIComponent(msg.code) + '&state=' + encodeURIComponent(msg.state)); } catch { this.logService.error('Unable to open sso popout tab'); @@ -151,7 +151,8 @@ export default class RuntimeBackground { return; } - const params = `webAuthnResponse=${encodeURIComponent(msg.data)};remember=${msg.remember}`; + const params = `webAuthnResponse=${encodeURIComponent(msg.data)};` + + `remember=${encodeURIComponent(msg.remember)}`; BrowserApi.createNewTab(`popup/index.html?uilocation=popout#/2fa;${params}`, undefined, false); break; case 'reloadPopup': From cf28435ce3e1a84c094bc290c853a9c4d5fc9c4d Mon Sep 17 00:00:00 2001 From: Thomas Rittson <31796059+eliykat@users.noreply.github.com> Date: Wed, 10 Nov 2021 03:59:51 +1000 Subject: [PATCH 15/50] [Key Connector] Add support for key connector and OTP (#2156) Co-authored-by: Hinton --- jslib | 2 +- src/_locales/en/messages.json | 24 +++++++++++++++ src/background/main.background.ts | 15 +++++++--- src/popup/accounts/lock.component.ts | 6 ++-- .../accounts/remove-password.component.html | 29 +++++++++++++++++++ .../accounts/remove-password.component.ts | 10 +++++++ src/popup/accounts/sso.component.ts | 10 +++++-- src/popup/app-routing.module.ts | 7 +++++ src/popup/app.component.ts | 10 +++++-- src/popup/app.module.ts | 16 ++++++---- src/popup/services/services.module.ts | 5 ++++ src/popup/settings/export.component.html | 23 ++++----------- src/popup/settings/export.component.ts | 6 ++-- src/popup/settings/settings.component.html | 2 +- src/popup/settings/settings.component.ts | 6 +++- src/popup/vault/add-edit.component.html | 5 ++-- src/popup/vault/add-edit.component.ts | 6 ++-- 17 files changed, 139 insertions(+), 43 deletions(-) create mode 100644 src/popup/accounts/remove-password.component.html create mode 100644 src/popup/accounts/remove-password.component.ts diff --git a/jslib b/jslib index 2db9e1ce0d..8f177e2d3a 160000 --- a/jslib +++ b/jslib @@ -1 +1 @@ -Subproject commit 2db9e1ce0d7a702f07f20ecb916dd8191ff617e1 +Subproject commit 8f177e2d3a879b854db5c6e6d7d386b24d637a66 diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json index f2853be848..3c65df4a41 100644 --- a/src/_locales/en/messages.json +++ b/src/_locales/en/messages.json @@ -121,6 +121,9 @@ "continue": { "message": "Continue" }, + "requestVerificationCode": { + "message": "Request one-time password" + }, "verificationCode": { "message": "Verification Code" }, @@ -411,6 +414,9 @@ "verificationCodeRequired": { "message": "Verification code is required." }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, "valueCopied": { "message": "$VALUE$ copied", "description": "Value has been copied to the clipboard.", @@ -1821,5 +1827,23 @@ }, "copyCustomFieldNameNotUnique": { "message": "No unique identifier found." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." } } diff --git a/src/background/main.background.ts b/src/background/main.background.ts index 349a2152b1..11ebc51f85 100644 --- a/src/background/main.background.ts +++ b/src/background/main.background.ts @@ -17,6 +17,7 @@ import { EventService } from 'jslib-common/services/event.service'; import { ExportService } from 'jslib-common/services/export.service'; import { FileUploadService } from 'jslib-common/services/fileUpload.service'; import { FolderService } from 'jslib-common/services/folder.service'; +import { KeyConnectorService } from 'jslib-common/services/keyConnector.service'; import { NotificationsService } from 'jslib-common/services/notifications.service'; import { PasswordGenerationService } from 'jslib-common/services/passwordGeneration.service'; import { PolicyService } from 'jslib-common/services/policy.service'; @@ -45,6 +46,7 @@ import { ExportService as ExportServiceAbstraction } from 'jslib-common/abstract import { FileUploadService as FileUploadServiceAbstraction } from 'jslib-common/abstractions/fileUpload.service'; import { FolderService as FolderServiceAbstraction } from 'jslib-common/abstractions/folder.service'; import { I18nService as I18nServiceAbstraction } from 'jslib-common/abstractions/i18n.service'; +import { KeyConnectorService as KeyConnectorServiceAbstraction } from 'jslib-common/abstractions/keyConnector.service'; import { LogService as LogServiceAbstraction } from 'jslib-common/abstractions/log.service'; import { MessagingService as MessagingServiceAbstraction } from 'jslib-common/abstractions/messaging.service'; import { NotificationsService as NotificationsServiceAbstraction } from 'jslib-common/abstractions/notifications.service'; @@ -64,8 +66,6 @@ import { UserService as UserServiceAbstraction } from 'jslib-common/abstractions import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from 'jslib-common/abstractions/vaultTimeout.service'; import { AutofillService as AutofillServiceAbstraction } from '../services/abstractions/autofill.service'; -import { Utils } from 'jslib-common/misc/utils'; - import { BrowserApi } from '../browser/browserApi'; import { SafariApp } from '../browser/safariApp'; @@ -125,6 +125,7 @@ export default class MainBackground { popupUtilsService: PopupUtilsService; sendService: SendServiceAbstraction; fileUploadService: FileUploadServiceAbstraction; + keyConnectorService: KeyConnectorServiceAbstraction; onUpdatedRan: boolean; onReplacedRan: boolean; @@ -195,9 +196,12 @@ export default class MainBackground { this.storageService, this.i18nService, this.cryptoFunctionService); this.stateService = new StateService(); this.policyService = new PolicyService(this.userService, this.storageService, this.apiService); + this.keyConnectorService = new KeyConnectorService(this.storageService, this.userService, this.cryptoService, + this.apiService, this.environmentService, this.tokenService, this.logService); this.vaultTimeoutService = new VaultTimeoutService(this.cipherService, this.folderService, this.collectionService, this.cryptoService, this.platformUtilsService, this.storageService, this.messagingService, this.searchService, this.userService, this.tokenService, this.policyService, + this.keyConnectorService, async () => { if (this.notificationsService != null) { this.notificationsService.updateConnection(false); @@ -212,7 +216,8 @@ export default class MainBackground { this.syncService = new SyncService(this.userService, this.apiService, this.settingsService, this.folderService, this.cipherService, this.cryptoService, this.collectionService, this.storageService, this.messagingService, this.policyService, this.sendService, - this.logService, async (expired: boolean) => await this.logout(expired)); + this.logService, this.tokenService, this.keyConnectorService, + async (expired: boolean) => await this.logout(expired)); this.eventService = new EventService(this.storageService, this.apiService, this.userService, this.cipherService, this.logService); this.passwordGenerationService = new PasswordGenerationService(this.cryptoService, this.storageService, @@ -271,7 +276,8 @@ export default class MainBackground { const message = Object.assign({}, { command: subscriber }, arg); that.runtimeBackground.processMessage(message, that, null); } - }(), this.vaultTimeoutService, this.logService, this.cryptoFunctionService); + }(), this.vaultTimeoutService, this.logService, this.cryptoFunctionService, this.environmentService, + this.keyConnectorService); } async bootstrap() { @@ -362,6 +368,7 @@ export default class MainBackground { this.policyService.clear(userId), this.passwordGenerationService.clear(), this.vaultTimeoutService.clear(), + this.keyConnectorService.clear(), ]); this.searchService.clearIndex(); diff --git a/src/popup/accounts/lock.component.ts b/src/popup/accounts/lock.component.ts index 09c9bd22fd..ec7d48ff9b 100644 --- a/src/popup/accounts/lock.component.ts +++ b/src/popup/accounts/lock.component.ts @@ -8,6 +8,7 @@ import { ApiService } from 'jslib-common/abstractions/api.service'; import { CryptoService } from 'jslib-common/abstractions/crypto.service'; import { EnvironmentService } from 'jslib-common/abstractions/environment.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; +import { KeyConnectorService } from 'jslib-common/abstractions/keyConnector.service'; import { LogService } from 'jslib-common/abstractions/log.service'; import { MessagingService } from 'jslib-common/abstractions/messaging.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; @@ -30,9 +31,10 @@ export class LockComponent extends BaseLockComponent { userService: UserService, cryptoService: CryptoService, storageService: StorageService, vaultTimeoutService: VaultTimeoutService, environmentService: EnvironmentService, stateService: StateService, - apiService: ApiService, logService: LogService) { + apiService: ApiService, logService: LogService, keyConnectorService: KeyConnectorService) { super(router, i18nService, platformUtilsService, messagingService, userService, cryptoService, - storageService, vaultTimeoutService, environmentService, stateService, apiService, logService); + storageService, vaultTimeoutService, environmentService, stateService, apiService, logService, + keyConnectorService); this.successRoute = '/tabs/current'; this.isInitialLockScreen = (window as any).previousPopupUrl == null; } diff --git a/src/popup/accounts/remove-password.component.html b/src/popup/accounts/remove-password.component.html new file mode 100644 index 0000000000..dcbaac8ade --- /dev/null +++ b/src/popup/accounts/remove-password.component.html @@ -0,0 +1,29 @@ +
+
+
+ {{'removeMasterPassword' | i18n}} +
+
+
+ + +
+
+
+

{{'convertOrganizationEncryptionDesc' | i18n : organization.name}}

+
+
+ +
+
+ +
+
+
+
diff --git a/src/popup/accounts/remove-password.component.ts b/src/popup/accounts/remove-password.component.ts new file mode 100644 index 0000000000..c83269494a --- /dev/null +++ b/src/popup/accounts/remove-password.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +import { RemovePasswordComponent as BaseRemovePasswordComponent } from 'jslib-angular/components/remove-password.component'; + +@Component({ + selector: 'app-remove-password', + templateUrl: 'remove-password.component.html', +}) +export class RemovePasswordComponent extends BaseRemovePasswordComponent { +} diff --git a/src/popup/accounts/sso.component.ts b/src/popup/accounts/sso.component.ts index 1ee79a0aae..e5ad186d26 100644 --- a/src/popup/accounts/sso.component.ts +++ b/src/popup/accounts/sso.component.ts @@ -16,6 +16,7 @@ import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.se import { StateService } from 'jslib-common/abstractions/state.service'; import { StorageService } from 'jslib-common/abstractions/storage.service'; import { SyncService } from 'jslib-common/abstractions/sync.service'; +import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service'; import { SsoComponent as BaseSsoComponent } from 'jslib-angular/components/sso.component'; import { BrowserApi } from '../../browser/browserApi'; @@ -30,7 +31,8 @@ export class SsoComponent extends BaseSsoComponent { storageService: StorageService, stateService: StateService, platformUtilsService: PlatformUtilsService, apiService: ApiService, cryptoFunctionService: CryptoFunctionService, passwordGenerationService: PasswordGenerationService, - syncService: SyncService, environmentService: EnvironmentService, logService: LogService) { + syncService: SyncService, environmentService: EnvironmentService, logService: LogService, + private vaultTimeoutService: VaultTimeoutService) { super(authService, router, i18nService, route, storageService, stateService, platformUtilsService, apiService, cryptoFunctionService, environmentService, passwordGenerationService, logService); @@ -41,7 +43,11 @@ export class SsoComponent extends BaseSsoComponent { super.onSuccessfulLogin = async () => { await syncService.fullSync(true); - BrowserApi.reloadOpenWindows(); + if (await this.vaultTimeoutService.isLocked()) { + // If the vault is unlocked then this will clear keys from memory, which we don't want to do + BrowserApi.reloadOpenWindows(); + } + const thisWindow = window.open('', '_self'); thisWindow.close(); }; diff --git a/src/popup/app-routing.module.ts b/src/popup/app-routing.module.ts index f6558b7484..4b058f2842 100644 --- a/src/popup/app-routing.module.ts +++ b/src/popup/app-routing.module.ts @@ -18,6 +18,7 @@ import { HomeComponent } from './accounts/home.component'; import { LockComponent } from './accounts/lock.component'; import { LoginComponent } from './accounts/login.component'; import { RegisterComponent } from './accounts/register.component'; +import { RemovePasswordComponent } from './accounts/remove-password.component'; import { SetPasswordComponent } from './accounts/set-password.component'; import { SsoComponent } from './accounts/sso.component'; import { TwoFactorOptionsComponent } from './accounts/two-factor-options.component'; @@ -105,6 +106,12 @@ const routes: Routes = [ component: SetPasswordComponent, data: { state: 'set-password' }, }, + { + path: 'remove-password', + component: RemovePasswordComponent, + canActivate: [AuthGuardService], + data: { state: 'remove-password' }, + }, { path: 'register', component: RegisterComponent, diff --git a/src/popup/app.component.ts b/src/popup/app.component.ts index b9551efb38..837f17d6e4 100644 --- a/src/popup/app.component.ts +++ b/src/popup/app.component.ts @@ -26,6 +26,7 @@ import { BroadcasterService } from 'jslib-angular/services/broadcaster.service'; import { AuthService } from 'jslib-common/abstractions/auth.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; +import { KeyConnectorService } from 'jslib-common/abstractions/keyConnector.service'; import { MessagingService } from 'jslib-common/abstractions/messaging.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; import { StateService } from 'jslib-common/abstractions/state.service'; @@ -33,7 +34,6 @@ import { StorageService } from 'jslib-common/abstractions/storage.service'; import { ConstantsService } from 'jslib-common/services/constants.service'; -import BrowserPlatformUtilsService from 'src/services/browserPlatformUtils.service'; import { routerTransition } from './app-routing.animations'; @Component({ @@ -63,7 +63,8 @@ export class AppComponent implements OnInit { private i18nService: I18nService, private router: Router, private stateService: StateService, private messagingService: MessagingService, private changeDetectorRef: ChangeDetectorRef, private ngZone: NgZone, - private sanitizer: DomSanitizer, private platformUtilsService: PlatformUtilsService) { } + private sanitizer: DomSanitizer, private platformUtilsService: PlatformUtilsService, + private keyConnectoService: KeyConnectorService) { } ngOnInit() { if (BrowserApi.getBackgroundPage() == null) { @@ -121,6 +122,11 @@ export class AppComponent implements OnInit { this.ngZone.run(() => { this.router.navigate(['/']); }); + } else if (msg.command === 'convertAccountToKeyConnector') { + this.ngZone.run(async () => { + await this.keyConnectoService.setConvertAccountRequired(true); + this.router.navigate(['/remove-password']); + }); } else { msg.webExtSender = sender; this.broadcasterService.send(msg); diff --git a/src/popup/app.module.ts b/src/popup/app.module.ts index 57aa6a5507..89719c79e1 100644 --- a/src/popup/app.module.ts +++ b/src/popup/app.module.ts @@ -17,6 +17,7 @@ import { HomeComponent } from './accounts/home.component'; import { LockComponent } from './accounts/lock.component'; import { LoginComponent } from './accounts/login.component'; import { RegisterComponent } from './accounts/register.component'; +import { RemovePasswordComponent } from './accounts/remove-password.component'; import { SetPasswordComponent } from './accounts/set-password.component'; import { SsoComponent } from './accounts/sso.component'; import { TwoFactorOptionsComponent } from './accounts/two-factor-options.component'; @@ -83,6 +84,7 @@ import { SetPinComponent } from './components/set-pin.component'; import { CalloutComponent } from 'jslib-angular/components/callout.component'; import { IconComponent } from 'jslib-angular/components/icon.component'; +import { VerifyMasterPasswordComponent } from 'jslib-angular/components/verify-master-password.component'; import { CurrencyPipe, @@ -192,6 +194,7 @@ registerLocaleData(localeZhTw, 'zh-TW'); A11yTitleDirective, ActionButtonsComponent, AddEditComponent, + AddEditCustomFieldsComponent, ApiActionDirective, AppComponent, AttachmentsComponent, @@ -212,8 +215,8 @@ registerLocaleData(localeZhTw, 'zh-TW'); FolderAddEditComponent, FoldersComponent, GroupingsComponent, - HomeComponent, HintComponent, + HomeComponent, I18nPipe, IconComponent, InputVerbatimDirective, @@ -223,6 +226,7 @@ registerLocaleData(localeZhTw, 'zh-TW'); PasswordGeneratorComponent, PasswordGeneratorHistoryComponent, PasswordHistoryComponent, + PasswordRepromptComponent, PopOutComponent, PremiumComponent, PrivateModeComponent, @@ -235,6 +239,7 @@ registerLocaleData(localeZhTw, 'zh-TW'); SendListComponent, SendTypeComponent, SetPasswordComponent, + SetPinComponent, SettingsComponent, ShareComponent, SsoComponent, @@ -243,15 +248,14 @@ registerLocaleData(localeZhTw, 'zh-TW'); SyncComponent, TabsComponent, TrueFalseValueDirective, - TwoFactorOptionsComponent, TwoFactorComponent, + TwoFactorOptionsComponent, UpdateTempPasswordComponent, - ViewComponent, - PasswordRepromptComponent, - SetPinComponent, VaultTimeoutInputComponent, - AddEditCustomFieldsComponent, + VerifyMasterPasswordComponent, + ViewComponent, ViewCustomFieldsComponent, + RemovePasswordComponent, ], entryComponents: [], providers: [ diff --git a/src/popup/services/services.module.ts b/src/popup/services/services.module.ts index 4ca02093d4..3a1c84be61 100644 --- a/src/popup/services/services.module.ts +++ b/src/popup/services/services.module.ts @@ -33,6 +33,7 @@ import { ExportService } from 'jslib-common/abstractions/export.service'; import { FileUploadService } from 'jslib-common/abstractions/fileUpload.service'; import { FolderService } from 'jslib-common/abstractions/folder.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; +import { KeyConnectorService } from 'jslib-common/abstractions/keyConnector.service'; import { LogService as LogServiceAbstraction } from 'jslib-common/abstractions/log.service'; import { MessagingService } from 'jslib-common/abstractions/messaging.service'; import { NotificationsService } from 'jslib-common/abstractions/notifications.service'; @@ -49,6 +50,7 @@ import { SyncService } from 'jslib-common/abstractions/sync.service'; import { TokenService } from 'jslib-common/abstractions/token.service'; import { TotpService } from 'jslib-common/abstractions/totp.service'; import { UserService } from 'jslib-common/abstractions/user.service'; +import { UserVerificationService as UserVerificationServiceAbstraction } from 'jslib-common/abstractions/userVerification.service'; import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service'; import { AutofillService } from '../../services/abstractions/autofill.service'; @@ -59,6 +61,7 @@ import { ConsoleLogService } from 'jslib-common/services/consoleLog.service'; import { ConstantsService } from 'jslib-common/services/constants.service'; import { SearchService } from 'jslib-common/services/search.service'; import { StateService } from 'jslib-common/services/state.service'; +import { UserVerificationService } from 'jslib-common/services/userVerification.service'; import { PopupSearchService } from './popup-search.service'; import { PopupUtilsService } from './popup-utils.service'; @@ -182,6 +185,7 @@ export function initFactory(platformUtilsService: PlatformUtilsService, i18nServ { provide: AutofillService, useFactory: getBgService('autofillService'), deps: [] }, { provide: ExportService, useFactory: getBgService('exportService'), deps: [] }, { provide: SendService, useFactory: getBgService('sendService'), deps: [] }, + { provide: KeyConnectorService, useFactory: getBgService('keyConnectorService'), deps: [] }, { provide: VaultTimeoutService, useFactory: getBgService('vaultTimeoutService'), @@ -204,6 +208,7 @@ export function initFactory(platformUtilsService: PlatformUtilsService, i18nServ deps: [], }, { provide: PasswordRepromptServiceAbstraction, useClass: PasswordRepromptService }, + { provide: UserVerificationServiceAbstraction, useClass: UserVerificationService }, ], }) export class ServicesModule { diff --git a/src/popup/settings/export.component.html b/src/popup/settings/export.component.html index 922f3ebc15..75b918cebd 100644 --- a/src/popup/settings/export.component.html +++ b/src/popup/settings/export.component.html @@ -1,4 +1,4 @@ -
+
- +
@@ -22,25 +22,14 @@
- +
- - -
-
- + +
diff --git a/src/popup/settings/export.component.ts b/src/popup/settings/export.component.ts index ad936f0f05..b60986a5b5 100644 --- a/src/popup/settings/export.component.ts +++ b/src/popup/settings/export.component.ts @@ -1,4 +1,5 @@ import { Component } from '@angular/core'; +import { FormBuilder } from '@angular/forms'; import { Router } from '@angular/router'; import { CryptoService } from 'jslib-common/abstractions/crypto.service'; @@ -8,6 +9,7 @@ import { I18nService } from 'jslib-common/abstractions/i18n.service'; import { LogService } from 'jslib-common/abstractions/log.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; import { PolicyService } from 'jslib-common/abstractions/policy.service'; +import { UserVerificationService } from 'jslib-common/abstractions/userVerification.service'; import { ExportComponent as BaseExportComponent } from 'jslib-angular/components/export.component'; @@ -19,9 +21,9 @@ export class ExportComponent extends BaseExportComponent { constructor(cryptoService: CryptoService, i18nService: I18nService, platformUtilsService: PlatformUtilsService, exportService: ExportService, eventService: EventService, policyService: PolicyService, private router: Router, - logService: LogService) { + logService: LogService, userVerificationService: UserVerificationService, fb: FormBuilder) { super(cryptoService, i18nService, platformUtilsService, exportService, eventService, policyService, window, - logService); + logService, userVerificationService, fb); } protected saved() { diff --git a/src/popup/settings/settings.component.html b/src/popup/settings/settings.component.html index 66df2da28f..20908836e8 100644 --- a/src/popup/settings/settings.component.html +++ b/src/popup/settings/settings.component.html @@ -71,7 +71,7 @@
diff --git a/src/popup/settings/settings.component.ts b/src/popup/settings/settings.component.ts index 89c3c415d5..94fb371272 100644 --- a/src/popup/settings/settings.component.ts +++ b/src/popup/settings/settings.component.ts @@ -18,6 +18,7 @@ import { ConstantsService } from 'jslib-common/services/constants.service'; import { CryptoService } from 'jslib-common/abstractions/crypto.service'; import { EnvironmentService } from 'jslib-common/abstractions/environment.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service'; +import { KeyConnectorService } from 'jslib-common/abstractions/keyConnector.service'; import { MessagingService } from 'jslib-common/abstractions/messaging.service'; import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service'; import { StorageService } from 'jslib-common/abstractions/storage.service'; @@ -58,6 +59,7 @@ export class SettingsComponent implements OnInit { biometric: boolean = false; disableAutoBiometricsPrompt = true; previousVaultTimeout: number = null; + showChangeMasterPass = true; vaultTimeout: FormControl = new FormControl(null); @@ -66,7 +68,8 @@ export class SettingsComponent implements OnInit { public messagingService: MessagingService, private router: Router, private environmentService: EnvironmentService, private cryptoService: CryptoService, private userService: UserService, private popupUtilsService: PopupUtilsService, - private modalService: ModalService, private toasterService: ToasterService) { + private modalService: ModalService, private toasterService: ToasterService, + private keyConnectorService: KeyConnectorService) { } async ngOnInit() { @@ -118,6 +121,7 @@ export class SettingsComponent implements OnInit { this.biometric = await this.vaultTimeoutService.isBiometricLockSet(); this.disableAutoBiometricsPrompt = await this.storageService.get( ConstantsService.disableAutoBiometricsPromptKey) ?? true; + this.showChangeMasterPass = !await this.keyConnectorService.getUsesKeyConnector(); } async saveVaultTimeout(newValue: number) { diff --git a/src/popup/vault/add-edit.component.html b/src/popup/vault/add-edit.component.html index 6427b0cd21..591886b993 100644 --- a/src/popup/vault/add-edit.component.html +++ b/src/popup/vault/add-edit.component.html @@ -290,7 +290,7 @@ -
+
- +
+ + + {{'codeSent' | i18n}} + +
+ +
+ + +
+ diff --git a/src/popup/components/verify-master-password.component.ts b/src/popup/components/verify-master-password.component.ts new file mode 100644 index 0000000000..d51e5dc614 --- /dev/null +++ b/src/popup/components/verify-master-password.component.ts @@ -0,0 +1,31 @@ +import { + animate, + style, + transition, + trigger, +} from '@angular/animations'; +import { Component } from '@angular/core'; +import { NG_VALUE_ACCESSOR } from '@angular/forms'; + +import { VerifyMasterPasswordComponent as BaseComponent } from 'jslib-angular/components/verify-master-password.component'; + +@Component({ + selector: 'app-verify-master-password', + templateUrl: 'verify-master-password.component.html', + providers: [ + { + provide: NG_VALUE_ACCESSOR, + multi: true, + useExisting: VerifyMasterPasswordComponent, + }, + ], + animations: [ + trigger('sent', [ + transition(':enter', [ + style({ opacity: 0 }), + animate('100ms', style({ opacity: 1 })), + ]), + ]), + ], +}) +export class VerifyMasterPasswordComponent extends BaseComponent { } diff --git a/src/popup/settings/export.component.html b/src/popup/settings/export.component.html index 75b918cebd..8dfe5babdd 100644 --- a/src/popup/settings/export.component.html +++ b/src/popup/settings/export.component.html @@ -26,15 +26,11 @@ -
-
- - -
-
+ + From adb95e76f41ccf0a0021f98935a9377fdb3c7d96 Mon Sep 17 00:00:00 2001 From: Thomas Rittson <31796059+eliykat@users.noreply.github.com> Date: Thu, 18 Nov 2021 21:38:47 +1000 Subject: [PATCH 24/50] [Key Connector] Hide "Master Pass On Restart" prompt when setting pin (#2186) * Disable Master Pass on Restart for Key Connector * Update jslib --- jslib | 2 +- src/popup/components/set-pin.component.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jslib b/jslib index ea9a8b979d..fc0d624621 160000 --- a/jslib +++ b/jslib @@ -1 +1 @@ -Subproject commit ea9a8b979d5b5797ddf010bbc625843b149065e9 +Subproject commit fc0d6246215f6154c2d566e44f6ddbe8eaa056e6 diff --git a/src/popup/components/set-pin.component.html b/src/popup/components/set-pin.component.html index bd113f8cc7..06f3a5808b 100644 --- a/src/popup/components/set-pin.component.html +++ b/src/popup/components/set-pin.component.html @@ -23,7 +23,7 @@ -
+