diff --git a/.eslintrc.json b/.eslintrc.json index 4fba3dd6128..d6c329a94dc 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -34,20 +34,14 @@ } }, "rules": { - "@typescript-eslint/no-explicit-any": "off", // TODO: This should be re-enabled - "@typescript-eslint/no-unused-vars": ["error", { "args": "none" }], "@typescript-eslint/explicit-member-accessibility": [ "error", - { - "accessibility": "no-public" - } - ], - "@typescript-eslint/no-this-alias": [ - "error", - { - "allowedNames": ["self"] - } + { "accessibility": "no-public" } ], + "@typescript-eslint/no-explicit-any": "off", // TODO: This should be re-enabled + "@typescript-eslint/no-misused-promises": ["error", { "checksVoidReturn": false }], + "@typescript-eslint/no-this-alias": ["error", { "allowedNames": ["self"] }], + "@typescript-eslint/no-unused-vars": ["error", { "args": "none" }], "no-console": "error", "import/no-unresolved": "off", // TODO: Look into turning off once each package is an actual package. "import/order": [ diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c5f55674aee..a70774b5e1d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -75,8 +75,8 @@ apps/web/src/translation-constants.ts @bitwarden/team-platform-dev apps/browser/src/autofill @bitwarden/team-autofill-dev ## Component Library ## -.storybook @bitwarden/team-platform-dev -libs/components @bitwarden/team-platform-dev +.storybook @bitwarden/team-component-library +libs/components @bitwarden/team-component-library ## Desktop native module ## apps/desktop/desktop_native @bitwarden/team-platform-dev diff --git a/.github/workflows/brew-bump-cli.yml b/.github/workflows/brew-bump-cli.yml index d2e998eacb0..8273ab00e80 100644 --- a/.github/workflows/brew-bump-cli.yml +++ b/.github/workflows/brew-bump-cli.yml @@ -23,7 +23,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: "bitwarden-ci" secrets: "brew-bump-workflow-pat" diff --git a/.github/workflows/brew-bump-desktop.yml b/.github/workflows/brew-bump-desktop.yml index 1856cc5fb82..4032f5883a0 100644 --- a/.github/workflows/brew-bump-desktop.yml +++ b/.github/workflows/brew-bump-desktop.yml @@ -23,7 +23,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: "bitwarden-ci" secrets: "brew-bump-workflow-pat" diff --git a/.github/workflows/build-browser.yml b/.github/workflows/build-browser.yml index 57c2fdcef07..f2441c79536 100644 --- a/.github/workflows/build-browser.yml +++ b/.github/workflows/build-browser.yml @@ -58,7 +58,11 @@ jobs: outputs: repo_url: ${{ steps.gen_vars.outputs.repo_url }} adj_build_number: ${{ steps.gen_vars.outputs.adj_build_number }} + node_version: ${{ steps.retrieve-node-version.outputs.node_version }} steps: + - name: Checkout repo + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: Get Package Version id: gen_vars run: | @@ -68,6 +72,14 @@ jobs: echo "repo_url=$repo_url" >> $GITHUB_OUTPUT echo "adj_build_number=$adj_build_num" >> $GITHUB_OUTPUT + - name: Get Node Version + id: retrieve-node-version + working-directory: ./ + run: | + NODE_NVMRC=$(cat .nvmrc) + NODE_VERSION=${NODE_NVMRC/v/''} + echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT + locales-test: name: Locales Test @@ -114,6 +126,7 @@ jobs: - locales-test env: _BUILD_NUMBER: ${{ needs.setup.outputs.adj_build_number }} + _NODE_VERSION: ${{ needs.setup.outputs.node_version }} steps: - name: Checkout repo uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 @@ -123,7 +136,7 @@ jobs: with: cache: 'npm' cache-dependency-path: '**/package-lock.json' - node-version: '18' + node-version: ${{ env._NODE_VERSION }} - name: Install node-gyp run: | @@ -251,6 +264,7 @@ jobs: - locales-test env: _BUILD_NUMBER: ${{ needs.setup.outputs.adj_build_number }} + _NODE_VERSION: ${{ needs.setup.outputs.node_version }} steps: - name: Checkout repo uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 @@ -260,7 +274,7 @@ jobs: with: cache: 'npm' cache-dependency-path: '**/package-lock.json' - node-version: '18' + node-version: ${{ env._NODE_VERSION }} - name: Print environment run: | @@ -361,7 +375,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: "bitwarden-ci" secrets: "crowdin-api-token" @@ -423,7 +437,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets if: failure() - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: "bitwarden-ci" secrets: "devops-alerts-slack-webhook-url" diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index 9fa71cb24fe..ffffdccb8a7 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -53,17 +53,26 @@ jobs: name: Setup runs-on: ubuntu-22.04 outputs: - package_version: ${{ steps.retrieve-version.outputs.package_version }} + package_version: ${{ steps.retrieve-package-version.outputs.package_version }} + node_version: ${{ steps.retrieve-node-version.outputs.node_version }} steps: - name: Checkout repo uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Get Package Version - id: retrieve-version + id: retrieve-package-version run: | PKG_VERSION=$(jq -r .version package.json) echo "package_version=$PKG_VERSION" >> $GITHUB_OUTPUT + - name: Get Node Version + id: retrieve-node-version + working-directory: ./ + run: | + NODE_NVMRC=$(cat .nvmrc) + NODE_VERSION=${NODE_NVMRC/v/''} + echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT + cli: name: Build CLI ${{ matrix.os }} @@ -75,6 +84,7 @@ jobs: - setup env: _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} + _NODE_VERSION: ${{ needs.setup.outputs.node_version }} _WIN_PKG_FETCH_VERSION: 18.5.0 _WIN_PKG_VERSION: 3.4 steps: @@ -92,7 +102,7 @@ jobs: with: cache: 'npm' cache-dependency-path: '**/package-lock.json' - node-version: '18' + node-version: ${{ env._NODE_VERSION }} - name: Install node-gyp run: | @@ -149,6 +159,7 @@ jobs: - setup env: _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} + _NODE_VERSION: ${{ needs.setup.outputs.node_version }} _WIN_PKG_FETCH_VERSION: 18.5.0 _WIN_PKG_VERSION: 3.4 steps: @@ -166,7 +177,7 @@ jobs: with: cache: 'npm' cache-dependency-path: '**/package-lock.json' - node-version: '18' + node-version: ${{ env._NODE_VERSION }} - name: Install node-gyp run: | @@ -404,7 +415,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets if: failure() - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: "bitwarden-ci" secrets: "devops-alerts-slack-webhook-url" diff --git a/.github/workflows/build-desktop.yml b/.github/workflows/build-desktop.yml index 6db1e59a3fa..8b0482c3671 100644 --- a/.github/workflows/build-desktop.yml +++ b/.github/workflows/build-desktop.yml @@ -78,6 +78,7 @@ jobs: build_number: ${{ steps.increment-version.outputs.build_number }} rc_branch_exists: ${{ steps.branch-check.outputs.rc_branch_exists }} hotfix_branch_exists: ${{ steps.branch-check.outputs.hotfix_branch_exists }} + node_version: ${{ steps.retrieve-node-version.outputs.node_version }} defaults: run: working-directory: apps/desktop @@ -130,6 +131,13 @@ jobs: echo "hotfix_branch_exists=0" >> $GITHUB_OUTPUT fi + - name: Get Node Version + id: retrieve-node-version + working-directory: ./ + run: | + NODE_NVMRC=$(cat .nvmrc) + NODE_VERSION=${NODE_NVMRC/v/''} + echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT linux: name: Linux Build @@ -138,6 +146,7 @@ jobs: - setup env: _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} + _NODE_VERSION: ${{ needs.setup.outputs.node_version }} defaults: run: working-directory: apps/desktop @@ -150,7 +159,7 @@ jobs: with: cache: 'npm' cache-dependency-path: '**/package-lock.json' - node-version: '18' + node-version: ${{ env._NODE_VERSION }} - name: Set Node options run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV @@ -257,6 +266,7 @@ jobs: working-directory: apps/desktop env: _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} + _NODE_VERSION: ${{ needs.setup.outputs.node_version }} steps: - name: Checkout repo uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 @@ -266,7 +276,7 @@ jobs: with: cache: 'npm' cache-dependency-path: '**/package-lock.json' - node-version: '18' + node-version: ${{ env._NODE_VERSION }} - name: Set Node options run: echo "NODE_OPTIONS=--max_old_space_size=4096" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append @@ -277,7 +287,7 @@ jobs: node-gyp install $(node -v) - name: Install AST - uses: bitwarden/gh-actions/install-ast@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/install-ast@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 - name: Set up environmentF run: choco install checksum --no-progress @@ -302,7 +312,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: "bitwarden-ci" secrets: "code-signing-vault-url, @@ -467,6 +477,7 @@ jobs: - setup env: _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} + _NODE_VERSION: ${{ needs.setup.outputs.node_version }} defaults: run: working-directory: apps/desktop @@ -479,7 +490,7 @@ jobs: with: cache: 'npm' cache-dependency-path: '**/package-lock.json' - node-version: '18' + node-version: ${{ env._NODE_VERSION }} - name: Set Node options run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV @@ -619,6 +630,7 @@ jobs: - setup env: _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} + _NODE_VERSION: ${{ needs.setup.outputs.node_version }} defaults: run: working-directory: apps/desktop @@ -631,7 +643,7 @@ jobs: with: cache: 'npm' cache-dependency-path: '**/package-lock.json' - node-version: '18' + node-version: ${{ env._NODE_VERSION }} - name: Set Node options run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV @@ -816,6 +828,7 @@ jobs: - setup env: _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} + _NODE_VERSION: ${{ needs.setup.outputs.node_version }} defaults: run: working-directory: apps/desktop @@ -828,7 +841,7 @@ jobs: with: cache: 'npm' cache-dependency-path: '**/package-lock.json' - node-version: '18' + node-version: ${{ env._NODE_VERSION }} - name: Set Node options run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV @@ -1005,6 +1018,7 @@ jobs: - setup env: _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} + _NODE_VERSION: ${{ needs.setup.outputs.node_version }} defaults: run: working-directory: apps/desktop @@ -1017,7 +1031,7 @@ jobs: with: cache: 'npm' cache-dependency-path: '**/package-lock.json' - node-version: '18' + node-version: ${{ env._NODE_VERSION }} - name: Set Node options run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV @@ -1190,7 +1204,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: "bitwarden-ci" secrets: "crowdin-api-token" @@ -1269,7 +1283,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets if: failure() - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: "bitwarden-ci" secrets: "devops-alerts-slack-webhook-url" diff --git a/.github/workflows/build-web.yml b/.github/workflows/build-web.yml index f5458448465..d0360b4a4ed 100644 --- a/.github/workflows/build-web.yml +++ b/.github/workflows/build-web.yml @@ -57,6 +57,7 @@ jobs: runs-on: ubuntu-22.04 outputs: version: ${{ steps.version.outputs.value }} + node_version: ${{ steps.retrieve-node-version.outputs.node_version }} steps: - name: Checkout repo uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 @@ -65,12 +66,20 @@ jobs: id: version run: echo "value=${GITHUB_SHA:0:7}" >> $GITHUB_OUTPUT + - name: Get Node Version + id: retrieve-node-version + run: | + NODE_NVMRC=$(cat .nvmrc) + NODE_VERSION=${NODE_NVMRC/v/''} + echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT + build-artifacts: name: Build artifacts runs-on: ubuntu-22.04 needs: setup env: _VERSION: ${{ needs.setup.outputs.version }} + _NODE_VERSION: ${{ needs.setup.outputs.node_version }} strategy: matrix: include: @@ -98,7 +107,7 @@ jobs: with: cache: 'npm' cache-dependency-path: '**/package-lock.json' - node-version: "16" + node-version: ${{ env._NODE_VERSION }} - name: Print environment run: | @@ -188,7 +197,7 @@ jobs: - name: Retrieve github PAT secrets id: retrieve-secret-pat - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: "bitwarden-ci" secrets: "github-pat-bitwarden-devops-bot-repo-scope" @@ -264,7 +273,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: "bitwarden-ci" secrets: "crowdin-api-token" @@ -325,7 +334,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets if: failure() - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: "bitwarden-ci" secrets: "devops-alerts-slack-webhook-url" diff --git a/.github/workflows/chromatic.yml b/.github/workflows/chromatic.yml index 7f6d5cc11c4..ccaf9a1a6a0 100644 --- a/.github/workflows/chromatic.yml +++ b/.github/workflows/chromatic.yml @@ -12,16 +12,23 @@ jobs: runs-on: ubuntu-20.04 steps: - - name: Set up Node - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 - with: - node-version: "16" - - name: Checkout repo uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 with: fetch-depth: 0 + - name: Get Node Version + id: retrieve-node-version + run: | + NODE_NVMRC=$(cat .nvmrc) + NODE_VERSION=${NODE_NVMRC/v/''} + echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT + + - name: Set up Node + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 + with: + node-version: ${{ steps.retrieve-node-version.outputs.node_version }} + - name: Cache npm id: npm-cache uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 @@ -31,7 +38,7 @@ jobs: - name: Install Node dependencies run: npm ci - + # Manual build the storybook to resolve a chromatic/storybook bug related to TurboSnap - name: Build Storybook run: npm run build-storybook:ci diff --git a/.github/workflows/crowdin-pull.yml b/.github/workflows/crowdin-pull.yml index d14938cc468..0ff79d68296 100644 --- a/.github/workflows/crowdin-pull.yml +++ b/.github/workflows/crowdin-pull.yml @@ -32,13 +32,13 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: "bitwarden-ci" secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase" - name: Download translations - uses: bitwarden/gh-actions/crowdin@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/crowdin@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} diff --git a/.github/workflows/deploy-eu-prod-web.yml b/.github/workflows/deploy-eu-prod-web.yml index 523e0f44de7..aeb5d2c0197 100644 --- a/.github/workflows/deploy-eu-prod-web.yml +++ b/.github/workflows/deploy-eu-prod-web.yml @@ -24,13 +24,13 @@ jobs: - name: Retrieve Storage Account connection string id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: webvault-westeurope-prod secrets: "sa-bitwarden-web-vault-dev-key-temp" - name: Download latest cloud asset - uses: bitwarden/gh-actions/download-artifacts@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: workflow: build-web.yml path: apps/web diff --git a/.github/workflows/deploy-eu-qa-web.yml b/.github/workflows/deploy-eu-qa-web.yml index 2a1e271f18b..0b71fbc9981 100644 --- a/.github/workflows/deploy-eu-qa-web.yml +++ b/.github/workflows/deploy-eu-qa-web.yml @@ -24,13 +24,13 @@ jobs: - name: Retrieve Storage Account connection string id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: webvaulteu-westeurope-qa secrets: "sa-bitwarden-web-vault-dev-key-temp" - name: Download latest cloud asset - uses: bitwarden/gh-actions/download-artifacts@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: workflow: build-web.yml path: apps/web diff --git a/.github/workflows/deploy-non-prod-web.yml b/.github/workflows/deploy-non-prod-web.yml index 78e0f12b7e9..8e5b8f5c9f3 100644 --- a/.github/workflows/deploy-non-prod-web.yml +++ b/.github/workflows/deploy-non-prod-web.yml @@ -67,7 +67,7 @@ jobs: uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Download latest cloud asset - uses: bitwarden/gh-actions/download-artifacts@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: workflow: build-web.yml path: apps/web diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index a3c3efdd19d..0e8de8f1962 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -38,12 +38,19 @@ jobs: > tmp.txt diff <(sort .github/whitelist-capital-letters.txt) <(sort tmp.txt) + - name: Get Node Version + id: retrieve-node-version + run: | + NODE_NVMRC=$(cat .nvmrc) + NODE_VERSION=${NODE_NVMRC/v/''} + echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT + - name: Set up Node uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 with: cache: 'npm' cache-dependency-path: '**/package-lock.json' - node-version: '18' + node-version: ${{ steps.retrieve-node-version.outputs.node_version }} - name: Run linter run: | diff --git a/.github/workflows/release-browser.yml b/.github/workflows/release-browser.yml index 5fd9441f14a..32cf8d18546 100644 --- a/.github/workflows/release-browser.yml +++ b/.github/workflows/release-browser.yml @@ -41,7 +41,7 @@ jobs: - name: Check Release Version id: version - uses: bitwarden/gh-actions/release-version-check@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/release-version-check@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: release-type: ${{ github.event.inputs.release_type }} project-type: ts @@ -103,7 +103,7 @@ jobs: - name: Download latest Release build artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: workflow: build-browser.yml workflow_conclusion: success @@ -116,7 +116,7 @@ jobs: - name: Dry Run - Download latest master build artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: workflow: build-browser.yml workflow_conclusion: success diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml index 7c21cafcfd1..73c0f24affd 100644 --- a/.github/workflows/release-cli.yml +++ b/.github/workflows/release-cli.yml @@ -57,7 +57,7 @@ jobs: - name: Check Release Version id: version - uses: bitwarden/gh-actions/release-version-check@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/release-version-check@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: release-type: ${{ github.event.inputs.release_type }} project-type: ts @@ -78,7 +78,7 @@ jobs: - name: Download all Release artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: workflow: build-cli.yml path: apps/cli @@ -87,7 +87,7 @@ jobs: - name: Dry Run - Download all artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: workflow: build-cli.yml path: apps/cli @@ -150,7 +150,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: "bitwarden-ci" secrets: "snapcraft-store-token" @@ -162,7 +162,7 @@ jobs: - name: Download artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: workflow: build-cli.yml path: apps/cli @@ -172,7 +172,7 @@ jobs: - name: Dry Run - Download artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: workflow: build-cli.yml path: apps/cli @@ -206,7 +206,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: "bitwarden-ci" secrets: "cli-choco-api-key" @@ -222,7 +222,7 @@ jobs: - name: Download artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: workflow: build-cli.yml path: apps/cli/dist @@ -232,7 +232,7 @@ jobs: - name: Dry Run - Download artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: workflow: build-cli.yml path: apps/cli/dist @@ -265,14 +265,14 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: "bitwarden-ci" secrets: "npm-api-key" - name: Download artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: workflow: build-cli.yml path: apps/cli/build @@ -282,7 +282,7 @@ jobs: - name: Dry Run - Download artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: workflow: build-cli.yml path: apps/cli/build diff --git a/.github/workflows/release-desktop-beta.yml b/.github/workflows/release-desktop-beta.yml index ce09a7d80ad..b2e568632b5 100644 --- a/.github/workflows/release-desktop-beta.yml +++ b/.github/workflows/release-desktop-beta.yml @@ -21,6 +21,7 @@ jobs: release-channel: ${{ steps.release-channel.outputs.channel }} branch-name: ${{ steps.branch.outputs.branch-name }} build_number: ${{ steps.increment-version.outputs.build_number }} + node_version: ${{ steps.retrieve-node-version.outputs.node_version }} steps: - name: Checkout repo uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 @@ -47,7 +48,7 @@ jobs: - name: Check Release Version id: version - uses: bitwarden/gh-actions/release-version-check@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/release-version-check@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: release-type: 'Initial Release' project-type: ts @@ -104,12 +105,20 @@ jobs: echo "branch-name=$branch_name" >> $GITHUB_OUTPUT + - name: Get Node Version + id: retrieve-node-version + run: | + NODE_NVMRC=$(cat .nvmrc) + NODE_VERSION=${NODE_NVMRC/v/''} + echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT + linux: name: Linux Build runs-on: ubuntu-20.04 needs: setup env: _PACKAGE_VERSION: ${{ needs.setup.outputs.release-version }} + _NODE_VERSION: ${{ needs.setup.outputs.node_version }} defaults: run: working-directory: apps/desktop @@ -124,7 +133,7 @@ jobs: with: cache: 'npm' cache-dependency-path: '**/package-lock.json' - node-version: '18' + node-version: ${{ env._NODE_VERSION }} - name: Set Node options run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV @@ -209,6 +218,7 @@ jobs: working-directory: apps/desktop env: _PACKAGE_VERSION: ${{ needs.setup.outputs.release-version }} + _NODE_VERSION: ${{ needs.setup.outputs.node_version }} steps: - name: Checkout repo uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 @@ -220,7 +230,7 @@ jobs: with: cache: 'npm' cache-dependency-path: '**/package-lock.json' - node-version: '18' + node-version: ${{ env._NODE_VERSION }} - name: Set Node options run: echo "NODE_OPTIONS=--max_old_space_size=4096" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append @@ -231,7 +241,7 @@ jobs: node-gyp install $(node -v) - name: Install AST - uses: bitwarden/gh-actions/install-ast@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/install-ast@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 - name: Set up environment run: choco install checksum --no-progress @@ -249,7 +259,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: "bitwarden-ci" secrets: "code-signing-vault-url, @@ -401,6 +411,7 @@ jobs: needs: setup env: _PACKAGE_VERSION: ${{ needs.setup.outputs.release-version }} + _NODE_VERSION: ${{ needs.setup.outputs.node_version }} defaults: run: working-directory: apps/desktop @@ -415,7 +426,7 @@ jobs: with: cache: 'npm' cache-dependency-path: '**/package-lock.json' - node-version: '18' + node-version: ${{ env._NODE_VERSION }} - name: Set Node options run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV @@ -530,6 +541,7 @@ jobs: - macos-build env: _PACKAGE_VERSION: ${{ needs.setup.outputs.release-version }} + _NODE_VERSION: ${{ needs.setup.outputs.node_version }} defaults: run: working-directory: apps/desktop @@ -544,7 +556,7 @@ jobs: with: cache: 'npm' cache-dependency-path: '**/package-lock.json' - node-version: '18' + node-version: ${{ env._NODE_VERSION }} - name: Set Node options run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV @@ -732,6 +744,7 @@ jobs: - macos-build env: _PACKAGE_VERSION: ${{ needs.setup.outputs.release-version }} + _NODE_VERSION: ${{ needs.setup.outputs.node_version }} defaults: run: working-directory: apps/desktop @@ -746,7 +759,7 @@ jobs: with: cache: 'npm' cache-dependency-path: '**/package-lock.json' - node-version: '18' + node-version: ${{ env._NODE_VERSION }} - name: Set Node options run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV @@ -932,7 +945,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: "bitwarden-ci" secrets: "aws-electron-access-id, diff --git a/.github/workflows/release-desktop.yml b/.github/workflows/release-desktop.yml index f60020c7327..28314e8e9c1 100644 --- a/.github/workflows/release-desktop.yml +++ b/.github/workflows/release-desktop.yml @@ -67,7 +67,7 @@ jobs: - name: Check Release Version id: version - uses: bitwarden/gh-actions/release-version-check@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/release-version-check@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: release-type: ${{ inputs.release_type }} project-type: ts @@ -110,7 +110,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: "bitwarden-ci" secrets: "aws-electron-access-id, @@ -123,7 +123,7 @@ jobs: - name: Download all artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: workflow: build-desktop.yml workflow_conclusion: success @@ -132,7 +132,7 @@ jobs: - name: Dry Run - Download all artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: workflow: build-desktop.yml workflow_conclusion: success @@ -185,7 +185,7 @@ jobs: --endpoint-url https://${CF_ACCOUNT}.r2.cloudflarestorage.com - name: Get checksum files - uses: bitwarden/gh-actions/get-checksum@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-checksum@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: packages_dir: "apps/desktop/artifacts" file_path: "apps/desktop/artifacts/sha256-checksums.txt" @@ -263,7 +263,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: "bitwarden-ci" secrets: "snapcraft-store-token" @@ -279,7 +279,7 @@ jobs: - name: Download Snap artifact if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: workflow: build-desktop.yml workflow_conclusion: success @@ -289,7 +289,7 @@ jobs: - name: Dry Run - Download Snap artifact if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: workflow: build-desktop.yml workflow_conclusion: success @@ -329,7 +329,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: "bitwarden-ci" secrets: "cli-choco-api-key" @@ -347,7 +347,7 @@ jobs: - name: Download choco artifact if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: workflow: build-desktop.yml workflow_conclusion: success @@ -357,7 +357,7 @@ jobs: - name: Dry Run - Download choco artifact if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: workflow: build-desktop.yml workflow_conclusion: success diff --git a/.github/workflows/release-web.yml b/.github/workflows/release-web.yml index 46113b94b40..cbf83dc9cdf 100644 --- a/.github/workflows/release-web.yml +++ b/.github/workflows/release-web.yml @@ -41,7 +41,7 @@ jobs: - name: Check Release Version id: version - uses: bitwarden/gh-actions/release-version-check@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/release-version-check@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: release-type: ${{ github.event.inputs.release_type }} project-type: ts @@ -130,7 +130,7 @@ jobs: - name: Retrieve bot secrets id: retrieve-bot-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: bitwarden-ci secrets: "github-pat-bitwarden-devops-bot-repo-scope" @@ -144,7 +144,7 @@ jobs: - name: Download latest cloud asset if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: workflow: build-web.yml path: assets @@ -154,7 +154,7 @@ jobs: - name: Dry Run - Download latest cloud asset if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: workflow: build-web.yml path: assets @@ -227,7 +227,7 @@ jobs: - name: Download latest build artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: workflow: build-web.yml path: apps/web/artifacts @@ -238,7 +238,7 @@ jobs: - name: Dry Run - Download latest build artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: workflow: build-web.yml path: apps/web/artifacts diff --git a/.github/workflows/staged-rollout-desktop.yml b/.github/workflows/staged-rollout-desktop.yml index b0c57e1a1be..a3eacb868fd 100644 --- a/.github/workflows/staged-rollout-desktop.yml +++ b/.github/workflows/staged-rollout-desktop.yml @@ -26,7 +26,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: "bitwarden-ci" secrets: "aws-electron-access-id, diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 55363a329ea..59f52bd1964 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,12 +27,19 @@ jobs: - name: Checkout repo uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: Get Node Version + id: retrieve-node-version + run: | + NODE_NVMRC=$(cat .nvmrc) + NODE_VERSION=${NODE_NVMRC/v/''} + echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT + - name: Set up Node uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 with: cache: 'npm' cache-dependency-path: '**/package-lock.json' - node-version: '18' + node-version: ${{ steps.retrieve-node-version.outputs.node_version }} - name: Print environment run: | diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index f50a6fe6cd5..14755097b0e 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -54,7 +54,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: keyvault: "bitwarden-ci" secrets: "github-gpg-private-key, github-gpg-private-key-passphrase" @@ -125,14 +125,14 @@ jobs: - name: Bump Browser Version - Manifest if: ${{ inputs.bump_browser == true }} - uses: bitwarden/gh-actions/version-bump@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/version-bump@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: version: ${{ inputs.version_number }} file_path: "apps/browser/src/manifest.json" - name: Bump Browser Version - Manifest v3 if: ${{ inputs.bump_browser == true }} - uses: bitwarden/gh-actions/version-bump@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/version-bump@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 with: version: ${{ inputs.version_number }} file_path: "apps/browser/src/manifest.v3.json" diff --git a/.github/workflows/workflow-linter.yml b/.github/workflows/workflow-linter.yml index f38d228dda6..49388c11f82 100644 --- a/.github/workflows/workflow-linter.yml +++ b/.github/workflows/workflow-linter.yml @@ -8,4 +8,4 @@ on: jobs: call-workflow: - uses: bitwarden/gh-actions/.github/workflows/workflow-linter.yml@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/.github/workflows/workflow-linter.yml@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 diff --git a/.storybook/main.ts b/.storybook/main.ts index acc6e2a56db..37339b7343c 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -4,6 +4,7 @@ import remarkGfm from "remark-gfm"; const config: StorybookConfig = { stories: [ + "../libs/auth/src/**/*.stories.@(js|jsx|ts|tsx)", "../libs/components/src/**/*.mdx", "../libs/components/src/**/*.stories.@(js|jsx|ts|tsx)", "../apps/web/src/**/*.mdx", diff --git a/apps/browser/config/base.json b/apps/browser/config/base.json index 81b11cd38b7..348f00d1f36 100644 --- a/apps/browser/config/base.json +++ b/apps/browser/config/base.json @@ -1,6 +1,7 @@ { "dev_flags": {}, "flags": { - "showPasswordless": true + "showPasswordless": true, + "enableCipherKeyEncryption": false } } diff --git a/apps/browser/config/development.json b/apps/browser/config/development.json index 972812a9c59..eafd0ffd878 100644 --- a/apps/browser/config/development.json +++ b/apps/browser/config/development.json @@ -6,6 +6,7 @@ } }, "flags": { - "showPasswordless": true + "showPasswordless": true, + "enableCipherKeyEncryption": false } } diff --git a/apps/browser/config/production.json b/apps/browser/config/production.json index b04d1531a2f..f57c3d9bc38 100644 --- a/apps/browser/config/production.json +++ b/apps/browser/config/production.json @@ -1,3 +1,5 @@ { - "flags": {} + "flags": { + "enableCipherKeyEncryption": false + } } diff --git a/apps/browser/package.json b/apps/browser/package.json index fb7b8ad19bf..4e17fd4288d 100644 --- a/apps/browser/package.json +++ b/apps/browser/package.json @@ -1,6 +1,6 @@ { "name": "@bitwarden/browser", - "version": "2023.9.1", + "version": "2023.9.2", "scripts": { "build": "webpack", "build:mv3": "cross-env MANIFEST_VERSION=3 webpack", diff --git a/apps/browser/src/_locales/ar/messages.json b/apps/browser/src/_locales/ar/messages.json index be4eaca46f7..ba917a9e681 100644 --- a/apps/browser/src/_locales/ar/messages.json +++ b/apps/browser/src/_locales/ar/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/az/messages.json b/apps/browser/src/_locales/az/messages.json index 774e3fd64cd..b784592a3b0 100644 --- a/apps/browser/src/_locales/az/messages.json +++ b/apps/browser/src/_locales/az/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Yığcamlaşdırmanı aç/bağla", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/be/messages.json b/apps/browser/src/_locales/be/messages.json index 2fc14ecb1fc..e941d525936 100644 --- a/apps/browser/src/_locales/be/messages.json +++ b/apps/browser/src/_locales/be/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/bg/messages.json b/apps/browser/src/_locales/bg/messages.json index 0bd4ba3b7f9..08451607d2b 100644 --- a/apps/browser/src/_locales/bg/messages.json +++ b/apps/browser/src/_locales/bg/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Превключване на свиването", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Псевдонимен домейн" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Записите с включено изискване за повторно въвеждане на главната парола не могат да бъдат попълвани автоматично при зареждане на страницата. Автоматичното попълване при зареждане на страницата е изключено.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Автоматичното попълване при зареждане на страницата използва настройката си по подразбиране.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Изключете повторното въвеждане на главната парола, за да редактирате това поле", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/bn/messages.json b/apps/browser/src/_locales/bn/messages.json index f57c4687ea3..edee2852116 100644 --- a/apps/browser/src/_locales/bn/messages.json +++ b/apps/browser/src/_locales/bn/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/bs/messages.json b/apps/browser/src/_locales/bs/messages.json index 1c930eeafc7..e984a88b7bc 100644 --- a/apps/browser/src/_locales/bs/messages.json +++ b/apps/browser/src/_locales/bs/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/ca/messages.json b/apps/browser/src/_locales/ca/messages.json index 41f022a4362..7839cceebcb 100644 --- a/apps/browser/src/_locales/ca/messages.json +++ b/apps/browser/src/_locales/ca/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Redueix/Amplia", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/cs/messages.json b/apps/browser/src/_locales/cs/messages.json index 27ddddb5124..71446db9f2c 100644 --- a/apps/browser/src/_locales/cs/messages.json +++ b/apps/browser/src/_locales/cs/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Přepnout sbalení", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Doména aliasu" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Položky se žádostí o změnu hlavního hesla nemohou být automaticky vyplněny při načítání stránky. Automatické vyplnění při načítání stránky je vypnuto.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Automatické vyplnění při načítání stránky bylo nastaveno na výchozí nastavení.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Pro úpravu tohoto pole vypněte požadavek na hlavní heslo", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/cy/messages.json b/apps/browser/src/_locales/cy/messages.json index c7817b42bce..7292370f533 100644 --- a/apps/browser/src/_locales/cy/messages.json +++ b/apps/browser/src/_locales/cy/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/da/messages.json b/apps/browser/src/_locales/da/messages.json index cce307701b2..1bc0ed79e5a 100644 --- a/apps/browser/src/_locales/da/messages.json +++ b/apps/browser/src/_locales/da/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Fold sammen/ud", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Aliasdomæne" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Emner, hvor der anmodes om hovedadgangskode igen, kan ikke autoudfyldes ved sideindlæsning. Autoudfyldning ved sideindlæsning er slået fra.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Autoudfyldning ved sideindlæsning sat til standardindstillingen.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Slå anmodning om hovedadgangskode igen fra for at redigere dette felt", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/de/messages.json b/apps/browser/src/_locales/de/messages.json index 1b3eb19ee8e..443d4294cd3 100644 --- a/apps/browser/src/_locales/de/messages.json +++ b/apps/browser/src/_locales/de/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Ein-/ausklappen", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias-Domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Einträge, die eine erneuten Abfrage des Master-Passworts verlangen, können nicht beim Laden einer Seite automatisch ausgefüllt werden. Auto-Ausfüllen beim Laden einer Seite deaktiviert.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-Ausfüllen beim Lader einer Seite wurde auf die Standardeinstellung gesetzt.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Deaktiviere die erneute Abfrage des Master-Passworts, um dieses Feld zu bearbeiten", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/el/messages.json b/apps/browser/src/_locales/el/messages.json index 552f0b14850..c0b349f8aff 100644 --- a/apps/browser/src/_locales/el/messages.json +++ b/apps/browser/src/_locales/el/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Εναλλαγή σύμπτυξης", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json index f8ffeff747e..22330901579 100644 --- a/apps/browser/src/_locales/en/messages.json +++ b/apps/browser/src/_locales/en/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Auto-fill" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "Generate password (copied)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "No matching logins" }, + "noCards": { + "message": "No cards" + }, + "noIdentities": { + "message": "No identities" + }, + "addLoginMenu": { + "message": "Add login" + }, + "addCardMenu": { + "message": "Add card" + }, + "addIdentityMenu": { + "message": "Add identity" + }, "unlockVaultMenu": { "message": "Unlock your vault" }, diff --git a/apps/browser/src/_locales/en_GB/messages.json b/apps/browser/src/_locales/en_GB/messages.json index 6307472164d..fbe9e4fc31e 100644 --- a/apps/browser/src/_locales/en_GB/messages.json +++ b/apps/browser/src/_locales/en_GB/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/en_IN/messages.json b/apps/browser/src/_locales/en_IN/messages.json index 8bdedacc45c..0ae234fbece 100644 --- a/apps/browser/src/_locales/en_IN/messages.json +++ b/apps/browser/src/_locales/en_IN/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/es/messages.json b/apps/browser/src/_locales/es/messages.json index 5890a499518..15f8b4fbefa 100644 --- a/apps/browser/src/_locales/es/messages.json +++ b/apps/browser/src/_locales/es/messages.json @@ -637,7 +637,7 @@ "message": "Unlock your Bitwarden vault to complete the auto-fill request." }, "notificationUnlock": { - "message": "Unlock" + "message": "Desbloquear" }, "enableContextMenuItem": { "message": "Mostrar las opciones de menú contextuales" @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/et/messages.json b/apps/browser/src/_locales/et/messages.json index c3d12a9b120..b799c3a63a3 100644 --- a/apps/browser/src/_locales/et/messages.json +++ b/apps/browser/src/_locales/et/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Peida", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domeen" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/eu/messages.json b/apps/browser/src/_locales/eu/messages.json index a57b243a923..6290304cda6 100644 --- a/apps/browser/src/_locales/eu/messages.json +++ b/apps/browser/src/_locales/eu/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/fa/messages.json b/apps/browser/src/_locales/fa/messages.json index a6c4f2652c0..250ca3631a5 100644 --- a/apps/browser/src/_locales/fa/messages.json +++ b/apps/browser/src/_locales/fa/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "باز و بسته کردن", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/fi/messages.json b/apps/browser/src/_locales/fi/messages.json index 81bf6c64322..3a829d4783d 100644 --- a/apps/browser/src/_locales/fi/messages.json +++ b/apps/browser/src/_locales/fi/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Laajenna tai supista", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Aliasverkkotunnus" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Kohteita, joille pääsalasanan uudelleenkysely on käytössä, ei voida täyttää automaattisesti sivujen avautuessa. Automaattinen täyttö sivujen avautuessa poistettiin käytöstä.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Automaattinen täyttö sivun avautuessa käyttää oletusasetusta.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Poista pääsalasanan uudelleenkysely käytöstä muokataksesi kenttää", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/fil/messages.json b/apps/browser/src/_locales/fil/messages.json index df4726ac9cb..a8673d001ae 100644 --- a/apps/browser/src/_locales/fil/messages.json +++ b/apps/browser/src/_locales/fil/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/fr/messages.json b/apps/browser/src/_locales/fr/messages.json index d4b04dfa24f..ba4d6a6dd86 100644 --- a/apps/browser/src/_locales/fr/messages.json +++ b/apps/browser/src/_locales/fr/messages.json @@ -339,7 +339,7 @@ "message": "Autre" }, "unlockMethodNeededToChangeTimeoutActionDesc": { - "message": "Set up an unlock method to change your vault timeout action." + "message": "Configurez une méthode de déverrouillage pour changer le délai d'attente de votre coffre." }, "rateExtension": { "message": "Noter l'extension" @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Domaine de l'alias" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Désactivez la resaisie du mot de passe maître pour éditer ce champ", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/gl/messages.json b/apps/browser/src/_locales/gl/messages.json index bf1eedd8261..f8ffeff747e 100644 --- a/apps/browser/src/_locales/gl/messages.json +++ b/apps/browser/src/_locales/gl/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/he/messages.json b/apps/browser/src/_locales/he/messages.json index 48d88f82d40..68f1ebc1218 100644 --- a/apps/browser/src/_locales/he/messages.json +++ b/apps/browser/src/_locales/he/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/hi/messages.json b/apps/browser/src/_locales/hi/messages.json index 2619e217370..2b99c964209 100644 --- a/apps/browser/src/_locales/hi/messages.json +++ b/apps/browser/src/_locales/hi/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "डोमेन उपनाम" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/hr/messages.json b/apps/browser/src/_locales/hr/messages.json index 9113a3b2687..b88c097804f 100644 --- a/apps/browser/src/_locales/hr/messages.json +++ b/apps/browser/src/_locales/hr/messages.json @@ -772,7 +772,7 @@ "message": "Značajka nije dostupna" }, "encryptionKeyMigrationRequired": { - "message": "Encryption key migration required. Please login through the web vault to update your encryption key." + "message": "Potrebna je migracija ključa za šifriranje. Prijavi se na web trezoru za ažuriranje ključa za šifriranje." }, "premiumMembership": { "message": "Premium članstvo" @@ -1992,7 +1992,7 @@ "message": "Izvoz osobnog trezora" }, "exportingIndividualVaultDescription": { - "message": "Only the individual vault items associated with $EMAIL$ will be exported. Organization vault items will not be included. Only vault item information will be exported and will not include associated attachments.", + "message": "Izvest će se samo stavke osobnog trezora povezanog s $EMAIL$. Stavke organizacijskog trezora neće biti uključene. Izvest će se samo informacija o stavci trezora bez pripadajućih podataka o povijesti lozinki i privitaka.", "placeholders": { "email": { "content": "$1", @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Sažmi/Proširi", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domene" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Stavke za koje je potrebna glavna lozinka neće se auto-ispuniti kod učitavanja stranice. Auto-ispuna pri učitavanju stranice je isključena.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-ispuna kod učitavanja stranice koristi zadane postavke.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Isključi traženje glavne lozinke za promjenu ovog polja", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/hu/messages.json b/apps/browser/src/_locales/hu/messages.json index 3b1c44dcfbb..efe6d260355 100644 --- a/apps/browser/src/_locales/hu/messages.json +++ b/apps/browser/src/_locales/hu/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Összezárás váltás", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Áldomain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "A mesterjelszót újra bekérő elemeket nem lehet automatikusan kitölteni az oldal betöltésekor. Az automatikus kitöltés az oldal betöltésekor kikapcsolásra kerül.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Az automatikus kitöltés az oldal betöltésekor az alapértelmezett beállítás használatára lett beállítva.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Kapcsoljuk ki a mesterjelszó újbóli bekérését a mező szerkesztéséhez.", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/id/messages.json b/apps/browser/src/_locales/id/messages.json index 3891b1ddc37..f3fdd1a7c27 100644 --- a/apps/browser/src/_locales/id/messages.json +++ b/apps/browser/src/_locales/id/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/it/messages.json b/apps/browser/src/_locales/it/messages.json index 9af1f04b8e2..691e2484cba 100644 --- a/apps/browser/src/_locales/it/messages.json +++ b/apps/browser/src/_locales/it/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Comprimi/espandi", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Dominio alias" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Gli elementi che richiedono di inserire la password principale di nuovo non possono essere riempiti automaticamente al caricamento della pagina.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Il riempimento automatico al caricamento della pagina impostata per usare l'impostazione predefinita.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Disattiva l'inserimento della password principale di nuovo per modificare questo campo", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/ja/messages.json b/apps/browser/src/_locales/ja/messages.json index e02207a0051..c3762ae4ef8 100644 --- a/apps/browser/src/_locales/ja/messages.json +++ b/apps/browser/src/_locales/ja/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "開く/閉じる", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "エイリアスドメイン" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "マスターパスワードの再入力を促すアイテムは、ページ読み込み時に自動入力できません。ページ読み込み時の自動入力をオフにしました。", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "ページ読み込み時の自動入力はデフォルトの設定を使うよう設定しました。", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "このフィールドを編集するには、マスターパスワードの再入力をオフにしてください", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/ka/messages.json b/apps/browser/src/_locales/ka/messages.json index c6503b69df3..50a25ad0dd9 100644 --- a/apps/browser/src/_locales/ka/messages.json +++ b/apps/browser/src/_locales/ka/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/km/messages.json b/apps/browser/src/_locales/km/messages.json index bf1eedd8261..f8ffeff747e 100644 --- a/apps/browser/src/_locales/km/messages.json +++ b/apps/browser/src/_locales/km/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/kn/messages.json b/apps/browser/src/_locales/kn/messages.json index c4f5aee4955..06f9461e5fd 100644 --- a/apps/browser/src/_locales/kn/messages.json +++ b/apps/browser/src/_locales/kn/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/ko/messages.json b/apps/browser/src/_locales/ko/messages.json index 795b47eca83..5921e579e24 100644 --- a/apps/browser/src/_locales/ko/messages.json +++ b/apps/browser/src/_locales/ko/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/lt/messages.json b/apps/browser/src/_locales/lt/messages.json index 8daba606fa6..425d0c98233 100644 --- a/apps/browser/src/_locales/lt/messages.json +++ b/apps/browser/src/_locales/lt/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/lv/messages.json b/apps/browser/src/_locales/lv/messages.json index f094022695c..624904d7213 100644 --- a/apps/browser/src/_locales/lv/messages.json +++ b/apps/browser/src/_locales/lv/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Pārslēgt sakļaušanu", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Aizstājdomēns" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Vienumus ar galvenās paroles pārvaicāšanu nevar automātiski aizpildīt lapas ielādes brīdī. Automātiskā aizpilde lapas ielādes brīdī ir izslēgta.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Automātiskā aizpilde lapas ielādes brīdī iestatīta izmantot noklusējuma iestatījumu.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Jāizslēdz galvenās paroles pārvaicāšana, lai labotu šo lauku", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/ml/messages.json b/apps/browser/src/_locales/ml/messages.json index 94e71f2d8f1..58d5b04fc8b 100644 --- a/apps/browser/src/_locales/ml/messages.json +++ b/apps/browser/src/_locales/ml/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/mr/messages.json b/apps/browser/src/_locales/mr/messages.json index 00a2e755376..8f8f58775f7 100644 --- a/apps/browser/src/_locales/mr/messages.json +++ b/apps/browser/src/_locales/mr/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/my/messages.json b/apps/browser/src/_locales/my/messages.json index bf1eedd8261..f8ffeff747e 100644 --- a/apps/browser/src/_locales/my/messages.json +++ b/apps/browser/src/_locales/my/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/nb/messages.json b/apps/browser/src/_locales/nb/messages.json index a69e43ddbd6..4dadbbc8a7b 100644 --- a/apps/browser/src/_locales/nb/messages.json +++ b/apps/browser/src/_locales/nb/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/ne/messages.json b/apps/browser/src/_locales/ne/messages.json index bf1eedd8261..f8ffeff747e 100644 --- a/apps/browser/src/_locales/ne/messages.json +++ b/apps/browser/src/_locales/ne/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/nl/messages.json b/apps/browser/src/_locales/nl/messages.json index d6dda3290e7..5915dad872a 100644 --- a/apps/browser/src/_locales/nl/messages.json +++ b/apps/browser/src/_locales/nl/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "In-/Uitklappen", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Aliasdomein" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/nn/messages.json b/apps/browser/src/_locales/nn/messages.json index bf1eedd8261..f8ffeff747e 100644 --- a/apps/browser/src/_locales/nn/messages.json +++ b/apps/browser/src/_locales/nn/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/or/messages.json b/apps/browser/src/_locales/or/messages.json index bf1eedd8261..f8ffeff747e 100644 --- a/apps/browser/src/_locales/or/messages.json +++ b/apps/browser/src/_locales/or/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/pl/messages.json b/apps/browser/src/_locales/pl/messages.json index 296c76ddbd1..2f28c87d801 100644 --- a/apps/browser/src/_locales/pl/messages.json +++ b/apps/browser/src/_locales/pl/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Zwiń/rozwiń", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Domena aliasu" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Elementy z pytaniem o hasło głównege nie mogą być automatycznie wypełniane przy wczytywaniu strony. Automatyczne wypełnianie po wczytywania strony zostało wyłączone.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Automatyczne wypełnianie przy wczytywaniu strony zostało ustawione, aby używać ustawień domyślnych.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Wyłącz prośbę o podanie hasła głównego, aby edytować to pole", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/pt_BR/messages.json b/apps/browser/src/_locales/pt_BR/messages.json index 89ba426c960..ed62f893a19 100644 --- a/apps/browser/src/_locales/pt_BR/messages.json +++ b/apps/browser/src/_locales/pt_BR/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/pt_PT/messages.json b/apps/browser/src/_locales/pt_PT/messages.json index 496350bb995..735edf60afe 100644 --- a/apps/browser/src/_locales/pt_PT/messages.json +++ b/apps/browser/src/_locales/pt_PT/messages.json @@ -781,7 +781,7 @@ "message": "Gerir subscrição" }, "premiumManageAlert": { - "message": "Pode gerir a sua subscrição no cofre Web bitwarden.com. Pretende visitar o site agora?" + "message": "Pode gerir a sua subscrição no cofre web em bitwarden.com. Pretende visitar o site agora?" }, "premiumRefresh": { "message": "Atualizar subscrição" @@ -814,7 +814,7 @@ "message": "Adquirir Premium" }, "premiumPurchaseAlert": { - "message": "Pode adquirir uma subscrição Premium no cofre Web bitwarden.com. Pretende visitar o site agora?" + "message": "Pode adquirir uma subscrição Premium no cofre web em bitwarden.com. Pretende visitar o site agora?" }, "premiumCurrentMember": { "message": "É um membro Premium!" @@ -930,7 +930,7 @@ "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." }, "duoOrganizationDesc": { - "message": "Verifique com a Duo Security para a sua organização utilizando a aplicação Duo Mobile, SMS, chamada telefónica, ou chave de segurança U2F.", + "message": "Proteja a sua organização com a Duo Security utilizando a aplicação Duo Mobile, SMS, chamada telefónica ou uma chave de segurança U2F.", "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." }, "webAuthnTitle": { @@ -1279,7 +1279,7 @@ "message": "Esta palavra-passe não foi encontrada em nenhuma violação de dados conhecida. A sua utilização deve ser segura." }, "baseDomain": { - "message": "Domínio base", + "message": "Domínio de base", "description": "Domain name. Ex. website.com" }, "domainName": { @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Alternar colapso", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias de domínio" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Os itens que voltem a pedir a palavra-passe mestra não podem ser preenchidos automaticamente no carregamento da página. Preenchimento automático no carregamento da página desativado.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Preenchimento automático no carregamento da página definido para utilizar a predefinição.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Desativar o pedido para reintroduzir a palavra-passe mestra para editar este campo", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/ro/messages.json b/apps/browser/src/_locales/ro/messages.json index cf8acef767b..f525f87b6c2 100644 --- a/apps/browser/src/_locales/ro/messages.json +++ b/apps/browser/src/_locales/ro/messages.json @@ -199,7 +199,7 @@ "message": "Centrul de Ajutor Bitwarden" }, "communityForums": { - "message": "Explorează forumurile comunității Bitwarden" + "message": "Explorați forumurile comunității Bitwarden" }, "contactSupport": { "message": "Contactați asistența Bitwarden" @@ -339,7 +339,7 @@ "message": "Altele" }, "unlockMethodNeededToChangeTimeoutActionDesc": { - "message": "Set up an unlock method to change your vault timeout action." + "message": "Configurați metoda de deblocare care să schimbe acțiunea de expirare a seifului." }, "rateExtension": { "message": "Evaluare extensie" @@ -634,7 +634,7 @@ "message": "Actualizare" }, "notificationUnlockDesc": { - "message": "Deblochează seiful Bitwarden pentru a finaliza solicitarea de completare automată." + "message": "Deblocați seiful Bitwarden pentru a finaliza solicitarea de auto-completare." }, "notificationUnlock": { "message": "Deblocare" @@ -772,7 +772,7 @@ "message": "Funcție indisponibilă" }, "encryptionKeyMigrationRequired": { - "message": "Encryption key migration required. Please login through the web vault to update your encryption key." + "message": "Este necesară migrarea cheilor de criptare. Autentificați-vă prin intermediul seifului web pentru a vă actualiza cheia de criptare." }, "premiumMembership": { "message": "Abonament Premium" @@ -796,7 +796,7 @@ "message": "1 GB spațiu de stocare criptat pentru atașamente de fișiere." }, "premiumSignUpTwoStepOptions": { - "message": "Proprietary two-step login options such as YubiKey and Duo." + "message": "Opțiuni brevetate de conectare cu doi factori, cum ar fi YubiKey și Duo." }, "ppremiumSignUpReports": { "message": "Rapoarte privind igiena parolelor, sănătatea contului și breșele de date pentru a vă păstra seiful în siguranță." @@ -985,10 +985,10 @@ "message": "Dacă se detectează un formular de autentificare, completați-l automat la încărcarea paginii web." }, "experimentalFeature": { - "message": "Site-urile web compromise sau nesigure pot exploata funcția de autocompletare la încărcarea paginii." + "message": "Site-urile web compromise sau nesigure pot profita de auto-completarea la încărcare." }, "learnMoreAboutAutofill": { - "message": "Learn more about auto-fill" + "message": "Mai multe informații despre auto-completare" }, "defaultAutoFillOnPageLoad": { "message": "Setarea implicită de completare automată pentru articole de conectare" @@ -1468,16 +1468,16 @@ "message": "Articolul s-a completat automat " }, "insecurePageWarning": { - "message": "Avertisment: Aceasta este o pagină HTTP nesecurizată și orice informație pe care o trimiteți poate fi văzută și modificată de alte persoane. Această Parolă a fost salvată inițial pe o pagină securizată (HTTPS)." + "message": "Avertisment: Acesta este un site HTTP nesecurizat. Orice informație transmisă poate fi vizualizată și modificată de alte persoane. Această autentificare a fost salvată inițial pe un site securizat (HTTPS)." }, "insecurePageWarningFillPrompt": { - "message": "Do you still wish to fill this login?" + "message": "Încă mai doriți să completați acest login?" }, "autofillIframeWarning": { - "message": "The form is hosted by a different domain than the URI of your saved login. Choose OK to auto-fill anyway, or Cancel to stop." + "message": "Formularul este găzduit pe un alt domeniu decât adresa URI de autentificare salvată. Alegeți OK pentru completarea automată oricum sau Anulare pentru a opri." }, "autofillIframeWarningTip": { - "message": "To prevent this warning in the future, save this URI, $HOSTNAME$, to your Bitwarden login item for this site.", + "message": "Pe viitor, pentru a evita acest avertisment, înregistrați acest URI, $HOSTNAME$, în login-ul Bitwarden pentru acest site.", "placeholders": { "hostname": { "content": "$1", @@ -1489,13 +1489,13 @@ "message": "Setare parolă principală" }, "currentMasterPass": { - "message": "Current master password" + "message": "Parola principală actuală" }, "newMasterPass": { - "message": "New master password" + "message": "Noua parolă principală" }, "confirmNewMasterPass": { - "message": "Confirm new master password" + "message": "Confirmați noua parolă principală" }, "masterPasswordPolicyInEffect": { "message": "Una sau mai multe politici ale organizației necesită ca parola principală să îndeplinească următoarele cerințe:" @@ -1606,10 +1606,10 @@ "message": "Biometria browserului nu este acceptată pe acest dispozitiv." }, "biometricsFailedTitle": { - "message": "Biometrics failed" + "message": "Biometrica a eșuat" }, "biometricsFailedDesc": { - "message": "Biometrics cannot be completed, consider using a master password or logging out. If this persists, please contact Bitwarden support." + "message": "Verificarea biometrică nu poate fi finalizată. Încercați parola principală sau deconectați-vă. Dacă problema persistă, vă rugăm să contactați serviciul de asistență Bitwarden." }, "nativeMessaginPermissionErrorTitle": { "message": "Permisiunea nu a fost furnizată" @@ -1884,7 +1884,7 @@ "message": "Parola principală a fost schimbată recent de către un administrator din organizație. Pentru a accesa seiful, trebuie să o actualizați acum. Continuarea vă va deconecta de la sesiunea curentă, cerându-vă să vă conectați din nou. Sesiunile active de pe alte dispozitive pot continua să rămână active timp de până la o oră." }, "updateWeakMasterPasswordWarning": { - "message": "Your master password does not meet one or more of your organization policies. In order to access the vault, you must update your master password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + "message": "Parola dvs. principală nu respectă una sau mai multe politici ale organizației. Pentru a accesa seiful, parola principală trebuie actualizată acum. În cazul în care continuați, veți fi deconectat din sesiunea curentă și va trebui să vă conectați din nou. Sesiunile active de pe alte dispozitive pot rămâne active timp de până la o oră." }, "resetPasswordPolicyAutoEnroll": { "message": "Înscrierea automată" @@ -1905,7 +1905,7 @@ "message": "Minute" }, "vaultTimeoutPolicyInEffect": { - "message": "Politicile organizației dvs vă afectează expirarea seifului. Timpul maxim permis de expirare a seifului este $HOURS$ oră (ore) și $MINUTES$ minut(e)", + "message": "Politicile organizației dvs. au stabilit timpul maxim de expirare permis pentru seif la $HOURS$ oră/ore și $MINUTES$ de minut(e).", "placeholders": { "hours": { "content": "$1", @@ -1918,7 +1918,7 @@ } }, "vaultTimeoutPolicyWithActionInEffect": { - "message": "Your organization policies are affecting your vault timeout. Maximum allowed vault timeout is $HOURS$ hour(s) and $MINUTES$ minute(s). Your vault timeout action is set to $ACTION$.", + "message": "Politicile organizației dvs. afectează timpul de expirare al seifului. Timpul maxim de așteptare permis pentru seif este de $HOURS$ oră(e) și $MINUTES$ minut(e). Acțiunea de temporizare a seifului este setată la $ACTION$.", "placeholders": { "hours": { "content": "$1", @@ -1935,7 +1935,7 @@ } }, "vaultTimeoutActionPolicyInEffect": { - "message": "Your organization policies have set your vault timeout action to $ACTION$.", + "message": "Politicile organizației dvs. au setat acțiunea de expirare a seifului la $ACTION$.", "placeholders": { "action": { "content": "$1", @@ -1992,7 +1992,7 @@ "message": "Exportul seifului individual" }, "exportingIndividualVaultDescription": { - "message": "Only the individual vault items associated with $EMAIL$ will be exported. Organization vault items will not be included. Only vault item information will be exported and will not include associated attachments.", + "message": "Se exportă numai intrările din seiful personal asociate cu $EMAIL$. Nu sunt incluse intrările de seif ale organizației. Se exportă numai informațiile despre intrările din seif. Acestea nu includ atașamentele asociate.", "placeholders": { "email": { "content": "$1", @@ -2093,7 +2093,7 @@ "message": "Versiune server" }, "selfHostedServer": { - "message": "self-hosted" + "message": "auto-găzduit" }, "thirdParty": { "message": "Parte terță" @@ -2132,52 +2132,52 @@ "message": "Memorare e-mail" }, "loginWithDevice": { - "message": "Log in with device" + "message": "Conectați-vă cu dispozitivul" }, "loginWithDeviceEnabledInfo": { - "message": "Log in with device must be set up in the settings of the Bitwarden app. Need another option?" + "message": "Conectarea cu dispozitivul trebuie să fie configurată în setările aplicației Bitwarden. Aveți nevoie de o altă opțiune?" }, "fingerprintPhraseHeader": { - "message": "Fingerprint phrase" + "message": "Fraza amprentă" }, "fingerprintMatchInfo": { - "message": "Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device." + "message": "Asigurați-vă că seiful este deblocat și că fraza amprentă se potrivește cu cea de pe celălalt dispozitiv." }, "resendNotification": { - "message": "Resend notification" + "message": "Reîntoarceți notificarea" }, "viewAllLoginOptions": { - "message": "View all log in options" + "message": "Afișați toate opțiunile de conectare" }, "notificationSentDevice": { - "message": "A notification has been sent to your device." + "message": "O notificare a fost trimisă pe dispozitivul dvs." }, "loginInitiated": { - "message": "Login initiated" + "message": "Conectare inițiată" }, "exposedMasterPassword": { - "message": "Exposed Master Password" + "message": "Parolă principală compromisă" }, "exposedMasterPasswordDesc": { - "message": "Password found in a data breach. Use a unique password to protect your account. Are you sure you want to use an exposed password?" + "message": "Parola găsită în scurgerea de date. Folosiți o parolă unică pentru a vă proteja contul. Sunteți sigur că doriți să folosiți o parolă compromisă?" }, "weakAndExposedMasterPassword": { - "message": "Weak and Exposed Master Password" + "message": "Parolă principală slabă și compromisă" }, "weakAndBreachedMasterPasswordDesc": { - "message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?" + "message": "Parolă slabă identificată și găsită într-o scurgere de date. Folosiți o parolă puternică și unică pentru a vă proteja contul. Sunteți sigur că doriți să utilizați această parolă?" }, "checkForBreaches": { - "message": "Check known data breaches for this password" + "message": "Verificați scurgerile de date cunoscute pentru această parolă" }, "important": { "message": "Important:" }, "masterPasswordHint": { - "message": "Your master password cannot be recovered if you forget it!" + "message": "Parola principală nu poate fi recuperată dacă este uitată!" }, "characterMinimum": { - "message": "$LENGTH$ character minimum", + "message": "Minim $LENGTH$ caractere", "placeholders": { "length": { "content": "$1", @@ -2186,13 +2186,13 @@ } }, "autofillPageLoadPolicyActivated": { - "message": "Your organization policies have turned on auto-fill on page load." + "message": "Politicile organizației dvs. au activat auto-completarea la încărcarea paginii." }, "howToAutofill": { - "message": "How to auto-fill" + "message": "Instrucțiuni de auto-completare" }, "autofillSelectInfoWithCommand": { - "message": "Select an item from this page or use the shortcut: $COMMAND$", + "message": "Selectați un element din această pagină sau utilizați comanda rapidă: $COMMAND$", "placeholders": { "command": { "content": "$1", @@ -2201,22 +2201,22 @@ } }, "autofillSelectInfoWithoutCommand": { - "message": "Select an item from this page or set a shortcut in settings." + "message": "Selectați un element din această pagină sau setați o comandă rapidă în setări." }, "gotIt": { - "message": "Got it" + "message": "Am înțeles" }, "autofillSettings": { - "message": "Auto-fill settings" + "message": "Setări de auto-completare" }, "autofillShortcut": { - "message": "Auto-fill keyboard shortcut" + "message": "Scurtătură de tastatură pentru auto-completare" }, "autofillShortcutNotSet": { - "message": "The auto-fill shortcut is not set. Change this in the browser's settings." + "message": "Scurtătura de auto-completare nu este setată. Modificați acest lucru în setările browserului." }, "autofillShortcutText": { - "message": "The auto-fill shortcut is: $COMMAND$. Change this in the browser's settings.", + "message": "Scurtătura de auto-completare este: $COMMAND$. Modificați acest lucru în setările browserului.", "placeholders": { "command": { "content": "$1", @@ -2225,7 +2225,7 @@ } }, "autofillShortcutTextSafari": { - "message": "Default auto-fill shortcut: $COMMAND$.", + "message": "Scurtătură implicită de auto-completare: $COMMAND$.", "placeholders": { "command": { "content": "$1", @@ -2234,31 +2234,31 @@ } }, "loggingInOn": { - "message": "Logging in on" + "message": "Conectare la" }, "opensInANewWindow": { - "message": "Opens in a new window" + "message": "Se deschide într-o nouă fereastră" }, "deviceApprovalRequired": { - "message": "Device approval required. Select an approval option below:" + "message": "Este necesară aprobarea dispozitivului. Selectați o opțiune de autorizare de mai jos:" }, "rememberThisDevice": { - "message": "Remember this device" + "message": "Memorizează acest dispozitiv" }, "uncheckIfPublicDevice": { - "message": "Uncheck if using a public device" + "message": "Debifați dacă utilizați un dispozitiv public" }, "approveFromYourOtherDevice": { - "message": "Approve from your other device" + "message": "Aprobați de pe celălalt dispozitiv" }, "requestAdminApproval": { - "message": "Request admin approval" + "message": "Cereți aprobarea administratorului" }, "approveWithMasterPassword": { - "message": "Approve with master password" + "message": "Aprobați cu parola principală" }, "ssoIdentifierRequired": { - "message": "Organization SSO identifier is required." + "message": "Identificatorul SSO al organizației este necesar." }, "eu": { "message": "EU", @@ -2271,49 +2271,49 @@ "message": "bitwarden.eu" }, "accessDenied": { - "message": "Access denied. You do not have permission to view this page." + "message": "Acces refuzat. Nu aveți permisiunea de a vizualiza această pagină." }, "general": { "message": "General" }, "display": { - "message": "Display" + "message": "Afișare" }, "accountSuccessfullyCreated": { - "message": "Account successfully created!" + "message": "Cont creat cu succes!" }, "adminApprovalRequested": { - "message": "Admin approval requested" + "message": "Autorizație administrativă solicitată" }, "adminApprovalRequestSentToAdmins": { - "message": "Your request has been sent to your admin." + "message": "Cererea dvs. a fost trimisă administratorului." }, "youWillBeNotifiedOnceApproved": { - "message": "You will be notified once approved." + "message": "Veți primi o notificare după aprobare." }, "troubleLoggingIn": { - "message": "Trouble logging in?" + "message": "Aveți probleme la logare?" }, "loginApproved": { - "message": "Login approved" + "message": "Autentificare aprobată" }, "userEmailMissing": { - "message": "User email missing" + "message": "Lipsește e-mailul utilizatorului" }, "deviceTrusted": { - "message": "Device trusted" + "message": "Dispozitiv de încredere" }, "inputRequired": { - "message": "Input is required." + "message": "Este necesară o intrare." }, "required": { - "message": "required" + "message": "necesar" }, "search": { - "message": "Search" + "message": "Căutare" }, "inputMinLength": { - "message": "Input must be at least $COUNT$ characters long.", + "message": "Intrarea trebuie să aibă o lungime de cel puțin $COUNT$ caractere.", "placeholders": { "count": { "content": "$1", @@ -2322,7 +2322,7 @@ } }, "inputMaxLength": { - "message": "Input must not exceed $COUNT$ characters in length.", + "message": "Intrarea nu trebuie să fie mai lungă de $COUNT$ caractere.", "placeholders": { "count": { "content": "$1", @@ -2331,7 +2331,7 @@ } }, "inputForbiddenCharacters": { - "message": "The following characters are not allowed: $CHARACTERS$", + "message": "Următoarele caractere nu sunt permise: $CHARACTERS$", "placeholders": { "characters": { "content": "$1", @@ -2340,7 +2340,7 @@ } }, "inputMinValue": { - "message": "Input value must be at least $MIN$.", + "message": "Valoarea de intrare trebuie să fie cel puțin $MIN$.", "placeholders": { "min": { "content": "$1", @@ -2349,7 +2349,7 @@ } }, "inputMaxValue": { - "message": "Input value must not exceed $MAX$.", + "message": "Valoarea de intrare nu trebuie să depășească $MAX$.", "placeholders": { "max": { "content": "$1", @@ -2358,17 +2358,17 @@ } }, "multipleInputEmails": { - "message": "1 or more emails are invalid" + "message": "1 sau mai multe e-mailuri sunt invalide" }, "inputTrimValidator": { - "message": "Input must not contain only whitespace.", + "message": "Datele introduse nu trebuie să conțină numai spații.", "description": "Notification to inform the user that a form's input can't contain only whitespace." }, "inputEmail": { - "message": "Input is not an email address." + "message": "Intrarea nu este o adresă de e-mail." }, "fieldsNeedAttention": { - "message": "$COUNT$ field(s) above need your attention.", + "message": "$COUNT$ câmp(uri) de mai sus necesită atenție.", "placeholders": { "count": { "content": "$1", @@ -2377,22 +2377,22 @@ } }, "selectPlaceholder": { - "message": "-- Select --" + "message": "-- Selectați --" }, "multiSelectPlaceholder": { - "message": "-- Type to filter --" + "message": "-- Scrieți pentru a filtra --" }, "multiSelectLoading": { - "message": "Retrieving options..." + "message": "Recuperarea opțiunilor..." }, "multiSelectNotFound": { - "message": "No items found" + "message": "Niciun element găsit" }, "multiSelectClearAll": { - "message": "Clear all" + "message": "Ștergeți tot" }, "plusNMore": { - "message": "+ $QUANTITY$ more", + "message": "+ $QUANTITY$ mai mult", "placeholders": { "quantity": { "content": "$1", @@ -2401,10 +2401,25 @@ } }, "submenu": { - "message": "Submenu" + "message": "Submeniu" }, "toggleCollapse": { - "message": "Toggle collapse", + "message": "Comutare restrângere", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Elementele în care parola principală este solicitată din nou nu pot fi completate automat la încărcarea paginii. Completarea automată la încărcarea paginii este dezactivată.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Completarea automată la încărcarea paginii este setată la valoarea implicită.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Dezactivați reintroducerea parolei principale pentru a edita acest câmp", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/ru/messages.json b/apps/browser/src/_locales/ru/messages.json index 5dfbe64abc8..40452e56dce 100644 --- a/apps/browser/src/_locales/ru/messages.json +++ b/apps/browser/src/_locales/ru/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Свернуть/развернуть", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Псевдоним домена" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Элементы с повторным запросом мастер-пароля не могут быть автоматически заполнены при загрузке страницы. Автозаполнение при загрузке страницы выключено.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Автозаполнение при загрузке страницы использует настройку по умолчанию.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Для редактирования этого поля отключите повторный запрос мастер-пароля", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/si/messages.json b/apps/browser/src/_locales/si/messages.json index 2c9a44b2afe..04f2a619a82 100644 --- a/apps/browser/src/_locales/si/messages.json +++ b/apps/browser/src/_locales/si/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/sk/messages.json b/apps/browser/src/_locales/sk/messages.json index 405402ccac7..684c677c45b 100644 --- a/apps/browser/src/_locales/sk/messages.json +++ b/apps/browser/src/_locales/sk/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Prepnúť zbalenie", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias doména" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Položky, ktoré vyžadujú opätovné zadanie hlavného hesla sa nedajú automaticky vyplniť pri načítaní stránky. Automatické vypĺňanie pri načítaní stránky je vypnuté.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Automatické vypĺňanie pri načítaní stránky nastavené na pôvodnú predvoľbu.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Vypnite výzvu na opätovné zadanie hlavného hesla na úpravu tohto poľa", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/sl/messages.json b/apps/browser/src/_locales/sl/messages.json index ee581226b0c..8878c308045 100644 --- a/apps/browser/src/_locales/sl/messages.json +++ b/apps/browser/src/_locales/sl/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/sr/messages.json b/apps/browser/src/_locales/sr/messages.json index a75cd39ebca..46e96c7d8df 100644 --- a/apps/browser/src/_locales/sr/messages.json +++ b/apps/browser/src/_locales/sr/messages.json @@ -772,7 +772,7 @@ "message": "Функција је недоступна" }, "encryptionKeyMigrationRequired": { - "message": "Encryption key migration required. Please login through the web vault to update your encryption key." + "message": "Потребна је миграција кључа за шифровање. Пријавите се преко веб сефа да бисте ажурирали кључ за шифровање." }, "premiumMembership": { "message": "Премијум чланство" @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Промени проширење", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Ставке са упитом за поновно постављање главне лозинке не могу се ауто-попунити при учитавању странице. Ауто-попуњавање при учитавању странице је искључено.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Ауто-попуњавање при учитавању странице је подешено да користи подразумевано подешавање.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Искључите поновни упит главне лозинке да бисте уредили ово поље", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/sv/messages.json b/apps/browser/src/_locales/sv/messages.json index 7a4816dfa96..680a3aac0bd 100644 --- a/apps/browser/src/_locales/sv/messages.json +++ b/apps/browser/src/_locales/sv/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Aliasdomän" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/te/messages.json b/apps/browser/src/_locales/te/messages.json index bf1eedd8261..f8ffeff747e 100644 --- a/apps/browser/src/_locales/te/messages.json +++ b/apps/browser/src/_locales/te/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/th/messages.json b/apps/browser/src/_locales/th/messages.json index 20e234e4f8f..0db240ea797 100644 --- a/apps/browser/src/_locales/th/messages.json +++ b/apps/browser/src/_locales/th/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/tr/messages.json b/apps/browser/src/_locales/tr/messages.json index f40c94f1222..e52a2f59f26 100644 --- a/apps/browser/src/_locales/tr/messages.json +++ b/apps/browser/src/_locales/tr/messages.json @@ -339,7 +339,7 @@ "message": "Diğer" }, "unlockMethodNeededToChangeTimeoutActionDesc": { - "message": "Set up an unlock method to change your vault timeout action." + "message": "Kasa zaman aşımı eyleminizi değiştirmek için kilit açma yönteminizi ayarlayın." }, "rateExtension": { "message": "Uzantıyı değerlendirin" @@ -2277,7 +2277,7 @@ "message": "Genel" }, "display": { - "message": "Display" + "message": "Görünüm" }, "accountSuccessfullyCreated": { "message": "Hesap başarıyla oluşturuldu!" @@ -2304,16 +2304,16 @@ "message": "Cihaza güvenildi" }, "inputRequired": { - "message": "Input is required." + "message": "Girdi gerekli." }, "required": { - "message": "required" + "message": "gerekli" }, "search": { "message": "Ara" }, "inputMinLength": { - "message": "Input must be at least $COUNT$ characters long.", + "message": "Girdi en az $COUNT$ karakter uzunluğunda olmalıdır.", "placeholders": { "count": { "content": "$1", @@ -2322,7 +2322,7 @@ } }, "inputMaxLength": { - "message": "Input must not exceed $COUNT$ characters in length.", + "message": "Girdi $COUNT$ karakter uzunluğunu geçmemelidir.", "placeholders": { "count": { "content": "$1", @@ -2331,7 +2331,7 @@ } }, "inputForbiddenCharacters": { - "message": "The following characters are not allowed: $CHARACTERS$", + "message": "Şu karakterlere izin verilmez: $CHARACTERS$", "placeholders": { "characters": { "content": "$1", @@ -2349,7 +2349,7 @@ } }, "inputMaxValue": { - "message": "Input value must not exceed $MAX$.", + "message": "Girdi değeri en fazla $MAX$ olmalı.", "placeholders": { "max": { "content": "$1", @@ -2358,17 +2358,17 @@ } }, "multipleInputEmails": { - "message": "1 or more emails are invalid" + "message": "Bir veya daha fazla e-posta geçersiz" }, "inputTrimValidator": { - "message": "Input must not contain only whitespace.", + "message": "Girdi yalnızca boşluktan ibaret olamaz.", "description": "Notification to inform the user that a form's input can't contain only whitespace." }, "inputEmail": { - "message": "Input is not an email address." + "message": "Girdi bir e-posta adresi değil." }, "fieldsNeedAttention": { - "message": "$COUNT$ field(s) above need your attention.", + "message": "Yukarıdaki $COUNT$ alanla ilgilenmeniz gerekiyor.", "placeholders": { "count": { "content": "$1", @@ -2377,13 +2377,13 @@ } }, "selectPlaceholder": { - "message": "-- Select --" + "message": "-- Seçin --" }, "multiSelectPlaceholder": { - "message": "-- Type to filter --" + "message": "-- Filtrelemek için yazın --" }, "multiSelectLoading": { - "message": "Retrieving options..." + "message": "Seçenekler alınıyor..." }, "multiSelectNotFound": { "message": "Hiç kayıt bulunamadı" @@ -2392,7 +2392,7 @@ "message": "Tümünü temizle" }, "plusNMore": { - "message": "+ $QUANTITY$ more", + "message": "+ $QUANTITY$ tane daha", "placeholders": { "quantity": { "content": "$1", @@ -2401,10 +2401,25 @@ } }, "submenu": { - "message": "Submenu" + "message": "Alt menü" }, "toggleCollapse": { - "message": "Toggle collapse", + "message": "Daraltmayı aç/kapat", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias alan adı" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Ana parolayı yeniden isteyen kayıtlar sayfa yüklendiğinde otomatik olarak doldurulamaz. Sayfa yüklendiğinde otomatik doldurma kapatıldı.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Sayfa yüklendiğinde otomatik doldurma, varsayılan ayarı kullanacak şekilde ayarlandı.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Bu alanı düzenlemek için ana parolayı yeniden istemeyi kapatın", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/uk/messages.json b/apps/browser/src/_locales/uk/messages.json index 88a9dd902d2..6cb70bd76bd 100644 --- a/apps/browser/src/_locales/uk/messages.json +++ b/apps/browser/src/_locales/uk/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Згорнути/розгорнути", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/vi/messages.json b/apps/browser/src/_locales/vi/messages.json index 7f256311f16..e562a0b5d5d 100644 --- a/apps/browser/src/_locales/vi/messages.json +++ b/apps/browser/src/_locales/vi/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "Auto-fill on page load set to use default setting.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Turn off master password re-prompt to edit this field", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/zh_CN/messages.json b/apps/browser/src/_locales/zh_CN/messages.json index 04c9d9484c6..b1d0aac7e4a 100644 --- a/apps/browser/src/_locales/zh_CN/messages.json +++ b/apps/browser/src/_locales/zh_CN/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "切换折叠", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "别名域" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "具有主密码重新提示的项目无法在页面加载时自动填充。页面加载时的自动填充功能已关闭。", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "页面加载时自动填充设置为默认设置。", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "关闭主密码重新提示以编辑此字段", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/_locales/zh_TW/messages.json b/apps/browser/src/_locales/zh_TW/messages.json index 3612d93edb3..58ca526bc68 100644 --- a/apps/browser/src/_locales/zh_TW/messages.json +++ b/apps/browser/src/_locales/zh_TW/messages.json @@ -2406,5 +2406,20 @@ "toggleCollapse": { "message": "Toggle collapse", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Alias domain" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "使用主密碼重新提示的項目無法在頁面加載時自動填寫。已關閉頁面加載時的自動填入。", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "將頁面加載時的自動填入設置為使用默認設定。", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "關閉主密碼重新提示以編輯此欄位", + "description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item." } } diff --git a/apps/browser/src/autofill/background/notification.background.ts b/apps/browser/src/autofill/background/notification.background.ts index 1cb006fa3a2..73bdc2cd16f 100644 --- a/apps/browser/src/autofill/background/notification.background.ts +++ b/apps/browser/src/autofill/background/notification.background.ts @@ -464,7 +464,7 @@ export default class NotificationBackground { private async getDecryptedCipherById(cipherId: string) { const cipher = await this.cipherService.get(cipherId); if (cipher != null && cipher.type === CipherType.Login) { - return await cipher.decrypt(); + return await cipher.decrypt(await this.cipherService.getKeyForCipherKeyDecryption(cipher)); } return null; } diff --git a/apps/browser/src/autofill/browser/cipher-context-menu-handler.spec.ts b/apps/browser/src/autofill/browser/cipher-context-menu-handler.spec.ts index d7cac8d44b2..4532718809e 100644 --- a/apps/browser/src/autofill/browser/cipher-context-menu-handler.spec.ts +++ b/apps/browser/src/autofill/browser/cipher-context-menu-handler.spec.ts @@ -69,19 +69,20 @@ describe("CipherContextMenuHandler", () => { expect(mainContextMenuHandler.noLogins).toHaveBeenCalledTimes(1); }); - it("only adds login ciphers including ciphers that require reprompt", async () => { + it("only adds autofill ciphers including ciphers that require reprompt", async () => { authService.getAuthStatus.mockResolvedValue(AuthenticationStatus.Unlocked); mainContextMenuHandler.init.mockResolvedValue(true); - const realCipher = { + const loginCipher = { id: "5", type: CipherType.Login, reprompt: CipherRepromptType.None, name: "Test Cipher", login: { username: "Test Username" }, }; - const repromptCipher = { + + const repromptLoginCipher = { id: "6", type: CipherType.Login, reprompt: CipherRepromptType.Password, @@ -89,34 +90,49 @@ describe("CipherContextMenuHandler", () => { login: { username: "Test Username" }, }; + const cardCipher = { + id: "7", + type: CipherType.Card, + name: "Test Card Cipher", + card: { username: "Test Username" }, + }; + cipherService.getAllDecryptedForUrl.mockResolvedValue([ null, // invalid cipher undefined, // invalid cipher - { type: CipherType.Card }, // invalid cipher - realCipher, // valid cipher - repromptCipher, + { type: CipherType.SecureNote }, // invalid cipher + loginCipher, // valid cipher + repromptLoginCipher, + cardCipher, // valid cipher ] as any[]); await sut.update("https://test.com"); expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledTimes(1); - expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledWith("https://test.com"); + expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledWith("https://test.com", [ + CipherType.Card, + CipherType.Identity, + ]); - expect(mainContextMenuHandler.loadOptions).toHaveBeenCalledTimes(2); + expect(mainContextMenuHandler.loadOptions).toHaveBeenCalledTimes(3); expect(mainContextMenuHandler.loadOptions).toHaveBeenCalledWith( "Test Cipher (Test Username)", "5", - "https://test.com", - realCipher + loginCipher ); expect(mainContextMenuHandler.loadOptions).toHaveBeenCalledWith( "Test Reprompt Cipher (Test Username)", "6", - "https://test.com", - repromptCipher + repromptLoginCipher + ); + + expect(mainContextMenuHandler.loadOptions).toHaveBeenCalledWith( + "Test Card Cipher", + "7", + cardCipher ); }); }); diff --git a/apps/browser/src/autofill/browser/cipher-context-menu-handler.ts b/apps/browser/src/autofill/browser/cipher-context-menu-handler.ts index 6140db260f5..f46442c4192 100644 --- a/apps/browser/src/autofill/browser/cipher-context-menu-handler.ts +++ b/apps/browser/src/autofill/browser/cipher-context-menu-handler.ts @@ -18,6 +18,7 @@ import { cipherServiceFactory, CipherServiceInitOptions, } from "../../vault/background/service_factories/cipher-service.factory"; +import { AutofillCipherTypeId } from "../types"; import { MainContextMenuHandler } from "./main-context-menu-handler"; @@ -159,29 +160,67 @@ export class CipherContextMenuHandler { return; } - const ciphers = await this.cipherService.getAllDecryptedForUrl(url); + const ciphers = await this.cipherService.getAllDecryptedForUrl(url, [ + CipherType.Card, + CipherType.Identity, + ]); ciphers.sort((a, b) => this.cipherService.sortCiphersByLastUsedThenName(a, b)); - if (ciphers.length === 0) { - await this.mainContextMenuHandler.noLogins(url); - return; + const groupedCiphers: Record = ciphers.reduce( + (ciphersByType, cipher) => { + if (!cipher?.type) { + return ciphersByType; + } + + const existingCiphersOfType = ciphersByType[cipher.type as AutofillCipherTypeId] || []; + + return { + ...ciphersByType, + [cipher.type]: [...existingCiphersOfType, cipher], + }; + }, + { + [CipherType.Login]: [], + [CipherType.Card]: [], + [CipherType.Identity]: [], + } + ); + + if (groupedCiphers[CipherType.Login].length === 0) { + await this.mainContextMenuHandler.noLogins(); + } + + if (groupedCiphers[CipherType.Identity].length === 0) { + await this.mainContextMenuHandler.noIdentities(); + } + + if (groupedCiphers[CipherType.Card].length === 0) { + await this.mainContextMenuHandler.noCards(); } for (const cipher of ciphers) { - await this.updateForCipher(url, cipher); + await this.updateForCipher(cipher); } } - private async updateForCipher(url: string, cipher: CipherView) { - if (cipher == null || cipher.type !== CipherType.Login) { + private async updateForCipher(cipher: CipherView) { + if ( + cipher == null || + !new Set([CipherType.Login, CipherType.Card, CipherType.Identity]).has(cipher.type) + ) { return; } let title = cipher.name; - if (!Utils.isNullOrEmpty(title)) { + + if (cipher.type === CipherType.Login && !Utils.isNullOrEmpty(title) && cipher.login?.username) { title += ` (${cipher.login.username})`; } - await this.mainContextMenuHandler.loadOptions(title, cipher.id, url, cipher); + if (cipher.type === CipherType.Card && cipher.card?.subTitle) { + title += ` ${cipher.card.subTitle}`; + } + + await this.mainContextMenuHandler.loadOptions(title, cipher.id, cipher); } } diff --git a/apps/browser/src/autofill/browser/context-menu-clicked-handler.spec.ts b/apps/browser/src/autofill/browser/context-menu-clicked-handler.spec.ts index 021d15df89e..5c6b5e07da3 100644 --- a/apps/browser/src/autofill/browser/context-menu-clicked-handler.spec.ts +++ b/apps/browser/src/autofill/browser/context-menu-clicked-handler.spec.ts @@ -4,12 +4,22 @@ import { EventCollectionService } from "@bitwarden/common/abstractions/event/eve import { TotpService } from "@bitwarden/common/abstractions/totp.service"; import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction"; +import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type"; import { CipherType } from "@bitwarden/common/vault/enums/cipher-type"; import { Cipher } from "@bitwarden/common/vault/models/domain/cipher"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; +import { + AUTOFILL_ID, + COPY_PASSWORD_ID, + COPY_USERNAME_ID, + COPY_VERIFICATIONCODE_ID, + GENERATE_PASSWORD_ID, + NOOP_COMMAND_SUFFIX, +} from "../constants"; + import { CopyToClipboardAction, ContextMenuClickedHandler, @@ -17,13 +27,6 @@ import { GeneratePasswordToClipboardAction, AutofillAction, } from "./context-menu-clicked-handler"; -import { - AUTOFILL_ID, - COPY_PASSWORD_ID, - COPY_USERNAME_ID, - COPY_VERIFICATIONCODE_ID, - GENERATE_PASSWORD_ID, -} from "./main-context-menu-handler"; describe("ContextMenuClickedHandler", () => { const createData = ( @@ -51,6 +54,7 @@ describe("ContextMenuClickedHandler", () => { type: CipherType.Login, } as any) ); + cipherView.login.username = username ?? "USERNAME"; cipherView.login.password = password ?? "PASSWORD"; cipherView.login.totp = totp ?? "TOTP"; @@ -62,6 +66,7 @@ describe("ContextMenuClickedHandler", () => { let autofill: AutofillAction; let authService: MockProxy; let cipherService: MockProxy; + let stateService: MockProxy; let totpService: MockProxy; let eventCollectionService: MockProxy; let userVerificationService: MockProxy; @@ -74,6 +79,7 @@ describe("ContextMenuClickedHandler", () => { autofill = jest.fn, [tab: chrome.tabs.Tab, cipher: CipherView]>(); authService = mock(); cipherService = mock(); + stateService = mock(); totpService = mock(); eventCollectionService = mock(); @@ -83,6 +89,7 @@ describe("ContextMenuClickedHandler", () => { autofill, authService, cipherService, + stateService, totpService, eventCollectionService, userVerificationService @@ -106,7 +113,7 @@ describe("ContextMenuClickedHandler", () => { const cipher = createCipher(); cipherService.getAllDecrypted.mockResolvedValue([cipher]); - await sut.run(createData("T_1", AUTOFILL_ID), { id: 5 } as any); + await sut.run(createData(`${AUTOFILL_ID}_1`, AUTOFILL_ID), { id: 5 } as any); expect(autofill).toBeCalledTimes(1); @@ -118,11 +125,16 @@ describe("ContextMenuClickedHandler", () => { createCipher({ username: "TEST_USERNAME" }), ]); - await sut.run(createData("T_1", COPY_USERNAME_ID)); + await sut.run(createData(`${COPY_USERNAME_ID}_1`, COPY_USERNAME_ID), { + url: "https://test.com", + } as any); expect(copyToClipboard).toBeCalledTimes(1); - expect(copyToClipboard).toHaveBeenCalledWith({ text: "TEST_USERNAME", options: undefined }); + expect(copyToClipboard).toHaveBeenCalledWith({ + text: "TEST_USERNAME", + tab: { url: "https://test.com" }, + }); }); it("copies password to clipboard", async () => { @@ -130,11 +142,16 @@ describe("ContextMenuClickedHandler", () => { createCipher({ password: "TEST_PASSWORD" }), ]); - await sut.run(createData("T_1", COPY_PASSWORD_ID)); + await sut.run(createData(`${COPY_PASSWORD_ID}_1`, COPY_PASSWORD_ID), { + url: "https://test.com", + } as any); expect(copyToClipboard).toBeCalledTimes(1); - expect(copyToClipboard).toHaveBeenCalledWith({ text: "TEST_PASSWORD", options: undefined }); + expect(copyToClipboard).toHaveBeenCalledWith({ + text: "TEST_PASSWORD", + tab: { url: "https://test.com" }, + }); }); it("copies totp code to clipboard", async () => { @@ -148,11 +165,16 @@ describe("ContextMenuClickedHandler", () => { return Promise.resolve("654321"); }); - await sut.run(createData("T_1", COPY_VERIFICATIONCODE_ID)); + await sut.run(createData(`${COPY_VERIFICATIONCODE_ID}_1`, COPY_VERIFICATIONCODE_ID), { + url: "https://test.com", + } as any); expect(totpService.getCode).toHaveBeenCalledTimes(1); - expect(copyToClipboard).toHaveBeenCalledWith({ text: "123456" }); + expect(copyToClipboard).toHaveBeenCalledWith({ + text: "123456", + tab: { url: "https://test.com" }, + }); }); it("attempts to find a cipher when noop but unlocked", async () => { @@ -163,11 +185,13 @@ describe("ContextMenuClickedHandler", () => { } as any, ]); - await sut.run(createData("T_noop", COPY_USERNAME_ID), { url: "https://test.com" } as any); + await sut.run(createData(`${COPY_USERNAME_ID}_${NOOP_COMMAND_SUFFIX}`, COPY_USERNAME_ID), { + url: "https://test.com", + } as any); expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledTimes(1); - expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledWith("https://test.com"); + expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledWith("https://test.com", []); expect(copyToClipboard).toHaveBeenCalledTimes(1); @@ -185,11 +209,13 @@ describe("ContextMenuClickedHandler", () => { } as any, ]); - await sut.run(createData("T_noop", COPY_USERNAME_ID), { url: "https://test.com" } as any); + await sut.run(createData(`${COPY_USERNAME_ID}_${NOOP_COMMAND_SUFFIX}`, COPY_USERNAME_ID), { + url: "https://test.com", + } as any); expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledTimes(1); - expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledWith("https://test.com"); + expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledWith("https://test.com", []); }); }); }); diff --git a/apps/browser/src/autofill/browser/context-menu-clicked-handler.ts b/apps/browser/src/autofill/browser/context-menu-clicked-handler.ts index 62c6c9c25a4..54c3e244991 100644 --- a/apps/browser/src/autofill/browser/context-menu-clicked-handler.ts +++ b/apps/browser/src/autofill/browser/context-menu-clicked-handler.ts @@ -4,10 +4,12 @@ import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction"; import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status"; import { EventType } from "@bitwarden/common/enums"; +import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { StateFactory } from "@bitwarden/common/platform/factories/state-factory"; import { GlobalState } from "@bitwarden/common/platform/models/domain/global-state"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type"; +import { CipherType } from "@bitwarden/common/vault/enums/cipher-type"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { @@ -30,16 +32,21 @@ import { import { autofillServiceFactory } from "../background/service_factories/autofill-service.factory"; import { copyToClipboard, GeneratePasswordToClipboardCommand } from "../clipboard"; import { AutofillTabCommand } from "../commands/autofill-tab-command"; - import { + AUTOFILL_CARD_ID, AUTOFILL_ID, + AUTOFILL_IDENTITY_ID, COPY_IDENTIFIER_ID, COPY_PASSWORD_ID, COPY_USERNAME_ID, COPY_VERIFICATIONCODE_ID, + CREATE_CARD_ID, + CREATE_IDENTITY_ID, + CREATE_LOGIN_ID, GENERATE_PASSWORD_ID, NOOP_COMMAND_SUFFIX, -} from "./main-context-menu-handler"; +} from "../constants"; +import { AutofillCipherTypeId } from "../types"; export type CopyToClipboardOptions = { text: string; tab: chrome.tabs.Tab }; export type CopyToClipboardAction = (options: CopyToClipboardOptions) => void; @@ -57,6 +64,7 @@ export class ContextMenuClickedHandler { private autofillAction: AutofillAction, private authService: AuthService, private cipherService: CipherService, + private stateService: StateService, private totpService: TotpService, private eventCollectionService: EventCollectionService, private userVerificationService: UserVerificationService @@ -108,6 +116,7 @@ export class ContextMenuClickedHandler { (tab, cipher) => autofillCommand.doAutofillTabWithCipherCommand(tab, cipher), await authServiceFactory(cachedServices, serviceOptions), await cipherServiceFactory(cachedServices, serviceOptions), + await stateServiceFactory(cachedServices, serviceOptions), await totpServiceFactory(cachedServices, serviceOptions), await eventCollectionServiceFactory(cachedServices, serviceOptions), await userVerificationServiceFactory(cachedServices, serviceOptions) @@ -142,18 +151,16 @@ export class ContextMenuClickedHandler { ); } - async run(info: chrome.contextMenus.OnClickData, tab?: chrome.tabs.Tab) { + async run(info: chrome.contextMenus.OnClickData, tab: chrome.tabs.Tab) { + if (!tab) { + return; + } + switch (info.menuItemId) { case GENERATE_PASSWORD_ID: - if (!tab) { - return; - } await this.generatePasswordToClipboard(tab); break; case COPY_IDENTIFIER_ID: - if (!tab) { - return; - } this.copyToClipboard({ text: await this.getIdentifier(tab, info), tab: tab }); break; default: @@ -161,7 +168,11 @@ export class ContextMenuClickedHandler { } } - async cipherAction(info: chrome.contextMenus.OnClickData, tab?: chrome.tabs.Tab) { + async cipherAction(info: chrome.contextMenus.OnClickData, tab: chrome.tabs.Tab) { + if (!tab) { + return; + } + if ((await this.authService.getAuthStatus()) < AuthenticationStatus.Unlocked) { const retryMessage: LockedVaultPendingNotificationsItem = { commandToRetry: { @@ -182,32 +193,58 @@ export class ContextMenuClickedHandler { // NOTE: We don't actually use the first part of this ID, we further switch based on the parentMenuItemId // I would really love to not add it but that is a departure from how it currently works. - const id = (info.menuItemId as string).split("_")[1]; // We create all the ids, we can guarantee they are strings + const menuItemId = (info.menuItemId as string).split("_")[1]; // We create all the ids, we can guarantee they are strings let cipher: CipherView | undefined; - if (id === NOOP_COMMAND_SUFFIX) { + const isCreateCipherAction = [CREATE_LOGIN_ID, CREATE_IDENTITY_ID, CREATE_CARD_ID].includes( + menuItemId as string + ); + + if (isCreateCipherAction) { + // pass; defer to logic below + } else if (menuItemId === NOOP_COMMAND_SUFFIX) { + const additionalCiphersToGet = + info.parentMenuItemId === AUTOFILL_IDENTITY_ID + ? [CipherType.Identity] + : info.parentMenuItemId === AUTOFILL_CARD_ID + ? [CipherType.Card] + : []; + // This NOOP item has come through which is generally only for no access state but since we got here // we are actually unlocked we will do our best to find a good match of an item to autofill this is useful // in scenarios like unlock on autofill - const ciphers = await this.cipherService.getAllDecryptedForUrl(tab.url); + const ciphers = await this.cipherService.getAllDecryptedForUrl( + tab.url, + additionalCiphersToGet + ); + cipher = ciphers[0]; } else { const ciphers = await this.cipherService.getAllDecrypted(); - cipher = ciphers.find((c) => c.id === id); + cipher = ciphers.find(({ id }) => id === menuItemId); } - if (cipher == null) { + if (!cipher && !isCreateCipherAction) { return; } + this.stateService.setLastActive(new Date().getTime()); switch (info.parentMenuItemId) { case AUTOFILL_ID: - if (tab == null) { - return; + case AUTOFILL_IDENTITY_ID: + case AUTOFILL_CARD_ID: { + const cipherType = this.getCipherCreationType(menuItemId); + + if (cipherType) { + await BrowserApi.tabSendMessageData(tab, "openAddEditCipher", { + cipherType, + }); + break; } if (await this.isPasswordRepromptRequired(cipher)) { await BrowserApi.tabSendMessageData(tab, "passwordReprompt", { cipherId: cipher.id, + // The action here is passed on to the single-use reprompt window and doesn't change based on cipher type action: AUTOFILL_ID, }); } else { @@ -215,14 +252,29 @@ export class ContextMenuClickedHandler { } break; + } case COPY_USERNAME_ID: + if (menuItemId === CREATE_LOGIN_ID) { + await BrowserApi.tabSendMessageData(tab, "openAddEditCipher", { + cipherType: CipherType.Login, + }); + break; + } + this.copyToClipboard({ text: cipher.login.username, tab: tab }); break; case COPY_PASSWORD_ID: + if (menuItemId === CREATE_LOGIN_ID) { + await BrowserApi.tabSendMessageData(tab, "openAddEditCipher", { + cipherType: CipherType.Login, + }); + break; + } + if (await this.isPasswordRepromptRequired(cipher)) { await BrowserApi.tabSendMessageData(tab, "passwordReprompt", { cipherId: cipher.id, - action: COPY_PASSWORD_ID, + action: info.parentMenuItemId, }); } else { this.copyToClipboard({ text: cipher.login.password, tab: tab }); @@ -231,10 +283,17 @@ export class ContextMenuClickedHandler { break; case COPY_VERIFICATIONCODE_ID: + if (menuItemId === CREATE_LOGIN_ID) { + await BrowserApi.tabSendMessageData(tab, "openAddEditCipher", { + cipherType: CipherType.Login, + }); + break; + } + if (await this.isPasswordRepromptRequired(cipher)) { await BrowserApi.tabSendMessageData(tab, "passwordReprompt", { cipherId: cipher.id, - action: COPY_VERIFICATIONCODE_ID, + action: info.parentMenuItemId, }); } else { this.copyToClipboard({ @@ -254,6 +313,16 @@ export class ContextMenuClickedHandler { ); } + private getCipherCreationType(menuItemId?: string): AutofillCipherTypeId | null { + return menuItemId === CREATE_IDENTITY_ID + ? CipherType.Identity + : menuItemId === CREATE_CARD_ID + ? CipherType.Card + : menuItemId === CREATE_LOGIN_ID + ? CipherType.Login + : null; + } + private async getIdentifier(tab: chrome.tabs.Tab, info: chrome.contextMenus.OnClickData) { return new Promise((resolve, reject) => { BrowserApi.sendTabsMessage( diff --git a/apps/browser/src/autofill/browser/main-context-menu-handler.spec.ts b/apps/browser/src/autofill/browser/main-context-menu-handler.spec.ts index 6b599986b67..95916d2e6f1 100644 --- a/apps/browser/src/autofill/browser/main-context-menu-handler.spec.ts +++ b/apps/browser/src/autofill/browser/main-context-menu-handler.spec.ts @@ -60,7 +60,7 @@ describe("context-menu", () => { const createdMenu = await sut.init(); expect(createdMenu).toBeTruthy(); - expect(createSpy).toHaveBeenCalledTimes(7); + expect(createSpy).toHaveBeenCalledTimes(10); }); it("has menu enabled and has premium", async () => { @@ -70,7 +70,7 @@ describe("context-menu", () => { const createdMenu = await sut.init(); expect(createdMenu).toBeTruthy(); - expect(createSpy).toHaveBeenCalledTimes(8); + expect(createSpy).toHaveBeenCalledTimes(11); }); }); @@ -97,7 +97,7 @@ describe("context-menu", () => { }; it("is not a login cipher", async () => { - await sut.loadOptions("TEST_TITLE", "1", "", { + await sut.loadOptions("TEST_TITLE", "1", { ...createCipher(), type: CipherType.SecureNote, } as any); @@ -109,7 +109,6 @@ describe("context-menu", () => { await sut.loadOptions( "TEST_TITLE", "1", - "", createCipher({ username: "", totp: "", @@ -123,18 +122,18 @@ describe("context-menu", () => { it("create entry for each cipher piece", async () => { stateService.getCanAccessPremium.mockResolvedValue(true); - await sut.loadOptions("TEST_TITLE", "1", "", createCipher()); + await sut.loadOptions("TEST_TITLE", "1", createCipher()); // One for autofill, copy username, copy password, and copy totp code expect(createSpy).toHaveBeenCalledTimes(4); }); - it("creates noop item for no cipher", async () => { + it("creates a login/unlock item for each context menu action option when user is not authenticated", async () => { stateService.getCanAccessPremium.mockResolvedValue(true); - await sut.loadOptions("TEST_TITLE", "NOOP", ""); + await sut.loadOptions("TEST_TITLE", "NOOP"); - expect(createSpy).toHaveBeenCalledTimes(4); + expect(createSpy).toHaveBeenCalledTimes(6); }); }); }); diff --git a/apps/browser/src/autofill/browser/main-context-menu-handler.ts b/apps/browser/src/autofill/browser/main-context-menu-handler.ts index b9af3dd191f..cc5cc9a5166 100644 --- a/apps/browser/src/autofill/browser/main-context-menu-handler.ts +++ b/apps/browser/src/autofill/browser/main-context-menu-handler.ts @@ -21,22 +21,24 @@ import { StateServiceInitOptions, } from "../../platform/background/service-factories/state-service.factory"; import { BrowserStateService } from "../../platform/services/abstractions/browser-state.service"; - -export const ROOT_ID = "root"; - -export const AUTOFILL_ID = "autofill"; -export const COPY_USERNAME_ID = "copy-username"; -export const COPY_PASSWORD_ID = "copy-password"; -export const COPY_VERIFICATIONCODE_ID = "copy-totp"; -export const COPY_IDENTIFIER_ID = "copy-identifier"; - -const SEPARATOR_ID = "separator"; -export const GENERATE_PASSWORD_ID = "generate-password"; - -export const NOOP_COMMAND_SUFFIX = "noop"; +import { + AUTOFILL_CARD_ID, + AUTOFILL_ID, + AUTOFILL_IDENTITY_ID, + COPY_IDENTIFIER_ID, + COPY_PASSWORD_ID, + COPY_USERNAME_ID, + COPY_VERIFICATIONCODE_ID, + CREATE_CARD_ID, + CREATE_IDENTITY_ID, + CREATE_LOGIN_ID, + GENERATE_PASSWORD_ID, + NOOP_COMMAND_SUFFIX, + ROOT_ID, + SEPARATOR_ID, +} from "../constants"; export class MainContextMenuHandler { - // private initRunning = false; create: (options: chrome.contextMenus.CreateProperties) => Promise; @@ -120,7 +122,7 @@ export class MainContextMenuHandler { await create({ id: AUTOFILL_ID, parentId: ROOT_ID, - title: this.i18nService.t("autoFill"), + title: this.i18nService.t("autoFillLogin"), }); await create({ @@ -144,7 +146,25 @@ export class MainContextMenuHandler { } await create({ - id: SEPARATOR_ID, + id: SEPARATOR_ID + 1, + type: "separator", + parentId: ROOT_ID, + }); + + await create({ + id: AUTOFILL_IDENTITY_ID, + parentId: ROOT_ID, + title: this.i18nService.t("autoFillIdentity"), + }); + + await create({ + id: AUTOFILL_CARD_ID, + parentId: ROOT_ID, + title: this.i18nService.t("autoFillCard"), + }); + + await create({ + id: SEPARATOR_ID + 2, type: "separator", parentId: ROOT_ID, }); @@ -194,40 +214,52 @@ export class MainContextMenuHandler { }); } - async loadOptions(title: string, id: string, url: string, cipher?: CipherView | undefined) { - if (cipher != null && cipher.type !== CipherType.Login) { - return; - } - + async loadOptions(title: string, optionId: string, cipher?: CipherView) { try { const sanitizedTitle = MainContextMenuHandler.sanitizeContextMenuTitle(title); - const createChildItem = async (parent: string) => { - const menuItemId = `${parent}_${id}`; + const createChildItem = async (parentId: string) => { + const menuItemId = `${parentId}_${optionId}`; + return await this.create({ type: "normal", id: menuItemId, - parentId: parent, + parentId, title: sanitizedTitle, contexts: ["all"], }); }; - if (cipher == null || !Utils.isNullOrEmpty(cipher.login.password)) { + if ( + !cipher || + (cipher.type === CipherType.Login && !Utils.isNullOrEmpty(cipher.login?.password)) + ) { await createChildItem(AUTOFILL_ID); + if (cipher?.viewPassword ?? true) { await createChildItem(COPY_PASSWORD_ID); } } - if (cipher == null || !Utils.isNullOrEmpty(cipher.login.username)) { + if ( + !cipher || + (cipher.type === CipherType.Login && !Utils.isNullOrEmpty(cipher.login?.username)) + ) { await createChildItem(COPY_USERNAME_ID); } const canAccessPremium = await this.stateService.getCanAccessPremium(); - if (canAccessPremium && (cipher == null || !Utils.isNullOrEmpty(cipher.login.totp))) { + if (canAccessPremium && (!cipher || !Utils.isNullOrEmpty(cipher.login?.totp))) { await createChildItem(COPY_VERIFICATIONCODE_ID); } + + if ((!cipher || cipher.type === CipherType.Card) && optionId !== CREATE_LOGIN_ID) { + await createChildItem(AUTOFILL_CARD_ID); + } + + if ((!cipher || cipher.type === CipherType.Identity) && optionId !== CREATE_LOGIN_ID) { + await createChildItem(AUTOFILL_IDENTITY_ID); + } } catch (error) { this.logService.warning(error.message); } @@ -242,13 +274,72 @@ export class MainContextMenuHandler { const authed = await this.stateService.getIsAuthenticated(); await this.loadOptions( this.i18nService.t(authed ? "unlockVaultMenu" : "loginToVaultMenu"), - NOOP_COMMAND_SUFFIX, - "" + NOOP_COMMAND_SUFFIX ); } } - async noLogins(url: string) { - await this.loadOptions(this.i18nService.t("noMatchingLogins"), NOOP_COMMAND_SUFFIX, url); + async noCards() { + await this.create({ + id: `${AUTOFILL_CARD_ID}_NOTICE`, + enabled: false, + parentId: AUTOFILL_CARD_ID, + title: this.i18nService.t("noCards"), + type: "normal", + }); + + await this.create({ + id: `${AUTOFILL_CARD_ID}_${SEPARATOR_ID}`, + parentId: AUTOFILL_CARD_ID, + type: "separator", + }); + + await this.create({ + id: `${AUTOFILL_CARD_ID}_${CREATE_CARD_ID}`, + parentId: AUTOFILL_CARD_ID, + title: this.i18nService.t("addCardMenu"), + type: "normal", + }); + } + + async noIdentities() { + await this.create({ + id: `${AUTOFILL_IDENTITY_ID}_NOTICE`, + enabled: false, + parentId: AUTOFILL_IDENTITY_ID, + title: this.i18nService.t("noIdentities"), + type: "normal", + }); + + await this.create({ + id: `${AUTOFILL_IDENTITY_ID}_${SEPARATOR_ID}`, + parentId: AUTOFILL_IDENTITY_ID, + type: "separator", + }); + + await this.create({ + id: `${AUTOFILL_IDENTITY_ID}_${CREATE_IDENTITY_ID}`, + parentId: AUTOFILL_IDENTITY_ID, + title: this.i18nService.t("addIdentityMenu"), + type: "normal", + }); + } + + async noLogins() { + await this.create({ + id: `${AUTOFILL_ID}_NOTICE`, + enabled: false, + parentId: AUTOFILL_ID, + title: this.i18nService.t("noMatchingLogins"), + type: "normal", + }); + + await this.create({ + id: `${AUTOFILL_ID}_${SEPARATOR_ID}` + 1, + parentId: AUTOFILL_ID, + type: "separator", + }); + + await this.loadOptions(this.i18nService.t("addLoginMenu"), CREATE_LOGIN_ID); } } diff --git a/apps/browser/src/autofill/constants.ts b/apps/browser/src/autofill/constants.ts index 7f3637180b0..ef82035aef7 100644 --- a/apps/browser/src/autofill/constants.ts +++ b/apps/browser/src/autofill/constants.ts @@ -11,3 +11,19 @@ export const EVENTS = { KEYPRESS: "keypress", KEYUP: "keyup", } as const; + +/* Context Menu item Ids */ +export const AUTOFILL_CARD_ID = "autofill-card"; +export const AUTOFILL_ID = "autofill"; +export const AUTOFILL_IDENTITY_ID = "autofill-identity"; +export const COPY_IDENTIFIER_ID = "copy-identifier"; +export const COPY_PASSWORD_ID = "copy-password"; +export const COPY_USERNAME_ID = "copy-username"; +export const COPY_VERIFICATIONCODE_ID = "copy-totp"; +export const CREATE_CARD_ID = "create-card"; +export const CREATE_IDENTITY_ID = "create-identity"; +export const CREATE_LOGIN_ID = "create-login"; +export const GENERATE_PASSWORD_ID = "generate-password"; +export const NOOP_COMMAND_SUFFIX = "noop"; +export const ROOT_ID = "root"; +export const SEPARATOR_ID = "separator"; diff --git a/apps/browser/src/autofill/services/abstractions/autofill.service.ts b/apps/browser/src/autofill/services/abstractions/autofill.service.ts index ac7971768e4..bbd0b21d226 100644 --- a/apps/browser/src/autofill/services/abstractions/autofill.service.ts +++ b/apps/browser/src/autofill/services/abstractions/autofill.service.ts @@ -1,4 +1,5 @@ import { UriMatchType } from "@bitwarden/common/enums"; +import { CipherType } from "@bitwarden/common/vault/enums/cipher-type"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import AutofillField from "../../models/autofill-field"; @@ -55,5 +56,9 @@ export abstract class AutofillService { tab: chrome.tabs.Tab, fromCommand: boolean ) => Promise; - doAutoFillActiveTab: (pageDetails: PageDetail[], fromCommand: boolean) => Promise; + doAutoFillActiveTab: ( + pageDetails: PageDetail[], + fromCommand: boolean, + cipherType?: CipherType + ) => Promise; } diff --git a/apps/browser/src/autofill/services/autofill.service.spec.ts b/apps/browser/src/autofill/services/autofill.service.spec.ts index e6a629cfc9d..f8f12fa7ddb 100644 --- a/apps/browser/src/autofill/services/autofill.service.spec.ts +++ b/apps/browser/src/autofill/services/autofill.service.spec.ts @@ -780,6 +780,18 @@ describe("AutofillService", () => { ]; }); + it("returns a null vault without doing autofill if the page details does not contain fields ", async () => { + pageDetails[0].details.fields = []; + jest.spyOn(autofillService as any, "getActiveTab"); + jest.spyOn(autofillService, "doAutoFill"); + + const result = await autofillService.doAutoFillActiveTab(pageDetails, false); + + expect(autofillService["getActiveTab"]).not.toHaveBeenCalled(); + expect(autofillService.doAutoFill).not.toHaveBeenCalled(); + expect(result).toBeNull(); + }); + it("returns a null value without doing autofill if the active tab cannot be found", async () => { jest.spyOn(autofillService as any, "getActiveTab").mockResolvedValueOnce(undefined); jest.spyOn(autofillService, "doAutoFill"); diff --git a/apps/browser/src/autofill/services/autofill.service.ts b/apps/browser/src/autofill/services/autofill.service.ts index c494b8ece0f..ee233c42524 100644 --- a/apps/browser/src/autofill/services/autofill.service.ts +++ b/apps/browser/src/autofill/services/autofill.service.ts @@ -205,6 +205,7 @@ export default class AutofillService implements AutofillServiceInterface { if ( options.cipher.type !== CipherType.Login || + // eslint-disable-next-line @typescript-eslint/no-misused-promises totpPromise || !options.cipher.login.totp || (!canAccessPremium && !options.cipher.organizationUseTotp) @@ -303,21 +304,51 @@ export default class AutofillService implements AutofillServiceInterface { } /** - * Autofill the active tab with the next login item from the cache + * Autofill the active tab with the next cipher from the cache * @param {PageDetail[]} pageDetails The data scraped from the page * @param {boolean} fromCommand Whether the autofill is triggered by a keyboard shortcut (`true`) or autofill on page load (`false`) * @returns {Promise} The TOTP code of the successfully autofilled login, if any */ async doAutoFillActiveTab( pageDetails: PageDetail[], - fromCommand: boolean + fromCommand: boolean, + cipherType?: CipherType ): Promise { + if (!pageDetails[0]?.details?.fields?.length) { + return null; + } + const tab = await this.getActiveTab(); + if (!tab || !tab.url) { return null; } - return await this.doAutoFillOnTab(pageDetails, tab, fromCommand); + if (!cipherType || cipherType === CipherType.Login) { + return await this.doAutoFillOnTab(pageDetails, tab, fromCommand); + } + + // Cipher is a non-login type + const cipher: CipherView = ( + (await this.cipherService.getAllDecryptedForUrl(tab.url, [cipherType])) || [] + ).find(({ type }) => type === cipherType); + + if (!cipher || cipher.reprompt !== CipherRepromptType.None) { + return null; + } + + return await this.doAutoFill({ + tab: tab, + cipher: cipher, + pageDetails: pageDetails, + skipLastUsed: !fromCommand, + skipUsernameOnlyFill: !fromCommand, + onlyEmptyFields: !fromCommand, + onlyVisibleFields: !fromCommand, + fillNewPassword: false, + allowUntrustedIframe: fromCommand, + allowTotpAutofill: false, + }); } /** diff --git a/apps/browser/src/autofill/types/index.ts b/apps/browser/src/autofill/types/index.ts index 8bab87709d2..8a97e397477 100644 --- a/apps/browser/src/autofill/types/index.ts +++ b/apps/browser/src/autofill/types/index.ts @@ -1,5 +1,6 @@ import { Region } from "@bitwarden/common/platform/abstractions/environment.service"; import { VaultTimeoutAction } from "@bitwarden/common/src/enums/vault-timeout-action.enum"; +import { CipherType } from "@bitwarden/common/vault/enums/cipher-type"; export type UserSettings = { avatarColor: string | null; @@ -58,3 +59,5 @@ export type FillableFormFieldElement = HTMLInputElement | HTMLSelectElement | HT export type FormFieldElement = FillableFormFieldElement | HTMLSpanElement; export type FormElementWithAttribute = FormFieldElement & Record; + +export type AutofillCipherTypeId = CipherType.Login | CipherType.Card | CipherType.Identity; diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index 3aba0c77679..caac8e6bb81 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -103,6 +103,12 @@ import { VaultExportService, VaultExportServiceAbstraction, } from "@bitwarden/exporter/vault-export"; +import { + ImportApiServiceAbstraction, + ImportApiService, + ImportServiceAbstraction, + ImportService, +} from "@bitwarden/importer"; import { BrowserOrganizationService } from "../admin-console/services/browser-organization.service"; import { BrowserPolicyService } from "../admin-console/services/browser-policy.service"; @@ -172,6 +178,8 @@ export default class MainBackground { containerService: ContainerService; auditService: AuditServiceAbstraction; authService: AuthServiceAbstraction; + importApiService: ImportApiServiceAbstraction; + importService: ImportServiceAbstraction; exportService: VaultExportServiceAbstraction; searchService: SearchServiceAbstraction; notificationsService: NotificationsServiceAbstraction; @@ -322,23 +330,6 @@ export default class MainBackground { ); this.searchService = new SearchService(this.logService, this.i18nService); - this.cipherService = new CipherService( - this.cryptoService, - this.settingsService, - this.apiService, - this.i18nService, - this.searchService, - this.stateService, - this.encryptService, - this.cipherFileUploadService - ); - this.folderService = new BrowserFolderService( - this.cryptoService, - this.i18nService, - this.cipherService, - this.stateService - ); - this.folderApiService = new FolderApiService(this.folderService, this.apiService); this.collectionService = new CollectionService( this.cryptoService, this.i18nService, @@ -362,14 +353,6 @@ export default class MainBackground { this.cryptoFunctionService, logoutCallback ); - this.vaultFilterService = new VaultFilterService( - this.stateService, - this.organizationService, - this.folderService, - this.cipherService, - this.collectionService, - this.policyService - ); this.passwordStrengthService = new PasswordStrengthService(); @@ -436,6 +419,36 @@ export default class MainBackground { this.userVerificationApiService ); + this.configApiService = new ConfigApiService(this.apiService, this.authService); + + this.configService = new BrowserConfigService( + this.stateService, + this.configApiService, + this.authService, + this.environmentService, + this.logService, + true + ); + + this.cipherService = new CipherService( + this.cryptoService, + this.settingsService, + this.apiService, + this.i18nService, + this.searchService, + this.stateService, + this.encryptService, + this.cipherFileUploadService, + this.configService + ); + this.folderService = new BrowserFolderService( + this.cryptoService, + this.i18nService, + this.cipherService, + this.stateService + ); + this.folderApiService = new FolderApiService(this.folderService, this.apiService); + this.vaultTimeoutSettingsService = new VaultTimeoutSettingsService( this.cryptoService, this.tokenService, @@ -444,6 +457,15 @@ export default class MainBackground { this.userVerificationService ); + this.vaultFilterService = new VaultFilterService( + this.stateService, + this.organizationService, + this.folderService, + this.cipherService, + this.collectionService, + this.policyService + ); + this.vaultTimeoutService = new VaultTimeoutService( this.cipherService, this.folderService, @@ -513,6 +535,18 @@ export default class MainBackground { this.userVerificationService ); this.auditService = new AuditService(this.cryptoFunctionService, this.apiService); + + this.importApiService = new ImportApiService(this.apiService); + + this.importService = new ImportService( + this.cipherService, + this.folderService, + this.importApiService, + this.i18nService, + this.collectionService, + this.cryptoService + ); + this.exportService = new VaultExportService( this.folderService, this.cipherService, @@ -533,16 +567,6 @@ export default class MainBackground { this.messagingService ); - this.configApiService = new ConfigApiService(this.apiService, this.authService); - - this.configService = new BrowserConfigService( - this.stateService, - this.configApiService, - this.authService, - this.environmentService, - this.logService, - true - ); this.browserPopoutWindowService = new BrowserPopoutWindowService(); const systemUtilsServiceReloadCallback = () => { @@ -571,6 +595,7 @@ export default class MainBackground { this.platformUtilsService as BrowserPlatformUtilsService, this.i18nService, this.notificationsService, + this.stateService, this.systemService, this.environmentService, this.messagingService, @@ -631,6 +656,7 @@ export default class MainBackground { }, this.authService, this.cipherService, + this.stateService, this.totpService, this.eventCollectionService, this.userVerificationService diff --git a/apps/browser/src/background/runtime.background.ts b/apps/browser/src/background/runtime.background.ts index dcf828ef4a0..e921a736f71 100644 --- a/apps/browser/src/background/runtime.background.ts +++ b/apps/browser/src/background/runtime.background.ts @@ -6,10 +6,12 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service" import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { SystemService } from "@bitwarden/common/platform/abstractions/system.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; +import { CipherType } from "@bitwarden/common/vault/enums/cipher-type"; import { AutofillService } from "../autofill/services/abstractions/autofill.service"; import { BrowserApi } from "../platform/browser/browser-api"; import { BrowserPopoutWindowService } from "../platform/popup/abstractions/browser-popout-window.service"; +import { BrowserStateService } from "../platform/services/abstractions/browser-state.service"; import { BrowserEnvironmentService } from "../platform/services/browser-environment.service"; import BrowserPlatformUtilsService from "../platform/services/browser-platform-utils.service"; @@ -28,6 +30,7 @@ export default class RuntimeBackground { private platformUtilsService: BrowserPlatformUtilsService, private i18nService: I18nService, private notificationsService: NotificationsService, + private stateService: BrowserStateService, private systemService: SystemService, private environmentService: BrowserEnvironmentService, private messagingService: MessagingService, @@ -123,12 +126,28 @@ export default class RuntimeBackground { } break; case "openAddEditCipher": { - const addEditCipherUrl = - cipherId == null - ? "popup/index.html#/edit-cipher" - : "popup/index.html#/edit-cipher?cipherId=" + cipherId; + const isNewCipher = !cipherId; + const cipherType = msg.data?.cipherType; + const senderTab = sender.tab; + + if (!senderTab) { + break; + } + + if (isNewCipher) { + await this.browserPopoutWindowService.openCipherCreation(senderTab.windowId, { + cipherType, + senderTabId: senderTab.id, + senderTabURI: senderTab.url, + }); + } else { + await this.browserPopoutWindowService.openCipherEdit(senderTab.windowId, { + cipherId, + senderTabId: senderTab.id, + senderTabURI: senderTab.url, + }); + } - BrowserApi.openBitwardenExtensionTab(addEditCipherUrl, true); break; } case "closeTab": @@ -159,6 +178,7 @@ export default class RuntimeBackground { switch (msg.sender) { case "autofiller": case "autofill_cmd": { + this.stateService.setLastActive(new Date().getTime()); const totpCode = await this.autofillService.doAutoFillActiveTab( [ { @@ -174,6 +194,34 @@ export default class RuntimeBackground { } break; } + case "autofill_card": { + await this.autofillService.doAutoFillActiveTab( + [ + { + frameId: sender.frameId, + tab: msg.tab, + details: msg.details, + }, + ], + false, + CipherType.Card + ); + break; + } + case "autofill_identity": { + await this.autofillService.doAutoFillActiveTab( + [ + { + frameId: sender.frameId, + tab: msg.tab, + details: msg.details, + }, + ], + false, + CipherType.Identity + ); + break; + } case "contextMenu": clearTimeout(this.autofillTimeout); this.pageDetailsToAutoFill.push({ diff --git a/apps/browser/src/manifest.json b/apps/browser/src/manifest.json index 7bd5e9f5a06..41efa59632b 100644 --- a/apps/browser/src/manifest.json +++ b/apps/browser/src/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 2, "name": "__MSG_extName__", "short_name": "__MSG_appName__", - "version": "2023.9.1", + "version": "2023.9.2", "description": "__MSG_extDesc__", "default_locale": "en", "author": "Bitwarden Inc.", diff --git a/apps/browser/src/manifest.v3.json b/apps/browser/src/manifest.v3.json index 7a42aa0ffae..ba8668984de 100644 --- a/apps/browser/src/manifest.v3.json +++ b/apps/browser/src/manifest.v3.json @@ -3,7 +3,7 @@ "minimum_chrome_version": "102.0", "name": "__MSG_extName__", "short_name": "__MSG_appName__", - "version": "2023.9.1", + "version": "2023.9.2", "description": "__MSG_extDesc__", "default_locale": "en", "author": "Bitwarden Inc.", diff --git a/apps/browser/src/platform/background/service-factories/config-api.service.factory.ts b/apps/browser/src/platform/background/service-factories/config-api.service.factory.ts new file mode 100644 index 00000000000..e9e1b86488a --- /dev/null +++ b/apps/browser/src/platform/background/service-factories/config-api.service.factory.ts @@ -0,0 +1,32 @@ +import { ConfigApiServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config-api.service.abstraction"; +import { ConfigApiService } from "@bitwarden/common/platform/services/config/config-api.service"; + +import { + authServiceFactory, + AuthServiceInitOptions, +} from "../../../auth/background/service-factories/auth-service.factory"; + +import { apiServiceFactory, ApiServiceInitOptions } from "./api-service.factory"; +import { FactoryOptions, CachedServices, factory } from "./factory-options"; + +type ConfigApiServiceFactoyOptions = FactoryOptions; + +export type ConfigApiServiceInitOptions = ConfigApiServiceFactoyOptions & + ApiServiceInitOptions & + AuthServiceInitOptions; + +export function configApiServiceFactory( + cache: { configApiService?: ConfigApiServiceAbstraction } & CachedServices, + opts: ConfigApiServiceInitOptions +): Promise { + return factory( + cache, + "configApiService", + opts, + async () => + new ConfigApiService( + await apiServiceFactory(cache, opts), + await authServiceFactory(cache, opts) + ) + ); +} diff --git a/apps/browser/src/platform/background/service-factories/config-service.factory.ts b/apps/browser/src/platform/background/service-factories/config-service.factory.ts new file mode 100644 index 00000000000..a5dc6016c65 --- /dev/null +++ b/apps/browser/src/platform/background/service-factories/config-service.factory.ts @@ -0,0 +1,49 @@ +import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; +import { ConfigService } from "@bitwarden/common/platform/services/config/config.service"; + +import { + authServiceFactory, + AuthServiceInitOptions, +} from "../../../auth/background/service-factories/auth-service.factory"; + +import { configApiServiceFactory, ConfigApiServiceInitOptions } from "./config-api.service.factory"; +import { + environmentServiceFactory, + EnvironmentServiceInitOptions, +} from "./environment-service.factory"; +import { FactoryOptions, CachedServices, factory } from "./factory-options"; +import { logServiceFactory, LogServiceInitOptions } from "./log-service.factory"; +import { stateServiceFactory, StateServiceInitOptions } from "./state-service.factory"; + +type ConfigServiceFactoryOptions = FactoryOptions & { + configServiceOptions?: { + subscribe?: boolean; + }; +}; + +export type ConfigServiceInitOptions = ConfigServiceFactoryOptions & + StateServiceInitOptions & + ConfigApiServiceInitOptions & + AuthServiceInitOptions & + EnvironmentServiceInitOptions & + LogServiceInitOptions; + +export function configServiceFactory( + cache: { configService?: ConfigServiceAbstraction } & CachedServices, + opts: ConfigServiceInitOptions +): Promise { + return factory( + cache, + "configService", + opts, + async () => + new ConfigService( + await stateServiceFactory(cache, opts), + await configApiServiceFactory(cache, opts), + await authServiceFactory(cache, opts), + await environmentServiceFactory(cache, opts), + await logServiceFactory(cache, opts), + opts.configServiceOptions?.subscribe ?? true + ) + ); +} diff --git a/apps/browser/src/platform/popup/abstractions/browser-popout-window.service.ts b/apps/browser/src/platform/popup/abstractions/browser-popout-window.service.ts index 0b3f55ee990..0ded45bea94 100644 --- a/apps/browser/src/platform/popup/abstractions/browser-popout-window.service.ts +++ b/apps/browser/src/platform/popup/abstractions/browser-popout-window.service.ts @@ -1,3 +1,5 @@ +import { CipherType } from "@bitwarden/common/vault/enums/cipher-type"; + interface BrowserPopoutWindowService { openUnlockPrompt(senderWindowId: number): Promise; closeUnlockPrompt(): Promise; @@ -9,6 +11,22 @@ interface BrowserPopoutWindowService { senderTabId: number; } ): Promise; + openCipherCreation( + senderWindowId: number, + promptData: { + cipherType?: CipherType; + senderTabId: number; + senderTabURI: string; + } + ): Promise; + openCipherEdit( + senderWindowId: number, + promptData: { + cipherId: string; + senderTabId: number; + senderTabURI: string; + } + ): Promise; closePasswordRepromptPrompt(): Promise; } diff --git a/apps/browser/src/platform/popup/browser-popout-window.service.ts b/apps/browser/src/platform/popup/browser-popout-window.service.ts index ee03e3a2ec4..f5ac2f3128e 100644 --- a/apps/browser/src/platform/popup/browser-popout-window.service.ts +++ b/apps/browser/src/platform/popup/browser-popout-window.service.ts @@ -1,3 +1,5 @@ +import { CipherType } from "@bitwarden/common/vault/enums/cipher-type"; + import { BrowserApi } from "../browser/browser-api"; import { BrowserPopoutWindowService as BrowserPopupWindowServiceInterface } from "./abstractions/browser-popout-window.service"; @@ -45,6 +47,50 @@ class BrowserPopoutWindowService implements BrowserPopupWindowServiceInterface { await this.openSingleActionPopout(senderWindowId, promptWindowPath, "passwordReprompt"); } + async openCipherCreation( + senderWindowId: number, + { + cipherType = CipherType.Login, + senderTabId, + senderTabURI, + }: { + cipherType?: CipherType; + senderTabId: number; + senderTabURI: string; + } + ) { + const promptWindowPath = + "popup/index.html#/edit-cipher" + + "?uilocation=popout" + + `&type=${cipherType}` + + `&senderTabId=${senderTabId}` + + `&uri=${senderTabURI}`; + + await this.openSingleActionPopout(senderWindowId, promptWindowPath, "cipherCreation"); + } + + async openCipherEdit( + senderWindowId: number, + { + cipherId, + senderTabId, + senderTabURI, + }: { + cipherId: string; + senderTabId: number; + senderTabURI: string; + } + ) { + const promptWindowPath = + "popup/index.html#/edit-cipher" + + "?uilocation=popout" + + `&cipherId=${cipherId}` + + `&senderTabId=${senderTabId}` + + `&uri=${senderTabURI}`; + + await this.openSingleActionPopout(senderWindowId, promptWindowPath, "cipherEdit"); + } + async closePasswordRepromptPrompt() { await this.closeSingleActionPopout("passwordReprompt"); } diff --git a/apps/browser/src/popup/services/services.module.ts b/apps/browser/src/popup/services/services.module.ts index 0ba396af92f..c0597e29e44 100644 --- a/apps/browser/src/popup/services/services.module.ts +++ b/apps/browser/src/popup/services/services.module.ts @@ -85,6 +85,7 @@ import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.serv import { FolderApiService } from "@bitwarden/common/vault/services/folder/folder-api.service"; import { DialogService } from "@bitwarden/components"; import { VaultExportServiceAbstraction } from "@bitwarden/exporter/vault-export"; +import { ImportServiceAbstraction } from "@bitwarden/importer"; import { BrowserOrganizationService } from "../../admin-console/services/browser-organization.service"; import { BrowserPolicyService } from "../../admin-console/services/browser-policy.service"; @@ -368,6 +369,11 @@ function getBgService(service: keyof MainBackground) { useFactory: getBgService("autofillService"), deps: [], }, + { + provide: ImportServiceAbstraction, + useFactory: getBgService("importService"), + deps: [], + }, { provide: VaultExportServiceAbstraction, useFactory: getBgService("exportService"), diff --git a/apps/browser/src/tools/background/service_factories/import-api-service.factory.ts b/apps/browser/src/tools/background/service_factories/import-api-service.factory.ts new file mode 100644 index 00000000000..4344647bbe8 --- /dev/null +++ b/apps/browser/src/tools/background/service_factories/import-api-service.factory.ts @@ -0,0 +1,26 @@ +import { ImportApiService, ImportApiServiceAbstraction } from "@bitwarden/importer"; + +import { + ApiServiceInitOptions, + apiServiceFactory, +} from "../../../platform/background/service-factories/api-service.factory"; +import { + FactoryOptions, + CachedServices, + factory, +} from "../../../platform/background/service-factories/factory-options"; + +export type ImportApiServiceInitOptions = FactoryOptions & ApiServiceInitOptions; +type ServiceCache = { importApiService?: ImportApiServiceAbstraction } & CachedServices; + +export function importApiServiceFactory( + cache: ServiceCache, + opts: ImportApiServiceInitOptions +): Promise { + return factory( + cache, + "importApiService", + opts, + async () => new ImportApiService(await apiServiceFactory(cache, opts)) + ); +} diff --git a/apps/browser/src/tools/background/service_factories/import-service.factory.ts b/apps/browser/src/tools/background/service_factories/import-service.factory.ts new file mode 100644 index 00000000000..3dc9bbd4f0a --- /dev/null +++ b/apps/browser/src/tools/background/service_factories/import-service.factory.ts @@ -0,0 +1,61 @@ +import { ImportService, ImportServiceAbstraction } from "@bitwarden/importer"; + +import { + cryptoServiceFactory, + CryptoServiceInitOptions, +} from "../../../platform/background/service-factories/crypto-service.factory"; +import { + CachedServices, + factory, + FactoryOptions, +} from "../../../platform/background/service-factories/factory-options"; +import { + i18nServiceFactory, + I18nServiceInitOptions, +} from "../../../platform/background/service-factories/i18n-service.factory"; +import { + cipherServiceFactory, + CipherServiceInitOptions, +} from "../../../vault/background/service_factories/cipher-service.factory"; +import { + collectionServiceFactory, + CollectionServiceInitOptions, +} from "../../../vault/background/service_factories/collection-service.factory"; +import { + folderServiceFactory, + FolderServiceInitOptions, +} from "../../../vault/background/service_factories/folder-service.factory"; + +import { importApiServiceFactory, ImportApiServiceInitOptions } from "./import-api-service.factory"; + +type ImportServiceFactoryOptions = FactoryOptions; + +export type ImportServiceInitOptions = ImportServiceFactoryOptions & + CipherServiceInitOptions & + FolderServiceInitOptions & + ImportApiServiceInitOptions & + I18nServiceInitOptions & + CollectionServiceInitOptions & + CryptoServiceInitOptions; + +export function importServiceFactory( + cache: { + importService?: ImportServiceAbstraction; + } & CachedServices, + opts: ImportServiceInitOptions +): Promise { + return factory( + cache, + "importService", + opts, + async () => + new ImportService( + await cipherServiceFactory(cache, opts), + await folderServiceFactory(cache, opts), + await importApiServiceFactory(cache, opts), + await i18nServiceFactory(cache, opts), + await collectionServiceFactory(cache, opts), + await cryptoServiceFactory(cache, opts) + ) + ); +} diff --git a/apps/browser/src/vault/background/service_factories/cipher-service.factory.ts b/apps/browser/src/vault/background/service_factories/cipher-service.factory.ts index 006daadc1af..46062ebc9cc 100644 --- a/apps/browser/src/vault/background/service_factories/cipher-service.factory.ts +++ b/apps/browser/src/vault/background/service_factories/cipher-service.factory.ts @@ -18,8 +18,12 @@ import { ApiServiceInitOptions, } from "../../../platform/background/service-factories/api-service.factory"; import { - CryptoServiceInitOptions, + configServiceFactory, + ConfigServiceInitOptions, +} from "../../../platform/background/service-factories/config-service.factory"; +import { cryptoServiceFactory, + CryptoServiceInitOptions, } from "../../../platform/background/service-factories/crypto-service.factory"; import { EncryptServiceInitOptions, @@ -49,7 +53,8 @@ export type CipherServiceInitOptions = CipherServiceFactoryOptions & I18nServiceInitOptions & SearchServiceInitOptions & StateServiceInitOptions & - EncryptServiceInitOptions; + EncryptServiceInitOptions & + ConfigServiceInitOptions; export function cipherServiceFactory( cache: { cipherService?: AbstractCipherService } & CachedServices, @@ -68,7 +73,8 @@ export function cipherServiceFactory( await searchServiceFactory(cache, opts), await stateServiceFactory(cache, opts), await encryptServiceFactory(cache, opts), - await cipherFileUploadServiceFactory(cache, opts) + await cipherFileUploadServiceFactory(cache, opts), + await configServiceFactory(cache, opts) ) ); } diff --git a/apps/browser/src/vault/popup/components/vault/add-edit.component.ts b/apps/browser/src/vault/popup/components/vault/add-edit.component.ts index 54cb08ae893..f4e9fad5634 100644 --- a/apps/browser/src/vault/popup/components/vault/add-edit.component.ts +++ b/apps/browser/src/vault/popup/components/vault/add-edit.component.ts @@ -35,6 +35,9 @@ export class AddEditComponent extends BaseAddEditComponent { showAttachments = true; openAttachmentsInPopup: boolean; showAutoFillOnPageLoadOptions: boolean; + senderTabId?: number; + uilocation?: "popout" | "popup" | "sidebar" | "tab"; + inPopout = false; constructor( cipherService: CipherService, @@ -81,6 +84,9 @@ export class AddEditComponent extends BaseAddEditComponent { // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (params) => { + this.senderTabId = parseInt(params?.senderTabId, 10) || undefined; + this.uilocation = params?.uilocation; + if (params.cipherId) { this.cipherId = params.cipherId; } @@ -128,6 +134,8 @@ export class AddEditComponent extends BaseAddEditComponent { this.openAttachmentsInPopup = this.popupUtilsService.inPopup(window); }); + this.inPopout = this.uilocation === "popout" || this.popupUtilsService.inPopout(window); + if (!this.editMode) { const tabs = await BrowserApi.tabsQuery({ windowType: "normal" }); this.currentUris = @@ -162,6 +170,11 @@ export class AddEditComponent extends BaseAddEditComponent { return true; } + if (this.senderTabId && this.inPopout) { + setTimeout(() => this.close(), 1000); + return true; + } + if (this.cloneMode) { this.router.navigate(["/tabs/vault"]); } else { @@ -194,6 +207,11 @@ export class AddEditComponent extends BaseAddEditComponent { cancel() { super.cancel(); + if (this.senderTabId && this.inPopout) { + this.close(); + return; + } + if (this.popupUtilsService.inTab(window)) { this.messagingService.send("closeTab"); return; @@ -202,6 +220,14 @@ export class AddEditComponent extends BaseAddEditComponent { this.location.back(); } + // Used for closing single-action views + close() { + BrowserApi.focusTab(this.senderTabId); + window.close(); + + return; + } + async generateUsername(): Promise { const confirmed = await super.generateUsername(); if (confirmed) { diff --git a/apps/browser/tsconfig.json b/apps/browser/tsconfig.json index 9624939c872..ecb2f996e55 100644 --- a/apps/browser/tsconfig.json +++ b/apps/browser/tsconfig.json @@ -15,6 +15,7 @@ "@bitwarden/common/*": ["../../libs/common/src/*"], "@bitwarden/components": ["../../libs/components/src"], "@bitwarden/exporter/*": ["../../libs/exporter/src/*"], + "@bitwarden/importer": ["../../libs/importer/src"], "@bitwarden/vault": ["../../libs/auth/src"] }, "useDefineForClassFields": false diff --git a/apps/cli/config/development.json b/apps/cli/config/development.json index b04d1531a2f..f57c3d9bc38 100644 --- a/apps/cli/config/development.json +++ b/apps/cli/config/development.json @@ -1,3 +1,5 @@ { - "flags": {} + "flags": { + "enableCipherKeyEncryption": false + } } diff --git a/apps/cli/config/production.json b/apps/cli/config/production.json index b04d1531a2f..f57c3d9bc38 100644 --- a/apps/cli/config/production.json +++ b/apps/cli/config/production.json @@ -1,3 +1,5 @@ { - "flags": {} + "flags": { + "enableCipherKeyEncryption": false + } } diff --git a/apps/cli/package.json b/apps/cli/package.json index 153b8d9ce89..f38c5cbbd65 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -1,7 +1,7 @@ { "name": "@bitwarden/cli", "description": "A secure and free password manager for all of your devices.", - "version": "2023.9.0", + "version": "2023.9.2", "keywords": [ "bitwarden", "password", diff --git a/apps/cli/src/admin-console/commands/share.command.ts b/apps/cli/src/admin-console/commands/share.command.ts index 68bd8a18056..88fe256af18 100644 --- a/apps/cli/src/admin-console/commands/share.command.ts +++ b/apps/cli/src/admin-console/commands/share.command.ts @@ -45,11 +45,15 @@ export class ShareCommand { if (cipher.organizationId != null) { return Response.badRequest("This item already belongs to an organization."); } - const cipherView = await cipher.decrypt(); + const cipherView = await cipher.decrypt( + await this.cipherService.getKeyForCipherKeyDecryption(cipher) + ); try { await this.cipherService.shareWithServer(cipherView, organizationId, req); const updatedCipher = await this.cipherService.get(cipher.id); - const decCipher = await updatedCipher.decrypt(); + const decCipher = await updatedCipher.decrypt( + await this.cipherService.getKeyForCipherKeyDecryption(updatedCipher) + ); const res = new CipherResponse(decCipher); return Response.success(res); } catch (e) { diff --git a/apps/cli/src/bw.ts b/apps/cli/src/bw.ts index 42ba158ee72..ca501690193 100644 --- a/apps/cli/src/bw.ts +++ b/apps/cli/src/bw.ts @@ -25,11 +25,13 @@ import { TwoFactorService } from "@bitwarden/common/auth/services/two-factor.ser import { UserVerificationApiService } from "@bitwarden/common/auth/services/user-verification/user-verification-api.service"; import { UserVerificationService } from "@bitwarden/common/auth/services/user-verification/user-verification.service"; import { ClientType, KeySuffixOptions, LogLevelType } from "@bitwarden/common/enums"; +import { ConfigApiServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config-api.service.abstraction"; import { StateFactory } from "@bitwarden/common/platform/factories/state-factory"; import { Account } from "@bitwarden/common/platform/models/domain/account"; import { GlobalState } from "@bitwarden/common/platform/models/domain/global-state"; import { AppIdService } from "@bitwarden/common/platform/services/app-id.service"; import { BroadcasterService } from "@bitwarden/common/platform/services/broadcaster.service"; +import { ConfigApiService } from "@bitwarden/common/platform/services/config/config-api.service"; import { ContainerService } from "@bitwarden/common/platform/services/container.service"; import { CryptoService } from "@bitwarden/common/platform/services/crypto.service"; import { EncryptServiceImplementation } from "@bitwarden/common/platform/services/cryptography/encrypt.service.implementation"; @@ -75,6 +77,7 @@ import { } from "@bitwarden/importer"; import { NodeCryptoFunctionService } from "@bitwarden/node/services/node-crypto-function.service"; +import { CliConfigService } from "./platform/services/cli-config.service"; import { CliPlatformUtilsService } from "./platform/services/cli-platform-utils.service"; import { ConsoleLogService } from "./platform/services/console-log.service"; import { I18nService } from "./platform/services/i18n.service"; @@ -147,6 +150,8 @@ export class Main { devicesApiService: DevicesApiServiceAbstraction; deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction; authRequestCryptoService: AuthRequestCryptoServiceAbstraction; + configApiService: ConfigApiServiceAbstraction; + configService: CliConfigService; constructor() { let p = null; @@ -252,28 +257,8 @@ export class Main { this.searchService = new SearchService(this.logService, this.i18nService); - this.cipherService = new CipherService( - this.cryptoService, - this.settingsService, - this.apiService, - this.i18nService, - this.searchService, - this.stateService, - this.encryptService, - this.cipherFileUploadService - ); - this.broadcasterService = new BroadcasterService(); - this.folderService = new FolderService( - this.cryptoService, - this.i18nService, - this.cipherService, - this.stateService - ); - - this.folderApiService = new FolderApiService(this.folderService, this.apiService); - this.collectionService = new CollectionService( this.cryptoService, this.i18nService, @@ -349,6 +334,38 @@ export class Main { this.authRequestCryptoService ); + this.configApiService = new ConfigApiService(this.apiService, this.authService); + + this.configService = new CliConfigService( + this.stateService, + this.configApiService, + this.authService, + this.environmentService, + this.logService, + true + ); + + this.cipherService = new CipherService( + this.cryptoService, + this.settingsService, + this.apiService, + this.i18nService, + this.searchService, + this.stateService, + this.encryptService, + this.cipherFileUploadService, + this.configService + ); + + this.folderService = new FolderService( + this.cryptoService, + this.i18nService, + this.cipherService, + this.stateService + ); + + this.folderApiService = new FolderApiService(this.folderService, this.apiService); + const lockedCallback = async (userId?: string) => await this.cryptoService.clearStoredUserKey(KeySuffixOptions.Auto); @@ -472,6 +489,7 @@ export class Main { const locale = await this.stateService.getLocale(); await this.i18nService.init(locale); this.twoFactorService.init(); + this.configService.init(); const installedVersion = await this.stateService.getInstalledVersion(); const currentVersion = await this.platformUtilsService.getApplicationVersion(); diff --git a/apps/cli/src/commands/edit.command.ts b/apps/cli/src/commands/edit.command.ts index 960b0999146..60e5ee7936e 100644 --- a/apps/cli/src/commands/edit.command.ts +++ b/apps/cli/src/commands/edit.command.ts @@ -77,7 +77,9 @@ export class EditCommand { return Response.notFound(); } - let cipherView = await cipher.decrypt(); + let cipherView = await cipher.decrypt( + await this.cipherService.getKeyForCipherKeyDecryption(cipher) + ); if (cipherView.isDeleted) { return Response.badRequest("You may not edit a deleted item. Use the restore command first."); } @@ -86,7 +88,9 @@ export class EditCommand { try { await this.cipherService.updateWithServer(encCipher); const updatedCipher = await this.cipherService.get(cipher.id); - const decCipher = await updatedCipher.decrypt(); + const decCipher = await updatedCipher.decrypt( + await this.cipherService.getKeyForCipherKeyDecryption(updatedCipher) + ); const res = new CipherResponse(decCipher); return Response.success(res); } catch (e) { @@ -109,7 +113,9 @@ export class EditCommand { try { await this.cipherService.saveCollectionsWithServer(cipher); const updatedCipher = await this.cipherService.get(cipher.id); - const decCipher = await updatedCipher.decrypt(); + const decCipher = await updatedCipher.decrypt( + await this.cipherService.getKeyForCipherKeyDecryption(updatedCipher) + ); const res = new CipherResponse(decCipher); return Response.success(res); } catch (e) { diff --git a/apps/cli/src/commands/get.command.ts b/apps/cli/src/commands/get.command.ts index 265e24c9d4e..4a84f1efefd 100644 --- a/apps/cli/src/commands/get.command.ts +++ b/apps/cli/src/commands/get.command.ts @@ -103,7 +103,9 @@ export class GetCommand extends DownloadCommand { if (Utils.isGuid(id)) { const cipher = await this.cipherService.get(id); if (cipher != null) { - decCipher = await cipher.decrypt(); + decCipher = await cipher.decrypt( + await this.cipherService.getKeyForCipherKeyDecryption(cipher) + ); } } else if (id.trim() !== "") { let ciphers = await this.cipherService.getAllDecrypted(); diff --git a/apps/cli/src/platform/services/cli-config.service.ts b/apps/cli/src/platform/services/cli-config.service.ts new file mode 100644 index 00000000000..6faa1b12e8a --- /dev/null +++ b/apps/cli/src/platform/services/cli-config.service.ts @@ -0,0 +1,9 @@ +import { NEVER } from "rxjs"; + +import { ConfigService } from "@bitwarden/common/platform/services/config/config.service"; + +export class CliConfigService extends ConfigService { + // The rxjs timer uses setTimeout/setInterval under the hood, which prevents the node process from exiting + // when the command is finished. Cli should never be alive long enough to use the timer, so we disable it. + protected refreshTimer$ = NEVER; +} diff --git a/apps/cli/src/vault/create.command.ts b/apps/cli/src/vault/create.command.ts index 3f4d53e9737..01217dbc307 100644 --- a/apps/cli/src/vault/create.command.ts +++ b/apps/cli/src/vault/create.command.ts @@ -80,7 +80,9 @@ export class CreateCommand { try { await this.cipherService.createWithServer(cipher); const newCipher = await this.cipherService.get(cipher.id); - const decCipher = await newCipher.decrypt(); + const decCipher = await newCipher.decrypt( + await this.cipherService.getKeyForCipherKeyDecryption(newCipher) + ); const res = new CipherResponse(decCipher); return Response.success(res); } catch (e) { @@ -141,7 +143,9 @@ export class CreateCommand { new Uint8Array(fileBuf).buffer ); const updatedCipher = await this.cipherService.get(cipher.id); - const decCipher = await updatedCipher.decrypt(); + const decCipher = await updatedCipher.decrypt( + await this.cipherService.getKeyForCipherKeyDecryption(updatedCipher) + ); return Response.success(new CipherResponse(decCipher)); } catch (e) { return Response.error(e); diff --git a/apps/desktop/config/base.json b/apps/desktop/config/base.json index 3ae895a19cf..cb408a87d87 100644 --- a/apps/desktop/config/base.json +++ b/apps/desktop/config/base.json @@ -1,6 +1,7 @@ { "dev_flags": {}, "flags": { - "multithreadDecryption": false + "multithreadDecryption": false, + "enableCipherKeyEncryption": false } } diff --git a/apps/desktop/config/development.json b/apps/desktop/config/development.json index b587e9ecfb9..d2b10738124 100644 --- a/apps/desktop/config/development.json +++ b/apps/desktop/config/development.json @@ -1,6 +1,7 @@ { "devFlags": {}, "flags": { - "showDDGSetting": true + "showDDGSetting": true, + "enableCipherKeyEncryption": false } } diff --git a/apps/desktop/config/production.json b/apps/desktop/config/production.json index 56f19341304..39b78094d0f 100644 --- a/apps/desktop/config/production.json +++ b/apps/desktop/config/production.json @@ -1,5 +1,6 @@ { "flags": { - "showDDGSetting": true + "showDDGSetting": true, + "enableCipherKeyEncryption": false } } diff --git a/apps/desktop/desktop_native/Cargo.lock b/apps/desktop/desktop_native/Cargo.lock index 09ffcd4fd9f..75e8e076f21 100644 --- a/apps/desktop/desktop_native/Cargo.lock +++ b/apps/desktop/desktop_native/Cargo.lock @@ -15,9 +15,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.20" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" dependencies = [ "memchr", ] @@ -28,6 +28,23 @@ version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +[[package]] +name = "arboard" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac57f2b058a76363e357c056e4f74f1945bf734d37b8b3ef49066c4787dde0fc" +dependencies = [ + "clipboard-win", + "log", + "objc", + "objc-foundation", + "objc_id", + "parking_lot", + "thiserror", + "winapi", + "x11rb", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -48,9 +65,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.2.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24a6904aef64d73cf10ab17ebace7befb918b82164785cb89907993be7f83813" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" [[package]] name = "block-buffer" @@ -72,9 +95,9 @@ dependencies = [ [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "cbc" @@ -87,17 +110,21 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cfg-expr" -version = "0.14.0" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a35b255461940a32985c627ce82900867c61db1659764d3675ea81963f72a4c6" +checksum = "03915af431787e6ffdcc74c645077518c6b6e01f80b761e0fbbfa288536311b3" dependencies = [ "smallvec", + "target-lexicon", ] [[package]] @@ -116,6 +143,17 @@ dependencies = [ "inout", ] +[[package]] +name = "clipboard-win" +version = "4.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362" +dependencies = [ + "error-code", + "str-buf", + "winapi", +] + [[package]] name = "codespan-reporting" version = "0.11.1" @@ -153,9 +191,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.6" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "280a9f2d8b3a38871a3c8a46fb80db65e5e5ed97da80c4d08bf27fb63e35e181" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" dependencies = [ "libc", ] @@ -172,19 +210,19 @@ dependencies = [ [[package]] name = "ctor" -version = "0.2.0" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4056f63fce3b82d852c3da92b08ea59959890813a7f4ce9c0ff85b10cf301b" +checksum = "1f34ba9a9bcb8645379e9de8cb3ecfcf4d1c85ba66d90deb3259206fa5aa193b" dependencies = [ "quote", - "syn 2.0.14", + "syn 2.0.37", ] [[package]] name = "cxx" -version = "1.0.94" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" +checksum = "bbe98ba1789d56fb3db3bee5e032774d4f421b685de7ba703643584ba24effbe" dependencies = [ "cc", "cxxbridge-flags", @@ -194,9 +232,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.94" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" +checksum = "5c0c11acd0e63bae27dcd2afced407063312771212b7a823b4fd72d633be30fb" dependencies = [ "cc", "codespan-reporting", @@ -204,24 +242,24 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.14", + "syn 2.0.37", ] [[package]] name = "cxxbridge-flags" -version = "1.0.94" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" +checksum = "20888d9e1d2298e2ff473cee30efe7d5036e437857ab68bbfea84c74dba91da2" [[package]] name = "cxxbridge-macro" -version = "1.0.94" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" +checksum = "2fa16a70dd58129e4dfffdff535fb1bce66673f7bbeec4a5a1765a504e1ccd84" dependencies = [ "proc-macro2", "quote", - "syn 2.0.14", + "syn 2.0.37", ] [[package]] @@ -230,6 +268,7 @@ version = "0.0.0" dependencies = [ "aes", "anyhow", + "arboard", "base64", "cbc", "core-foundation", @@ -254,14 +293,30 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "error-code" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64f18991e7bf11e7ffee451b5318b5c1a73c52d0d0ada6e5a3017c8c1ced6a21" +dependencies = [ + "libc", + "str-buf", +] + [[package]] name = "futures-channel" version = "0.3.28" @@ -302,7 +357,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.14", + "syn 2.0.37", ] [[package]] @@ -336,10 +391,20 @@ dependencies = [ ] [[package]] -name = "getrandom" -version = "0.2.9" +name = "gethostname" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", @@ -368,9 +433,9 @@ dependencies = [ [[package]] name = "gio-sys" -version = "0.17.4" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b1d43b0d7968b48455244ecafe41192871257f5740aa6b095eb19db78e362a5" +checksum = "0ccf87c30a12c469b6d958950f6a9c09f2be20b7773f7e70d20b867fdf2628c3" dependencies = [ "glib-sys", "gobject-sys", @@ -381,9 +446,9 @@ dependencies = [ [[package]] name = "glib" -version = "0.17.9" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7f1de7cbde31ea4f0a919453a2dcece5d54d5b70e08f8ad254dc4840f5f09b6" +checksum = "d3fad45ba8d4d2cea612b432717e834f48031cd8853c8aaf43b2c79fec8d144b" dependencies = [ "bitflags 1.3.2", "futures-channel", @@ -404,9 +469,9 @@ dependencies = [ [[package]] name = "glib-macros" -version = "0.17.9" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a7206c5c03851ef126ea1444990e81fdd6765fb799d5bc694e4897ca01bb97f" +checksum = "eca5c79337338391f1ab8058d6698125034ce8ef31b72a442437fa6c8580de26" dependencies = [ "anyhow", "heck", @@ -419,9 +484,9 @@ dependencies = [ [[package]] name = "glib-sys" -version = "0.17.4" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f00ad0a1bf548e61adfff15d83430941d9e1bb620e334f779edd1c745680a5" +checksum = "d80aa6ea7bba0baac79222204aa786a6293078c210abe69ef1336911d4bdc4f0" dependencies = [ "libc", "system-deps", @@ -429,9 +494,9 @@ dependencies = [ [[package]] name = "gobject-sys" -version = "0.17.4" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e75b0000a64632b2d8ca3cf856af9308e3a970844f6e9659bd197f026793d0" +checksum = "cd34c3317740a6358ec04572c1bcfd3ac0b5b6529275fae255b237b314bb8062" dependencies = [ "glib-sys", "libc", @@ -440,9 +505,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" [[package]] name = "heck" @@ -452,20 +517,17 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "indexmap" -version = "1.9.3" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" dependencies = [ - "autocfg", + "equivalent", "hashbrown", ] @@ -502,9 +564,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.141" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "libloading" @@ -546,18 +608,18 @@ dependencies = [ [[package]] name = "link-cplusplus" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +checksum = "9d240c6f7e1ba3a28b0249f774e6a9dd0175054b52dfbb61b16eb8505c3785c9" dependencies = [ "cc", ] [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" dependencies = [ "autocfg", "scopeguard", @@ -565,29 +627,43 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" dependencies = [ - "cfg-if", + "libc", ] [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] [[package]] name = "mio" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "log", "wasi", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] @@ -596,7 +672,7 @@ version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7f0a2e93526dd9c8c522d72a4d0c88678be8966fabe9fb8f2947fde6339b682" dependencies = [ - "bitflags 2.2.1", + "bitflags 2.4.0", "ctor", "napi-derive", "napi-sys", @@ -649,20 +725,61 @@ dependencies = [ ] [[package]] -name = "num_cpus" -version = "1.15.0" +name = "nix" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ "hermit-abi", "libc", ] [[package]] -name = "once_cell" -version = "1.17.1" +name = "objc" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "objc-foundation" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" +dependencies = [ + "block", + "objc", + "objc_id", +] + +[[package]] +name = "objc_id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +dependencies = [ + "objc", +] + +[[package]] +name = "once_cell" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" [[package]] name = "parking_lot" @@ -676,22 +793,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.7" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-sys 0.45.0", + "windows-targets", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -701,9 +818,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "ppv-lite86" @@ -747,18 +864,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.26" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -795,18 +912,30 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "regex" -version = "1.7.3" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" +checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" dependencies = [ "aho-corasick", "memchr", @@ -815,9 +944,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.29" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "retry" @@ -836,9 +965,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "scratch" -version = "1.0.5" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" +checksum = "a3cf7c11c38cb994f3d40e8a8cde3bbd1f72a435e4c49e85d6553d8312306152" [[package]] name = "security-framework" @@ -865,21 +994,35 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.17" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" [[package]] name = "serde" -version = "1.0.160" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.188" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.37", +] [[package]] name = "serde_spanned" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4" +checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" dependencies = [ "serde", ] @@ -906,18 +1049,18 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "socket2" @@ -929,6 +1072,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "str-buf" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" + [[package]] name = "syn" version = "1.0.109" @@ -942,9 +1091,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.14" +version = "2.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcf316d5356ed6847742d036f8a39c3b8435cac10bd528a4bd461928a6ab34d5" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" dependencies = [ "proc-macro2", "quote", @@ -953,9 +1102,9 @@ dependencies = [ [[package]] name = "system-deps" -version = "6.0.4" +version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555fc8147af6256f3931a36bb83ad0023240ce9cf2b319dec8236fd1f220b05f" +checksum = "30c2de8a4d8f4b823d634affc9cd2a74ec98c53a756f317e529a48046cbf71f3" dependencies = [ "cfg-expr", "heck", @@ -965,10 +1114,16 @@ dependencies = [ ] [[package]] -name = "termcolor" -version = "1.2.0" +name = "target-lexicon" +version = "0.12.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" + +[[package]] +name = "termcolor" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" dependencies = [ "winapi-util", ] @@ -990,7 +1145,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.14", + "syn 2.0.37", ] [[package]] @@ -1009,7 +1164,7 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -1020,14 +1175,14 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.14", + "syn 2.0.37", ] [[package]] name = "toml" -version = "0.7.3" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" dependencies = [ "serde", "serde_spanned", @@ -1037,18 +1192,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.8" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ "indexmap", "serde", @@ -1065,9 +1220,9 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-segmentation" @@ -1077,9 +1232,9 @@ checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "version-compare" @@ -1101,9 +1256,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "widestring" -version = "0.5.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983" +checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" [[package]] name = "winapi" @@ -1123,9 +1278,18 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-wsapoll" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e" dependencies = [ "winapi", ] @@ -1142,16 +1306,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets 0.48.0", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", + "windows-targets", ] [[package]] @@ -1160,128 +1315,93 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[package]] -name = "windows-targets" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" -dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.4.1" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28" +checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc" dependencies = [ "memchr", ] + +[[package]] +name = "x11rb" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "592b4883219f345e712b3209c62654ebda0bb50887f330cbd018d0f654bfd507" +dependencies = [ + "gethostname", + "nix", + "winapi", + "winapi-wsapoll", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56b245751c0ac9db0e006dc812031482784e434630205a93c73cfefcaabeac67" +dependencies = [ + "nix", +] diff --git a/apps/desktop/desktop_native/Cargo.toml b/apps/desktop/desktop_native/Cargo.toml index 15b0cb632e0..9dd36d32040 100644 --- a/apps/desktop/desktop_native/Cargo.toml +++ b/apps/desktop/desktop_native/Cargo.toml @@ -15,6 +15,7 @@ manual_test = [] [dependencies] aes = "=0.8.2" anyhow = "=1.0.71" +arboard = { version = "=3.2.1", default-features = false } base64 = "=0.21.2" cbc = { version = "=0.1.2", features = ["alloc"] } napi = { version = "=2.13.1", features = ["async"] } @@ -31,7 +32,7 @@ typenum = "=1.16.0" napi-build = "=2.0.1" [target.'cfg(windows)'.dependencies] -widestring = "=0.5.1" +widestring = "=1.0.2" windows = { version = "=0.48.0", features = [ "Foundation", "Security_Credentials_UI", diff --git a/apps/desktop/desktop_native/index.d.ts b/apps/desktop/desktop_native/index.d.ts index 573e2e49300..abfc998de04 100644 --- a/apps/desktop/desktop_native/index.d.ts +++ b/apps/desktop/desktop_native/index.d.ts @@ -37,3 +37,7 @@ export namespace biometrics { ivB64: string } } +export namespace clipboards { + export function read(): Promise + export function write(text: string, password: boolean): Promise +} diff --git a/apps/desktop/desktop_native/index.js b/apps/desktop/desktop_native/index.js index 8b48ac99402..1cf7ea9434e 100644 --- a/apps/desktop/desktop_native/index.js +++ b/apps/desktop/desktop_native/index.js @@ -206,7 +206,8 @@ if (!nativeBinding) { throw new Error(`Failed to load native binding`) } -const { passwords, biometrics } = nativeBinding +const { passwords, biometrics, clipboards } = nativeBinding module.exports.passwords = passwords module.exports.biometrics = biometrics +module.exports.clipboards = clipboards diff --git a/apps/desktop/desktop_native/src/biometric/windows.rs b/apps/desktop/desktop_native/src/biometric/windows.rs index 0ed39b98e04..54abea7281c 100644 --- a/apps/desktop/desktop_native/src/biometric/windows.rs +++ b/apps/desktop/desktop_native/src/biometric/windows.rs @@ -7,8 +7,8 @@ use rand::RngCore; use retry::delay::Fixed; use sha2::{Digest, Sha256}; use windows::{ - h, core::{factory, HSTRING}, + h, Foundation::IAsyncOperation, Security::{ Credentials::{ @@ -241,7 +241,9 @@ fn set_focus(window: HWND) { impl KeyMaterial { fn digest_material(&self) -> String { match self.client_key_part_b64.as_deref() { - Some(client_key_part_b64) => format!("{}|{}", self.os_key_part_b64, client_key_part_b64), + Some(client_key_part_b64) => { + format!("{}|{}", self.os_key_part_b64, client_key_part_b64) + } None => self.os_key_part_b64.clone(), } } @@ -419,7 +421,14 @@ mod tests { let mut key_material = key_material(); key_material.client_key_part_b64 = None; let result = key_material.derive_key().unwrap(); - assert_eq!(result, [81, 100, 62, 172, 151, 119, 182, 58, 123, 38, 129, 116, 209, 253, 66, 118, 218, 237, 236, 155, 201, 234, 11, 198, 229, 171, 246, 144, 71, 188, 84, 246].into()); + assert_eq!( + result, + [ + 81, 100, 62, 172, 151, 119, 182, 58, 123, 38, 129, 116, 209, 253, 66, 118, 218, + 237, 236, 155, 201, 234, 11, 198, 229, 171, 246, 144, 71, 188, 84, 246 + ] + .into() + ); } #[test] diff --git a/apps/desktop/desktop_native/src/clipboard.rs b/apps/desktop/desktop_native/src/clipboard.rs new file mode 100644 index 00000000000..cecf2478656 --- /dev/null +++ b/apps/desktop/desktop_native/src/clipboard.rs @@ -0,0 +1,56 @@ +use anyhow::Result; +use arboard::{Clipboard, Set}; + +pub fn read() -> Result { + let mut clipboard = Clipboard::new()?; + + Ok(clipboard.get_text()?) +} + +pub fn write(text: &str, password: bool) -> Result<()> { + let mut clipboard = Clipboard::new()?; + + let set = clipboard_set(clipboard.set(), password); + + set.text(text)?; + Ok(()) +} + +// Exclude from windows clipboard history +#[cfg(target_os = "windows")] +fn clipboard_set(set: Set, password: bool) -> Set { + use arboard::SetExtWindows; + + if password { + set.exclude_from_cloud().exclude_from_history() + } else { + set + } +} + +// Wait for clipboard to be available on linux +#[cfg(target_os = "linux")] +fn clipboard_set(set: Set, _password: bool) -> Set { + use arboard::SetExtLinux; + + set.wait() +} + +#[cfg(target_os = "macos")] +fn clipboard_set(set: Set, _password: bool) -> Set { + set +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[cfg(any(feature = "manual_test", not(target_os = "linux")))] + fn test_write_read() { + let message = "Hello world!"; + + write(message, false).unwrap(); + assert_eq!(message, read().unwrap()); + } +} diff --git a/apps/desktop/desktop_native/src/lib.rs b/apps/desktop/desktop_native/src/lib.rs index fefede4f749..d00b95c47f2 100644 --- a/apps/desktop/desktop_native/src/lib.rs +++ b/apps/desktop/desktop_native/src/lib.rs @@ -2,6 +2,7 @@ extern crate napi_derive; mod biometric; +mod clipboard; mod crypto; mod error; mod password; @@ -107,3 +108,17 @@ pub mod biometrics { pub iv_b64: String, } } + +#[napi] +pub mod clipboards { + #[napi] + pub async fn read() -> napi::Result { + super::clipboard::read().map_err(|e| napi::Error::from_reason(e.to_string())) + } + + #[napi] + pub async fn write(text: String, password: bool) -> napi::Result<()> { + super::clipboard::write(&text, password) + .map_err(|e| napi::Error::from_reason(e.to_string())) + } +} diff --git a/apps/desktop/desktop_native/src/password/windows.rs b/apps/desktop/desktop_native/src/password/windows.rs index 6e644b34962..9a92ae7cc85 100644 --- a/apps/desktop/desktop_native/src/password/windows.rs +++ b/apps/desktop/desktop_native/src/password/windows.rs @@ -95,7 +95,7 @@ pub fn set_password(service: &str, account: &str, password: &str) -> Result<()> let credential = CREDENTIALW { Flags: CRED_FLAGS(CRED_FLAGS_NONE), Type: CRED_TYPE_GENERIC, - TargetName: PWSTR(unsafe { target_name.as_mut_ptr() }), + TargetName: PWSTR(target_name.as_mut_ptr()), Comment: PWSTR::null(), LastWritten: last_written, CredentialBlobSize: credential_len, @@ -104,7 +104,7 @@ pub fn set_password(service: &str, account: &str, password: &str) -> Result<()> AttributeCount: 0, Attributes: std::ptr::null_mut(), TargetAlias: PWSTR::null(), - UserName: PWSTR(unsafe { user_name.as_mut_ptr() }), + UserName: PWSTR(user_name.as_mut_ptr()), }; let result = unsafe { CredWriteW(&credential, 0) }; diff --git a/apps/desktop/electron-builder.json b/apps/desktop/electron-builder.json index f1768f9b03b..6f760ef2b1e 100644 --- a/apps/desktop/electron-builder.json +++ b/apps/desktop/electron-builder.json @@ -19,7 +19,7 @@ "**/node_modules/@bitwarden/desktop-native/index.js", "**/node_modules/@bitwarden/desktop-native/desktop_native.${platform}-${arch}*.node" ], - "electronVersion": "24.8.3", + "electronVersion": "24.8.5", "generateUpdatesFilesForAllChannels": true, "publish": { "provider": "generic", diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 719e680dd22..444753e9206 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -1,7 +1,7 @@ { "name": "@bitwarden/desktop", "description": "A secure and free password manager for all of your devices.", - "version": "2023.9.1", + "version": "2023.9.2", "keywords": [ "bitwarden", "password", @@ -18,7 +18,7 @@ "scripts": { "postinstall": "electron-rebuild", "start": "cross-env ELECTRON_IS_DEV=0 ELECTRON_NO_UPDATER=1 electron ./build", - "build-native": "cargo build --manifest-path=./desktop_native/Cargo.toml", + "build-native": "cd desktop_native && npm run build", "build": "concurrently -n Main,Rend -c yellow,cyan \"npm run build:main\" \"npm run build:renderer\"", "build:dev": "concurrently -n Main,Rend -c yellow,cyan \"npm run build:main:dev\" \"npm run build:renderer:dev\"", "build:main": "cross-env NODE_ENV=production webpack --config webpack.main.js", diff --git a/apps/desktop/src/locales/af/messages.json b/apps/desktop/src/locales/af/messages.json index e6548b533f7..6c7b8281e57 100644 --- a/apps/desktop/src/locales/af/messages.json +++ b/apps/desktop/src/locales/af/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/ar/messages.json b/apps/desktop/src/locales/ar/messages.json index bd767139f71..cd0f5a6752e 100644 --- a/apps/desktop/src/locales/ar/messages.json +++ b/apps/desktop/src/locales/ar/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "قائمة فرعية" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/az/messages.json b/apps/desktop/src/locales/az/messages.json index 41c35e45820..5c8e11c9891 100644 --- a/apps/desktop/src/locales/az/messages.json +++ b/apps/desktop/src/locales/az/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Alt menyu" + }, + "aliasDomain": { + "message": "Domen ləqəbi" } } diff --git a/apps/desktop/src/locales/be/messages.json b/apps/desktop/src/locales/be/messages.json index d8302dec530..00b275789cf 100644 --- a/apps/desktop/src/locales/be/messages.json +++ b/apps/desktop/src/locales/be/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Падменю" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/bg/messages.json b/apps/desktop/src/locales/bg/messages.json index 2315ae8519e..bb7d2925107 100644 --- a/apps/desktop/src/locales/bg/messages.json +++ b/apps/desktop/src/locales/bg/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Подменю" + }, + "aliasDomain": { + "message": "Псевдонимен домейн" } } diff --git a/apps/desktop/src/locales/bn/messages.json b/apps/desktop/src/locales/bn/messages.json index 4271873c462..d06c92179ed 100644 --- a/apps/desktop/src/locales/bn/messages.json +++ b/apps/desktop/src/locales/bn/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/bs/messages.json b/apps/desktop/src/locales/bs/messages.json index 17ebcf15e8f..b2888e0e071 100644 --- a/apps/desktop/src/locales/bs/messages.json +++ b/apps/desktop/src/locales/bs/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/ca/messages.json b/apps/desktop/src/locales/ca/messages.json index f7b980b791e..5d5826cdaf8 100644 --- a/apps/desktop/src/locales/ca/messages.json +++ b/apps/desktop/src/locales/ca/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenú" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/cs/messages.json b/apps/desktop/src/locales/cs/messages.json index c66c3dc9246..8fcbf5a3bd9 100644 --- a/apps/desktop/src/locales/cs/messages.json +++ b/apps/desktop/src/locales/cs/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Podmenu" + }, + "aliasDomain": { + "message": "Doména aliasu" } } diff --git a/apps/desktop/src/locales/cy/messages.json b/apps/desktop/src/locales/cy/messages.json index fb6177cfb4a..d3a13313e9e 100644 --- a/apps/desktop/src/locales/cy/messages.json +++ b/apps/desktop/src/locales/cy/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/da/messages.json b/apps/desktop/src/locales/da/messages.json index 2d545648f0a..b51e6b1e385 100644 --- a/apps/desktop/src/locales/da/messages.json +++ b/apps/desktop/src/locales/da/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Undermenu" + }, + "aliasDomain": { + "message": "Aliasdomæne" } } diff --git a/apps/desktop/src/locales/de/messages.json b/apps/desktop/src/locales/de/messages.json index e9d1e5de6ed..fc4490e3c0d 100644 --- a/apps/desktop/src/locales/de/messages.json +++ b/apps/desktop/src/locales/de/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Untermenü" + }, + "aliasDomain": { + "message": "Alias-Domain" } } diff --git a/apps/desktop/src/locales/el/messages.json b/apps/desktop/src/locales/el/messages.json index 11d2aba2f74..9c48c69f2f3 100644 --- a/apps/desktop/src/locales/el/messages.json +++ b/apps/desktop/src/locales/el/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/en/messages.json b/apps/desktop/src/locales/en/messages.json index 48e3f0e7bd0..d3a13313e9e 100644 --- a/apps/desktop/src/locales/en/messages.json +++ b/apps/desktop/src/locales/en/messages.json @@ -1,4 +1,4 @@ -{ +{ "bitwarden": { "message": "Bitwarden" }, diff --git a/apps/desktop/src/locales/en_GB/messages.json b/apps/desktop/src/locales/en_GB/messages.json index 77bb93b520a..2b633fe418d 100644 --- a/apps/desktop/src/locales/en_GB/messages.json +++ b/apps/desktop/src/locales/en_GB/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/en_IN/messages.json b/apps/desktop/src/locales/en_IN/messages.json index faa3a67731b..3d76a215982 100644 --- a/apps/desktop/src/locales/en_IN/messages.json +++ b/apps/desktop/src/locales/en_IN/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/eo/messages.json b/apps/desktop/src/locales/eo/messages.json index ae7fc279de4..5b790ffa3de 100644 --- a/apps/desktop/src/locales/eo/messages.json +++ b/apps/desktop/src/locales/eo/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/es/messages.json b/apps/desktop/src/locales/es/messages.json index e534989c461..3f290fba306 100644 --- a/apps/desktop/src/locales/es/messages.json +++ b/apps/desktop/src/locales/es/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/et/messages.json b/apps/desktop/src/locales/et/messages.json index aa92702b8e3..43012caf212 100644 --- a/apps/desktop/src/locales/et/messages.json +++ b/apps/desktop/src/locales/et/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/eu/messages.json b/apps/desktop/src/locales/eu/messages.json index 99cd64ea7b3..db7dd72a9d7 100644 --- a/apps/desktop/src/locales/eu/messages.json +++ b/apps/desktop/src/locales/eu/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/fa/messages.json b/apps/desktop/src/locales/fa/messages.json index e01c6ffda49..dad420ca1d1 100644 --- a/apps/desktop/src/locales/fa/messages.json +++ b/apps/desktop/src/locales/fa/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/fi/messages.json b/apps/desktop/src/locales/fi/messages.json index 90a378996fc..8992d155244 100644 --- a/apps/desktop/src/locales/fi/messages.json +++ b/apps/desktop/src/locales/fi/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Alavalikko" + }, + "aliasDomain": { + "message": "Aliasverkkotunnus" } } diff --git a/apps/desktop/src/locales/fil/messages.json b/apps/desktop/src/locales/fil/messages.json index 2a1866896f7..72be6018694 100644 --- a/apps/desktop/src/locales/fil/messages.json +++ b/apps/desktop/src/locales/fil/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/fr/messages.json b/apps/desktop/src/locales/fr/messages.json index 1a7f86e744a..f6baea6ee6f 100644 --- a/apps/desktop/src/locales/fr/messages.json +++ b/apps/desktop/src/locales/fr/messages.json @@ -1411,7 +1411,7 @@ "message": "Demander à Windows Hello au démarrage" }, "autoPromptTouchId": { - "message": "Demander à Touch ID au démarrage" + "message": "Demander Touch ID au démarrage de l'application" }, "requirePasswordOnStart": { "message": "Exiger un mot de passe ou un code PIN au démarrage de Bitwarden" @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Sous-menu" + }, + "aliasDomain": { + "message": "Domaine de l'alias" } } diff --git a/apps/desktop/src/locales/gl/messages.json b/apps/desktop/src/locales/gl/messages.json index fb6177cfb4a..d3a13313e9e 100644 --- a/apps/desktop/src/locales/gl/messages.json +++ b/apps/desktop/src/locales/gl/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/he/messages.json b/apps/desktop/src/locales/he/messages.json index b809355385d..a43a20fd62c 100644 --- a/apps/desktop/src/locales/he/messages.json +++ b/apps/desktop/src/locales/he/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/hi/messages.json b/apps/desktop/src/locales/hi/messages.json index d88afc01d54..f31adfc16dd 100644 --- a/apps/desktop/src/locales/hi/messages.json +++ b/apps/desktop/src/locales/hi/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/hr/messages.json b/apps/desktop/src/locales/hr/messages.json index 83c2d06105a..4578cc44fdd 100644 --- a/apps/desktop/src/locales/hr/messages.json +++ b/apps/desktop/src/locales/hr/messages.json @@ -476,7 +476,7 @@ "message": "Najveća veličina datoteke je 500 MB." }, "encryptionKeyMigrationRequired": { - "message": "Encryption key migration required. Please login through the web vault to update your encryption key." + "message": "Potrebna je migracija ključa za šifriranje. Prijavi se na web trezoru za ažuriranje ključa za šifriranje." }, "editedFolder": { "message": "Mapa spremljena" @@ -1985,7 +1985,7 @@ "message": "Izvoz osobnog trezora u tijeku" }, "exportingIndividualVaultDescription": { - "message": "Only the individual vault items associated with $EMAIL$ will be exported. Organization vault items will not be included. Only vault item information will be exported and will not include associated attachments.", + "message": "Izvest će se samo stavke osobnog trezora povezanog s $EMAIL$. Stavke organizacijskog trezora neće biti uključene. Izvest će se samo informacija o stavci trezora bez pripadajućih podataka o povijesti lozinki i privitaka.", "placeholders": { "email": { "content": "$1", @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Podizbornik" + }, + "aliasDomain": { + "message": "Alias domene" } } diff --git a/apps/desktop/src/locales/hu/messages.json b/apps/desktop/src/locales/hu/messages.json index d9b383710ec..db32fd48655 100644 --- a/apps/desktop/src/locales/hu/messages.json +++ b/apps/desktop/src/locales/hu/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Almenü" + }, + "aliasDomain": { + "message": "Áldomain" } } diff --git a/apps/desktop/src/locales/id/messages.json b/apps/desktop/src/locales/id/messages.json index d4f87cee3a8..16ff465fee4 100644 --- a/apps/desktop/src/locales/id/messages.json +++ b/apps/desktop/src/locales/id/messages.json @@ -771,7 +771,7 @@ "message": "Hubungi kami" }, "helpAndFeedback": { - "message": "Help and feedback" + "message": "Bantuan dan masukan" }, "getHelp": { "message": "Dapatkan bantuan" @@ -1417,7 +1417,7 @@ "message": "Require password or PIN on app start" }, "recommendedForSecurity": { - "message": "Recommended for security." + "message": "Direkomendasikan untuk keamanan." }, "lockWithMasterPassOnRestart": { "message": "Kunci dengan kata sandi utama saat komputer dihidupkan ulang" @@ -1537,7 +1537,7 @@ "message": "Untuk menyelesaikan masuk dengan SSO, harap setel kata sandi utama untuk mengakses dan melindungi brankas Anda." }, "currentMasterPass": { - "message": "Current master password" + "message": "Kata sandi utama saat ini" }, "newMasterPass": { "message": "Kata Sandi Utama Baru" @@ -1973,7 +1973,7 @@ } }, "switchAccount": { - "message": "Switch account" + "message": "Pindah akun" }, "options": { "message": "Pilihan" @@ -1982,7 +1982,7 @@ "message": "Your session has timed out. Please go back and try logging in again." }, "exportingPersonalVaultTitle": { - "message": "Exporting individual vault" + "message": "Mengekspor brankas individu" }, "exportingIndividualVaultDescription": { "message": "Only the individual vault items associated with $EMAIL$ will be exported. Organization vault items will not be included. Only vault item information will be exported and will not include associated attachments.", @@ -2000,22 +2000,22 @@ "message": "Tidak terkunci" }, "generator": { - "message": "Generator" + "message": "Pembuat Sandi" }, "whatWouldYouLikeToGenerate": { - "message": "What would you like to generate?" + "message": "Apa yang ingin anda buat?" }, "passwordType": { - "message": "Password type" + "message": "Jenis kata sandi" }, "regenerateUsername": { - "message": "Regenerate username" + "message": "Buat nama pengguna baru" }, "generateUsername": { - "message": "Generate username" + "message": "Buat nama pengguna baru" }, "usernameType": { - "message": "Username type" + "message": "Jenis nama pengguna" }, "plusAddressedEmail": { "message": "Plus addressed email", @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/it/messages.json b/apps/desktop/src/locales/it/messages.json index 387dbf647c1..457ec571fee 100644 --- a/apps/desktop/src/locales/it/messages.json +++ b/apps/desktop/src/locales/it/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Sottomenu" + }, + "aliasDomain": { + "message": "Dominio alias" } } diff --git a/apps/desktop/src/locales/ja/messages.json b/apps/desktop/src/locales/ja/messages.json index ba26101b223..25bf40fe6a8 100644 --- a/apps/desktop/src/locales/ja/messages.json +++ b/apps/desktop/src/locales/ja/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "サブメニュー" + }, + "aliasDomain": { + "message": "エイリアスドメイン" } } diff --git a/apps/desktop/src/locales/ka/messages.json b/apps/desktop/src/locales/ka/messages.json index fb6177cfb4a..d3a13313e9e 100644 --- a/apps/desktop/src/locales/ka/messages.json +++ b/apps/desktop/src/locales/ka/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/km/messages.json b/apps/desktop/src/locales/km/messages.json index fb6177cfb4a..d3a13313e9e 100644 --- a/apps/desktop/src/locales/km/messages.json +++ b/apps/desktop/src/locales/km/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/kn/messages.json b/apps/desktop/src/locales/kn/messages.json index ca8961b2e28..14dfd27d429 100644 --- a/apps/desktop/src/locales/kn/messages.json +++ b/apps/desktop/src/locales/kn/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/ko/messages.json b/apps/desktop/src/locales/ko/messages.json index fc90ddd3054..31568e9c298 100644 --- a/apps/desktop/src/locales/ko/messages.json +++ b/apps/desktop/src/locales/ko/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/lt/messages.json b/apps/desktop/src/locales/lt/messages.json index e501ed2dd58..3d8adfa1209 100644 --- a/apps/desktop/src/locales/lt/messages.json +++ b/apps/desktop/src/locales/lt/messages.json @@ -476,7 +476,7 @@ "message": "Didžiausias failo dydis – 500 MB." }, "encryptionKeyMigrationRequired": { - "message": "Encryption key migration required. Please login through the web vault to update your encryption key." + "message": "Privaloma migruoti šifravimo raktą. Prašome prisijungti per internetinę saugyklą norint jį atnaujinti." }, "editedFolder": { "message": "Aplankas išsaugotas" @@ -849,117 +849,117 @@ "message": "Atsijungta nuo saugyklos" }, "vaultTimeoutDesc": { - "message": "Choose when your vault will take the vault timeout action." + "message": "Pasirinkite kada jūsų saugykla įvykdys laiko limito veiksmą." }, "immediately": { - "message": "Immediately" + "message": "Nedelsiant" }, "tenSeconds": { - "message": "10 seconds" + "message": "10 sekundžių" }, "twentySeconds": { - "message": "20 seconds" + "message": "20 sekundžių" }, "thirtySeconds": { - "message": "30 seconds" + "message": "30 sekundžių" }, "oneMinute": { - "message": "1 minute" + "message": "1 minutės" }, "twoMinutes": { - "message": "2 minutes" + "message": "2 minučių" }, "fiveMinutes": { - "message": "5 minutes" + "message": "5 minučių" }, "fifteenMinutes": { - "message": "15 minutes" + "message": "15 minučių" }, "thirtyMinutes": { - "message": "30 minutes" + "message": "30 minučių" }, "oneHour": { - "message": "1 hour" + "message": "1 valandos" }, "fourHours": { - "message": "4 hours" + "message": "4 valandų" }, "onIdle": { - "message": "On system idle" + "message": "Sistemai būnant neaktyviai" }, "onSleep": { - "message": "On system sleep" + "message": "Sistemai užmigus" }, "onLocked": { - "message": "On system lock" + "message": "Sistemą užrakinus" }, "onRestart": { - "message": "On restart" + "message": "Paleidus programą iš naujo" }, "never": { - "message": "Never" + "message": "Niekada" }, "security": { - "message": "Security" + "message": "Apsauga" }, "clearClipboard": { - "message": "Clear clipboard", + "message": "Išvalyti iškarpinę", "description": "Clipboard is the operating system thing where you copy/paste data to on your device." }, "clearClipboardDesc": { - "message": "Automatically clear copied values from your clipboard.", + "message": "Automatiškai išvalyti nukopijuotas reikšmes iškarpinėje.", "description": "Clipboard is the operating system thing where you copy/paste data to on your device." }, "enableFavicon": { - "message": "Show website icons" + "message": "Rodyti tinklalapių ikonėles" }, "faviconDesc": { - "message": "Show a recognizable image next to each login." + "message": "Prie kiekvieno prisijungimo parodykite atpažįstamą vaizdą." }, "enableMinToTray": { - "message": "Minimize to tray icon" + "message": "Sumažinti į užduočių juostos piktogramą" }, "enableMinToTrayDesc": { - "message": "When minimizing the window, show an icon in the system tray instead." + "message": "Sumažinus langą, rodyti ikoną užduočių juostoje." }, "enableMinToMenuBar": { - "message": "Minimize to menu bar" + "message": "Sumažinti meniu juostoje" }, "enableMinToMenuBarDesc": { - "message": "When minimizing the window, show an icon in the menu bar instead." + "message": "Sumažinus langą, rodyti ikoną užduočių juostoje." }, "enableCloseToTray": { - "message": "Close to tray icon" + "message": "Uždarymo į užduočių juostą ikona" }, "enableCloseToTrayDesc": { - "message": "When closing the window, show an icon in the system tray instead." + "message": "Uždarius langą, rodyti ikoną užduočių juostoje." }, "enableCloseToMenuBar": { - "message": "Close to menu bar" + "message": "Uždaryti meniu juostoje" }, "enableCloseToMenuBarDesc": { - "message": "When closing the window, show an icon in the menu bar instead." + "message": "Uždarius langą, rodyti ikoną užduočių juostoje." }, "enableTray": { - "message": "Show tray icon" + "message": "Rodyti užduočių juostos ikoną" }, "enableTrayDesc": { - "message": "Always show an icon in the system tray." + "message": "Visada rodyti ikoną užduočių juostoje." }, "startToTray": { - "message": "Start to tray icon" + "message": "Paleisti su užduočių juostos ikona" }, "startToTrayDesc": { - "message": "When the application is first started, only show an icon in the system tray." + "message": "Paleidus programą, rodyti tik ikoną užduočių juostoje." }, "startToMenuBar": { - "message": "Start to menu bar" + "message": "Pradėti užduočių juostoje" }, "startToMenuBarDesc": { - "message": "When the application is first started, only show an icon in the menu bar." + "message": "Paleidus programą, rodyti tik ikoną užduočių juostoje." }, "openAtLogin": { - "message": "Start automatically on login" + "message": "Automatiškai pasileisti prisijungus" }, "openAtLoginDesc": { "message": "Prisijungus pradėti Bitwarden darbalaukio aplikaciją automatiškai." @@ -971,10 +971,10 @@ "message": "Rodyti Bitwarden ikoną, esančią Dock, net kai ji sumažinta į meniu juostą." }, "confirmTrayTitle": { - "message": "Patvirtinti sumažinimą informacijos srityje" + "message": "Patvirtinti sumažinimą užduočių juostoje" }, "confirmTrayDesc": { - "message": "Išjungus šį nustatymą bus išjungti visi kiti su informacijos sritimi susiję nustatymai." + "message": "Išjungus šį nustatymą bus išjungti visi kiti su užduočių juosta susiję nustatymai." }, "language": { "message": "Kalba" @@ -1269,7 +1269,7 @@ "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." }, "hideToTray": { - "message": "Paslėpti" + "message": "Paslėpti užduočių juostoje" }, "alwaysOnTop": { "message": "Visada viršuje", @@ -1371,44 +1371,44 @@ "message": "Silpnas pagrindinis slaptažodis" }, "weakMasterPasswordDesc": { - "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" + "message": "Jūsų pasirinktas pagrindinis slaptažodis yra silpnas. Jums reikėtų naudoti stiprų pagrindinį slaptažodį (arba slaptą frazę) norint apsaugoti savo Bitwarden paskyrą. Ar Jūs tikrai norite naudoti šį pagrindinį slaptažodį?" }, "pin": { "message": "PIN", "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." }, "unlockWithPin": { - "message": "Unlock with PIN" + "message": "Atrakinti PIN kodu" }, "setYourPinCode": { - "message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application." + "message": "Nustatykite savo PIN kodą, kad atrakintumėte „Bitwarden“. Jūsų PIN nustatymai bus nustatyti iš naujo, jei kada nors visiškai atsijungsite nuo programos." }, "pinRequired": { - "message": "PIN code is required." + "message": "PIN kodas yra privalomas." }, "invalidPin": { - "message": "Invalid PIN code." + "message": "Neteisingas PIN kodas." }, "unlockWithWindowsHello": { - "message": "Unlock with Windows Hello" + "message": "Atrakinti naudojant Windows Hello" }, "additionalWindowsHelloSettings": { - "message": "Additional Windows Hello settings" + "message": "Papildomi Windows Hello nustatymai" }, "windowsHelloConsentMessage": { - "message": "Verify for Bitwarden." + "message": "Patvirtinti Bitwarden." }, "unlockWithTouchId": { - "message": "Unlock with Touch ID" + "message": "Atrakinti naudojant Touch ID" }, "additionalTouchIdSettings": { - "message": "Additional Touch ID settings" + "message": "Papildomi Touch ID nustatymai" }, "touchIdConsentMessage": { - "message": "unlock your vault" + "message": "atrakinti saugyklą" }, "autoPromptWindowsHello": { - "message": "Ask for Windows Hello on app start" + "message": "Paprašyti Windows Hello paleidus programą" }, "autoPromptTouchId": { "message": "Prašyti Touch ID paleidus programėlę" @@ -1522,7 +1522,7 @@ "message": "Ištrinti visam laikui" }, "vaultTimeoutLogOutConfirmation": { - "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + "message": "Atsijungus bus pašalinta visa prieiga prie saugyklos, o pasibaigus skirtajam laikotarpiui reikės autentifikuotis prisijungus. Ar tikrai norite naudoti šį nustatymą?" }, "vaultTimeoutLogOutConfirmationTitle": { "message": "Laiko limito atjungimo veiksmo patvirtinimas" @@ -1663,7 +1663,7 @@ "message": "Organizacijos politika turi įtakos jūsų nuosavybės galimybėms." }, "allSends": { - "message": "Visi Siuntiniai", + "message": "Visi Sendai", "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendTypeFile": { @@ -1673,11 +1673,11 @@ "message": "Tekstas" }, "searchSends": { - "message": "Ieškoti Siuntinių", + "message": "Ieškoti Sendų", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "editSend": { - "message": "Redaguoti Siuntinį", + "message": "Redaguoti Sendą", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "myVault": { @@ -1690,14 +1690,14 @@ "message": "Ištrynimo data" }, "deletionDateDesc": { - "message": "Nurodytos datos ir laiko metu Siuntinys bus visam laikui ištrintas.", + "message": "Nurodytos datos ir laiko metu Sendo bus visam laikui ištrintas.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "expirationDate": { "message": "Galiojimo data" }, "expirationDateDesc": { - "message": "Jei nustatyta, prieiga prie šio Siuntinio nustos galioti pasiekus nurodytą datą ir laiką.", + "message": "Jei nustatyta, prieiga prie šio Sendo nustos galioti pasiekus nurodytą datą ir laiką.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "maxAccessCount": { @@ -1705,67 +1705,67 @@ "description": "This text will be displayed after a Send has been accessed the maximum amount of times." }, "maxAccessCountDesc": { - "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "message": "Jei nustatyta, vartotojai nebegalės pasiekti šio siuntimo, kai bus pasiektas maksimalus prisijungimų skaičius.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "currentAccessCount": { - "message": "Current access count" + "message": "Dabartinis prisijungimų skaičius" }, "disableSend": { - "message": "Deactivate this Send so that no one can access it.", + "message": "Išjunkite šį siuntimą, kad niekas negalėtų jo pasiekti.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendPasswordDesc": { - "message": "Optionally require a password for users to access this Send.", + "message": "Pasirinktinai reikalauti slaptažodžio, kad vartotojai galėtų pasiekti šį siuntimą.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendNotesDesc": { - "message": "Private notes about this Send.", + "message": "Asmeninės pastabos apie šį Sendą.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendLink": { - "message": "Send link", + "message": "Siųsti nuorodą", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendLinkLabel": { - "message": "Send link", + "message": "Siųsti nuorodą", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "textHiddenByDefault": { - "message": "When accessing the Send, hide the text by default", + "message": "Kai pasiekiate Sendą, pagal numatytuosius nustatymus paslėpkite tekstą", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "createdSend": { - "message": "Send added", + "message": "Sendas pridėtas", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "editedSend": { - "message": "Send saved", + "message": "Sendas išsaugotas", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "deletedSend": { - "message": "Send deleted", + "message": "Sendas ištrintas", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "newPassword": { - "message": "New password" + "message": "Naujas slaptažodis" }, "whatTypeOfSend": { - "message": "What type of Send is this?", + "message": "Kokios rūšies šis Sendas?", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "createSend": { - "message": "New Send", + "message": "Naujas Send", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendTextDesc": { - "message": "The text you want to send." + "message": "Tekstas, kurį norite siųsti." }, "sendFileDesc": { - "message": "The file you want to send." + "message": "Failas, kurį norite siųsti." }, "days": { - "message": "$DAYS$ days", + "message": "$DAYS$ dienos", "placeholders": { "days": { "content": "$1", @@ -1774,98 +1774,98 @@ } }, "oneDay": { - "message": "1 day" + "message": "1 d" }, "custom": { - "message": "Custom" + "message": "Pasirinktinis" }, "deleteSendConfirmation": { - "message": "Are you sure you want to delete this Send?", + "message": "Ar tikrai norite ištrinti šį Sendą?", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "copySendLinkToClipboard": { - "message": "Copy Send link to clipboard", + "message": "Kopijuoti Sendą į iškarpinę", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "copySendLinkOnSave": { - "message": "Copy the link to share this Send to my clipboard upon save." + "message": "Išsaugojus nukopijuoti nuorodą, kad būtų galima pasidalinti šiuo Sendu mano iškarpinėje." }, "sendDisabled": { - "message": "Send removed", + "message": "Sendas pašalintas", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "sendDisabledWarning": { - "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "message": "Dėl įmonės politikos galite ištrinti tik esamą Sendą.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "copyLink": { - "message": "Copy link" + "message": "Kopijuoti nuorodą" }, "disabled": { - "message": "Disabled" + "message": "Išjungta" }, "removePassword": { - "message": "Remove password" + "message": "Šalinti slaptažodį" }, "removedPassword": { - "message": "Password removed" + "message": "Slaptažodis pašalintas" }, "removePasswordConfirmation": { - "message": "Are you sure you want to remove the password?" + "message": "Ar tikrai norite pašalinti slaptažodį?" }, "maxAccessCountReached": { - "message": "Max access count reached" + "message": "Pasiektas maksimalus prisijungimų skaičius" }, "expired": { - "message": "Expired" + "message": "Nebegalioja" }, "pendingDeletion": { - "message": "Pending deletion" + "message": "Laukiama ištrynimo" }, "webAuthnAuthenticate": { - "message": "Authenticate WebAuthn" + "message": "Autentifikuoti WebAuthn" }, "hideEmail": { - "message": "Hide my email address from recipients." + "message": "Slėpti mano el. pašto adresą nuo gavėjų." }, "sendOptionsPolicyInEffect": { - "message": "One or more organization policies are affecting your Send options." + "message": "Viena ar daugiau organizacijos politikų turi įtakos jūsų Sendo nustatymams." }, "emailVerificationRequired": { - "message": "Email verification required" + "message": "Reikalingas elektroninio pašto patvirtinimas" }, "emailVerificationRequiredDesc": { - "message": "You must verify your email to use this feature." + "message": "Privalote patvirtinti savo el. paštą norint naudotis šia funkcija." }, "passwordPrompt": { - "message": "Master password re-prompt" + "message": "Iš naujo prašoma pagrindinio slaptažodžio" }, "passwordConfirmation": { - "message": "Master password confirmation" + "message": "Pagrindinio slaptažodžio patvirtinimas" }, "passwordConfirmationDesc": { - "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + "message": "Šis veiksmas yra apsaugotas. Jei norite tęsti, iš naujo įveskite pagrindinį slaptažodį, kad patvirtintumėte savo tapatybę." }, "updatedMasterPassword": { - "message": "Updated master password" + "message": "Atnaujintas pagrindinis slaptažodis" }, "updateMasterPassword": { - "message": "Update master password" + "message": "Atnaujinti pagrindinį slaptažodį" }, "updateMasterPasswordWarning": { - "message": "Your master password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + "message": "Jūsų pagrindinį slaptažodį neseniai pakeitė jūsų organizacijos administratorius. Kad galėtumėte pasiekti saugyklą, dabar turite atnaujinti pagrindinį slaptažodį. Tęsdami būsite atjungti nuo dabartinės sesijos, todėl turėsite vėl prisijungti. Aktyvios sesijos kituose įrenginiuose gali išlikti aktyvios iki vienos valandos." }, "updateWeakMasterPasswordWarning": { - "message": "Your master password does not meet one or more of your organization policies. In order to access the vault, you must update your master password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + "message": "Jūsų pagrindinis slaptažodis neatitinka vieno ar kelių organizacijos slaptažodžiui keliamų reikalavimų. Norėdami prisijungti prie saugyklos, jūs turite atnaujinti savo pagrindinį slaptažodį. Jeigu nuspręsite tęsti, jūs būsite atjungti nuo dabartinės sesijos ir jums reikės vėl prisijungti. Visos aktyvios sesijos kituose įrenginiuose gali išlikti aktyvios iki vienos valandos." }, "hours": { - "message": "Hours" + "message": "Valandų" }, "minutes": { - "message": "Minutes" + "message": "Minučių" }, "vaultTimeoutPolicyInEffect": { - "message": "Your organization policies have set your maximum allowed vault timeout to $HOURS$ hour(s) and $MINUTES$ minute(s).", + "message": "Jūsų organizacijos politika pakeitė didžiausią leidžiamą saugyklos laiko limitą į $HOURS$ valandas(-ų) ir $MINUTES$ minutes(-čių).", "placeholders": { "hours": { "content": "$1", @@ -1878,7 +1878,7 @@ } }, "vaultTimeoutPolicyWithActionInEffect": { - "message": "Your organization policies are affecting your vault timeout. Maximum allowed vault timeout is $HOURS$ hour(s) and $MINUTES$ minute(s). Your vault timeout action is set to $ACTION$.", + "message": "Jūsų organizacijos politika apriboja jūsų saugyklos neaktyvumo laiko nustatymus. Maksimalus leidžiamas saugyklos neaktyvumo laikas yra $HOURS$ valanda(-os) ir $MINUTES$ minutė(s). Jūsų saugyklos neaktyvumo laikas yra nustatytas $ACTION$.", "placeholders": { "hours": { "content": "$1", @@ -1895,7 +1895,7 @@ } }, "vaultTimeoutActionPolicyInEffect": { - "message": "Your organization policies have set your vault timeout action to $ACTION$.", + "message": "Jūsų organizacija nustatė saugyklos neaktyvumo trukmę $ACTION$.", "placeholders": { "action": { "content": "$1", @@ -1904,7 +1904,7 @@ } }, "vaultTimeoutTooLarge": { - "message": "Your vault timeout exceeds the restrictions set by your organization." + "message": "Jūsų saugyklos skirtasis laikas viršija jūsų organizacijos nustatytus apribojimus." }, "resetPasswordPolicyAutoEnroll": { "message": "Automatinis įtraukimas" @@ -1928,7 +1928,7 @@ "message": "Pagrindinis slaptažodis pašalintas" }, "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.", + "message": "$ORGANIZATION$ naudoja SSO su savarankiškai sukurtu raktų serveriu. Pagrindinis slaptažaodis nebėra reikalingas norint šios organizacijos nariams prisijungti.", "placeholders": { "organization": { "content": "$1", @@ -1937,34 +1937,34 @@ } }, "leaveOrganization": { - "message": "Leave organization" + "message": "Palikti organizaciją" }, "leaveOrganizationConfirmation": { - "message": "Are you sure you want to leave this organization?" + "message": "Ar tikrai norite palikti šią organizaciją?" }, "leftOrganization": { - "message": "You have left the organization." + "message": "Jūs palikote organizaciją." }, "ssoKeyConnectorError": { - "message": "Key connector error: make sure key connector is available and working correctly." + "message": "Rakto prisijungimo klaida: įsitikinkite kad rakto prisijungimas prieinamas ir veikia tinkamai." }, "lockAllVaults": { - "message": "Lock all vaults" + "message": "Užrakinti visas saugyklas" }, "accountLimitReached": { - "message": "No more than 5 accounts may be logged in at the same time." + "message": "Vienu metu negali būti prisijungusios daugiau nei 5 paskyros." }, "accountPreferences": { - "message": "Preferences" + "message": "Nuostatos" }, "appPreferences": { - "message": "App settings (all accounts)" + "message": "Programos nustatymai (visoms paskyroms)" }, "accountSwitcherLimitReached": { - "message": "Account limit reached. Log out of an account to add another." + "message": "Paskyrų limitas pasiektas. Norint pridėti kitą, atsijunkite iš paskyros." }, "settingsTitle": { - "message": "App settings for $EMAIL$", + "message": "Programos nustatymai $EMAIL$", "placeholders": { "email": { "content": "$1", @@ -1973,19 +1973,19 @@ } }, "switchAccount": { - "message": "Switch account" + "message": "Perjungti paskyrą" }, "options": { - "message": "Options" + "message": "Nustatymai" }, "sessionTimeout": { - "message": "Your session has timed out. Please go back and try logging in again." + "message": "Jūsų sesija pasibaigė. Prašome grįžti ir prisijungti iš naujo." }, "exportingPersonalVaultTitle": { - "message": "Exporting individual vault" + "message": "Eksportuojama individuali saugykla" }, "exportingIndividualVaultDescription": { - "message": "Only the individual vault items associated with $EMAIL$ will be exported. Organization vault items will not be included. Only vault item information will be exported and will not include associated attachments.", + "message": "Bus eksportuoti tik saugyklos elementai kurie susiję su $EMAIL$. Organizacijos saugyklos elementai nebus įtraukti. Bus eksportuota tik saugyklos elementų informaciją, be susijusių priedų.", "placeholders": { "email": { "content": "$1", @@ -1994,111 +1994,111 @@ } }, "locked": { - "message": "Locked" + "message": "Užrakinta" }, "unlocked": { - "message": "Unlocked" + "message": "Atrakinta" }, "generator": { - "message": "Generator" + "message": "Generatorius" }, "whatWouldYouLikeToGenerate": { - "message": "What would you like to generate?" + "message": "Ką norėtumėte sugeneruoti?" }, "passwordType": { - "message": "Password type" + "message": "Slaptažodžio tipas" }, "regenerateUsername": { - "message": "Regenerate username" + "message": "Generuoti naują vartotojo vardą iš naujo" }, "generateUsername": { - "message": "Generate username" + "message": "Sugeneruoti naują vartotojo vardą" }, "usernameType": { - "message": "Username type" + "message": "Vartotojo vardo tipas" }, "plusAddressedEmail": { - "message": "Plus addressed email", + "message": "Plius adresuotas el. paštas", "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" }, "plusAddressedEmailDesc": { - "message": "Use your email provider's sub-addressing capabilities." + "message": "Pasinaudokite el. pašto teikėjo antrinio adreso galimybėmis." }, "catchallEmail": { - "message": "Catch-all email" + "message": "Viską palaikantis el. paštas" }, "catchallEmailDesc": { - "message": "Use your domain's configured catch-all inbox." + "message": "Naudokite savo domeno sukonfigūruotą viską palaikančią pašto dežutę." }, "random": { - "message": "Random" + "message": "Atsitiktinis" }, "randomWord": { - "message": "Random word" + "message": "Atsitiktinis žodis" }, "websiteName": { - "message": "Website name" + "message": "Svetainės pavadinimas" }, "service": { - "message": "Service" + "message": "Paslauga" }, "allVaults": { - "message": "All vaults" + "message": "Visos saugyklos" }, "searchOrganization": { - "message": "Search organization" + "message": "Ieškoti organizacijoje" }, "searchMyVault": { - "message": "Search my vault" + "message": "Ieškoti saugykloje" }, "forwardedEmail": { - "message": "Forwarded email alias" + "message": "Persiunčiamas el. pašto slapyvardis" }, "forwardedEmailDesc": { - "message": "Generate an email alias with an external forwarding service." + "message": "Sugeneruoti el. pašto slapyvardį su išorine persiuntimo paslauga." }, "hostname": { - "message": "Hostname", + "message": "Pagrindinio kompiuterio vardas", "description": "Part of a URL." }, "apiAccessToken": { - "message": "API Access Token" + "message": "API prieigos raktas" }, "apiKey": { - "message": "API key" + "message": "API raktas" }, "premiumSubcriptionRequired": { - "message": "Premium subscription required" + "message": "Reikalingas Premium abonementas" }, "organizationIsDisabled": { - "message": "Organization suspended" + "message": "Organizacija suspenduota" }, "disabledOrganizationFilterError": { - "message": "Items in suspended organizations cannot be accessed. Contact your organization owner for assistance." + "message": "Elementai esantys suspenduotose organizacijose yra neprieinami. Susisiekite su savo organizacijos savininku." }, "neverLockWarning": { - "message": "Are you sure you want to use the \"Never\" option? Setting your lock options to \"Never\" stores your vault's encryption key on your device. If you use this option you should ensure that you keep your device properly protected." + "message": "Ar jūs tikrai norite naudoti \"Niekada\" pasirinkimą? Nustačius savo užraktą į \"Niekada\", saugyklos šifravimo raktas bus laikomas jūsų įrenginyje. Jei norite naudotis šiuo pasirinkimu, užtikrinkite savo įrenginio saugą." }, "vault": { - "message": "Vault" + "message": "Saugykla" }, "loginWithMasterPassword": { - "message": "Log in with master password" + "message": "Prisijungti su pagrindiniu slaptažodžiu" }, "loggingInAs": { - "message": "Logging in as" + "message": "Prisijungimas kaip" }, "rememberEmail": { - "message": "Remember email" + "message": "Prisiminti el. paštą" }, "notYou": { - "message": "Not you?" + "message": "Ne jūs?" }, "newAroundHere": { - "message": "New around here?" + "message": "Ar jūs naujas čia?" }, "loggingInTo": { - "message": "Logging in to $DOMAIN$", + "message": "Prisijungiama prie $DOMAIN$", "placeholders": { "domain": { "content": "$1", @@ -2107,38 +2107,38 @@ } }, "logInWithAnotherDevice": { - "message": "Log in with another device" + "message": "Prisijungti su kitu įrenginiu" }, "loginInitiated": { - "message": "Login initiated" + "message": "Pradėtas prisijungimas" }, "notificationSentDevice": { - "message": "A notification has been sent to your device." + "message": "Į jūsų įrenginį išsiųstas pranešimas." }, "fingerprintMatchInfo": { - "message": "Please make sure your vault is unlocked and Fingerprint phrase matches the other device." + "message": "Prašome užtikrinti jog jūsų saugykla atrakinta ir piršto antspaudo frazė sutampa su kitu įrenginiu." }, "fingerprintPhraseHeader": { - "message": "Fingerprint phrase" + "message": "Piršto antspaudo frazė" }, "needAnotherOption": { - "message": "Log in with device must be set up in the settings of the Bitwarden app. Need another option?" + "message": "Prisijungimas su įrenginiu turi būti nustatytas Bitwarden aplikacijos nustatymuose. Reikia kito pasirinkimo?" }, "viewAllLoginOptions": { - "message": "View all login options" + "message": "Peržiūrėti visas prisijungimo parinktis" }, "resendNotification": { - "message": "Resend notification" + "message": "Iš naujo siųsti pranešimą" }, "toggleCharacterCount": { - "message": "Toggle character count", + "message": "Perjungti simbolių skaičių", "description": "'Character count' describes a feature that displays a number next to each character of the password." }, "areYouTryingtoLogin": { - "message": "Are you trying to log in?" + "message": "Ar bandote prisijungti?" }, "logInAttemptBy": { - "message": "Login attempt by $EMAIL$", + "message": "Prisijungimo bandymas iš $EMAIL$", "placeholders": { "email": { "content": "$1", @@ -2147,25 +2147,25 @@ } }, "deviceType": { - "message": "Device Type" + "message": "Įrenginio tipas" }, "ipAddress": { - "message": "IP Address" + "message": "IP adresas" }, "time": { - "message": "Time" + "message": "Laikas" }, "confirmLogIn": { - "message": "Confirm login" + "message": "Patvirtinkite prisijungimą" }, "denyLogIn": { - "message": "Deny login" + "message": "Neleisti prisijungti" }, "approveLoginRequests": { - "message": "Approve login requests" + "message": "Patvirtinti prisijungimo užklausas" }, "logInConfirmedForEmailOnDevice": { - "message": "Login confirmed for $EMAIL$ on $DEVICE$", + "message": "$EMAIL$ prisijungimas patvirtinas $DEVICE$ įrenginyje", "placeholders": { "email": { "content": "$1", @@ -2178,13 +2178,13 @@ } }, "youDeniedALogInAttemptFromAnotherDevice": { - "message": "You denied a login attempt from another device. If this really was you, try to log in with the device again." + "message": "Jūs neleidote prisijungti iš kito įrenginio. Jei tai tikrai buvote jūs, bandykite vėl prisijungti iš įrenginio." }, "justNow": { - "message": "Just now" + "message": "Ką tik" }, "requestedXMinutesAgo": { - "message": "Requested $MINUTES$ minutes ago", + "message": "Pateikta užklausa prieš $MINUTES$ minučių", "placeholders": { "minutes": { "content": "$1", @@ -2193,16 +2193,16 @@ } }, "loginRequestHasAlreadyExpired": { - "message": "Login request has already expired." + "message": "Prisijungimo prašymas jau pasibaigęs." }, "thisRequestIsNoLongerValid": { - "message": "This request is no longer valid." + "message": "Ši užklausa nebegalioja." }, "approveLoginRequestDesc": { - "message": "Use this device to approve login requests made from other devices." + "message": "Naudokite šį įrenginį, kad patvirtintumėte prisijungimo užklausas, pateiktas iš kitų įrenginių." }, "confirmLoginAtemptForMail": { - "message": "Confirm login attempt for $EMAIL$", + "message": "Patvirtinti bandymą prisijungti iš $EMAIL$", "placeholders": { "email": { "content": "$1", @@ -2211,31 +2211,31 @@ } }, "logInRequested": { - "message": "Log in requested" + "message": "Prašoma prisijungti" }, "exposedMasterPassword": { - "message": "Exposed Master Password" + "message": "Atskleistas pagrindinis slaptažodis" }, "exposedMasterPasswordDesc": { - "message": "Password found in a data breach. Use a unique password to protect your account. Are you sure you want to use an exposed password?" + "message": "Slaptažodis rastas duomenų pažeidimo metu. Norėdami apsaugoti paskyrą, naudokite unikalų slaptažodį. Ar tikrai norite naudoti atvirą slaptažodį?" }, "weakAndExposedMasterPassword": { - "message": "Weak and Exposed Master Password" + "message": "Silpnas ir atskleistas pagrindinis slaptažodis" }, "weakAndBreachedMasterPasswordDesc": { - "message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?" + "message": "Silpnas slaptažodis nustatytas ir rastas per duomenų pažeidimą. Norėdami apsaugoti paskyrą, naudokite stiprų ir unikalų slaptažodį. Ar tikrai norite naudoti šį slaptažodį?" }, "checkForBreaches": { - "message": "Check known data breaches for this password" + "message": "Patikrinti žinomus šio slaptažodžio duomenų pažeidimus" }, "important": { - "message": "Important:" + "message": "Svarbu:" }, "masterPasswordHint": { - "message": "Your master password cannot be recovered if you forget it!" + "message": "Pagrindinis slaptažodis negali būti atkurtas, jei jį pamiršite!" }, "characterMinimum": { - "message": "$LENGTH$ character minimum", + "message": "Mažiausiai $LENGTH$ simboliai", "placeholders": { "length": { "content": "$1", @@ -2244,41 +2244,41 @@ } }, "windowsBiometricUpdateWarning": { - "message": "Bitwarden recommends updating your biometric settings to require your master password (or PIN) on the first unlock. Would you like to update your settings now?" + "message": "Bitwarden rekomenduoja atnaujinti savo biometrinius nustatymus, jog pirmo atrakinimo metu būtų reikalaujama pagrindinio slaptažodžio (arba PIN). Ar norėtumėte atnaujinti savo nustatymus dabar?" }, "windowsBiometricUpdateWarningTitle": { - "message": "Recommended Settings Update" + "message": "Rekomenduojamas nustatymų atnaujinimas" }, "deviceApprovalRequired": { - "message": "Device approval required. Select an approval option below:" + "message": "Įrenginio patvirtinimas reikalingas. Pasirinkite patvirtinimo būdą toliau:" }, "rememberThisDevice": { - "message": "Remember this device" + "message": "Prisiminti šį įrenginį" }, "uncheckIfPublicDevice": { - "message": "Uncheck if using a public device" + "message": "Nežymėti, jei naudojamas viešasis įrenginys" }, "approveFromYourOtherDevice": { - "message": "Approve from your other device" + "message": "Patvirtinti iš kito jūsų įrenginio" }, "requestAdminApproval": { - "message": "Request admin approval" + "message": "Prašyti administratoriaus patvirtinimo" }, "approveWithMasterPassword": { - "message": "Approve with master password" + "message": "Patvirtinti su pagrindiniu slaptažodžiu" }, "region": { - "message": "Region" + "message": "Regionas" }, "ssoIdentifierRequired": { - "message": "Organization SSO identifier is required." + "message": "Organizacijos SSO identifikatorius yra reikalingas." }, "eu": { - "message": "EU", + "message": "ES", "description": "European Union" }, "loggingInOn": { - "message": "Logging in on" + "message": "Prisijungiama prie" }, "usDomain": { "message": "bitwarden.com" @@ -2287,46 +2287,46 @@ "message": "bitwarden.eu" }, "selfHostedServer": { - "message": "self-hosted" + "message": "savarankiškai sukurtas" }, "accessDenied": { - "message": "Access denied. You do not have permission to view this page." + "message": "Prieiga uždrausta. Neturite teisės peržiūrėti šį puslapį." }, "accountSuccessfullyCreated": { - "message": "Account successfully created!" + "message": "Paskyra sėkmingai sukurta!" }, "adminApprovalRequested": { - "message": "Admin approval requested" + "message": "Prašomas administratoriaus patvirtinimas" }, "adminApprovalRequestSentToAdmins": { - "message": "Your request has been sent to your admin." + "message": "Jūsų prašymas išsiųstas administratoriui." }, "youWillBeNotifiedOnceApproved": { - "message": "You will be notified once approved." + "message": "Jums bus pranešta, kai bus patvirtinta." }, "troubleLoggingIn": { - "message": "Trouble logging in?" + "message": "Nepavyksta prisijungti?" }, "loginApproved": { - "message": "Login approved" + "message": "Prisijungimas patvirtintas" }, "userEmailMissing": { - "message": "User email missing" + "message": "Trūksta naudotojo el. pašto" }, "deviceTrusted": { - "message": "Device trusted" + "message": "Patikimas įrenginys" }, "inputRequired": { - "message": "Input is required." + "message": "Įvestis yra būtina." }, "required": { - "message": "required" + "message": "privaloma" }, "search": { - "message": "Search" + "message": "Ieškoti" }, "inputMinLength": { - "message": "Input must be at least $COUNT$ characters long.", + "message": "Įvestis turi būti bent $COUNT$ simbolių ilgio.", "placeholders": { "count": { "content": "$1", @@ -2335,7 +2335,7 @@ } }, "inputMaxLength": { - "message": "Input must not exceed $COUNT$ characters in length.", + "message": "Įvestis negali būti ilgesnė už $COUNT$ simbolių.", "placeholders": { "count": { "content": "$1", @@ -2344,7 +2344,7 @@ } }, "inputForbiddenCharacters": { - "message": "The following characters are not allowed: $CHARACTERS$", + "message": "Šie simboliai yra neleidžiami: $CHARACTERS$", "placeholders": { "characters": { "content": "$1", @@ -2353,7 +2353,7 @@ } }, "inputMinValue": { - "message": "Input value must be at least $MIN$.", + "message": "Įvesties reikšmė turi būti bent $MIN$.", "placeholders": { "min": { "content": "$1", @@ -2362,7 +2362,7 @@ } }, "inputMaxValue": { - "message": "Input value must not exceed $MAX$.", + "message": "Įvesties reikšmė negali viršyti $MAX$.", "placeholders": { "max": { "content": "$1", @@ -2371,17 +2371,17 @@ } }, "multipleInputEmails": { - "message": "1 or more emails are invalid" + "message": "1 ar daugiau el. paštų yra netinkami" }, "inputTrimValidator": { - "message": "Input must not contain only whitespace.", + "message": "Įvestis negali būti sudaryta tik iš tarpų.", "description": "Notification to inform the user that a form's input can't contain only whitespace." }, "inputEmail": { - "message": "Input is not an email address." + "message": "Įvestis nėra el. pašto adresas." }, "fieldsNeedAttention": { - "message": "$COUNT$ field(s) above need your attention.", + "message": "$COUNT$ laukeliai viršuje yra klaidingi.", "placeholders": { "count": { "content": "$1", @@ -2390,22 +2390,22 @@ } }, "selectPlaceholder": { - "message": "-- Select --" + "message": "-- Pasirinkti --" }, "multiSelectPlaceholder": { - "message": "-- Type to filter --" + "message": "-- Rašykite, kad filtruoti --" }, "multiSelectLoading": { - "message": "Retrieving options..." + "message": "Gaunami pasirinkimai..." }, "multiSelectNotFound": { - "message": "No items found" + "message": "Elementų nerasta" }, "multiSelectClearAll": { - "message": "Clear all" + "message": "Išvalyti viską" }, "plusNMore": { - "message": "+ $QUANTITY$ more", + "message": "+$QUANTITY$ daugiau", "placeholders": { "quantity": { "content": "$1", @@ -2414,6 +2414,9 @@ } }, "submenu": { - "message": "Submenu" + "message": "Submeniu" + }, + "aliasDomain": { + "message": "Alias domenas" } } diff --git a/apps/desktop/src/locales/lv/messages.json b/apps/desktop/src/locales/lv/messages.json index 4146ccc59cb..4c20c44f867 100644 --- a/apps/desktop/src/locales/lv/messages.json +++ b/apps/desktop/src/locales/lv/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Apakšizvēlne" + }, + "aliasDomain": { + "message": "Aizstājdomēns" } } diff --git a/apps/desktop/src/locales/me/messages.json b/apps/desktop/src/locales/me/messages.json index 66f90e8c989..6c664efa5b9 100644 --- a/apps/desktop/src/locales/me/messages.json +++ b/apps/desktop/src/locales/me/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/ml/messages.json b/apps/desktop/src/locales/ml/messages.json index d7a6814e8a9..be26f4c695a 100644 --- a/apps/desktop/src/locales/ml/messages.json +++ b/apps/desktop/src/locales/ml/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/mr/messages.json b/apps/desktop/src/locales/mr/messages.json index fb6177cfb4a..d3a13313e9e 100644 --- a/apps/desktop/src/locales/mr/messages.json +++ b/apps/desktop/src/locales/mr/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/my/messages.json b/apps/desktop/src/locales/my/messages.json index bc52b76f5db..e1d87b2e073 100644 --- a/apps/desktop/src/locales/my/messages.json +++ b/apps/desktop/src/locales/my/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/nb/messages.json b/apps/desktop/src/locales/nb/messages.json index 55262558144..ded2c66b6d2 100644 --- a/apps/desktop/src/locales/nb/messages.json +++ b/apps/desktop/src/locales/nb/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/ne/messages.json b/apps/desktop/src/locales/ne/messages.json index 2db4d1eb3e6..b0e7c9b0b37 100644 --- a/apps/desktop/src/locales/ne/messages.json +++ b/apps/desktop/src/locales/ne/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/nl/messages.json b/apps/desktop/src/locales/nl/messages.json index d0c7991b2b2..f2b621cdcdc 100644 --- a/apps/desktop/src/locales/nl/messages.json +++ b/apps/desktop/src/locales/nl/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Aliasdomein" } } diff --git a/apps/desktop/src/locales/nn/messages.json b/apps/desktop/src/locales/nn/messages.json index 9a235d5853a..ebc40d5f817 100644 --- a/apps/desktop/src/locales/nn/messages.json +++ b/apps/desktop/src/locales/nn/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/or/messages.json b/apps/desktop/src/locales/or/messages.json index 9581b28d06a..c69a78977d0 100644 --- a/apps/desktop/src/locales/or/messages.json +++ b/apps/desktop/src/locales/or/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/pl/messages.json b/apps/desktop/src/locales/pl/messages.json index ca4027153f8..9420bf4d6ed 100644 --- a/apps/desktop/src/locales/pl/messages.json +++ b/apps/desktop/src/locales/pl/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Podmenu" + }, + "aliasDomain": { + "message": "Domena aliasu" } } diff --git a/apps/desktop/src/locales/pt_BR/messages.json b/apps/desktop/src/locales/pt_BR/messages.json index 7381ffeea1b..af072a840ee 100644 --- a/apps/desktop/src/locales/pt_BR/messages.json +++ b/apps/desktop/src/locales/pt_BR/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/pt_PT/messages.json b/apps/desktop/src/locales/pt_PT/messages.json index 2f1ed01ed20..189473997be 100644 --- a/apps/desktop/src/locales/pt_PT/messages.json +++ b/apps/desktop/src/locales/pt_PT/messages.json @@ -476,7 +476,7 @@ "message": "O tamanho máximo do ficheiro é de 500 MB." }, "encryptionKeyMigrationRequired": { - "message": "É necessária a migração da chave de encriptação. Inicie sessão através do cofre Web para atualizar a sua chave de encriptação." + "message": "É necessária a migração da chave de encriptação. Inicie sessão através do cofre web para atualizar a sua chave de encriptação." }, "editedFolder": { "message": "Pasta guardada" @@ -653,7 +653,7 @@ "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." }, "duoOrganizationDesc": { - "message": "Verifique com a Duo Security para a sua organização utilizando a aplicação Duo Mobile, SMS, chamada telefónica, ou chave de segurança U2F.", + "message": "Proteja a sua organização com a Duo Security utilizando a aplicação Duo Mobile, SMS, chamada telefónica ou uma chave de segurança U2F.", "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." }, "webAuthnTitle": { @@ -699,7 +699,7 @@ "message": "URL do servidor da API" }, "webVaultUrl": { - "message": "URL do servidor do cofre Web" + "message": "URL do servidor do cofre web" }, "identityUrl": { "message": "URL do servidor de identidade" @@ -803,7 +803,7 @@ "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." }, "goToWebVault": { - "message": "Ir para o cofre Web" + "message": "Ir para o cofre web" }, "getMobileApp": { "message": "Obter a aplicação móvel" @@ -1063,7 +1063,7 @@ "message": "Gerir subscrição" }, "premiumManageAlert": { - "message": "Pode gerir a sua subscrição no cofre Web bitwarden.com. Pretende visitar o site agora?" + "message": "Pode gerir a sua subscrição no cofre web em bitwarden.com. Pretende visitar o site agora?" }, "premiumRefresh": { "message": "Atualizar subscrição" @@ -1096,7 +1096,7 @@ "message": "Adquirir Premium" }, "premiumPurchaseAlert": { - "message": "Pode adquirir uma subscrição Premium no cofre Web bitwarden.com. Pretende visitar o site agora?" + "message": "Pode adquirir uma subscrição Premium no cofre web em bitwarden.com. Pretende visitar o site agora?" }, "premiumCurrentMember": { "message": "É um membro Premium!" @@ -1222,7 +1222,7 @@ "message": "Esta palavra-passe não foi encontrada em nenhuma violação de dados conhecida. A sua utilização deve ser segura." }, "baseDomain": { - "message": "Domínio base", + "message": "Domínio de base", "description": "Domain name. Ex. website.com" }, "domainName": { @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias de domínio" } } diff --git a/apps/desktop/src/locales/ro/messages.json b/apps/desktop/src/locales/ro/messages.json index 1fa5762094e..c3db9b1ba5e 100644 --- a/apps/desktop/src/locales/ro/messages.json +++ b/apps/desktop/src/locales/ro/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/ru/messages.json b/apps/desktop/src/locales/ru/messages.json index b158ec1d3bc..68ba897acdf 100644 --- a/apps/desktop/src/locales/ru/messages.json +++ b/apps/desktop/src/locales/ru/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Подменю" + }, + "aliasDomain": { + "message": "Псевдоним домена" } } diff --git a/apps/desktop/src/locales/si/messages.json b/apps/desktop/src/locales/si/messages.json index af0ce89aff7..639203a1c4b 100644 --- a/apps/desktop/src/locales/si/messages.json +++ b/apps/desktop/src/locales/si/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/sk/messages.json b/apps/desktop/src/locales/sk/messages.json index 01ee45312bb..cbe56af8c14 100644 --- a/apps/desktop/src/locales/sk/messages.json +++ b/apps/desktop/src/locales/sk/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Podponuka" + }, + "aliasDomain": { + "message": "Alias doména" } } diff --git a/apps/desktop/src/locales/sl/messages.json b/apps/desktop/src/locales/sl/messages.json index db640080c7e..342cd4f8e30 100644 --- a/apps/desktop/src/locales/sl/messages.json +++ b/apps/desktop/src/locales/sl/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/sr/messages.json b/apps/desktop/src/locales/sr/messages.json index 5c08226ed5f..7ce3fe92ab4 100644 --- a/apps/desktop/src/locales/sr/messages.json +++ b/apps/desktop/src/locales/sr/messages.json @@ -476,7 +476,7 @@ "message": "Максимална величина је 500МБ." }, "encryptionKeyMigrationRequired": { - "message": "Encryption key migration required. Please login through the web vault to update your encryption key." + "message": "Потребна је миграција кључа за шифровање. Пријавите се преко веб сефа да бисте ажурирали кључ за шифровање." }, "editedFolder": { "message": "Фасцикла измењена" @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Под-мени" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/sv/messages.json b/apps/desktop/src/locales/sv/messages.json index f998e30c731..b515087ed32 100644 --- a/apps/desktop/src/locales/sv/messages.json +++ b/apps/desktop/src/locales/sv/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Undermeny" + }, + "aliasDomain": { + "message": "Aliasdomän" } } diff --git a/apps/desktop/src/locales/te/messages.json b/apps/desktop/src/locales/te/messages.json index fb6177cfb4a..d3a13313e9e 100644 --- a/apps/desktop/src/locales/te/messages.json +++ b/apps/desktop/src/locales/te/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/th/messages.json b/apps/desktop/src/locales/th/messages.json index fd41e44c78e..4463b158d74 100644 --- a/apps/desktop/src/locales/th/messages.json +++ b/apps/desktop/src/locales/th/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/tr/messages.json b/apps/desktop/src/locales/tr/messages.json index d1b51a01d46..66a6a5a8bc7 100644 --- a/apps/desktop/src/locales/tr/messages.json +++ b/apps/desktop/src/locales/tr/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Alt menü" + }, + "aliasDomain": { + "message": "Alias alan adı" } } diff --git a/apps/desktop/src/locales/uk/messages.json b/apps/desktop/src/locales/uk/messages.json index 84923d2d9a9..61e50fb0e44 100644 --- a/apps/desktop/src/locales/uk/messages.json +++ b/apps/desktop/src/locales/uk/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Підменю" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/vi/messages.json b/apps/desktop/src/locales/vi/messages.json index d8fc0ff1462..5bbfddd5676 100644 --- a/apps/desktop/src/locales/vi/messages.json +++ b/apps/desktop/src/locales/vi/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "Submenu" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/locales/zh_CN/messages.json b/apps/desktop/src/locales/zh_CN/messages.json index 8f778415b9c..2e24b4d9080 100644 --- a/apps/desktop/src/locales/zh_CN/messages.json +++ b/apps/desktop/src/locales/zh_CN/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "子菜单" + }, + "aliasDomain": { + "message": "别名域" } } diff --git a/apps/desktop/src/locales/zh_TW/messages.json b/apps/desktop/src/locales/zh_TW/messages.json index 5660ec8ec09..819e81b91f5 100644 --- a/apps/desktop/src/locales/zh_TW/messages.json +++ b/apps/desktop/src/locales/zh_TW/messages.json @@ -2415,5 +2415,8 @@ }, "submenu": { "message": "子選單" + }, + "aliasDomain": { + "message": "Alias domain" } } diff --git a/apps/desktop/src/main.ts b/apps/desktop/src/main.ts index 5107d31b1c5..1eb229281c8 100644 --- a/apps/desktop/src/main.ts +++ b/apps/desktop/src/main.ts @@ -15,6 +15,7 @@ import { UpdaterMain } from "./main/updater.main"; import { WindowMain } from "./main/window.main"; import { Account } from "./models/account"; import { BiometricsService, BiometricsServiceAbstraction } from "./platform/main/biometric/index"; +import { ClipboardMain } from "./platform/main/clipboard.main"; import { DesktopCredentialStorageListener } from "./platform/main/desktop-credential-storage-listener"; import { ElectronLogService } from "./platform/services/electron-log.service"; import { ElectronStateService } from "./platform/services/electron-state.service"; @@ -39,6 +40,7 @@ export class Main { trayMain: TrayMain; biometricsService: BiometricsServiceAbstraction; nativeMessagingMain: NativeMessagingMain; + clipboardMain: ClipboardMain; constructor() { // Set paths for portable builds @@ -138,6 +140,9 @@ export class Main { app.getPath("userData"), app.getPath("exe") ); + + this.clipboardMain = new ClipboardMain(); + this.clipboardMain.init(); } bootstrap() { diff --git a/apps/desktop/src/package-lock.json b/apps/desktop/src/package-lock.json index fc1f62db020..6112806d32a 100644 --- a/apps/desktop/src/package-lock.json +++ b/apps/desktop/src/package-lock.json @@ -1,12 +1,12 @@ { "name": "@bitwarden/desktop", - "version": "2023.9.1", + "version": "2023.9.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@bitwarden/desktop", - "version": "2023.9.1", + "version": "2023.9.2", "license": "GPL-3.0", "dependencies": { "@bitwarden/desktop-native": "file:../desktop_native" diff --git a/apps/desktop/src/package.json b/apps/desktop/src/package.json index eca9f715417..3f4163c160a 100644 --- a/apps/desktop/src/package.json +++ b/apps/desktop/src/package.json @@ -2,7 +2,7 @@ "name": "@bitwarden/desktop", "productName": "Bitwarden", "description": "A secure and free password manager for all of your devices.", - "version": "2023.9.1", + "version": "2023.9.2", "author": "Bitwarden Inc. (https://bitwarden.com)", "homepage": "https://bitwarden.com", "license": "GPL-3.0", diff --git a/apps/desktop/src/platform/main/clipboard.main.ts b/apps/desktop/src/platform/main/clipboard.main.ts new file mode 100644 index 00000000000..c60932b33ba --- /dev/null +++ b/apps/desktop/src/platform/main/clipboard.main.ts @@ -0,0 +1,17 @@ +import { ipcMain } from "electron"; + +import { clipboards } from "@bitwarden/desktop-native"; + +import { ClipboardWriteMessage } from "../types/clipboard"; + +export class ClipboardMain { + init() { + ipcMain.handle("clipboard.read", async (_event: any, _message: any) => { + return await clipboards.read(); + }); + + ipcMain.handle("clipboard.write", async (_event: any, message: ClipboardWriteMessage) => { + return await clipboards.write(message.text, message.password ?? false); + }); + } +} diff --git a/apps/desktop/src/platform/services/electron-platform-utils.service.ts b/apps/desktop/src/platform/services/electron-platform-utils.service.ts index 6f4f55b4f4b..dbc35de9311 100644 --- a/apps/desktop/src/platform/services/electron-platform-utils.service.ts +++ b/apps/desktop/src/platform/services/electron-platform-utils.service.ts @@ -1,12 +1,16 @@ -import { clipboard, ipcRenderer, shell } from "electron"; +import { ipcRenderer, shell } from "electron"; import { ClientType, DeviceType } from "@bitwarden/common/enums"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; -import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; +import { + ClipboardOptions, + PlatformUtilsService, +} from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { BiometricMessage, BiometricStorageAction } from "../../types/biometric-message"; import { isDev, isMacAppStore } from "../../utils"; +import { ClipboardWriteMessage } from "../types/clipboard"; export class ElectronPlatformUtilsService implements PlatformUtilsService { private deviceCache: DeviceType = null; @@ -117,24 +121,26 @@ export class ElectronPlatformUtilsService implements PlatformUtilsService { return false; } - copyToClipboard(text: string, options?: any): void { - const type = options ? options.type : null; - const clearing = options ? !!options.clearing : false; - const clearMs: number = options && options.clearMs ? options.clearMs : null; - clipboard.writeText(text, type); + copyToClipboard(text: string, options?: ClipboardOptions): void { + const clearing = options?.clearing === true; + const clearMs = options?.clearMs ?? null; + + ipcRenderer.invoke("clipboard.write", { + text: text, + password: (options?.allowHistory ?? false) === false, // default to false + } satisfies ClipboardWriteMessage); + if (!clearing) { this.messagingService.send("copiedToClipboard", { clipboardValue: text, clearMs: clearMs, - type: type, clearing: clearing, }); } } - readFromClipboard(options?: any): Promise { - const type = options ? options.type : null; - return Promise.resolve(clipboard.readText(type)); + readFromClipboard(): Promise { + return ipcRenderer.invoke("clipboard.read"); } async supportsBiometric(): Promise { diff --git a/apps/desktop/src/platform/types/clipboard.ts b/apps/desktop/src/platform/types/clipboard.ts new file mode 100644 index 00000000000..6317c32be40 --- /dev/null +++ b/apps/desktop/src/platform/types/clipboard.ts @@ -0,0 +1,4 @@ +export type ClipboardWriteMessage = { + text: string; + password?: boolean; +}; diff --git a/apps/desktop/src/services/encrypted-message-handler.service.ts b/apps/desktop/src/services/encrypted-message-handler.service.ts index 1889bfc7451..1ce52cfecc0 100644 --- a/apps/desktop/src/services/encrypted-message-handler.service.ts +++ b/apps/desktop/src/services/encrypted-message-handler.service.ts @@ -190,7 +190,9 @@ export class EncryptedMessageHandlerService { if (cipher === null) { return { status: "failure" }; } - const cipherView = await cipher.decrypt(); + const cipherView = await cipher.decrypt( + await this.cipherService.getKeyForCipherKeyDecryption(cipher) + ); cipherView.name = credentialUpdatePayload.name; cipherView.login.password = credentialUpdatePayload.password; cipherView.login.username = credentialUpdatePayload.userName; diff --git a/apps/desktop/src/services/native-messaging.service.ts b/apps/desktop/src/services/native-messaging.service.ts index c18a67e6b43..bb92beca782 100644 --- a/apps/desktop/src/services/native-messaging.service.ts +++ b/apps/desktop/src/services/native-messaging.service.ts @@ -116,6 +116,7 @@ export class NativeMessagingService { switch (message.command) { case "biometricUnlock": { + // eslint-disable-next-line @typescript-eslint/no-misused-promises if (!this.platformUtilService.supportsBiometric()) { return this.send({ command: "biometricUnlock", response: "not supported" }, appId); } diff --git a/apps/desktop/src/vault/app/vault/vault.component.ts b/apps/desktop/src/vault/app/vault/vault.component.ts index 194cee098f7..0b419b5088f 100644 --- a/apps/desktop/src/vault/app/vault/vault.component.ts +++ b/apps/desktop/src/vault/app/vault/vault.component.ts @@ -33,10 +33,10 @@ import { DialogService } from "@bitwarden/components"; import { SearchBarService } from "../../../app/layout/search/search-bar.service"; import { GeneratorComponent } from "../../../app/tools/generator.component"; import { invokeMenu, RendererMenuItem } from "../../../utils"; -import { CollectionsComponent } from "../../../vault/app/vault/collections.component"; import { AddEditComponent } from "./add-edit.component"; import { AttachmentsComponent } from "./attachments.component"; +import { CollectionsComponent } from "./collections.component"; import { FolderAddEditComponent } from "./folder-add-edit.component"; import { PasswordHistoryComponent } from "./password-history.component"; import { ShareComponent } from "./share.component"; diff --git a/apps/desktop/tsconfig.json b/apps/desktop/tsconfig.json index d587997f9e6..67bfba64426 100644 --- a/apps/desktop/tsconfig.json +++ b/apps/desktop/tsconfig.json @@ -15,6 +15,7 @@ "@bitwarden/common/*": ["../../libs/common/src/*"], "@bitwarden/components": ["../../libs/components/src"], "@bitwarden/exporter/*": ["../../libs/exporter/src/*"], + "@bitwarden/importer": ["../../libs/importer/src"], "@bitwarden/vault": ["../../libs/vault/src"] }, "useDefineForClassFields": false diff --git a/apps/web/.eslintrc.json b/apps/web/.eslintrc.json index 69dae5e732f..459c7a0b622 100644 --- a/apps/web/.eslintrc.json +++ b/apps/web/.eslintrc.json @@ -13,7 +13,8 @@ "**/organizations/settings/*", "**/organizations/policies/*", "@bitwarden/web-vault/*", - "src/**/*" + "src/**/*", + "bitwarden_license" ], "paths": ["@fluffy-spoon/substitute"] } diff --git a/apps/web/config/base.json b/apps/web/config/base.json index ed0bc0a850d..a377298c637 100644 --- a/apps/web/config/base.json +++ b/apps/web/config/base.json @@ -12,6 +12,7 @@ }, "flags": { "secretsManager": false, - "showPasswordless": false + "showPasswordless": false, + "enableCipherKeyEncryption": false } } diff --git a/apps/web/config/cloud.json b/apps/web/config/cloud.json index 45269d18c63..6e5c65af1d3 100644 --- a/apps/web/config/cloud.json +++ b/apps/web/config/cloud.json @@ -18,6 +18,7 @@ }, "flags": { "secretsManager": true, - "showPasswordless": true + "showPasswordless": true, + "enableCipherKeyEncryption": false } } diff --git a/apps/web/config/development.json b/apps/web/config/development.json index 7aeffe55d0d..e3107f8788b 100644 --- a/apps/web/config/development.json +++ b/apps/web/config/development.json @@ -11,6 +11,7 @@ }, "flags": { "secretsManager": true, - "showPasswordless": true + "showPasswordless": true, + "enableCipherKeyEncryption": false } } diff --git a/apps/web/config/euprd.json b/apps/web/config/euprd.json index 19864cdab66..4b6c9fa9098 100644 --- a/apps/web/config/euprd.json +++ b/apps/web/config/euprd.json @@ -12,6 +12,7 @@ }, "flags": { "secretsManager": true, - "showPasswordless": true + "showPasswordless": true, + "enableCipherKeyEncryption": false } } diff --git a/apps/web/config/qa.json b/apps/web/config/qa.json index 6f514079010..be9911cc578 100644 --- a/apps/web/config/qa.json +++ b/apps/web/config/qa.json @@ -12,6 +12,7 @@ }, "flags": { "secretsManager": true, - "showPasswordless": true + "showPasswordless": true, + "enableCipherKeyEncryption": false } } diff --git a/apps/web/config/selfhosted.json b/apps/web/config/selfhosted.json index 8ffbc0f9e5a..6b290baa6b5 100644 --- a/apps/web/config/selfhosted.json +++ b/apps/web/config/selfhosted.json @@ -8,6 +8,7 @@ }, "flags": { "secretsManager": false, - "showPasswordless": true + "showPasswordless": true, + "enableCipherKeyEncryption": false } } diff --git a/apps/web/package.json b/apps/web/package.json index ef42fafd79a..37c95cc6dcd 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,6 +1,6 @@ { "name": "@bitwarden/web-vault", - "version": "2023.9.1", + "version": "2023.9.2", "scripts": { "build:oss": "webpack", "build:bit": "webpack -c ../../bitwarden_license/bit-web/webpack.config.js", diff --git a/apps/web/src/app/admin-console/organizations/members/components/reset-password.component.html b/apps/web/src/app/admin-console/organizations/members/components/reset-password.component.html index 4116f56de79..6d41249d6e1 100644 --- a/apps/web/src/app/admin-console/organizations/members/components/reset-password.component.html +++ b/apps/web/src/app/admin-console/organizations/members/components/reset-password.component.html @@ -19,13 +19,12 @@ {{ "resetPasswordLoggedOutWarning" | i18n : loggedOutWarningName }} - - +
diff --git a/apps/web/src/app/admin-console/organizations/members/members.module.ts b/apps/web/src/app/admin-console/organizations/members/members.module.ts index 71f5692a119..083fe354ff1 100644 --- a/apps/web/src/app/admin-console/organizations/members/members.module.ts +++ b/apps/web/src/app/admin-console/organizations/members/members.module.ts @@ -1,5 +1,7 @@ import { NgModule } from "@angular/core"; +import { PasswordCalloutComponent } from "@bitwarden/auth"; + import { LooseComponentsModule } from "../../../shared"; import { SharedOrganizationModule } from "../shared"; @@ -19,6 +21,7 @@ import { PeopleComponent } from "./people.component"; LooseComponentsModule, MembersRoutingModule, UserDialogModule, + PasswordCalloutComponent, ], declarations: [ BulkConfirmComponent, diff --git a/apps/web/src/app/admin-console/organizations/sponsorships/families-for-enterprise-setup.component.ts b/apps/web/src/app/admin-console/organizations/sponsorships/families-for-enterprise-setup.component.ts index c3a687a7f95..c598ce6442a 100644 --- a/apps/web/src/app/admin-console/organizations/sponsorships/families-for-enterprise-setup.component.ts +++ b/apps/web/src/app/admin-console/organizations/sponsorships/families-for-enterprise-setup.component.ts @@ -15,15 +15,17 @@ import { ValidationService } from "@bitwarden/common/platform/abstractions/valid import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; import { DialogService } from "@bitwarden/components"; -import { OrganizationPlansComponent } from "../../../billing/settings/organization-plans.component"; +import { OrganizationPlansComponent } from "../../../billing"; +import { SharedModule } from "../../../shared"; import { DeleteOrganizationDialogResult, openDeleteOrganizationDialog, } from "../settings/components"; @Component({ - selector: "families-for-enterprise-setup", templateUrl: "families-for-enterprise-setup.component.html", + standalone: true, + imports: [SharedModule, OrganizationPlansComponent], }) export class FamiliesForEnterpriseSetupComponent implements OnInit, OnDestroy { @ViewChild(OrganizationPlansComponent, { static: false }) diff --git a/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.html b/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.html index f8d07581f42..613e2a7a922 100644 --- a/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.html +++ b/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.html @@ -1,52 +1,19 @@ - +
+ + {{ "enrollAccountRecovery" | i18n }} +
+ + {{ "resetPasswordEnrollmentWarning" | i18n }} + + +
+ + + + +
+
diff --git a/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.ts b/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.ts index 535d7d375ab..8e2b5c70523 100644 --- a/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.ts +++ b/apps/web/src/app/admin-console/organizations/users/enroll-master-password-reset.component.ts @@ -1,7 +1,7 @@ -import { Component } from "@angular/core"; +import { DIALOG_DATA, DialogRef } from "@angular/cdk/dialog"; +import { Component, Inject } from "@angular/core"; +import { FormControl, FormGroup, Validators } from "@angular/forms"; -import { ModalRef } from "@bitwarden/angular/components/modal/modal.ref"; -import { ModalConfig } from "@bitwarden/angular/services/modal.service"; import { OrganizationUserService } from "@bitwarden/common/abstractions/organization-user/organization-user.service"; import { OrganizationUserResetPasswordEnrollmentRequest } from "@bitwarden/common/abstractions/organization-user/requests"; import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction"; @@ -14,71 +14,83 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl import { Utils } from "@bitwarden/common/platform/misc/utils"; import { Verification } from "@bitwarden/common/types/verification"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; +import { DialogService } from "@bitwarden/components"; + +interface EnrollMasterPasswordResetData { + organization: Organization; +} @Component({ selector: "app-enroll-master-password-reset", templateUrl: "enroll-master-password-reset.component.html", }) export class EnrollMasterPasswordReset { - organization: Organization; + protected organization: Organization; - verification: Verification; - formPromise: Promise; + protected formGroup = new FormGroup({ + verification: new FormControl(null, Validators.required), + }); constructor( + private dialogRef: DialogRef, + @Inject(DIALOG_DATA) protected data: EnrollMasterPasswordResetData, private userVerificationService: UserVerificationService, private platformUtilsService: PlatformUtilsService, private i18nService: I18nService, private cryptoService: CryptoService, private syncService: SyncService, private logService: LogService, - private modalRef: ModalRef, - config: ModalConfig, private organizationApiService: OrganizationApiServiceAbstraction, private organizationUserService: OrganizationUserService ) { - this.organization = config.data.organization; + this.organization = data.organization; } - async submit() { + submit = async () => { let toastStringRef = "withdrawPasswordResetSuccess"; - this.formPromise = this.userVerificationService - .buildRequest(this.verification, OrganizationUserResetPasswordEnrollmentRequest) - .then(async (request) => { - // Set variables - let keyString: string = null; - - // Retrieve Public Key - const orgKeys = await this.organizationApiService.getKeys(this.organization.id); - if (orgKeys == null) { - throw new Error(this.i18nService.t("resetPasswordOrgKeysError")); - } - - const publicKey = Utils.fromB64ToArray(orgKeys.publicKey); - - // RSA Encrypt user's encKey.key with organization public key - const userKey = await this.cryptoService.getUserKey(); - const encryptedKey = await this.cryptoService.rsaEncrypt(userKey.key, publicKey); - keyString = encryptedKey.encryptedString; - toastStringRef = "enrollPasswordResetSuccess"; - - // Create request and execute enrollment - request.resetPasswordKey = keyString; - await this.organizationUserService.putOrganizationUserResetPasswordEnrollment( - this.organization.id, - this.organization.userId, - request - ); - - await this.syncService.fullSync(true); - }); try { - await this.formPromise; + await this.userVerificationService + .buildRequest( + this.formGroup.value.verification, + OrganizationUserResetPasswordEnrollmentRequest + ) + .then(async (request) => { + // Set variables + let keyString: string = null; + + // Retrieve Public Key + const orgKeys = await this.organizationApiService.getKeys(this.organization.id); + if (orgKeys == null) { + throw new Error(this.i18nService.t("resetPasswordOrgKeysError")); + } + + const publicKey = Utils.fromB64ToArray(orgKeys.publicKey); + + // RSA Encrypt user's encKey.key with organization public key + const userKey = await this.cryptoService.getUserKey(); + const encryptedKey = await this.cryptoService.rsaEncrypt(userKey.key, publicKey); + keyString = encryptedKey.encryptedString; + toastStringRef = "enrollPasswordResetSuccess"; + + // Create request and execute enrollment + request.resetPasswordKey = keyString; + await this.organizationUserService.putOrganizationUserResetPasswordEnrollment( + this.organization.id, + this.organization.userId, + request + ); + + await this.syncService.fullSync(true); + }); this.platformUtilsService.showToast("success", null, this.i18nService.t(toastStringRef)); - this.modalRef.close(); + this.dialogRef.close(); } catch (e) { this.logService.error(e); } + }; + + static open(dialogService: DialogService, data: EnrollMasterPasswordResetData) { + return dialogService.open(EnrollMasterPasswordReset, { data }); } } diff --git a/apps/web/src/app/admin-console/settings/create-organization.component.ts b/apps/web/src/app/admin-console/settings/create-organization.component.ts index c7fc53c5256..7728ddc540a 100644 --- a/apps/web/src/app/admin-console/settings/create-organization.component.ts +++ b/apps/web/src/app/admin-console/settings/create-organization.component.ts @@ -5,11 +5,13 @@ import { first } from "rxjs/operators"; import { PlanType } from "@bitwarden/common/billing/enums"; import { ProductType } from "@bitwarden/common/enums"; -import { OrganizationPlansComponent } from "../../billing/settings/organization-plans.component"; +import { OrganizationPlansComponent } from "../../billing"; +import { SharedModule } from "../../shared"; @Component({ - selector: "app-create-organization", templateUrl: "create-organization.component.html", + standalone: true, + imports: [SharedModule, OrganizationPlansComponent], }) // eslint-disable-next-line rxjs-angular/prefer-takeuntil export class CreateOrganizationComponent implements OnInit { diff --git a/apps/web/src/app/auth/register-form/register-form.component.html b/apps/web/src/app/auth/register-form/register-form.component.html index e53c963c938..481140a7d2e 100644 --- a/apps/web/src/app/auth/register-form/register-form.component.html +++ b/apps/web/src/app/auth/register-form/register-form.component.html @@ -25,12 +25,8 @@
- - + + {{ "masterPass" | i18n }}
- - + +
diff --git a/apps/web/src/app/auth/settings/change-password.component.html b/apps/web/src/app/auth/settings/change-password.component.html index 7088cb5a686..b3ad78168d9 100644 --- a/apps/web/src/app/auth/settings/change-password.component.html +++ b/apps/web/src/app/auth/settings/change-password.component.html @@ -3,12 +3,8 @@
{{ "loggedOutWarning" | i18n }} - - + +
diff --git a/apps/web/src/app/auth/settings/emergency-access/emergency-access-takeover.component.html b/apps/web/src/app/auth/settings/emergency-access/emergency-access-takeover.component.html index dbcce914e9f..99aa194c5d6 100644 --- a/apps/web/src/app/auth/settings/emergency-access/emergency-access-takeover.component.html +++ b/apps/web/src/app/auth/settings/emergency-access/emergency-access-takeover.component.html @@ -23,12 +23,8 @@