diff --git a/.eslintrc.json b/.eslintrc.json index d6c329a94dc..44b4e09adf2 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -179,6 +179,23 @@ "rules": { "no-restricted-imports": ["error", { "patterns": ["@bitwarden/vault/*", "src/**/*"] }] } + }, + { + "files": ["apps/browser/src/**/*.ts", "libs/**/*.ts"], + "excludedFiles": "apps/browser/src/autofill/{content,notification}/**/*.ts", + "rules": { + "no-restricted-syntax": [ + "error", + { + "message": "Using addListener in the browser popup produces a memory leak in Safari, use `BrowserApi.messageListener` instead", + "selector": "CallExpression > [object.object.object.name='chrome'][object.object.property.name='runtime'][object.property.name='onMessage'][property.name='addListener']" + }, + { + "message": "Using addListener in the browser popup produces a memory leak in Safari, use `BrowserApi.storageChangeListener` instead", + "selector": "CallExpression > [object.object.object.name='chrome'][object.object.property.name='storage'][object.property.name='onChanged'][property.name='addListener']" + } + ] + } } ] } 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..04a8a04f4f5 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,19 +150,17 @@ 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" - name: Install Snap uses: samuelmeuli/action-snapcraft@d33c176a9b784876d966f80fb1b461808edc0641 # v2.1.1 - with: - snapcraft_token: ${{ steps.retrieve-secrets.outputs.snapcraft-store-token }} - 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 +170,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 @@ -185,7 +183,7 @@ jobs: env: SNAPCRAFT_STORE_CREDENTIALS: ${{ steps.retrieve-secrets.outputs.snapcraft-store-token }} run: | - snapcraft push bw_${{ env._PKG_VERSION }}_amd64.snap --release stable + snapcraft upload bw_${{ env._PKG_VERSION }}_amd64.snap --release stable snapcraft logout choco: @@ -206,7 +204,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 +220,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 +230,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 +263,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 +280,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..b9ffa80e512 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,15 +263,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: "snapcraft-store-token" - name: Install Snap uses: samuelmeuli/action-snapcraft@d33c176a9b784876d966f80fb1b461808edc0641 # v2.1.1 - env: - SNAPCRAFT_STORE_CREDENTIALS: ${{ steps.retrieve-secrets.outputs.snapcraft-store-token }} - name: Setup run: mkdir dist @@ -279,7 +277,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 +287,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 @@ -302,8 +300,8 @@ jobs: env: SNAPCRAFT_STORE_CREDENTIALS: ${{ steps.retrieve-secrets.outputs.snapcraft-store-token }} run: | - /snap/bin/snapcraft upload bitwarden_${{ env._PKG_VERSION }}_amd64.snap --release stable - /snap/bin/snapcraft logout + snapcraft upload bitwarden_${{ env._PKG_VERSION }}_amd64.snap --release stable + snapcraft logout working-directory: apps/desktop/dist choco: @@ -329,7 +327,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 +345,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 +355,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/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..c3ba5c4a950 100644 --- a/apps/browser/src/_locales/ar/messages.json +++ b/apps/browser/src/_locales/ar/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "التعبئة التلقائية" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "إنشاء كلمة مرور (تم النسخ)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "لا توجد تسجيلات دخول مطابقة." }, + "noCards": { + "message": "No cards" + }, + "noIdentities": { + "message": "No identities" + }, + "addLoginMenu": { + "message": "Add login" + }, + "addCardMenu": { + "message": "Add card" + }, + "addIdentityMenu": { + "message": "Add identity" + }, "unlockVaultMenu": { "message": "افتح خزنتك" }, @@ -2406,5 +2430,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..483dc2c14f1 100644 --- a/apps/browser/src/_locales/az/messages.json +++ b/apps/browser/src/_locales/az/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Avto-doldurma" }, + "autoFillLogin": { + "message": "Giriş avto-doldurma" + }, + "autoFillCard": { + "message": "Kart avto-doldurma" + }, + "autoFillIdentity": { + "message": "Kimlik avto-doldurma" + }, "generatePasswordCopied": { "message": "Parol yarat (kopyalandı)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Uyğun gələn hesab yoxdur." }, + "noCards": { + "message": "Kart yoxdur" + }, + "noIdentities": { + "message": "Kimlik yoxdur" + }, + "addLoginMenu": { + "message": "Giriş əlavə et" + }, + "addCardMenu": { + "message": "Kart əlavə et" + }, + "addIdentityMenu": { + "message": "Kimlik əlavə et" + }, "unlockVaultMenu": { "message": "Anbarın kilidini açın" }, @@ -671,7 +695,7 @@ "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." }, "exportVault": { - "message": "Anbarı ixrac et" + "message": "Anbarı xaricə köçür" }, "fileFormat": { "message": "Fayl formatı" @@ -681,19 +705,19 @@ "description": "WARNING (should stay in capitalized letters if the language permits)" }, "confirmVaultExport": { - "message": "Anbarın ixracını təsdiqləyin" + "message": "Anbarın xaricə köçürülməsini təsdiqləyin" }, "exportWarningDesc": { - "message": "Bu ixrac faylındakı anbar verilənləriniz şifrələnməmiş formatdadır. İxrac edilən faylı, güvənli olmayan kanallar üzərində saxlamamalı və ya göndərməməlisiniz (e-poçt kimi). Bu faylı işiniz bitdikdən sonra dərhal silin." + "message": "Xaricə köçürdüyünüz bu fayldakı datanız şifrələnməmiş formatdadır. Bu faylı güvənli olmayan kanallar (e-poçt kimi) üzərində saxlamamalı və ya göndərməməlisiniz. İşiniz bitdikdən sonra faylı dərhal silin." }, "encExportKeyWarningDesc": { - "message": "Bu ixrac faylı, hesabınızın şifrələmə açarını istifadə edərək verilənlərinizi şifrələyir. Hesabınızın şifrələmə açarını döndərsəniz, bu ixrac faylının şifrəsini aça bilməyəcəyiniz üçün yenidən ixrac etməli olacaqsınız." + "message": "Xaricə köçürdüyünüz bu fayldakı data, hesabınızın şifrələmə açarı istifadə edilərək şifrələnir. Hesabınızın şifrələmə açarını dəyişdirsəniz, bu faylın şifrəsini aça bilməyəcəksiniz və onu yenidən xaricə köçürməli olacaqsınız." }, "encExportAccountWarningDesc": { "message": "Hesab şifrələmə açarları, hər Bitwarden istifadəçi hesabı üçün unikaldır, buna görə də şifrələnmiş bir ixracı, fərqli bir hesaba idxal edə bilməzsiniz." }, "exportMasterPassword": { - "message": "Anbar verilənlərinizi ixrac etmək üçün ana parolunuzu daxil edin." + "message": "Anbar datanızı xaricə köçürmək üçün ana parolunuzu daxil edin." }, "shared": { "message": "Paylaşılan" @@ -799,7 +823,7 @@ "message": "YubiKey və Duo kimi mülkiyyətçi iki addımlı giriş seçimləri." }, "ppremiumSignUpReports": { - "message": "Anbarınızın təhlükəsiyini təmin etmək üçün parol gigiyenası, hesab sağlamlığı və verilənlərin pozulması hesabatları." + "message": "Anbarınızın təhlükəsizliyini təmin etmək üçün parol gigiyenası, hesab sağlamlığı və data pozuntusu hesabatları." }, "ppremiumSignUpTotp": { "message": "Anbarınızdakı hesablar üçün TOTP təsdiqləmə kodu (2FA) yaradıcısı." @@ -2406,5 +2430,20 @@ "toggleCollapse": { "message": "Yığcamlaşdırmanı aç/bağla", "description": "Toggling an expand/collapse state." + }, + "aliasDomain": { + "message": "Domen ləqəbi" + }, + "passwordRepromptDisabledAutofillOnPageLoad": { + "message": "\"Ana parolu təkrar soruş\" özəlliyi olan elementlər səhifə yüklənəndə avto-doldurulmur. \"Səhifə yüklənəndə avto-doldurma\" özəlliyi söndürülüb.", + "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." + }, + "autofillOnPageLoadSetToDefault": { + "message": "\"Səhifə yüklənəndə avto-doldurma\" özəlliyi ilkin tənzimləməni istifadə etmək üzrə tənzimləndi.", + "description": "Toast message for informing the user that auto-fill on page load has been set to the default setting." + }, + "turnOffMasterPasswordPromptToEditField": { + "message": "Bu sahəyə düzəliş etmək üçün \"Ana parolu təkrar soruş\"u söndürü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/be/messages.json b/apps/browser/src/_locales/be/messages.json index 2fc14ecb1fc..d0c1bac2bb7 100644 --- a/apps/browser/src/_locales/be/messages.json +++ b/apps/browser/src/_locales/be/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Аўтазапаўненне" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "Генерыраваць пароль (з капіяваннем)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Няма адпаведных лагінаў." }, + "noCards": { + "message": "No cards" + }, + "noIdentities": { + "message": "No identities" + }, + "addLoginMenu": { + "message": "Add login" + }, + "addCardMenu": { + "message": "Add card" + }, + "addIdentityMenu": { + "message": "Add identity" + }, "unlockVaultMenu": { "message": "Разблакіраваць сховішча" }, @@ -2406,5 +2430,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..c96fadbd422 100644 --- a/apps/browser/src/_locales/bg/messages.json +++ b/apps/browser/src/_locales/bg/messages.json @@ -14,7 +14,7 @@ "message": "Впишете се или създайте нов абонамент, за да достъпите защитен трезор." }, "createAccount": { - "message": "Създаване на абонамент" + "message": "Създаване на акаунт" }, "login": { "message": "Вписване" @@ -91,6 +91,15 @@ "autoFill": { "message": "Автоматично дописване" }, + "autoFillLogin": { + "message": "Авт. попълване на данни за вход" + }, + "autoFillCard": { + "message": "Самопопълваща се карта" + }, + "autoFillIdentity": { + "message": "Самопопълваща се самоличност" + }, "generatePasswordCopied": { "message": "Генериране на парола (копирана)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Няма съвпадащи записи." }, + "noCards": { + "message": "Няма карти" + }, + "noIdentities": { + "message": "Няма самоличности" + }, + "addLoginMenu": { + "message": "Добавяне на запис за вход" + }, + "addCardMenu": { + "message": "Добавяне на карта" + }, + "addIdentityMenu": { + "message": "Добавяне на самоличност" + }, "unlockVaultMenu": { "message": "Отключете трезора си" }, @@ -467,7 +491,7 @@ "message": "Грешен код за потвърждаване" }, "valueCopied": { - "message": "$VALUE$ — копирано", + "message": "Копирано е $VALUE$", "description": "Value has been copied to the clipboard.", "placeholders": { "value": { @@ -537,7 +561,7 @@ "message": "Копирана парола" }, "uri": { - "message": "Адрес" + "message": "Унифициран идентификатор на ресурс" }, "uriPosition": { "message": "Адрес $POSITION$", @@ -550,7 +574,7 @@ } }, "newUri": { - "message": "Нов адрес" + "message": "Нов унифициран идентификатор на ресурс" }, "addedItem": { "message": "Елементът е добавен" @@ -631,7 +655,7 @@ "message": "Да се обнови ли паролата в Bitwarden?" }, "notificationChangeSave": { - "message": "Да, нека се обнови сега" + "message": "Осъвременяване" }, "notificationUnlockDesc": { "message": "Отключете трезора си в Битуорден, за да завършите заявката за автоматично попълване." @@ -684,7 +708,7 @@ "message": "Потвърждаване на изнасянето на трезора" }, "exportWarningDesc": { - "message": "Данните от трезора ви ще се изнесат в незащитен формат. Не го пращайте по незащитени канали като е-поща. Изтрийте файла незабавно след като свършите работата си с него." + "message": "Този износ съдържа данни на трезора ви в некриптиран формат. Не трябва да съхранявате или изпращате износния файл през незащитени канали (като имейл). Изтрийте файла моментално след като свършите работата си с него." }, "encExportKeyWarningDesc": { "message": "При изнасяне данните се шифрират с ключа ви. Ако го смените, ще трябва наново да ги изнесете, защото няма да може да дешифрирате настоящия файл." @@ -699,10 +723,10 @@ "message": "Споделено" }, "learnOrg": { - "message": "Разберете повече за организациите" + "message": "Научете за организациите" }, "learnOrgConfirmation": { - "message": "Битуорден позволява да споделяте части от трезора си чрез използването на организация. Искате ли да научите повече от сайта bitwarden.com?" + "message": "Битуорден позволява да споделяте елементи от трезора си а други, използвайки организация. Бихте ли посетили сайта bitwarden.com, за да научите повече?" }, "moveToOrganization": { "message": "Преместване в организация" @@ -781,7 +805,7 @@ "message": "Управление на абонамента" }, "premiumManageAlert": { - "message": "Можете да управлявате абонамента си през сайта bitwarden.com. Искате ли да го посетите сега?" + "message": "Може да управлявате членството си в мрежата на трезора в bitwarden.com. Искате ли да посетите уебсайта сега?" }, "premiumRefresh": { "message": "Опресняване на абонамента" @@ -901,7 +925,7 @@ "message": "Регистрацията е защитена с двустепенно удостоверяване, но никой от настроените доставчици на удостоверяване не се поддържа от този браузър." }, "noTwoStepProviders2": { - "message": "Пробвайте с поддържан уеб браузър (като Chrome или Firefox) и други доставчици на удостоверяване, които се поддържат от браузърите (като специални програми за удостоверяване)." + "message": "Употребявайте поддържан браузър (като Chrome, Firefox) и/или добавете други доставчици на удостоверяване, които се поддържат по-добре от браузърите (като специални програми за удостоверяване)." }, "twoStepOptions": { "message": "Настройки на двустепенното удостоверяване" @@ -920,10 +944,10 @@ "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." }, "yubiKeyTitle": { - "message": "Устройство YubiKey OTP" + "message": "Ключ за сигурност YubiKey OTP" }, "yubiKeyDesc": { - "message": "Използвайте устройство на YubiKey, за да влезете в абонамента си. Поддържат се моделите YubiKey 4, 4 Nano, 4C и NEO." + "message": "Използвайте ключа за сигурност YubiKey, за да влезете в акаунта си. Работи с устройствата YubiKey 4, 4 Nano, 4C и NEO." }, "duoDesc": { "message": "Удостоверяване чрез Duo Security, с ползване на приложението Duo Mobile, SMS, телефонен разговор или устройство U2F.", @@ -2096,7 +2120,7 @@ "message": "собствен хостинг" }, "thirdParty": { - "message": "Third-party" + "message": "Трета страна" }, "thirdPartyServerMessage": { "message": "Connected to third-party server implementation, $SERVERNAME$. Please verify bugs using the official server, or report them to the third-party server.", @@ -2406,5 +2430,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..f8c5fb8c85b 100644 --- a/apps/browser/src/_locales/bn/messages.json +++ b/apps/browser/src/_locales/bn/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "স্বতঃপূরণ" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "পাসওয়ার্ড তৈরি করুন (অনুলিপিকৃত)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "কোনও মিলত লগইন নেই।" }, + "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" }, @@ -2406,5 +2430,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..d5d1bbb16a6 100644 --- a/apps/browser/src/_locales/bs/messages.json +++ b/apps/browser/src/_locales/bs/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" }, @@ -2406,5 +2430,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..af85e586c80 100644 --- a/apps/browser/src/_locales/ca/messages.json +++ b/apps/browser/src/_locales/ca/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Emplenament automàtic" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "Genera contrasenya (copiada)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "No hi ha inicis de sessió coincidents." }, + "noCards": { + "message": "No cards" + }, + "noIdentities": { + "message": "No identities" + }, + "addLoginMenu": { + "message": "Add login" + }, + "addCardMenu": { + "message": "Add card" + }, + "addIdentityMenu": { + "message": "Add identity" + }, "unlockVaultMenu": { "message": "1. Desbloquegeu la caixa forta." }, @@ -2406,5 +2430,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..e9b3bf997cd 100644 --- a/apps/browser/src/_locales/cs/messages.json +++ b/apps/browser/src/_locales/cs/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Automatické vyplňování" }, + "autoFillLogin": { + "message": "Automaticky vyplnit přihlášení" + }, + "autoFillCard": { + "message": "Automaticky vyplnit kartu" + }, + "autoFillIdentity": { + "message": "Automaticky vyplnit identitu" + }, "generatePasswordCopied": { "message": "Vygenerovat heslo a zkopírovat do schránky" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Žádné odpovídající přihlašovací údaje" }, + "noCards": { + "message": "Žádné karty" + }, + "noIdentities": { + "message": "Žádné identity" + }, + "addLoginMenu": { + "message": "Přidat přihlašovací údaje" + }, + "addCardMenu": { + "message": "Přidat kartu" + }, + "addIdentityMenu": { + "message": "Přidat identitu" + }, "unlockVaultMenu": { "message": "Odemknout Váš trezor" }, @@ -2406,5 +2430,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..ff3ccc684f7 100644 --- a/apps/browser/src/_locales/cy/messages.json +++ b/apps/browser/src/_locales/cy/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Llenwi'n awtomatig" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "Cynhyrchu cyfrinair (wedi'i gopïo)" }, @@ -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": "Datgloi'ch cell" }, @@ -2406,5 +2430,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..5dd437827f3 100644 --- a/apps/browser/src/_locales/da/messages.json +++ b/apps/browser/src/_locales/da/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Auto-udfyld" }, + "autoFillLogin": { + "message": "Autoudfyld login" + }, + "autoFillCard": { + "message": "Autoudfyld kort" + }, + "autoFillIdentity": { + "message": "Autoudfyld identitet" + }, "generatePasswordCopied": { "message": "Generér adgangskode (kopieret)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Ingen matchende logins" }, + "noCards": { + "message": "Ingen kort" + }, + "noIdentities": { + "message": "Ingen identiteter" + }, + "addLoginMenu": { + "message": "Tilføj login" + }, + "addCardMenu": { + "message": "Tilføj kort" + }, + "addIdentityMenu": { + "message": "Tilføj identitet" + }, "unlockVaultMenu": { "message": "Lås din boks op" }, @@ -2406,5 +2430,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..3edd462918f 100644 --- a/apps/browser/src/_locales/de/messages.json +++ b/apps/browser/src/_locales/de/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Auto-Ausfüllen" }, + "autoFillLogin": { + "message": "Zugangsdaten automatisch ausfüllen" + }, + "autoFillCard": { + "message": "Karte automatisch ausfüllen" + }, + "autoFillIdentity": { + "message": "Identität automatisch ausfüllen" + }, "generatePasswordCopied": { "message": "Passwort generieren (kopiert)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Keine passenden Zugangsdaten" }, + "noCards": { + "message": "Keine Karten" + }, + "noIdentities": { + "message": "Keine Identitäten" + }, + "addLoginMenu": { + "message": "Zugangsdaten hinzufügen" + }, + "addCardMenu": { + "message": "Karte hinzufügen" + }, + "addIdentityMenu": { + "message": "Identität hinzufügen" + }, "unlockVaultMenu": { "message": "Entsperre deinen Tresor" }, @@ -2406,5 +2430,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..2692a89b7db 100644 --- a/apps/browser/src/_locales/el/messages.json +++ b/apps/browser/src/_locales/el/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Αυτόματη συμπλήρωση" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "Δημιουργία Κωδικού (αντιγράφηκε)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Δεν υπάρχουν αντιστοιχίσεις σύνδεσης." }, + "noCards": { + "message": "No cards" + }, + "noIdentities": { + "message": "No identities" + }, + "addLoginMenu": { + "message": "Add login" + }, + "addCardMenu": { + "message": "Add card" + }, + "addIdentityMenu": { + "message": "Add identity" + }, "unlockVaultMenu": { "message": "Ξεκλειδώστε το vault σας" }, @@ -2406,5 +2430,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 ea9486379f8..48d69ace9d2 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..4e1057956fa 100644 --- a/apps/browser/src/_locales/en_GB/messages.json +++ b/apps/browser/src/_locales/en_GB/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" }, @@ -2406,5 +2430,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..32dd196f2ae 100644 --- a/apps/browser/src/_locales/en_IN/messages.json +++ b/apps/browser/src/_locales/en_IN/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" }, @@ -2406,5 +2430,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..b81a05c9a4b 100644 --- a/apps/browser/src/_locales/es/messages.json +++ b/apps/browser/src/_locales/es/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Autorellenar" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "Generar contraseña (copiada)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Sin entradas coincidentes." }, + "noCards": { + "message": "No cards" + }, + "noIdentities": { + "message": "No identities" + }, + "addLoginMenu": { + "message": "Add login" + }, + "addCardMenu": { + "message": "Add card" + }, + "addIdentityMenu": { + "message": "Add identity" + }, "unlockVaultMenu": { "message": "Desbloquea la caja fuerte" }, @@ -637,7 +661,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 +2430,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..4fe20767c0e 100644 --- a/apps/browser/src/_locales/et/messages.json +++ b/apps/browser/src/_locales/et/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Automaatne täitmine" }, + "autoFillLogin": { + "message": "Täida konto andmed" + }, + "autoFillCard": { + "message": "Täida kaardi andmed" + }, + "autoFillIdentity": { + "message": "Täida identiteet" + }, "generatePasswordCopied": { "message": "Genereeri parool (kopeeritakse)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Sobivaid kontoandmeid ei leitud." }, + "noCards": { + "message": "Kaardid puuduvad" + }, + "noIdentities": { + "message": "Identiteedid puuduvad" + }, + "addLoginMenu": { + "message": "Lisa konto andmed" + }, + "addCardMenu": { + "message": "Lisa kaart" + }, + "addIdentityMenu": { + "message": "Lisa identiteet" + }, "unlockVaultMenu": { "message": "Lukusta hoidla lahti" }, @@ -2406,5 +2430,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..291a687f8b4 100644 --- a/apps/browser/src/_locales/eu/messages.json +++ b/apps/browser/src/_locales/eu/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Auto-betetzea" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "Sortu pasahitza (kopiatuta)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Bat datozen saio-hasierarik gabe" }, + "noCards": { + "message": "No cards" + }, + "noIdentities": { + "message": "No identities" + }, + "addLoginMenu": { + "message": "Add login" + }, + "addCardMenu": { + "message": "Add card" + }, + "addIdentityMenu": { + "message": "Add identity" + }, "unlockVaultMenu": { "message": "Desblokeatu kutxa gotorra" }, @@ -2406,5 +2430,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..bcfab0cdbc8 100644 --- a/apps/browser/src/_locales/fa/messages.json +++ b/apps/browser/src/_locales/fa/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "پر کردن خودکار" }, + "autoFillLogin": { + "message": "پر کردن خودکار ورود" + }, + "autoFillCard": { + "message": "پر کردن خودکار کارت" + }, + "autoFillIdentity": { + "message": "پر کردن خودکار هویت" + }, "generatePasswordCopied": { "message": "ساخت کلمه عبور (کپی شد)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "ورودی‌ها منتطبق نیست" }, + "noCards": { + "message": "کارتی وجود ندارد" + }, + "noIdentities": { + "message": "هویتی وجود ندارد" + }, + "addLoginMenu": { + "message": "افزودن ورود" + }, + "addCardMenu": { + "message": "افزودن کارت" + }, + "addIdentityMenu": { + "message": "افزودن هویت" + }, "unlockVaultMenu": { "message": "قفل گاوصندوق خود را باز کنید" }, @@ -637,7 +661,7 @@ "message": "برای پر کردن خودکار گاوصندوق Bitwarden خود را باز کنید." }, "notificationUnlock": { - "message": "بازگشایی" + "message": "باز کردن قفل" }, "enableContextMenuItem": { "message": "نمایش گزینه‌های منوی زمینه" @@ -772,7 +796,7 @@ "message": "ویژگی موجود نیست" }, "encryptionKeyMigrationRequired": { - "message": "Encryption key migration required. Please login through the web vault to update your encryption key." + "message": "انتقال کلید رمزگذاری مورد نیاز است. لطفاً از طریق گاوصندوق وب وارد شوید تا کلید رمزگذاری خود را به روز کنید." }, "premiumMembership": { "message": "عضویت پرمیوم" @@ -1606,10 +1630,10 @@ "message": "بیومتریک مرورگر در این دستگاه پشتیبانی نمی‌شود." }, "biometricsFailedTitle": { - "message": "زیست‌سنجی ناتمام ماند" + "message": "زیست‌سنجی ناموفق بود" }, "biometricsFailedDesc": { - "message": "زیست‌سنجی نمی تواند انجام شود، استفاده از کلمه عبور اصلی یا خروج را در نظر بگیرید. اگر این مشکل ادامه یافت لطفا با پشتیبانی Bitwarden تماس بگیرید." + "message": "زیست‌سنجی نمی‌تواند انجام شود، استفاده از کلمه عبور اصلی یا خروج را در نظر بگیرید. اگر این مشکل ادامه یافت لطفاً با پشتیبانی Bitwarden تماس بگیرید." }, "nativeMessaginPermissionErrorTitle": { "message": "مجوز ارائه نشده است" @@ -1992,7 +2016,7 @@ "message": "برون ریزی گاو‌صندوق شخصی" }, "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": "فقط موارد شخصی گاوصندوق مرتبط با $EMAIL$ برون ریزی خواهند شد. موارد گاوصندوق سازمان شامل نخواهد شد. فقط اطلاعات مورد گاوصندوق برون ریزی خواهد شد و شامل تاریخچه کلمه عبور مرتبط یا پیوست نمی‌شود.", "placeholders": { "email": { "content": "$1", @@ -2234,28 +2258,28 @@ } }, "loggingInOn": { - "message": "ورود به عنوان" + "message": "ورود با" }, "opensInANewWindow": { "message": "در پنجره جدید باز می‌شود" }, "deviceApprovalRequired": { - "message": "تایید دستگاه لازم است. یک روش تایید برگزینید:" + "message": "تأیید دستگاه لازم است. یک روش تأیید انتخاب کنید:" }, "rememberThisDevice": { "message": "این دستگاه را به خاطر بسپار" }, "uncheckIfPublicDevice": { - "message": "بردارید اگر از دستگاه عمومی استفاده میکنید" + "message": "اگر از دستگاه عمومی استفاده می‌کنید علامت را بردارید" }, "approveFromYourOtherDevice": { - "message": "تایید با دستگاه دیگرتان" + "message": "تأیید با دستگاه دیگرتان" }, "requestAdminApproval": { - "message": "درخواست تایید مدیر" + "message": "درخواست تأیید مدیر" }, "approveWithMasterPassword": { - "message": "تایید با کلمه عبور اصلی" + "message": "تأیید با کلمه عبور اصلی" }, "ssoIdentifierRequired": { "message": "شناسه سازمان SSO مورد نیاز است." @@ -2283,37 +2307,37 @@ "message": "حساب کاربری با موفقیت ایجاد شد!" }, "adminApprovalRequested": { - "message": "تایید مدیر در خواست شد" + "message": "تأیید مدیر درخواست شد" }, "adminApprovalRequestSentToAdmins": { "message": "درخواست شما به مدیرتان فرستاده شد." }, "youWillBeNotifiedOnceApproved": { - "message": "به محض تایید مطلع خواهید شد." + "message": "به محض تأیید مطلع خواهید شد." }, "troubleLoggingIn": { "message": "در ورود مشکلی دارید؟" }, "loginApproved": { - "message": "ورود تایید شد" + "message": "ورود تأیید شد" }, "userEmailMissing": { - "message": "رایانامه کاربر کم است" + "message": "ایمیل کاربر وجود ندارد" }, "deviceTrusted": { "message": "دستگاه مورد اعتماد است" }, "inputRequired": { - "message": "ورودی مورد نیاز است." + "message": "ورودی ضروری است." }, "required": { - "message": "الزامی" + "message": "ضروری" }, "search": { "message": "جستجو" }, "inputMinLength": { - "message": "ورودی باید حداقل $COUNT$ نشانه داشته باشد.", + "message": "ورودی باید حداقل $COUNT$ کاراکتر داشته باشد.", "placeholders": { "count": { "content": "$1", @@ -2322,7 +2346,7 @@ } }, "inputMaxLength": { - "message": "اندازه ورودی نباید بیش از $COUNT$ نشانه باشد.", + "message": "طول ورودی نباید بیش از $COUNT$ کاراکتر باشد.", "placeholders": { "count": { "content": "$1", @@ -2331,7 +2355,7 @@ } }, "inputForbiddenCharacters": { - "message": "نشانه های زیر مجاز نیستند: $CHARACTERS$", + "message": "کاراکترهای زیر مجاز نیستند: $CHARACTERS$", "placeholders": { "characters": { "content": "$1", @@ -2340,7 +2364,7 @@ } }, "inputMinValue": { - "message": "مقدار ورودی باید دست کم $MIN$ باشد.", + "message": "مقدار ورودی باید حداقل $MIN$ باشد.", "placeholders": { "min": { "content": "$1", @@ -2349,7 +2373,7 @@ } }, "inputMaxValue": { - "message": "مقدار ورودی نباید بیش از $MAX$ باشد.", + "message": "مقدار ورودی نباید از $MAX$ تجاوز کند.", "placeholders": { "max": { "content": "$1", @@ -2358,17 +2382,17 @@ } }, "multipleInputEmails": { - "message": "یک یا چند رایانامه نامعتبر است" + "message": "یک یا چند ایمیل نامعتبر است" }, "inputTrimValidator": { - "message": "ورودی نباید فقط فاصله باشد.", + "message": "ورودی نباید فقط حاوی فضای خالی باشد.", "description": "Notification to inform the user that a form's input can't contain only whitespace." }, "inputEmail": { - "message": "ورودی یک نشانی رایانامه نیست." + "message": "ورودی یک نشانی ایمیل نیست." }, "fieldsNeedAttention": { - "message": "بخش (های) $COUNT$ در بالا نیازمند توجه شما است.", + "message": "فیلد $COUNT$ در بالا به توجه شما نیاز دارد.", "placeholders": { "count": { "content": "$1", @@ -2380,16 +2404,16 @@ "message": "-- انتخاب --" }, "multiSelectPlaceholder": { - "message": "-- برای گزینش چیزی بنویسید --" + "message": "-- برای فیلتر تایپ کنید --" }, "multiSelectLoading": { "message": "در حال بازیابی گزینه‌ها..." }, "multiSelectNotFound": { - "message": "موردی پیدا نشد" + "message": "موردی یافت نشد" }, "multiSelectClearAll": { - "message": "پاک کردن همه" + "message": "پاک‌کردن همه" }, "plusNMore": { "message": "+ $QUANTITY$ بیشتر", @@ -2401,10 +2425,25 @@ } }, "submenu": { - "message": "زیرفهرست" + "message": "زیرمنو" }, "toggleCollapse": { - "message": "باز و بسته کردن", + "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/fi/messages.json b/apps/browser/src/_locales/fi/messages.json index 81bf6c64322..daaa9a89258 100644 --- a/apps/browser/src/_locales/fi/messages.json +++ b/apps/browser/src/_locales/fi/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Automaattinen täyttö" }, + "autoFillLogin": { + "message": "Täytä kirjautumistieto automaattisesti" + }, + "autoFillCard": { + "message": "Täytä kortti automaattisesti" + }, + "autoFillIdentity": { + "message": "Täytä identiteetti automaattisesti" + }, "generatePasswordCopied": { "message": "Luo salasana (leikepöydälle)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Ei tunnistettuja kirjautumistietoja." }, + "noCards": { + "message": "Kortteja ei ole" + }, + "noIdentities": { + "message": "Identiteettejä ei ole" + }, + "addLoginMenu": { + "message": "Lisää kirjautumistieto" + }, + "addCardMenu": { + "message": "Lisää kortti" + }, + "addIdentityMenu": { + "message": "Lisää identiteetti" + }, "unlockVaultMenu": { "message": "Avaa holvisi" }, @@ -2406,5 +2430,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..464cf888899 100644 --- a/apps/browser/src/_locales/fil/messages.json +++ b/apps/browser/src/_locales/fil/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Auto-fill sa Filipino ay Awtomatikong Pagpuno" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "Maglagay ng Password" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Walang tumutugmang mga login" }, + "noCards": { + "message": "No cards" + }, + "noIdentities": { + "message": "No identities" + }, + "addLoginMenu": { + "message": "Add login" + }, + "addCardMenu": { + "message": "Add card" + }, + "addIdentityMenu": { + "message": "Add identity" + }, "unlockVaultMenu": { "message": "Buksan ang iyong kahadeyero" }, @@ -2406,5 +2430,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..b0827b39006 100644 --- a/apps/browser/src/_locales/fr/messages.json +++ b/apps/browser/src/_locales/fr/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Saisie automatique" }, + "autoFillLogin": { + "message": "Saisie automatique de l'identifiant" + }, + "autoFillCard": { + "message": "Saisie automatique de la carte" + }, + "autoFillIdentity": { + "message": "Saisie automatique de l'identité" + }, "generatePasswordCopied": { "message": "Générer un mot de passe (copié)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Aucun identifiant correspondant." }, + "noCards": { + "message": "Aucune carte" + }, + "noIdentities": { + "message": "Aucune identité" + }, + "addLoginMenu": { + "message": "Ajouter un identifiant" + }, + "addCardMenu": { + "message": "Ajouter une carte" + }, + "addIdentityMenu": { + "message": "Ajouter une identité" + }, "unlockVaultMenu": { "message": "Déverrouillez votre coffre" }, @@ -339,7 +363,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" @@ -634,7 +658,7 @@ "message": "Mettre à jour" }, "notificationUnlockDesc": { - "message": "Unlock your Bitwarden vault to complete the auto-fill request." + "message": "Déverrouillez votre coffre Bitwarden pour terminer la demande de saisie automatique." }, "notificationUnlock": { "message": "Déverrouiller" @@ -2406,5 +2430,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..22330901579 100644 --- a/apps/browser/src/_locales/gl/messages.json +++ b/apps/browser/src/_locales/gl/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" }, @@ -2406,5 +2430,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..19985cd5ec8 100644 --- a/apps/browser/src/_locales/he/messages.json +++ b/apps/browser/src/_locales/he/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "השלמה אוטומטית" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "צור סיסמה (העתק)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "לא נמצאו פרטי כניסה תואמים." }, + "noCards": { + "message": "No cards" + }, + "noIdentities": { + "message": "No identities" + }, + "addLoginMenu": { + "message": "Add login" + }, + "addCardMenu": { + "message": "Add card" + }, + "addIdentityMenu": { + "message": "Add identity" + }, "unlockVaultMenu": { "message": "שחרור הכספת שלך" }, @@ -2406,5 +2430,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..4b686192902 100644 --- a/apps/browser/src/_locales/hi/messages.json +++ b/apps/browser/src/_locales/hi/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "स्वत:भरण" }, + "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": "कोई मेल-मिला लॉगिन नहीं |" }, + "noCards": { + "message": "No cards" + }, + "noIdentities": { + "message": "No identities" + }, + "addLoginMenu": { + "message": "Add login" + }, + "addCardMenu": { + "message": "Add card" + }, + "addIdentityMenu": { + "message": "Add identity" + }, "unlockVaultMenu": { "message": "आपकी तिजोरी का ताला खोलें" }, @@ -2406,5 +2430,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..b334d22332f 100644 --- a/apps/browser/src/_locales/hr/messages.json +++ b/apps/browser/src/_locales/hr/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Auto-ispuna" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "Generiraj lozinku (i kopiraj)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Nema podudarajućih prijava" }, + "noCards": { + "message": "No cards" + }, + "noIdentities": { + "message": "No identities" + }, + "addLoginMenu": { + "message": "Add login" + }, + "addCardMenu": { + "message": "Add card" + }, + "addIdentityMenu": { + "message": "Add identity" + }, "unlockVaultMenu": { "message": "Otključaj svoj trezor" }, @@ -772,7 +796,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 +2016,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 +2430,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..abf5a12e5e5 100644 --- a/apps/browser/src/_locales/hu/messages.json +++ b/apps/browser/src/_locales/hu/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Automatikus kitöltés" }, + "autoFillLogin": { + "message": "Automatikus kitöltés bejelentkezés" + }, + "autoFillCard": { + "message": "Automatikus kitöltés kártya" + }, + "autoFillIdentity": { + "message": "Automatikus kitöltés személyazonosság" + }, "generatePasswordCopied": { "message": "Jelszó generálás (másolt)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Nincsenek egyező bejelentkezések." }, + "noCards": { + "message": "Nincsenek kártyák" + }, + "noIdentities": { + "message": "Nincsenek személyazonosságok" + }, + "addLoginMenu": { + "message": "Bejelentkezés hozzáadása" + }, + "addCardMenu": { + "message": "Kártya hozzáadása" + }, + "addIdentityMenu": { + "message": "Személyazonossság hozzáadása" + }, "unlockVaultMenu": { "message": "Széf kinyitása" }, @@ -143,7 +167,7 @@ "message": "A folytatáshoz meg kell erősíteni a személyazonosságot." }, "account": { - "message": "Felhasználó" + "message": "Fiók" }, "changeMasterPassword": { "message": "Mesterjelszó módosítása" @@ -513,7 +537,7 @@ "message": "A kétlépcsős bejelentkezés biztonságosabbá teszi a fiókot azáltal, hogy ellenőrizni kell a bejelentkezést egy másik olyan eszközzel mint például biztonsági kulcs, hitelesítő alkalmazás, SMS, telefon hívás vagy email. A kétlépcsős bejelentkezést a bitwarden.com webes széfben lehet engedélyezni. Felkeressük a webhelyet most?" }, "editedFolder": { - "message": "A mappa módosításra került." + "message": "A mappa mentésre került." }, "deleteFolderConfirmation": { "message": "Biztos, hogy törölni akarod ezt a mappát?" @@ -562,7 +586,7 @@ "message": "Biztosan törlésre kerüljön ezt az elem?" }, "deletedItem": { - "message": "Az elem törlésre került." + "message": "Az elem a lomtárba került." }, "overwritePassword": { "message": "Jelszó felülírása" @@ -769,7 +793,7 @@ "message": "A naximális fájlméret 500 MB." }, "featureUnavailable": { - "message": "Ez a funkció nem érhető el." + "message": "A funkció nem érhető el." }, "encryptionKeyMigrationRequired": { "message": "Titkosítási kulcs migráció szükséges. Jelentkezzünk be a webes széfen keresztül a titkosítási kulcs frissítéséhez." @@ -787,7 +811,7 @@ "message": "Tagság frissítése" }, "premiumNotCurrentMember": { - "message": "Jelenleg nincs prémium tagság." + "message": "Jelenleg nem vagyunk prémium tag." }, "premiumSignUpAndGet": { "message": "Regisztráció a prémium tagságra az alábbi funkciókért:" @@ -796,7 +820,7 @@ "message": "1 GB titkosított tárhely a fájlmellékleteknek." }, "premiumSignUpTwoStepOptions": { - "message": "Proprietary two-step login options such as YubiKey and Duo." + "message": "Saját kétlépcsős bejelentkezési lehetőségek mint a YubiKey és a Duo." }, "ppremiumSignUpReports": { "message": "Jelszó higiénia, fiók biztonság és adatszivárgási jelentések a széf biztonsága érdekében." @@ -817,7 +841,7 @@ "message": "A prémium tagság megvásárolható a bitwarden.com webes széfben. Szeretnénk felkeresni a webhelyet most?" }, "premiumCurrentMember": { - "message": "Jelenleg a prémium tagság érvényben van." + "message": "Prémium tag vagyunk!" }, "premiumCurrentMemberThanks": { "message": "Köszönjük a Bitwarden támogatását." @@ -994,7 +1018,7 @@ "message": "Alapértelmezett beállítások bejelentkezési elemekhez" }, "defaultAutoFillOnPageLoadDesc": { - "message": "Az Automatikus kitöltés engedélyezése az oldalbetöltéskor engedélyezheti vagy letilthatja a funkciót az egyes bejelentkezési elemeknél. Ez az alapértelmezett beállítás a bejelentkezési elemeknéll, amelyek nincsenek külön konfigurálva." + "message": "Az egyes bejelentkezési elemeknél kikapcsolhatjuk oldalbetöltéskor az automatikus kitöltést az elem Szerkesztés nézetében." }, "itemAutoFillOnPageLoad": { "message": "Automatikus kitöltés oldal betöltésnél (Ha engedélyezett az opcióknál)" @@ -1905,7 +1929,7 @@ "message": "Perc" }, "vaultTimeoutPolicyInEffect": { - "message": "A szervezeti házirendek hatással vannak a széf időkorlátjára. A széf időkorlátja legfeljebb $HOURS$ óra és $MINUTES$ perc lehet.", + "message": "A szervezeti szabályzata $HOURS$ órára és $MINUTES$ percre állította be a maximálisan megengedett széf időtúllépést.", "placeholders": { "hours": { "content": "$1", @@ -2406,5 +2430,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..7b19a6838c0 100644 --- a/apps/browser/src/_locales/id/messages.json +++ b/apps/browser/src/_locales/id/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Isi otomatis" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "Membuat Kata Sandi (tersalin)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Tidak ada info masuk yang cocok." }, + "noCards": { + "message": "No cards" + }, + "noIdentities": { + "message": "No identities" + }, + "addLoginMenu": { + "message": "Add login" + }, + "addCardMenu": { + "message": "Add card" + }, + "addIdentityMenu": { + "message": "Add identity" + }, "unlockVaultMenu": { "message": "Buka brankas Anda" }, @@ -2406,5 +2430,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..9bca2da6062 100644 --- a/apps/browser/src/_locales/it/messages.json +++ b/apps/browser/src/_locales/it/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Riempimento automatico" }, + "autoFillLogin": { + "message": "Riempi automaticamente login" + }, + "autoFillCard": { + "message": "Riempi automaticamente carta" + }, + "autoFillIdentity": { + "message": "Riempi automaticamente identità" + }, "generatePasswordCopied": { "message": "Genera password e copiala" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Nessun login corrispondente" }, + "noCards": { + "message": "Nessuna carta" + }, + "noIdentities": { + "message": "Nessuna identità" + }, + "addLoginMenu": { + "message": "Aggiungi login" + }, + "addCardMenu": { + "message": "Aggiungi carta" + }, + "addIdentityMenu": { + "message": "Aggiungi identità" + }, "unlockVaultMenu": { "message": "Sblocca la tua cassaforte" }, @@ -2406,5 +2430,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..d2528a45489 100644 --- a/apps/browser/src/_locales/ja/messages.json +++ b/apps/browser/src/_locales/ja/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "自動入力" }, + "autoFillLogin": { + "message": "自動入力ログイン" + }, + "autoFillCard": { + "message": "自動入力カード" + }, + "autoFillIdentity": { + "message": "自動入力 ID" + }, "generatePasswordCopied": { "message": "パスワードを生成 (コピー)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "一致するログインがありません。" }, + "noCards": { + "message": "カードなし" + }, + "noIdentities": { + "message": "ID なし" + }, + "addLoginMenu": { + "message": "ログイン情報を追加" + }, + "addCardMenu": { + "message": "カードを追加" + }, + "addIdentityMenu": { + "message": "ID を追加" + }, "unlockVaultMenu": { "message": "保管庫のロックを解除" }, @@ -2406,5 +2430,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..2d2b5cb8a5e 100644 --- a/apps/browser/src/_locales/ka/messages.json +++ b/apps/browser/src/_locales/ka/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "თვითშევსება" }, + "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" }, @@ -2406,5 +2430,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..22330901579 100644 --- a/apps/browser/src/_locales/km/messages.json +++ b/apps/browser/src/_locales/km/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" }, @@ -2406,5 +2430,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..95c9350aff8 100644 --- a/apps/browser/src/_locales/kn/messages.json +++ b/apps/browser/src/_locales/kn/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "ಸ್ವಯಂ ಭರ್ತಿ" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "ಪಾಸ್ವರ್ಡ್ ರಚಿಸಿ (ನಕಲಿಸಲಾಗಿದೆ)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "ಹೊಂದಾಣಿಕೆಯ ಲಾಗಿನ್‌ಗಳು ಇಲ್ಲ." }, + "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" }, @@ -2406,5 +2430,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..e7aba95f493 100644 --- a/apps/browser/src/_locales/ko/messages.json +++ b/apps/browser/src/_locales/ko/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "자동 완성" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "비밀번호 생성 및 클립보드에 복사" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "사용할 수 있는 로그인이 없습니다." }, + "noCards": { + "message": "No cards" + }, + "noIdentities": { + "message": "No identities" + }, + "addLoginMenu": { + "message": "Add login" + }, + "addCardMenu": { + "message": "Add card" + }, + "addIdentityMenu": { + "message": "Add identity" + }, "unlockVaultMenu": { "message": "보관함 잠금 해제" }, @@ -2406,5 +2430,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..885b3cbec8f 100644 --- a/apps/browser/src/_locales/lt/messages.json +++ b/apps/browser/src/_locales/lt/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Automatinis užpildymas" }, + "autoFillLogin": { + "message": "Automatinio užpildymo prisijungimas" + }, + "autoFillCard": { + "message": "Automatinio užpildymo kortelė" + }, + "autoFillIdentity": { + "message": "Automatinio užpildymo tapatybė" + }, "generatePasswordCopied": { "message": "Kurti slaptažodį (paruoštas įterpti)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Nėra atitinkančių prisijungimų." }, + "noCards": { + "message": "Nėra kortelių" + }, + "noIdentities": { + "message": "Nėra tapatybių" + }, + "addLoginMenu": { + "message": "Pridėti prisijungimą" + }, + "addCardMenu": { + "message": "Pridėti kortelę" + }, + "addIdentityMenu": { + "message": "Pridėti tapatybę" + }, "unlockVaultMenu": { "message": "Atrakinti saugyklą" }, @@ -2406,5 +2430,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..2abb0ac4de6 100644 --- a/apps/browser/src/_locales/lv/messages.json +++ b/apps/browser/src/_locales/lv/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Automātiskā aizpildīšana" }, + "autoFillLogin": { + "message": "Automātiski aizpildīt pieteikšanos" + }, + "autoFillCard": { + "message": "Automātiski aizpildīt karti" + }, + "autoFillIdentity": { + "message": "Automātiski aizpildīt identitāti" + }, "generatePasswordCopied": { "message": "Izveidot paroli (tiks ievietota starpliktuvē)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Nav atbilstošu pieteikšanās vienumu" }, + "noCards": { + "message": "Nav karšu" + }, + "noIdentities": { + "message": "Nav identitāšu" + }, + "addLoginMenu": { + "message": "Pievienot pieteikšanās vienumu" + }, + "addCardMenu": { + "message": "Pievienot karti" + }, + "addIdentityMenu": { + "message": "Pievienot identitāti" + }, "unlockVaultMenu": { "message": "Atslēgt glabātavu" }, @@ -2406,5 +2430,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..258ad3fd966 100644 --- a/apps/browser/src/_locales/ml/messages.json +++ b/apps/browser/src/_locales/ml/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "ഓട്ടോഫിൽ" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "പാസ്‌വേഡ് സൃഷ്ടിക്കുക (പകർത്തുക )" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "പൊരുത്തപ്പെടുന്ന ലോഗിനുകളൊന്നുമില്ല." }, + "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" }, @@ -2406,5 +2430,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..131c062d544 100644 --- a/apps/browser/src/_locales/mr/messages.json +++ b/apps/browser/src/_locales/mr/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "स्वयंभरण" }, + "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": "तिजोरी उघडा" }, @@ -2406,5 +2430,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..22330901579 100644 --- a/apps/browser/src/_locales/my/messages.json +++ b/apps/browser/src/_locales/my/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" }, @@ -2406,5 +2430,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..43a19478bb0 100644 --- a/apps/browser/src/_locales/nb/messages.json +++ b/apps/browser/src/_locales/nb/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Auto-utfylling" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "Generer et passord (kopiert)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Ingen samsvarende innlogginger." }, + "noCards": { + "message": "No cards" + }, + "noIdentities": { + "message": "No identities" + }, + "addLoginMenu": { + "message": "Add login" + }, + "addCardMenu": { + "message": "Add card" + }, + "addIdentityMenu": { + "message": "Add identity" + }, "unlockVaultMenu": { "message": "Lås opp hvelvet ditt" }, @@ -2406,5 +2430,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..22330901579 100644 --- a/apps/browser/src/_locales/ne/messages.json +++ b/apps/browser/src/_locales/ne/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" }, @@ -2406,5 +2430,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..630510f6723 100644 --- a/apps/browser/src/_locales/nl/messages.json +++ b/apps/browser/src/_locales/nl/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Auto-invullen" }, + "autoFillLogin": { + "message": "Login automatisch invullen" + }, + "autoFillCard": { + "message": "Kaart automatisch invullen" + }, + "autoFillIdentity": { + "message": "Identiteit automatisch invullen" + }, "generatePasswordCopied": { "message": "Wachtwoord genereren (op klembord)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Geen overeenkomstige logins." }, + "noCards": { + "message": "Geen kaarten" + }, + "noIdentities": { + "message": "Geen identiteiten" + }, + "addLoginMenu": { + "message": "Login toevoegen" + }, + "addCardMenu": { + "message": "Kaart toevoegen" + }, + "addIdentityMenu": { + "message": "Identiteit toevoegen" + }, "unlockVaultMenu": { "message": "Ontgrendel je kluis" }, @@ -772,7 +796,7 @@ "message": "Functionaliteit niet beschikbaar" }, "encryptionKeyMigrationRequired": { - "message": "Encryption key migration required. Please login through the web vault to update your encryption key." + "message": "Migratie van de encryptiesleutel vereist. Login via de website om je sleutel te bij te werken." }, "premiumMembership": { "message": "Premium-abonnement" @@ -2406,5 +2430,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..22330901579 100644 --- a/apps/browser/src/_locales/nn/messages.json +++ b/apps/browser/src/_locales/nn/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" }, @@ -2406,5 +2430,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..22330901579 100644 --- a/apps/browser/src/_locales/or/messages.json +++ b/apps/browser/src/_locales/or/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" }, @@ -2406,5 +2430,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..5b16c13ef14 100644 --- a/apps/browser/src/_locales/pl/messages.json +++ b/apps/browser/src/_locales/pl/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Autouzupełnianie" }, + "autoFillLogin": { + "message": "Autouzupełnianie logowania" + }, + "autoFillCard": { + "message": "Autouzupełnianie karty" + }, + "autoFillIdentity": { + "message": "Autouzupełnianie tożsamości" + }, "generatePasswordCopied": { "message": "Wygeneruj hasło (do schowka)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Brak pasujących danych logowania" }, + "noCards": { + "message": "Brak kart" + }, + "noIdentities": { + "message": "Brak tożsamości" + }, + "addLoginMenu": { + "message": "Dodaj dane logowania" + }, + "addCardMenu": { + "message": "Dodaj kartę" + }, + "addIdentityMenu": { + "message": "Dodaj tożsamość" + }, "unlockVaultMenu": { "message": "Odblokuj sejf" }, @@ -2406,5 +2430,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..7578ae170ca 100644 --- a/apps/browser/src/_locales/pt_BR/messages.json +++ b/apps/browser/src/_locales/pt_BR/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Autopreencher" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "Gerar Senha (copiada)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Sem credenciais correspondentes." }, + "noCards": { + "message": "No cards" + }, + "noIdentities": { + "message": "No identities" + }, + "addLoginMenu": { + "message": "Add login" + }, + "addCardMenu": { + "message": "Add card" + }, + "addIdentityMenu": { + "message": "Add identity" + }, "unlockVaultMenu": { "message": "Desbloqueie seu cofre" }, @@ -2406,5 +2430,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..1495b64e453 100644 --- a/apps/browser/src/_locales/pt_PT/messages.json +++ b/apps/browser/src/_locales/pt_PT/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Preenchimento automático" }, + "autoFillLogin": { + "message": "Preenchimento automático da credencial" + }, + "autoFillCard": { + "message": "Preenchimento automático do cartão" + }, + "autoFillIdentity": { + "message": "Preenchimento automático da identidade" + }, "generatePasswordCopied": { "message": "Gerar palavra-passe (copiada)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Sem credenciais correspondentes" }, + "noCards": { + "message": "Sem cartões" + }, + "noIdentities": { + "message": "Sem identidades" + }, + "addLoginMenu": { + "message": "Adicionar credencial" + }, + "addCardMenu": { + "message": "Adicionar cartão" + }, + "addIdentityMenu": { + "message": "Adicionar identidade" + }, "unlockVaultMenu": { "message": "Desbloquear o cofre" }, @@ -781,7 +805,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 +838,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 +954,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 +1303,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 +2430,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..085951a93f1 100644 --- a/apps/browser/src/_locales/ro/messages.json +++ b/apps/browser/src/_locales/ro/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Auto-completare" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "Generare parolă (s-a copiat)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Nu există potrivire de autentificări" }, + "noCards": { + "message": "No cards" + }, + "noIdentities": { + "message": "No identities" + }, + "addLoginMenu": { + "message": "Add login" + }, + "addCardMenu": { + "message": "Add card" + }, + "addIdentityMenu": { + "message": "Add identity" + }, "unlockVaultMenu": { "message": "Deblocați-vă seiful" }, @@ -199,7 +223,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 +363,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 +658,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 +796,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 +820,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 +1009,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 +1492,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 +1513,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 +1630,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 +1908,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 +1929,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 +1942,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 +1959,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 +2016,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 +2117,7 @@ "message": "Versiune server" }, "selfHostedServer": { - "message": "self-hosted" + "message": "auto-găzduit" }, "thirdParty": { "message": "Parte terță" @@ -2132,52 +2156,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 +2210,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 +2225,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 +2249,7 @@ } }, "autofillShortcutTextSafari": { - "message": "Default auto-fill shortcut: $COMMAND$.", + "message": "Scurtătură implicită de auto-completare: $COMMAND$.", "placeholders": { "command": { "content": "$1", @@ -2234,31 +2258,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 +2295,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 +2346,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 +2355,7 @@ } }, "inputForbiddenCharacters": { - "message": "The following characters are not allowed: $CHARACTERS$", + "message": "Următoarele caractere nu sunt permise: $CHARACTERS$", "placeholders": { "characters": { "content": "$1", @@ -2340,7 +2364,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 +2373,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 +2382,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 +2401,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 +2425,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..40ecd382bd5 100644 --- a/apps/browser/src/_locales/ru/messages.json +++ b/apps/browser/src/_locales/ru/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Автозаполнение" }, + "autoFillLogin": { + "message": "Автозаполнение логина" + }, + "autoFillCard": { + "message": "Автозаполнение карты" + }, + "autoFillIdentity": { + "message": "Автозаполнение личности" + }, "generatePasswordCopied": { "message": "Сгенерировать пароль (с копированием)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Нет подходящих логинов." }, + "noCards": { + "message": "Нет карт" + }, + "noIdentities": { + "message": "Нет личностей" + }, + "addLoginMenu": { + "message": "Добавить логин" + }, + "addCardMenu": { + "message": "Добавить карту" + }, + "addIdentityMenu": { + "message": "Добавить личность" + }, "unlockVaultMenu": { "message": "Разблокировать хранилище" }, @@ -2406,5 +2430,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..8ea364cb6d1 100644 --- a/apps/browser/src/_locales/si/messages.json +++ b/apps/browser/src/_locales/si/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "ස්වයං-පිරවීම" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "මුරපදය ජනනය (පිටපත්)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "ගැලපෙන පිවිසුම් නොමැත." }, + "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" }, @@ -2406,5 +2430,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..d04f2ccf05a 100644 --- a/apps/browser/src/_locales/sk/messages.json +++ b/apps/browser/src/_locales/sk/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Automatické vypĺňanie" }, + "autoFillLogin": { + "message": "Automatické vyplnenie prihlasovacích údajov" + }, + "autoFillCard": { + "message": "Automatické vyplnenie karty" + }, + "autoFillIdentity": { + "message": "Automatické vyplnenie identity" + }, "generatePasswordCopied": { "message": "Vygenerovať heslo (skopírované)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Žiadne zodpovedajúce prihlasovacie údaje." }, + "noCards": { + "message": "Žiadne karty" + }, + "noIdentities": { + "message": "Žiadne identity" + }, + "addLoginMenu": { + "message": "Pridať prihlasovacie údaje" + }, + "addCardMenu": { + "message": "Pridať kartu" + }, + "addIdentityMenu": { + "message": "Pridať identitu" + }, "unlockVaultMenu": { "message": "Odomknúť trezor" }, @@ -2406,5 +2430,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..5f859e9e5f3 100644 --- a/apps/browser/src/_locales/sl/messages.json +++ b/apps/browser/src/_locales/sl/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Samodejno izpolnjevanje" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "Generiraj geslo (kopirano)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Ni ustreznih prijav." }, + "noCards": { + "message": "No cards" + }, + "noIdentities": { + "message": "No identities" + }, + "addLoginMenu": { + "message": "Add login" + }, + "addCardMenu": { + "message": "Add card" + }, + "addIdentityMenu": { + "message": "Add identity" + }, "unlockVaultMenu": { "message": "Odkleni svoj trezor" }, @@ -2406,5 +2430,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..d55a5bfe197 100644 --- a/apps/browser/src/_locales/sr/messages.json +++ b/apps/browser/src/_locales/sr/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Аутоматско допуњавање" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "Генериши Лозинку (копирано)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Нема одговарајућих пријављивања." }, + "noCards": { + "message": "No cards" + }, + "noIdentities": { + "message": "No identities" + }, + "addLoginMenu": { + "message": "Add login" + }, + "addCardMenu": { + "message": "Add card" + }, + "addIdentityMenu": { + "message": "Add identity" + }, "unlockVaultMenu": { "message": "Откључај свој сеф" }, @@ -772,7 +796,7 @@ "message": "Функција је недоступна" }, "encryptionKeyMigrationRequired": { - "message": "Encryption key migration required. Please login through the web vault to update your encryption key." + "message": "Потребна је миграција кључа за шифровање. Пријавите се преко веб сефа да бисте ажурирали кључ за шифровање." }, "premiumMembership": { "message": "Премијум чланство" @@ -2406,5 +2430,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/sv/messages.json b/apps/browser/src/_locales/sv/messages.json index 7a4816dfa96..ca0b8de6580 100644 --- a/apps/browser/src/_locales/sv/messages.json +++ b/apps/browser/src/_locales/sv/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Fyll i automatiskt" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "Skapa lösenord (kopierad)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Inga matchande inloggningar" }, + "noCards": { + "message": "Inga kort" + }, + "noIdentities": { + "message": "Inga identiteter" + }, + "addLoginMenu": { + "message": "Lägg till inloggning" + }, + "addCardMenu": { + "message": "Lägg till kort" + }, + "addIdentityMenu": { + "message": "Lägg till identitet" + }, "unlockVaultMenu": { "message": "Lås upp ditt valv" }, @@ -2406,5 +2430,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..22330901579 100644 --- a/apps/browser/src/_locales/te/messages.json +++ b/apps/browser/src/_locales/te/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" }, @@ -2406,5 +2430,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..20702a1de4a 100644 --- a/apps/browser/src/_locales/th/messages.json +++ b/apps/browser/src/_locales/th/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "กรอกข้อมูลอัตโนมัติ" }, + "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": "ไม่พบข้อมูลล็อกอินที่ตรงกัน" }, + "noCards": { + "message": "No cards" + }, + "noIdentities": { + "message": "No identities" + }, + "addLoginMenu": { + "message": "Add login" + }, + "addCardMenu": { + "message": "Add card" + }, + "addIdentityMenu": { + "message": "Add identity" + }, "unlockVaultMenu": { "message": "ปลดล็อกกตู้นิรภัยของคุณ" }, @@ -2406,5 +2430,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..e9763386aa6 100644 --- a/apps/browser/src/_locales/tr/messages.json +++ b/apps/browser/src/_locales/tr/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Otomatik doldur" }, + "autoFillLogin": { + "message": "Hesabı otomatik doldur" + }, + "autoFillCard": { + "message": "Kartı otomatik doldur" + }, + "autoFillIdentity": { + "message": "Kimliği otomatik doldur" + }, "generatePasswordCopied": { "message": "Parola oluştur (ve kopyala)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Eşleşen hesap yok" }, + "noCards": { + "message": "Kart yok" + }, + "noIdentities": { + "message": "Kimlik yok" + }, + "addLoginMenu": { + "message": "Hesap ekle" + }, + "addCardMenu": { + "message": "Kart ekle" + }, + "addIdentityMenu": { + "message": "Kimlik ekle" + }, "unlockVaultMenu": { "message": "Kasanızın kilidini açın" }, @@ -339,7 +363,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" @@ -1609,7 +1633,7 @@ "message": "Biyometri doğrulanamadı" }, "biometricsFailedDesc": { - "message": "Biometrics cannot be completed, consider using a master password or logging out. If this persists, please contact Bitwarden support." + "message": "Biyometri doğrulaması tamamlanamadı. Ana parolanızı kullanabilir veya çıkış yapabilirsiniz. Sorun devam ederse Bitwarden destek ekibiyle iletişime geçin." }, "nativeMessaginPermissionErrorTitle": { "message": "İzin verilmedi" @@ -2277,7 +2301,7 @@ "message": "Genel" }, "display": { - "message": "Display" + "message": "Görünüm" }, "accountSuccessfullyCreated": { "message": "Hesap başarıyla oluşturuldu!" @@ -2304,16 +2328,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 +2346,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 +2355,7 @@ } }, "inputForbiddenCharacters": { - "message": "The following characters are not allowed: $CHARACTERS$", + "message": "Şu karakterlere izin verilmez: $CHARACTERS$", "placeholders": { "characters": { "content": "$1", @@ -2349,7 +2373,7 @@ } }, "inputMaxValue": { - "message": "Input value must not exceed $MAX$.", + "message": "Girdi değeri en fazla $MAX$ olmalı.", "placeholders": { "max": { "content": "$1", @@ -2358,17 +2382,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 +2401,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 +2416,7 @@ "message": "Tümünü temizle" }, "plusNMore": { - "message": "+ $QUANTITY$ more", + "message": "+ $QUANTITY$ tane daha", "placeholders": { "quantity": { "content": "$1", @@ -2401,10 +2425,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..666870146d4 100644 --- a/apps/browser/src/_locales/uk/messages.json +++ b/apps/browser/src/_locales/uk/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Автозаповнення" }, + "autoFillLogin": { + "message": "Автозаповнення входу" + }, + "autoFillCard": { + "message": "Автозаповнення картки" + }, + "autoFillIdentity": { + "message": "Автозаповнення особистих даних" + }, "generatePasswordCopied": { "message": "Генерувати пароль (з копіюванням)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Немає відповідних записів" }, + "noCards": { + "message": "Немає карток" + }, + "noIdentities": { + "message": "Немає особистих даних" + }, + "addLoginMenu": { + "message": "Додати запис входу" + }, + "addCardMenu": { + "message": "Додати картку" + }, + "addIdentityMenu": { + "message": "Додати особисті дані" + }, "unlockVaultMenu": { "message": "Розблокуйте сховище" }, @@ -2406,5 +2430,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/vi/messages.json b/apps/browser/src/_locales/vi/messages.json index 7f256311f16..caedbb8b917 100644 --- a/apps/browser/src/_locales/vi/messages.json +++ b/apps/browser/src/_locales/vi/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "Tự động điền" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "Tạo mật khẩu (đã sao chép)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "Không có thông tin đăng nhập phù hợp." }, + "noCards": { + "message": "No cards" + }, + "noIdentities": { + "message": "No identities" + }, + "addLoginMenu": { + "message": "Add login" + }, + "addCardMenu": { + "message": "Add card" + }, + "addIdentityMenu": { + "message": "Add identity" + }, "unlockVaultMenu": { "message": "Mở khoá kho lưu trữ của bạn" }, @@ -2406,5 +2430,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..5331208af82 100644 --- a/apps/browser/src/_locales/zh_CN/messages.json +++ b/apps/browser/src/_locales/zh_CN/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "自动填充" }, + "autoFillLogin": { + "message": "自动填充登录" + }, + "autoFillCard": { + "message": "自动填充支付卡" + }, + "autoFillIdentity": { + "message": "自动填充身份" + }, "generatePasswordCopied": { "message": "生成密码(并复制)" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "无匹配的登录项目" }, + "noCards": { + "message": "无支付卡" + }, + "noIdentities": { + "message": "无身份" + }, + "addLoginMenu": { + "message": "添加登录项目" + }, + "addCardMenu": { + "message": "添加支付卡" + }, + "addIdentityMenu": { + "message": "添加身份" + }, "unlockVaultMenu": { "message": "解锁您的密码库" }, @@ -850,7 +874,7 @@ "message": "使用此功能需要高级会员资格。" }, "enterVerificationCodeApp": { - "message": "请输入您的验证器应用中的 6 位验证码。" + "message": "请输入您的验证器应用中的 6 位数验证码。" }, "enterVerificationCodeEmail": { "message": "请输入发送给电子邮件 $EMAIL$ 的 6 位数验证码。", @@ -2117,7 +2141,7 @@ } }, "loginWithMasterPassword": { - "message": "主密码登录" + "message": "使用主密码登录" }, "loggingInAs": { "message": "正登录为" @@ -2132,7 +2156,7 @@ "message": "记住电子邮件地址" }, "loginWithDevice": { - "message": "设备登录" + "message": "使用设备登录" }, "loginWithDeviceEnabledInfo": { "message": "设备登录必须在 Bitwarden 应用程序的设置中启用。需要其他登录选项吗?" @@ -2406,5 +2430,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..b3368beb188 100644 --- a/apps/browser/src/_locales/zh_TW/messages.json +++ b/apps/browser/src/_locales/zh_TW/messages.json @@ -91,6 +91,15 @@ "autoFill": { "message": "自動填入" }, + "autoFillLogin": { + "message": "Auto-fill login" + }, + "autoFillCard": { + "message": "Auto-fill card" + }, + "autoFillIdentity": { + "message": "Auto-fill identity" + }, "generatePasswordCopied": { "message": "產生及複製密碼" }, @@ -100,6 +109,21 @@ "noMatchingLogins": { "message": "無符合的登入資料" }, + "noCards": { + "message": "No cards" + }, + "noIdentities": { + "message": "No identities" + }, + "addLoginMenu": { + "message": "Add login" + }, + "addCardMenu": { + "message": "Add card" + }, + "addIdentityMenu": { + "message": "Add identity" + }, "unlockVaultMenu": { "message": "解鎖您的密碼庫" }, @@ -2406,5 +2430,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/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 81bf107650d..aca72562287 100644 --- a/apps/browser/src/autofill/services/autofill.service.ts +++ b/apps/browser/src/autofill/services/autofill.service.ts @@ -148,7 +148,7 @@ export default class AutofillService implements AutofillServiceInterface { throw new Error("Nothing to auto-fill."); } - let totpPromise: Promise = null; + let totp: string | null = null; const canAccessPremium = await this.stateService.getCanAccessPremium(); const defaultUriMatch = (await this.stateService.getDefaultUriMatch()) ?? UriMatchType.Domain; @@ -205,15 +205,14 @@ export default class AutofillService implements AutofillServiceInterface { if ( options.cipher.type !== CipherType.Login || - // eslint-disable-next-line @typescript-eslint/no-misused-promises - totpPromise || + totp !== null || !options.cipher.login.totp || (!canAccessPremium && !options.cipher.organizationUseTotp) ) { return; } - totpPromise = this.stateService.getDisableAutoTotpCopy().then((disabled) => { + totp = await this.stateService.getDisableAutoTotpCopy().then((disabled) => { if (!disabled) { return this.totpService.getCode(options.cipher.login.totp); } @@ -224,8 +223,8 @@ export default class AutofillService implements AutofillServiceInterface { if (didAutofill) { this.eventCollectionService.collect(EventType.Cipher_ClientAutofilled, options.cipher.id); - if (totpPromise != null) { - return await totpPromise; + if (totp !== null) { + return totp; } else { return null; } @@ -304,21 +303,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 582c0782caf..4fcfa685270 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -108,6 +108,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"; @@ -179,6 +185,8 @@ export default class MainBackground { containerService: ContainerService; auditService: AuditServiceAbstraction; authService: AuthServiceAbstraction; + importApiService: ImportApiServiceAbstraction; + importService: ImportServiceAbstraction; exportService: VaultExportServiceAbstraction; searchService: SearchServiceAbstraction; notificationsService: NotificationsServiceAbstraction; @@ -538,6 +546,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, @@ -602,6 +622,7 @@ export default class MainBackground { this.platformUtilsService as BrowserPlatformUtilsService, this.i18nService, this.notificationsService, + this.stateService, this.systemService, this.environmentService, this.messagingService, @@ -662,6 +683,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 3a6ed213d80..53711c1dc11 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"; import { AbortManager } from "../vault/background/abort-manager"; @@ -30,6 +32,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, @@ -140,12 +143,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": @@ -176,6 +195,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( [ { @@ -191,6 +211,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 0f21a10a84f..f0da7195f29 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 b02d7aec847..e87cdc0023b 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/browser/browser-api.ts b/apps/browser/src/platform/browser/browser-api.ts index 1295eeb6aee..a09c63e18ab 100644 --- a/apps/browser/src/platform/browser/browser-api.ts +++ b/apps/browser/src/platform/browser/browser-api.ts @@ -229,6 +229,8 @@ export class BrowserApi { // updated to pass synchronous callbacks to addListener. // Will not pass async methods because they will default return a Promoise // this causes race conditions in Firefox when a runtime.sendMessage listener receives undefined + + // eslint-disable-next-line no-restricted-syntax chrome.runtime.onMessage.addListener(callback); if (BrowserApi.isSafariApi && !BrowserApi.isBackgroundPage(window)) { @@ -240,6 +242,7 @@ export class BrowserApi { static storageChangeListener( callback: Parameters[0] ) { + // eslint-disable-next-line no-restricted-syntax chrome.storage.onChanged.addListener(callback); if (BrowserApi.isSafariApi && !BrowserApi.isBackgroundPage(window)) { 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 e25bed10677..9d41878c754 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; openFido2Popout( senderWindowId: number, 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 96c3d8b9c46..2c40d3da474 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/app.module.ts b/apps/browser/src/popup/app.module.ts index 23d033473c6..dd27a419a34 100644 --- a/apps/browser/src/popup/app.module.ts +++ b/apps/browser/src/popup/app.module.ts @@ -42,7 +42,6 @@ import { CipherRowComponent } from "../vault/popup/components/cipher-row.compone import { Fido2CipherRowComponent } from "../vault/popup/components/fido2/fido2-cipher-row.component"; import { Fido2UseBrowserLinkComponent } from "../vault/popup/components/fido2/fido2-use-browser-link.component"; import { Fido2Component } from "../vault/popup/components/fido2/fido2.component"; -import { PasswordRepromptComponent } from "../vault/popup/components/password-reprompt.component"; import { AddEditCustomFieldsComponent } from "../vault/popup/components/vault/add-edit-custom-fields.component"; import { AddEditComponent } from "../vault/popup/components/vault/add-edit.component"; import { AttachmentsComponent } from "../vault/popup/components/vault/attachments.component"; @@ -130,7 +129,6 @@ import "../platform/popup/locales"; GeneratorComponent, PasswordGeneratorHistoryComponent, PasswordHistoryComponent, - PasswordRepromptComponent, PopOutComponent, PremiumComponent, PrivateModeWarningComponent, diff --git a/apps/browser/src/popup/services/services.module.ts b/apps/browser/src/popup/services/services.module.ts index 0ba396af92f..6770e152504 100644 --- a/apps/browser/src/popup/services/services.module.ts +++ b/apps/browser/src/popup/services/services.module.ts @@ -80,11 +80,11 @@ import { FolderService, InternalFolderService, } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction"; -import { PasswordRepromptService as PasswordRepromptServiceAbstraction } from "@bitwarden/common/vault/abstractions/password-reprompt.service"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; 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"; @@ -103,7 +103,6 @@ import BrowserMessagingService from "../../platform/services/browser-messaging.s import { BrowserStateService } from "../../platform/services/browser-state.service"; import { BrowserSendService } from "../../services/browser-send.service"; import { BrowserSettingsService } from "../../services/browser-settings.service"; -import { PasswordRepromptService } from "../../vault/popup/services/password-reprompt.service"; import { BrowserFolderService } from "../../vault/services/browser-folder.service"; import { VaultFilterService } from "../../vault/services/vault-filter.service"; @@ -368,6 +367,11 @@ function getBgService(service: keyof MainBackground) { useFactory: getBgService("autofillService"), deps: [], }, + { + provide: ImportServiceAbstraction, + useFactory: getBgService("importService"), + deps: [], + }, { provide: VaultExportServiceAbstraction, useFactory: getBgService("exportService"), @@ -403,7 +407,6 @@ function getBgService(service: keyof MainBackground) { useFactory: getBgService("logService"), deps: [], }, - { provide: PasswordRepromptServiceAbstraction, useClass: PasswordRepromptService }, { provide: OrganizationService, useFactory: (stateService: StateServiceAbstraction) => { 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/popup/components/action-buttons.component.ts b/apps/browser/src/vault/popup/components/action-buttons.component.ts index 110e4ef32a5..ff8b7cab0d1 100644 --- a/apps/browser/src/vault/popup/components/action-buttons.component.ts +++ b/apps/browser/src/vault/popup/components/action-buttons.component.ts @@ -6,10 +6,10 @@ import { EventType } from "@bitwarden/common/enums"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; -import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/password-reprompt.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 { PasswordRepromptService } from "@bitwarden/vault"; @Component({ selector: "app-action-buttons", diff --git a/apps/browser/src/vault/popup/components/fido2/fido2.component.ts b/apps/browser/src/vault/popup/components/fido2/fido2.component.ts index bbf7e55ad77..7ee9e959f0e 100644 --- a/apps/browser/src/vault/popup/components/fido2/fido2.component.ts +++ b/apps/browser/src/vault/popup/components/fido2/fido2.component.ts @@ -19,7 +19,6 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service" import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; -import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/password-reprompt.service"; import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type"; import { CipherType } from "@bitwarden/common/vault/enums/cipher-type"; import { CardView } from "@bitwarden/common/vault/models/view/card.view"; @@ -29,6 +28,7 @@ import { LoginUriView } from "@bitwarden/common/vault/models/view/login-uri.view import { LoginView } from "@bitwarden/common/vault/models/view/login.view"; import { SecureNoteView } from "@bitwarden/common/vault/models/view/secure-note.view"; import { DialogService } from "@bitwarden/components"; +import { PasswordRepromptService } from "@bitwarden/vault"; import { BrowserApi } from "../../../../platform/browser/browser-api"; import { diff --git a/apps/browser/src/vault/popup/components/password-reprompt.component.html b/apps/browser/src/vault/popup/components/password-reprompt.component.html deleted file mode 100644 index 730e96fab96..00000000000 --- a/apps/browser/src/vault/popup/components/password-reprompt.component.html +++ /dev/null @@ -1,55 +0,0 @@ - diff --git a/apps/browser/src/vault/popup/components/password-reprompt.component.ts b/apps/browser/src/vault/popup/components/password-reprompt.component.ts deleted file mode 100644 index f63da5ed48e..00000000000 --- a/apps/browser/src/vault/popup/components/password-reprompt.component.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Component } from "@angular/core"; - -import { PasswordRepromptComponent as BasePasswordRepromptComponent } from "@bitwarden/angular/vault/components/password-reprompt.component"; - -@Component({ - templateUrl: "password-reprompt.component.html", -}) -export class PasswordRepromptComponent extends BasePasswordRepromptComponent {} 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 41ef6105bd1..bab2a8fe41b 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 @@ -2,7 +2,7 @@ import { Location } from "@angular/common"; import { Component } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; import { firstValueFrom } from "rxjs"; -import { first, takeUntil } from "rxjs/operators"; +import { first } from "rxjs/operators"; import { AddEditComponent as BaseAddEditComponent } from "@bitwarden/angular/vault/components/add-edit.component"; import { AuditService } from "@bitwarden/common/abstractions/audit.service"; @@ -18,10 +18,10 @@ import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.s import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service"; import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction"; -import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/password-reprompt.service"; import { CipherType } from "@bitwarden/common/vault/enums/cipher-type"; import { LoginUriView } from "@bitwarden/common/vault/models/view/login-uri.view"; import { DialogService } from "@bitwarden/components"; +import { PasswordRepromptService } from "@bitwarden/vault"; import { BrowserApi } from "../../../../platform/browser/browser-api"; import { PopupUtilsService } from "../../../../popup/services/popup-utils.service"; @@ -40,9 +40,9 @@ export class AddEditComponent extends BaseAddEditComponent { showAttachments = true; openAttachmentsInPopup: boolean; showAutoFillOnPageLoadOptions: boolean; - inPopout = false; senderTabId?: number; uilocation?: "popout" | "popup" | "sidebar" | "tab"; + inPopout = false; private fido2PopoutSessionData$ = fido2PopoutSessionData$(); @@ -89,15 +89,11 @@ export class AddEditComponent extends BaseAddEditComponent { async ngOnInit() { await super.ngOnInit(); - this.route.queryParams.pipe(takeUntil(this.destroy$)).subscribe((value) => { - this.senderTabId = parseInt(value?.senderTabId, 10) || undefined; - this.uilocation = value?.uilocation; - }); - - this.inPopout = this.uilocation === "popout" || this.popupUtilsService.inPopout(window); - // 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; } @@ -145,6 +141,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 = @@ -185,6 +183,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 { @@ -224,13 +227,13 @@ export class AddEditComponent extends BaseAddEditComponent { return; } - if (this.popupUtilsService.inTab(window)) { - this.messagingService.send("closeTab"); + if (this.senderTabId && this.inPopout) { + this.close(); return; } - if (this.inPopout && this.senderTabId) { - this.close(); + if (this.popupUtilsService.inTab(window)) { + this.messagingService.send("closeTab"); return; } diff --git a/apps/browser/src/vault/popup/components/vault/current-tab.component.ts b/apps/browser/src/vault/popup/components/vault/current-tab.component.ts index 4b2c62a0e0d..4f1ceb466de 100644 --- a/apps/browser/src/vault/popup/components/vault/current-tab.component.ts +++ b/apps/browser/src/vault/popup/components/vault/current-tab.component.ts @@ -11,11 +11,11 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; -import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/password-reprompt.service"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; 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 { PasswordRepromptService } from "@bitwarden/vault"; import { AutofillService } from "../../../../autofill/services/abstractions/autofill.service"; import { BrowserApi } from "../../../../platform/browser/browser-api"; diff --git a/apps/browser/src/vault/popup/components/vault/view.component.ts b/apps/browser/src/vault/popup/components/vault/view.component.ts index eabd9442eb0..3393e852cb6 100644 --- a/apps/browser/src/vault/popup/components/vault/view.component.ts +++ b/apps/browser/src/vault/popup/components/vault/view.component.ts @@ -20,10 +20,11 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction"; -import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/password-reprompt.service"; +import { CipherType } from "@bitwarden/common/vault/enums/cipher-type"; import { Cipher } from "@bitwarden/common/vault/models/domain/cipher"; import { LoginUriView } from "@bitwarden/common/vault/models/view/login-uri.view"; import { DialogService } from "@bitwarden/components"; +import { PasswordRepromptService } from "@bitwarden/vault"; import { AutofillService } from "../../../../autofill/services/abstractions/autofill.service"; import { BrowserApi } from "../../../../platform/browser/browser-api"; @@ -59,6 +60,7 @@ export class ViewComponent extends BaseViewComponent { uilocation?: "popout" | "popup" | "sidebar" | "tab"; loadPageDetailsTimeout: number; inPopout = false; + cipherType = CipherType; private fido2PopoutSessionData$ = fido2PopoutSessionData$(); private destroy$ = new Subject(); diff --git a/apps/browser/src/vault/popup/services/password-reprompt.service.ts b/apps/browser/src/vault/popup/services/password-reprompt.service.ts deleted file mode 100644 index 22bbcf44d7f..00000000000 --- a/apps/browser/src/vault/popup/services/password-reprompt.service.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Injectable } from "@angular/core"; - -import { PasswordRepromptService as BasePasswordRepromptService } from "@bitwarden/angular/vault/services/password-reprompt.service"; - -import { PasswordRepromptComponent } from "../components/password-reprompt.component"; - -@Injectable() -export class PasswordRepromptService extends BasePasswordRepromptService { - component = PasswordRepromptComponent; -} diff --git a/apps/browser/store/locales/az/copy.resx b/apps/browser/store/locales/az/copy.resx index 677ad41b6bc..cb05f8e5d9e 100644 --- a/apps/browser/store/locales/az/copy.resx +++ b/apps/browser/store/locales/az/copy.resx @@ -139,7 +139,7 @@ Bitwarden, parolları iş yoldaşlarınızla təhlükəsiz paylaşa bilməyiniz Nəyə görə Bitwarden-i seçməliyik: Yüksək səviyyə şifrələmə -Parollarınız qabaqcıl bir ucdan digərinə kimi şifrələmə (AES-256 bit, salted hashtag və PBKDF2 SHA-256) ilə qorunur, beləcə verilənlərinizin güvənli və gizli qalmasını təmin edir. +Parollarınız qabaqcıl ucdan-uca şifrələmə (AES-256 bit, salted hashtag və PBKDF2 SHA-256) ilə qorunur, beləcə datanızın güvənli və gizli qalmasını təmin edir. Daxili parol yaradıcı Çox istifadə etdiyiniz hər veb sayt üçün təhlükəsizlik tələblərinə görə güclü, unikal və təsadüfi şifrələr yaradın. diff --git a/apps/browser/tsconfig.json b/apps/browser/tsconfig.json index 9624939c872..357be6c5281 100644 --- a/apps/browser/tsconfig.json +++ b/apps/browser/tsconfig.json @@ -15,7 +15,8 @@ "@bitwarden/common/*": ["../../libs/common/src/*"], "@bitwarden/components": ["../../libs/components/src"], "@bitwarden/exporter/*": ["../../libs/exporter/src/*"], - "@bitwarden/vault": ["../../libs/auth/src"] + "@bitwarden/importer": ["../../libs/importer/src"], + "@bitwarden/vault": ["../../libs/vault/src"] }, "useDefineForClassFields": 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/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..0830fabf13d 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": "26.3.0", "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/app/app.module.ts b/apps/desktop/src/app/app.module.ts index d14c40854cc..172447822c9 100644 --- a/apps/desktop/src/app/app.module.ts +++ b/apps/desktop/src/app/app.module.ts @@ -24,7 +24,6 @@ import { TwoFactorOptionsComponent } from "../auth/two-factor-options.component" import { TwoFactorComponent } from "../auth/two-factor.component"; import { UpdateTempPasswordComponent } from "../auth/update-temp-password.component"; import { PremiumComponent } from "../vault/app/accounts/premium.component"; -import { PasswordRepromptComponent } from "../vault/app/components/password-reprompt.component"; import { AddEditCustomFieldsComponent } from "../vault/app/vault/add-edit-custom-fields.component"; import { AddEditComponent } from "../vault/app/vault/add-edit.component"; import { AttachmentsComponent } from "../vault/app/vault/attachments.component"; @@ -79,7 +78,6 @@ import { SendComponent } from "./tools/send/send.component"; GeneratorComponent, PasswordGeneratorHistoryComponent, PasswordHistoryComponent, - PasswordRepromptComponent, PremiumComponent, RegisterComponent, RemovePasswordComponent, diff --git a/apps/desktop/src/app/services/services.module.ts b/apps/desktop/src/app/services/services.module.ts index c6fd0049901..f4841073c9c 100644 --- a/apps/desktop/src/app/services/services.module.ts +++ b/apps/desktop/src/app/services/services.module.ts @@ -35,7 +35,6 @@ import { MemoryStorageService } from "@bitwarden/common/platform/services/memory import { SystemService } from "@bitwarden/common/platform/services/system.service"; import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password"; import { CipherService as CipherServiceAbstraction } from "@bitwarden/common/vault/abstractions/cipher.service"; -import { PasswordRepromptService as PasswordRepromptServiceAbstraction } from "@bitwarden/common/vault/abstractions/password-reprompt.service"; import { DialogService } from "@bitwarden/components"; import { LoginGuard } from "../../auth/guards/login.guard"; @@ -52,7 +51,6 @@ import { I18nService } from "../../platform/services/i18n.service"; import { EncryptedMessageHandlerService } from "../../services/encrypted-message-handler.service"; import { NativeMessageHandlerService } from "../../services/native-message-handler.service"; import { NativeMessagingService } from "../../services/native-messaging.service"; -import { PasswordRepromptService } from "../../vault/services/password-reprompt.service"; import { SearchBarService } from "../layout/search/search-bar.service"; import { DesktopFileDownloadService } from "./desktop-file-download.service"; @@ -113,7 +111,6 @@ const RELOAD_CALLBACK = new InjectionToken<() => any>("RELOAD_CALLBACK"); StateServiceAbstraction, ], }, - { provide: PasswordRepromptServiceAbstraction, useClass: PasswordRepromptService }, { provide: StateServiceAbstraction, useClass: ElectronStateService, 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_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..363159ecbdd 100644 --- a/apps/desktop/src/locales/fa/messages.json +++ b/apps/desktop/src/locales/fa/messages.json @@ -476,7 +476,7 @@ "message": "بیشترین حجم پرونده ۵۰۰ مگابایت است." }, "encryptionKeyMigrationRequired": { - "message": "Encryption key migration required. Please login through the web vault to update your encryption key." + "message": "انتقال کلید رمزگذاری مورد نیاز است. لطفاً از طریق گاوصندوق وب وارد شوید تا کلید رمزگذاری خود را به روز کنید." }, "editedFolder": { "message": "پوشه ذخیره شد" @@ -1078,7 +1078,7 @@ "message": "۱ گیگابایت فضای ذخیره‌سازی رمزنگاری شده برای پرونده‌های پیوست." }, "premiumSignUpTwoStepOptions": { - "message": "Proprietary two-step login options such as YubiKey and Duo." + "message": "گزینه های ورود اضافی دو مرحله ای مانند YubiKey و Duo." }, "premiumSignUpReports": { "message": "گزارش‌های بهداشت رمز عبور، سلامت حساب و نقض داده‌ها برای ایمن نگهداشتن گاوصندوق شما." @@ -1493,7 +1493,7 @@ "message": "یک گاوصندوق خارج شده درخواست احراز هویت مجدد را برای دسترسی آن می‌دهد." }, "unlockMethodNeededToChangeTimeoutActionDesc": { - "message": "Set up an unlock method to change your vault timeout action." + "message": "یک روش بازگشایی برای پایان زمان مجاز تنظیم کنید." }, "lock": { "message": "قفل", @@ -1985,7 +1985,7 @@ "message": "برون ریزی گاو‌صندوق شخصی" }, "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": "فقط موارد شخصی گاوصندوق مرتبط با $EMAIL$ برون ریزی خواهند شد. موارد گاوصندوق سازمان شامل نخواهد شد. فقط اطلاعات مورد گاوصندوق برون ریزی خواهد شد و شامل تاریخچه کلمه عبور مرتبط یا پیوست نمی‌شود.", "placeholders": { "email": { "content": "$1", @@ -2110,7 +2110,7 @@ "message": "با دستگاه دیگری وارد شوید" }, "loginInitiated": { - "message": "Login initiated" + "message": "ورود به سیستم آغاز شد" }, "notificationSentDevice": { "message": "یک اعلان به دستگاه شما ارسال شده است." @@ -2250,35 +2250,35 @@ "message": "به‌روز رسانی تنظیمات توصیه شده" }, "deviceApprovalRequired": { - "message": "Device approval required. Select an approval option below:" + "message": "تأیید دستگاه لازم است. یک روش تأیید انتخاب کنید:" }, "rememberThisDevice": { - "message": "Remember this device" + "message": "این دستگاه را به خاطر بسپار" }, "uncheckIfPublicDevice": { - "message": "Uncheck if using a public device" + "message": "اگر از دستگاه عمومی استفاده می‌کنید علامت را بردارید" }, "approveFromYourOtherDevice": { - "message": "Approve from your other device" + "message": "تأیید با دستگاه دیگرتان" }, "requestAdminApproval": { - "message": "Request admin approval" + "message": "درخواست تأیید مدیر" }, "approveWithMasterPassword": { - "message": "Approve with master password" + "message": "تأیید با کلمه عبور اصلی" }, "region": { - "message": "Region" + "message": "منطقه" }, "ssoIdentifierRequired": { - "message": "Organization SSO identifier is required." + "message": "شناسه سازمان SSO مورد نیاز است." }, "eu": { - "message": "EU", + "message": "اروپا", "description": "European Union" }, "loggingInOn": { - "message": "Logging in on" + "message": "ورود با" }, "usDomain": { "message": "bitwarden.com" @@ -2287,46 +2287,46 @@ "message": "bitwarden.eu" }, "selfHostedServer": { - "message": "self-hosted" + "message": "خود میزبان" }, "accessDenied": { "message": "دسترسی رد شد. شما اجازه مشاهده این صفحه را ندارید." }, "accountSuccessfullyCreated": { - "message": "Account successfully created!" + "message": "حساب کاربری با موفقیت ایجاد شد!" }, "adminApprovalRequested": { - "message": "Admin approval requested" + "message": "تأیید مدیر درخواست شد" }, "adminApprovalRequestSentToAdmins": { - "message": "Your request has been sent to your admin." + "message": "درخواست شما به مدیرتان فرستاده شد." }, "youWillBeNotifiedOnceApproved": { - "message": "You will be notified once approved." + "message": "به محض تأیید مطلع خواهید شد." }, "troubleLoggingIn": { - "message": "Trouble logging in?" + "message": "در ورود مشکلی دارید؟" }, "loginApproved": { - "message": "Login approved" + "message": "ورود تأیید شد" }, "userEmailMissing": { - "message": "User email missing" + "message": "ایمیل کاربر وجود ندارد" }, "deviceTrusted": { - "message": "Device trusted" + "message": "دستگاه مورد اعتماد است" }, "inputRequired": { - "message": "Input is required." + "message": "ورودی ضروری است." }, "required": { - "message": "required" + "message": "ضروری" }, "search": { - "message": "Search" + "message": "جستجو" }, "inputMinLength": { - "message": "Input must be at least $COUNT$ characters long.", + "message": "ورودی باید حداقل $COUNT$ کاراکتر داشته باشد.", "placeholders": { "count": { "content": "$1", @@ -2335,7 +2335,7 @@ } }, "inputMaxLength": { - "message": "Input must not exceed $COUNT$ characters in length.", + "message": "طول ورودی نباید بیش از $COUNT$ کاراکتر باشد.", "placeholders": { "count": { "content": "$1", @@ -2344,7 +2344,7 @@ } }, "inputForbiddenCharacters": { - "message": "The following characters are not allowed: $CHARACTERS$", + "message": "کاراکترهای زیر مجاز نیستند: $CHARACTERS$", "placeholders": { "characters": { "content": "$1", @@ -2353,7 +2353,7 @@ } }, "inputMinValue": { - "message": "Input value must be at least $MIN$.", + "message": "مقدار ورودی باید حداقل $MIN$ باشد.", "placeholders": { "min": { "content": "$1", @@ -2362,7 +2362,7 @@ } }, "inputMaxValue": { - "message": "Input value must not exceed $MAX$.", + "message": "مقدار ورودی نباید از $MAX$ تجاوز کند.", "placeholders": { "max": { "content": "$1", @@ -2371,17 +2371,17 @@ } }, "multipleInputEmails": { - "message": "1 or more emails are invalid" + "message": "یک یا چند ایمیل نامعتبر است" }, "inputTrimValidator": { - "message": "Input must not contain only whitespace.", + "message": "ورودی نباید فقط حاوی فضای خالی باشد.", "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": "ورودی یک نشانی ایمیل نیست." }, "fieldsNeedAttention": { - "message": "$COUNT$ field(s) above need your attention.", + "message": "فیلد $COUNT$ در بالا به توجه شما نیاز دارد.", "placeholders": { "count": { "content": "$1", @@ -2390,22 +2390,22 @@ } }, "selectPlaceholder": { - "message": "-- Select --" + "message": "-- انتخاب --" }, "multiSelectPlaceholder": { - "message": "-- Type to filter --" + "message": "-- برای فیلتر تایپ کنید --" }, "multiSelectLoading": { - "message": "Retrieving options..." + "message": "در حال بازیابی گزینه‌ها..." }, "multiSelectNotFound": { - "message": "No items found" + "message": "موردی یافت نشد" }, "multiSelectClearAll": { - "message": "Clear all" + "message": "پاک‌کردن همه" }, "plusNMore": { - "message": "+ $QUANTITY$ more", + "message": "+ $QUANTITY$ بیشتر", "placeholders": { "quantity": { "content": "$1", @@ -2414,6 +2414,9 @@ } }, "submenu": { - "message": "Submenu" + "message": "زیرمنو" + }, + "aliasDomain": { + "message": "دامنه مستعار" } } 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..392dbe4a141 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": "Домен алијаса" } } 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..a3489dce44e 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": "Псевдонім домену" } } 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..f656607fe60 100644 --- a/apps/desktop/src/locales/zh_CN/messages.json +++ b/apps/desktop/src/locales/zh_CN/messages.json @@ -594,7 +594,7 @@ "message": "继续" }, "enterVerificationCodeApp": { - "message": "请输入您的身份验证器应用中的 6 位验证码。" + "message": "请输入您的验证器应用中的 6 位数验证码。" }, "enterVerificationCodeEmail": { "message": "请输入发送给电子邮件 $EMAIL$ 的 6 位数验证码。", @@ -2083,7 +2083,7 @@ "message": "密码库" }, "loginWithMasterPassword": { - "message": "主密码登录" + "message": "使用主密码登录" }, "loggingInAs": { "message": "正登录为" @@ -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..3e8cf00867b 100644 --- a/apps/desktop/src/locales/zh_TW/messages.json +++ b/apps/desktop/src/locales/zh_TW/messages.json @@ -2119,7 +2119,7 @@ "message": "Please make sure your vault is unlocked and Fingerprint phrase matches the other device." }, "fingerprintPhraseHeader": { - "message": "Fingerprint phrase" + "message": "指紋短語" }, "needAnotherOption": { "message": "Log in with device must be set up in the settings of the Bitwarden app. Need another option?" @@ -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/vault/app/components/password-reprompt.component.html b/apps/desktop/src/vault/app/components/password-reprompt.component.html deleted file mode 100644 index 1ff853c278c..00000000000 --- a/apps/desktop/src/vault/app/components/password-reprompt.component.html +++ /dev/null @@ -1,57 +0,0 @@ - diff --git a/apps/desktop/src/vault/app/components/password-reprompt.component.ts b/apps/desktop/src/vault/app/components/password-reprompt.component.ts deleted file mode 100644 index f63da5ed48e..00000000000 --- a/apps/desktop/src/vault/app/components/password-reprompt.component.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Component } from "@angular/core"; - -import { PasswordRepromptComponent as BasePasswordRepromptComponent } from "@bitwarden/angular/vault/components/password-reprompt.component"; - -@Component({ - templateUrl: "password-reprompt.component.html", -}) -export class PasswordRepromptComponent extends BasePasswordRepromptComponent {} diff --git a/apps/desktop/src/vault/app/vault/add-edit.component.ts b/apps/desktop/src/vault/app/vault/add-edit.component.ts index 8a90d6a7e1a..00ae8022b16 100644 --- a/apps/desktop/src/vault/app/vault/add-edit.component.ts +++ b/apps/desktop/src/vault/app/vault/add-edit.component.ts @@ -16,8 +16,8 @@ import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.s import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service"; import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction"; -import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/password-reprompt.service"; import { DialogService } from "@bitwarden/components"; +import { PasswordRepromptService } from "@bitwarden/vault"; const BroadcasterSubscriptionId = "AddEditComponent"; diff --git a/apps/desktop/src/vault/app/vault/vault.component.ts b/apps/desktop/src/vault/app/vault/vault.component.ts index 194cee098f7..7930663499d 100644 --- a/apps/desktop/src/vault/app/vault/vault.component.ts +++ b/apps/desktop/src/vault/app/vault/vault.component.ts @@ -22,21 +22,21 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; -import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/password-reprompt.service"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; 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 { FolderView } from "@bitwarden/common/vault/models/view/folder.view"; import { DialogService } from "@bitwarden/components"; +import { PasswordRepromptService } from "@bitwarden/vault"; 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/src/vault/app/vault/view.component.ts b/apps/desktop/src/vault/app/vault/view.component.ts index b6bf63d6e64..adb72dbfe33 100644 --- a/apps/desktop/src/vault/app/vault/view.component.ts +++ b/apps/desktop/src/vault/app/vault/view.component.ts @@ -23,9 +23,9 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction"; -import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/password-reprompt.service"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { DialogService } from "@bitwarden/components"; +import { PasswordRepromptService } from "@bitwarden/vault"; const BroadcasterSubscriptionId = "ViewComponent"; diff --git a/apps/desktop/src/vault/services/password-reprompt.service.ts b/apps/desktop/src/vault/services/password-reprompt.service.ts deleted file mode 100644 index ebff838d5ca..00000000000 --- a/apps/desktop/src/vault/services/password-reprompt.service.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Injectable } from "@angular/core"; - -import { PasswordRepromptService as BasePasswordRepromptService } from "@bitwarden/angular/vault/services/password-reprompt.service"; - -import { PasswordRepromptComponent } from "../app/components/password-reprompt.component"; - -@Injectable() -export class PasswordRepromptService extends BasePasswordRepromptService { - component = PasswordRepromptComponent; -} 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/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/settings/organization-settings-routing.module.ts b/apps/web/src/app/admin-console/organizations/settings/organization-settings-routing.module.ts index 7feda23f5cf..1606d86497c 100644 --- a/apps/web/src/app/admin-console/organizations/settings/organization-settings-routing.module.ts +++ b/apps/web/src/app/admin-console/organizations/settings/organization-settings-routing.module.ts @@ -45,10 +45,20 @@ const routes: Routes = [ }, { path: "tools", - loadChildren: () => - import("../tools/import-export/org-import-export.module").then( - (m) => m.OrganizationImportExportModule - ), + children: [ + { + path: "import", + loadChildren: () => + import("../tools/import/org-import.module").then((m) => m.OrganizationImportModule), + }, + { + path: "export", + loadChildren: () => + import("../tools/vault-export/org-vault-export.module").then( + (m) => m.OrganizationVaultExportModule + ), + }, + ], }, ], }, 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/tools/exposed-passwords-report.component.ts b/apps/web/src/app/admin-console/organizations/tools/exposed-passwords-report.component.ts index cf721098a2c..415bd6516c2 100644 --- a/apps/web/src/app/admin-console/organizations/tools/exposed-passwords-report.component.ts +++ b/apps/web/src/app/admin-console/organizations/tools/exposed-passwords-report.component.ts @@ -6,9 +6,9 @@ import { AuditService } from "@bitwarden/common/abstractions/audit.service"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; -import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/password-reprompt.service"; import { Cipher } from "@bitwarden/common/vault/models/domain/cipher"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; +import { PasswordRepromptService } from "@bitwarden/vault"; // eslint-disable-next-line no-restricted-imports import { ExposedPasswordsReportComponent as BaseExposedPasswordsReportComponent } from "../../../reports/pages/exposed-passwords-report.component"; diff --git a/apps/web/src/app/admin-console/organizations/tools/import-export/org-import-export-routing.module.ts b/apps/web/src/app/admin-console/organizations/tools/import/org-import-routing.module.ts similarity index 53% rename from apps/web/src/app/admin-console/organizations/tools/import-export/org-import-export-routing.module.ts rename to apps/web/src/app/admin-console/organizations/tools/import/org-import-routing.module.ts index c0430ab2e07..9b4b4b5c787 100644 --- a/apps/web/src/app/admin-console/organizations/tools/import-export/org-import-export-routing.module.ts +++ b/apps/web/src/app/admin-console/organizations/tools/import/org-import-routing.module.ts @@ -3,14 +3,13 @@ import { RouterModule, Routes } from "@angular/router"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; -import { OrganizationPermissionsGuard } from "../../../../admin-console/organizations/guards/org-permissions.guard"; +import { OrganizationPermissionsGuard } from "../../guards/org-permissions.guard"; -import { OrganizationExportComponent } from "./org-export.component"; import { OrganizationImportComponent } from "./org-import.component"; const routes: Routes = [ { - path: "import", + path: "", component: OrganizationImportComponent, canActivate: [OrganizationPermissionsGuard], data: { @@ -18,18 +17,9 @@ const routes: Routes = [ organizationPermissions: (org: Organization) => org.canAccessImportExport, }, }, - { - path: "export", - component: OrganizationExportComponent, - canActivate: [OrganizationPermissionsGuard], - data: { - titleId: "exportVault", - organizationPermissions: (org: Organization) => org.canAccessImportExport, - }, - }, ]; @NgModule({ imports: [RouterModule.forChild(routes)], }) -export class OrganizationImportExportRoutingModule {} +export class OrganizationImportRoutingModule {} diff --git a/apps/web/src/app/admin-console/organizations/tools/import-export/org-import.component.ts b/apps/web/src/app/admin-console/organizations/tools/import/org-import.component.ts similarity index 95% rename from apps/web/src/app/admin-console/organizations/tools/import-export/org-import.component.ts rename to apps/web/src/app/admin-console/organizations/tools/import/org-import.component.ts index e8dad8baf41..b514f2bcf38 100644 --- a/apps/web/src/app/admin-console/organizations/tools/import-export/org-import.component.ts +++ b/apps/web/src/app/admin-console/organizations/tools/import/org-import.component.ts @@ -18,11 +18,11 @@ import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.serv import { DialogService } from "@bitwarden/components"; import { ImportServiceAbstraction } from "@bitwarden/importer"; -import { ImportComponent } from "../../../../tools/import-export/import.component"; +import { ImportComponent } from "../../../../tools/import/import.component"; @Component({ selector: "app-org-import", - templateUrl: "../../../../tools/import-export/import.component.html", + templateUrl: "../../../../tools/import/import.component.html", }) // eslint-disable-next-line rxjs-angular/prefer-takeuntil export class OrganizationImportComponent extends ImportComponent { diff --git a/apps/web/src/app/admin-console/organizations/tools/import-export/org-import-export.module.ts b/apps/web/src/app/admin-console/organizations/tools/import/org-import.module.ts similarity index 81% rename from apps/web/src/app/admin-console/organizations/tools/import-export/org-import-export.module.ts rename to apps/web/src/app/admin-console/organizations/tools/import/org-import.module.ts index e40e961ac98..66a22158e20 100644 --- a/apps/web/src/app/admin-console/organizations/tools/import-export/org-import-export.module.ts +++ b/apps/web/src/app/admin-console/organizations/tools/import/org-import.module.ts @@ -15,13 +15,12 @@ import { import { LooseComponentsModule, SharedModule } from "../../../../shared"; -import { OrganizationExportComponent } from "./org-export.component"; -import { OrganizationImportExportRoutingModule } from "./org-import-export-routing.module"; +import { OrganizationImportRoutingModule } from "./org-import-routing.module"; import { OrganizationImportComponent } from "./org-import.component"; @NgModule({ - imports: [SharedModule, LooseComponentsModule, OrganizationImportExportRoutingModule], - declarations: [OrganizationImportComponent, OrganizationExportComponent], + imports: [SharedModule, LooseComponentsModule, OrganizationImportRoutingModule], + declarations: [OrganizationImportComponent], providers: [ { provide: ImportApiServiceAbstraction, @@ -42,4 +41,4 @@ import { OrganizationImportComponent } from "./org-import.component"; }, ], }) -export class OrganizationImportExportModule {} +export class OrganizationImportModule {} diff --git a/apps/web/src/app/admin-console/organizations/tools/inactive-two-factor-report.component.ts b/apps/web/src/app/admin-console/organizations/tools/inactive-two-factor-report.component.ts index 9d62073e066..4cc68b1f9d0 100644 --- a/apps/web/src/app/admin-console/organizations/tools/inactive-two-factor-report.component.ts +++ b/apps/web/src/app/admin-console/organizations/tools/inactive-two-factor-report.component.ts @@ -6,8 +6,8 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; -import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/password-reprompt.service"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; +import { PasswordRepromptService } from "@bitwarden/vault"; // eslint-disable-next-line no-restricted-imports import { InactiveTwoFactorReportComponent as BaseInactiveTwoFactorReportComponent } from "../../../reports/pages/inactive-two-factor-report.component"; diff --git a/apps/web/src/app/admin-console/organizations/tools/reused-passwords-report.component.ts b/apps/web/src/app/admin-console/organizations/tools/reused-passwords-report.component.ts index b410b63e0ff..93652239a11 100644 --- a/apps/web/src/app/admin-console/organizations/tools/reused-passwords-report.component.ts +++ b/apps/web/src/app/admin-console/organizations/tools/reused-passwords-report.component.ts @@ -6,9 +6,9 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; -import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/password-reprompt.service"; import { Cipher } from "@bitwarden/common/vault/models/domain/cipher"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; +import { PasswordRepromptService } from "@bitwarden/vault"; // eslint-disable-next-line no-restricted-imports import { ReusedPasswordsReportComponent as BaseReusedPasswordsReportComponent } from "../../../reports/pages/reused-passwords-report.component"; diff --git a/apps/web/src/app/admin-console/organizations/tools/unsecured-websites-report.component.ts b/apps/web/src/app/admin-console/organizations/tools/unsecured-websites-report.component.ts index 53ce0304507..e8fbc0ed5e6 100644 --- a/apps/web/src/app/admin-console/organizations/tools/unsecured-websites-report.component.ts +++ b/apps/web/src/app/admin-console/organizations/tools/unsecured-websites-report.component.ts @@ -5,8 +5,8 @@ import { ModalService } from "@bitwarden/angular/services/modal.service"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; -import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/password-reprompt.service"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; +import { PasswordRepromptService } from "@bitwarden/vault"; // eslint-disable-next-line no-restricted-imports import { UnsecuredWebsitesReportComponent as BaseUnsecuredWebsitesReportComponent } from "../../../reports/pages/unsecured-websites-report.component"; diff --git a/apps/web/src/app/admin-console/organizations/tools/vault-export/org-vault-export-routing.module.ts b/apps/web/src/app/admin-console/organizations/tools/vault-export/org-vault-export-routing.module.ts new file mode 100644 index 00000000000..e3e809a550d --- /dev/null +++ b/apps/web/src/app/admin-console/organizations/tools/vault-export/org-vault-export-routing.module.ts @@ -0,0 +1,25 @@ +import { NgModule } from "@angular/core"; +import { RouterModule, Routes } from "@angular/router"; + +import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; + +import { OrganizationPermissionsGuard } from "../../guards/org-permissions.guard"; + +import { OrganizationVaultExportComponent } from "./org-vault-export.component"; + +const routes: Routes = [ + { + path: "", + component: OrganizationVaultExportComponent, + canActivate: [OrganizationPermissionsGuard], + data: { + titleId: "exportVault", + organizationPermissions: (org: Organization) => org.canAccessImportExport, + }, + }, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], +}) +export class OrganizationVaultExportRoutingModule {} diff --git a/apps/web/src/app/admin-console/organizations/tools/import-export/org-export.component.ts b/apps/web/src/app/admin-console/organizations/tools/vault-export/org-vault-export.component.ts similarity index 92% rename from apps/web/src/app/admin-console/organizations/tools/import-export/org-export.component.ts rename to apps/web/src/app/admin-console/organizations/tools/vault-export/org-vault-export.component.ts index 9ea1442fd13..ae91150f608 100644 --- a/apps/web/src/app/admin-console/organizations/tools/import-export/org-export.component.ts +++ b/apps/web/src/app/admin-console/organizations/tools/vault-export/org-vault-export.component.ts @@ -14,14 +14,14 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl import { DialogService } from "@bitwarden/components"; import { VaultExportServiceAbstraction } from "@bitwarden/exporter/vault-export"; -import { ExportComponent } from "../../../../tools/import-export/export.component"; +import { ExportComponent } from "../../../../tools/vault-export/export.component"; @Component({ selector: "app-org-export", - templateUrl: "../../../../tools/import-export/export.component.html", + templateUrl: "../../../../tools/vault-export/export.component.html", }) // eslint-disable-next-line rxjs-angular/prefer-takeuntil -export class OrganizationExportComponent extends ExportComponent { +export class OrganizationVaultExportComponent extends ExportComponent { constructor( cryptoService: CryptoService, i18nService: I18nService, diff --git a/apps/web/src/app/admin-console/organizations/tools/vault-export/org-vault-export.module.ts b/apps/web/src/app/admin-console/organizations/tools/vault-export/org-vault-export.module.ts new file mode 100644 index 00000000000..34b4fa4adba --- /dev/null +++ b/apps/web/src/app/admin-console/organizations/tools/vault-export/org-vault-export.module.ts @@ -0,0 +1,12 @@ +import { NgModule } from "@angular/core"; + +import { LooseComponentsModule, SharedModule } from "../../../../shared"; + +import { OrganizationVaultExportRoutingModule } from "./org-vault-export-routing.module"; +import { OrganizationVaultExportComponent } from "./org-vault-export.component"; + +@NgModule({ + imports: [SharedModule, LooseComponentsModule, OrganizationVaultExportRoutingModule], + declarations: [OrganizationVaultExportComponent], +}) +export class OrganizationVaultExportModule {} diff --git a/apps/web/src/app/admin-console/organizations/tools/weak-passwords-report.component.ts b/apps/web/src/app/admin-console/organizations/tools/weak-passwords-report.component.ts index 68619b27514..540f71d91dc 100644 --- a/apps/web/src/app/admin-console/organizations/tools/weak-passwords-report.component.ts +++ b/apps/web/src/app/admin-console/organizations/tools/weak-passwords-report.component.ts @@ -6,9 +6,9 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; -import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/password-reprompt.service"; import { Cipher } from "@bitwarden/common/vault/models/domain/cipher"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; +import { PasswordRepromptService } from "@bitwarden/vault"; // eslint-disable-next-line no-restricted-imports import { WeakPasswordsReportComponent as BaseWeakPasswordsReportComponent } from "../../../reports/pages/weak-passwords-report.component"; 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/auth.module.ts b/apps/web/src/app/auth/auth.module.ts new file mode 100644 index 00000000000..056b9f161f9 --- /dev/null +++ b/apps/web/src/app/auth/auth.module.ts @@ -0,0 +1,11 @@ +import { NgModule } from "@angular/core"; + +import { AuthSettingsModule } from "./settings/settings.module"; + +@NgModule({ + imports: [AuthSettingsModule], + declarations: [], + providers: [], + exports: [AuthSettingsModule], +}) +export class AuthModule {} diff --git a/apps/web/src/app/auth/core/index.ts b/apps/web/src/app/auth/core/index.ts new file mode 100644 index 00000000000..b2221a94a89 --- /dev/null +++ b/apps/web/src/app/auth/core/index.ts @@ -0,0 +1 @@ +export * from "./services"; diff --git a/apps/web/src/app/auth/core/services/index.ts b/apps/web/src/app/auth/core/services/index.ts new file mode 100644 index 00000000000..4ef20f4b97d --- /dev/null +++ b/apps/web/src/app/auth/core/services/index.ts @@ -0,0 +1 @@ +export * from "./webauthn-login"; diff --git a/apps/web/src/app/auth/core/services/webauthn-login/index.ts b/apps/web/src/app/auth/core/services/webauthn-login/index.ts new file mode 100644 index 00000000000..10dea636b8d --- /dev/null +++ b/apps/web/src/app/auth/core/services/webauthn-login/index.ts @@ -0,0 +1 @@ +export * from "./webauthn-login.service"; diff --git a/apps/web/src/app/auth/core/services/webauthn-login/request/save-credential.request.ts b/apps/web/src/app/auth/core/services/webauthn-login/request/save-credential.request.ts new file mode 100644 index 00000000000..ffd0e6cf709 --- /dev/null +++ b/apps/web/src/app/auth/core/services/webauthn-login/request/save-credential.request.ts @@ -0,0 +1,18 @@ +import { WebauthnLoginAttestationResponseRequest } from "./webauthn-login-attestation-response.request"; + +/** + * Request sent to the server to save a newly created webauthn login credential. + */ +export class SaveCredentialRequest { + /** The response recieved from the authenticator. This contains the public key */ + deviceResponse: WebauthnLoginAttestationResponseRequest; + + /** Nickname chosen by the user to identify this credential */ + name: string; + + /** + * Token required by the server to complete the creation. + * It contains encrypted information that the server needs to verify the credential. + */ + token: string; +} diff --git a/apps/web/src/app/auth/core/services/webauthn-login/request/webauthn-login-attestation-response.request.ts b/apps/web/src/app/auth/core/services/webauthn-login/request/webauthn-login-attestation-response.request.ts new file mode 100644 index 00000000000..4b33896290c --- /dev/null +++ b/apps/web/src/app/auth/core/services/webauthn-login/request/webauthn-login-attestation-response.request.ts @@ -0,0 +1,27 @@ +import { Utils } from "@bitwarden/common/platform/misc/utils"; + +import { WebauthnLoginAuthenticatorResponseRequest } from "./webauthn-login-authenticator-response.request"; + +/** + * The response recieved from an authentiator after a successful attestation. + * This request is used to save newly created webauthn login credentials to the server. + */ +export class WebauthnLoginAttestationResponseRequest extends WebauthnLoginAuthenticatorResponseRequest { + response: { + attestationObject: string; + clientDataJson: string; + }; + + constructor(credential: PublicKeyCredential) { + super(credential); + + if (!(credential.response instanceof AuthenticatorAttestationResponse)) { + throw new Error("Invalid authenticator response"); + } + + this.response = { + attestationObject: Utils.fromBufferToB64(credential.response.attestationObject), + clientDataJson: Utils.fromBufferToB64(credential.response.clientDataJSON), + }; + } +} diff --git a/apps/web/src/app/auth/core/services/webauthn-login/request/webauthn-login-authenticator-response.request.ts b/apps/web/src/app/auth/core/services/webauthn-login/request/webauthn-login-authenticator-response.request.ts new file mode 100644 index 00000000000..9e332ad5381 --- /dev/null +++ b/apps/web/src/app/auth/core/services/webauthn-login/request/webauthn-login-authenticator-response.request.ts @@ -0,0 +1,19 @@ +import { Utils } from "@bitwarden/common/platform/misc/utils"; + +/** + * An abstract class that represents responses recieved from the webauthn authenticator. + * It contains data that is commonly returned during different types of authenticator interactions. + */ +export abstract class WebauthnLoginAuthenticatorResponseRequest { + id: string; + rawId: string; + type: string; + extensions: Record; + + constructor(credential: PublicKeyCredential) { + this.id = credential.id; + this.rawId = Utils.fromBufferToB64(credential.rawId); + this.type = credential.type; + this.extensions = {}; // Extensions are handled client-side + } +} diff --git a/apps/web/src/app/auth/core/services/webauthn-login/response/webauthn-login-credential-create-options.response.ts b/apps/web/src/app/auth/core/services/webauthn-login/response/webauthn-login-credential-create-options.response.ts new file mode 100644 index 00000000000..ce588207727 --- /dev/null +++ b/apps/web/src/app/auth/core/services/webauthn-login/response/webauthn-login-credential-create-options.response.ts @@ -0,0 +1,22 @@ +import { ChallengeResponse } from "@bitwarden/common/auth/models/response/two-factor-web-authn.response"; +import { BaseResponse } from "@bitwarden/common/models/response/base.response"; + +/** + * Options provided by the server to be used during attestation (i.e. creation of a new webauthn credential) + */ +export class WebauthnLoginCredentialCreateOptionsResponse extends BaseResponse { + /** Options to be provided to the webauthn authenticator */ + options: ChallengeResponse; + + /** + * Contains an encrypted version of the {@link options}. + * Used by the server to validate the attestation response of newly created credentials. + */ + token: string; + + constructor(response: unknown) { + super(response); + this.options = new ChallengeResponse(this.getResponseProperty("options")); + this.token = this.getResponseProperty("token"); + } +} diff --git a/apps/web/src/app/auth/core/services/webauthn-login/response/webauthn-login-credential.response.ts b/apps/web/src/app/auth/core/services/webauthn-login/response/webauthn-login-credential.response.ts new file mode 100644 index 00000000000..7a7f5199e7c --- /dev/null +++ b/apps/web/src/app/auth/core/services/webauthn-login/response/webauthn-login-credential.response.ts @@ -0,0 +1,17 @@ +import { BaseResponse } from "@bitwarden/common/models/response/base.response"; + +/** + * A webauthn login credential recieved from the server. + */ +export class WebauthnLoginCredentialResponse extends BaseResponse { + id: string; + name: string; + prfSupport: boolean; + + constructor(response: unknown) { + super(response); + this.id = this.getResponseProperty("id"); + this.name = this.getResponseProperty("name"); + this.prfSupport = this.getResponseProperty("prfSupport"); + } +} diff --git a/apps/web/src/app/auth/core/services/webauthn-login/webauthn-login-api.service.ts b/apps/web/src/app/auth/core/services/webauthn-login/webauthn-login-api.service.ts new file mode 100644 index 00000000000..6dc61563491 --- /dev/null +++ b/apps/web/src/app/auth/core/services/webauthn-login/webauthn-login-api.service.ts @@ -0,0 +1,34 @@ +import { Injectable } from "@angular/core"; + +import { ApiService } from "@bitwarden/common/abstractions/api.service"; +import { SecretVerificationRequest } from "@bitwarden/common/auth/models/request/secret-verification.request"; +import { ListResponse } from "@bitwarden/common/models/response/list.response"; + +import { SaveCredentialRequest } from "./request/save-credential.request"; +import { WebauthnLoginCredentialCreateOptionsResponse } from "./response/webauthn-login-credential-create-options.response"; +import { WebauthnLoginCredentialResponse } from "./response/webauthn-login-credential.response"; + +@Injectable({ providedIn: "root" }) +export class WebauthnLoginApiService { + constructor(private apiService: ApiService) {} + + async getCredentialCreateOptions( + request: SecretVerificationRequest + ): Promise { + const response = await this.apiService.send("POST", "/webauthn/options", request, true, true); + return new WebauthnLoginCredentialCreateOptionsResponse(response); + } + + async saveCredential(request: SaveCredentialRequest): Promise { + await this.apiService.send("POST", "/webauthn", request, true, true); + return true; + } + + getCredentials(): Promise> { + return this.apiService.send("GET", "/webauthn", null, true, true); + } + + async deleteCredential(credentialId: string, request: SecretVerificationRequest): Promise { + await this.apiService.send("POST", `/webauthn/${credentialId}/delete`, request, true, true); + } +} diff --git a/apps/web/src/app/auth/core/services/webauthn-login/webauthn-login.service.spec.ts b/apps/web/src/app/auth/core/services/webauthn-login/webauthn-login.service.spec.ts new file mode 100644 index 00000000000..1e4f1fa7717 --- /dev/null +++ b/apps/web/src/app/auth/core/services/webauthn-login/webauthn-login.service.spec.ts @@ -0,0 +1,67 @@ +import { mock, MockProxy } from "jest-mock-extended"; + +import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction"; + +import { CredentialCreateOptionsView } from "../../views/credential-create-options.view"; + +import { WebauthnLoginApiService } from "./webauthn-login-api.service"; +import { WebauthnLoginService } from "./webauthn-login.service"; + +describe("WebauthnService", () => { + let apiService!: MockProxy; + let userVerificationService!: MockProxy; + let credentials: MockProxy; + let webauthnService!: WebauthnLoginService; + + beforeAll(() => { + // Polyfill missing class + window.PublicKeyCredential = class {} as any; + window.AuthenticatorAttestationResponse = class {} as any; + apiService = mock(); + userVerificationService = mock(); + credentials = mock(); + webauthnService = new WebauthnLoginService(apiService, userVerificationService, credentials); + }); + + describe("createCredential", () => { + it("should return undefined when navigator.credentials throws", async () => { + credentials.create.mockRejectedValue(new Error("Mocked error")); + const options = createCredentialCreateOptions(); + + const result = await webauthnService.createCredential(options); + + expect(result).toBeUndefined(); + }); + + it("should return credential when navigator.credentials does not throw", async () => { + const credential = createDeviceResponse(); + credentials.create.mockResolvedValue(credential as PublicKeyCredential); + const options = createCredentialCreateOptions(); + + const result = await webauthnService.createCredential(options); + + expect(result).toBe(credential); + }); + }); +}); + +function createCredentialCreateOptions(): CredentialCreateOptionsView { + return new CredentialCreateOptionsView(Symbol() as any, Symbol() as any); +} + +function createDeviceResponse(): PublicKeyCredential { + const credential = { + id: "dGVzdA==", + rawId: new Uint8Array([0x74, 0x65, 0x73, 0x74]), + type: "public-key", + response: { + attestationObject: new Uint8Array([0, 0, 0]), + clientDataJSON: "eyJ0ZXN0IjoidGVzdCJ9", + }, + } as any; + + Object.setPrototypeOf(credential, PublicKeyCredential.prototype); + Object.setPrototypeOf(credential.response, AuthenticatorAttestationResponse.prototype); + + return credential; +} diff --git a/apps/web/src/app/auth/core/services/webauthn-login/webauthn-login.service.ts b/apps/web/src/app/auth/core/services/webauthn-login/webauthn-login.service.ts new file mode 100644 index 00000000000..c5979f08c61 --- /dev/null +++ b/apps/web/src/app/auth/core/services/webauthn-login/webauthn-login.service.ts @@ -0,0 +1,115 @@ +import { Injectable, Optional } from "@angular/core"; +import { BehaviorSubject, filter, from, map, Observable, shareReplay, switchMap, tap } from "rxjs"; + +import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction"; +import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; +import { Verification } from "@bitwarden/common/types/verification"; + +import { CredentialCreateOptionsView } from "../../views/credential-create-options.view"; +import { WebauthnCredentialView } from "../../views/webauth-credential.view"; + +import { SaveCredentialRequest } from "./request/save-credential.request"; +import { WebauthnLoginAttestationResponseRequest } from "./request/webauthn-login-attestation-response.request"; +import { WebauthnLoginApiService } from "./webauthn-login-api.service"; + +@Injectable({ providedIn: "root" }) +export class WebauthnLoginService { + static readonly MaxCredentialCount = 5; + + private navigatorCredentials: CredentialsContainer; + private _refresh$ = new BehaviorSubject(undefined); + private _loading$ = new BehaviorSubject(true); + private readonly credentials$ = this._refresh$.pipe( + tap(() => this._loading$.next(true)), + switchMap(() => this.fetchCredentials$()), + tap(() => this._loading$.next(false)), + shareReplay({ bufferSize: 1, refCount: true }) + ); + + readonly loading$ = this._loading$.asObservable(); + + constructor( + private apiService: WebauthnLoginApiService, + private userVerificationService: UserVerificationService, + @Optional() navigatorCredentials?: CredentialsContainer, + @Optional() private logService?: LogService + ) { + // Default parameters don't work when used with Angular DI + this.navigatorCredentials = navigatorCredentials ?? navigator.credentials; + } + + async getCredentialCreateOptions( + verification: Verification + ): Promise { + const request = await this.userVerificationService.buildRequest(verification); + const response = await this.apiService.getCredentialCreateOptions(request); + return new CredentialCreateOptionsView(response.options, response.token); + } + + async createCredential( + credentialOptions: CredentialCreateOptionsView + ): Promise { + const nativeOptions: CredentialCreationOptions = { + publicKey: credentialOptions.options, + }; + + try { + const response = await this.navigatorCredentials.create(nativeOptions); + if (!(response instanceof PublicKeyCredential)) { + return undefined; + } + return response; + } catch (error) { + this.logService?.error(error); + return undefined; + } + } + + async saveCredential( + credentialOptions: CredentialCreateOptionsView, + deviceResponse: PublicKeyCredential, + name: string + ) { + const request = new SaveCredentialRequest(); + request.deviceResponse = new WebauthnLoginAttestationResponseRequest(deviceResponse); + request.token = credentialOptions.token; + request.name = name; + await this.apiService.saveCredential(request); + this.refresh(); + } + + /** + * List of webauthn credentials saved on the server. + * + * **Note:** + * - Subscribing might trigger a network request if the credentials haven't been fetched yet. + * - The observable is shared and will not create unnecessary duplicate requests. + * - The observable will automatically re-fetch if the user adds or removes a credential. + * - The observable is lazy and will only fetch credentials when subscribed to. + * - Don't subscribe to this in the constructor of a long-running service, as it will keep the observable alive. + */ + getCredentials$(): Observable { + return this.credentials$; + } + + getCredential$(credentialId: string): Observable { + return this.credentials$.pipe( + map((credentials) => credentials.find((c) => c.id === credentialId)), + filter((c) => c !== undefined) + ); + } + + async deleteCredential(credentialId: string, verification: Verification): Promise { + const request = await this.userVerificationService.buildRequest(verification); + await this.apiService.deleteCredential(credentialId, request); + this.refresh(); + } + + private fetchCredentials$(): Observable { + return from(this.apiService.getCredentials()).pipe(map((response) => response.data)); + } + + private refresh() { + this._refresh$.next(); + } +} diff --git a/apps/web/src/app/auth/core/views/credential-create-options.view.ts b/apps/web/src/app/auth/core/views/credential-create-options.view.ts new file mode 100644 index 00000000000..29efdef5ee6 --- /dev/null +++ b/apps/web/src/app/auth/core/views/credential-create-options.view.ts @@ -0,0 +1,5 @@ +import { ChallengeResponse } from "@bitwarden/common/auth/models/response/two-factor-web-authn.response"; + +export class CredentialCreateOptionsView { + constructor(readonly options: ChallengeResponse, readonly token: string) {} +} diff --git a/apps/web/src/app/auth/core/views/webauth-credential.view.ts b/apps/web/src/app/auth/core/views/webauth-credential.view.ts new file mode 100644 index 00000000000..ff5a9c692df --- /dev/null +++ b/apps/web/src/app/auth/core/views/webauth-credential.view.ts @@ -0,0 +1,5 @@ +export class WebauthnCredentialView { + id: string; + name: string; + prfSupport: boolean; +} diff --git a/apps/web/src/app/auth/index.ts b/apps/web/src/app/auth/index.ts new file mode 100644 index 00000000000..fb09223bd9e --- /dev/null +++ b/apps/web/src/app/auth/index.ts @@ -0,0 +1,2 @@ +export * from "./auth.module"; +export * from "./core"; 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..37a4ad5b59a 100644 --- a/apps/web/src/app/auth/settings/change-password.component.html +++ b/apps/web/src/app/auth/settings/change-password.component.html @@ -3,14 +3,17 @@
{{ "loggedOutWarning" | i18n }} - - + + -
+
@@ -122,3 +125,7 @@ {{ "changeMasterPassword" | i18n }} + + diff --git a/apps/web/src/app/auth/settings/change-password.component.ts b/apps/web/src/app/auth/settings/change-password.component.ts index 9ed8227316c..958582eb0a7 100644 --- a/apps/web/src/app/auth/settings/change-password.component.ts +++ b/apps/web/src/app/auth/settings/change-password.component.ts @@ -1,6 +1,6 @@ import { Component } from "@angular/core"; import { Router } from "@angular/router"; -import { firstValueFrom } from "rxjs"; +import { firstValueFrom, Observable } from "rxjs"; import { ChangePasswordComponent as BaseChangePasswordComponent } from "@bitwarden/angular/auth/components/change-password.component"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; @@ -11,12 +11,13 @@ import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-conso import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction"; -import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service"; import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction"; import { EmergencyAccessStatusType } from "@bitwarden/common/auth/enums/emergency-access-status-type"; import { EmergencyAccessUpdateRequest } from "@bitwarden/common/auth/models/request/emergency-access-update.request"; import { PasswordRequest } from "@bitwarden/common/auth/models/request/password.request"; +import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { UpdateKeyRequest } from "@bitwarden/common/models/request/update-key.request"; +import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; @@ -50,6 +51,8 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent { checkForBreaches = true; characterMinimumMessage = ""; + protected showWebauthnLoginSettings$: Observable; + constructor( i18nService: I18nService, cryptoService: CryptoService, @@ -65,13 +68,13 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent { private apiService: ApiService, private sendService: SendService, private organizationService: OrganizationService, - private keyConnectorService: KeyConnectorService, private router: Router, private organizationApiService: OrganizationApiServiceAbstraction, private organizationUserService: OrganizationUserService, dialogService: DialogService, private userVerificationService: UserVerificationService, - private deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction + private deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction, + private configService: ConfigServiceAbstraction ) { super( i18nService, @@ -86,6 +89,10 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent { } async ngOnInit() { + this.showWebauthnLoginSettings$ = this.configService.getFeatureFlag$( + FeatureFlag.PasswordlessLogin + ); + if (!(await this.userVerificationService.hasMasterPassword())) { this.router.navigate(["/settings/security/two-factor"]); } 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 @@