mirror of
https://github.com/bitwarden/browser
synced 2025-12-17 16:53:34 +00:00
Merged branch with master
This commit is contained in:
@@ -156,7 +156,10 @@
|
|||||||
{
|
{
|
||||||
"files": ["libs/components/src/**/*.ts"],
|
"files": ["libs/components/src/**/*.ts"],
|
||||||
"rules": {
|
"rules": {
|
||||||
"no-restricted-imports": ["error", { "patterns": ["@bitwarden/components/*", "src/**/*"] }]
|
"no-restricted-imports": [
|
||||||
|
"error",
|
||||||
|
{ "patterns": ["@bitwarden/components/*", "src/**/*", "@bitwarden/angular/*"] }
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -176,6 +179,12 @@
|
|||||||
"rules": {
|
"rules": {
|
||||||
"no-restricted-imports": ["error", { "patterns": ["@bitwarden/node/*", "src/**/*"] }]
|
"no-restricted-imports": ["error", { "patterns": ["@bitwarden/node/*", "src/**/*"] }]
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["libs/vault/src/**/*.ts"],
|
||||||
|
"rules": {
|
||||||
|
"no-restricted-imports": ["error", { "patterns": ["@bitwarden/vault/*", "src/**/*"] }]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
3
.github/CODEOWNERS
vendored
3
.github/CODEOWNERS
vendored
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
# The following owners will be the default owners for everything in the repo.
|
# The following owners will be the default owners for everything in the repo.
|
||||||
# Unless a later match takes precedence
|
# Unless a later match takes precedence
|
||||||
* @bitwarden/team-leads-eng
|
* @bitwarden/tech-leads
|
||||||
|
|
||||||
## Secrets Manager team files ##
|
## Secrets Manager team files ##
|
||||||
bitwarden_license/bit-web/src/app/secrets-manager @bitwarden/team-secrets-manager-dev
|
bitwarden_license/bit-web/src/app/secrets-manager @bitwarden/team-secrets-manager-dev
|
||||||
@@ -39,6 +39,7 @@ apps/desktop/src/vault @bitwarden/team-vault-dev
|
|||||||
apps/web/src/app/vault @bitwarden/team-vault-dev
|
apps/web/src/app/vault @bitwarden/team-vault-dev
|
||||||
libs/angular/src/vault @bitwarden/team-vault-dev
|
libs/angular/src/vault @bitwarden/team-vault-dev
|
||||||
libs/common/src/vault @bitwarden/team-vault-dev
|
libs/common/src/vault @bitwarden/team-vault-dev
|
||||||
|
libs/vault @bitwarden/team-vault-dev
|
||||||
|
|
||||||
## Admin Console team files ##
|
## Admin Console team files ##
|
||||||
apps/browser/src/admin-console @bitwarden/team-admin-console-dev
|
apps/browser/src/admin-console @bitwarden/team-admin-console-dev
|
||||||
|
|||||||
9
.github/whitelist-capital-letters.txt
vendored
9
.github/whitelist-capital-letters.txt
vendored
@@ -2,10 +2,7 @@
|
|||||||
./apps/browser/src/safari/desktop/Assets.xcassets/AccentColor.colorset
|
./apps/browser/src/safari/desktop/Assets.xcassets/AccentColor.colorset
|
||||||
./apps/browser/src/safari/desktop/Assets.xcassets/AppIcon.appiconset
|
./apps/browser/src/safari/desktop/Assets.xcassets/AppIcon.appiconset
|
||||||
./apps/browser/src/safari/desktop/Base.lproj
|
./apps/browser/src/safari/desktop/Base.lproj
|
||||||
./apps/browser/src/services/vaultTimeout
|
|
||||||
./apps/browser/store/windows/Assets
|
./apps/browser/store/windows/Assets
|
||||||
./libs/common/src/abstractions/vaultTimeout
|
|
||||||
./libs/common/src/services/vaultTimeout
|
|
||||||
./bitwarden_license/README.md
|
./bitwarden_license/README.md
|
||||||
./libs/angular/src/directives/cipherListVirtualScroll.directive.ts
|
./libs/angular/src/directives/cipherListVirtualScroll.directive.ts
|
||||||
./libs/angular/src/scss/webfonts/Open_Sans-italic-700.woff
|
./libs/angular/src/scss/webfonts/Open_Sans-italic-700.woff
|
||||||
@@ -25,13 +22,10 @@
|
|||||||
./libs/common/src/misc/linkedFieldOption.decorator.ts
|
./libs/common/src/misc/linkedFieldOption.decorator.ts
|
||||||
./libs/common/src/misc/serviceUtils.ts
|
./libs/common/src/misc/serviceUtils.ts
|
||||||
./libs/common/src/misc/serviceUtils.spec.ts
|
./libs/common/src/misc/serviceUtils.spec.ts
|
||||||
./libs/common/src/abstractions/vaultTimeout/vaultTimeoutSettings.service.ts
|
|
||||||
./libs/common/src/abstractions/vaultTimeout/vaultTimeout.service.ts
|
|
||||||
./libs/common/src/abstractions/anonymousHub.service.ts
|
./libs/common/src/abstractions/anonymousHub.service.ts
|
||||||
./libs/common/src/services/vaultTimeout/vaultTimeoutSettings.service.ts
|
|
||||||
./libs/common/src/services/vaultTimeout/vaultTimeout.service.ts
|
|
||||||
./libs/common/src/services/anonymousHub.service.ts
|
./libs/common/src/services/anonymousHub.service.ts
|
||||||
./libs/auth/README.md
|
./libs/auth/README.md
|
||||||
|
./libs/vault/README.md
|
||||||
./README.md
|
./README.md
|
||||||
./LICENSE_BITWARDEN.txt
|
./LICENSE_BITWARDEN.txt
|
||||||
./CONTRIBUTING.md
|
./CONTRIBUTING.md
|
||||||
@@ -78,5 +72,4 @@
|
|||||||
./apps/browser/src/safari/safari/SafariWebExtensionHandler.swift
|
./apps/browser/src/safari/safari/SafariWebExtensionHandler.swift
|
||||||
./apps/browser/src/safari/safari/Info.plist
|
./apps/browser/src/safari/safari/Info.plist
|
||||||
./apps/browser/src/safari/desktop.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
|
./apps/browser/src/safari/desktop.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
|
||||||
./apps/browser/src/services/vaultTimeout/vaultTimeout.service.ts
|
|
||||||
./SECURITY.md
|
./SECURITY.md
|
||||||
|
|||||||
79
.github/workflows/build-web.yml
vendored
79
.github/workflows/build-web.yml
vendored
@@ -31,6 +31,9 @@ on:
|
|||||||
description: "Custom image tag extension"
|
description: "Custom image tag extension"
|
||||||
required: false
|
required: false
|
||||||
|
|
||||||
|
env:
|
||||||
|
_AZ_REGISTRY: bitwardenprod.azurecr.io
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
cloc:
|
cloc:
|
||||||
name: CLOC
|
name: CLOC
|
||||||
@@ -65,8 +68,7 @@ jobs:
|
|||||||
build-artifacts:
|
build-artifacts:
|
||||||
name: Build artifacts
|
name: Build artifacts
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
needs:
|
needs: setup
|
||||||
- setup
|
|
||||||
env:
|
env:
|
||||||
_VERSION: ${{ needs.setup.outputs.version }}
|
_VERSION: ${{ needs.setup.outputs.version }}
|
||||||
strategy:
|
strategy:
|
||||||
@@ -146,13 +148,10 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- artifact_name: cloud-QA
|
- artifact_name: cloud-QA
|
||||||
registries: [bitwardenprod.azurecr.io, bitwardenqa.azurecr.io]
|
|
||||||
image_name: web-qa-cloud
|
image_name: web-qa-cloud
|
||||||
- artifact_name: ee
|
- artifact_name: ee
|
||||||
registries: [bitwardenprod.azurecr.io, bitwardenqa.azurecr.io]
|
|
||||||
image_name: web-ee
|
image_name: web-ee
|
||||||
- artifact_name: selfhosted-COMMERCIAL
|
- artifact_name: selfhosted-COMMERCIAL
|
||||||
registries: [bitwarden, bitwardenprod.azurecr.io, bitwardenqa.azurecr.io]
|
|
||||||
image_name: web
|
image_name: web
|
||||||
env:
|
env:
|
||||||
_VERSION: ${{ needs.setup.outputs.version }}
|
_VERSION: ${{ needs.setup.outputs.version }}
|
||||||
@@ -174,15 +173,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
########## ACRs ##########
|
########## ACRs ##########
|
||||||
- name: Login to Azure - QA
|
- name: Login to Prod Azure
|
||||||
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
|
|
||||||
with:
|
|
||||||
creds: ${{ secrets.AZURE_QA_KV_CREDENTIALS }}
|
|
||||||
|
|
||||||
- name: Log into QA container registry
|
|
||||||
run: az acr login -n bitwardenqa
|
|
||||||
|
|
||||||
- name: Login to Azure - Prod
|
|
||||||
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
|
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
|
||||||
with:
|
with:
|
||||||
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
|
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
|
||||||
@@ -190,6 +181,18 @@ jobs:
|
|||||||
- name: Log into Prod container registry
|
- name: Log into Prod container registry
|
||||||
run: az acr login -n bitwardenprod
|
run: az acr login -n bitwardenprod
|
||||||
|
|
||||||
|
- name: Login to Azure - CI Subscription
|
||||||
|
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
|
||||||
|
with:
|
||||||
|
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
||||||
|
|
||||||
|
- name: Retrieve github PAT secrets
|
||||||
|
id: retrieve-secret-pat
|
||||||
|
uses: bitwarden/gh-actions/get-keyvault-secrets@f096207b7a2f31723165aee6ad03e91716686e78
|
||||||
|
with:
|
||||||
|
keyvault: "bitwarden-ci"
|
||||||
|
secrets: "github-pat-bitwarden-devops-bot-repo-scope"
|
||||||
|
|
||||||
- name: Download ${{ matrix.artifact_name }} artifact
|
- name: Download ${{ matrix.artifact_name }} artifact
|
||||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||||
with:
|
with:
|
||||||
@@ -218,37 +221,17 @@ jobs:
|
|||||||
|
|
||||||
echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT
|
echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Generate tag list
|
|
||||||
id: tag-list
|
|
||||||
env:
|
|
||||||
IMAGE_TAG: ${{ steps.tag.outputs.image_tag }}
|
|
||||||
PROJECT_NAME: ${{ matrix.image_name }}
|
|
||||||
run: echo "tags=bitwardenqa.azurecr.io/${PROJECT_NAME}:${IMAGE_TAG},bitwardenprod.azurecr.io/${PROJECT_NAME}:${IMAGE_TAG}" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
########## Build Image ##########
|
########## Build Image ##########
|
||||||
- name: Extract artifact
|
- name: Extract artifact
|
||||||
working-directory: apps/web
|
working-directory: apps/web
|
||||||
run: unzip web-${{ env._VERSION }}-${{ matrix.artifact_name }}.zip
|
run: unzip web-${{ env._VERSION }}-${{ matrix.artifact_name }}.zip
|
||||||
|
|
||||||
- name: Login to Azure
|
- name: Generate image full name
|
||||||
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
|
id: image-name
|
||||||
with:
|
env:
|
||||||
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
IMAGE_TAG: ${{ steps.tag.outputs.image_tag }}
|
||||||
|
PROJECT_NAME: ${{ matrix.image_name }}
|
||||||
- name: Retrieve github PAT secrets
|
run: echo "name=$_AZ_REGISTRY/${PROJECT_NAME}:${IMAGE_TAG}" >> $GITHUB_OUTPUT
|
||||||
id: retrieve-secret-pat
|
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@a30e9c3d658dc97c4c2e61ec749fdab64b83386c
|
|
||||||
with:
|
|
||||||
keyvault: "bitwarden-ci"
|
|
||||||
secrets: "github-pat-bitwarden-devops-bot-repo-scope"
|
|
||||||
|
|
||||||
- name: Setup DCT
|
|
||||||
if: ${{ env.is_publish_branch == 'true' }}
|
|
||||||
id: setup-dct
|
|
||||||
uses: bitwarden/gh-actions/setup-docker-trust@a30e9c3d658dc97c4c2e61ec749fdab64b83386c
|
|
||||||
with:
|
|
||||||
azure-creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
|
||||||
azure-keyvault-name: "bitwarden-ci"
|
|
||||||
|
|
||||||
- name: Build Docker image
|
- name: Build Docker image
|
||||||
uses: docker/build-push-action@2eb1c1961a95fc15694676618e422e8ba1d63825 # v4.1.1
|
uses: docker/build-push-action@2eb1c1961a95fc15694676618e422e8ba1d63825 # v4.1.1
|
||||||
@@ -257,21 +240,10 @@ jobs:
|
|||||||
file: apps/web/Dockerfile
|
file: apps/web/Dockerfile
|
||||||
platforms: linux/amd64
|
platforms: linux/amd64
|
||||||
push: true
|
push: true
|
||||||
tags: ${{ steps.tag-list.outputs.tags }}
|
tags: ${{ steps.image-name.outputs.name }}
|
||||||
secrets: |
|
secrets: |
|
||||||
"GH_PAT=${{ steps.retrieve-secret-pat.outputs.github-pat-bitwarden-devops-bot-repo-scope }}"
|
"GH_PAT=${{ steps.retrieve-secret-pat.outputs.github-pat-bitwarden-devops-bot-repo-scope }}"
|
||||||
|
|
||||||
- name: Push to DockerHub
|
|
||||||
if: contains(matrix.registries, 'bitwarden') && env.is_publish_branch == 'true'
|
|
||||||
env:
|
|
||||||
IMAGE_TAG: ${{ steps.tag.outputs.image_tag }}
|
|
||||||
PROJECT_NAME: ${{ matrix.image_name }}
|
|
||||||
DOCKER_CONTENT_TRUST: 1
|
|
||||||
DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: ${{ steps.setup-dct.outputs.dct-delegate-repo-passphrase }}
|
|
||||||
run: |
|
|
||||||
docker tag bitwardenprod.azurecr.io/$PROJECT_NAME:$IMAGE_TAG bitwarden/$PROJECT_NAME:$IMAGE_TAG
|
|
||||||
docker push bitwarden/$PROJECT_NAME:$IMAGE_TAG
|
|
||||||
|
|
||||||
- name: Log out of Docker
|
- name: Log out of Docker
|
||||||
run: docker logout
|
run: docker logout
|
||||||
|
|
||||||
@@ -279,8 +251,7 @@ jobs:
|
|||||||
crowdin-push:
|
crowdin-push:
|
||||||
name: Crowdin Push
|
name: Crowdin Push
|
||||||
if: github.ref == 'refs/heads/master'
|
if: github.ref == 'refs/heads/master'
|
||||||
needs:
|
needs: build-artifacts
|
||||||
- build-artifacts
|
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
|
|||||||
90
.github/workflows/release-web.yml
vendored
90
.github/workflows/release-web.yml
vendored
@@ -15,10 +15,13 @@ on:
|
|||||||
- Redeploy
|
- Redeploy
|
||||||
- Dry Run
|
- Dry Run
|
||||||
|
|
||||||
|
env:
|
||||||
|
_AZ_REGISTRY: bitwardenprod.azurecr.io
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
setup:
|
setup:
|
||||||
name: Setup
|
name: Setup
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
outputs:
|
outputs:
|
||||||
release_version: ${{ steps.version.outputs.version }}
|
release_version: ${{ steps.version.outputs.version }}
|
||||||
tag_version: ${{ steps.version.outputs.tag }}
|
tag_version: ${{ steps.version.outputs.tag }}
|
||||||
@@ -46,10 +49,9 @@ jobs:
|
|||||||
monorepo: true
|
monorepo: true
|
||||||
monorepo-project: web
|
monorepo-project: web
|
||||||
|
|
||||||
|
|
||||||
self-host:
|
self-host:
|
||||||
name: Release self-host docker
|
name: Release self-host docker
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
needs: setup
|
needs: setup
|
||||||
env:
|
env:
|
||||||
_BRANCH_NAME: ${{ github.ref_name }}
|
_BRANCH_NAME: ${{ github.ref_name }}
|
||||||
@@ -67,42 +69,6 @@ jobs:
|
|||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
|
|
||||||
########## DockerHub ##########
|
|
||||||
- name: Setup DCT
|
|
||||||
id: setup-dct
|
|
||||||
uses: bitwarden/gh-actions/setup-docker-trust@a30e9c3d658dc97c4c2e61ec749fdab64b83386c
|
|
||||||
with:
|
|
||||||
azure-creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
|
||||||
azure-keyvault-name: "bitwarden-ci"
|
|
||||||
|
|
||||||
- name: Pull branch image
|
|
||||||
run: |
|
|
||||||
if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then
|
|
||||||
docker pull bitwarden/web:latest
|
|
||||||
else
|
|
||||||
docker pull bitwarden/web:$_BRANCH_NAME
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Docker Tag version
|
|
||||||
run: |
|
|
||||||
if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then
|
|
||||||
docker tag bitwarden/web:latest bitwarden/web:$_RELEASE_VERSION
|
|
||||||
else
|
|
||||||
docker tag bitwarden/web:$_BRANCH_NAME bitwarden/web:$_RELEASE_VERSION
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Docker Push version
|
|
||||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
|
||||||
env:
|
|
||||||
DOCKER_CONTENT_TRUST: 1
|
|
||||||
DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: ${{ steps.setup-dct.outputs.dct-delegate-repo-passphrase }}
|
|
||||||
run: docker push bitwarden/web:$_RELEASE_VERSION
|
|
||||||
|
|
||||||
- name: Log out of Docker and disable Docker Notary
|
|
||||||
run: |
|
|
||||||
docker logout
|
|
||||||
echo "DOCKER_CONTENT_TRUST=0" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
########## ACR ##########
|
########## ACR ##########
|
||||||
- name: Login to Azure - PROD Subscription
|
- name: Login to Azure - PROD Subscription
|
||||||
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
|
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
|
||||||
@@ -112,38 +78,46 @@ jobs:
|
|||||||
- name: Login to Azure ACR
|
- name: Login to Azure ACR
|
||||||
run: az acr login -n bitwardenprod
|
run: az acr login -n bitwardenprod
|
||||||
|
|
||||||
- name: Tag version
|
- name: Pull branch image
|
||||||
env:
|
|
||||||
REGISTRY: bitwardenprod.azurecr.io
|
|
||||||
run: |
|
run: |
|
||||||
if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then
|
if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then
|
||||||
docker tag bitwarden/web:latest $REGISTRY/web:$_RELEASE_VERSION
|
docker pull $_AZ_REGISTRY/web:latest
|
||||||
|
|
||||||
docker tag bitwarden/web:latest $REGISTRY/web-sh:$_RELEASE_VERSION
|
|
||||||
else
|
else
|
||||||
docker tag bitwarden/web:$_BRANCH_NAME $REGISTRY/web:$_RELEASE_VERSION
|
docker pull $_AZ_REGISTRY/web:$_BRANCH_NAME
|
||||||
|
fi
|
||||||
|
|
||||||
docker tag bitwarden/web:$_BRANCH_NAME $REGISTRY/web-sh:$_RELEASE_VERSION
|
- name: Tag version
|
||||||
|
run: |
|
||||||
|
if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then
|
||||||
|
docker tag $_AZ_REGISTRY/web:latest $_AZ_REGISTRY/web:dryrun
|
||||||
|
docker tag $_AZ_REGISTRY/web:latest $_AZ_REGISTRY/web-sh:dryrun
|
||||||
|
else
|
||||||
|
docker tag $_AZ_REGISTRY/web:$_BRANCH_NAME $_AZ_REGISTRY/web:$_RELEASE_VERSION
|
||||||
|
docker tag $_AZ_REGISTRY/web:$_BRANCH_NAME $_AZ_REGISTRY/web-sh:$_RELEASE_VERSION
|
||||||
|
docker tag $_AZ_REGISTRY/web:$_BRANCH_NAME $_AZ_REGISTRY/web:latest
|
||||||
|
docker tag $_AZ_REGISTRY/web:$_BRANCH_NAME $_AZ_REGISTRY/web-sh:latest
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Push version
|
- name: Push version
|
||||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
|
||||||
env:
|
|
||||||
REGISTRY: bitwardenprod.azurecr.io
|
|
||||||
run: |
|
run: |
|
||||||
docker push $REGISTRY/web:$_RELEASE_VERSION
|
if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then
|
||||||
|
docker push $_AZ_REGISTRY/web:dryrun
|
||||||
docker push $REGISTRY/web-sh:$_RELEASE_VERSION
|
docker push $_AZ_REGISTRY/web-sh:dryrun
|
||||||
|
else
|
||||||
|
docker push $_AZ_REGISTRY/web:$_RELEASE_VERSION
|
||||||
|
docker push $_AZ_REGISTRY/web-sh:$_RELEASE_VERSION
|
||||||
|
docker push $_AZ_REGISTRY/web:latest
|
||||||
|
docker push $_AZ_REGISTRY/web-sh:latest
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Log out of Docker
|
- name: Log out of Docker
|
||||||
run: docker logout
|
run: docker logout
|
||||||
|
|
||||||
|
|
||||||
ghpages-deploy:
|
ghpages-deploy:
|
||||||
name: Deploy to GitHub Pages
|
name: Create Deploy PR for GitHub Pages
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
needs:
|
needs: setup
|
||||||
- setup
|
|
||||||
env:
|
env:
|
||||||
_RELEASE_VERSION: ${{ needs.setup.outputs.release_version }}
|
_RELEASE_VERSION: ${{ needs.setup.outputs.release_version }}
|
||||||
_TAG_VERSION: ${{ needs.setup.outputs.tag_version }}
|
_TAG_VERSION: ${{ needs.setup.outputs.tag_version }}
|
||||||
@@ -233,7 +207,7 @@ jobs:
|
|||||||
|
|
||||||
release:
|
release:
|
||||||
name: Create GitHub Release
|
name: Create GitHub Release
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
needs:
|
needs:
|
||||||
- setup
|
- setup
|
||||||
- self-host
|
- self-host
|
||||||
|
|||||||
8
.vscode/settings.json
vendored
8
.vscode/settings.json
vendored
@@ -1,3 +1,9 @@
|
|||||||
{
|
{
|
||||||
"cSpell.words": ["Csprng", "decryptable", "Popout", "Reprompt", "takeuntil"]
|
"cSpell.words": ["Csprng", "decryptable", "Popout", "Reprompt", "takeuntil"],
|
||||||
|
"search.exclude": {
|
||||||
|
"**/locales/[^e]*/messages.json": true,
|
||||||
|
"**/locales/*[^n]/messages.json": true,
|
||||||
|
"**/_locales/[^e]*/messages.json": true,
|
||||||
|
"**/_locales/*[^n]/messages.json": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@bitwarden/browser",
|
"name": "@bitwarden/browser",
|
||||||
"version": "2023.7.1",
|
"version": "2023.8.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack",
|
"build": "webpack",
|
||||||
"build:mv3": "cross-env MANIFEST_VERSION=3 webpack",
|
"build:mv3": "cross-env MANIFEST_VERSION=3 webpack",
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "استعادة العنصر"
|
"message": "استعادة العنصر"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "هل أنت متأكد من أنك تريد استعادة هذا العنصر؟"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "تم استعادة العنصر"
|
"message": "تم استعادة العنصر"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Elementi bərpa et"
|
"message": "Elementi bərpa et"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Elementi bərpa etmək istədiyinizə əminsiniz?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Element bərpa edildi"
|
"message": "Element bərpa edildi"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Аднавіць элемент"
|
"message": "Аднавіць элемент"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Вы сапраўды хочаце аднавіць гэты элемент?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Элемент адноўлены"
|
"message": "Элемент адноўлены"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Възстановяване на запис"
|
"message": "Възстановяване на запис"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Сигурни ли сте, че искате да възстановите записа?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Записът е възстановен"
|
"message": "Записът е възстановен"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "বস্তু পুনরুদ্ধার"
|
"message": "বস্তু পুনরুদ্ধার"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "আপনি কি নিশ্চিত যে আপনি এই বস্তুটি পুনরুদ্ধার করতে চান?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "বস্তু পুনরুদ্ধারকৃত"
|
"message": "বস্তু পুনরুদ্ধারকৃত"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Restore item"
|
"message": "Restore item"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Are you sure you want to restore this item?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Item restored"
|
"message": "Item restored"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Restaura l'element"
|
"message": "Restaura l'element"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Esteu segur que voleu restaurar aquest element?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Element restaurat"
|
"message": "Element restaurat"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Obnovit položku"
|
"message": "Obnovit položku"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Opravdu chcete tuto položku obnovit?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Položka byla obnovena"
|
"message": "Položka byla obnovena"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Adfer yr eitem"
|
"message": "Adfer yr eitem"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Are you sure you want to restore this item?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Item restored"
|
"message": "Item restored"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Gendan element"
|
"message": "Gendan element"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Er du sikker på, at du vil gendanne dette element?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Element gendannet"
|
"message": "Element gendannet"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Eintrag wiederherstellen"
|
"message": "Eintrag wiederherstellen"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Soll dieser Eintrag wirklich wiederhergestellt werden?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Eintrag wiederhergestellt"
|
"message": "Eintrag wiederhergestellt"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Ανάκτηση Στοιχείου"
|
"message": "Ανάκτηση Στοιχείου"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Είστε βέβαιοι ότι θέλετε να ανακτήσετε αυτό το στοιχείο;"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Στοιχείο που έχει Ανακτηθεί"
|
"message": "Στοιχείο που έχει Ανακτηθεί"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -338,6 +338,9 @@
|
|||||||
"other": {
|
"other": {
|
||||||
"message": "Other"
|
"message": "Other"
|
||||||
},
|
},
|
||||||
|
"unlockMethodNeededToChangeTimeoutActionDesc": {
|
||||||
|
"message": "Set up an unlock method to change your vault timeout action."
|
||||||
|
},
|
||||||
"rateExtension": {
|
"rateExtension": {
|
||||||
"message": "Rate the extension"
|
"message": "Rate the extension"
|
||||||
},
|
},
|
||||||
@@ -1449,9 +1452,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Restore item"
|
"message": "Restore item"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Are you sure you want to restore this item?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Item restored"
|
"message": "Item restored"
|
||||||
},
|
},
|
||||||
@@ -1608,6 +1608,12 @@
|
|||||||
"biometricsNotSupportedDesc": {
|
"biometricsNotSupportedDesc": {
|
||||||
"message": "Browser biometrics is not supported on this device."
|
"message": "Browser biometrics is not supported on this device."
|
||||||
},
|
},
|
||||||
|
"biometricsFailedTitle": {
|
||||||
|
"message": "Biometrics failed"
|
||||||
|
},
|
||||||
|
"biometricsFailedDesc": {
|
||||||
|
"message": "Biometrics cannot be completed, consider using a master password or logging out. If this persists, please contact Bitwarden support."
|
||||||
|
},
|
||||||
"nativeMessaginPermissionErrorTitle": {
|
"nativeMessaginPermissionErrorTitle": {
|
||||||
"message": "Permission not provided"
|
"message": "Permission not provided"
|
||||||
},
|
},
|
||||||
@@ -2158,8 +2164,8 @@
|
|||||||
"notificationSentDevice": {
|
"notificationSentDevice": {
|
||||||
"message": "A notification has been sent to your device."
|
"message": "A notification has been sent to your device."
|
||||||
},
|
},
|
||||||
"logInInitiated": {
|
"loginInitiated": {
|
||||||
"message": "Log in initiated"
|
"message": "Login initiated"
|
||||||
},
|
},
|
||||||
"exposedMasterPassword": {
|
"exposedMasterPassword": {
|
||||||
"message": "Exposed Master Password"
|
"message": "Exposed Master Password"
|
||||||
@@ -2245,6 +2251,31 @@
|
|||||||
"opensInANewWindow": {
|
"opensInANewWindow": {
|
||||||
"message": "Opens in a new window"
|
"message": "Opens in a new window"
|
||||||
},
|
},
|
||||||
|
"deviceApprovalRequired": {
|
||||||
|
"message": "Device approval required. Select an approval option below:"
|
||||||
|
},
|
||||||
|
"rememberThisDevice": {
|
||||||
|
"message": "Remember this device"
|
||||||
|
},
|
||||||
|
"uncheckIfPublicDevice": {
|
||||||
|
"message": "Uncheck if using a public device"
|
||||||
|
},
|
||||||
|
"approveFromYourOtherDevice": {
|
||||||
|
"message": "Approve from your other device"
|
||||||
|
},
|
||||||
|
"requestAdminApproval": {
|
||||||
|
"message": "Request admin approval"
|
||||||
|
},
|
||||||
|
"approveWithMasterPassword": {
|
||||||
|
"message": "Approve with master password"
|
||||||
|
},
|
||||||
|
"ssoIdentifierRequired": {
|
||||||
|
"message": "Organization SSO identifier is required."
|
||||||
|
},
|
||||||
|
"eu": {
|
||||||
|
"message": "EU",
|
||||||
|
"description": "European Union"
|
||||||
|
},
|
||||||
"usDomain": {
|
"usDomain": {
|
||||||
"message": "bitwarden.com"
|
"message": "bitwarden.com"
|
||||||
},
|
},
|
||||||
@@ -2260,6 +2291,134 @@
|
|||||||
"display": {
|
"display": {
|
||||||
"message": "Display"
|
"message": "Display"
|
||||||
},
|
},
|
||||||
|
"accountSuccessfullyCreated": {
|
||||||
|
"message": "Account successfully created!"
|
||||||
|
},
|
||||||
|
"adminApprovalRequested": {
|
||||||
|
"message": "Admin approval requested"
|
||||||
|
},
|
||||||
|
"adminApprovalRequestSentToAdmins": {
|
||||||
|
"message": "Your request has been sent to your admin."
|
||||||
|
},
|
||||||
|
"youWillBeNotifiedOnceApproved": {
|
||||||
|
"message": "You will be notified once approved."
|
||||||
|
},
|
||||||
|
"troubleLoggingIn": {
|
||||||
|
"message": "Trouble logging in?"
|
||||||
|
},
|
||||||
|
"loginApproved": {
|
||||||
|
"message": "Login approved"
|
||||||
|
},
|
||||||
|
"userEmailMissing": {
|
||||||
|
"message": "User email missing"
|
||||||
|
},
|
||||||
|
"deviceTrusted": {
|
||||||
|
"message": "Device trusted"
|
||||||
|
},
|
||||||
|
"inputRequired": {
|
||||||
|
"message": "Input is required."
|
||||||
|
},
|
||||||
|
"required": {
|
||||||
|
"message": "required"
|
||||||
|
},
|
||||||
|
"search": {
|
||||||
|
"message": "Search"
|
||||||
|
},
|
||||||
|
"inputMinLength": {
|
||||||
|
"message": "Input must be at least $COUNT$ characters long.",
|
||||||
|
"placeholders": {
|
||||||
|
"count": {
|
||||||
|
"content": "$1",
|
||||||
|
"example": "8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inputMaxLength": {
|
||||||
|
"message": "Input must not exceed $COUNT$ characters in length.",
|
||||||
|
"placeholders": {
|
||||||
|
"count": {
|
||||||
|
"content": "$1",
|
||||||
|
"example": "20"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inputForbiddenCharacters": {
|
||||||
|
"message": "The following characters are not allowed: $CHARACTERS$",
|
||||||
|
"placeholders": {
|
||||||
|
"characters": {
|
||||||
|
"content": "$1",
|
||||||
|
"example": "@, #, $, %"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inputMinValue": {
|
||||||
|
"message": "Input value must be at least $MIN$.",
|
||||||
|
"placeholders": {
|
||||||
|
"min": {
|
||||||
|
"content": "$1",
|
||||||
|
"example": "8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inputMaxValue": {
|
||||||
|
"message": "Input value must not exceed $MAX$.",
|
||||||
|
"placeholders": {
|
||||||
|
"max": {
|
||||||
|
"content": "$1",
|
||||||
|
"example": "100"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"multipleInputEmails": {
|
||||||
|
"message": "1 or more emails are invalid"
|
||||||
|
},
|
||||||
|
"inputTrimValidator": {
|
||||||
|
"message": "Input must not contain only whitespace.",
|
||||||
|
"description": "Notification to inform the user that a form's input can't contain only whitespace."
|
||||||
|
},
|
||||||
|
"inputEmail": {
|
||||||
|
"message": "Input is not an email address."
|
||||||
|
},
|
||||||
|
"fieldsNeedAttention": {
|
||||||
|
"message": "$COUNT$ field(s) above need your attention.",
|
||||||
|
"placeholders": {
|
||||||
|
"count": {
|
||||||
|
"content": "$1",
|
||||||
|
"example": "4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"selectPlaceholder": {
|
||||||
|
"message": "-- Select --"
|
||||||
|
},
|
||||||
|
"multiSelectPlaceholder": {
|
||||||
|
"message": "-- Type to filter --"
|
||||||
|
},
|
||||||
|
"multiSelectLoading": {
|
||||||
|
"message": "Retrieving options..."
|
||||||
|
},
|
||||||
|
"multiSelectNotFound": {
|
||||||
|
"message": "No items found"
|
||||||
|
},
|
||||||
|
"multiSelectClearAll": {
|
||||||
|
"message": "Clear all"
|
||||||
|
},
|
||||||
|
"plusNMore": {
|
||||||
|
"message": "+ $QUANTITY$ more",
|
||||||
|
"placeholders": {
|
||||||
|
"quantity": {
|
||||||
|
"content": "$1",
|
||||||
|
"example": "5"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"submenu": {
|
||||||
|
"message": "Submenu"
|
||||||
|
},
|
||||||
|
"toggleCollapse": {
|
||||||
|
"message": "Toggle collapse",
|
||||||
|
"description": "Toggling an expand/collapse state."
|
||||||
|
},
|
||||||
"loginPasskey": {
|
"loginPasskey": {
|
||||||
"message": "This login uses a passkey"
|
"message": "This login uses a passkey"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Restore item"
|
"message": "Restore item"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Are you sure you want to restore this item?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Item restored"
|
"message": "Item restored"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Restore item"
|
"message": "Restore item"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Are you sure you want to restore this item?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Restored item"
|
"message": "Restored item"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Restaurar elemento"
|
"message": "Restaurar elemento"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "¿Estás seguro de que quieres restaurar este elemento?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Elemento restaurado"
|
"message": "Elemento restaurado"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Taasta kirje"
|
"message": "Taasta kirje"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Oled kindel, et soovid selle kirje taastada?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Kirje on taastatud"
|
"message": "Kirje on taastatud"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Berreskuratu elementua"
|
"message": "Berreskuratu elementua"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Ziur zaude elementu hau berreskuratu nahi duzula?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Elementua berreskuratua"
|
"message": "Elementua berreskuratua"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "بازیابی مورد"
|
"message": "بازیابی مورد"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "آیا مطمئن هستید که میخواهید این مورد را بازیابی کنید؟"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "مورد بازیابی شد"
|
"message": "مورد بازیابی شد"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Palauta kohde"
|
"message": "Palauta kohde"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Haluatko varmasti palauttaa kohteen?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Kohde palautettiin"
|
"message": "Kohde palautettiin"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Ibalik ang item"
|
"message": "Ibalik ang item"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Sigurado ka bang nais mong ibalik ang item na ito?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Item na nai-restore"
|
"message": "Item na nai-restore"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Restaurer l'élément"
|
"message": "Restaurer l'élément"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Êtes-vous sûr de vouloir restaurer cet élément ?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Élément restauré"
|
"message": "Élément restauré"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Restore item"
|
"message": "Restore item"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Are you sure you want to restore this item?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Item restored"
|
"message": "Item restored"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "שחזר פריט"
|
"message": "שחזר פריט"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "האם אתה בטוח שברצונך לשחזר פריט זה?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "פריט ששוחזר"
|
"message": "פריט ששוחזר"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "आइटम बहाल करें"
|
"message": "आइटम बहाल करें"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "क्या आप सुनिश्चित हैं कि आप इस आइटम को बहाल करना चाहते हैं?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "बहाल आइटम"
|
"message": "बहाल आइटम"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Vrati stavku"
|
"message": "Vrati stavku"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Sigurno želiš vratiti ovu stavku?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Stavka vraćena"
|
"message": "Stavka vraćena"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Elem visszaállítása"
|
"message": "Elem visszaállítása"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Biztosan visszaállításra kerüljön ezt az elem?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Visszaállított elem"
|
"message": "Visszaállított elem"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Pulihkan Item"
|
"message": "Pulihkan Item"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Apakah Anda yakin ingin memulihkan item ini?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Item Yang Dipulihkan"
|
"message": "Item Yang Dipulihkan"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Ripristina elemento"
|
"message": "Ripristina elemento"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Sei sicuro di voler ripristinare questo elemento?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Elemento ripristinato"
|
"message": "Elemento ripristinato"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "アイテムをリストア"
|
"message": "アイテムをリストア"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "このアイテムをリストアしますか?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "リストアされたアイテム"
|
"message": "リストアされたアイテム"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Restore item"
|
"message": "Restore item"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Are you sure you want to restore this item?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Item restored"
|
"message": "Item restored"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Restore item"
|
"message": "Restore item"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Are you sure you want to restore this item?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Item restored"
|
"message": "Item restored"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "ಐಟಂ ಅನ್ನು ಮರುಸ್ಥಾಪಿಸಿ"
|
"message": "ಐಟಂ ಅನ್ನು ಮರುಸ್ಥಾಪಿಸಿ"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "ಈ ಐಟಂ ಅನ್ನು ಮರುಸ್ಥಾಪಿಸಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "ಐಟಂ ಅನ್ನು ಮರುಸ್ಥಾಪಿಸಲಾಗಿದೆ"
|
"message": "ಐಟಂ ಅನ್ನು ಮರುಸ್ಥಾಪಿಸಲಾಗಿದೆ"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "항목 복원"
|
"message": "항목 복원"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "정말 이 항목을 복원하시겠습니까?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "복원된 항목"
|
"message": "복원된 항목"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Atkurti elementą"
|
"message": "Atkurti elementą"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Are you sure you want to restore this item?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Elementas atkurtas"
|
"message": "Elementas atkurtas"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Atjaunot vienumu"
|
"message": "Atjaunot vienumu"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Jūs tiešām atjaunot šo vienumu?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Vienums atjaunots"
|
"message": "Vienums atjaunots"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "ഇനം വീണ്ടെടുക്കുക "
|
"message": "ഇനം വീണ്ടെടുക്കുക "
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "ഈ ഇനം വീണ്ടെടുക്കണമെന്ന് ഉറപ്പാണോ?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "വീണ്ടെടുത്ത ഇനം"
|
"message": "വീണ്ടെടുത്ത ഇനം"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Restore item"
|
"message": "Restore item"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Are you sure you want to restore this item?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Item restored"
|
"message": "Item restored"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Restore item"
|
"message": "Restore item"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Are you sure you want to restore this item?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Item restored"
|
"message": "Item restored"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Gjenopprett objekt"
|
"message": "Gjenopprett objekt"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Er du sikker på at du vil gjenopprette dette elementet?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Gjenopprettet objekt"
|
"message": "Gjenopprettet objekt"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Restore item"
|
"message": "Restore item"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Are you sure you want to restore this item?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Item restored"
|
"message": "Item restored"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Item herstellen"
|
"message": "Item herstellen"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Weet je zeker dat je dit item wilt herstellen?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Hersteld item"
|
"message": "Hersteld item"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Restore item"
|
"message": "Restore item"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Are you sure you want to restore this item?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Item restored"
|
"message": "Item restored"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Restore item"
|
"message": "Restore item"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Are you sure you want to restore this item?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Item restored"
|
"message": "Item restored"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Przywróć element"
|
"message": "Przywróć element"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Czy na pewno chcesz przywrócić ten element?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Element został przywrócony"
|
"message": "Element został przywrócony"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Restaurar Item"
|
"message": "Restaurar Item"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Você tem certeza que deseja restaurar esse item?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Item Restaurado"
|
"message": "Item Restaurado"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Restaurar item"
|
"message": "Restaurar item"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Tem a certeza de que pretende restaurar este item?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Item restaurado"
|
"message": "Item restaurado"
|
||||||
},
|
},
|
||||||
@@ -2129,7 +2126,7 @@
|
|||||||
"message": "Iniciar sessão com o dispositivo"
|
"message": "Iniciar sessão com o dispositivo"
|
||||||
},
|
},
|
||||||
"loginWithDeviceEnabledInfo": {
|
"loginWithDeviceEnabledInfo": {
|
||||||
"message": "O início de sessão com o dispositivo deve ser ativado nas definições da aplicação Bitwarden. Necessita de outra opção?"
|
"message": "O início de sessão com o dispositivo deve ser ativado nas definições da aplicação Bitwarden. Precisa de outra opção?"
|
||||||
},
|
},
|
||||||
"fingerprintPhraseHeader": {
|
"fingerprintPhraseHeader": {
|
||||||
"message": "Frase de impressão digital"
|
"message": "Frase de impressão digital"
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Restabilire articol"
|
"message": "Restabilire articol"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Sigur doriți să restabiliți acest articol?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Articol restabilit"
|
"message": "Articol restabilit"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -631,7 +631,7 @@
|
|||||||
"message": "Обновить"
|
"message": "Обновить"
|
||||||
},
|
},
|
||||||
"notificationUnlockDesc": {
|
"notificationUnlockDesc": {
|
||||||
"message": "Разблокируйте свое хранилище Bitwarden для завершения запроса автозаполнения."
|
"message": "Разблокируйте свое хранилище Bitwarden чтобы выполнить автозаполнение."
|
||||||
},
|
},
|
||||||
"notificationUnlock": {
|
"notificationUnlock": {
|
||||||
"message": "Разблокировать"
|
"message": "Разблокировать"
|
||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Восстановить элемент"
|
"message": "Восстановить элемент"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Вы уверены, что хотите восстановить этот элемент?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Элемент восстановлен"
|
"message": "Элемент восстановлен"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "අයිතමය යළි පිහිටුවන්න"
|
"message": "අයිතමය යළි පිහිටුවන්න"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "ඔබට මෙම අයිතමය යථා තත්වයට පත් කිරීමට අවශ්ය බව ඔබට විශ්වාසද?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "ප්රතිෂ්ඨාපනය අයිතමය"
|
"message": "ප්රතිෂ්ඨාපනය අයිතමය"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Obnoviť položku"
|
"message": "Obnoviť položku"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Naozaj chcete obnoviť túto položku?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Obnovená položka"
|
"message": "Obnovená položka"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Obnovi element"
|
"message": "Obnovi element"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Ste prepričani, da želite obnoviti ta element?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Element obnovljen"
|
"message": "Element obnovljen"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Врати ставку"
|
"message": "Врати ставку"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Да ли сте сигурни да желите да вратите ову ставку?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Ставка враћена"
|
"message": "Ставка враћена"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
"description": "Extension description"
|
"description": "Extension description"
|
||||||
},
|
},
|
||||||
"loginOrCreateNewAccount": {
|
"loginOrCreateNewAccount": {
|
||||||
"message": "Logga in eller skapa ett nytt konto för att komma åt dina lösenord."
|
"message": "Logga in eller skapa ett nytt konto för att komma åt ditt säkra valv."
|
||||||
},
|
},
|
||||||
"createAccount": {
|
"createAccount": {
|
||||||
"message": "Skapa konto"
|
"message": "Skapa konto"
|
||||||
@@ -342,7 +342,7 @@
|
|||||||
"message": "Betygsätt tillägget"
|
"message": "Betygsätt tillägget"
|
||||||
},
|
},
|
||||||
"rateExtensionDesc": {
|
"rateExtensionDesc": {
|
||||||
"message": "Överväg gärna att hjälpa oss genom att ge oss en bra recension!"
|
"message": "Överväg gärna att skriva en recension om oss!"
|
||||||
},
|
},
|
||||||
"browserNotSupportClipboard": {
|
"browserNotSupportClipboard": {
|
||||||
"message": "Din webbläsare har inte stöd för att enkelt kopiera till urklipp. Kopiera till urklipp manuellt istället."
|
"message": "Din webbläsare har inte stöd för att enkelt kopiera till urklipp. Kopiera till urklipp manuellt istället."
|
||||||
@@ -370,7 +370,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"invalidMasterPassword": {
|
"invalidMasterPassword": {
|
||||||
"message": "Felaktigt huvudlösenord"
|
"message": "Ogiltigt huvudlösenord"
|
||||||
},
|
},
|
||||||
"vaultTimeout": {
|
"vaultTimeout": {
|
||||||
"message": "Valvets tidsgräns"
|
"message": "Valvets tidsgräns"
|
||||||
@@ -736,7 +736,7 @@
|
|||||||
"message": "Kopiera verifieringskod"
|
"message": "Kopiera verifieringskod"
|
||||||
},
|
},
|
||||||
"attachments": {
|
"attachments": {
|
||||||
"message": "Bifogade filer"
|
"message": "Bilagor"
|
||||||
},
|
},
|
||||||
"deleteAttachment": {
|
"deleteAttachment": {
|
||||||
"message": "Radera bilaga"
|
"message": "Radera bilaga"
|
||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Återställ objekt"
|
"message": "Återställ objekt"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Är du säker på att du vill återställa detta objekt?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Återställde objekt"
|
"message": "Återställde objekt"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Restore item"
|
"message": "Restore item"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Are you sure you want to restore this item?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Item restored"
|
"message": "Item restored"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "กู้คืนรายการ"
|
"message": "กู้คืนรายการ"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "คุณแน่ใจหรือไม่ว่าต้องการกู้คืนรายการนี้"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "คืนค่ารายการแล้ว"
|
"message": "คืนค่ารายการแล้ว"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Kaydı geri yükle"
|
"message": "Kaydı geri yükle"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Bu kaydı geri yüklemek istediğinizden emin misiniz?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Kayıt geri yüklendi"
|
"message": "Kayıt geri yüklendi"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -631,10 +631,10 @@
|
|||||||
"message": "Оновити"
|
"message": "Оновити"
|
||||||
},
|
},
|
||||||
"notificationUnlockDesc": {
|
"notificationUnlockDesc": {
|
||||||
"message": "Unlock your Bitwarden vault to complete the auto-fill request."
|
"message": "Розблокуйте своє сховище Bitwarden, щоб завершити запит автозаповнення."
|
||||||
},
|
},
|
||||||
"notificationUnlock": {
|
"notificationUnlock": {
|
||||||
"message": "Unlock"
|
"message": "Розблокувати"
|
||||||
},
|
},
|
||||||
"enableContextMenuItem": {
|
"enableContextMenuItem": {
|
||||||
"message": "Показувати в контекстному меню"
|
"message": "Показувати в контекстному меню"
|
||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Відновити запис"
|
"message": "Відновити запис"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Ви дійсно хочете відновити цей запис?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Запис відновлено"
|
"message": "Запис відновлено"
|
||||||
},
|
},
|
||||||
@@ -2228,7 +2225,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"loggingInOn": {
|
"loggingInOn": {
|
||||||
"message": "Logging in on"
|
"message": "Увійти на"
|
||||||
},
|
},
|
||||||
"opensInANewWindow": {
|
"opensInANewWindow": {
|
||||||
"message": "Відкривається у новому вікні"
|
"message": "Відкривається у новому вікні"
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "Khôi phục mục"
|
"message": "Khôi phục mục"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "Bạn có chắc chắn muốn khôi phục mục này không?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "Mục đã được khôi phục"
|
"message": "Mục đã được khôi phục"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "恢复项目"
|
"message": "恢复项目"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "您确定要恢复此项目吗?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "项目已恢复"
|
"message": "项目已恢复"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1446,9 +1446,6 @@
|
|||||||
"restoreItem": {
|
"restoreItem": {
|
||||||
"message": "還原項目"
|
"message": "還原項目"
|
||||||
},
|
},
|
||||||
"restoreItemConfirmation": {
|
|
||||||
"message": "您確定要還原此項目嗎?"
|
|
||||||
},
|
|
||||||
"restoredItem": {
|
"restoredItem": {
|
||||||
"message": "項目已還原"
|
"message": "項目已還原"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { AuthRequestCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-crypto.service.abstraction";
|
||||||
|
import { AuthRequestCryptoServiceImplementation } from "@bitwarden/common/auth/services/auth-request-crypto.service.implementation";
|
||||||
|
|
||||||
|
import {
|
||||||
|
CryptoServiceInitOptions,
|
||||||
|
cryptoServiceFactory,
|
||||||
|
} from "../../../platform/background/service-factories/crypto-service.factory";
|
||||||
|
import {
|
||||||
|
CachedServices,
|
||||||
|
FactoryOptions,
|
||||||
|
factory,
|
||||||
|
} from "../../../platform/background/service-factories/factory-options";
|
||||||
|
|
||||||
|
type AuthRequestCryptoServiceFactoryOptions = FactoryOptions;
|
||||||
|
|
||||||
|
export type AuthRequestCryptoServiceInitOptions = AuthRequestCryptoServiceFactoryOptions &
|
||||||
|
CryptoServiceInitOptions;
|
||||||
|
|
||||||
|
export function authRequestCryptoServiceFactory(
|
||||||
|
cache: { authRequestCryptoService?: AuthRequestCryptoServiceAbstraction } & CachedServices,
|
||||||
|
opts: AuthRequestCryptoServiceInitOptions
|
||||||
|
): Promise<AuthRequestCryptoServiceAbstraction> {
|
||||||
|
return factory(
|
||||||
|
cache,
|
||||||
|
"authRequestCryptoService",
|
||||||
|
opts,
|
||||||
|
async () => new AuthRequestCryptoServiceImplementation(await cryptoServiceFactory(cache, opts))
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -52,6 +52,14 @@ import {
|
|||||||
PasswordStrengthServiceInitOptions,
|
PasswordStrengthServiceInitOptions,
|
||||||
} from "../../../tools/background/service_factories/password-strength-service.factory";
|
} from "../../../tools/background/service_factories/password-strength-service.factory";
|
||||||
|
|
||||||
|
import {
|
||||||
|
authRequestCryptoServiceFactory,
|
||||||
|
AuthRequestCryptoServiceInitOptions,
|
||||||
|
} from "./auth-request-crypto-service.factory";
|
||||||
|
import {
|
||||||
|
deviceTrustCryptoServiceFactory,
|
||||||
|
DeviceTrustCryptoServiceInitOptions,
|
||||||
|
} from "./device-trust-crypto-service.factory";
|
||||||
import {
|
import {
|
||||||
keyConnectorServiceFactory,
|
keyConnectorServiceFactory,
|
||||||
KeyConnectorServiceInitOptions,
|
KeyConnectorServiceInitOptions,
|
||||||
@@ -75,7 +83,9 @@ export type AuthServiceInitOptions = AuthServiceFactoyOptions &
|
|||||||
I18nServiceInitOptions &
|
I18nServiceInitOptions &
|
||||||
EncryptServiceInitOptions &
|
EncryptServiceInitOptions &
|
||||||
PolicyServiceInitOptions &
|
PolicyServiceInitOptions &
|
||||||
PasswordStrengthServiceInitOptions;
|
PasswordStrengthServiceInitOptions &
|
||||||
|
DeviceTrustCryptoServiceInitOptions &
|
||||||
|
AuthRequestCryptoServiceInitOptions;
|
||||||
|
|
||||||
export function authServiceFactory(
|
export function authServiceFactory(
|
||||||
cache: { authService?: AbstractAuthService } & CachedServices,
|
cache: { authService?: AbstractAuthService } & CachedServices,
|
||||||
@@ -101,7 +111,9 @@ export function authServiceFactory(
|
|||||||
await i18nServiceFactory(cache, opts),
|
await i18nServiceFactory(cache, opts),
|
||||||
await encryptServiceFactory(cache, opts),
|
await encryptServiceFactory(cache, opts),
|
||||||
await passwordStrengthServiceFactory(cache, opts),
|
await passwordStrengthServiceFactory(cache, opts),
|
||||||
await policyServiceFactory(cache, opts)
|
await policyServiceFactory(cache, opts),
|
||||||
|
await deviceTrustCryptoServiceFactory(cache, opts),
|
||||||
|
await authRequestCryptoServiceFactory(cache, opts)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
||||||
|
import { DeviceTrustCryptoService } from "@bitwarden/common/auth/services/device-trust-crypto.service.implementation";
|
||||||
|
|
||||||
|
import {
|
||||||
|
DevicesApiServiceInitOptions,
|
||||||
|
devicesApiServiceFactory,
|
||||||
|
} from "../../../background/service-factories/devices-api-service.factory";
|
||||||
|
import {
|
||||||
|
AppIdServiceInitOptions,
|
||||||
|
appIdServiceFactory,
|
||||||
|
} from "../../../platform/background/service-factories/app-id-service.factory";
|
||||||
|
import {
|
||||||
|
CryptoFunctionServiceInitOptions,
|
||||||
|
cryptoFunctionServiceFactory,
|
||||||
|
} from "../../../platform/background/service-factories/crypto-function-service.factory";
|
||||||
|
import {
|
||||||
|
CryptoServiceInitOptions,
|
||||||
|
cryptoServiceFactory,
|
||||||
|
} from "../../../platform/background/service-factories/crypto-service.factory";
|
||||||
|
import {
|
||||||
|
EncryptServiceInitOptions,
|
||||||
|
encryptServiceFactory,
|
||||||
|
} from "../../../platform/background/service-factories/encrypt-service.factory";
|
||||||
|
import {
|
||||||
|
CachedServices,
|
||||||
|
FactoryOptions,
|
||||||
|
factory,
|
||||||
|
} from "../../../platform/background/service-factories/factory-options";
|
||||||
|
import {
|
||||||
|
I18nServiceInitOptions,
|
||||||
|
i18nServiceFactory,
|
||||||
|
} from "../../../platform/background/service-factories/i18n-service.factory";
|
||||||
|
import {
|
||||||
|
PlatformUtilsServiceInitOptions,
|
||||||
|
platformUtilsServiceFactory,
|
||||||
|
} from "../../../platform/background/service-factories/platform-utils-service.factory";
|
||||||
|
import {
|
||||||
|
StateServiceInitOptions,
|
||||||
|
stateServiceFactory,
|
||||||
|
} from "../../../platform/background/service-factories/state-service.factory";
|
||||||
|
|
||||||
|
type DeviceTrustCryptoServiceFactoryOptions = FactoryOptions;
|
||||||
|
|
||||||
|
export type DeviceTrustCryptoServiceInitOptions = DeviceTrustCryptoServiceFactoryOptions &
|
||||||
|
CryptoFunctionServiceInitOptions &
|
||||||
|
CryptoServiceInitOptions &
|
||||||
|
EncryptServiceInitOptions &
|
||||||
|
StateServiceInitOptions &
|
||||||
|
AppIdServiceInitOptions &
|
||||||
|
DevicesApiServiceInitOptions &
|
||||||
|
I18nServiceInitOptions &
|
||||||
|
PlatformUtilsServiceInitOptions;
|
||||||
|
|
||||||
|
export function deviceTrustCryptoServiceFactory(
|
||||||
|
cache: { deviceTrustCryptoService?: DeviceTrustCryptoServiceAbstraction } & CachedServices,
|
||||||
|
opts: DeviceTrustCryptoServiceInitOptions
|
||||||
|
): Promise<DeviceTrustCryptoServiceAbstraction> {
|
||||||
|
return factory(
|
||||||
|
cache,
|
||||||
|
"deviceTrustCryptoService",
|
||||||
|
opts,
|
||||||
|
async () =>
|
||||||
|
new DeviceTrustCryptoService(
|
||||||
|
await cryptoFunctionServiceFactory(cache, opts),
|
||||||
|
await cryptoServiceFactory(cache, opts),
|
||||||
|
await encryptServiceFactory(cache, opts),
|
||||||
|
await stateServiceFactory(cache, opts),
|
||||||
|
await appIdServiceFactory(cache, opts),
|
||||||
|
await devicesApiServiceFactory(cache, opts),
|
||||||
|
await i18nServiceFactory(cache, opts),
|
||||||
|
await platformUtilsServiceFactory(cache, opts)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { UserVerificationApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/user-verification/user-verification-api.service.abstraction";
|
||||||
|
import { UserVerificationApiService } from "@bitwarden/common/auth/services/user-verification/user-verification-api.service";
|
||||||
|
|
||||||
|
import {
|
||||||
|
ApiServiceInitOptions,
|
||||||
|
apiServiceFactory,
|
||||||
|
} from "../../../platform/background/service-factories/api-service.factory";
|
||||||
|
import {
|
||||||
|
FactoryOptions,
|
||||||
|
CachedServices,
|
||||||
|
factory,
|
||||||
|
} from "../../../platform/background/service-factories/factory-options";
|
||||||
|
|
||||||
|
type UserVerificationApiServiceFactoryOptions = FactoryOptions;
|
||||||
|
|
||||||
|
export type UserVerificationApiServiceInitOptions = UserVerificationApiServiceFactoryOptions &
|
||||||
|
ApiServiceInitOptions;
|
||||||
|
|
||||||
|
export function userVerificationApiServiceFactory(
|
||||||
|
cache: { userVerificationApiService?: UserVerificationApiServiceAbstraction } & CachedServices,
|
||||||
|
opts: UserVerificationApiServiceInitOptions
|
||||||
|
): Promise<UserVerificationApiServiceAbstraction> {
|
||||||
|
return factory(
|
||||||
|
cache,
|
||||||
|
"userVerificationApiService",
|
||||||
|
opts,
|
||||||
|
async () => new UserVerificationApiService(await apiServiceFactory(cache, opts))
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import { UserVerificationService as AbstractUserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||||
|
import { UserVerificationService } from "@bitwarden/common/auth/services/user-verification/user-verification.service";
|
||||||
|
|
||||||
|
import {
|
||||||
|
CryptoServiceInitOptions,
|
||||||
|
cryptoServiceFactory,
|
||||||
|
} from "../../../platform/background/service-factories/crypto-service.factory";
|
||||||
|
import {
|
||||||
|
FactoryOptions,
|
||||||
|
CachedServices,
|
||||||
|
factory,
|
||||||
|
} from "../../../platform/background/service-factories/factory-options";
|
||||||
|
import {
|
||||||
|
I18nServiceInitOptions,
|
||||||
|
i18nServiceFactory,
|
||||||
|
} from "../../../platform/background/service-factories/i18n-service.factory";
|
||||||
|
import {
|
||||||
|
StateServiceInitOptions,
|
||||||
|
stateServiceFactory,
|
||||||
|
} from "../../../platform/background/service-factories/state-service.factory";
|
||||||
|
|
||||||
|
import {
|
||||||
|
UserVerificationApiServiceInitOptions,
|
||||||
|
userVerificationApiServiceFactory,
|
||||||
|
} from "./user-verification-api-service.factory";
|
||||||
|
|
||||||
|
type UserVerificationServiceFactoryOptions = FactoryOptions;
|
||||||
|
|
||||||
|
export type UserVerificationServiceInitOptions = UserVerificationServiceFactoryOptions &
|
||||||
|
StateServiceInitOptions &
|
||||||
|
CryptoServiceInitOptions &
|
||||||
|
I18nServiceInitOptions &
|
||||||
|
UserVerificationApiServiceInitOptions;
|
||||||
|
|
||||||
|
export function userVerificationServiceFactory(
|
||||||
|
cache: { userVerificationService?: AbstractUserVerificationService } & CachedServices,
|
||||||
|
opts: UserVerificationServiceInitOptions
|
||||||
|
): Promise<AbstractUserVerificationService> {
|
||||||
|
return factory(
|
||||||
|
cache,
|
||||||
|
"userVerificationService",
|
||||||
|
opts,
|
||||||
|
async () =>
|
||||||
|
new UserVerificationService(
|
||||||
|
await stateServiceFactory(cache, opts),
|
||||||
|
await cryptoServiceFactory(cache, opts),
|
||||||
|
await i18nServiceFactory(cache, opts),
|
||||||
|
await userVerificationApiServiceFactory(cache, opts)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -5,14 +5,20 @@
|
|||||||
<span class="title">{{ "verifyIdentity" | i18n }}</span>
|
<span class="title">{{ "verifyIdentity" | i18n }}</span>
|
||||||
</h1>
|
</h1>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<button type="submit" *ngIf="!hideInput">{{ "unlock" | i18n }}</button>
|
<button type="submit" *ngIf="pinEnabled || masterPasswordEnabled">
|
||||||
|
{{ "unlock" | i18n }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<main tabindex="-1">
|
<main tabindex="-1">
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="box-content">
|
<div class="box-content">
|
||||||
<div class="box-content-row box-content-row-flex" appBoxRow *ngIf="!hideInput">
|
<div
|
||||||
<div class="row-main" *ngIf="pinLock">
|
class="box-content-row box-content-row-flex"
|
||||||
|
appBoxRow
|
||||||
|
*ngIf="pinEnabled || masterPasswordEnabled"
|
||||||
|
>
|
||||||
|
<div class="row-main" *ngIf="pinEnabled">
|
||||||
<label for="pin">{{ "pin" | i18n }}</label>
|
<label for="pin">{{ "pin" | i18n }}</label>
|
||||||
<input
|
<input
|
||||||
id="pin"
|
id="pin"
|
||||||
@@ -24,7 +30,7 @@
|
|||||||
appInputVerbatim
|
appInputVerbatim
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="row-main" *ngIf="!pinLock">
|
<div class="row-main" *ngIf="masterPasswordEnabled && !pinEnabled">
|
||||||
<label for="masterPassword">{{ "masterPass" | i18n }}</label>
|
<label for="masterPassword">{{ "masterPass" | i18n }}</label>
|
||||||
<input
|
<input
|
||||||
id="masterPassword"
|
id="masterPassword"
|
||||||
|
|||||||
@@ -2,14 +2,14 @@ import { Component, NgZone } from "@angular/core";
|
|||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
|
|
||||||
import { LockComponent as BaseLockComponent } from "@bitwarden/angular/auth/components/lock.component";
|
import { LockComponent as BaseLockComponent } from "@bitwarden/angular/auth/components/lock.component";
|
||||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeout.service";
|
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
|
||||||
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeoutSettings.service";
|
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
|
||||||
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
|
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
|
||||||
import { InternalPolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { InternalPolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
||||||
|
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
@@ -19,6 +19,7 @@ import { MessagingService } from "@bitwarden/common/platform/abstractions/messag
|
|||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||||
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
|
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
|
||||||
|
import { DialogService } from "@bitwarden/components";
|
||||||
|
|
||||||
import { BiometricErrors, BiometricErrorTypes } from "../../models/biometricErrors";
|
import { BiometricErrors, BiometricErrorTypes } from "../../models/biometricErrors";
|
||||||
|
|
||||||
@@ -44,14 +45,15 @@ export class LockComponent extends BaseLockComponent {
|
|||||||
stateService: StateService,
|
stateService: StateService,
|
||||||
apiService: ApiService,
|
apiService: ApiService,
|
||||||
logService: LogService,
|
logService: LogService,
|
||||||
keyConnectorService: KeyConnectorService,
|
|
||||||
ngZone: NgZone,
|
ngZone: NgZone,
|
||||||
policyApiService: PolicyApiServiceAbstraction,
|
policyApiService: PolicyApiServiceAbstraction,
|
||||||
policyService: InternalPolicyService,
|
policyService: InternalPolicyService,
|
||||||
passwordStrengthService: PasswordStrengthServiceAbstraction,
|
passwordStrengthService: PasswordStrengthServiceAbstraction,
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
route: ActivatedRoute,
|
route: ActivatedRoute,
|
||||||
dialogService: DialogServiceAbstraction
|
dialogService: DialogService,
|
||||||
|
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
|
||||||
|
userVerificationService: UserVerificationService
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
router,
|
router,
|
||||||
@@ -65,13 +67,14 @@ export class LockComponent extends BaseLockComponent {
|
|||||||
stateService,
|
stateService,
|
||||||
apiService,
|
apiService,
|
||||||
logService,
|
logService,
|
||||||
keyConnectorService,
|
|
||||||
ngZone,
|
ngZone,
|
||||||
policyApiService,
|
policyApiService,
|
||||||
policyService,
|
policyService,
|
||||||
passwordStrengthService,
|
passwordStrengthService,
|
||||||
route,
|
route,
|
||||||
dialogService
|
dialogService,
|
||||||
|
deviceTrustCryptoService,
|
||||||
|
userVerificationService
|
||||||
);
|
);
|
||||||
this.successRoute = "/tabs/current";
|
this.successRoute = "/tabs/current";
|
||||||
this.isInitialLockScreen = (window as any).previousPopupUrl == null;
|
this.isInitialLockScreen = (window as any).previousPopupUrl == null;
|
||||||
@@ -83,7 +86,7 @@ export class LockComponent extends BaseLockComponent {
|
|||||||
(await this.stateService.getDisableAutoBiometricsPrompt()) ?? true;
|
(await this.stateService.getDisableAutoBiometricsPrompt()) ?? true;
|
||||||
|
|
||||||
window.setTimeout(async () => {
|
window.setTimeout(async () => {
|
||||||
document.getElementById(this.pinLock ? "pin" : "masterPassword").focus();
|
document.getElementById(this.pinEnabled ? "pin" : "masterPassword")?.focus();
|
||||||
if (
|
if (
|
||||||
this.biometricLock &&
|
this.biometricLock &&
|
||||||
!disableAutoBiometricsPrompt &&
|
!disableAutoBiometricsPrompt &&
|
||||||
@@ -95,7 +98,7 @@ export class LockComponent extends BaseLockComponent {
|
|||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
async unlockBiometric(): Promise<boolean> {
|
override async unlockBiometric(): Promise<boolean> {
|
||||||
if (!this.biometricLock) {
|
if (!this.biometricLock) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
<div id="login-initiated">
|
||||||
|
<header>
|
||||||
|
<h1 class="margin-auto">
|
||||||
|
<span class="title">{{ "loginInitiated" | i18n }}</span>
|
||||||
|
</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="content login-page">
|
||||||
|
<div class="full-loading-spinner" *ngIf="loading">
|
||||||
|
<i class="bwi bwi-spinner bwi-spin bwi-3x" aria-hidden="true"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ng-container *ngIf="!loading">
|
||||||
|
<ng-container *ngIf="data.state == State.ExistingUserUntrustedDevice">
|
||||||
|
<div class="standard-x-margin">
|
||||||
|
<p class="lead">{{ "loginInitiated" | i18n }}</p>
|
||||||
|
<h6 class="mb-20px">{{ "deviceApprovalRequired" | i18n }}</h6>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form
|
||||||
|
id="rememberDeviceForm"
|
||||||
|
class="mb-20px standard-x-margin"
|
||||||
|
[formGroup]="rememberDeviceForm"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="rememberDevice"
|
||||||
|
name="rememberDevice"
|
||||||
|
formControlName="rememberDevice"
|
||||||
|
/>
|
||||||
|
<label for="rememberDevice">
|
||||||
|
{{ "rememberThisDevice" | i18n }}
|
||||||
|
</label>
|
||||||
|
<p id="rememberThisDeviceHintText">{{ "uncheckIfPublicDevice" | i18n }}</p>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="box mb-20px">
|
||||||
|
<button
|
||||||
|
*ngIf="data.showApproveFromOtherDeviceBtn"
|
||||||
|
(click)="approveFromOtherDevice()"
|
||||||
|
type="button"
|
||||||
|
class="btn primary block"
|
||||||
|
>
|
||||||
|
<b>{{ "approveFromYourOtherDevice" | i18n }}</b>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
*ngIf="data.showReqAdminApprovalBtn"
|
||||||
|
(click)="requestAdminApproval()"
|
||||||
|
type="button"
|
||||||
|
class="btn block btn-top-margin"
|
||||||
|
>
|
||||||
|
{{ "requestAdminApproval" | i18n }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
*ngIf="data.showApproveWithMasterPasswordBtn"
|
||||||
|
type="button"
|
||||||
|
class="btn block btn-top-margin"
|
||||||
|
(click)="approveWithMasterPassword()"
|
||||||
|
>
|
||||||
|
{{ "approveWithMasterPassword" | i18n }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="data.state == State.NewUser">
|
||||||
|
<div class="standard-x-margin">
|
||||||
|
<p class="lead">{{ "loginInitiated" | i18n }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form
|
||||||
|
id="rememberDeviceForm"
|
||||||
|
class="mb-20px standard-x-margin"
|
||||||
|
[formGroup]="rememberDeviceForm"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="rememberDevice"
|
||||||
|
name="rememberDevice"
|
||||||
|
formControlName="rememberDevice"
|
||||||
|
/>
|
||||||
|
<label for="rememberDevice">
|
||||||
|
{{ "rememberThisDevice" | i18n }}
|
||||||
|
</label>
|
||||||
|
<p id="rememberThisDeviceHintText">{{ "uncheckIfPublicDevice" | i18n }}</p>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="box mb-20px">
|
||||||
|
<button (click)="createUser()" type="button" class="btn primary block">
|
||||||
|
<b>{{ "continue" | i18n }}</b>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<hr class="muted-hr mx-5px mb-20px" />
|
||||||
|
|
||||||
|
<div class="small mx-5px">
|
||||||
|
<p class="no-margin">{{ "loggingInAs" | i18n }} {{ data.userEmail }}</p>
|
||||||
|
<a tabindex="0" role="button" style="cursor: pointer" (click)="logOut()">{{
|
||||||
|
"notYou" | i18n
|
||||||
|
}}</a>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { Component } from "@angular/core";
|
||||||
|
|
||||||
|
import { BaseLoginDecryptionOptionsComponent } from "@bitwarden/angular/auth/components/base-login-decryption-options.component";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: "browser-login-decryption-options",
|
||||||
|
templateUrl: "login-decryption-options.component.html",
|
||||||
|
})
|
||||||
|
export class LoginDecryptionOptionsComponent extends BaseLoginDecryptionOptionsComponent {
|
||||||
|
override async createUser(): Promise<void> {
|
||||||
|
try {
|
||||||
|
await super.createUser();
|
||||||
|
await this.router.navigate(["/tabs/vault"]);
|
||||||
|
} catch (error) {
|
||||||
|
this.validationService.showError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,8 +5,9 @@
|
|||||||
</h1>
|
</h1>
|
||||||
</header>
|
</header>
|
||||||
<div class="content login-page">
|
<div class="content login-page">
|
||||||
|
<ng-container *ngIf="state == StateEnum.StandardAuthRequest">
|
||||||
<div>
|
<div>
|
||||||
<p class="lead">{{ "logInInitiated" | i18n }}</p>
|
<p class="lead">{{ "loginInitiated" | i18n }}</p>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<p>{{ "notificationSentDevice" | i18n }}</p>
|
<p>{{ "notificationSentDevice" | i18n }}</p>
|
||||||
@@ -29,8 +30,32 @@
|
|||||||
|
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
{{ "loginWithDeviceEnabledInfo" | i18n }}
|
{{ "loginWithDeviceEnabledInfo" | i18n }}
|
||||||
<a routerLink="/login">{{ "viewAllLoginOptions" | i18n }}</a>
|
<a href="#" (click)="back()">{{ "viewAllLoginOptions" | i18n }}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="state == StateEnum.AdminAuthRequest">
|
||||||
|
<div>
|
||||||
|
<p class="lead">{{ "adminApprovalRequested" | i18n }}</p>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<p>{{ "adminApprovalRequestSentToAdmins" | i18n }}</p>
|
||||||
|
<p>{{ "youWillBeNotifiedOnceApproved" | i18n }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<b class="fingerprint-phrase-header">{{ "fingerprintPhraseHeader" | i18n }}</b>
|
||||||
|
<p class="fingerprint-text">
|
||||||
|
<code>{{ fingerprintPhrase }}</code>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
{{ "troubleLoggingIn" | i18n }}
|
||||||
|
<a routerLink="/login-initiated">{{ "viewAllLoginOptions" | i18n }}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
|
import { Location } from "@angular/common";
|
||||||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||||
import { Router } from "@angular/router";
|
import { Router } from "@angular/router";
|
||||||
|
|
||||||
import { LoginWithDeviceComponent as BaseLoginWithDeviceComponent } from "@bitwarden/angular/auth/components/login-with-device.component";
|
import { LoginWithDeviceComponent as BaseLoginWithDeviceComponent } from "@bitwarden/angular/auth/components/login-with-device.component";
|
||||||
import { AnonymousHubService } from "@bitwarden/common/abstractions/anonymousHub.service";
|
import { AnonymousHubService } from "@bitwarden/common/abstractions/anonymousHub.service";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
|
import { AuthRequestCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-crypto.service.abstraction";
|
||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
|
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
||||||
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||||
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
||||||
@@ -42,7 +45,10 @@ export class LoginWithDeviceComponent
|
|||||||
validationService: ValidationService,
|
validationService: ValidationService,
|
||||||
stateService: StateService,
|
stateService: StateService,
|
||||||
loginService: LoginService,
|
loginService: LoginService,
|
||||||
syncService: SyncService
|
syncService: SyncService,
|
||||||
|
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
|
||||||
|
authReqCryptoService: AuthRequestCryptoServiceAbstraction,
|
||||||
|
private location: Location
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
router,
|
router,
|
||||||
@@ -59,10 +65,16 @@ export class LoginWithDeviceComponent
|
|||||||
anonymousHubService,
|
anonymousHubService,
|
||||||
validationService,
|
validationService,
|
||||||
stateService,
|
stateService,
|
||||||
loginService
|
loginService,
|
||||||
|
deviceTrustCryptoService,
|
||||||
|
authReqCryptoService
|
||||||
);
|
);
|
||||||
super.onSuccessfulLogin = async () => {
|
super.onSuccessfulLogin = async () => {
|
||||||
await syncService.fullSync(true);
|
await syncService.fullSync(true);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected back() {
|
||||||
|
this.location.back();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import { ActivatedRoute, Router } from "@angular/router";
|
|||||||
|
|
||||||
import { LoginComponent as BaseLoginComponent } from "@bitwarden/angular/auth/components/login.component";
|
import { LoginComponent as BaseLoginComponent } from "@bitwarden/angular/auth/components/login.component";
|
||||||
import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service";
|
import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service";
|
||||||
import { DevicesApiServiceAbstraction } from "@bitwarden/common/abstractions/devices/devices-api.service.abstraction";
|
|
||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
|
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
||||||
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||||
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { Router } from "@angular/router";
|
|||||||
|
|
||||||
import { RegisterComponent as BaseRegisterComponent } from "@bitwarden/angular/components/register.component";
|
import { RegisterComponent as BaseRegisterComponent } from "@bitwarden/angular/components/register.component";
|
||||||
import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service";
|
import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service";
|
||||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
@@ -15,6 +14,7 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
|
|||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
||||||
|
import { DialogService } from "@bitwarden/components";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-register",
|
selector: "app-register",
|
||||||
@@ -38,7 +38,7 @@ export class RegisterComponent extends BaseRegisterComponent {
|
|||||||
environmentService: EnvironmentService,
|
environmentService: EnvironmentService,
|
||||||
logService: LogService,
|
logService: LogService,
|
||||||
auditService: AuditService,
|
auditService: AuditService,
|
||||||
dialogService: DialogServiceAbstraction
|
dialogService: DialogService
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
formValidationErrorService,
|
formValidationErrorService,
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
export { LockGuardService } from "./lock-guard.service";
|
|
||||||
export { UnauthGuardService } from "./unauth-guard.service";
|
export { UnauthGuardService } from "./unauth-guard.service";
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
import { Injectable } from "@angular/core";
|
|
||||||
|
|
||||||
import { LockGuard as BaseLockGuardService } from "@bitwarden/angular/auth/guards/lock.guard";
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class LockGuardService extends BaseLockGuardService {
|
|
||||||
protected homepage = "tabs/current";
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Injectable } from "@angular/core";
|
import { Injectable } from "@angular/core";
|
||||||
|
|
||||||
import { UnauthGuard as BaseUnauthGuardService } from "@bitwarden/angular/auth/guards/unauth.guard";
|
import { UnauthGuard as BaseUnauthGuardService } from "@bitwarden/angular/auth/guards";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UnauthGuardService extends BaseUnauthGuardService {
|
export class UnauthGuardService extends BaseUnauthGuardService {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { Component } from "@angular/core";
|
|||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
|
|
||||||
import { SetPasswordComponent as BaseSetPasswordComponent } from "@bitwarden/angular/components/set-password.component";
|
import { SetPasswordComponent as BaseSetPasswordComponent } from "@bitwarden/angular/components/set-password.component";
|
||||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { OrganizationUserService } from "@bitwarden/common/abstractions/organization-user/organization-user.service";
|
import { OrganizationUserService } from "@bitwarden/common/abstractions/organization-user/organization-user.service";
|
||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||||
@@ -15,6 +14,7 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
|
|||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
||||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||||
|
import { DialogService } from "@bitwarden/components";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-set-password",
|
selector: "app-set-password",
|
||||||
@@ -36,7 +36,7 @@ export class SetPasswordComponent extends BaseSetPasswordComponent {
|
|||||||
route: ActivatedRoute,
|
route: ActivatedRoute,
|
||||||
organizationApiService: OrganizationApiServiceAbstraction,
|
organizationApiService: OrganizationApiServiceAbstraction,
|
||||||
organizationUserService: OrganizationUserService,
|
organizationUserService: OrganizationUserService,
|
||||||
dialogService: DialogServiceAbstraction
|
dialogService: DialogService
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
i18nService,
|
i18nService,
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import { Component } from "@angular/core";
|
import { Component, Inject } from "@angular/core";
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
|
|
||||||
import { SsoComponent as BaseSsoComponent } from "@bitwarden/angular/auth/components/sso.component";
|
import { SsoComponent as BaseSsoComponent } from "@bitwarden/angular/auth/components/sso.component";
|
||||||
|
import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeout.service";
|
|
||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||||
|
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
|
||||||
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
||||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
@@ -35,7 +36,8 @@ export class SsoComponent extends BaseSsoComponent {
|
|||||||
syncService: SyncService,
|
syncService: SyncService,
|
||||||
environmentService: EnvironmentService,
|
environmentService: EnvironmentService,
|
||||||
logService: LogService,
|
logService: LogService,
|
||||||
private vaultTimeoutService: VaultTimeoutService
|
configService: ConfigServiceAbstraction,
|
||||||
|
@Inject(WINDOW) private win: Window
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
authService,
|
authService,
|
||||||
@@ -48,7 +50,8 @@ export class SsoComponent extends BaseSsoComponent {
|
|||||||
cryptoFunctionService,
|
cryptoFunctionService,
|
||||||
environmentService,
|
environmentService,
|
||||||
passwordGenerationService,
|
passwordGenerationService,
|
||||||
logService
|
logService,
|
||||||
|
configService
|
||||||
);
|
);
|
||||||
|
|
||||||
const url = this.environmentService.getWebVaultUrl();
|
const url = this.environmentService.getWebVaultUrl();
|
||||||
@@ -57,15 +60,22 @@ export class SsoComponent extends BaseSsoComponent {
|
|||||||
this.clientId = "browser";
|
this.clientId = "browser";
|
||||||
|
|
||||||
super.onSuccessfulLogin = async () => {
|
super.onSuccessfulLogin = async () => {
|
||||||
await syncService.fullSync(true);
|
syncService.fullSync(true);
|
||||||
|
|
||||||
// If the vault is unlocked then this will clear keys from memory, which we don't want to do
|
// If the vault is unlocked then this will clear keys from memory, which we don't want to do
|
||||||
if ((await this.authService.getAuthStatus()) !== AuthenticationStatus.Unlocked) {
|
if ((await this.authService.getAuthStatus()) !== AuthenticationStatus.Unlocked) {
|
||||||
BrowserApi.reloadOpenWindows();
|
BrowserApi.reloadOpenWindows();
|
||||||
}
|
}
|
||||||
|
|
||||||
const thisWindow = window.open("", "_self");
|
this.win.close();
|
||||||
thisWindow.close();
|
};
|
||||||
|
|
||||||
|
super.onSuccessfulLoginTde = async () => {
|
||||||
|
syncService.fullSync(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
super.onSuccessfulLoginTdeNavigate = async () => {
|
||||||
|
this.win.close();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Component } from "@angular/core";
|
import { Component, Inject } from "@angular/core";
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
import { first } from "rxjs/operators";
|
import { first } from "rxjs/operators";
|
||||||
|
|
||||||
import { TwoFactorComponent as BaseTwoFactorComponent } from "@bitwarden/angular/auth/components/two-factor.component";
|
import { TwoFactorComponent as BaseTwoFactorComponent } from "@bitwarden/angular/auth/components/two-factor.component";
|
||||||
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
|
import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
||||||
@@ -11,6 +11,7 @@ import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor
|
|||||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||||
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||||
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
||||||
|
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
|
||||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
@@ -18,6 +19,7 @@ import { MessagingService } from "@bitwarden/common/platform/abstractions/messag
|
|||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||||
|
import { DialogService } from "@bitwarden/components";
|
||||||
|
|
||||||
import { BrowserApi } from "../../platform/browser/browser-api";
|
import { BrowserApi } from "../../platform/browser/browser-api";
|
||||||
import { PopupUtilsService } from "../../popup/services/popup-utils.service";
|
import { PopupUtilsService } from "../../popup/services/popup-utils.service";
|
||||||
@@ -48,7 +50,9 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
|
|||||||
twoFactorService: TwoFactorService,
|
twoFactorService: TwoFactorService,
|
||||||
appIdService: AppIdService,
|
appIdService: AppIdService,
|
||||||
loginService: LoginService,
|
loginService: LoginService,
|
||||||
private dialogService: DialogServiceAbstraction
|
configService: ConfigServiceAbstraction,
|
||||||
|
private dialogService: DialogService,
|
||||||
|
@Inject(WINDOW) protected win: Window
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
authService,
|
authService,
|
||||||
@@ -56,19 +60,28 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
|
|||||||
i18nService,
|
i18nService,
|
||||||
apiService,
|
apiService,
|
||||||
platformUtilsService,
|
platformUtilsService,
|
||||||
window,
|
win,
|
||||||
environmentService,
|
environmentService,
|
||||||
stateService,
|
stateService,
|
||||||
route,
|
route,
|
||||||
logService,
|
logService,
|
||||||
twoFactorService,
|
twoFactorService,
|
||||||
appIdService,
|
appIdService,
|
||||||
loginService
|
loginService,
|
||||||
|
configService
|
||||||
);
|
);
|
||||||
super.onSuccessfulLogin = () => {
|
super.onSuccessfulLogin = async () => {
|
||||||
this.loginService.clearValues();
|
syncService.fullSync(true);
|
||||||
return syncService.fullSync(true);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
super.onSuccessfulLoginTde = async () => {
|
||||||
|
syncService.fullSync(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
super.onSuccessfulLoginTdeNavigate = async () => {
|
||||||
|
this.win.close();
|
||||||
|
};
|
||||||
|
|
||||||
super.successRoute = "/tabs/vault";
|
super.successRoute = "/tabs/vault";
|
||||||
// FIXME: Chromium 110 has broken WebAuthn support in extensions via an iframe
|
// FIXME: Chromium 110 has broken WebAuthn support in extensions via an iframe
|
||||||
this.webAuthnNewTab = true;
|
this.webAuthnNewTab = true;
|
||||||
@@ -107,7 +120,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
|
|||||||
const confirmed = await this.dialogService.openSimpleDialog({
|
const confirmed = await this.dialogService.openSimpleDialog({
|
||||||
title: { key: "warning" },
|
title: { key: "warning" },
|
||||||
content: { key: "popup2faCloseMessage" },
|
content: { key: "popup2faCloseMessage" },
|
||||||
type: SimpleDialogType.WARNING,
|
type: "warning",
|
||||||
});
|
});
|
||||||
if (confirmed) {
|
if (confirmed) {
|
||||||
this.popupUtilsService.popOut(window);
|
this.popupUtilsService.popOut(window);
|
||||||
@@ -117,11 +130,11 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
|
|||||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
||||||
this.route.queryParams.pipe(first()).subscribe(async (qParams) => {
|
this.route.queryParams.pipe(first()).subscribe(async (qParams) => {
|
||||||
if (qParams.sso === "true") {
|
if (qParams.sso === "true") {
|
||||||
super.onSuccessfulLogin = () => {
|
super.onSuccessfulLogin = async () => {
|
||||||
// This is not awaited so we don't pause the application while the sync is happening.
|
// This is not awaited so we don't pause the application while the sync is happening.
|
||||||
// This call is executed by the service that lives in the background script so it will continue
|
// This call is executed by the service that lives in the background script so it will continue
|
||||||
// the sync even if this tab closes.
|
// the sync even if this tab closes.
|
||||||
const syncPromise = this.syncService.fullSync(true);
|
this.syncService.fullSync(true);
|
||||||
|
|
||||||
// Force sidebars (FF && Opera) to reload while exempting current window
|
// Force sidebars (FF && Opera) to reload while exempting current window
|
||||||
// because we are just going to close the current window.
|
// because we are just going to close the current window.
|
||||||
@@ -130,8 +143,6 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
|
|||||||
// We don't need this window anymore because the intent is for the user to be left
|
// We don't need this window anymore because the intent is for the user to be left
|
||||||
// on the web vault screen which tells them to continue in the browser extension (sidebar or popup)
|
// on the web vault screen which tells them to continue in the browser extension (sidebar or popup)
|
||||||
BrowserApi.closeBitwardenExtensionTab();
|
BrowserApi.closeBitwardenExtensionTab();
|
||||||
|
|
||||||
return syncPromise;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,6 +2,10 @@ import {
|
|||||||
TotpServiceInitOptions,
|
TotpServiceInitOptions,
|
||||||
totpServiceFactory,
|
totpServiceFactory,
|
||||||
} from "../../../auth/background/service-factories/totp-service.factory";
|
} from "../../../auth/background/service-factories/totp-service.factory";
|
||||||
|
import {
|
||||||
|
UserVerificationServiceInitOptions,
|
||||||
|
userVerificationServiceFactory,
|
||||||
|
} from "../../../auth/background/service-factories/user-verification-service.factory";
|
||||||
import {
|
import {
|
||||||
EventCollectionServiceInitOptions,
|
EventCollectionServiceInitOptions,
|
||||||
eventCollectionServiceFactory,
|
eventCollectionServiceFactory,
|
||||||
@@ -38,7 +42,8 @@ export type AutoFillServiceInitOptions = AutoFillServiceOptions &
|
|||||||
TotpServiceInitOptions &
|
TotpServiceInitOptions &
|
||||||
EventCollectionServiceInitOptions &
|
EventCollectionServiceInitOptions &
|
||||||
LogServiceInitOptions &
|
LogServiceInitOptions &
|
||||||
SettingsServiceInitOptions;
|
SettingsServiceInitOptions &
|
||||||
|
UserVerificationServiceInitOptions;
|
||||||
|
|
||||||
export function autofillServiceFactory(
|
export function autofillServiceFactory(
|
||||||
cache: { autofillService?: AbstractAutoFillService } & CachedServices,
|
cache: { autofillService?: AbstractAutoFillService } & CachedServices,
|
||||||
@@ -55,7 +60,8 @@ export function autofillServiceFactory(
|
|||||||
await totpServiceFactory(cache, opts),
|
await totpServiceFactory(cache, opts),
|
||||||
await eventCollectionServiceFactory(cache, opts),
|
await eventCollectionServiceFactory(cache, opts),
|
||||||
await logServiceFactory(cache, opts),
|
await logServiceFactory(cache, opts),
|
||||||
await settingsServiceFactory(cache, opts)
|
await settingsServiceFactory(cache, opts),
|
||||||
|
await userVerificationServiceFactory(cache, opts)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { mock, MockProxy } from "jest-mock-extended";
|
import { mock, MockProxy } from "jest-mock-extended";
|
||||||
|
|
||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
|
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type";
|
import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type";
|
||||||
@@ -13,6 +14,7 @@ describe("CipherContextMenuHandler", () => {
|
|||||||
let mainContextMenuHandler: MockProxy<MainContextMenuHandler>;
|
let mainContextMenuHandler: MockProxy<MainContextMenuHandler>;
|
||||||
let authService: MockProxy<AuthService>;
|
let authService: MockProxy<AuthService>;
|
||||||
let cipherService: MockProxy<CipherService>;
|
let cipherService: MockProxy<CipherService>;
|
||||||
|
let userVerificationService: MockProxy<UserVerificationService>;
|
||||||
|
|
||||||
let sut: CipherContextMenuHandler;
|
let sut: CipherContextMenuHandler;
|
||||||
|
|
||||||
@@ -20,10 +22,17 @@ describe("CipherContextMenuHandler", () => {
|
|||||||
mainContextMenuHandler = mock();
|
mainContextMenuHandler = mock();
|
||||||
authService = mock();
|
authService = mock();
|
||||||
cipherService = mock();
|
cipherService = mock();
|
||||||
|
userVerificationService = mock();
|
||||||
|
userVerificationService.hasMasterPassword.mockResolvedValue(true);
|
||||||
|
|
||||||
jest.spyOn(MainContextMenuHandler, "removeAll").mockResolvedValue();
|
jest.spyOn(MainContextMenuHandler, "removeAll").mockResolvedValue();
|
||||||
|
|
||||||
sut = new CipherContextMenuHandler(mainContextMenuHandler, authService, cipherService);
|
sut = new CipherContextMenuHandler(
|
||||||
|
mainContextMenuHandler,
|
||||||
|
authService,
|
||||||
|
cipherService,
|
||||||
|
userVerificationService
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => jest.resetAllMocks());
|
afterEach(() => jest.resetAllMocks());
|
||||||
@@ -83,11 +92,11 @@ describe("CipherContextMenuHandler", () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
cipherService.getAllDecryptedForUrl.mockResolvedValue([
|
cipherService.getAllDecryptedForUrl.mockResolvedValue([
|
||||||
null,
|
null, // invalid cipher
|
||||||
undefined,
|
undefined, // invalid cipher
|
||||||
{ type: CipherType.Card },
|
{ type: CipherType.Card }, // invalid cipher
|
||||||
{ type: CipherType.Login, reprompt: CipherRepromptType.Password },
|
{ type: CipherType.Login, reprompt: CipherRepromptType.Password }, // invalid cipher
|
||||||
realCipher,
|
realCipher, // valid cipher
|
||||||
] as any[]);
|
] as any[]);
|
||||||
|
|
||||||
await sut.update("https://test.com");
|
await sut.update("https://test.com");
|
||||||
@@ -96,7 +105,7 @@ describe("CipherContextMenuHandler", () => {
|
|||||||
|
|
||||||
expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledWith("https://test.com");
|
expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledWith("https://test.com");
|
||||||
|
|
||||||
expect(mainContextMenuHandler.loadOptions).toHaveBeenCalledTimes(1);
|
expect(mainContextMenuHandler.loadOptions).toHaveBeenCalledTimes(2);
|
||||||
|
|
||||||
expect(mainContextMenuHandler.loadOptions).toHaveBeenCalledWith(
|
expect(mainContextMenuHandler.loadOptions).toHaveBeenCalledWith(
|
||||||
"Test Cipher (Test Username)",
|
"Test Cipher (Test Username)",
|
||||||
@@ -105,5 +114,61 @@ describe("CipherContextMenuHandler", () => {
|
|||||||
realCipher
|
realCipher
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("adds ciphers with master password reprompt if the user does not have a master password", async () => {
|
||||||
|
authService.getAuthStatus.mockResolvedValue(AuthenticationStatus.Unlocked);
|
||||||
|
|
||||||
|
// User does not have a master password, or has one but hasn't logged in with it (key connector user or TDE user)
|
||||||
|
userVerificationService.hasMasterPasswordAndMasterKeyHash.mockResolvedValue(false);
|
||||||
|
|
||||||
|
mainContextMenuHandler.init.mockResolvedValue(true);
|
||||||
|
|
||||||
|
const realCipher = {
|
||||||
|
id: "5",
|
||||||
|
type: CipherType.Login,
|
||||||
|
reprompt: CipherRepromptType.None,
|
||||||
|
name: "Test Cipher",
|
||||||
|
login: { username: "Test Username" },
|
||||||
|
};
|
||||||
|
|
||||||
|
const repromptCipher = {
|
||||||
|
id: "6",
|
||||||
|
type: CipherType.Login,
|
||||||
|
reprompt: CipherRepromptType.Password,
|
||||||
|
name: "Test Reprompt Cipher",
|
||||||
|
login: { username: "Test Username" },
|
||||||
|
};
|
||||||
|
|
||||||
|
cipherService.getAllDecryptedForUrl.mockResolvedValue([
|
||||||
|
null, // invalid cipher
|
||||||
|
undefined, // invalid cipher
|
||||||
|
{ type: CipherType.Card }, // invalid cipher
|
||||||
|
repromptCipher, // valid cipher
|
||||||
|
realCipher, // valid cipher
|
||||||
|
] as any[]);
|
||||||
|
|
||||||
|
await sut.update("https://test.com");
|
||||||
|
|
||||||
|
expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledWith("https://test.com");
|
||||||
|
|
||||||
|
// Should call this twice, once for each valid cipher
|
||||||
|
expect(mainContextMenuHandler.loadOptions).toHaveBeenCalledTimes(2);
|
||||||
|
|
||||||
|
expect(mainContextMenuHandler.loadOptions).toHaveBeenCalledWith(
|
||||||
|
"Test Cipher (Test Username)",
|
||||||
|
"5",
|
||||||
|
"https://test.com",
|
||||||
|
realCipher
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(mainContextMenuHandler.loadOptions).toHaveBeenCalledWith(
|
||||||
|
"Test Reprompt Cipher (Test Username)",
|
||||||
|
"6",
|
||||||
|
"https://test.com",
|
||||||
|
repromptCipher
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
|
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||||
import { StateFactory } from "@bitwarden/common/platform/factories/state-factory";
|
import { StateFactory } from "@bitwarden/common/platform/factories/state-factory";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
import { GlobalState } from "@bitwarden/common/platform/models/domain/global-state";
|
import { GlobalState } from "@bitwarden/common/platform/models/domain/global-state";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type";
|
|
||||||
import { CipherType } from "@bitwarden/common/vault/enums/cipher-type";
|
import { CipherType } from "@bitwarden/common/vault/enums/cipher-type";
|
||||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||||
|
|
||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
authServiceFactory,
|
authServiceFactory,
|
||||||
AuthServiceInitOptions,
|
AuthServiceInitOptions,
|
||||||
} from "../../auth/background/service-factories/auth-service.factory";
|
} from "../../auth/background/service-factories/auth-service.factory";
|
||||||
|
import { userVerificationServiceFactory } from "../../auth/background/service-factories/user-verification-service.factory";
|
||||||
import { Account } from "../../models/account";
|
import { Account } from "../../models/account";
|
||||||
import { CachedServices } from "../../platform/background/service-factories/factory-options";
|
import { CachedServices } from "../../platform/background/service-factories/factory-options";
|
||||||
import { BrowserApi } from "../../platform/browser/browser-api";
|
import { BrowserApi } from "../../platform/browser/browser-api";
|
||||||
@@ -38,7 +39,8 @@ export class CipherContextMenuHandler {
|
|||||||
constructor(
|
constructor(
|
||||||
private mainContextMenuHandler: MainContextMenuHandler,
|
private mainContextMenuHandler: MainContextMenuHandler,
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private cipherService: CipherService
|
private cipherService: CipherService,
|
||||||
|
private userVerificationService: UserVerificationService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
static async create(cachedServices: CachedServices) {
|
static async create(cachedServices: CachedServices) {
|
||||||
@@ -77,7 +79,8 @@ export class CipherContextMenuHandler {
|
|||||||
return new CipherContextMenuHandler(
|
return new CipherContextMenuHandler(
|
||||||
await MainContextMenuHandler.mv3Create(cachedServices),
|
await MainContextMenuHandler.mv3Create(cachedServices),
|
||||||
await authServiceFactory(cachedServices, serviceOptions),
|
await authServiceFactory(cachedServices, serviceOptions),
|
||||||
await cipherServiceFactory(cachedServices, serviceOptions)
|
await cipherServiceFactory(cachedServices, serviceOptions),
|
||||||
|
await userVerificationServiceFactory(cachedServices, serviceOptions)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +183,7 @@ export class CipherContextMenuHandler {
|
|||||||
if (
|
if (
|
||||||
cipher == null ||
|
cipher == null ||
|
||||||
cipher.type !== CipherType.Login ||
|
cipher.type !== CipherType.Login ||
|
||||||
cipher.reprompt !== CipherRepromptType.None
|
(await this.userVerificationService.hasMasterPasswordAndMasterKeyHash())
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -203,17 +203,45 @@ export class ContextMenuClickedHandler {
|
|||||||
if (tab == null) {
|
if (tab == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cipher.reprompt !== CipherRepromptType.None) {
|
||||||
|
await BrowserApi.tabSendMessageData(tab, "passwordReprompt", {
|
||||||
|
cipherId: cipher.id,
|
||||||
|
action: AUTOFILL_ID,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
await this.autofillAction(tab, cipher);
|
await this.autofillAction(tab, cipher);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case COPY_USERNAME_ID:
|
case COPY_USERNAME_ID:
|
||||||
this.copyToClipboard({ text: cipher.login.username, tab: tab });
|
this.copyToClipboard({ text: cipher.login.username, tab: tab });
|
||||||
break;
|
break;
|
||||||
case COPY_PASSWORD_ID:
|
case COPY_PASSWORD_ID:
|
||||||
|
if (cipher.reprompt !== CipherRepromptType.None) {
|
||||||
|
await BrowserApi.tabSendMessageData(tab, "passwordReprompt", {
|
||||||
|
cipherId: cipher.id,
|
||||||
|
action: COPY_PASSWORD_ID,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
this.copyToClipboard({ text: cipher.login.password, tab: tab });
|
this.copyToClipboard({ text: cipher.login.password, tab: tab });
|
||||||
this.eventCollectionService.collect(EventType.Cipher_ClientCopiedPassword, cipher.id);
|
this.eventCollectionService.collect(EventType.Cipher_ClientCopiedPassword, cipher.id);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case COPY_VERIFICATIONCODE_ID:
|
case COPY_VERIFICATIONCODE_ID:
|
||||||
this.copyToClipboard({ text: await this.totpService.getCode(cipher.login.totp), tab: tab });
|
if (cipher.reprompt !== CipherRepromptType.None) {
|
||||||
|
await BrowserApi.tabSendMessageData(tab, "passwordReprompt", {
|
||||||
|
cipherId: cipher.id,
|
||||||
|
action: COPY_VERIFICATIONCODE_ID,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.copyToClipboard({
|
||||||
|
text: await this.totpService.getCode(cipher.login.totp),
|
||||||
|
tab: tab,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ window.addEventListener(
|
|||||||
|
|
||||||
const forwardCommands = [
|
const forwardCommands = [
|
||||||
"promptForLogin",
|
"promptForLogin",
|
||||||
|
"passwordReprompt",
|
||||||
"addToLockedVaultPendingNotifications",
|
"addToLockedVaultPendingNotifications",
|
||||||
"unlockCompleted",
|
"unlockCompleted",
|
||||||
"addedCipher",
|
"addedCipher",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||||
import { SettingsService } from "@bitwarden/common/abstractions/settings.service";
|
import { SettingsService } from "@bitwarden/common/abstractions/settings.service";
|
||||||
import { TotpService } from "@bitwarden/common/abstractions/totp.service";
|
import { TotpService } from "@bitwarden/common/abstractions/totp.service";
|
||||||
|
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||||
import { EventType, FieldType, UriMatchType } from "@bitwarden/common/enums";
|
import { EventType, FieldType, UriMatchType } from "@bitwarden/common/enums";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
@@ -45,7 +46,8 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
private totpService: TotpService,
|
private totpService: TotpService,
|
||||||
private eventCollectionService: EventCollectionService,
|
private eventCollectionService: EventCollectionService,
|
||||||
private logService: LogService,
|
private logService: LogService,
|
||||||
private settingsService: SettingsService
|
private settingsService: SettingsService,
|
||||||
|
private userVerificationService: UserVerificationService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
getFormsWithPasswordFields(pageDetails: AutofillPageDetails): FormData[] {
|
getFormsWithPasswordFields(pageDetails: AutofillPageDetails): FormData[] {
|
||||||
@@ -234,7 +236,19 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cipher == null || cipher.reprompt !== CipherRepromptType.None) {
|
if (cipher == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
cipher.reprompt !== CipherRepromptType.None &&
|
||||||
|
(await this.userVerificationService.hasMasterPasswordAndMasterKeyHash())
|
||||||
|
) {
|
||||||
|
await BrowserApi.tabSendMessageData(tab, "passwordReprompt", {
|
||||||
|
cipherId: cipher.id,
|
||||||
|
action: "autofill",
|
||||||
|
});
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeout.service";
|
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
|
||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { NotificationsService } from "@bitwarden/common/abstractions/notifications.service";
|
import { NotificationsService } from "@bitwarden/common/abstractions/notifications.service";
|
||||||
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeout.service";
|
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
|
||||||
import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum";
|
import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum";
|
||||||
|
|
||||||
import { BrowserStateService } from "../platform/services/abstractions/browser-state.service";
|
import { BrowserStateService } from "../platform/services/abstractions/browser-state.service";
|
||||||
|
|||||||
@@ -1,27 +1,33 @@
|
|||||||
import { AvatarUpdateService as AvatarUpdateServiceAbstraction } from "@bitwarden/common/abstractions/account/avatar-update.service";
|
import { AvatarUpdateService as AvatarUpdateServiceAbstraction } from "@bitwarden/common/abstractions/account/avatar-update.service";
|
||||||
import { ApiService as ApiServiceAbstraction } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService as ApiServiceAbstraction } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { AuditService as AuditServiceAbstraction } from "@bitwarden/common/abstractions/audit.service";
|
import { AuditService as AuditServiceAbstraction } from "@bitwarden/common/abstractions/audit.service";
|
||||||
|
import { DevicesServiceAbstraction } from "@bitwarden/common/abstractions/devices/devices.service.abstraction";
|
||||||
import { EventCollectionService as EventCollectionServiceAbstraction } from "@bitwarden/common/abstractions/event/event-collection.service";
|
import { EventCollectionService as EventCollectionServiceAbstraction } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||||
import { EventUploadService as EventUploadServiceAbstraction } from "@bitwarden/common/abstractions/event/event-upload.service";
|
import { EventUploadService as EventUploadServiceAbstraction } from "@bitwarden/common/abstractions/event/event-upload.service";
|
||||||
import { NotificationsService as NotificationsServiceAbstraction } from "@bitwarden/common/abstractions/notifications.service";
|
import { NotificationsService as NotificationsServiceAbstraction } from "@bitwarden/common/abstractions/notifications.service";
|
||||||
import { SearchService as SearchServiceAbstraction } from "@bitwarden/common/abstractions/search.service";
|
import { SearchService as SearchServiceAbstraction } from "@bitwarden/common/abstractions/search.service";
|
||||||
import { SettingsService as SettingsServiceAbstraction } from "@bitwarden/common/abstractions/settings.service";
|
import { SettingsService as SettingsServiceAbstraction } from "@bitwarden/common/abstractions/settings.service";
|
||||||
import { TotpService as TotpServiceAbstraction } from "@bitwarden/common/abstractions/totp.service";
|
import { TotpService as TotpServiceAbstraction } from "@bitwarden/common/abstractions/totp.service";
|
||||||
import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeout.service";
|
import { VaultTimeoutSettingsService as VaultTimeoutSettingsServiceAbstraction } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
|
||||||
import { VaultTimeoutSettingsService as VaultTimeoutSettingsServiceAbstraction } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeoutSettings.service";
|
|
||||||
import { InternalOrganizationServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { InternalOrganizationServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
|
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
|
||||||
import { InternalPolicyService as InternalPolicyServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { InternalPolicyService as InternalPolicyServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { ProviderService as ProviderServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
import { ProviderService as ProviderServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
||||||
import { PolicyApiService } from "@bitwarden/common/admin-console/services/policy/policy-api.service";
|
import { PolicyApiService } from "@bitwarden/common/admin-console/services/policy/policy-api.service";
|
||||||
import { ProviderService } from "@bitwarden/common/admin-console/services/provider.service";
|
import { ProviderService } from "@bitwarden/common/admin-console/services/provider.service";
|
||||||
|
import { AuthRequestCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-crypto.service.abstraction";
|
||||||
import { AuthService as AuthServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService as AuthServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
|
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
||||||
|
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
|
||||||
import { KeyConnectorService as KeyConnectorServiceAbstraction } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
import { KeyConnectorService as KeyConnectorServiceAbstraction } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
||||||
import { TokenService as TokenServiceAbstraction } from "@bitwarden/common/auth/abstractions/token.service";
|
import { TokenService as TokenServiceAbstraction } from "@bitwarden/common/auth/abstractions/token.service";
|
||||||
import { TwoFactorService as TwoFactorServiceAbstraction } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
import { TwoFactorService as TwoFactorServiceAbstraction } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
||||||
import { UserVerificationApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/user-verification/user-verification-api.service.abstraction";
|
import { UserVerificationApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/user-verification/user-verification-api.service.abstraction";
|
||||||
import { UserVerificationService as UserVerificationServiceAbstraction } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
import { UserVerificationService as UserVerificationServiceAbstraction } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||||
|
import { AuthRequestCryptoServiceImplementation } from "@bitwarden/common/auth/services/auth-request-crypto.service.implementation";
|
||||||
import { AuthService } from "@bitwarden/common/auth/services/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/services/auth.service";
|
||||||
|
import { DeviceTrustCryptoService } from "@bitwarden/common/auth/services/device-trust-crypto.service.implementation";
|
||||||
|
import { DevicesApiServiceImplementation } from "@bitwarden/common/auth/services/devices-api.service.implementation";
|
||||||
import { KeyConnectorService } from "@bitwarden/common/auth/services/key-connector.service";
|
import { KeyConnectorService } from "@bitwarden/common/auth/services/key-connector.service";
|
||||||
import { TokenService } from "@bitwarden/common/auth/services/token.service";
|
import { TokenService } from "@bitwarden/common/auth/services/token.service";
|
||||||
import { TwoFactorService } from "@bitwarden/common/auth/services/two-factor.service";
|
import { TwoFactorService } from "@bitwarden/common/auth/services/two-factor.service";
|
||||||
@@ -60,12 +66,13 @@ import { WebCryptoFunctionService } from "@bitwarden/common/platform/services/we
|
|||||||
import { AvatarUpdateService } from "@bitwarden/common/services/account/avatar-update.service";
|
import { AvatarUpdateService } from "@bitwarden/common/services/account/avatar-update.service";
|
||||||
import { ApiService } from "@bitwarden/common/services/api.service";
|
import { ApiService } from "@bitwarden/common/services/api.service";
|
||||||
import { AuditService } from "@bitwarden/common/services/audit.service";
|
import { AuditService } from "@bitwarden/common/services/audit.service";
|
||||||
|
import { DevicesServiceImplementation } from "@bitwarden/common/services/devices/devices.service.implementation";
|
||||||
import { EventCollectionService } from "@bitwarden/common/services/event/event-collection.service";
|
import { EventCollectionService } from "@bitwarden/common/services/event/event-collection.service";
|
||||||
import { EventUploadService } from "@bitwarden/common/services/event/event-upload.service";
|
import { EventUploadService } from "@bitwarden/common/services/event/event-upload.service";
|
||||||
import { NotificationsService } from "@bitwarden/common/services/notifications.service";
|
import { NotificationsService } from "@bitwarden/common/services/notifications.service";
|
||||||
import { SearchService } from "@bitwarden/common/services/search.service";
|
import { SearchService } from "@bitwarden/common/services/search.service";
|
||||||
import { TotpService } from "@bitwarden/common/services/totp.service";
|
import { TotpService } from "@bitwarden/common/services/totp.service";
|
||||||
import { VaultTimeoutSettingsService } from "@bitwarden/common/services/vaultTimeout/vaultTimeoutSettings.service";
|
import { VaultTimeoutSettingsService } from "@bitwarden/common/services/vault-timeout/vault-timeout-settings.service";
|
||||||
import {
|
import {
|
||||||
PasswordGenerationService,
|
PasswordGenerationService,
|
||||||
PasswordGenerationServiceAbstraction,
|
PasswordGenerationServiceAbstraction,
|
||||||
@@ -136,7 +143,7 @@ import { PopupUtilsService } from "../popup/services/popup-utils.service";
|
|||||||
import { BrowserSendService } from "../services/browser-send.service";
|
import { BrowserSendService } from "../services/browser-send.service";
|
||||||
import { BrowserSettingsService } from "../services/browser-settings.service";
|
import { BrowserSettingsService } from "../services/browser-settings.service";
|
||||||
import { BrowserFido2UserInterfaceService } from "../services/fido2/browser-fido2-user-interface.service";
|
import { BrowserFido2UserInterfaceService } from "../services/fido2/browser-fido2-user-interface.service";
|
||||||
import VaultTimeoutService from "../services/vaultTimeout/vaultTimeout.service";
|
import VaultTimeoutService from "../services/vault-timeout/vault-timeout.service";
|
||||||
import { BrowserFolderService } from "../vault/services/browser-folder.service";
|
import { BrowserFolderService } from "../vault/services/browser-folder.service";
|
||||||
import { VaultFilterService } from "../vault/services/vault-filter.service";
|
import { VaultFilterService } from "../vault/services/vault-filter.service";
|
||||||
|
|
||||||
@@ -164,7 +171,7 @@ export default class MainBackground {
|
|||||||
cipherService: CipherServiceAbstraction;
|
cipherService: CipherServiceAbstraction;
|
||||||
folderService: InternalFolderServiceAbstraction;
|
folderService: InternalFolderServiceAbstraction;
|
||||||
collectionService: CollectionServiceAbstraction;
|
collectionService: CollectionServiceAbstraction;
|
||||||
vaultTimeoutService: VaultTimeoutServiceAbstraction;
|
vaultTimeoutService: VaultTimeoutService;
|
||||||
vaultTimeoutSettingsService: VaultTimeoutSettingsServiceAbstraction;
|
vaultTimeoutSettingsService: VaultTimeoutSettingsServiceAbstraction;
|
||||||
syncService: SyncServiceAbstraction;
|
syncService: SyncServiceAbstraction;
|
||||||
passwordGenerationService: PasswordGenerationServiceAbstraction;
|
passwordGenerationService: PasswordGenerationServiceAbstraction;
|
||||||
@@ -207,6 +214,10 @@ export default class MainBackground {
|
|||||||
cipherContextMenuHandler: CipherContextMenuHandler;
|
cipherContextMenuHandler: CipherContextMenuHandler;
|
||||||
configService: ConfigServiceAbstraction;
|
configService: ConfigServiceAbstraction;
|
||||||
configApiService: ConfigApiServiceAbstraction;
|
configApiService: ConfigApiServiceAbstraction;
|
||||||
|
devicesApiService: DevicesApiServiceAbstraction;
|
||||||
|
devicesService: DevicesServiceAbstraction;
|
||||||
|
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction;
|
||||||
|
authRequestCryptoService: AuthRequestCryptoServiceAbstraction;
|
||||||
popupUtilsService: PopupUtilsService;
|
popupUtilsService: PopupUtilsService;
|
||||||
browserPopoutWindowService: BrowserPopoutWindowService;
|
browserPopoutWindowService: BrowserPopoutWindowService;
|
||||||
|
|
||||||
@@ -399,6 +410,23 @@ export default class MainBackground {
|
|||||||
that.runtimeBackground.processMessage(message, that as any);
|
that.runtimeBackground.processMessage(message, that as any);
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
this.devicesApiService = new DevicesApiServiceImplementation(this.apiService);
|
||||||
|
this.deviceTrustCryptoService = new DeviceTrustCryptoService(
|
||||||
|
this.cryptoFunctionService,
|
||||||
|
this.cryptoService,
|
||||||
|
this.encryptService,
|
||||||
|
this.stateService,
|
||||||
|
this.appIdService,
|
||||||
|
this.devicesApiService,
|
||||||
|
this.i18nService,
|
||||||
|
this.platformUtilsService
|
||||||
|
);
|
||||||
|
|
||||||
|
this.devicesService = new DevicesServiceImplementation(this.devicesApiService);
|
||||||
|
|
||||||
|
this.authRequestCryptoService = new AuthRequestCryptoServiceImplementation(this.cryptoService);
|
||||||
|
|
||||||
this.authService = new AuthService(
|
this.authService = new AuthService(
|
||||||
this.cryptoService,
|
this.cryptoService,
|
||||||
this.apiService,
|
this.apiService,
|
||||||
@@ -414,14 +442,26 @@ export default class MainBackground {
|
|||||||
this.i18nService,
|
this.i18nService,
|
||||||
this.encryptService,
|
this.encryptService,
|
||||||
this.passwordStrengthService,
|
this.passwordStrengthService,
|
||||||
this.policyService
|
this.policyService,
|
||||||
|
this.deviceTrustCryptoService,
|
||||||
|
this.authRequestCryptoService
|
||||||
|
);
|
||||||
|
|
||||||
|
this.userVerificationApiService = new UserVerificationApiService(this.apiService);
|
||||||
|
|
||||||
|
this.userVerificationService = new UserVerificationService(
|
||||||
|
this.stateService,
|
||||||
|
this.cryptoService,
|
||||||
|
this.i18nService,
|
||||||
|
this.userVerificationApiService
|
||||||
);
|
);
|
||||||
|
|
||||||
this.vaultTimeoutSettingsService = new VaultTimeoutSettingsService(
|
this.vaultTimeoutSettingsService = new VaultTimeoutSettingsService(
|
||||||
this.cryptoService,
|
this.cryptoService,
|
||||||
this.tokenService,
|
this.tokenService,
|
||||||
this.policyService,
|
this.policyService,
|
||||||
this.stateService
|
this.stateService,
|
||||||
|
this.userVerificationService
|
||||||
);
|
);
|
||||||
|
|
||||||
this.vaultTimeoutService = new VaultTimeoutService(
|
this.vaultTimeoutService = new VaultTimeoutService(
|
||||||
@@ -432,7 +472,6 @@ export default class MainBackground {
|
|||||||
this.platformUtilsService,
|
this.platformUtilsService,
|
||||||
this.messagingService,
|
this.messagingService,
|
||||||
this.searchService,
|
this.searchService,
|
||||||
this.keyConnectorService,
|
|
||||||
this.stateService,
|
this.stateService,
|
||||||
this.authService,
|
this.authService,
|
||||||
this.vaultTimeoutSettingsService,
|
this.vaultTimeoutSettingsService,
|
||||||
@@ -483,13 +522,15 @@ export default class MainBackground {
|
|||||||
this.eventUploadService
|
this.eventUploadService
|
||||||
);
|
);
|
||||||
this.totpService = new TotpService(this.cryptoFunctionService, this.logService);
|
this.totpService = new TotpService(this.cryptoFunctionService, this.logService);
|
||||||
|
|
||||||
this.autofillService = new AutofillService(
|
this.autofillService = new AutofillService(
|
||||||
this.cipherService,
|
this.cipherService,
|
||||||
this.stateService,
|
this.stateService,
|
||||||
this.totpService,
|
this.totpService,
|
||||||
this.eventCollectionService,
|
this.eventCollectionService,
|
||||||
this.logService,
|
this.logService,
|
||||||
this.settingsService
|
this.settingsService,
|
||||||
|
this.userVerificationService
|
||||||
);
|
);
|
||||||
this.auditService = new AuditService(this.cryptoFunctionService, this.apiService);
|
this.auditService = new AuditService(this.cryptoFunctionService, this.apiService);
|
||||||
this.exportService = new VaultExportService(
|
this.exportService = new VaultExportService(
|
||||||
@@ -511,15 +552,6 @@ export default class MainBackground {
|
|||||||
this.authService,
|
this.authService,
|
||||||
this.messagingService
|
this.messagingService
|
||||||
);
|
);
|
||||||
|
|
||||||
this.userVerificationApiService = new UserVerificationApiService(this.apiService);
|
|
||||||
|
|
||||||
this.userVerificationService = new UserVerificationService(
|
|
||||||
this.cryptoService,
|
|
||||||
this.i18nService,
|
|
||||||
this.userVerificationApiService
|
|
||||||
);
|
|
||||||
|
|
||||||
this.configApiService = new ConfigApiService(this.apiService, this.authService);
|
this.configApiService = new ConfigApiService(this.apiService, this.authService);
|
||||||
|
|
||||||
this.configService = new ConfigService(
|
this.configService = new ConfigService(
|
||||||
@@ -528,6 +560,7 @@ export default class MainBackground {
|
|||||||
this.authService,
|
this.authService,
|
||||||
this.environmentService
|
this.environmentService
|
||||||
);
|
);
|
||||||
|
|
||||||
this.browserPopoutWindowService = new BrowserPopoutWindowService();
|
this.browserPopoutWindowService = new BrowserPopoutWindowService();
|
||||||
|
|
||||||
this.popupUtilsService = new PopupUtilsService(this.isPrivateMode);
|
this.popupUtilsService = new PopupUtilsService(this.isPrivateMode);
|
||||||
@@ -669,7 +702,8 @@ export default class MainBackground {
|
|||||||
this.cipherContextMenuHandler = new CipherContextMenuHandler(
|
this.cipherContextMenuHandler = new CipherContextMenuHandler(
|
||||||
this.mainContextMenuHandler,
|
this.mainContextMenuHandler,
|
||||||
this.authService,
|
this.authService,
|
||||||
this.cipherService
|
this.cipherService,
|
||||||
|
this.userVerificationService
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -679,7 +713,7 @@ export default class MainBackground {
|
|||||||
|
|
||||||
await this.stateService.init();
|
await this.stateService.init();
|
||||||
|
|
||||||
await (this.vaultTimeoutService as VaultTimeoutService).init(true);
|
await this.vaultTimeoutService.init(true);
|
||||||
await (this.i18nService as BrowserI18nService).init();
|
await (this.i18nService as BrowserI18nService).init();
|
||||||
await (this.eventUploadService as EventUploadService).init(true);
|
await (this.eventUploadService as EventUploadService).init(true);
|
||||||
await this.runtimeBackground.init();
|
await this.runtimeBackground.init();
|
||||||
|
|||||||
@@ -10,7 +10,11 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
|
|||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
|
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
|
||||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
import {
|
||||||
|
MasterKey,
|
||||||
|
SymmetricCryptoKey,
|
||||||
|
UserKey,
|
||||||
|
} from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||||
|
|
||||||
import { BrowserApi } from "../platform/browser/browser-api";
|
import { BrowserApi } from "../platform/browser/browser-api";
|
||||||
|
|
||||||
@@ -42,6 +46,7 @@ type ReceiveMessage = {
|
|||||||
|
|
||||||
// Unlock key
|
// Unlock key
|
||||||
keyB64?: string;
|
keyB64?: string;
|
||||||
|
userKeyB64?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ReceiveMessageOuter = {
|
type ReceiveMessageOuter = {
|
||||||
@@ -320,16 +325,55 @@ export class NativeMessagingBackground {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (message.response === "unlocked") {
|
if (message.response === "unlocked") {
|
||||||
await this.cryptoService.setKey(
|
try {
|
||||||
new SymmetricCryptoKey(Utils.fromB64ToArray(message.keyB64))
|
if (message.userKeyB64) {
|
||||||
|
const userKey = new SymmetricCryptoKey(
|
||||||
|
Utils.fromB64ToArray(message.userKeyB64)
|
||||||
|
) as UserKey;
|
||||||
|
await this.cryptoService.setUserKey(userKey);
|
||||||
|
} else if (message.keyB64) {
|
||||||
|
// Backwards compatibility to support cases in which the user hasn't updated their desktop app
|
||||||
|
// TODO: Remove after 2023.10 release (https://bitwarden.atlassian.net/browse/PM-3472)
|
||||||
|
let encUserKey = await this.stateService.getEncryptedCryptoSymmetricKey();
|
||||||
|
encUserKey ||= await this.stateService.getMasterKeyEncryptedUserKey();
|
||||||
|
if (!encUserKey) {
|
||||||
|
throw new Error("No encrypted user key found");
|
||||||
|
}
|
||||||
|
const masterKey = new SymmetricCryptoKey(
|
||||||
|
Utils.fromB64ToArray(message.keyB64)
|
||||||
|
) as MasterKey;
|
||||||
|
const userKey = await this.cryptoService.decryptUserKeyWithMasterKey(
|
||||||
|
masterKey,
|
||||||
|
new EncString(encUserKey)
|
||||||
);
|
);
|
||||||
|
await this.cryptoService.setMasterKey(masterKey);
|
||||||
|
await this.cryptoService.setUserKey(userKey);
|
||||||
|
} else {
|
||||||
|
throw new Error("No key received");
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
this.logService.error("Unable to set key: " + e);
|
||||||
|
this.messagingService.send("showDialog", {
|
||||||
|
title: { key: "biometricsFailedTitle" },
|
||||||
|
content: { key: "biometricsFailedDesc" },
|
||||||
|
acceptButtonText: { key: "ok" },
|
||||||
|
cancelButtonText: null,
|
||||||
|
type: "danger",
|
||||||
|
});
|
||||||
|
|
||||||
|
// Exit early
|
||||||
|
if (this.resolver) {
|
||||||
|
this.resolver(message);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Verify key is correct by attempting to decrypt a secret
|
// Verify key is correct by attempting to decrypt a secret
|
||||||
try {
|
try {
|
||||||
await this.cryptoService.getFingerprint(await this.stateService.getUserId());
|
await this.cryptoService.getFingerprint(await this.stateService.getUserId());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logService.error("Unable to verify key: " + e);
|
this.logService.error("Unable to verify key: " + e);
|
||||||
await this.cryptoService.clearKey();
|
await this.cryptoService.clearKeys();
|
||||||
this.showWrongUserDialog();
|
this.showWrongUserDialog();
|
||||||
|
|
||||||
// Exit early
|
// Exit early
|
||||||
|
|||||||
@@ -52,7 +52,11 @@ export default class RuntimeBackground {
|
|||||||
sender: chrome.runtime.MessageSender,
|
sender: chrome.runtime.MessageSender,
|
||||||
sendResponse: any
|
sendResponse: any
|
||||||
) => {
|
) => {
|
||||||
const messagesWithResponse = ["fido2RegisterCredentialRequest", "fido2GetCredentialRequest"];
|
const messagesWithResponse = [
|
||||||
|
"checkFido2FeatureEnabled",
|
||||||
|
"fido2RegisterCredentialRequest",
|
||||||
|
"fido2GetCredentialRequest",
|
||||||
|
];
|
||||||
|
|
||||||
if (messagesWithResponse.includes(msg.command)) {
|
if (messagesWithResponse.includes(msg.command)) {
|
||||||
this.processMessage(msg, sender).then(
|
this.processMessage(msg, sender).then(
|
||||||
@@ -75,6 +79,8 @@ export default class RuntimeBackground {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async processMessage(msg: any, sender: chrome.runtime.MessageSender) {
|
async processMessage(msg: any, sender: chrome.runtime.MessageSender) {
|
||||||
|
const cipherId = msg.data?.cipherId;
|
||||||
|
|
||||||
switch (msg.command) {
|
switch (msg.command) {
|
||||||
case "loggedIn":
|
case "loggedIn":
|
||||||
case "unlocked": {
|
case "unlocked": {
|
||||||
@@ -82,7 +88,7 @@ export default class RuntimeBackground {
|
|||||||
|
|
||||||
if (this.lockedVaultPendingNotifications?.length > 0) {
|
if (this.lockedVaultPendingNotifications?.length > 0) {
|
||||||
item = this.lockedVaultPendingNotifications.pop();
|
item = this.lockedVaultPendingNotifications.pop();
|
||||||
await this.browserPopoutWindowService.closeLoginPrompt();
|
await this.browserPopoutWindowService.closeUnlockPrompt();
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.main.refreshBadge();
|
await this.main.refreshBadge();
|
||||||
@@ -122,13 +128,22 @@ export default class RuntimeBackground {
|
|||||||
break;
|
break;
|
||||||
case "promptForLogin":
|
case "promptForLogin":
|
||||||
case "bgReopenPromptForLogin":
|
case "bgReopenPromptForLogin":
|
||||||
await this.browserPopoutWindowService.openLoginPrompt(sender.tab?.windowId);
|
await this.browserPopoutWindowService.openUnlockPrompt(sender.tab?.windowId);
|
||||||
|
break;
|
||||||
|
case "passwordReprompt":
|
||||||
|
if (cipherId) {
|
||||||
|
await this.browserPopoutWindowService.openPasswordRepromptPrompt(sender.tab?.windowId, {
|
||||||
|
cipherId: cipherId,
|
||||||
|
senderTabId: sender.tab.id,
|
||||||
|
action: msg.data?.action,
|
||||||
|
});
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "openAddEditCipher": {
|
case "openAddEditCipher": {
|
||||||
const addEditCipherUrl =
|
const addEditCipherUrl =
|
||||||
msg.data?.cipherId == null
|
cipherId == null
|
||||||
? "popup/index.html#/edit-cipher"
|
? "popup/index.html#/edit-cipher"
|
||||||
: "popup/index.html#/edit-cipher?cipherId=" + msg.data.cipherId;
|
: "popup/index.html#/edit-cipher?cipherId=" + cipherId;
|
||||||
|
|
||||||
BrowserApi.openBitwardenExtensionTab(addEditCipherUrl, true);
|
BrowserApi.openBitwardenExtensionTab(addEditCipherUrl, true);
|
||||||
break;
|
break;
|
||||||
@@ -233,6 +248,8 @@ export default class RuntimeBackground {
|
|||||||
case "fido2AbortRequest":
|
case "fido2AbortRequest":
|
||||||
this.abortControllers.get(msg.abortedRequestId)?.abort();
|
this.abortControllers.get(msg.abortedRequestId)?.abort();
|
||||||
break;
|
break;
|
||||||
|
case "checkFido2FeatureEnabled":
|
||||||
|
return await this.main.fido2ClientService.isFido2FeatureEnabled();
|
||||||
case "fido2RegisterCredentialRequest":
|
case "fido2RegisterCredentialRequest":
|
||||||
return await this.main.fido2ClientService
|
return await this.main.fido2ClientService
|
||||||
.createCredential(msg.data, this.createAbortController(msg.requestId))
|
.createCredential(msg.data, this.createAbortController(msg.requestId))
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
|
||||||
|
import { DevicesApiServiceImplementation } from "@bitwarden/common/auth/services/devices-api.service.implementation";
|
||||||
|
|
||||||
|
import {
|
||||||
|
ApiServiceInitOptions,
|
||||||
|
apiServiceFactory,
|
||||||
|
} from "../../platform/background/service-factories/api-service.factory";
|
||||||
|
import {
|
||||||
|
FactoryOptions,
|
||||||
|
CachedServices,
|
||||||
|
factory,
|
||||||
|
} from "../../platform/background/service-factories/factory-options";
|
||||||
|
|
||||||
|
type DevicesApiServiceFactoryOptions = FactoryOptions;
|
||||||
|
|
||||||
|
export type DevicesApiServiceInitOptions = DevicesApiServiceFactoryOptions & ApiServiceInitOptions;
|
||||||
|
|
||||||
|
export function devicesApiServiceFactory(
|
||||||
|
cache: { devicesApiService?: DevicesApiServiceAbstraction } & CachedServices,
|
||||||
|
opts: DevicesApiServiceInitOptions
|
||||||
|
): Promise<DevicesApiServiceAbstraction> {
|
||||||
|
return factory(
|
||||||
|
cache,
|
||||||
|
"devicesApiService",
|
||||||
|
opts,
|
||||||
|
async () => new DevicesApiServiceImplementation(await apiServiceFactory(cache, opts))
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,13 +1,9 @@
|
|||||||
import { VaultTimeoutService as AbstractVaultTimeoutService } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeout.service";
|
import { VaultTimeoutService as AbstractVaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
authServiceFactory,
|
authServiceFactory,
|
||||||
AuthServiceInitOptions,
|
AuthServiceInitOptions,
|
||||||
} from "../../auth/background/service-factories/auth-service.factory";
|
} from "../../auth/background/service-factories/auth-service.factory";
|
||||||
import {
|
|
||||||
keyConnectorServiceFactory,
|
|
||||||
KeyConnectorServiceInitOptions,
|
|
||||||
} from "../../auth/background/service-factories/key-connector-service.factory";
|
|
||||||
import {
|
import {
|
||||||
CryptoServiceInitOptions,
|
CryptoServiceInitOptions,
|
||||||
cryptoServiceFactory,
|
cryptoServiceFactory,
|
||||||
@@ -29,7 +25,7 @@ import {
|
|||||||
StateServiceInitOptions,
|
StateServiceInitOptions,
|
||||||
stateServiceFactory,
|
stateServiceFactory,
|
||||||
} from "../../platform/background/service-factories/state-service.factory";
|
} from "../../platform/background/service-factories/state-service.factory";
|
||||||
import VaultTimeoutService from "../../services/vaultTimeout/vaultTimeout.service";
|
import VaultTimeoutService from "../../services/vault-timeout/vault-timeout.service";
|
||||||
import {
|
import {
|
||||||
cipherServiceFactory,
|
cipherServiceFactory,
|
||||||
CipherServiceInitOptions,
|
CipherServiceInitOptions,
|
||||||
@@ -64,7 +60,6 @@ export type VaultTimeoutServiceInitOptions = VaultTimeoutServiceFactoryOptions &
|
|||||||
PlatformUtilsServiceInitOptions &
|
PlatformUtilsServiceInitOptions &
|
||||||
MessagingServiceInitOptions &
|
MessagingServiceInitOptions &
|
||||||
SearchServiceInitOptions &
|
SearchServiceInitOptions &
|
||||||
KeyConnectorServiceInitOptions &
|
|
||||||
StateServiceInitOptions &
|
StateServiceInitOptions &
|
||||||
AuthServiceInitOptions &
|
AuthServiceInitOptions &
|
||||||
VaultTimeoutSettingsServiceInitOptions;
|
VaultTimeoutSettingsServiceInitOptions;
|
||||||
@@ -86,7 +81,6 @@ export function vaultTimeoutServiceFactory(
|
|||||||
await platformUtilsServiceFactory(cache, opts),
|
await platformUtilsServiceFactory(cache, opts),
|
||||||
await messagingServiceFactory(cache, opts),
|
await messagingServiceFactory(cache, opts),
|
||||||
await searchServiceFactory(cache, opts),
|
await searchServiceFactory(cache, opts),
|
||||||
await keyConnectorServiceFactory(cache, opts),
|
|
||||||
await stateServiceFactory(cache, opts),
|
await stateServiceFactory(cache, opts),
|
||||||
await authServiceFactory(cache, opts),
|
await authServiceFactory(cache, opts),
|
||||||
await vaultTimeoutSettingsServiceFactory(cache, opts),
|
await vaultTimeoutSettingsServiceFactory(cache, opts),
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user