mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-02 13:23:29 +01:00
Merge branch 'master' into tde-key-model-migration
This commit is contained in:
commit
a4b329b413
2
.github/workflows/brew-bump-cli.yml
vendored
2
.github/workflows/brew-bump-cli.yml
vendored
@ -23,7 +23,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Retrieve secrets
|
- name: Retrieve secrets
|
||||||
id: retrieve-secrets
|
id: retrieve-secrets
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
keyvault: "bitwarden-ci"
|
keyvault: "bitwarden-ci"
|
||||||
secrets: "brew-bump-workflow-pat"
|
secrets: "brew-bump-workflow-pat"
|
||||||
|
2
.github/workflows/brew-bump-desktop.yml
vendored
2
.github/workflows/brew-bump-desktop.yml
vendored
@ -23,7 +23,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Retrieve secrets
|
- name: Retrieve secrets
|
||||||
id: retrieve-secrets
|
id: retrieve-secrets
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
keyvault: "bitwarden-ci"
|
keyvault: "bitwarden-ci"
|
||||||
secrets: "brew-bump-workflow-pat"
|
secrets: "brew-bump-workflow-pat"
|
||||||
|
4
.github/workflows/build-browser.yml
vendored
4
.github/workflows/build-browser.yml
vendored
@ -354,7 +354,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Retrieve secrets
|
- name: Retrieve secrets
|
||||||
id: retrieve-secrets
|
id: retrieve-secrets
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
keyvault: "bitwarden-ci"
|
keyvault: "bitwarden-ci"
|
||||||
secrets: "crowdin-api-token"
|
secrets: "crowdin-api-token"
|
||||||
@ -416,7 +416,7 @@ jobs:
|
|||||||
- name: Retrieve secrets
|
- name: Retrieve secrets
|
||||||
id: retrieve-secrets
|
id: retrieve-secrets
|
||||||
if: failure()
|
if: failure()
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
keyvault: "bitwarden-ci"
|
keyvault: "bitwarden-ci"
|
||||||
secrets: "devops-alerts-slack-webhook-url"
|
secrets: "devops-alerts-slack-webhook-url"
|
||||||
|
2
.github/workflows/build-cli.yml
vendored
2
.github/workflows/build-cli.yml
vendored
@ -404,7 +404,7 @@ jobs:
|
|||||||
- name: Retrieve secrets
|
- name: Retrieve secrets
|
||||||
id: retrieve-secrets
|
id: retrieve-secrets
|
||||||
if: failure()
|
if: failure()
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
keyvault: "bitwarden-ci"
|
keyvault: "bitwarden-ci"
|
||||||
secrets: "devops-alerts-slack-webhook-url"
|
secrets: "devops-alerts-slack-webhook-url"
|
||||||
|
8
.github/workflows/build-desktop.yml
vendored
8
.github/workflows/build-desktop.yml
vendored
@ -277,7 +277,7 @@ jobs:
|
|||||||
node-gyp install $(node -v)
|
node-gyp install $(node -v)
|
||||||
|
|
||||||
- name: Install AST
|
- name: Install AST
|
||||||
uses: bitwarden/gh-actions/install-ast@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/install-ast@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
|
|
||||||
- name: Set up environmentF
|
- name: Set up environmentF
|
||||||
run: choco install checksum --no-progress
|
run: choco install checksum --no-progress
|
||||||
@ -302,7 +302,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Retrieve secrets
|
- name: Retrieve secrets
|
||||||
id: retrieve-secrets
|
id: retrieve-secrets
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
keyvault: "bitwarden-ci"
|
keyvault: "bitwarden-ci"
|
||||||
secrets: "code-signing-vault-url,
|
secrets: "code-signing-vault-url,
|
||||||
@ -1190,7 +1190,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Retrieve secrets
|
- name: Retrieve secrets
|
||||||
id: retrieve-secrets
|
id: retrieve-secrets
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
keyvault: "bitwarden-ci"
|
keyvault: "bitwarden-ci"
|
||||||
secrets: "crowdin-api-token"
|
secrets: "crowdin-api-token"
|
||||||
@ -1269,7 +1269,7 @@ jobs:
|
|||||||
- name: Retrieve secrets
|
- name: Retrieve secrets
|
||||||
id: retrieve-secrets
|
id: retrieve-secrets
|
||||||
if: failure()
|
if: failure()
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
keyvault: "bitwarden-ci"
|
keyvault: "bitwarden-ci"
|
||||||
secrets: "devops-alerts-slack-webhook-url"
|
secrets: "devops-alerts-slack-webhook-url"
|
||||||
|
8
.github/workflows/build-web.yml
vendored
8
.github/workflows/build-web.yml
vendored
@ -235,7 +235,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Retrieve github PAT secrets
|
- name: Retrieve github PAT secrets
|
||||||
id: retrieve-secret-pat
|
id: retrieve-secret-pat
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
keyvault: "bitwarden-ci"
|
keyvault: "bitwarden-ci"
|
||||||
secrets: "github-pat-bitwarden-devops-bot-repo-scope"
|
secrets: "github-pat-bitwarden-devops-bot-repo-scope"
|
||||||
@ -243,7 +243,7 @@ jobs:
|
|||||||
- name: Setup DCT
|
- name: Setup DCT
|
||||||
if: ${{ env.is_publish_branch == 'true' }}
|
if: ${{ env.is_publish_branch == 'true' }}
|
||||||
id: setup-dct
|
id: setup-dct
|
||||||
uses: bitwarden/gh-actions/setup-docker-trust@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/setup-docker-trust@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
azure-creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
azure-creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
||||||
azure-keyvault-name: "bitwarden-ci"
|
azure-keyvault-name: "bitwarden-ci"
|
||||||
@ -291,7 +291,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Retrieve secrets
|
- name: Retrieve secrets
|
||||||
id: retrieve-secrets
|
id: retrieve-secrets
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
keyvault: "bitwarden-ci"
|
keyvault: "bitwarden-ci"
|
||||||
secrets: "crowdin-api-token"
|
secrets: "crowdin-api-token"
|
||||||
@ -352,7 +352,7 @@ jobs:
|
|||||||
- name: Retrieve secrets
|
- name: Retrieve secrets
|
||||||
id: retrieve-secrets
|
id: retrieve-secrets
|
||||||
if: failure()
|
if: failure()
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
keyvault: "bitwarden-ci"
|
keyvault: "bitwarden-ci"
|
||||||
secrets: "devops-alerts-slack-webhook-url"
|
secrets: "devops-alerts-slack-webhook-url"
|
||||||
|
4
.github/workflows/crowdin-pull.yml
vendored
4
.github/workflows/crowdin-pull.yml
vendored
@ -32,13 +32,13 @@ jobs:
|
|||||||
|
|
||||||
- name: Retrieve secrets
|
- name: Retrieve secrets
|
||||||
id: retrieve-secrets
|
id: retrieve-secrets
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
keyvault: "bitwarden-ci"
|
keyvault: "bitwarden-ci"
|
||||||
secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase"
|
secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase"
|
||||||
|
|
||||||
- name: Download translations
|
- name: Download translations
|
||||||
uses: bitwarden/gh-actions/crowdin@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/crowdin@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
|
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
|
||||||
|
53
.github/workflows/deploy-eu-prod-web.yml
vendored
Normal file
53
.github/workflows/deploy-eu-prod-web.yml
vendored
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
---
|
||||||
|
name: Deploy Web to EU-PRD Cloud
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
tag:
|
||||||
|
description: "Branch name to deploy (examples: 'master', 'feature/sm')"
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
default: master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
azure-deploy:
|
||||||
|
name: Deploy to Azure
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
env:
|
||||||
|
_WEB_ARTIFACT: "web-*-cloud-euprd.zip"
|
||||||
|
steps:
|
||||||
|
- name: Login to Azure - EU Subscription
|
||||||
|
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.6
|
||||||
|
with:
|
||||||
|
creds: ${{ secrets.AZURE_KV_EU_PRD_SERVICE_PRINCIPAL }}
|
||||||
|
|
||||||
|
- name: Retrieve Storage Account connection string
|
||||||
|
id: retrieve-secrets
|
||||||
|
uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
|
with:
|
||||||
|
keyvault: webvault-westeurope-prod
|
||||||
|
secrets: "sa-bitwarden-web-vault-dev-key-temp"
|
||||||
|
|
||||||
|
- name: Download latest cloud asset
|
||||||
|
uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
|
with:
|
||||||
|
workflow: build-web.yml
|
||||||
|
path: apps/web
|
||||||
|
workflow_conclusion: success
|
||||||
|
branch: ${{ github.event.inputs.tag }}
|
||||||
|
artifacts: ${{ env._WEB_ARTIFACT }}
|
||||||
|
|
||||||
|
- name: Unzip build asset
|
||||||
|
working-directory: apps/web
|
||||||
|
run: unzip ${{ env._WEB_ARTIFACT }}
|
||||||
|
|
||||||
|
- name: Deploy to Azure Storage Account
|
||||||
|
working-directory: apps/web
|
||||||
|
run: |
|
||||||
|
az storage blob upload-batch --source "./build" \
|
||||||
|
--destination '$web' \
|
||||||
|
--account-name "bwwebvault1itgprod" \
|
||||||
|
--connection-string "${{ steps.retrieve-secrets.outputs.sa-bitwarden-web-vault-dev-key-temp }}" \
|
||||||
|
--overwrite \
|
||||||
|
--no-progress
|
2
.github/workflows/deploy-non-prod-web.yml
vendored
2
.github/workflows/deploy-non-prod-web.yml
vendored
@ -64,7 +64,7 @@ jobs:
|
|||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
||||||
|
|
||||||
- name: Download latest cloud asset
|
- name: Download latest cloud asset
|
||||||
uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
workflow: build-web.yml
|
workflow: build-web.yml
|
||||||
path: apps/web
|
path: apps/web
|
||||||
|
13
.github/workflows/deploy-prod-web.yml
vendored
13
.github/workflows/deploy-prod-web.yml
vendored
@ -1,13 +0,0 @@
|
|||||||
---
|
|
||||||
name: Deploy Web - EU Prod - STUB
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
stub-job:
|
|
||||||
name: Stub Job
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
steps:
|
|
||||||
- name: Stub Step
|
|
||||||
run: exit 0
|
|
6
.github/workflows/release-browser.yml
vendored
6
.github/workflows/release-browser.yml
vendored
@ -41,7 +41,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Check Release Version
|
- name: Check Release Version
|
||||||
id: version
|
id: version
|
||||||
uses: bitwarden/gh-actions/release-version-check@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/release-version-check@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
release-type: ${{ github.event.inputs.release_type }}
|
release-type: ${{ github.event.inputs.release_type }}
|
||||||
project-type: ts
|
project-type: ts
|
||||||
@ -103,7 +103,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Download latest Release build artifacts
|
- name: Download latest Release build artifacts
|
||||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||||
uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
workflow: build-browser.yml
|
workflow: build-browser.yml
|
||||||
workflow_conclusion: success
|
workflow_conclusion: success
|
||||||
@ -116,7 +116,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Dry Run - Download latest master build artifacts
|
- name: Dry Run - Download latest master build artifacts
|
||||||
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
||||||
uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
workflow: build-browser.yml
|
workflow: build-browser.yml
|
||||||
workflow_conclusion: success
|
workflow_conclusion: success
|
||||||
|
24
.github/workflows/release-cli.yml
vendored
24
.github/workflows/release-cli.yml
vendored
@ -57,7 +57,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Check Release Version
|
- name: Check Release Version
|
||||||
id: version
|
id: version
|
||||||
uses: bitwarden/gh-actions/release-version-check@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/release-version-check@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
release-type: ${{ github.event.inputs.release_type }}
|
release-type: ${{ github.event.inputs.release_type }}
|
||||||
project-type: ts
|
project-type: ts
|
||||||
@ -78,7 +78,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Download all Release artifacts
|
- name: Download all Release artifacts
|
||||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||||
uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
workflow: build-cli.yml
|
workflow: build-cli.yml
|
||||||
path: apps/cli
|
path: apps/cli
|
||||||
@ -87,7 +87,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Dry Run - Download all artifacts
|
- name: Dry Run - Download all artifacts
|
||||||
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
||||||
uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
workflow: build-cli.yml
|
workflow: build-cli.yml
|
||||||
path: apps/cli
|
path: apps/cli
|
||||||
@ -150,7 +150,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Retrieve secrets
|
- name: Retrieve secrets
|
||||||
id: retrieve-secrets
|
id: retrieve-secrets
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
keyvault: "bitwarden-ci"
|
keyvault: "bitwarden-ci"
|
||||||
secrets: "snapcraft-store-token"
|
secrets: "snapcraft-store-token"
|
||||||
@ -162,7 +162,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Download artifacts
|
- name: Download artifacts
|
||||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||||
uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
workflow: build-cli.yml
|
workflow: build-cli.yml
|
||||||
path: apps/cli
|
path: apps/cli
|
||||||
@ -172,7 +172,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Dry Run - Download artifacts
|
- name: Dry Run - Download artifacts
|
||||||
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
||||||
uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
workflow: build-cli.yml
|
workflow: build-cli.yml
|
||||||
path: apps/cli
|
path: apps/cli
|
||||||
@ -204,7 +204,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Retrieve secrets
|
- name: Retrieve secrets
|
||||||
id: retrieve-secrets
|
id: retrieve-secrets
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
keyvault: "bitwarden-ci"
|
keyvault: "bitwarden-ci"
|
||||||
secrets: "cli-choco-api-key"
|
secrets: "cli-choco-api-key"
|
||||||
@ -220,7 +220,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Download artifacts
|
- name: Download artifacts
|
||||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||||
uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
workflow: build-cli.yml
|
workflow: build-cli.yml
|
||||||
path: apps/cli/dist
|
path: apps/cli/dist
|
||||||
@ -230,7 +230,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Dry Run - Download artifacts
|
- name: Dry Run - Download artifacts
|
||||||
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
||||||
uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
workflow: build-cli.yml
|
workflow: build-cli.yml
|
||||||
path: apps/cli/dist
|
path: apps/cli/dist
|
||||||
@ -263,14 +263,14 @@ jobs:
|
|||||||
|
|
||||||
- name: Retrieve secrets
|
- name: Retrieve secrets
|
||||||
id: retrieve-secrets
|
id: retrieve-secrets
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
keyvault: "bitwarden-ci"
|
keyvault: "bitwarden-ci"
|
||||||
secrets: "npm-api-key"
|
secrets: "npm-api-key"
|
||||||
|
|
||||||
- name: Download artifacts
|
- name: Download artifacts
|
||||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||||
uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
workflow: build-cli.yml
|
workflow: build-cli.yml
|
||||||
path: apps/cli/build
|
path: apps/cli/build
|
||||||
@ -280,7 +280,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Dry Run - Download artifacts
|
- name: Dry Run - Download artifacts
|
||||||
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
||||||
uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
workflow: build-cli.yml
|
workflow: build-cli.yml
|
||||||
path: apps/cli/build
|
path: apps/cli/build
|
||||||
|
8
.github/workflows/release-desktop-beta.yml
vendored
8
.github/workflows/release-desktop-beta.yml
vendored
@ -47,7 +47,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Check Release Version
|
- name: Check Release Version
|
||||||
id: version
|
id: version
|
||||||
uses: bitwarden/gh-actions/release-version-check@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/release-version-check@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
release-type: 'Initial Release'
|
release-type: 'Initial Release'
|
||||||
project-type: ts
|
project-type: ts
|
||||||
@ -231,7 +231,7 @@ jobs:
|
|||||||
node-gyp install $(node -v)
|
node-gyp install $(node -v)
|
||||||
|
|
||||||
- name: Install AST
|
- name: Install AST
|
||||||
uses: bitwarden/gh-actions/install-ast@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/install-ast@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
|
|
||||||
- name: Set up environment
|
- name: Set up environment
|
||||||
run: choco install checksum --no-progress
|
run: choco install checksum --no-progress
|
||||||
@ -249,7 +249,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Retrieve secrets
|
- name: Retrieve secrets
|
||||||
id: retrieve-secrets
|
id: retrieve-secrets
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
keyvault: "bitwarden-ci"
|
keyvault: "bitwarden-ci"
|
||||||
secrets: "code-signing-vault-url,
|
secrets: "code-signing-vault-url,
|
||||||
@ -932,7 +932,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Retrieve secrets
|
- name: Retrieve secrets
|
||||||
id: retrieve-secrets
|
id: retrieve-secrets
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
keyvault: "bitwarden-ci"
|
keyvault: "bitwarden-ci"
|
||||||
secrets: "aws-electron-access-id,
|
secrets: "aws-electron-access-id,
|
||||||
|
24
.github/workflows/release-desktop.yml
vendored
24
.github/workflows/release-desktop.yml
vendored
@ -67,7 +67,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Check Release Version
|
- name: Check Release Version
|
||||||
id: version
|
id: version
|
||||||
uses: bitwarden/gh-actions/release-version-check@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/release-version-check@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
release-type: ${{ github.event.inputs.release_type }}
|
release-type: ${{ github.event.inputs.release_type }}
|
||||||
project-type: ts
|
project-type: ts
|
||||||
@ -110,7 +110,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Retrieve secrets
|
- name: Retrieve secrets
|
||||||
id: retrieve-secrets
|
id: retrieve-secrets
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
keyvault: "bitwarden-ci"
|
keyvault: "bitwarden-ci"
|
||||||
secrets: "aws-electron-access-id,
|
secrets: "aws-electron-access-id,
|
||||||
@ -123,7 +123,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Download all artifacts
|
- name: Download all artifacts
|
||||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||||
uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
workflow: build-desktop.yml
|
workflow: build-desktop.yml
|
||||||
workflow_conclusion: success
|
workflow_conclusion: success
|
||||||
@ -132,7 +132,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Dry Run - Download all artifacts
|
- name: Dry Run - Download all artifacts
|
||||||
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
||||||
uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
workflow: build-desktop.yml
|
workflow: build-desktop.yml
|
||||||
workflow_conclusion: success
|
workflow_conclusion: success
|
||||||
@ -185,7 +185,7 @@ jobs:
|
|||||||
--endpoint-url https://${CF_ACCOUNT}.r2.cloudflarestorage.com
|
--endpoint-url https://${CF_ACCOUNT}.r2.cloudflarestorage.com
|
||||||
|
|
||||||
- name: Get checksum files
|
- name: Get checksum files
|
||||||
uses: bitwarden/gh-actions/get-checksum@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/get-checksum@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
packages_dir: "apps/desktop/artifacts"
|
packages_dir: "apps/desktop/artifacts"
|
||||||
file_path: "apps/desktop/artifacts/sha256-checksums.txt"
|
file_path: "apps/desktop/artifacts/sha256-checksums.txt"
|
||||||
@ -263,7 +263,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Retrieve secrets
|
- name: Retrieve secrets
|
||||||
id: retrieve-secrets
|
id: retrieve-secrets
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
keyvault: "bitwarden-ci"
|
keyvault: "bitwarden-ci"
|
||||||
secrets: "snapcraft-store-token"
|
secrets: "snapcraft-store-token"
|
||||||
@ -279,7 +279,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Download Snap artifact
|
- name: Download Snap artifact
|
||||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||||
uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
workflow: build-desktop.yml
|
workflow: build-desktop.yml
|
||||||
workflow_conclusion: success
|
workflow_conclusion: success
|
||||||
@ -289,7 +289,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Dry Run - Download Snap artifact
|
- name: Dry Run - Download Snap artifact
|
||||||
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
||||||
uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
workflow: build-desktop.yml
|
workflow: build-desktop.yml
|
||||||
workflow_conclusion: success
|
workflow_conclusion: success
|
||||||
@ -329,7 +329,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Retrieve secrets
|
- name: Retrieve secrets
|
||||||
id: retrieve-secrets
|
id: retrieve-secrets
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
keyvault: "bitwarden-ci"
|
keyvault: "bitwarden-ci"
|
||||||
secrets: "cli-choco-api-key"
|
secrets: "cli-choco-api-key"
|
||||||
@ -347,7 +347,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Download choco artifact
|
- name: Download choco artifact
|
||||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||||
uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
workflow: build-desktop.yml
|
workflow: build-desktop.yml
|
||||||
workflow_conclusion: success
|
workflow_conclusion: success
|
||||||
@ -357,7 +357,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Dry Run - Download choco artifact
|
- name: Dry Run - Download choco artifact
|
||||||
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
||||||
uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
workflow: build-desktop.yml
|
workflow: build-desktop.yml
|
||||||
workflow_conclusion: success
|
workflow_conclusion: success
|
||||||
@ -368,5 +368,5 @@ jobs:
|
|||||||
- name: Push to Chocolatey
|
- name: Push to Chocolatey
|
||||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: choco push
|
run: choco push --source=https://push.chocolatey.org/
|
||||||
working-directory: apps/desktop/dist
|
working-directory: apps/desktop/dist
|
||||||
|
2
.github/workflows/release-qa-web.yml
vendored
2
.github/workflows/release-qa-web.yml
vendored
@ -23,7 +23,7 @@ jobs:
|
|||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
||||||
|
|
||||||
- name: Download latest cloud asset
|
- name: Download latest cloud asset
|
||||||
uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
workflow: build-web.yml
|
workflow: build-web.yml
|
||||||
path: apps/web
|
path: apps/web
|
||||||
|
14
.github/workflows/release-web.yml
vendored
14
.github/workflows/release-web.yml
vendored
@ -38,7 +38,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Check Release Version
|
- name: Check Release Version
|
||||||
id: version
|
id: version
|
||||||
uses: bitwarden/gh-actions/release-version-check@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/release-version-check@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
release-type: ${{ github.event.inputs.release_type }}
|
release-type: ${{ github.event.inputs.release_type }}
|
||||||
project-type: ts
|
project-type: ts
|
||||||
@ -70,7 +70,7 @@ jobs:
|
|||||||
########## DockerHub ##########
|
########## DockerHub ##########
|
||||||
- name: Setup DCT
|
- name: Setup DCT
|
||||||
id: setup-dct
|
id: setup-dct
|
||||||
uses: bitwarden/gh-actions/setup-docker-trust@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/setup-docker-trust@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
azure-creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
azure-creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
||||||
azure-keyvault-name: "bitwarden-ci"
|
azure-keyvault-name: "bitwarden-ci"
|
||||||
@ -156,7 +156,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Retrieve bot secrets
|
- name: Retrieve bot secrets
|
||||||
id: retrieve-bot-secrets
|
id: retrieve-bot-secrets
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
keyvault: bitwarden-ci
|
keyvault: bitwarden-ci
|
||||||
secrets: "github-pat-bitwarden-devops-bot-repo-scope"
|
secrets: "github-pat-bitwarden-devops-bot-repo-scope"
|
||||||
@ -170,7 +170,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Download latest cloud asset
|
- name: Download latest cloud asset
|
||||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||||
uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
workflow: build-web.yml
|
workflow: build-web.yml
|
||||||
path: assets
|
path: assets
|
||||||
@ -180,7 +180,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Dry Run - Download latest cloud asset
|
- name: Dry Run - Download latest cloud asset
|
||||||
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
||||||
uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
workflow: build-web.yml
|
workflow: build-web.yml
|
||||||
path: assets
|
path: assets
|
||||||
@ -253,7 +253,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Download latest build artifacts
|
- name: Download latest build artifacts
|
||||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||||
uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
workflow: build-web.yml
|
workflow: build-web.yml
|
||||||
path: apps/web/artifacts
|
path: apps/web/artifacts
|
||||||
@ -264,7 +264,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Dry Run - Download latest build artifacts
|
- name: Dry Run - Download latest build artifacts
|
||||||
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
||||||
uses: bitwarden/gh-actions/download-artifacts@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/download-artifacts@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
workflow: build-web.yml
|
workflow: build-web.yml
|
||||||
path: apps/web/artifacts
|
path: apps/web/artifacts
|
||||||
|
2
.github/workflows/staged-rollout-desktop.yml
vendored
2
.github/workflows/staged-rollout-desktop.yml
vendored
@ -26,7 +26,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Retrieve secrets
|
- name: Retrieve secrets
|
||||||
id: retrieve-secrets
|
id: retrieve-secrets
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
keyvault: "bitwarden-ci"
|
keyvault: "bitwarden-ci"
|
||||||
secrets: "aws-electron-access-id,
|
secrets: "aws-electron-access-id,
|
||||||
|
6
.github/workflows/version-bump.yml
vendored
6
.github/workflows/version-bump.yml
vendored
@ -49,7 +49,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Retrieve secrets
|
- name: Retrieve secrets
|
||||||
id: retrieve-secrets
|
id: retrieve-secrets
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/get-keyvault-secrets@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
keyvault: "bitwarden-ci"
|
keyvault: "bitwarden-ci"
|
||||||
secrets: "github-gpg-private-key, github-gpg-private-key-passphrase"
|
secrets: "github-gpg-private-key, github-gpg-private-key-passphrase"
|
||||||
@ -86,14 +86,14 @@ jobs:
|
|||||||
|
|
||||||
- name: Bump Browser Version - Manifest
|
- name: Bump Browser Version - Manifest
|
||||||
if: ${{ github.event.inputs.client == 'Browser' || github.event.inputs.client == 'All' }}
|
if: ${{ github.event.inputs.client == 'Browser' || github.event.inputs.client == 'All' }}
|
||||||
uses: bitwarden/gh-actions/version-bump@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/version-bump@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
version: ${{ github.event.inputs.version_number }}
|
version: ${{ github.event.inputs.version_number }}
|
||||||
file_path: "apps/browser/src/manifest.json"
|
file_path: "apps/browser/src/manifest.json"
|
||||||
|
|
||||||
- name: Bump Browser Version - Manifest v3
|
- name: Bump Browser Version - Manifest v3
|
||||||
if: ${{ github.event.inputs.client == 'Browser' || github.event.inputs.client == 'All' }}
|
if: ${{ github.event.inputs.client == 'Browser' || github.event.inputs.client == 'All' }}
|
||||||
uses: bitwarden/gh-actions/version-bump@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/version-bump@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
with:
|
with:
|
||||||
version: ${{ github.event.inputs.version_number }}
|
version: ${{ github.event.inputs.version_number }}
|
||||||
file_path: "apps/browser/src/manifest.v3.json"
|
file_path: "apps/browser/src/manifest.v3.json"
|
||||||
|
2
.github/workflows/workflow-linter.yml
vendored
2
.github/workflows/workflow-linter.yml
vendored
@ -8,4 +8,4 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
call-workflow:
|
call-workflow:
|
||||||
uses: bitwarden/gh-actions/.github/workflows/workflow-linter.yml@72594be690a4e7bfa87b1402b2aedc75acdbff12
|
uses: bitwarden/gh-actions/.github/workflows/workflow-linter.yml@37ffa14164a7308bc273829edfe75c97cd562375
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@bitwarden/browser",
|
"name": "@bitwarden/browser",
|
||||||
"version": "2023.5.0",
|
"version": "2023.5.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack",
|
"build": "webpack",
|
||||||
"build:mv3": "cross-env MANIFEST_VERSION=3 webpack",
|
"build:mv3": "cross-env MANIFEST_VERSION=3 webpack",
|
||||||
|
@ -46,6 +46,7 @@ export class AutofillTabCommand {
|
|||||||
onlyEmptyFields: false,
|
onlyEmptyFields: false,
|
||||||
onlyVisibleFields: false,
|
onlyVisibleFields: false,
|
||||||
fillNewPassword: true,
|
fillNewPassword: true,
|
||||||
|
allowTotpAutofill: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ export interface AutoFillOptions {
|
|||||||
fillNewPassword?: boolean;
|
fillNewPassword?: boolean;
|
||||||
skipLastUsed?: boolean;
|
skipLastUsed?: boolean;
|
||||||
allowUntrustedIframe?: boolean;
|
allowUntrustedIframe?: boolean;
|
||||||
|
allowTotpAutofill?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FormData {
|
export interface FormData {
|
||||||
|
@ -20,6 +20,17 @@ export class AutoFillConstants {
|
|||||||
"benutzer id",
|
"benutzer id",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
static readonly TotpFieldNames: string[] = [
|
||||||
|
"totp",
|
||||||
|
"2fa",
|
||||||
|
"mfa",
|
||||||
|
"totpcode",
|
||||||
|
"2facode",
|
||||||
|
"mfacode",
|
||||||
|
"twofactor",
|
||||||
|
"twofactorcode",
|
||||||
|
];
|
||||||
|
|
||||||
static readonly PasswordFieldIgnoreList: string[] = [
|
static readonly PasswordFieldIgnoreList: string[] = [
|
||||||
"onetimepassword",
|
"onetimepassword",
|
||||||
"captcha",
|
"captcha",
|
||||||
|
@ -32,6 +32,7 @@ export interface GenerateFillScriptOptions {
|
|||||||
onlyEmptyFields: boolean;
|
onlyEmptyFields: boolean;
|
||||||
onlyVisibleFields: boolean;
|
onlyVisibleFields: boolean;
|
||||||
fillNewPassword: boolean;
|
fillNewPassword: boolean;
|
||||||
|
allowTotpAutofill: boolean;
|
||||||
cipher: CipherView;
|
cipher: CipherView;
|
||||||
tabUrl: string;
|
tabUrl: string;
|
||||||
defaultUriMatch: UriMatchType;
|
defaultUriMatch: UriMatchType;
|
||||||
@ -127,17 +128,19 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
const defaultUriMatch = (await this.stateService.getDefaultUriMatch()) ?? UriMatchType.Domain;
|
const defaultUriMatch = (await this.stateService.getDefaultUriMatch()) ?? UriMatchType.Domain;
|
||||||
|
|
||||||
let didAutofill = false;
|
let didAutofill = false;
|
||||||
options.pageDetails.forEach((pd) => {
|
await Promise.all(
|
||||||
|
options.pageDetails.map(async (pd) => {
|
||||||
// make sure we're still on correct tab
|
// make sure we're still on correct tab
|
||||||
if (pd.tab.id !== tab.id || pd.tab.url !== tab.url) {
|
if (pd.tab.id !== tab.id || pd.tab.url !== tab.url) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fillScript = this.generateFillScript(pd.details, {
|
const fillScript = await this.generateFillScript(pd.details, {
|
||||||
skipUsernameOnlyFill: options.skipUsernameOnlyFill || false,
|
skipUsernameOnlyFill: options.skipUsernameOnlyFill || false,
|
||||||
onlyEmptyFields: options.onlyEmptyFields || false,
|
onlyEmptyFields: options.onlyEmptyFields || false,
|
||||||
onlyVisibleFields: options.onlyVisibleFields || false,
|
onlyVisibleFields: options.onlyVisibleFields || false,
|
||||||
fillNewPassword: options.fillNewPassword || false,
|
fillNewPassword: options.fillNewPassword || false,
|
||||||
|
allowTotpAutofill: options.allowTotpAutofill || false,
|
||||||
cipher: options.cipher,
|
cipher: options.cipher,
|
||||||
tabUrl: tab.url,
|
tabUrl: tab.url,
|
||||||
defaultUriMatch: defaultUriMatch,
|
defaultUriMatch: defaultUriMatch,
|
||||||
@ -189,7 +192,8 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
});
|
})
|
||||||
|
);
|
||||||
|
|
||||||
if (didAutofill) {
|
if (didAutofill) {
|
||||||
this.eventCollectionService.collect(EventType.Cipher_ClientAutofilled, options.cipher.id);
|
this.eventCollectionService.collect(EventType.Cipher_ClientAutofilled, options.cipher.id);
|
||||||
@ -244,6 +248,7 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
onlyVisibleFields: !fromCommand,
|
onlyVisibleFields: !fromCommand,
|
||||||
fillNewPassword: fromCommand,
|
fillNewPassword: fromCommand,
|
||||||
allowUntrustedIframe: fromCommand,
|
allowUntrustedIframe: fromCommand,
|
||||||
|
allowTotpAutofill: fromCommand,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Update last used index as autofill has succeed
|
// Update last used index as autofill has succeed
|
||||||
@ -280,10 +285,10 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
return tab;
|
return tab;
|
||||||
}
|
}
|
||||||
|
|
||||||
private generateFillScript(
|
private async generateFillScript(
|
||||||
pageDetails: AutofillPageDetails,
|
pageDetails: AutofillPageDetails,
|
||||||
options: GenerateFillScriptOptions
|
options: GenerateFillScriptOptions
|
||||||
): AutofillScript {
|
): Promise<AutofillScript> {
|
||||||
if (!pageDetails || !options.cipher) {
|
if (!pageDetails || !options.cipher) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -333,7 +338,12 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
|
|
||||||
switch (options.cipher.type) {
|
switch (options.cipher.type) {
|
||||||
case CipherType.Login:
|
case CipherType.Login:
|
||||||
fillScript = this.generateLoginFillScript(fillScript, pageDetails, filledFields, options);
|
fillScript = await this.generateLoginFillScript(
|
||||||
|
fillScript,
|
||||||
|
pageDetails,
|
||||||
|
filledFields,
|
||||||
|
options
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case CipherType.Card:
|
case CipherType.Card:
|
||||||
fillScript = this.generateCardFillScript(fillScript, pageDetails, filledFields, options);
|
fillScript = this.generateCardFillScript(fillScript, pageDetails, filledFields, options);
|
||||||
@ -353,20 +363,22 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
return fillScript;
|
return fillScript;
|
||||||
}
|
}
|
||||||
|
|
||||||
private generateLoginFillScript(
|
private async generateLoginFillScript(
|
||||||
fillScript: AutofillScript,
|
fillScript: AutofillScript,
|
||||||
pageDetails: AutofillPageDetails,
|
pageDetails: AutofillPageDetails,
|
||||||
filledFields: { [id: string]: AutofillField },
|
filledFields: { [id: string]: AutofillField },
|
||||||
options: GenerateFillScriptOptions
|
options: GenerateFillScriptOptions
|
||||||
): AutofillScript {
|
): Promise<AutofillScript> {
|
||||||
if (!options.cipher.login) {
|
if (!options.cipher.login) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const passwords: AutofillField[] = [];
|
const passwords: AutofillField[] = [];
|
||||||
const usernames: AutofillField[] = [];
|
const usernames: AutofillField[] = [];
|
||||||
|
const totps: AutofillField[] = [];
|
||||||
let pf: AutofillField = null;
|
let pf: AutofillField = null;
|
||||||
let username: AutofillField = null;
|
let username: AutofillField = null;
|
||||||
|
let totp: AutofillField = null;
|
||||||
const login = options.cipher.login;
|
const login = options.cipher.login;
|
||||||
fillScript.savedUrls =
|
fillScript.savedUrls =
|
||||||
login?.uris?.filter((u) => u.match != UriMatchType.Never).map((u) => u.uri) ?? [];
|
login?.uris?.filter((u) => u.match != UriMatchType.Never).map((u) => u.uri) ?? [];
|
||||||
@ -420,6 +432,19 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
usernames.push(username);
|
usernames.push(username);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.allowTotpAutofill && login.totp) {
|
||||||
|
totp = this.findTotpField(pageDetails, pf, false, false, false);
|
||||||
|
|
||||||
|
if (!totp && !options.onlyVisibleFields) {
|
||||||
|
// not able to find any viewable totp fields. maybe there are some "hidden" ones?
|
||||||
|
totp = this.findTotpField(pageDetails, pf, true, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totp) {
|
||||||
|
totps.push(totp);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,18 +467,42 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
usernames.push(username);
|
usernames.push(username);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.allowTotpAutofill && login.totp && pf.elementNumber > 0) {
|
||||||
|
totp = this.findTotpField(pageDetails, pf, false, false, true);
|
||||||
|
|
||||||
|
if (!totp && !options.onlyVisibleFields) {
|
||||||
|
// not able to find any viewable username fields. maybe there are some "hidden" ones?
|
||||||
|
totp = this.findTotpField(pageDetails, pf, true, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!passwordFields.length && !options.skipUsernameOnlyFill) {
|
if (totp) {
|
||||||
|
totps.push(totp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!passwordFields.length) {
|
||||||
// No password fields on this page. Let's try to just fuzzy fill the username.
|
// No password fields on this page. Let's try to just fuzzy fill the username.
|
||||||
pageDetails.fields.forEach((f) => {
|
pageDetails.fields.forEach((f) => {
|
||||||
if (
|
if (
|
||||||
|
!options.skipUsernameOnlyFill &&
|
||||||
f.viewable &&
|
f.viewable &&
|
||||||
(f.type === "text" || f.type === "email" || f.type === "tel") &&
|
(f.type === "text" || f.type === "email" || f.type === "tel") &&
|
||||||
AutofillService.fieldIsFuzzyMatch(f, AutoFillConstants.UsernameFieldNames)
|
AutofillService.fieldIsFuzzyMatch(f, AutoFillConstants.UsernameFieldNames)
|
||||||
) {
|
) {
|
||||||
usernames.push(f);
|
usernames.push(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
options.allowTotpAutofill &&
|
||||||
|
f.viewable &&
|
||||||
|
(f.type === "text" || f.type === "number") &&
|
||||||
|
(AutofillService.fieldIsFuzzyMatch(f, AutoFillConstants.TotpFieldNames) ||
|
||||||
|
f.autoCompleteType === "one-time-code")
|
||||||
|
) {
|
||||||
|
totps.push(f);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,6 +526,20 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
AutofillService.fillByOpid(fillScript, p, login.password);
|
AutofillService.fillByOpid(fillScript, p, login.password);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (options.allowTotpAutofill) {
|
||||||
|
await Promise.all(
|
||||||
|
totps.map(async (t) => {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(filledFields, t.opid)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
filledFields[t.opid] = t;
|
||||||
|
const totpValue = await this.totpService.getCode(login.totp);
|
||||||
|
AutofillService.fillByOpid(fillScript, t, totpValue);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fillScript = AutofillService.setFillScriptForFocus(filledFields, fillScript);
|
fillScript = AutofillService.setFillScriptForFocus(filledFields, fillScript);
|
||||||
return fillScript;
|
return fillScript;
|
||||||
}
|
}
|
||||||
@ -1258,6 +1321,42 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
return usernameField;
|
return usernameField;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private findTotpField(
|
||||||
|
pageDetails: AutofillPageDetails,
|
||||||
|
passwordField: AutofillField,
|
||||||
|
canBeHidden: boolean,
|
||||||
|
canBeReadOnly: boolean,
|
||||||
|
withoutForm: boolean
|
||||||
|
) {
|
||||||
|
let totpField: AutofillField = null;
|
||||||
|
for (let i = 0; i < pageDetails.fields.length; i++) {
|
||||||
|
const f = pageDetails.fields[i];
|
||||||
|
if (AutofillService.forCustomFieldsOnly(f)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!f.disabled &&
|
||||||
|
(canBeReadOnly || !f.readonly) &&
|
||||||
|
(withoutForm || f.form === passwordField.form) &&
|
||||||
|
(canBeHidden || f.viewable) &&
|
||||||
|
(f.type === "text" || f.type === "number")
|
||||||
|
) {
|
||||||
|
totpField = f;
|
||||||
|
|
||||||
|
if (
|
||||||
|
this.findMatchingFieldIndex(f, AutoFillConstants.TotpFieldNames) > -1 ||
|
||||||
|
f.autoCompleteType === "one-time-code"
|
||||||
|
) {
|
||||||
|
// We found an exact match. No need to keep looking.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return totpField;
|
||||||
|
}
|
||||||
|
|
||||||
private findMatchingFieldIndex(field: AutofillField, names: string[]): number {
|
private findMatchingFieldIndex(field: AutofillField, names: string[]): number {
|
||||||
for (let i = 0; i < names.length; i++) {
|
for (let i = 0; i < names.length; i++) {
|
||||||
if (names[i].indexOf("=") > -1) {
|
if (names[i].indexOf("=") > -1) {
|
||||||
@ -1267,6 +1366,12 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
if (this.fieldPropertyIsPrefixMatch(field, "htmlName", names[i], "name")) {
|
if (this.fieldPropertyIsPrefixMatch(field, "htmlName", names[i], "name")) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
if (this.fieldPropertyIsPrefixMatch(field, "label-left", names[i], "label")) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
if (this.fieldPropertyIsPrefixMatch(field, "label-right", names[i], "label")) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
if (this.fieldPropertyIsPrefixMatch(field, "label-tag", names[i], "label")) {
|
if (this.fieldPropertyIsPrefixMatch(field, "label-tag", names[i], "label")) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@ -1284,6 +1389,12 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
if (this.fieldPropertyIsMatch(field, "htmlName", names[i])) {
|
if (this.fieldPropertyIsMatch(field, "htmlName", names[i])) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
if (this.fieldPropertyIsMatch(field, "label-left", names[i])) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
if (this.fieldPropertyIsMatch(field, "label-right", names[i])) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
if (this.fieldPropertyIsMatch(field, "label-tag", names[i])) {
|
if (this.fieldPropertyIsMatch(field, "label-tag", names[i])) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -224,6 +224,7 @@ export default class RuntimeBackground {
|
|||||||
cipher: this.main.loginToAutoFill,
|
cipher: this.main.loginToAutoFill,
|
||||||
pageDetails: this.pageDetailsToAutoFill,
|
pageDetails: this.pageDetailsToAutoFill,
|
||||||
fillNewPassword: true,
|
fillNewPassword: true,
|
||||||
|
allowTotpAutofill: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (totpCode != null) {
|
if (totpCode != null) {
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"name": "__MSG_extName__",
|
"name": "__MSG_extName__",
|
||||||
"short_name": "__MSG_appName__",
|
"short_name": "__MSG_appName__",
|
||||||
"version": "2023.5.0",
|
"version": "2023.5.1",
|
||||||
"description": "__MSG_extDesc__",
|
"description": "__MSG_extDesc__",
|
||||||
"default_locale": "en",
|
"default_locale": "en",
|
||||||
"author": "Bitwarden Inc.",
|
"author": "Bitwarden Inc.",
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"minimum_chrome_version": "102.0",
|
"minimum_chrome_version": "102.0",
|
||||||
"name": "__MSG_extName__",
|
"name": "__MSG_extName__",
|
||||||
"short_name": "__MSG_appName__",
|
"short_name": "__MSG_appName__",
|
||||||
"version": "2023.5.0",
|
"version": "2023.5.1",
|
||||||
"description": "__MSG_extDesc__",
|
"description": "__MSG_extDesc__",
|
||||||
"default_locale": "en",
|
"default_locale": "en",
|
||||||
"author": "Bitwarden Inc.",
|
"author": "Bitwarden Inc.",
|
||||||
|
@ -180,6 +180,7 @@ export class CurrentTabComponent implements OnInit, OnDestroy {
|
|||||||
pageDetails: this.pageDetails,
|
pageDetails: this.pageDetails,
|
||||||
doc: window.document,
|
doc: window.document,
|
||||||
fillNewPassword: true,
|
fillNewPassword: true,
|
||||||
|
allowTotpAutofill: true,
|
||||||
});
|
});
|
||||||
if (this.totpCode != null) {
|
if (this.totpCode != null) {
|
||||||
this.platformUtilsService.copyToClipboard(this.totpCode, { window: window });
|
this.platformUtilsService.copyToClipboard(this.totpCode, { window: window });
|
||||||
|
@ -288,6 +288,7 @@ export class ViewComponent extends BaseViewComponent {
|
|||||||
pageDetails: this.pageDetails,
|
pageDetails: this.pageDetails,
|
||||||
doc: window.document,
|
doc: window.document,
|
||||||
fillNewPassword: true,
|
fillNewPassword: true,
|
||||||
|
allowTotpAutofill: true,
|
||||||
});
|
});
|
||||||
if (this.totpCode != null) {
|
if (this.totpCode != null) {
|
||||||
this.platformUtilsService.copyToClipboard(this.totpCode, { window: window });
|
this.platformUtilsService.copyToClipboard(this.totpCode, { window: window });
|
||||||
|
@ -245,6 +245,10 @@ export class ServeCommand {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("/unlock", async (ctx, next) => {
|
router.post("/unlock", async (ctx, next) => {
|
||||||
|
// Do not allow guessing password location through serve command
|
||||||
|
delete ctx.request.query.passwordFile;
|
||||||
|
delete ctx.request.query.passwordEnv;
|
||||||
|
|
||||||
const response = await this.unlockCommand.run(
|
const response = await this.unlockCommand.run(
|
||||||
ctx.request.body.password == null ? null : (ctx.request.body.password as string),
|
ctx.request.body.password == null ? null : (ctx.request.body.password as string),
|
||||||
ctx.request.query
|
ctx.request.query
|
||||||
|
@ -6,13 +6,13 @@
|
|||||||
"message": "Filtriloj"
|
"message": "Filtriloj"
|
||||||
},
|
},
|
||||||
"allItems": {
|
"allItems": {
|
||||||
"message": "All items"
|
"message": "Ĉiuj Eroj"
|
||||||
},
|
},
|
||||||
"favorites": {
|
"favorites": {
|
||||||
"message": "Favorites"
|
"message": "Plej ŝatataj"
|
||||||
},
|
},
|
||||||
"types": {
|
"types": {
|
||||||
"message": "Types"
|
"message": "Tipoj"
|
||||||
},
|
},
|
||||||
"typeLogin": {
|
"typeLogin": {
|
||||||
"message": "Saluto"
|
"message": "Saluto"
|
||||||
@ -21,7 +21,7 @@
|
|||||||
"message": "Karto"
|
"message": "Karto"
|
||||||
},
|
},
|
||||||
"typeIdentity": {
|
"typeIdentity": {
|
||||||
"message": "Identity"
|
"message": "Idento"
|
||||||
},
|
},
|
||||||
"typeSecureNote": {
|
"typeSecureNote": {
|
||||||
"message": "Sekura noto"
|
"message": "Sekura noto"
|
||||||
@ -30,10 +30,10 @@
|
|||||||
"message": "Dosierujoj"
|
"message": "Dosierujoj"
|
||||||
},
|
},
|
||||||
"collections": {
|
"collections": {
|
||||||
"message": "Collections"
|
"message": "Kolektoj"
|
||||||
},
|
},
|
||||||
"searchVault": {
|
"searchVault": {
|
||||||
"message": "Search vault"
|
"message": "Traserĉu trezorejon"
|
||||||
},
|
},
|
||||||
"addItem": {
|
"addItem": {
|
||||||
"message": "Aldoni elementon"
|
"message": "Aldoni elementon"
|
||||||
@ -45,10 +45,10 @@
|
|||||||
"message": "Kundividi"
|
"message": "Kundividi"
|
||||||
},
|
},
|
||||||
"moveToOrganization": {
|
"moveToOrganization": {
|
||||||
"message": "Move to organization"
|
"message": "Movu al organizo"
|
||||||
},
|
},
|
||||||
"movedItemToOrg": {
|
"movedItemToOrg": {
|
||||||
"message": "$ITEMNAME$ moved to $ORGNAME$",
|
"message": "$ITEMNAME$ moviĝis al $ORGNAME$",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"itemname": {
|
"itemname": {
|
||||||
"content": "$1",
|
"content": "$1",
|
||||||
@ -61,7 +61,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"moveToOrgDesc": {
|
"moveToOrgDesc": {
|
||||||
"message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved."
|
"message": "Elektu organizon kun kiu vi volas dividi ĉi tiun eron. Dividado transdonas posedon de la ero al la organizo. Vi ne plu estos la rekta posedanto de ĉi tiu ero post kiam ĝi estos dividita."
|
||||||
},
|
},
|
||||||
"attachments": {
|
"attachments": {
|
||||||
"message": "Aldonaĵoj"
|
"message": "Aldonaĵoj"
|
||||||
@ -104,10 +104,10 @@
|
|||||||
"message": "Retpoŝta adreso"
|
"message": "Retpoŝta adreso"
|
||||||
},
|
},
|
||||||
"verificationCodeTotp": {
|
"verificationCodeTotp": {
|
||||||
"message": "Verification code (TOTP)"
|
"message": "Kontrola kodo (TOTP)"
|
||||||
},
|
},
|
||||||
"website": {
|
"website": {
|
||||||
"message": "Website"
|
"message": "Retejo"
|
||||||
},
|
},
|
||||||
"notes": {
|
"notes": {
|
||||||
"message": "Notoj"
|
"message": "Notoj"
|
||||||
@ -116,10 +116,10 @@
|
|||||||
"message": "Propraj kampoj"
|
"message": "Propraj kampoj"
|
||||||
},
|
},
|
||||||
"launch": {
|
"launch": {
|
||||||
"message": "Launch"
|
"message": "Lanĉo"
|
||||||
},
|
},
|
||||||
"copyValue": {
|
"copyValue": {
|
||||||
"message": "Copy value",
|
"message": "Kopii valoron",
|
||||||
"description": "Copy value to clipboard"
|
"description": "Copy value to clipboard"
|
||||||
},
|
},
|
||||||
"minimizeOnCopyToClipboard": {
|
"minimizeOnCopyToClipboard": {
|
||||||
|
@ -962,7 +962,7 @@
|
|||||||
"message": "Käynnistä automaattisesti kirjauduttaessa"
|
"message": "Käynnistä automaattisesti kirjauduttaessa"
|
||||||
},
|
},
|
||||||
"openAtLoginDesc": {
|
"openAtLoginDesc": {
|
||||||
"message": "Käynnistä sovellus automaattisesti kirjautumisen yhteydessä."
|
"message": "Käynnistä Bitwarden-sovellus automaattisesti kirjautumisen yhteydessä."
|
||||||
},
|
},
|
||||||
"alwaysShowDock": {
|
"alwaysShowDock": {
|
||||||
"message": "Näytä aina Dockissa"
|
"message": "Näytä aina Dockissa"
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"urls": {
|
"urls": {
|
||||||
"icons": "https://icons.bitwarden.net",
|
"icons": "https://icons.bitwarden.net",
|
||||||
"notifications": "https://notifications.bitwarden.net",
|
"notifications": "https://notifications.beta.bitwarden.net",
|
||||||
"scim": "https://scim.bitwarden.net"
|
"scim": "https://scim.beta.bitwarden.net"
|
||||||
},
|
},
|
||||||
"flags": {
|
"flags": {
|
||||||
"secretsManager": true,
|
"secretsManager": true,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@bitwarden/web-vault",
|
"name": "@bitwarden/web-vault",
|
||||||
"version": "2023.5.0",
|
"version": "2023.5.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:oss": "webpack",
|
"build:oss": "webpack",
|
||||||
"build:bit": "webpack -c ../../bitwarden_license/bit-web/webpack.config.js",
|
"build:bit": "webpack -c ../../bitwarden_license/bit-web/webpack.config.js",
|
||||||
|
@ -35,6 +35,7 @@ import {
|
|||||||
} from "../../../shared/components/access-selector";
|
} from "../../../shared/components/access-selector";
|
||||||
|
|
||||||
import { commaSeparatedEmails } from "./validators/comma-separated-emails.validator";
|
import { commaSeparatedEmails } from "./validators/comma-separated-emails.validator";
|
||||||
|
import { freeOrgSeatLimitReachedValidator } from "./validators/free-org-inv-limit-reached.validator";
|
||||||
|
|
||||||
export enum MemberDialogTab {
|
export enum MemberDialogTab {
|
||||||
Role = 0,
|
Role = 0,
|
||||||
@ -46,6 +47,7 @@ export interface MemberDialogParams {
|
|||||||
name: string;
|
name: string;
|
||||||
organizationId: string;
|
organizationId: string;
|
||||||
organizationUserId: string;
|
organizationUserId: string;
|
||||||
|
allOrganizationUserEmails: string[];
|
||||||
usesKeyConnector: boolean;
|
usesKeyConnector: boolean;
|
||||||
initialTab?: MemberDialogTab;
|
initialTab?: MemberDialogTab;
|
||||||
}
|
}
|
||||||
@ -79,7 +81,7 @@ export class MemberDialogComponent implements OnInit, OnDestroy {
|
|||||||
protected groupAccessItems: AccessItemView[] = [];
|
protected groupAccessItems: AccessItemView[] = [];
|
||||||
protected tabIndex: MemberDialogTab;
|
protected tabIndex: MemberDialogTab;
|
||||||
protected formGroup = this.formBuilder.group({
|
protected formGroup = this.formBuilder.group({
|
||||||
emails: ["", [Validators.required, commaSeparatedEmails]],
|
emails: ["", { updateOn: "blur" }],
|
||||||
type: OrganizationUserType.User,
|
type: OrganizationUserType.User,
|
||||||
externalId: this.formBuilder.control({ value: "", disabled: true }),
|
externalId: this.formBuilder.control({ value: "", disabled: true }),
|
||||||
accessAllCollections: false,
|
accessAllCollections: false,
|
||||||
@ -167,6 +169,20 @@ export class MemberDialogComponent implements OnInit, OnDestroy {
|
|||||||
this.canUseCustomPermissions = organization.useCustomPermissions;
|
this.canUseCustomPermissions = organization.useCustomPermissions;
|
||||||
this.canUseSecretsManager = organization.useSecretsManager && flagEnabled("secretsManager");
|
this.canUseSecretsManager = organization.useSecretsManager && flagEnabled("secretsManager");
|
||||||
|
|
||||||
|
const emailsControlValidators = [
|
||||||
|
Validators.required,
|
||||||
|
commaSeparatedEmails,
|
||||||
|
freeOrgSeatLimitReachedValidator(
|
||||||
|
this.organization,
|
||||||
|
this.params.allOrganizationUserEmails,
|
||||||
|
this.i18nService.t("subscriptionFreePlan", organization.seats)
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
const emailsControl = this.formGroup.get("emails");
|
||||||
|
emailsControl.setValidators(emailsControlValidators);
|
||||||
|
emailsControl.updateValueAndValidity();
|
||||||
|
|
||||||
this.collectionAccessItems = [].concat(
|
this.collectionAccessItems = [].concat(
|
||||||
collections.map((c) => mapCollectionToAccessItemView(c))
|
collections.map((c) => mapCollectionToAccessItemView(c))
|
||||||
);
|
);
|
||||||
|
@ -0,0 +1,106 @@
|
|||||||
|
import { AbstractControl, FormControl, ValidationErrors } from "@angular/forms";
|
||||||
|
|
||||||
|
import { OrganizationUserType } from "@bitwarden/common/admin-console/enums";
|
||||||
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
|
import { ProductType } from "@bitwarden/common/enums";
|
||||||
|
|
||||||
|
import { freeOrgSeatLimitReachedValidator } from "./free-org-inv-limit-reached.validator";
|
||||||
|
|
||||||
|
const orgFactory = (props: Partial<Organization> = {}) =>
|
||||||
|
Object.assign(
|
||||||
|
new Organization(),
|
||||||
|
{
|
||||||
|
id: "myOrgId",
|
||||||
|
enabled: true,
|
||||||
|
type: OrganizationUserType.Admin,
|
||||||
|
},
|
||||||
|
props
|
||||||
|
);
|
||||||
|
|
||||||
|
describe("freeOrgSeatLimitReachedValidator", () => {
|
||||||
|
let organization: Organization;
|
||||||
|
let allOrganizationUserEmails: string[];
|
||||||
|
let validatorFn: (control: AbstractControl) => ValidationErrors | null;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
allOrganizationUserEmails = ["user1@example.com"];
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return null when control value is empty", () => {
|
||||||
|
validatorFn = freeOrgSeatLimitReachedValidator(
|
||||||
|
organization,
|
||||||
|
allOrganizationUserEmails,
|
||||||
|
"You cannot invite more than 2 members without upgrading your plan."
|
||||||
|
);
|
||||||
|
const control = new FormControl("");
|
||||||
|
|
||||||
|
const result = validatorFn(control);
|
||||||
|
|
||||||
|
expect(result).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return null when control value is null", () => {
|
||||||
|
validatorFn = freeOrgSeatLimitReachedValidator(
|
||||||
|
organization,
|
||||||
|
allOrganizationUserEmails,
|
||||||
|
"You cannot invite more than 2 members without upgrading your plan."
|
||||||
|
);
|
||||||
|
const control = new FormControl(null);
|
||||||
|
|
||||||
|
const result = validatorFn(control);
|
||||||
|
|
||||||
|
expect(result).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return null when max seats are not exceeded on free plan", () => {
|
||||||
|
organization = orgFactory({
|
||||||
|
planProductType: ProductType.Free,
|
||||||
|
seats: 2,
|
||||||
|
});
|
||||||
|
validatorFn = freeOrgSeatLimitReachedValidator(
|
||||||
|
organization,
|
||||||
|
allOrganizationUserEmails,
|
||||||
|
"You cannot invite more than 2 members without upgrading your plan."
|
||||||
|
);
|
||||||
|
const control = new FormControl("user2@example.com");
|
||||||
|
|
||||||
|
const result = validatorFn(control);
|
||||||
|
|
||||||
|
expect(result).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return validation error when max seats are exceeded on free plan", () => {
|
||||||
|
organization = orgFactory({
|
||||||
|
planProductType: ProductType.Free,
|
||||||
|
seats: 2,
|
||||||
|
});
|
||||||
|
const errorMessage = "You cannot invite more than 2 members without upgrading your plan.";
|
||||||
|
validatorFn = freeOrgSeatLimitReachedValidator(
|
||||||
|
organization,
|
||||||
|
allOrganizationUserEmails,
|
||||||
|
"You cannot invite more than 2 members without upgrading your plan."
|
||||||
|
);
|
||||||
|
const control = new FormControl("user2@example.com,user3@example.com");
|
||||||
|
|
||||||
|
const result = validatorFn(control);
|
||||||
|
|
||||||
|
expect(result).toStrictEqual({ freePlanLimitReached: { message: errorMessage } });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return null when not on free plan", () => {
|
||||||
|
const control = new FormControl("user2@example.com,user3@example.com");
|
||||||
|
organization = orgFactory({
|
||||||
|
planProductType: ProductType.Enterprise,
|
||||||
|
seats: 100,
|
||||||
|
});
|
||||||
|
validatorFn = freeOrgSeatLimitReachedValidator(
|
||||||
|
organization,
|
||||||
|
allOrganizationUserEmails,
|
||||||
|
"You cannot invite more than 2 members without upgrading your plan."
|
||||||
|
);
|
||||||
|
|
||||||
|
const result = validatorFn(control);
|
||||||
|
|
||||||
|
expect(result).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,36 @@
|
|||||||
|
import { AbstractControl, ValidationErrors, ValidatorFn } from "@angular/forms";
|
||||||
|
|
||||||
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
|
import { ProductType } from "@bitwarden/common/enums";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the limit of free organization seats has been reached when adding new users
|
||||||
|
* @param organization An object representing the organization
|
||||||
|
* @param allOrganizationUserEmails An array of strings with existing user email addresses
|
||||||
|
* @param errorMessage A localized string to display if validation fails
|
||||||
|
* @returns A function that validates an `AbstractControl` and returns `ValidationErrors` or `null`
|
||||||
|
*/
|
||||||
|
export function freeOrgSeatLimitReachedValidator(
|
||||||
|
organization: Organization,
|
||||||
|
allOrganizationUserEmails: string[],
|
||||||
|
errorMessage: string
|
||||||
|
): ValidatorFn {
|
||||||
|
return (control: AbstractControl): ValidationErrors | null => {
|
||||||
|
if (control.value === "" || !control.value) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newEmailsToAdd = control.value
|
||||||
|
.split(",")
|
||||||
|
.filter(
|
||||||
|
(newEmailToAdd: string) =>
|
||||||
|
newEmailToAdd &&
|
||||||
|
!allOrganizationUserEmails.some((existingEmail) => existingEmail === newEmailToAdd)
|
||||||
|
);
|
||||||
|
|
||||||
|
return organization.planProductType === ProductType.Free &&
|
||||||
|
allOrganizationUserEmails.length + newEmailsToAdd.length > organization.seats
|
||||||
|
? { freePlanLimitReached: { message: errorMessage } }
|
||||||
|
: null;
|
||||||
|
};
|
||||||
|
}
|
@ -396,6 +396,7 @@ export class PeopleComponent
|
|||||||
name: this.userNamePipe.transform(user),
|
name: this.userNamePipe.transform(user),
|
||||||
organizationId: this.organization.id,
|
organizationId: this.organization.id,
|
||||||
organizationUserId: user != null ? user.id : null,
|
organizationUserId: user != null ? user.id : null,
|
||||||
|
allOrganizationUserEmails: this.allUsers?.map((user) => user.email) ?? [],
|
||||||
usesKeyConnector: user?.usesKeyConnector,
|
usesKeyConnector: user?.usesKeyConnector,
|
||||||
initialTab: initialTab,
|
initialTab: initialTab,
|
||||||
},
|
},
|
||||||
|
@ -38,11 +38,15 @@ export class InitService {
|
|||||||
|
|
||||||
init() {
|
init() {
|
||||||
return async () => {
|
return async () => {
|
||||||
|
// Workaround to ignore stateService.activeAccount until process.env.URLS are set
|
||||||
|
// TODO: Remove this when implementing ticket PM-2637
|
||||||
|
this.environmentService.initialized = false;
|
||||||
await this.stateService.init();
|
await this.stateService.init();
|
||||||
|
|
||||||
const urls = process.env.URLS as Urls;
|
const urls = process.env.URLS as Urls;
|
||||||
urls.base ??= this.win.location.origin;
|
urls.base ??= this.win.location.origin;
|
||||||
this.environmentService.setUrls(urls);
|
this.environmentService.setUrls(urls);
|
||||||
|
this.environmentService.initialized = true;
|
||||||
|
|
||||||
setTimeout(() => this.notificationsService.init(), 3000);
|
setTimeout(() => this.notificationsService.init(), 3000);
|
||||||
(this.vaultTimeoutService as VaultTimeoutService).init(true);
|
(this.vaultTimeoutService as VaultTimeoutService).init(true);
|
||||||
|
@ -38,7 +38,6 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction
|
|||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||||
import { DEFAULT_PBKDF2_ITERATIONS, EventType, KdfType } from "@bitwarden/common/enums";
|
import { DEFAULT_PBKDF2_ITERATIONS, EventType, KdfType } from "@bitwarden/common/enums";
|
||||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
|
||||||
import { ServiceUtils } from "@bitwarden/common/misc/serviceUtils";
|
import { ServiceUtils } from "@bitwarden/common/misc/serviceUtils";
|
||||||
import { TreeNode } from "@bitwarden/common/models/domain/tree-node";
|
import { TreeNode } from "@bitwarden/common/models/domain/tree-node";
|
||||||
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
||||||
@ -857,19 +856,11 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async isLowKdfIteration() {
|
async isLowKdfIteration() {
|
||||||
const showLowKdfEnabled = await this.configService.getFeatureFlagBool(
|
|
||||||
FeatureFlag.DisplayLowKdfIterationWarningFlag
|
|
||||||
);
|
|
||||||
|
|
||||||
if (showLowKdfEnabled) {
|
|
||||||
const kdfType = await this.stateService.getKdfType();
|
const kdfType = await this.stateService.getKdfType();
|
||||||
const kdfOptions = await this.stateService.getKdfConfig();
|
const kdfOptions = await this.stateService.getKdfConfig();
|
||||||
return kdfType === KdfType.PBKDF2_SHA256 && kdfOptions.iterations < DEFAULT_PBKDF2_ITERATIONS;
|
return kdfType === KdfType.PBKDF2_SHA256 && kdfOptions.iterations < DEFAULT_PBKDF2_ITERATIONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
return showLowKdfEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async repromptCipher(ciphers: CipherView[]) {
|
protected async repromptCipher(ciphers: CipherView[]) {
|
||||||
const notProtected = !ciphers.find((cipher) => cipher.reprompt !== CipherRepromptType.None);
|
const notProtected = !ciphers.find((cipher) => cipher.reprompt !== CipherRepromptType.None);
|
||||||
|
|
||||||
|
@ -658,7 +658,7 @@
|
|||||||
"message": "Hovedadgangskoden er den adgangskode, du bruger, når du tilgår din boks. Det er meget vigtigt, at hovedadgangskoden ikke glemmes, da der ikke er nogen måde, hvorpå den kan genoprettes."
|
"message": "Hovedadgangskoden er den adgangskode, du bruger, når du tilgår din boks. Det er meget vigtigt, at hovedadgangskoden ikke glemmes, da der ikke er nogen måde, hvorpå den kan genoprettes."
|
||||||
},
|
},
|
||||||
"masterPassImportant": {
|
"masterPassImportant": {
|
||||||
"message": "Hovedadgangskoder kan ikke gendannes, hvis du glemmer dem!"
|
"message": "Hovedadgangskoden kan ikke gendannes, hvis den glemmes!"
|
||||||
},
|
},
|
||||||
"masterPassHintDesc": {
|
"masterPassHintDesc": {
|
||||||
"message": "Et hovedadgangskodetip kan bidrage til at komme i tanke om adgangskoden, hvis den glemmes."
|
"message": "Et hovedadgangskodetip kan bidrage til at komme i tanke om adgangskoden, hvis den glemmes."
|
||||||
@ -5231,7 +5231,7 @@
|
|||||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Connect login with SSO to your self-hosted decryption key server. Using this option, members won’t need to use their master passwords to decrypt vault data. The require SSO authentication and single organization policies are required to set up Key Connector decryption. Contact Bitwarden Support for set up assistance.'"
|
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Connect login with SSO to your self-hosted decryption key server. Using this option, members won’t need to use their master passwords to decrypt vault data. The require SSO authentication and single organization policies are required to set up Key Connector decryption. Contact Bitwarden Support for set up assistance.'"
|
||||||
},
|
},
|
||||||
"memberDecryptionKeyConnectorDescLink": {
|
"memberDecryptionKeyConnectorDescLink": {
|
||||||
"message": "require SSO authentication and single organization policies",
|
"message": "kræver SSO-godkendelse samt enkeltorganisationspolitikker",
|
||||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Connect login with SSO to your self-hosted decryption key server. Using this option, members won’t need to use their master passwords to decrypt vault data. The require SSO authentication and single organization policies are required to set up Key Connector decryption. Contact Bitwarden Support for set up assistance.'"
|
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Connect login with SSO to your self-hosted decryption key server. Using this option, members won’t need to use their master passwords to decrypt vault data. The require SSO authentication and single organization policies are required to set up Key Connector decryption. Contact Bitwarden Support for set up assistance.'"
|
||||||
},
|
},
|
||||||
"memberDecryptionKeyConnectorDescEnd": {
|
"memberDecryptionKeyConnectorDescEnd": {
|
||||||
|
@ -6553,7 +6553,7 @@
|
|||||||
"message": "Laskutuksen synkronoinnin ohje"
|
"message": "Laskutuksen synkronoinnin ohje"
|
||||||
},
|
},
|
||||||
"licensePaidFeaturesHelp": {
|
"licensePaidFeaturesHelp": {
|
||||||
"message": "Maksullisen lisenssin oiminaisuusopas"
|
"message": "Maksullisen lisenssin ominaisuusopas"
|
||||||
},
|
},
|
||||||
"selfHostGracePeriodHelp": {
|
"selfHostGracePeriodHelp": {
|
||||||
"message": "Kun tilauksesi päättyy, sinulla on 60 päivää aikaa päivittää organisaatiosi lisenssitiedosto ajan tasalle. Varoaika päättyy $GRACE_PERIOD_END_DATE$.",
|
"message": "Kun tilauksesi päättyy, sinulla on 60 päivää aikaa päivittää organisaatiosi lisenssitiedosto ajan tasalle. Varoaika päättyy $GRACE_PERIOD_END_DATE$.",
|
||||||
@ -6830,7 +6830,7 @@
|
|||||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The master password reset policy with automatic enrollment will turn on when this option is used.'"
|
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'Once authenticated, members will decrypt vault data using a key stored on their device. The master password reset policy with automatic enrollment will turn on when this option is used.'"
|
||||||
},
|
},
|
||||||
"notFound": {
|
"notFound": {
|
||||||
"message": "$RESOURCE$ ei löytynyt",
|
"message": "Resurssia $RESOURCE$ ei löytynyt",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"resource": {
|
"resource": {
|
||||||
"content": "$1",
|
"content": "$1",
|
||||||
|
@ -574,7 +574,7 @@
|
|||||||
"message": "Êtes-vous sûr de vouloir écraser le mot de passe actuel ?"
|
"message": "Êtes-vous sûr de vouloir écraser le mot de passe actuel ?"
|
||||||
},
|
},
|
||||||
"editedFolder": {
|
"editedFolder": {
|
||||||
"message": "Dossier modifié"
|
"message": "Dossier enregistré"
|
||||||
},
|
},
|
||||||
"addedFolder": {
|
"addedFolder": {
|
||||||
"message": "Dossier ajouté"
|
"message": "Dossier ajouté"
|
||||||
@ -634,7 +634,7 @@
|
|||||||
"message": "Commencer la Période d'Essai"
|
"message": "Commencer la Période d'Essai"
|
||||||
},
|
},
|
||||||
"logIn": {
|
"logIn": {
|
||||||
"message": "S'identifier"
|
"message": "Se connecter"
|
||||||
},
|
},
|
||||||
"logInInitiated": {
|
"logInInitiated": {
|
||||||
"message": "Connexion initiée"
|
"message": "Connexion initiée"
|
||||||
@ -676,7 +676,7 @@
|
|||||||
"message": "Paramètres"
|
"message": "Paramètres"
|
||||||
},
|
},
|
||||||
"passwordHint": {
|
"passwordHint": {
|
||||||
"message": "Indice du mot de passe"
|
"message": "Indice de mot de passe"
|
||||||
},
|
},
|
||||||
"enterEmailToGetHint": {
|
"enterEmailToGetHint": {
|
||||||
"message": "Saisissez l'adresse électronique de votre compte pour recevoir l'indice de votre mot de passe principal."
|
"message": "Saisissez l'adresse électronique de votre compte pour recevoir l'indice de votre mot de passe principal."
|
||||||
@ -6900,6 +6900,6 @@
|
|||||||
"message": "Aucun mot de passe principal"
|
"message": "Aucun mot de passe principal"
|
||||||
},
|
},
|
||||||
"removeMembersWithoutMasterPasswordWarning": {
|
"removeMembersWithoutMasterPasswordWarning": {
|
||||||
"message": "La suppression des membres qui n'ont pas de mot de passe principal sans leur en définir un, peut restreindre l'accès à leur compte dans soin intégralité."
|
"message": "La suppression des membres qui n'ont pas de mot de passe principal sans leur en définir un, peut restreindre l'accès à leur compte dans son intégralité."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6849,7 +6849,7 @@
|
|||||||
"description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their organization's public key with another user, for the purposes of sharing."
|
"description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their organization's public key with another user, for the purposes of sharing."
|
||||||
},
|
},
|
||||||
"deviceApprovals": {
|
"deviceApprovals": {
|
||||||
"message": "Approvazioni dispositivi"
|
"message": "Approva dispositivi"
|
||||||
},
|
},
|
||||||
"deviceApprovalsDesc": {
|
"deviceApprovalsDesc": {
|
||||||
"message": "Approva le richieste di accesso qui sotto per consentire ai membri di completare l'accesso. Le richieste non approvate scadono dopo 1 settimana. Verifica le informazioni del membro prima di approvare."
|
"message": "Approva le richieste di accesso qui sotto per consentire ai membri di completare l'accesso. Le richieste non approvate scadono dopo 1 settimana. Verifica le informazioni del membro prima di approvare."
|
||||||
@ -6870,7 +6870,7 @@
|
|||||||
"message": "Approva richiesta"
|
"message": "Approva richiesta"
|
||||||
},
|
},
|
||||||
"noDeviceRequests": {
|
"noDeviceRequests": {
|
||||||
"message": "Nessuna richiesta dispositivo"
|
"message": "Nessuna richiesta da approvare"
|
||||||
},
|
},
|
||||||
"noDeviceRequestsDesc": {
|
"noDeviceRequestsDesc": {
|
||||||
"message": "Le richieste di approvazione dei dispositivi dei membri appariranno qui"
|
"message": "Le richieste di approvazione dei dispositivi dei membri appariranno qui"
|
||||||
|
@ -1001,7 +1001,7 @@
|
|||||||
"message": "Confirmar a palavra-passe do ficheiro"
|
"message": "Confirmar a palavra-passe do ficheiro"
|
||||||
},
|
},
|
||||||
"accountRestrictedOptionDescription": {
|
"accountRestrictedOptionDescription": {
|
||||||
"message": "Use your account encryption key, derived from your account's username and Master Password, to encrypt the export and restrict import to only the current Bitwarden account."
|
"message": "Utilize a chave de encriptação da sua conta, derivada do nome de utilizador e da palavra-passe mestra da sua conta, para encriptar a exportação e restringir a importação apenas à conta Bitwarden atual."
|
||||||
},
|
},
|
||||||
"passwordProtectedOptionDescription": {
|
"passwordProtectedOptionDescription": {
|
||||||
"message": "Defina uma palavra-passe do ficheiro para encriptar a exportação e importe-a para qualquer conta Bitwarden utilizando a palavra-passe de desencriptação."
|
"message": "Defina uma palavra-passe do ficheiro para encriptar a exportação e importe-a para qualquer conta Bitwarden utilizando a palavra-passe de desencriptação."
|
||||||
@ -1256,7 +1256,7 @@
|
|||||||
"message": "Dados importados com sucesso"
|
"message": "Dados importados com sucesso"
|
||||||
},
|
},
|
||||||
"importSuccessNumberOfItems": {
|
"importSuccessNumberOfItems": {
|
||||||
"message": "A total of $AMOUNT$ items were imported.",
|
"message": "Foi importado um total de $AMOUNT$ itens.",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"amount": {
|
"amount": {
|
||||||
"content": "$1",
|
"content": "$1",
|
||||||
@ -1919,7 +1919,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"premiumPriceWithFamilyPlan": {
|
"premiumPriceWithFamilyPlan": {
|
||||||
"message": "Go premium for just $PRICE$ /year, or get premium accounts for $FAMILYPLANUSERCOUNT$ users and unlimited family sharing with a ",
|
"message": "Adquira uma conta Premium por apenas $PRICE$ /ano, ou obtenha contas Premium para $FAMILYPLANUSERCOUNT$ utilizadores e partilha familiar ilimitada com um ",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"price": {
|
"price": {
|
||||||
"content": "$1",
|
"content": "$1",
|
||||||
@ -1932,7 +1932,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bitwardenFamiliesPlan": {
|
"bitwardenFamiliesPlan": {
|
||||||
"message": "Bitwarden Families plan."
|
"message": "plano Familiar do Bitwarden."
|
||||||
},
|
},
|
||||||
"addons": {
|
"addons": {
|
||||||
"message": "Addons"
|
"message": "Addons"
|
||||||
@ -2029,7 +2029,7 @@
|
|||||||
"message": "Cancelar subscrição"
|
"message": "Cancelar subscrição"
|
||||||
},
|
},
|
||||||
"subscriptionExpiration": {
|
"subscriptionExpiration": {
|
||||||
"message": "Subscription expiration"
|
"message": "Validade da subscrição"
|
||||||
},
|
},
|
||||||
"subscriptionCanceled": {
|
"subscriptionCanceled": {
|
||||||
"message": "A subscrição foi cancelada."
|
"message": "A subscrição foi cancelada."
|
||||||
@ -2265,7 +2265,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"planNameFamilies": {
|
"planNameFamilies": {
|
||||||
"message": "Famílias"
|
"message": "Familiar"
|
||||||
},
|
},
|
||||||
"planDescFamilies": {
|
"planDescFamilies": {
|
||||||
"message": "Para uso pessoal, para partilhar com a família e amigos."
|
"message": "Para uso pessoal, para partilhar com a família e amigos."
|
||||||
@ -2472,7 +2472,7 @@
|
|||||||
"message": "Tem a certeza de que pretende eliminar este grupo?"
|
"message": "Tem a certeza de que pretende eliminar este grupo?"
|
||||||
},
|
},
|
||||||
"deleteMultipleGroupsConfirmation": {
|
"deleteMultipleGroupsConfirmation": {
|
||||||
"message": "Are you sure you want to delete the following $QUANTITY$ group(s)?",
|
"message": "Tem a certeza de que pretende eliminar o(s) seguinte(s) $QUANTITY$ grupo(s)?",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"quantity": {
|
"quantity": {
|
||||||
"content": "$1",
|
"content": "$1",
|
||||||
@ -2532,7 +2532,7 @@
|
|||||||
"message": "Editar membro"
|
"message": "Editar membro"
|
||||||
},
|
},
|
||||||
"fieldOnTabRequiresAttention": {
|
"fieldOnTabRequiresAttention": {
|
||||||
"message": "A field on the '$TAB$' tab requires your attention.",
|
"message": "Um campo no separador '$TAB$' precisa da sua atenção.",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"tab": {
|
"tab": {
|
||||||
"content": "$1",
|
"content": "$1",
|
||||||
@ -2823,7 +2823,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deletedCollections": {
|
"deletedCollections": {
|
||||||
"message": "Deleted collections"
|
"message": "Coleções eliminadas"
|
||||||
},
|
},
|
||||||
"deletedCollectionId": {
|
"deletedCollectionId": {
|
||||||
"message": "Coleção $ID$ eliminada.",
|
"message": "Coleção $ID$ eliminada.",
|
||||||
@ -2871,7 +2871,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deletedManyGroups": {
|
"deletedManyGroups": {
|
||||||
"message": "Deleted $QUANTITY$ group(s).",
|
"message": "$QUANTITY$ grupo(s) eliminados.",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"quantity": {
|
"quantity": {
|
||||||
"content": "$1",
|
"content": "$1",
|
||||||
@ -3363,7 +3363,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"subscriptionFreePlan": {
|
"subscriptionFreePlan": {
|
||||||
"message": "You cannot invite more than $COUNT$ members without upgrading your plan.",
|
"message": "Não pode convidar mais do que $COUNT$ membros sem atualizar o seu plano.",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {
|
"count": {
|
||||||
"content": "$1",
|
"content": "$1",
|
||||||
@ -3372,7 +3372,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"subscriptionFamiliesPlan": {
|
"subscriptionFamiliesPlan": {
|
||||||
"message": "You cannot invite more than $COUNT$ members without upgrading your plan. Please contact Customer Support to upgrade.",
|
"message": "Não pode convidar mais do que $COUNT$ membros sem atualizar o seu plano. Contacte o Apoio ao cliente para atualizar.",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {
|
"count": {
|
||||||
"content": "$1",
|
"content": "$1",
|
||||||
@ -3381,7 +3381,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"subscriptionSponsoredFamiliesPlan": {
|
"subscriptionSponsoredFamiliesPlan": {
|
||||||
"message": "Your subscription allows for a total of $COUNT$ members. Your plan is sponsored and billed to an external organization.",
|
"message": "A sua subscrição permite um total de $COUNT$ membros. O seu plano é patrocinado e faturado por uma organização externa.",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {
|
"count": {
|
||||||
"content": "$1",
|
"content": "$1",
|
||||||
@ -5443,7 +5443,7 @@
|
|||||||
"message": "Histórico de faturação"
|
"message": "Histórico de faturação"
|
||||||
},
|
},
|
||||||
"backToReports": {
|
"backToReports": {
|
||||||
"message": "Back to reports"
|
"message": "Voltar aos relatórios"
|
||||||
},
|
},
|
||||||
"organizationPicker": {
|
"organizationPicker": {
|
||||||
"message": "Organization picker"
|
"message": "Organization picker"
|
||||||
@ -5503,7 +5503,7 @@
|
|||||||
"message": "Palavra aleatória"
|
"message": "Palavra aleatória"
|
||||||
},
|
},
|
||||||
"service": {
|
"service": {
|
||||||
"message": "Service"
|
"message": "Serviço"
|
||||||
},
|
},
|
||||||
"unknownCipher": {
|
"unknownCipher": {
|
||||||
"message": "Item desconhecido, poderá ser necessário pedir autorização para aceder a este item."
|
"message": "Item desconhecido, poderá ser necessário pedir autorização para aceder a este item."
|
||||||
@ -5961,7 +5961,7 @@
|
|||||||
"message": "A eliminação de contas de serviço é permanente e irreversível."
|
"message": "A eliminação de contas de serviço é permanente e irreversível."
|
||||||
},
|
},
|
||||||
"deleteServiceAccountsConfirmMessage": {
|
"deleteServiceAccountsConfirmMessage": {
|
||||||
"message": "Delete $COUNT$ service accounts",
|
"message": "Eliminar $COUNT$ contas de serviço",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {
|
"count": {
|
||||||
"content": "$1",
|
"content": "$1",
|
||||||
@ -5970,13 +5970,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deleteServiceAccountToast": {
|
"deleteServiceAccountToast": {
|
||||||
"message": "Service account deleted"
|
"message": "Conta de serviço eliminada"
|
||||||
},
|
},
|
||||||
"deleteServiceAccountsToast": {
|
"deleteServiceAccountsToast": {
|
||||||
"message": "Service accounts deleted"
|
"message": "Contas de serviço eliminadas"
|
||||||
},
|
},
|
||||||
"searchServiceAccounts": {
|
"searchServiceAccounts": {
|
||||||
"message": "Search service accounts",
|
"message": "Procurar contas de serviço",
|
||||||
"description": "Placeholder text for searching service accounts."
|
"description": "Placeholder text for searching service accounts."
|
||||||
},
|
},
|
||||||
"editServiceAccount": {
|
"editServiceAccount": {
|
||||||
@ -6071,7 +6071,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deleteProjectInputLabel": {
|
"deleteProjectInputLabel": {
|
||||||
"message": "Type \"$CONFIRM$\" to continue",
|
"message": "Escreva \"$CONFIRM$\" para continuar",
|
||||||
"description": "Users are prompted to type 'confirm' to delete a project",
|
"description": "Users are prompted to type 'confirm' to delete a project",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"confirm": {
|
"confirm": {
|
||||||
@ -6081,7 +6081,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deleteProjectConfirmMessage": {
|
"deleteProjectConfirmMessage": {
|
||||||
"message": "Delete $PROJECT$",
|
"message": "Eliminar $PROJECT$",
|
||||||
"description": "Confirmation prompt to delete a specific project, where '$PROJECT$' is a placeholder for the name of the project.",
|
"description": "Confirmation prompt to delete a specific project, where '$PROJECT$' is a placeholder for the name of the project.",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"project": {
|
"project": {
|
||||||
@ -6091,7 +6091,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deleteProjectsConfirmMessage": {
|
"deleteProjectsConfirmMessage": {
|
||||||
"message": "Delete $COUNT$ Projects",
|
"message": "Eliminar $COUNT$ projetos",
|
||||||
"description": "Confirmation prompt to delete multiple projects, where '$COUNT$' is a placeholder for the number of projects to be deleted.",
|
"description": "Confirmation prompt to delete multiple projects, where '$COUNT$' is a placeholder for the number of projects to be deleted.",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {
|
"count": {
|
||||||
@ -6113,22 +6113,22 @@
|
|||||||
"description": "Message to be displayed when there are no projects to display in the list."
|
"description": "Message to be displayed when there are no projects to display in the list."
|
||||||
},
|
},
|
||||||
"smConfirmationRequired": {
|
"smConfirmationRequired": {
|
||||||
"message": "Confirmation required",
|
"message": "Confirmação necessária",
|
||||||
"description": "Indicates that user confirmation is required for an action to proceed."
|
"description": "Indicates that user confirmation is required for an action to proceed."
|
||||||
},
|
},
|
||||||
"bulkDeleteProjectsErrorMessage": {
|
"bulkDeleteProjectsErrorMessage": {
|
||||||
"message": "The following projects could not be deleted:",
|
"message": "Os seguintes projetos não puderam ser eliminados:",
|
||||||
"description": "Message to be displayed when there is an error during bulk project deletion."
|
"description": "Message to be displayed when there is an error during bulk project deletion."
|
||||||
},
|
},
|
||||||
"softDeleteSuccessToast": {
|
"softDeleteSuccessToast": {
|
||||||
"message": "Secret sent to trash",
|
"message": "Segredo movido para o lixo",
|
||||||
"description": "Notification to be displayed when a secret is successfully sent to the trash."
|
"description": "Notification to be displayed when a secret is successfully sent to the trash."
|
||||||
},
|
},
|
||||||
"hardDeleteSuccessToast": {
|
"hardDeleteSuccessToast": {
|
||||||
"message": "Secret permanently deleted"
|
"message": "Segredo eliminado permanentemente"
|
||||||
},
|
},
|
||||||
"accessTokens": {
|
"accessTokens": {
|
||||||
"message": "Access tokens",
|
"message": "Tokens de acesso",
|
||||||
"description": "Title for the section displaying access tokens."
|
"description": "Title for the section displaying access tokens."
|
||||||
},
|
},
|
||||||
"newAccessToken": {
|
"newAccessToken": {
|
||||||
@ -6136,7 +6136,7 @@
|
|||||||
"description": "Button label for creating a new access token."
|
"description": "Button label for creating a new access token."
|
||||||
},
|
},
|
||||||
"expires": {
|
"expires": {
|
||||||
"message": "Expires",
|
"message": "Expira a",
|
||||||
"description": "Label for the expiration date of an access token."
|
"description": "Label for the expiration date of an access token."
|
||||||
},
|
},
|
||||||
"canRead": {
|
"canRead": {
|
||||||
@ -6144,11 +6144,11 @@
|
|||||||
"description": "Label for the access level of an access token (Read only)."
|
"description": "Label for the access level of an access token (Read only)."
|
||||||
},
|
},
|
||||||
"accessTokensNoItemsTitle": {
|
"accessTokensNoItemsTitle": {
|
||||||
"message": "No access tokens to show",
|
"message": "Sem tokens de acesso para mostrar",
|
||||||
"description": "Title to be displayed when there are no access tokens to display in the list."
|
"description": "Title to be displayed when there are no access tokens to display in the list."
|
||||||
},
|
},
|
||||||
"accessTokensNoItemsDesc": {
|
"accessTokensNoItemsDesc": {
|
||||||
"message": "To get started, create an access token",
|
"message": "Para começar, crie um token de acesso",
|
||||||
"description": "Message to be displayed when there are no access tokens to display in the list."
|
"description": "Message to be displayed when there are no access tokens to display in the list."
|
||||||
},
|
},
|
||||||
"downloadAccessToken": {
|
"downloadAccessToken": {
|
||||||
@ -6156,7 +6156,7 @@
|
|||||||
"description": "Message to be displayed before closing an access token, reminding the user to download or copy it."
|
"description": "Message to be displayed before closing an access token, reminding the user to download or copy it."
|
||||||
},
|
},
|
||||||
"expiresOnAccessToken": {
|
"expiresOnAccessToken": {
|
||||||
"message": "Expires on:",
|
"message": "Expira a:",
|
||||||
"description": "Label for the expiration date of an access token."
|
"description": "Label for the expiration date of an access token."
|
||||||
},
|
},
|
||||||
"accessTokenCallOutTitle": {
|
"accessTokenCallOutTitle": {
|
||||||
@ -6164,15 +6164,15 @@
|
|||||||
"description": "Notification to inform the user that access tokens are only displayed once and cannot be retrieved again."
|
"description": "Notification to inform the user that access tokens are only displayed once and cannot be retrieved again."
|
||||||
},
|
},
|
||||||
"copyToken": {
|
"copyToken": {
|
||||||
"message": "Copy token",
|
"message": "Copiar token",
|
||||||
"description": "Copies the generated access token to the user's clipboard."
|
"description": "Copies the generated access token to the user's clipboard."
|
||||||
},
|
},
|
||||||
"accessToken": {
|
"accessToken": {
|
||||||
"message": "Access token",
|
"message": "Token de acesso",
|
||||||
"description": "A unique string that gives a client application (eg. CLI) access to a secret or set of secrets."
|
"description": "A unique string that gives a client application (eg. CLI) access to a secret or set of secrets."
|
||||||
},
|
},
|
||||||
"accessTokenExpirationRequired": {
|
"accessTokenExpirationRequired": {
|
||||||
"message": "Expiration date required",
|
"message": "Data de validade necessária",
|
||||||
"description": "Error message indicating that an expiration date for the access token must be set."
|
"description": "Error message indicating that an expiration date for the access token must be set."
|
||||||
},
|
},
|
||||||
"accessTokenCreatedAndCopied": {
|
"accessTokenCreatedAndCopied": {
|
||||||
@ -6226,7 +6226,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"groupInfo": {
|
"groupInfo": {
|
||||||
"message": "Group info"
|
"message": "Informações do grupo"
|
||||||
},
|
},
|
||||||
"editGroupMembersDesc": {
|
"editGroupMembersDesc": {
|
||||||
"message": "Grant members access to the group's assigned collections."
|
"message": "Grant members access to the group's assigned collections."
|
||||||
@ -6241,22 +6241,22 @@
|
|||||||
"message": "If checked, this will replace all other collection permissions."
|
"message": "If checked, this will replace all other collection permissions."
|
||||||
},
|
},
|
||||||
"selectMembers": {
|
"selectMembers": {
|
||||||
"message": "Select members"
|
"message": "Selecionar membros"
|
||||||
},
|
},
|
||||||
"selectCollections": {
|
"selectCollections": {
|
||||||
"message": "Select collections"
|
"message": "Selecionar coleções"
|
||||||
},
|
},
|
||||||
"role": {
|
"role": {
|
||||||
"message": "Função"
|
"message": "Função"
|
||||||
},
|
},
|
||||||
"removeMember": {
|
"removeMember": {
|
||||||
"message": "Remove member"
|
"message": "Remover membro"
|
||||||
},
|
},
|
||||||
"collection": {
|
"collection": {
|
||||||
"message": "Collection"
|
"message": "Coleção"
|
||||||
},
|
},
|
||||||
"noCollection": {
|
"noCollection": {
|
||||||
"message": "No collection"
|
"message": "Sem coleções"
|
||||||
},
|
},
|
||||||
"canView": {
|
"canView": {
|
||||||
"message": "Pode ver"
|
"message": "Pode ver"
|
||||||
@ -6271,7 +6271,7 @@
|
|||||||
"message": "Pode editar, excepto palavras-passe"
|
"message": "Pode editar, excepto palavras-passe"
|
||||||
},
|
},
|
||||||
"noCollectionsAdded": {
|
"noCollectionsAdded": {
|
||||||
"message": "No collections added"
|
"message": "Sem coleções adicionadas"
|
||||||
},
|
},
|
||||||
"noMembersAdded": {
|
"noMembersAdded": {
|
||||||
"message": "No members added"
|
"message": "No members added"
|
||||||
@ -6364,28 +6364,28 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"domainStatusVerified": {
|
"domainStatusVerified": {
|
||||||
"message": "Verified"
|
"message": "Verificado"
|
||||||
},
|
},
|
||||||
"domainStatusUnverified": {
|
"domainStatusUnverified": {
|
||||||
"message": "Unverified"
|
"message": "Não verificado"
|
||||||
},
|
},
|
||||||
"domainNameTh": {
|
"domainNameTh": {
|
||||||
"message": "Name"
|
"message": "Nome"
|
||||||
},
|
},
|
||||||
"domainStatusTh": {
|
"domainStatusTh": {
|
||||||
"message": "Status"
|
"message": "Estado"
|
||||||
},
|
},
|
||||||
"lastChecked": {
|
"lastChecked": {
|
||||||
"message": "Last checked"
|
"message": "Last checked"
|
||||||
},
|
},
|
||||||
"editDomain": {
|
"editDomain": {
|
||||||
"message": "Edit domain"
|
"message": "Editar domínio"
|
||||||
},
|
},
|
||||||
"domainFormInvalid": {
|
"domainFormInvalid": {
|
||||||
"message": "There are form errors that need your attention"
|
"message": "There are form errors that need your attention"
|
||||||
},
|
},
|
||||||
"addedDomain": {
|
"addedDomain": {
|
||||||
"message": "Added domain $DOMAIN$",
|
"message": "Domínio $DOMAIN$ adicionado",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"DOMAIN": {
|
"DOMAIN": {
|
||||||
"content": "$1",
|
"content": "$1",
|
||||||
@ -6421,16 +6421,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"membersColumnHeader": {
|
"membersColumnHeader": {
|
||||||
"message": "Member/Group"
|
"message": "Membro/Grupo"
|
||||||
},
|
},
|
||||||
"groupAndMemberColumnHeader": {
|
"groupAndMemberColumnHeader": {
|
||||||
"message": "Member"
|
"message": "Membro"
|
||||||
},
|
},
|
||||||
"selectGroupsAndMembers": {
|
"selectGroupsAndMembers": {
|
||||||
"message": "Select groups and members"
|
"message": "Selecionar grupos e membros"
|
||||||
},
|
},
|
||||||
"selectGroups": {
|
"selectGroups": {
|
||||||
"message": "Select groups"
|
"message": "Selecionar grupos"
|
||||||
},
|
},
|
||||||
"userPermissionOverrideHelper": {
|
"userPermissionOverrideHelper": {
|
||||||
"message": "Permissions set for a member will replace permissions set by that member's group"
|
"message": "Permissions set for a member will replace permissions set by that member's group"
|
||||||
@ -6439,13 +6439,13 @@
|
|||||||
"message": "No members or groups added"
|
"message": "No members or groups added"
|
||||||
},
|
},
|
||||||
"deleted": {
|
"deleted": {
|
||||||
"message": "Deleted"
|
"message": "Eliminado"
|
||||||
},
|
},
|
||||||
"memberStatusFilter": {
|
"memberStatusFilter": {
|
||||||
"message": "Member status filter"
|
"message": "Member status filter"
|
||||||
},
|
},
|
||||||
"inviteMember": {
|
"inviteMember": {
|
||||||
"message": "Invite member"
|
"message": "Convidar membro"
|
||||||
},
|
},
|
||||||
"needsConfirmation": {
|
"needsConfirmation": {
|
||||||
"message": "Needs confirmation"
|
"message": "Needs confirmation"
|
||||||
@ -6496,10 +6496,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"server": {
|
"server": {
|
||||||
"message": "Server"
|
"message": "Servidor"
|
||||||
},
|
},
|
||||||
"exportData": {
|
"exportData": {
|
||||||
"message": "Export data"
|
"message": "Exportar dados"
|
||||||
},
|
},
|
||||||
"exportingOrganizationSecretDataTitle": {
|
"exportingOrganizationSecretDataTitle": {
|
||||||
"message": "Exporting Organization Secret Data"
|
"message": "Exporting Organization Secret Data"
|
||||||
@ -6619,13 +6619,13 @@
|
|||||||
"message": "This user can access the Secrets Manager Beta"
|
"message": "This user can access the Secrets Manager Beta"
|
||||||
},
|
},
|
||||||
"important": {
|
"important": {
|
||||||
"message": "Important:"
|
"message": "Importante:"
|
||||||
},
|
},
|
||||||
"viewAll": {
|
"viewAll": {
|
||||||
"message": "View all"
|
"message": "Ver tudo"
|
||||||
},
|
},
|
||||||
"showingPortionOfTotal": {
|
"showingPortionOfTotal": {
|
||||||
"message": "Showing $PORTION$ of $TOTAL$",
|
"message": "A mostrar $PORTION$ de $TOTAL$",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"portion": {
|
"portion": {
|
||||||
"content": "$1",
|
"content": "$1",
|
||||||
@ -6638,16 +6638,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"resolveTheErrorsBelowAndTryAgain": {
|
"resolveTheErrorsBelowAndTryAgain": {
|
||||||
"message": "Resolve the errors below and try again."
|
"message": "Resolva os erros abaixo e tente novamente."
|
||||||
},
|
},
|
||||||
"description": {
|
"description": {
|
||||||
"message": "Description"
|
"message": "Descrição"
|
||||||
},
|
},
|
||||||
"errorReadingImportFile": {
|
"errorReadingImportFile": {
|
||||||
"message": "An error occurred when trying to read the import file"
|
"message": "Ocorreu um erro ao tentar ler o ficheiro de importação"
|
||||||
},
|
},
|
||||||
"accessedSecret": {
|
"accessedSecret": {
|
||||||
"message": "Accessed secret $SECRET_ID$.",
|
"message": "Segredo $SECRET_ID$ acedido.",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"secret_id": {
|
"secret_id": {
|
||||||
"content": "$1",
|
"content": "$1",
|
||||||
@ -6660,29 +6660,29 @@
|
|||||||
"description": "Software Development Kit"
|
"description": "Software Development Kit"
|
||||||
},
|
},
|
||||||
"createSecret": {
|
"createSecret": {
|
||||||
"message": "Create a secret"
|
"message": "Criar um segredo"
|
||||||
},
|
},
|
||||||
"createProject": {
|
"createProject": {
|
||||||
"message": "Create a project"
|
"message": "Criar um projeto"
|
||||||
},
|
},
|
||||||
"createServiceAccount": {
|
"createServiceAccount": {
|
||||||
"message": "Create a service account"
|
"message": "Criar uma conta de serviço"
|
||||||
},
|
},
|
||||||
"downloadThe": {
|
"downloadThe": {
|
||||||
"message": "Download the",
|
"message": "Descarregar o",
|
||||||
"description": "Link to a downloadable resource. This will be used as part of a larger phrase. Example: Download the Secrets Manager CLI"
|
"description": "Link to a downloadable resource. This will be used as part of a larger phrase. Example: Download the Secrets Manager CLI"
|
||||||
},
|
},
|
||||||
"smCLI": {
|
"smCLI": {
|
||||||
"message": "Secrets Manager CLI"
|
"message": "gestor de segredos CLI"
|
||||||
},
|
},
|
||||||
"importSecrets": {
|
"importSecrets": {
|
||||||
"message": "Import secrets"
|
"message": "Importar segredos"
|
||||||
},
|
},
|
||||||
"getStarted": {
|
"getStarted": {
|
||||||
"message": "Get started"
|
"message": "Começar"
|
||||||
},
|
},
|
||||||
"complete": {
|
"complete": {
|
||||||
"message": "$COMPLETED$/$TOTAL$ Complete",
|
"message": "$COMPLETED$/$TOTAL$ concluídos",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"COMPLETED": {
|
"COMPLETED": {
|
||||||
"content": "$1",
|
"content": "$1",
|
||||||
@ -6695,25 +6695,25 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"restoreSecret": {
|
"restoreSecret": {
|
||||||
"message": "Restore secret"
|
"message": "Restaurar segredo"
|
||||||
},
|
},
|
||||||
"restoreSecrets": {
|
"restoreSecrets": {
|
||||||
"message": "Restore secrets"
|
"message": "Restaurar segredos"
|
||||||
},
|
},
|
||||||
"restoreSecretPrompt": {
|
"restoreSecretPrompt": {
|
||||||
"message": "Are you sure you want to restore this secret?"
|
"message": "Tem a certeza de que quer recuperar este segredo?"
|
||||||
},
|
},
|
||||||
"restoreSecretsPrompt": {
|
"restoreSecretsPrompt": {
|
||||||
"message": "Are you sure you want to restore these secrets?"
|
"message": "Tem a certeza de que quer recuperar estes segredos?"
|
||||||
},
|
},
|
||||||
"secretRestoredSuccessToast": {
|
"secretRestoredSuccessToast": {
|
||||||
"message": "Secret restored"
|
"message": "Segredo restaurado"
|
||||||
},
|
},
|
||||||
"secretsRestoredSuccessToast": {
|
"secretsRestoredSuccessToast": {
|
||||||
"message": "Secrets restored"
|
"message": "Segredos restaurados"
|
||||||
},
|
},
|
||||||
"selectionIsRequired": {
|
"selectionIsRequired": {
|
||||||
"message": "Selection is required."
|
"message": "É necessária uma seleção."
|
||||||
},
|
},
|
||||||
"secretsManagerSubscriptionDesc": {
|
"secretsManagerSubscriptionDesc": {
|
||||||
"message": "Turn on organization access to the Secrets Manager at no charge during the Beta program. Users can be granted access to the Beta in Members."
|
"message": "Turn on organization access to the Secrets Manager at no charge during the Beta program. Users can be granted access to the Beta in Members."
|
||||||
@ -6740,25 +6740,25 @@
|
|||||||
"message": "This action will remove your access to the service account."
|
"message": "This action will remove your access to the service account."
|
||||||
},
|
},
|
||||||
"removeAccess": {
|
"removeAccess": {
|
||||||
"message": "Remove access"
|
"message": "Remover acesso"
|
||||||
},
|
},
|
||||||
"checkForBreaches": {
|
"checkForBreaches": {
|
||||||
"message": "Check known data breaches for this password"
|
"message": "Verificar violações de dados conhecidas para esta palavra-passe"
|
||||||
},
|
},
|
||||||
"exposedMasterPassword": {
|
"exposedMasterPassword": {
|
||||||
"message": "Exposed Master Password"
|
"message": "Palavra-passe mestra exposta"
|
||||||
},
|
},
|
||||||
"exposedMasterPasswordDesc": {
|
"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": "Palavra-passe encontrada numa violação de dados. Utilize uma palavra-passe única para proteger a sua conta. Tem a certeza de que pretende utilizar uma palavra-passe exposta?"
|
||||||
},
|
},
|
||||||
"weakAndExposedMasterPassword": {
|
"weakAndExposedMasterPassword": {
|
||||||
"message": "Weak and Exposed Master Password"
|
"message": "Palavra-passe mestra fraca e exposta"
|
||||||
},
|
},
|
||||||
"weakAndBreachedMasterPasswordDesc": {
|
"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": "Palavra-passe fraca identificada e encontrada numa violação de dados. Utilize uma palavra-passe forte e única para proteger a sua conta. Tem a certeza de que pretende utilizar esta palavra-passe?"
|
||||||
},
|
},
|
||||||
"characterMinimum": {
|
"characterMinimum": {
|
||||||
"message": "$LENGTH$ character minimum",
|
"message": "$LENGTH$ caracteres no mínimo",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"length": {
|
"length": {
|
||||||
"content": "$1",
|
"content": "$1",
|
||||||
@ -6783,14 +6783,14 @@
|
|||||||
"message": "Dispensar"
|
"message": "Dispensar"
|
||||||
},
|
},
|
||||||
"notAvailableForFreeOrganization": {
|
"notAvailableForFreeOrganization": {
|
||||||
"message": "This feature is not available for free organizations. Contact your organization owner to upgrade."
|
"message": "Esta funcionalidade não está disponível para organizações gratuitas. Contacte o proprietário da organização para atualizar."
|
||||||
},
|
},
|
||||||
"smProjectSecretsNoItemsNoAccess": {
|
"smProjectSecretsNoItemsNoAccess": {
|
||||||
"message": "Contact your organization's admin to manage secrets for this project.",
|
"message": "Contacte o administrador da sua organização para gerir os segredos deste projeto.",
|
||||||
"description": "The message shown to the user under a project's secrets tab when the user only has read access to the project."
|
"description": "The message shown to the user under a project's secrets tab when the user only has read access to the project."
|
||||||
},
|
},
|
||||||
"enforceOnLoginDesc": {
|
"enforceOnLoginDesc": {
|
||||||
"message": "Require existing members to change their passwords"
|
"message": "Exigir que os membros existentes alterem as suas palavras-passe"
|
||||||
},
|
},
|
||||||
"region": {
|
"region": {
|
||||||
"message": "Região"
|
"message": "Região"
|
||||||
@ -6804,18 +6804,18 @@
|
|||||||
"description": "United States"
|
"description": "United States"
|
||||||
},
|
},
|
||||||
"smProjectDeleteAccessRestricted": {
|
"smProjectDeleteAccessRestricted": {
|
||||||
"message": "You don't have permissions to delete this project",
|
"message": "Não tem permissões para eliminar este projeto",
|
||||||
"description": "The individual description shown to the user when the user doesn't have access to delete a project."
|
"description": "The individual description shown to the user when the user doesn't have access to delete a project."
|
||||||
},
|
},
|
||||||
"smProjectsDeleteBulkConfirmation": {
|
"smProjectsDeleteBulkConfirmation": {
|
||||||
"message": "The following projects can not be deleted. Would you like to continue?",
|
"message": "Os seguintes projetos não podem ser eliminados. Gostaria de continuar?",
|
||||||
"description": "The message shown to the user when bulk deleting projects and the user doesn't have access to some projects."
|
"description": "The message shown to the user when bulk deleting projects and the user doesn't have access to some projects."
|
||||||
},
|
},
|
||||||
"updateKdfSettings": {
|
"updateKdfSettings": {
|
||||||
"message": "Update KDF settings"
|
"message": "Atualizar definições KDF"
|
||||||
},
|
},
|
||||||
"trustedDeviceEncryption": {
|
"trustedDeviceEncryption": {
|
||||||
"message": "Trusted device encryption"
|
"message": "Encriptação de dispositivo de confiança"
|
||||||
},
|
},
|
||||||
"memberDecryptionTdeDescriptionStart": {
|
"memberDecryptionTdeDescriptionStart": {
|
||||||
"message": "Uma vez autenticados, os membros desencriptam os dados do cofre utilizando uma chave armazenada no seu dispositivo. A",
|
"message": "Uma vez autenticados, os membros desencriptam os dados do cofre utilizando uma chave armazenada no seu dispositivo. A",
|
||||||
|
@ -88,11 +88,10 @@ export class EnvironmentSelectorComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async updateEnvironmentInfo() {
|
async updateEnvironmentInfo() {
|
||||||
|
this.selectedEnvironment = this.environmentService.selectedRegion;
|
||||||
this.euServerFlagEnabled = await this.configService.getFeatureFlagBool(
|
this.euServerFlagEnabled = await this.configService.getFeatureFlagBool(
|
||||||
FeatureFlag.DisplayEuEnvironmentFlag
|
FeatureFlag.DisplayEuEnvironmentFlag
|
||||||
);
|
);
|
||||||
|
|
||||||
this.selectedEnvironment = this.environmentService.selectedRegion;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
|
@ -304,10 +304,13 @@ export class AuthService implements AuthServiceAbstraction {
|
|||||||
throw new Error("Master key not found");
|
throw new Error("Master key not found");
|
||||||
}
|
}
|
||||||
const encryptedKey = await this.cryptoService.rsaEncrypt(masterKey.encKey, pubKey.buffer);
|
const encryptedKey = await this.cryptoService.rsaEncrypt(masterKey.encKey, pubKey.buffer);
|
||||||
const encryptedMasterPasswordHash = await this.cryptoService.rsaEncrypt(
|
let encryptedMasterPasswordHash = null;
|
||||||
|
if ((await this.stateService.getKeyHash()) != null) {
|
||||||
|
encryptedMasterPasswordHash = await this.cryptoService.rsaEncrypt(
|
||||||
Utils.fromUtf8ToArray(await this.stateService.getKeyHash()),
|
Utils.fromUtf8ToArray(await this.stateService.getKeyHash()),
|
||||||
pubKey.buffer
|
pubKey.buffer
|
||||||
);
|
);
|
||||||
|
}
|
||||||
const request = new PasswordlessAuthRequest(
|
const request = new PasswordlessAuthRequest(
|
||||||
encryptedKey.encryptedString,
|
encryptedKey.encryptedString,
|
||||||
encryptedMasterPasswordHash.encryptedString,
|
encryptedMasterPasswordHash.encryptedString,
|
||||||
|
@ -28,6 +28,7 @@ export abstract class EnvironmentService {
|
|||||||
usUrls: Urls;
|
usUrls: Urls;
|
||||||
euUrls: Urls;
|
euUrls: Urls;
|
||||||
selectedRegion?: Region;
|
selectedRegion?: Region;
|
||||||
|
initialized = true;
|
||||||
|
|
||||||
hasBaseUrl: () => boolean;
|
hasBaseUrl: () => boolean;
|
||||||
getNotificationsUrl: () => string;
|
getNotificationsUrl: () => string;
|
||||||
|
@ -12,6 +12,7 @@ export class EnvironmentService implements EnvironmentServiceAbstraction {
|
|||||||
private readonly urlsSubject = new Subject<void>();
|
private readonly urlsSubject = new Subject<void>();
|
||||||
urls: Observable<void> = this.urlsSubject.asObservable();
|
urls: Observable<void> = this.urlsSubject.asObservable();
|
||||||
selectedRegion?: Region;
|
selectedRegion?: Region;
|
||||||
|
initialized = true;
|
||||||
|
|
||||||
protected baseUrl: string;
|
protected baseUrl: string;
|
||||||
protected webVaultUrl: string;
|
protected webVaultUrl: string;
|
||||||
@ -49,6 +50,9 @@ export class EnvironmentService implements EnvironmentServiceAbstraction {
|
|||||||
this.stateService.activeAccount$
|
this.stateService.activeAccount$
|
||||||
.pipe(
|
.pipe(
|
||||||
concatMap(async () => {
|
concatMap(async () => {
|
||||||
|
if (!this.initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
await this.setUrlsFromStorage();
|
await this.setUrlsFromStorage();
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
@ -157,22 +161,23 @@ export class EnvironmentService implements EnvironmentServiceAbstraction {
|
|||||||
|
|
||||||
// fix environment urls for old users
|
// fix environment urls for old users
|
||||||
if (savedUrls.base === "https://vault.bitwarden.com") {
|
if (savedUrls.base === "https://vault.bitwarden.com") {
|
||||||
this.setRegion(Region.US);
|
await this.setRegion(Region.US);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (savedUrls.base === "https://vault.bitwarden.eu") {
|
if (savedUrls.base === "https://vault.bitwarden.eu") {
|
||||||
this.setRegion(Region.EU);
|
await this.setRegion(Region.EU);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (region) {
|
switch (region) {
|
||||||
case Region.EU:
|
case Region.EU:
|
||||||
this.setRegion(Region.EU);
|
await this.setRegion(Region.EU);
|
||||||
return;
|
return;
|
||||||
case Region.US:
|
case Region.US:
|
||||||
this.setRegion(Region.US);
|
await this.setRegion(Region.US);
|
||||||
return;
|
return;
|
||||||
case Region.SelfHosted:
|
case Region.SelfHosted:
|
||||||
|
case null:
|
||||||
default:
|
default:
|
||||||
this.baseUrl = envUrls.base = savedUrls.base;
|
this.baseUrl = envUrls.base = savedUrls.base;
|
||||||
this.webVaultUrl = savedUrls.webVault;
|
this.webVaultUrl = savedUrls.webVault;
|
||||||
@ -182,9 +187,9 @@ export class EnvironmentService implements EnvironmentServiceAbstraction {
|
|||||||
this.notificationsUrl = savedUrls.notifications;
|
this.notificationsUrl = savedUrls.notifications;
|
||||||
this.eventsUrl = envUrls.events = savedUrls.events;
|
this.eventsUrl = envUrls.events = savedUrls.events;
|
||||||
this.keyConnectorUrl = savedUrls.keyConnector;
|
this.keyConnectorUrl = savedUrls.keyConnector;
|
||||||
|
await this.setRegion(Region.SelfHosted);
|
||||||
// scimUrl is not saved to storage
|
// scimUrl is not saved to storage
|
||||||
this.urlsSubject.next();
|
this.urlsSubject.next();
|
||||||
this.setRegion(Region.SelfHosted);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -270,7 +275,7 @@ export class EnvironmentService implements EnvironmentServiceAbstraction {
|
|||||||
case Region.SelfHosted:
|
case Region.SelfHosted:
|
||||||
// if user saves with empty fields, default to US
|
// if user saves with empty fields, default to US
|
||||||
if (this.isEmpty()) {
|
if (this.isEmpty()) {
|
||||||
this.setRegion(Region.US);
|
await this.setRegion(Region.US);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
4
package-lock.json
generated
4
package-lock.json
generated
@ -189,7 +189,7 @@
|
|||||||
},
|
},
|
||||||
"apps/browser": {
|
"apps/browser": {
|
||||||
"name": "@bitwarden/browser",
|
"name": "@bitwarden/browser",
|
||||||
"version": "2023.5.0"
|
"version": "2023.5.1"
|
||||||
},
|
},
|
||||||
"apps/cli": {
|
"apps/cli": {
|
||||||
"name": "@bitwarden/cli",
|
"name": "@bitwarden/cli",
|
||||||
@ -243,7 +243,7 @@
|
|||||||
},
|
},
|
||||||
"apps/web": {
|
"apps/web": {
|
||||||
"name": "@bitwarden/web-vault",
|
"name": "@bitwarden/web-vault",
|
||||||
"version": "2023.5.0"
|
"version": "2023.5.1"
|
||||||
},
|
},
|
||||||
"libs/angular": {
|
"libs/angular": {
|
||||||
"name": "@bitwarden/angular",
|
"name": "@bitwarden/angular",
|
||||||
|
Loading…
Reference in New Issue
Block a user