mirror of
https://github.com/bitwarden/browser
synced 2026-02-13 06:54:07 +00:00
Merge branch 'main' into ps/extension-refresh
This commit is contained in:
2
.github/workflows/auto-branch-updater.yml
vendored
2
.github/workflows/auto-branch-updater.yml
vendored
@@ -28,7 +28,7 @@ jobs:
|
||||
run: echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: 'eu-web-${{ steps.setup.outputs.branch }}'
|
||||
fetch-depth: 0
|
||||
|
||||
14
.github/workflows/build-browser.yml
vendored
14
.github/workflows/build-browser.yml
vendored
@@ -42,7 +42,7 @@ jobs:
|
||||
node_version: ${{ steps.retrieve-node-version.outputs.node_version }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Get Package Version
|
||||
id: gen_vars
|
||||
@@ -72,7 +72,7 @@ jobs:
|
||||
working-directory: apps/browser
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Testing locales - extName length
|
||||
run: |
|
||||
@@ -110,10 +110,10 @@ jobs:
|
||||
_NODE_VERSION: ${{ needs.setup.outputs.node_version }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
@@ -241,10 +241,10 @@ jobs:
|
||||
_NODE_VERSION: ${{ needs.setup.outputs.node_version }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
@@ -354,7 +354,7 @@ jobs:
|
||||
- build-safari
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Login to Azure
|
||||
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
||||
|
||||
12
.github/workflows/build-cli.yml
vendored
12
.github/workflows/build-cli.yml
vendored
@@ -42,7 +42,7 @@ jobs:
|
||||
node_version: ${{ steps.retrieve-node-version.outputs.node_version }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Get Package Version
|
||||
id: retrieve-package-version
|
||||
@@ -83,7 +83,7 @@ jobs:
|
||||
_WIN_PKG_VERSION: 3.5
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Setup Unix Vars
|
||||
run: |
|
||||
@@ -92,7 +92,7 @@ jobs:
|
||||
awk '{print tolower($0)}')" >> $GITHUB_ENV
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
@@ -161,7 +161,7 @@ jobs:
|
||||
_WIN_PKG_VERSION: 3.5
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Setup Windows builder
|
||||
run: |
|
||||
@@ -170,7 +170,7 @@ jobs:
|
||||
choco install nasm --no-progress
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
@@ -311,7 +311,7 @@ jobs:
|
||||
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Print environment
|
||||
run: |
|
||||
|
||||
58
.github/workflows/build-desktop.yml
vendored
58
.github/workflows/build-desktop.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Verify
|
||||
run: |
|
||||
@@ -66,7 +66,7 @@ jobs:
|
||||
working-directory: apps/desktop
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Get Package Version
|
||||
id: retrieve-version
|
||||
@@ -139,10 +139,10 @@ jobs:
|
||||
working-directory: apps/desktop
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
@@ -168,7 +168,7 @@ jobs:
|
||||
working-directory: ./
|
||||
|
||||
- name: Cache Native Module
|
||||
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
||||
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
|
||||
id: cache
|
||||
with:
|
||||
path: |
|
||||
@@ -249,10 +249,10 @@ jobs:
|
||||
NODE_OPTIONS: --max_old_space_size=4096
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
@@ -298,7 +298,7 @@ jobs:
|
||||
working-directory: ./
|
||||
|
||||
- name: Cache Native Module
|
||||
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
||||
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
|
||||
id: cache
|
||||
with:
|
||||
path: |
|
||||
@@ -457,10 +457,10 @@ jobs:
|
||||
working-directory: apps/desktop
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
@@ -483,14 +483,14 @@ jobs:
|
||||
|
||||
- name: Cache Build
|
||||
id: build-cache
|
||||
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
||||
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
|
||||
with:
|
||||
path: apps/desktop/build
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-build
|
||||
|
||||
- name: Cache Safari
|
||||
id: safari-cache
|
||||
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
||||
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
|
||||
with:
|
||||
path: apps/browser/dist/Safari
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-safari-extension
|
||||
@@ -583,7 +583,7 @@ jobs:
|
||||
working-directory: ./
|
||||
|
||||
- name: Cache Native Module
|
||||
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
||||
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
|
||||
id: cache
|
||||
with:
|
||||
path: |
|
||||
@@ -623,10 +623,10 @@ jobs:
|
||||
working-directory: apps/desktop
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
@@ -649,14 +649,14 @@ jobs:
|
||||
|
||||
- name: Get Build Cache
|
||||
id: build-cache
|
||||
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
||||
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
|
||||
with:
|
||||
path: apps/desktop/build
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-build
|
||||
|
||||
- name: Setup Safari Cache
|
||||
id: safari-cache
|
||||
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
||||
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
|
||||
with:
|
||||
path: apps/browser/dist/Safari
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-safari-extension
|
||||
@@ -749,7 +749,7 @@ jobs:
|
||||
working-directory: ./
|
||||
|
||||
- name: Cache Native Module
|
||||
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
||||
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
|
||||
id: cache
|
||||
with:
|
||||
path: |
|
||||
@@ -842,10 +842,10 @@ jobs:
|
||||
working-directory: apps/desktop
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
@@ -868,14 +868,14 @@ jobs:
|
||||
|
||||
- name: Get Build Cache
|
||||
id: build-cache
|
||||
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
||||
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
|
||||
with:
|
||||
path: apps/desktop/build
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-build
|
||||
|
||||
- name: Setup Safari Cache
|
||||
id: safari-cache
|
||||
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
||||
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
|
||||
with:
|
||||
path: apps/browser/dist/Safari
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-safari-extension
|
||||
@@ -975,7 +975,7 @@ jobs:
|
||||
working-directory: ./
|
||||
|
||||
- name: Cache Native Module
|
||||
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
||||
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
|
||||
id: cache
|
||||
with:
|
||||
path: |
|
||||
@@ -1089,10 +1089,10 @@ jobs:
|
||||
working-directory: apps/desktop
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
@@ -1110,14 +1110,14 @@ jobs:
|
||||
|
||||
- name: Get Build Cache
|
||||
id: build-cache
|
||||
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
||||
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
|
||||
with:
|
||||
path: apps/desktop/build
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-build
|
||||
|
||||
- name: Setup Safari Cache
|
||||
id: safari-cache
|
||||
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
||||
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
|
||||
with:
|
||||
path: apps/browser/dist/Safari
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-safari-extension
|
||||
@@ -1210,7 +1210,7 @@ jobs:
|
||||
working-directory: ./
|
||||
|
||||
- name: Cache Native Module
|
||||
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
||||
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
|
||||
id: cache
|
||||
with:
|
||||
path: |
|
||||
@@ -1280,7 +1280,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Login to Azure
|
||||
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
||||
|
||||
10
.github/workflows/build-web.yml
vendored
10
.github/workflows/build-web.yml
vendored
@@ -44,7 +44,7 @@ jobs:
|
||||
node_version: ${{ steps.retrieve-node-version.outputs.node_version }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Get GitHub sha as version
|
||||
id: version
|
||||
@@ -90,10 +90,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
@@ -156,7 +156,7 @@ jobs:
|
||||
_VERSION: ${{ needs.setup.outputs.version }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Check Branch to Publish
|
||||
env:
|
||||
@@ -254,7 +254,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Login to Azure
|
||||
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
||||
|
||||
8
.github/workflows/chromatic.yml
vendored
8
.github/workflows/chromatic.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
@@ -37,13 +37,13 @@ jobs:
|
||||
echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
node-version: ${{ steps.retrieve-node-version.outputs.node_version }}
|
||||
|
||||
- name: Cache NPM
|
||||
id: npm-cache
|
||||
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
||||
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
|
||||
with:
|
||||
path: "~/.npm"
|
||||
key: ${{ runner.os }}-npm-chromatic-${{ hashFiles('**/package-lock.json') }}
|
||||
@@ -56,7 +56,7 @@ jobs:
|
||||
run: npm run build-storybook:ci
|
||||
|
||||
- name: Publish to Chromatic
|
||||
uses: chromaui/action@bbbf288765438d5fd2be13e1d80d542a39e74108 # v11.12.1
|
||||
uses: chromaui/action@dd2eecb9bef44f54774581f4163b0327fd8cf607 # v11.16.3
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
|
||||
|
||||
2
.github/workflows/crowdin-pull.yml
vendored
2
.github/workflows/crowdin-pull.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
crowdin_project_id: "308189"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Login to Azure
|
||||
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
||||
|
||||
4
.github/workflows/lint.yml
vendored
4
.github/workflows/lint.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Lint filenames (no capital characters)
|
||||
run: |
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
|
||||
4
.github/workflows/locales-lint.yml
vendored
4
.github/workflows/locales-lint.yml
vendored
@@ -14,9 +14,9 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Checkout base branch repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.base.sha }}
|
||||
path: base
|
||||
|
||||
6
.github/workflows/publish-cli.yml
vendored
6
.github/workflows/publish-cli.yml
vendored
@@ -91,7 +91,7 @@ jobs:
|
||||
_PKG_VERSION: ${{ needs.setup.outputs.release-version }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Login to Azure
|
||||
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
||||
@@ -128,7 +128,7 @@ jobs:
|
||||
_PKG_VERSION: ${{ needs.setup.outputs.release-version }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Login to Azure
|
||||
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
||||
@@ -168,7 +168,7 @@ jobs:
|
||||
_PKG_VERSION: ${{ needs.setup.outputs.release-version }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Login to Azure
|
||||
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
||||
|
||||
4
.github/workflows/publish-desktop.yml
vendored
4
.github/workflows/publish-desktop.yml
vendored
@@ -183,7 +183,7 @@ jobs:
|
||||
_RELEASE_TAG: ${{ needs.setup.outputs.tag-name }}
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Login to Azure
|
||||
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
||||
@@ -227,7 +227,7 @@ jobs:
|
||||
_RELEASE_TAG: ${{ needs.setup.outputs.tag-name }}
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Print Environment
|
||||
run: |
|
||||
|
||||
4
.github/workflows/publish-web.yml
vendored
4
.github/workflows/publish-web.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
tag_version: ${{ steps.version.outputs.tag }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Branch check
|
||||
if: ${{ inputs.publish_type != 'Dry Run' }}
|
||||
@@ -66,7 +66,7 @@ jobs:
|
||||
echo "Github Release Option: $_RELEASE_OPTION"
|
||||
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
########## ACR ##########
|
||||
- name: Login to Azure - PROD Subscription
|
||||
|
||||
4
.github/workflows/release-browser.yml
vendored
4
.github/workflows/release-browser.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
release-version: ${{ steps.version.outputs.version }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Branch check
|
||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||
@@ -55,7 +55,7 @@ jobs:
|
||||
needs: setup
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Testing locales - extName length
|
||||
run: |
|
||||
|
||||
2
.github/workflows/release-cli.yml
vendored
2
.github/workflows/release-cli.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
release-version: ${{ steps.version.outputs.version }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Branch check
|
||||
if: ${{ inputs.release_type != 'Dry Run' }}
|
||||
|
||||
36
.github/workflows/release-desktop-beta.yml
vendored
36
.github/workflows/release-desktop-beta.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
node_version: ${{ steps.retrieve-node-version.outputs.node_version }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Branch check
|
||||
run: |
|
||||
@@ -124,12 +124,12 @@ jobs:
|
||||
working-directory: apps/desktop
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ needs.setup.outputs.branch-name }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
@@ -214,12 +214,12 @@ jobs:
|
||||
NODE_OPTIONS: --max_old_space_size=4096
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ needs.setup.outputs.branch-name }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
@@ -403,12 +403,12 @@ jobs:
|
||||
working-directory: apps/desktop
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ needs.setup.outputs.branch-name }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
@@ -426,14 +426,14 @@ jobs:
|
||||
|
||||
- name: Cache Build
|
||||
id: build-cache
|
||||
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
||||
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
|
||||
with:
|
||||
path: apps/desktop/build
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-build
|
||||
|
||||
- name: Cache Safari
|
||||
id: safari-cache
|
||||
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
||||
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
|
||||
with:
|
||||
path: apps/browser/dist/Safari
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-safari-extension
|
||||
@@ -537,12 +537,12 @@ jobs:
|
||||
working-directory: apps/desktop
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ needs.setup.outputs.branch-name }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
@@ -560,14 +560,14 @@ jobs:
|
||||
|
||||
- name: Get Build Cache
|
||||
id: build-cache
|
||||
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
||||
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
|
||||
with:
|
||||
path: apps/desktop/build
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-build
|
||||
|
||||
- name: Setup Safari Cache
|
||||
id: safari-cache
|
||||
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
||||
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
|
||||
with:
|
||||
path: apps/browser/dist/Safari
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-safari-extension
|
||||
@@ -750,12 +750,12 @@ jobs:
|
||||
working-directory: apps/desktop
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ needs.setup.outputs.branch-name }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
@@ -773,14 +773,14 @@ jobs:
|
||||
|
||||
- name: Get Build Cache
|
||||
id: build-cache
|
||||
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
||||
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
|
||||
with:
|
||||
path: apps/desktop/build
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-build
|
||||
|
||||
- name: Setup Safari Cache
|
||||
id: safari-cache
|
||||
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
||||
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
|
||||
with:
|
||||
path: apps/browser/dist/Safari
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-safari-extension
|
||||
@@ -1010,7 +1010,7 @@ jobs:
|
||||
- release
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Setup git config
|
||||
run: |
|
||||
|
||||
2
.github/workflows/release-desktop.yml
vendored
2
.github/workflows/release-desktop.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
release-channel: ${{ steps.release-channel.outputs.channel }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Branch check
|
||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||
|
||||
2
.github/workflows/release-web.yml
vendored
2
.github/workflows/release-web.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
tag_version: ${{ steps.version.outputs.tag }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Branch check
|
||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||
|
||||
6
.github/workflows/scan.yml
vendored
6
.github/workflows/scan.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
@@ -46,7 +46,7 @@ jobs:
|
||||
--output-path . ${{ env.INCREMENTAL }}
|
||||
|
||||
- name: Upload Checkmarx results to GitHub
|
||||
uses: github/codeql-action/upload-sarif@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13
|
||||
uses: github/codeql-action/upload-sarif@662472033e021d55d94146f66f6058822b0b39fd # v3.27.0
|
||||
with:
|
||||
sarif_file: cx_result.sarif
|
||||
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
@@ -40,7 +40,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Get Node Version
|
||||
id: retrieve-node-version
|
||||
@@ -50,7 +50,7 @@ jobs:
|
||||
echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
@@ -120,7 +120,7 @@ jobs:
|
||||
sudo apt-get install -y gnome-keyring dbus-x11
|
||||
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Build
|
||||
working-directory: ./apps/desktop/desktop_native
|
||||
|
||||
6
.github/workflows/version-bump.yml
vendored
6
.github/workflows/version-bump.yml
vendored
@@ -57,7 +57,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Checkout Branch
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: main
|
||||
|
||||
@@ -85,7 +85,7 @@ jobs:
|
||||
github-gpg-private-key-passphrase"
|
||||
|
||||
- name: Import GPG key
|
||||
uses: crazy-max/ghaction-import-gpg@01dd5d3ca463c7f10f7f4f7b4f177225ac661ee4 # v6.1.0
|
||||
uses: crazy-max/ghaction-import-gpg@cb9bde2e2525e640591a934b1fd28eef1dcaf5e5 # v6.2.0
|
||||
with:
|
||||
gpg_private_key: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key }}
|
||||
passphrase: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key-passphrase }}
|
||||
@@ -532,7 +532,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout Branch
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: main
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import { matches, mock } from "jest-mock-extended";
|
||||
import { BehaviorSubject, ReplaySubject, firstValueFrom, of, timeout } from "rxjs";
|
||||
|
||||
import { AccountInfo, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import {
|
||||
Account,
|
||||
AccountInfo,
|
||||
AccountService,
|
||||
} from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { AvatarService } from "@bitwarden/common/auth/abstractions/avatar.service";
|
||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||
@@ -14,7 +18,7 @@ import { AccountSwitcherService } from "./account-switcher.service";
|
||||
|
||||
describe("AccountSwitcherService", () => {
|
||||
let accountsSubject: BehaviorSubject<Record<UserId, AccountInfo>>;
|
||||
let activeAccountSubject: BehaviorSubject<{ id: UserId } & AccountInfo>;
|
||||
let activeAccountSubject: BehaviorSubject<Account | null>;
|
||||
let authStatusSubject: ReplaySubject<Record<UserId, AuthenticationStatus>>;
|
||||
|
||||
const accountService = mock<AccountService>();
|
||||
@@ -29,7 +33,7 @@ describe("AccountSwitcherService", () => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
accountsSubject = new BehaviorSubject<Record<UserId, AccountInfo>>(null);
|
||||
activeAccountSubject = new BehaviorSubject<{ id: UserId } & AccountInfo>(null);
|
||||
activeAccountSubject = new BehaviorSubject<Account | null>(null);
|
||||
authStatusSubject = new ReplaySubject<Record<UserId, AuthenticationStatus>>(1);
|
||||
|
||||
// Use subject to allow for easy updates
|
||||
|
||||
@@ -940,13 +940,16 @@ export default class AutofillService implements AutofillServiceInterface {
|
||||
|
||||
if (options.allowTotpAutofill) {
|
||||
await Promise.all(
|
||||
totps.map(async (t) => {
|
||||
totps.map(async (t, i) => {
|
||||
if (Object.prototype.hasOwnProperty.call(filledFields, t.opid)) {
|
||||
return;
|
||||
}
|
||||
|
||||
filledFields[t.opid] = t;
|
||||
const totpValue = await this.totpService.getCode(login.totp);
|
||||
let totpValue = await this.totpService.getCode(login.totp);
|
||||
if (totpValue.length == totps.length) {
|
||||
totpValue = totpValue.charAt(i);
|
||||
}
|
||||
AutofillService.fillByOpid(fillScript, t, totpValue);
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -1347,14 +1347,17 @@ export default class MainBackground {
|
||||
if (flagEnabled("sdk")) {
|
||||
// Warn if the SDK for some reason can't be initialized
|
||||
let supported = false;
|
||||
let error: Error;
|
||||
try {
|
||||
supported = await firstValueFrom(this.sdkService.supported$);
|
||||
} catch (e) {
|
||||
// Do nothing.
|
||||
error = e;
|
||||
}
|
||||
|
||||
if (!supported) {
|
||||
this.sdkService.failedToInitialize().catch((e) => this.logService.error(e));
|
||||
this.sdkService
|
||||
.failedToInitialize("background", error)
|
||||
.catch((e) => this.logService.error(e));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ChangeDetectorRef, Component, NgZone, OnDestroy, OnInit, inject } from "@angular/core";
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { NavigationEnd, Router, RouterOutlet } from "@angular/router";
|
||||
import { Subject, takeUntil, firstValueFrom, concatMap, filter, tap, catchError, of } from "rxjs";
|
||||
import { Subject, takeUntil, firstValueFrom, concatMap, filter, tap } from "rxjs";
|
||||
|
||||
import { LogoutReason } from "@bitwarden/auth/common";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
@@ -71,21 +71,24 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
) {
|
||||
if (flagEnabled("sdk")) {
|
||||
// Warn if the SDK for some reason can't be initialized
|
||||
this.sdkService.supported$
|
||||
.pipe(
|
||||
takeUntilDestroyed(),
|
||||
catchError(() => {
|
||||
return of(false);
|
||||
}),
|
||||
)
|
||||
.subscribe((supported) => {
|
||||
this.sdkService.supported$.pipe(takeUntilDestroyed()).subscribe({
|
||||
next: (supported) => {
|
||||
if (!supported) {
|
||||
this.logService.debug("SDK is not supported");
|
||||
this.sdkService.failedToInitialize().catch((e) => this.logService.error(e));
|
||||
this.sdkService
|
||||
.failedToInitialize("popup", undefined)
|
||||
.catch((e) => this.logService.error(e));
|
||||
} else {
|
||||
this.logService.debug("SDK is supported");
|
||||
}
|
||||
});
|
||||
},
|
||||
error: (e: unknown) => {
|
||||
this.sdkService
|
||||
.failedToInitialize("popup", e as Error)
|
||||
.catch((e) => this.logService.error(e));
|
||||
this.logService.error(e);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -872,7 +872,7 @@ export class ServiceContainer {
|
||||
}
|
||||
|
||||
if (!supported) {
|
||||
this.sdkService.failedToInitialize().catch((e) => this.logService.error(e));
|
||||
this.sdkService.failedToInitialize("cli").catch((e) => this.logService.error(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
.subscribe((supported) => {
|
||||
if (!supported) {
|
||||
this.logService.debug("SDK is not supported");
|
||||
this.sdkService.failedToInitialize().catch((e) => this.logService.error(e));
|
||||
this.sdkService.failedToInitialize("desktop").catch((e) => this.logService.error(e));
|
||||
} else {
|
||||
this.logService.debug("SDK is supported");
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ export class AppComponent implements OnDestroy, OnInit {
|
||||
.subscribe((supported) => {
|
||||
if (!supported) {
|
||||
this.logService.debug("SDK is not supported");
|
||||
this.sdkService.failedToInitialize().catch((e) => this.logService.error(e));
|
||||
this.sdkService.failedToInitialize("web").catch((e) => this.logService.error(e));
|
||||
} else {
|
||||
this.logService.debug("SDK is supported");
|
||||
}
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
<h1 bitTypography="h1" class="tw-mt-16 tw-pb-2.5 !tw-text-danger">{{ "dangerZone" | i18n }}</h1>
|
||||
|
||||
<div class="tw-rounded tw-border tw-border-solid tw-border-danger-600 tw-p-5">
|
||||
<p>{{ "dangerZoneDesc" | i18n }}</p>
|
||||
<p>
|
||||
{{
|
||||
(accountDeprovisioningEnabled$ | async) && content.children.length === 1
|
||||
? ("dangerZoneDescSingular" | i18n)
|
||||
: ("dangerZoneDesc" | i18n)
|
||||
}}
|
||||
</p>
|
||||
|
||||
<div class="tw-flex tw-flex-row tw-gap-2">
|
||||
<div #content class="tw-flex tw-flex-row tw-gap-2">
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import { Component } from "@angular/core";
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { TypographyModule } from "@bitwarden/components";
|
||||
|
||||
/**
|
||||
@@ -10,6 +14,15 @@ import { TypographyModule } from "@bitwarden/components";
|
||||
selector: "app-danger-zone",
|
||||
templateUrl: "danger-zone.component.html",
|
||||
standalone: true,
|
||||
imports: [TypographyModule, JslibModule],
|
||||
imports: [TypographyModule, JslibModule, CommonModule],
|
||||
})
|
||||
export class DangerZoneComponent {}
|
||||
export class DangerZoneComponent implements OnInit {
|
||||
constructor(private configService: ConfigService) {}
|
||||
accountDeprovisioningEnabled$: Observable<boolean>;
|
||||
|
||||
ngOnInit(): void {
|
||||
this.accountDeprovisioningEnabled$ = this.configService.getFeatureFlag$(
|
||||
FeatureFlag.AccountDeprovisioning,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,12 @@
|
||||
Customize
|
||||
</button>
|
||||
</div>
|
||||
<div *ngIf="managingOrganization$ | async as managingOrganization">
|
||||
{{ "accountIsManagedMessage" | i18n: managingOrganization?.name }}
|
||||
<a href="https://bitwarden.com/help/claimed-accounts">
|
||||
<i class="bwi bwi-question-circle" aria-hidden="true"></i>
|
||||
</a>
|
||||
</div>
|
||||
<app-account-fingerprint
|
||||
[fingerprintMaterial]="fingerprintMaterial"
|
||||
fingerprintLabel="{{ 'yourAccountsFingerprint' | i18n }}"
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||
import { FormControl, FormGroup } from "@angular/forms";
|
||||
import { firstValueFrom, map, Subject, takeUntil } from "rxjs";
|
||||
import { firstValueFrom, map, Observable, of, Subject, switchMap, takeUntil } from "rxjs";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { UpdateProfileRequest } from "@bitwarden/common/auth/models/request/update-profile.request";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ProfileResponse } from "@bitwarden/common/models/response/profile.response";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
@@ -19,6 +23,7 @@ export class ProfileComponent implements OnInit, OnDestroy {
|
||||
loading = true;
|
||||
profile: ProfileResponse;
|
||||
fingerprintMaterial: string;
|
||||
managingOrganization$: Observable<Organization>;
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
protected formGroup = new FormGroup({
|
||||
@@ -32,6 +37,8 @@ export class ProfileComponent implements OnInit, OnDestroy {
|
||||
private accountService: AccountService,
|
||||
private dialogService: DialogService,
|
||||
private toastService: ToastService,
|
||||
private configService: ConfigService,
|
||||
private organizationService: OrganizationService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -40,6 +47,19 @@ export class ProfileComponent implements OnInit, OnDestroy {
|
||||
this.fingerprintMaterial = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
this.managingOrganization$ = this.configService
|
||||
.getFeatureFlag$(FeatureFlag.AccountDeprovisioning)
|
||||
.pipe(
|
||||
switchMap((isAccountDeprovisioningEnabled) =>
|
||||
isAccountDeprovisioningEnabled
|
||||
? this.organizationService.organizations$.pipe(
|
||||
map((organizations) =>
|
||||
organizations.find((o) => o.userIsManagedByOrganization === true),
|
||||
),
|
||||
)
|
||||
: of(null),
|
||||
),
|
||||
);
|
||||
this.formGroup.get("name").setValue(this.profile.name);
|
||||
this.formGroup.get("email").setValue(this.profile.email);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { AccountInfo } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { Account } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { DeviceTrustServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust.service.abstraction";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
import { VerificationType } from "@bitwarden/common/auth/enums/verification-type";
|
||||
@@ -46,10 +46,7 @@ export class UserKeyRotationService {
|
||||
* Creates a new user key and re-encrypts all required data with the it.
|
||||
* @param masterPassword current master password (used for validation)
|
||||
*/
|
||||
async rotateUserKeyAndEncryptedData(
|
||||
masterPassword: string,
|
||||
user: { id: UserId } & AccountInfo,
|
||||
): Promise<void> {
|
||||
async rotateUserKeyAndEncryptedData(masterPassword: string, user: Account): Promise<void> {
|
||||
this.logService.info("[Userkey rotation] Starting user key rotation...");
|
||||
if (!masterPassword) {
|
||||
this.logService.info("[Userkey rotation] Invalid master password provided. Aborting!");
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
<bit-tab label="Raw Data + members">
|
||||
<tools-password-health-members></tools-password-health-members>
|
||||
</bit-tab>
|
||||
<bit-tab label="Raw Data + uri">
|
||||
<tools-password-health-members-uri></tools-password-health-members-uri>
|
||||
</bit-tab>
|
||||
<!-- <bit-tab label="{{ 'allApplicationsWithCount' | i18n: apps.length }}">
|
||||
<h2 bitTypography="h2">{{ "allApplications" | i18n }}</h2>
|
||||
<tools-application-table></tools-application-table>
|
||||
|
||||
@@ -11,6 +11,7 @@ import { HeaderModule } from "../../layouts/header/header.module";
|
||||
|
||||
import { ApplicationTableComponent } from "./application-table.component";
|
||||
import { NotifiedMembersTableComponent } from "./notified-members-table.component";
|
||||
import { PasswordHealthMembersURIComponent } from "./password-health-members-uri.component";
|
||||
import { PasswordHealthMembersComponent } from "./password-health-members.component";
|
||||
import { PasswordHealthComponent } from "./password-health.component";
|
||||
|
||||
@@ -32,6 +33,7 @@ export enum AccessIntelligenceTabType {
|
||||
HeaderModule,
|
||||
PasswordHealthComponent,
|
||||
PasswordHealthMembersComponent,
|
||||
PasswordHealthMembersURIComponent,
|
||||
NotifiedMembersTableComponent,
|
||||
TabsModule,
|
||||
],
|
||||
|
||||
@@ -11,5 +11,5 @@ import { ButtonModule, NoItemsModule, Icons } from "@bitwarden/components";
|
||||
imports: [ButtonModule, CommonModule, JslibModule, NoItemsModule],
|
||||
})
|
||||
export class NoPriorityAppsComponent {
|
||||
noItemsIcon = Icons.NoResults;
|
||||
noItemsIcon = Icons.Security;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
<bit-container>
|
||||
<p>{{ "passwordsReportDesc" | i18n }}</p>
|
||||
<div *ngIf="loading">
|
||||
<i
|
||||
class="bwi bwi-spinner bwi-spin tw-text-muted"
|
||||
title="{{ 'loading' | i18n }}"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
|
||||
</div>
|
||||
<div class="tw-mt-4" *ngIf="!loading">
|
||||
<bit-table [dataSource]="dataSource">
|
||||
<ng-container header>
|
||||
<tr bitRow>
|
||||
<th bitCell bitSortable="hostURI">{{ "application" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "weakness" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "timesReused" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "timesExposed" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "totalMembers" | i18n }}</th>
|
||||
</tr>
|
||||
</ng-container>
|
||||
<ng-template body let-rows$>
|
||||
<tr bitRow *ngFor="let r of rows$ | async">
|
||||
<td bitCell>
|
||||
<ng-container>
|
||||
<span>{{ r.hostURI }}</span>
|
||||
</ng-container>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right">
|
||||
<span
|
||||
bitBadge
|
||||
*ngIf="passwordStrengthMap.has(r.id)"
|
||||
[variant]="passwordStrengthMap.get(r.id)[1]"
|
||||
>
|
||||
{{ passwordStrengthMap.get(r.id)[0] | i18n }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right">
|
||||
<span bitBadge *ngIf="passwordUseMap.has(r.login.password)" variant="warning">
|
||||
{{ "reusedXTimes" | i18n: passwordUseMap.get(r.login.password) }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right">
|
||||
<span bitBadge *ngIf="exposedPasswordMap.has(r.id)" variant="warning">
|
||||
{{ "exposedXTimes" | i18n: exposedPasswordMap.get(r.id) }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right" data-testid="total-membership">
|
||||
{{ totalMembersMap.get(r.id) || 0 }}
|
||||
</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
</bit-table>
|
||||
</div>
|
||||
</bit-container>
|
||||
@@ -0,0 +1,61 @@
|
||||
import { ComponentFixture, TestBed } from "@angular/core/testing";
|
||||
import { ActivatedRoute, convertToParamMap } from "@angular/router";
|
||||
import { mock, MockProxy } from "jest-mock-extended";
|
||||
import { of } from "rxjs";
|
||||
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { PasswordHealthService } from "@bitwarden/bit-common/tools/reports/access-intelligence";
|
||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { TableModule } from "@bitwarden/components";
|
||||
|
||||
import { LooseComponentsModule } from "../../shared";
|
||||
import { PipesModule } from "../../vault/individual-vault/pipes/pipes.module";
|
||||
|
||||
import { PasswordHealthMembersURIComponent } from "./password-health-members-uri.component";
|
||||
|
||||
describe("PasswordHealthMembersUriComponent", () => {
|
||||
let component: PasswordHealthMembersURIComponent;
|
||||
let fixture: ComponentFixture<PasswordHealthMembersURIComponent>;
|
||||
let cipherServiceMock: MockProxy<CipherService>;
|
||||
const passwordHealthServiceMock = mock<PasswordHealthService>();
|
||||
|
||||
const activeRouteParams = convertToParamMap({ organizationId: "orgId" });
|
||||
|
||||
beforeEach(async () => {
|
||||
cipherServiceMock = mock<CipherService>();
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [PasswordHealthMembersURIComponent, PipesModule, TableModule, LooseComponentsModule],
|
||||
providers: [
|
||||
{ provide: CipherService, useValue: cipherServiceMock },
|
||||
{ provide: I18nService, useValue: mock<I18nService>() },
|
||||
{ provide: AuditService, useValue: mock<AuditService>() },
|
||||
{ provide: OrganizationService, useValue: mock<OrganizationService>() },
|
||||
{
|
||||
provide: PasswordStrengthServiceAbstraction,
|
||||
useValue: mock<PasswordStrengthServiceAbstraction>(),
|
||||
},
|
||||
{ provide: PasswordHealthService, useValue: passwordHealthServiceMock },
|
||||
{
|
||||
provide: ActivatedRoute,
|
||||
useValue: {
|
||||
paramMap: of(activeRouteParams),
|
||||
url: of([]),
|
||||
},
|
||||
},
|
||||
],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(PasswordHealthMembersURIComponent);
|
||||
component = fixture.componentInstance;
|
||||
});
|
||||
|
||||
it("should initialize component", () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,108 @@
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { Component, DestroyRef, inject, OnInit } from "@angular/core";
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { map } from "rxjs";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { PasswordHealthService } from "@bitwarden/bit-common/tools/reports/access-intelligence";
|
||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import {
|
||||
BadgeModule,
|
||||
BadgeVariant,
|
||||
ContainerComponent,
|
||||
TableDataSource,
|
||||
TableModule,
|
||||
} from "@bitwarden/components";
|
||||
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { HeaderModule } from "../../layouts/header/header.module";
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { OrganizationBadgeModule } from "../../vault/individual-vault/organization-badge/organization-badge.module";
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { PipesModule } from "../../vault/individual-vault/pipes/pipes.module";
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: "tools-password-health-members-uri",
|
||||
templateUrl: "password-health-members-uri.component.html",
|
||||
imports: [
|
||||
BadgeModule,
|
||||
OrganizationBadgeModule,
|
||||
CommonModule,
|
||||
ContainerComponent,
|
||||
PipesModule,
|
||||
JslibModule,
|
||||
HeaderModule,
|
||||
TableModule,
|
||||
],
|
||||
providers: [PasswordHealthService],
|
||||
})
|
||||
export class PasswordHealthMembersURIComponent implements OnInit {
|
||||
passwordStrengthMap = new Map<string, [string, BadgeVariant]>();
|
||||
|
||||
weakPasswordCiphers: CipherView[] = [];
|
||||
|
||||
passwordUseMap = new Map<string, number>();
|
||||
|
||||
exposedPasswordMap = new Map<string, number>();
|
||||
|
||||
totalMembersMap = new Map<string, number>();
|
||||
|
||||
dataSource = new TableDataSource<CipherView>();
|
||||
|
||||
reportCiphers: (CipherView & { hostURI: string })[] = [];
|
||||
reportCipherURIs: string[] = [];
|
||||
|
||||
organization: Organization;
|
||||
|
||||
loading = true;
|
||||
|
||||
private destroyRef = inject(DestroyRef);
|
||||
|
||||
constructor(
|
||||
protected cipherService: CipherService,
|
||||
protected passwordStrengthService: PasswordStrengthServiceAbstraction,
|
||||
protected organizationService: OrganizationService,
|
||||
protected auditService: AuditService,
|
||||
protected i18nService: I18nService,
|
||||
protected activatedRoute: ActivatedRoute,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.activatedRoute.paramMap
|
||||
.pipe(
|
||||
takeUntilDestroyed(this.destroyRef),
|
||||
map(async (params) => {
|
||||
const organizationId = params.get("organizationId");
|
||||
await this.setCiphers(organizationId);
|
||||
}),
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
async setCiphers(organizationId: string) {
|
||||
const passwordHealthService = new PasswordHealthService(
|
||||
this.passwordStrengthService,
|
||||
this.auditService,
|
||||
this.cipherService,
|
||||
organizationId,
|
||||
);
|
||||
|
||||
await passwordHealthService.generateReport();
|
||||
|
||||
this.dataSource.data = passwordHealthService.groupCiphersByLoginUri();
|
||||
this.exposedPasswordMap = passwordHealthService.exposedPasswordMap;
|
||||
this.passwordStrengthMap = passwordHealthService.passwordStrengthMap;
|
||||
this.passwordUseMap = passwordHealthService.passwordUseMap;
|
||||
this.totalMembersMap = passwordHealthService.totalMembersMap;
|
||||
this.loading = false;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,38 @@
|
||||
<bit-container>
|
||||
<p>{{ "passwordsReportDesc" | i18n }}</p>
|
||||
<div *ngIf="loading">
|
||||
<i
|
||||
class="bwi bwi-spinner bwi-spin tw-text-muted"
|
||||
title="{{ 'loading' | i18n }}"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
|
||||
<p>{{ "passwordsReportDesc" | i18n }}</p>
|
||||
<div *ngIf="loading">
|
||||
<i
|
||||
class="bwi bwi-spinner bwi-spin tw-text-muted"
|
||||
title="{{ 'loading' | i18n }}"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
|
||||
</div>
|
||||
<div class="tw-mt-4" *ngIf="!dataSource.data.length">
|
||||
<tools-no-priority-apps></tools-no-priority-apps>
|
||||
</div>
|
||||
<div class="tw-mt-4 tw-flex tw-flex-col" *ngIf="!loading && dataSource.data.length">
|
||||
<div class="tw-flex tw-gap-6">
|
||||
<tools-card
|
||||
class="tw-flex-1"
|
||||
[title]="'atRiskMembers' | i18n"
|
||||
[value]="totalMembersMap.size - 3"
|
||||
[maxValue]="totalMembersMap.size"
|
||||
>
|
||||
</tools-card>
|
||||
<tools-card
|
||||
class="tw-flex-1"
|
||||
[title]="'atRiskApplications' | i18n"
|
||||
[value]="totalMembersMap.size - 1"
|
||||
[maxValue]="totalMembersMap.size"
|
||||
>
|
||||
</tools-card>
|
||||
</div>
|
||||
<div *ngIf="!dataSource.data.length">
|
||||
<tools-no-priority-apps></tools-no-priority-apps>
|
||||
<div class="tw-flex tw-mt-8 tw-mb-4 tw-gap-4">
|
||||
<bit-search class="tw-grow" [formControl]="searchControl"></bit-search>
|
||||
<button class="tw-rounded-lg" type="button" buttonType="secondary" bitButton>
|
||||
<i class="bwi bwi-star-f tw-mr-2"></i>
|
||||
{{ "markAppAsCritical" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="tw-mt-4 tw-flex tw-flex-col" *ngIf="!loading && dataSource.data.length">
|
||||
<div class="tw-flex tw-gap-6">
|
||||
@@ -30,7 +53,15 @@
|
||||
</div>
|
||||
<div class="tw-flex tw-mt-8 tw-mb-4 tw-gap-4">
|
||||
<bit-search class="tw-grow" [formControl]="searchControl"></bit-search>
|
||||
<button class="tw-rounded-lg" type="button" buttonType="secondary" bitButton>
|
||||
<button
|
||||
class="tw-rounded-lg"
|
||||
type="button"
|
||||
buttonType="secondary"
|
||||
[disabled]="!selectedIds.size"
|
||||
bitButton
|
||||
[bitAction]="markAppsAsCritical"
|
||||
appA11yTitle="{{ 'markAppAsCritical' | i18n }}"
|
||||
>
|
||||
<i class="bwi bwi-star-f tw-mr-2"></i>
|
||||
{{ "markAppAsCritical" | i18n }}
|
||||
</button>
|
||||
@@ -47,9 +78,14 @@
|
||||
</tr>
|
||||
</ng-container>
|
||||
<ng-template body let-rows$>
|
||||
<tr bitRow *ngFor="let r of rows$ | async">
|
||||
<tr bitRow *ngFor="let r of rows$ | async; trackBy: trackByFunction">
|
||||
<td bitCell>
|
||||
<app-vault-icon [cipher]="r"></app-vault-icon>
|
||||
<input
|
||||
bitCheckbox
|
||||
type="checkbox"
|
||||
[checked]="selectedIds.has(r.id)"
|
||||
(change)="onCheckboxChange(r.id, $event)"
|
||||
/>
|
||||
</td>
|
||||
<td bitCell>
|
||||
<ng-container>
|
||||
@@ -84,4 +120,4 @@
|
||||
</ng-template>
|
||||
</bit-table>
|
||||
</div>
|
||||
</bit-container>
|
||||
</div>
|
||||
|
||||
@@ -11,7 +11,13 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { BadgeVariant, SearchModule, TableDataSource, TableModule } from "@bitwarden/components";
|
||||
import {
|
||||
BadgeVariant,
|
||||
SearchModule,
|
||||
TableDataSource,
|
||||
TableModule,
|
||||
ToastService,
|
||||
} from "@bitwarden/components";
|
||||
import { CardComponent } from "@bitwarden/tools-card";
|
||||
|
||||
import { HeaderModule } from "../../layouts/header/header.module";
|
||||
@@ -53,6 +59,8 @@ export class PasswordHealthMembersComponent implements OnInit {
|
||||
|
||||
loading = true;
|
||||
|
||||
selectedIds: Set<number> = new Set<number>();
|
||||
|
||||
protected searchControl = new FormControl("", { nonNullable: true });
|
||||
|
||||
private destroyRef = inject(DestroyRef);
|
||||
@@ -63,6 +71,7 @@ export class PasswordHealthMembersComponent implements OnInit {
|
||||
protected auditService: AuditService,
|
||||
protected i18nService: I18nService,
|
||||
protected activatedRoute: ActivatedRoute,
|
||||
protected toastService: ToastService,
|
||||
) {
|
||||
this.searchControl.valueChanges
|
||||
.pipe(debounceTime(200), takeUntilDestroyed())
|
||||
@@ -91,7 +100,7 @@ export class PasswordHealthMembersComponent implements OnInit {
|
||||
|
||||
await passwordHealthService.generateReport();
|
||||
|
||||
this.dataSource.data = passwordHealthService.reportCiphers;
|
||||
this.dataSource.data = []; //passwordHealthService.reportCiphers;
|
||||
|
||||
this.exposedPasswordMap = passwordHealthService.exposedPasswordMap;
|
||||
this.passwordStrengthMap = passwordHealthService.passwordStrengthMap;
|
||||
@@ -99,4 +108,32 @@ export class PasswordHealthMembersComponent implements OnInit {
|
||||
this.totalMembersMap = passwordHealthService.totalMembersMap;
|
||||
this.loading = false;
|
||||
}
|
||||
|
||||
markAppsAsCritical = async () => {
|
||||
// TODO: Send to API once implemented
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
this.selectedIds.clear();
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("appsMarkedAsCritical"),
|
||||
});
|
||||
resolve(true);
|
||||
}, 1000);
|
||||
});
|
||||
};
|
||||
|
||||
trackByFunction(_: number, item: CipherView) {
|
||||
return item.id;
|
||||
}
|
||||
|
||||
onCheckboxChange(id: number, event: Event) {
|
||||
const isChecked = (event.target as HTMLInputElement).checked;
|
||||
if (isChecked) {
|
||||
this.selectedIds.add(id);
|
||||
} else {
|
||||
this.selectedIds.delete(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,9 @@
|
||||
"markAppAsCritical": {
|
||||
"message": "Mark app as critical"
|
||||
},
|
||||
"appsMarkedAsCritical": {
|
||||
"message": "Apps marked as critical"
|
||||
},
|
||||
"application": {
|
||||
"message": "Application"
|
||||
},
|
||||
@@ -1713,6 +1716,9 @@
|
||||
"dangerZoneDesc": {
|
||||
"message": "Careful, these actions are not reversible!"
|
||||
},
|
||||
"dangerZoneDescSingular": {
|
||||
"message": "Careful, this action is not reversible!"
|
||||
},
|
||||
"deauthorizeSessions": {
|
||||
"message": "Deauthorize sessions"
|
||||
},
|
||||
@@ -1725,6 +1731,15 @@
|
||||
"sessionsDeauthorized": {
|
||||
"message": "All sessions deauthorized"
|
||||
},
|
||||
"accountIsManagedMessage": {
|
||||
"message": "This account is managed by $ORGANIZATIONNAME$",
|
||||
"placeholders": {
|
||||
"organizationName": {
|
||||
"content": "$1",
|
||||
"example": "Organization"
|
||||
}
|
||||
}
|
||||
},
|
||||
"purgeVault": {
|
||||
"message": "Purge vault"
|
||||
},
|
||||
|
||||
@@ -12,6 +12,13 @@ export const mockCiphers: any[] = [
|
||||
organizationUseTotp: false,
|
||||
login: {
|
||||
password: "123",
|
||||
hasUris: true,
|
||||
uris: [
|
||||
{ uri: "www.google.com" },
|
||||
{ uri: "accounts.google.com" },
|
||||
{ uri: "https://www.google.com" },
|
||||
{ uri: "https://www.google.com/login" },
|
||||
],
|
||||
},
|
||||
edit: false,
|
||||
viewPassword: true,
|
||||
|
||||
@@ -64,5 +64,16 @@ export const mockMemberCipherDetailsResponse: { data: any[] } = {
|
||||
"cbea34a8-bde4-46ad-9d19-b05001228xy4",
|
||||
],
|
||||
},
|
||||
{
|
||||
UserName: "Chris Finch Tester",
|
||||
Email: "chris.finch@wernhamhogg.uk",
|
||||
UsesKeyConnector: true,
|
||||
cipherIds: [
|
||||
"cbea34a8-bde4-46ad-9d19-b05001228ab2",
|
||||
"cbea34a8-bde4-46ad-9d19-b05001228cd3",
|
||||
"cbea34a8-bde4-46ad-9d19-b05001228xy4",
|
||||
"cbea34a8-bde4-46ad-9d19-b05001228ab1",
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -99,12 +99,12 @@ describe("PasswordHealthService", () => {
|
||||
|
||||
it("should calculate total members per cipher", () => {
|
||||
expect(service.totalMembersMap.size).toBeGreaterThan(0);
|
||||
expect(service.totalMembersMap.get("cbea34a8-bde4-46ad-9d19-b05001228ab1")).toBe(2);
|
||||
expect(service.totalMembersMap.get("cbea34a8-bde4-46ad-9d19-b05001228ab2")).toBe(4);
|
||||
expect(service.totalMembersMap.get("cbea34a8-bde4-46ad-9d19-b05001228cd3")).toBe(5);
|
||||
expect(service.totalMembersMap.get("cbea34a8-bde4-46ad-9d19-b05001228ab1")).toBe(3);
|
||||
expect(service.totalMembersMap.get("cbea34a8-bde4-46ad-9d19-b05001228ab2")).toBe(5);
|
||||
expect(service.totalMembersMap.get("cbea34a8-bde4-46ad-9d19-b05001228cd3")).toBe(6);
|
||||
expect(service.totalMembersMap.get("cbea34a8-bde4-46ad-9d19-b05001227nm5")).toBe(4);
|
||||
expect(service.totalMembersMap.get("cbea34a8-bde4-46ad-9d19-b05001227nm7")).toBe(1);
|
||||
expect(service.totalMembersMap.get("cbea34a8-bde4-46ad-9d19-b05001228xy4")).toBe(6);
|
||||
expect(service.totalMembersMap.get("cbea34a8-bde4-46ad-9d19-b05001228xy4")).toBe(7);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { Inject, Injectable } from "@angular/core";
|
||||
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { mockCiphers } from "@bitwarden/bit-common/tools/reports/access-intelligence/services/ciphers.mock";
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { mockMemberCipherDetailsResponse } from "@bitwarden/bit-common/tools/reports/access-intelligence/services/member-cipher-details-response.mock";
|
||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
|
||||
@@ -8,9 +12,6 @@ import { CipherType } from "@bitwarden/common/vault/enums";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { BadgeVariant } from "@bitwarden/components";
|
||||
|
||||
import { mockCiphers } from "./ciphers.mock";
|
||||
import { mockMemberCipherDetailsResponse } from "./member-cipher-details-response.mock";
|
||||
|
||||
@Injectable()
|
||||
export class PasswordHealthService {
|
||||
reportCiphers: CipherView[] = [];
|
||||
@@ -157,10 +158,27 @@ export class PasswordHealthService {
|
||||
}
|
||||
}
|
||||
|
||||
private checkForExistingCipher(ciph: CipherView) {
|
||||
checkForExistingCipher(ciph: CipherView) {
|
||||
if (!this.reportCipherIds.includes(ciph.id)) {
|
||||
this.reportCipherIds.push(ciph.id);
|
||||
this.reportCiphers.push(ciph);
|
||||
}
|
||||
}
|
||||
|
||||
groupCiphersByLoginUri(): CipherView[] {
|
||||
const cipherViews: CipherView[] = [];
|
||||
const cipherUris: string[] = [];
|
||||
const ciphers = this.reportCiphers;
|
||||
|
||||
ciphers.forEach((ciph) => {
|
||||
const uris = ciph.login?.uris ?? [];
|
||||
uris.map((u: { uri: string }) => {
|
||||
const uri = Utils.getHostname(u.uri).replace("www.", "");
|
||||
cipherUris.push(uri);
|
||||
cipherViews.push({ ...ciph, hostURI: uri } as CipherView & { hostURI: string });
|
||||
});
|
||||
});
|
||||
|
||||
return cipherViews;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,11 @@ import { MockProxy, mock } from "jest-mock-extended";
|
||||
import { BehaviorSubject } from "rxjs";
|
||||
|
||||
import { EmptyComponent } from "@bitwarden/angular/platform/guard/feature-flag.guard.spec";
|
||||
import { AccountInfo, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import {
|
||||
Account,
|
||||
AccountInfo,
|
||||
AccountService,
|
||||
} from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
||||
import { MasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
|
||||
@@ -30,7 +34,7 @@ describe("AuthGuard", () => {
|
||||
keyConnectorServiceRequiresAccountConversion,
|
||||
);
|
||||
const accountService: MockProxy<AccountService> = mock<AccountService>();
|
||||
const activeAccountSubject = new BehaviorSubject<{ id: UserId } & AccountInfo>(null);
|
||||
const activeAccountSubject = new BehaviorSubject<Account | null>(null);
|
||||
accountService.activeAccount$ = activeAccountSubject;
|
||||
activeAccountSubject.next(
|
||||
Object.assign(
|
||||
|
||||
@@ -6,7 +6,11 @@ import { BehaviorSubject, of } from "rxjs";
|
||||
|
||||
import { EmptyComponent } from "@bitwarden/angular/platform/guard/feature-flag.guard.spec";
|
||||
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
|
||||
import { AccountInfo, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import {
|
||||
Account,
|
||||
AccountInfo,
|
||||
AccountService,
|
||||
} from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { DeviceTrustServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust.service.abstraction";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
@@ -56,7 +60,7 @@ describe("lockGuard", () => {
|
||||
userVerificationService.hasMasterPassword.mockResolvedValue(setupParams.hasMasterPassword);
|
||||
|
||||
const accountService: MockProxy<AccountService> = mock<AccountService>();
|
||||
const activeAccountSubject = new BehaviorSubject<{ id: UserId } & AccountInfo>(null);
|
||||
const activeAccountSubject = new BehaviorSubject<Account | null>(null);
|
||||
accountService.activeAccount$ = activeAccountSubject;
|
||||
activeAccountSubject.next(
|
||||
Object.assign(
|
||||
|
||||
@@ -7,7 +7,7 @@ import { BehaviorSubject, firstValueFrom, Subject, switchMap, take, takeUntil }
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { InternalPolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options";
|
||||
import { AccountInfo, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { Account, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { DeviceTrustServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust.service.abstraction";
|
||||
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
@@ -26,7 +26,6 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
|
||||
import { KeySuffixOptions } from "@bitwarden/common/platform/enums";
|
||||
import { SyncService } from "@bitwarden/common/platform/sync";
|
||||
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { UserKey } from "@bitwarden/common/types/key";
|
||||
import {
|
||||
AsyncActionsModule,
|
||||
@@ -73,7 +72,7 @@ const clientTypeToSuccessRouteRecord: Partial<Record<ClientType, string>> = {
|
||||
export class LockV2Component implements OnInit, OnDestroy {
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
activeAccount: { id: UserId | undefined } & AccountInfo;
|
||||
activeAccount: Account | null;
|
||||
|
||||
clientType: ClientType;
|
||||
ClientType = ClientType;
|
||||
@@ -202,11 +201,15 @@ export class LockV2Component implements OnInit, OnDestroy {
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
private async handleActiveAccountChange(activeAccount: { id: UserId | undefined } & AccountInfo) {
|
||||
private async handleActiveAccountChange(activeAccount: Account | null) {
|
||||
this.activeAccount = activeAccount;
|
||||
|
||||
this.resetDataOnActiveAccountChange();
|
||||
|
||||
if (activeAccount == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setEmailAsPageSubtitle(activeAccount.email);
|
||||
|
||||
this.unlockOptions = await firstValueFrom(
|
||||
|
||||
@@ -295,7 +295,7 @@ describe("LoginStrategyService", () => {
|
||||
new IdentityTokenResponse({
|
||||
ForcePasswordReset: false,
|
||||
Kdf: KdfType.PBKDF2_SHA256,
|
||||
KdfIterations: PBKDF2KdfConfig.PRELOGIN_ITERATIONS.min - 1,
|
||||
KdfIterations: PBKDF2KdfConfig.PRELOGIN_ITERATIONS_MIN - 1,
|
||||
Key: "KEY",
|
||||
PrivateKey: "PRIVATE_KEY",
|
||||
ResetMasterPassword: false,
|
||||
@@ -309,7 +309,7 @@ describe("LoginStrategyService", () => {
|
||||
apiService.postPrelogin.mockResolvedValue(
|
||||
new PreloginResponse({
|
||||
Kdf: KdfType.PBKDF2_SHA256,
|
||||
KdfIterations: PBKDF2KdfConfig.PRELOGIN_ITERATIONS.min - 1,
|
||||
KdfIterations: PBKDF2KdfConfig.PRELOGIN_ITERATIONS_MIN - 1,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -321,7 +321,7 @@ describe("LoginStrategyService", () => {
|
||||
});
|
||||
|
||||
await expect(sut.logIn(credentials)).rejects.toThrow(
|
||||
`PBKDF2 iterations must be between ${PBKDF2KdfConfig.PRELOGIN_ITERATIONS.min} and ${PBKDF2KdfConfig.PRELOGIN_ITERATIONS.max}`,
|
||||
`PBKDF2 iterations must be at least ${PBKDF2KdfConfig.PRELOGIN_ITERATIONS_MIN}, but was ${PBKDF2KdfConfig.PRELOGIN_ITERATIONS_MIN - 1}; possible pre-login downgrade attack detected.`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { mock } from "jest-mock-extended";
|
||||
import { ReplaySubject, combineLatest, map } from "rxjs";
|
||||
|
||||
import { AccountInfo, AccountService } from "../src/auth/abstractions/account.service";
|
||||
import { Account, AccountInfo, AccountService } from "../src/auth/abstractions/account.service";
|
||||
import { UserId } from "../src/types/guid";
|
||||
|
||||
export function mockAccountServiceWith(
|
||||
@@ -30,7 +30,7 @@ export class FakeAccountService implements AccountService {
|
||||
// eslint-disable-next-line rxjs/no-exposed-subjects -- test class
|
||||
accountsSubject = new ReplaySubject<Record<UserId, AccountInfo>>(1);
|
||||
// eslint-disable-next-line rxjs/no-exposed-subjects -- test class
|
||||
activeAccountSubject = new ReplaySubject<{ id: UserId } & AccountInfo>(1);
|
||||
activeAccountSubject = new ReplaySubject<Account | null>(1);
|
||||
// eslint-disable-next-line rxjs/no-exposed-subjects -- test class
|
||||
accountActivitySubject = new ReplaySubject<Record<UserId, Date>>(1);
|
||||
private _activeUserId: UserId;
|
||||
|
||||
@@ -12,6 +12,8 @@ export type AccountInfo = {
|
||||
name: string | undefined;
|
||||
};
|
||||
|
||||
export type Account = { id: UserId } & AccountInfo;
|
||||
|
||||
export function accountInfoEqual(a: AccountInfo, b: AccountInfo) {
|
||||
if (a == null && b == null) {
|
||||
return true;
|
||||
@@ -32,7 +34,8 @@ export function accountInfoEqual(a: AccountInfo, b: AccountInfo) {
|
||||
|
||||
export abstract class AccountService {
|
||||
accounts$: Observable<Record<UserId, AccountInfo>>;
|
||||
activeAccount$: Observable<{ id: UserId | undefined } & AccountInfo>;
|
||||
|
||||
activeAccount$: Observable<Account | null>;
|
||||
|
||||
/**
|
||||
* Observable of the last activity time for each account.
|
||||
@@ -41,7 +44,7 @@ export abstract class AccountService {
|
||||
/** Account list in order of descending recency */
|
||||
sortedUserIds$: Observable<UserId[]>;
|
||||
/** Next account that is not the current active account */
|
||||
nextUpAccount$: Observable<{ id: UserId } & AccountInfo>;
|
||||
nextUpAccount$: Observable<Account>;
|
||||
/**
|
||||
* Updates the `accounts$` observable with the new account data.
|
||||
*
|
||||
|
||||
@@ -13,7 +13,7 @@ export type KdfConfig = PBKDF2KdfConfig | Argon2KdfConfig;
|
||||
*/
|
||||
export class PBKDF2KdfConfig {
|
||||
static ITERATIONS = new RangeWithDefault(600_000, 2_000_000, 600_000);
|
||||
static PRELOGIN_ITERATIONS = new RangeWithDefault(5000, 2_000_000, 600_000);
|
||||
static PRELOGIN_ITERATIONS_MIN = 5000;
|
||||
kdfType: KdfType.PBKDF2_SHA256 = KdfType.PBKDF2_SHA256;
|
||||
iterations: number;
|
||||
|
||||
@@ -38,9 +38,9 @@ export class PBKDF2KdfConfig {
|
||||
* A Valid PBKDF2 KDF configuration has KDF iterations between the 5000 and 2_000_000.
|
||||
*/
|
||||
validateKdfConfigForPrelogin(): void {
|
||||
if (!PBKDF2KdfConfig.PRELOGIN_ITERATIONS.inRange(this.iterations)) {
|
||||
if (PBKDF2KdfConfig.PRELOGIN_ITERATIONS_MIN > this.iterations) {
|
||||
throw new Error(
|
||||
`PBKDF2 iterations must be between ${PBKDF2KdfConfig.PRELOGIN_ITERATIONS.min} and ${PBKDF2KdfConfig.PRELOGIN_ITERATIONS.max}`,
|
||||
`PBKDF2 iterations must be at least ${PBKDF2KdfConfig.PRELOGIN_ITERATIONS_MIN}, but was ${this.iterations}; possible pre-login downgrade attack detected.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -58,9 +58,9 @@ export class Argon2KdfConfig {
|
||||
static PARALLELISM = new RangeWithDefault(1, 16, 4);
|
||||
static ITERATIONS = new RangeWithDefault(2, 10, 3);
|
||||
|
||||
static PRELOGIN_MEMORY = Argon2KdfConfig.MEMORY;
|
||||
static PRELOGIN_PARALLELISM = Argon2KdfConfig.PARALLELISM;
|
||||
static PRELOGIN_ITERATIONS = Argon2KdfConfig.ITERATIONS;
|
||||
static PRELOGIN_MEMORY_MIN = 16;
|
||||
static PRELOGIN_PARALLELISM_MIN = 1;
|
||||
static PRELOGIN_ITERATIONS_MIN = 2;
|
||||
|
||||
kdfType: KdfType.Argon2id = KdfType.Argon2id;
|
||||
iterations: number;
|
||||
@@ -86,7 +86,7 @@ export class Argon2KdfConfig {
|
||||
|
||||
if (!Argon2KdfConfig.MEMORY.inRange(this.memory)) {
|
||||
throw new Error(
|
||||
`Argon2 memory must be between ${Argon2KdfConfig.MEMORY.min}mb and ${Argon2KdfConfig.MEMORY.max}mb`,
|
||||
`Argon2 memory must be between ${Argon2KdfConfig.MEMORY.min} MiB and ${Argon2KdfConfig.MEMORY.max} MiB`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -101,21 +101,21 @@ export class Argon2KdfConfig {
|
||||
* Validates the Argon2 KDF configuration for pre-login.
|
||||
*/
|
||||
validateKdfConfigForPrelogin(): void {
|
||||
if (!Argon2KdfConfig.PRELOGIN_ITERATIONS.inRange(this.iterations)) {
|
||||
if (Argon2KdfConfig.PRELOGIN_ITERATIONS_MIN > this.iterations) {
|
||||
throw new Error(
|
||||
`Argon2 iterations must be between ${Argon2KdfConfig.PRELOGIN_ITERATIONS.min} and ${Argon2KdfConfig.PRELOGIN_ITERATIONS.max}`,
|
||||
`Argon2 iterations must be at least ${Argon2KdfConfig.PRELOGIN_ITERATIONS_MIN}, but was ${this.iterations}; possible pre-login downgrade attack detected.`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!Argon2KdfConfig.PRELOGIN_MEMORY.inRange(this.memory)) {
|
||||
if (Argon2KdfConfig.PRELOGIN_MEMORY_MIN > this.memory) {
|
||||
throw new Error(
|
||||
`Argon2 memory must be between ${Argon2KdfConfig.PRELOGIN_MEMORY.min}mb and ${Argon2KdfConfig.PRELOGIN_MEMORY.max}mb`,
|
||||
`Argon2 memory must be at least ${Argon2KdfConfig.PRELOGIN_MEMORY_MIN} MiB, but was ${this.memory} MiB; possible pre-login downgrade attack detected.`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!Argon2KdfConfig.PRELOGIN_PARALLELISM.inRange(this.parallelism)) {
|
||||
if (Argon2KdfConfig.PRELOGIN_PARALLELISM_MIN > this.parallelism) {
|
||||
throw new Error(
|
||||
`Argon2 parallelism must be between ${Argon2KdfConfig.PRELOGIN_PARALLELISM.min} and ${Argon2KdfConfig.PRELOGIN_PARALLELISM.max}.`,
|
||||
`Argon2 parallelism must be at least ${Argon2KdfConfig.PRELOGIN_PARALLELISM_MIN}, but was ${this.parallelism}; possible pre-login downgrade attack detected.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,10 +88,10 @@ describe("accountService", () => {
|
||||
});
|
||||
|
||||
describe("activeAccount$", () => {
|
||||
it("should emit undefined if no account is active", () => {
|
||||
it("should emit null if no account is active", () => {
|
||||
const emissions = trackEmissions(sut.activeAccount$);
|
||||
|
||||
expect(emissions).toEqual([undefined]);
|
||||
expect(emissions).toEqual([null]);
|
||||
});
|
||||
|
||||
it("should emit the active account", async () => {
|
||||
@@ -100,7 +100,7 @@ describe("accountService", () => {
|
||||
activeAccountIdState.stateSubject.next(userId);
|
||||
|
||||
expect(emissions).toEqual([
|
||||
undefined, // initial value
|
||||
null, // initial value
|
||||
{ id: userId, ...userInfo },
|
||||
]);
|
||||
});
|
||||
@@ -258,10 +258,10 @@ describe("accountService", () => {
|
||||
activeAccountIdState.stateSubject.next(userId);
|
||||
});
|
||||
|
||||
it("should emit undefined if no account is provided", async () => {
|
||||
it("should emit null if no account is provided", async () => {
|
||||
await sut.switchAccount(null);
|
||||
const currentState = await firstValueFrom(sut.activeAccount$);
|
||||
expect(currentState).toBeUndefined();
|
||||
expect(currentState).toBeNull();
|
||||
});
|
||||
|
||||
it("should throw if the account does not exist", () => {
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
} from "rxjs";
|
||||
|
||||
import {
|
||||
Account,
|
||||
AccountInfo,
|
||||
InternalAccountService,
|
||||
accountInfoEqual,
|
||||
@@ -48,9 +49,9 @@ const LOGGED_OUT_INFO: AccountInfo = {
|
||||
/**
|
||||
* An rxjs map operator that extracts the UserId from an account, or throws if the account or UserId are null.
|
||||
*/
|
||||
export const getUserId = map<{ id: UserId | undefined }, UserId>((account) => {
|
||||
if (account?.id == null) {
|
||||
throw new Error("Null account or account ID");
|
||||
export const getUserId = map<Account | null, UserId>((account) => {
|
||||
if (account == null) {
|
||||
throw new Error("Null or undefined account");
|
||||
}
|
||||
|
||||
return account.id;
|
||||
@@ -59,8 +60,8 @@ export const getUserId = map<{ id: UserId | undefined }, UserId>((account) => {
|
||||
/**
|
||||
* An rxjs map operator that extracts the UserId from an account, or returns undefined if the account or UserId are null.
|
||||
*/
|
||||
export const getOptionalUserId = map<{ id: UserId | undefined }, UserId | undefined>(
|
||||
(account) => account?.id ?? undefined,
|
||||
export const getOptionalUserId = map<Account | null, UserId | null>(
|
||||
(account) => account?.id ?? null,
|
||||
);
|
||||
|
||||
export class AccountServiceImplementation implements InternalAccountService {
|
||||
@@ -68,10 +69,10 @@ export class AccountServiceImplementation implements InternalAccountService {
|
||||
private activeAccountIdState: GlobalState<UserId | undefined>;
|
||||
|
||||
accounts$: Observable<Record<UserId, AccountInfo>>;
|
||||
activeAccount$: Observable<{ id: UserId | undefined } & AccountInfo>;
|
||||
activeAccount$: Observable<Account | null>;
|
||||
accountActivity$: Observable<Record<UserId, Date>>;
|
||||
sortedUserIds$: Observable<UserId[]>;
|
||||
nextUpAccount$: Observable<{ id: UserId } & AccountInfo>;
|
||||
nextUpAccount$: Observable<Account>;
|
||||
|
||||
constructor(
|
||||
private messagingService: MessagingService,
|
||||
@@ -86,7 +87,7 @@ export class AccountServiceImplementation implements InternalAccountService {
|
||||
);
|
||||
this.activeAccount$ = this.activeAccountIdState.state$.pipe(
|
||||
combineLatestWith(this.accounts$),
|
||||
map(([id, accounts]) => (id ? { id, ...(accounts[id] as AccountInfo) } : undefined)),
|
||||
map(([id, accounts]) => (id ? ({ id, ...(accounts[id] as AccountInfo) } as Account) : null)),
|
||||
distinctUntilChanged((a, b) => a?.id === b?.id && accountInfoEqual(a, b)),
|
||||
shareReplay({ bufferSize: 1, refCount: false }),
|
||||
);
|
||||
|
||||
@@ -82,13 +82,6 @@ describe("KdfConfigService", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("validateKdfConfigForSetting(): should throw an error for invalid Argon2 memory", () => {
|
||||
const kdfConfig: Argon2KdfConfig = new Argon2KdfConfig(3, 1025, 4);
|
||||
expect(() => kdfConfig.validateKdfConfigForSetting()).toThrow(
|
||||
`Argon2 memory must be between ${Argon2KdfConfig.MEMORY.min}mb and ${Argon2KdfConfig.MEMORY.max}mb`,
|
||||
);
|
||||
});
|
||||
|
||||
it("validateKdfConfigForSetting(): should throw an error for invalid Argon2 parallelism", () => {
|
||||
const kdfConfig: Argon2KdfConfig = new Argon2KdfConfig(3, 64, 17);
|
||||
expect(() => kdfConfig.validateKdfConfigForSetting()).toThrow(
|
||||
@@ -108,70 +101,32 @@ describe("KdfConfigService", () => {
|
||||
|
||||
it("validateKdfConfigForPrelogin(): should throw an error for too low PBKDF2 iterations", () => {
|
||||
const kdfConfig: PBKDF2KdfConfig = new PBKDF2KdfConfig(
|
||||
PBKDF2KdfConfig.PRELOGIN_ITERATIONS.min - 1,
|
||||
PBKDF2KdfConfig.PRELOGIN_ITERATIONS_MIN - 1,
|
||||
);
|
||||
expect(() => kdfConfig.validateKdfConfigForPrelogin()).toThrow(
|
||||
`PBKDF2 iterations must be between ${PBKDF2KdfConfig.PRELOGIN_ITERATIONS.min} and ${PBKDF2KdfConfig.PRELOGIN_ITERATIONS.max}`,
|
||||
);
|
||||
});
|
||||
|
||||
it("validateKdfConfigForPrelogin(): should throw an error for too high PBKDF2 iterations", () => {
|
||||
const kdfConfig: PBKDF2KdfConfig = new PBKDF2KdfConfig(
|
||||
PBKDF2KdfConfig.PRELOGIN_ITERATIONS.max + 1,
|
||||
);
|
||||
expect(() => kdfConfig.validateKdfConfigForPrelogin()).toThrow(
|
||||
`PBKDF2 iterations must be between ${PBKDF2KdfConfig.PRELOGIN_ITERATIONS.min} and ${PBKDF2KdfConfig.PRELOGIN_ITERATIONS.max}`,
|
||||
`PBKDF2 iterations must be at least ${PBKDF2KdfConfig.PRELOGIN_ITERATIONS_MIN}, but was ${kdfConfig.iterations}; possible pre-login downgrade attack detected.`,
|
||||
);
|
||||
});
|
||||
|
||||
it("validateKdfConfigForPrelogin(): should throw an error for too low Argon2 iterations", () => {
|
||||
const kdfConfig: Argon2KdfConfig = new Argon2KdfConfig(
|
||||
Argon2KdfConfig.ITERATIONS.min - 1,
|
||||
Argon2KdfConfig.PRELOGIN_ITERATIONS_MIN - 1,
|
||||
64,
|
||||
4,
|
||||
);
|
||||
expect(() => kdfConfig.validateKdfConfigForPrelogin()).toThrow(
|
||||
`Argon2 iterations must be between ${Argon2KdfConfig.ITERATIONS.min} and ${Argon2KdfConfig.ITERATIONS.max}`,
|
||||
);
|
||||
});
|
||||
|
||||
it("validateKdfConfigForPrelogin(): should throw an error for too high Argon2 iterations", () => {
|
||||
const kdfConfig: Argon2KdfConfig = new Argon2KdfConfig(
|
||||
Argon2KdfConfig.PRELOGIN_ITERATIONS.max + 1,
|
||||
64,
|
||||
4,
|
||||
);
|
||||
expect(() => kdfConfig.validateKdfConfigForPrelogin()).toThrow(
|
||||
`Argon2 iterations must be between ${Argon2KdfConfig.ITERATIONS.min} and ${Argon2KdfConfig.ITERATIONS.max}`,
|
||||
`Argon2 iterations must be at least ${Argon2KdfConfig.PRELOGIN_ITERATIONS_MIN}, but was ${kdfConfig.iterations}; possible pre-login downgrade attack detected.`,
|
||||
);
|
||||
});
|
||||
|
||||
it("validateKdfConfigForPrelogin(): should throw an error for too low Argon2 memory", () => {
|
||||
const kdfConfig: Argon2KdfConfig = new Argon2KdfConfig(
|
||||
3,
|
||||
Argon2KdfConfig.PRELOGIN_MEMORY.min - 1,
|
||||
Argon2KdfConfig.PRELOGIN_MEMORY_MIN - 1,
|
||||
4,
|
||||
);
|
||||
expect(() => kdfConfig.validateKdfConfigForPrelogin()).toThrow(
|
||||
`Argon2 memory must be between ${Argon2KdfConfig.PRELOGIN_MEMORY.min}mb and ${Argon2KdfConfig.PRELOGIN_MEMORY.max}mb`,
|
||||
);
|
||||
});
|
||||
|
||||
it("validateKdfConfigForPrelogin(): should throw an error for too high Argon2 memory", () => {
|
||||
const kdfConfig: Argon2KdfConfig = new Argon2KdfConfig(
|
||||
3,
|
||||
Argon2KdfConfig.PRELOGIN_MEMORY.max + 1,
|
||||
4,
|
||||
);
|
||||
expect(() => kdfConfig.validateKdfConfigForPrelogin()).toThrow(
|
||||
`Argon2 memory must be between ${Argon2KdfConfig.PRELOGIN_MEMORY.min}mb and ${Argon2KdfConfig.PRELOGIN_MEMORY.max}mb`,
|
||||
);
|
||||
});
|
||||
|
||||
it("validateKdfConfigForPrelogin(): should throw an error for too high Argon2 parallelism", () => {
|
||||
const kdfConfig: Argon2KdfConfig = new Argon2KdfConfig(3, 64, 17);
|
||||
expect(() => kdfConfig.validateKdfConfigForPrelogin()).toThrow(
|
||||
`Argon2 parallelism must be between ${Argon2KdfConfig.PRELOGIN_PARALLELISM.min} and ${Argon2KdfConfig.PRELOGIN_PARALLELISM.max}`,
|
||||
`Argon2 memory must be at least ${Argon2KdfConfig.PRELOGIN_MEMORY_MIN} MiB, but was ${kdfConfig.memory} MiB; possible pre-login downgrade attack detected.`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,12 +9,12 @@ import { KeyService } from "../../../../key-management/src/abstractions/key.serv
|
||||
import { OrganizationApiServiceAbstraction } from "../../admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||
import { OrganizationAutoEnrollStatusResponse } from "../../admin-console/models/response/organization-auto-enroll-status.response";
|
||||
import { I18nService } from "../../platform/abstractions/i18n.service";
|
||||
import { AccountInfo, AccountService } from "../abstractions/account.service";
|
||||
import { Account, AccountInfo, AccountService } from "../abstractions/account.service";
|
||||
|
||||
import { PasswordResetEnrollmentServiceImplementation } from "./password-reset-enrollment.service.implementation";
|
||||
|
||||
describe("PasswordResetEnrollmentServiceImplementation", () => {
|
||||
const activeAccountSubject = new BehaviorSubject<{ id: UserId } & AccountInfo>(null);
|
||||
const activeAccountSubject = new BehaviorSubject<Account | null>(null);
|
||||
|
||||
let organizationApiService: MockProxy<OrganizationApiServiceAbstraction>;
|
||||
let accountService: MockProxy<AccountService>;
|
||||
|
||||
@@ -29,5 +29,5 @@ export abstract class SdkService {
|
||||
*/
|
||||
abstract userClient$(userId: UserId): Observable<BitwardenClient>;
|
||||
|
||||
abstract failedToInitialize(): Promise<void>;
|
||||
abstract failedToInitialize(category: string, error?: Error): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { TextEncoder } from "util";
|
||||
import { mock, MockProxy } from "jest-mock-extended";
|
||||
import { BehaviorSubject, of } from "rxjs";
|
||||
|
||||
import { AccountInfo, AccountService } from "../../../auth/abstractions/account.service";
|
||||
import { Account, AccountService } from "../../../auth/abstractions/account.service";
|
||||
import { UserId } from "../../../types/guid";
|
||||
import { CipherService } from "../../../vault/abstractions/cipher.service";
|
||||
import { SyncService } from "../../../vault/abstractions/sync/sync.service.abstraction";
|
||||
@@ -33,7 +33,7 @@ import { guidToRawFormat } from "./guid-utils";
|
||||
const RpId = "bitwarden.com";
|
||||
|
||||
describe("FidoAuthenticatorService", () => {
|
||||
const activeAccountSubject = new BehaviorSubject<{ id: UserId } & AccountInfo>({
|
||||
const activeAccountSubject = new BehaviorSubject<Account | null>({
|
||||
id: "testId" as UserId,
|
||||
email: "test@example.com",
|
||||
emailVerified: true,
|
||||
|
||||
@@ -130,7 +130,7 @@ export class DefaultSdkService implements SdkService {
|
||||
return client$;
|
||||
}
|
||||
|
||||
async failedToInitialize(): Promise<void> {
|
||||
async failedToInitialize(category: string, error?: Error): Promise<void> {
|
||||
// Only log on cloud instances
|
||||
if (
|
||||
this.platformUtilsService.isDev() ||
|
||||
@@ -139,9 +139,20 @@ export class DefaultSdkService implements SdkService {
|
||||
return;
|
||||
}
|
||||
|
||||
return this.apiService.send("POST", "/wasm-debug", null, false, false, null, (headers) => {
|
||||
headers.append("SDK-Version", "1.0.0");
|
||||
});
|
||||
return this.apiService.send(
|
||||
"POST",
|
||||
"/wasm-debug",
|
||||
{
|
||||
category: category,
|
||||
error: error?.message,
|
||||
},
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
(headers) => {
|
||||
headers.append("SDK-Version", "1.0.0");
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
private async initializeClient(
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Jsonify } from "type-fest";
|
||||
|
||||
import { awaitAsync, trackEmissions } from "../../../../spec";
|
||||
import { FakeStorageService } from "../../../../spec/fake-storage.service";
|
||||
import { AccountInfo } from "../../../auth/abstractions/account.service";
|
||||
import { Account } from "../../../auth/abstractions/account.service";
|
||||
import { UserId } from "../../../types/guid";
|
||||
import { LogService } from "../../abstractions/log.service";
|
||||
import { StorageServiceProvider } from "../../services/storage-service.provider";
|
||||
@@ -47,7 +47,7 @@ describe("DefaultActiveUserState", () => {
|
||||
const storageServiceProvider = mock<StorageServiceProvider>();
|
||||
const stateEventRegistrarService = mock<StateEventRegistrarService>();
|
||||
const logService = mock<LogService>();
|
||||
let activeAccountSubject: BehaviorSubject<{ id: UserId } & AccountInfo>;
|
||||
let activeAccountSubject: BehaviorSubject<Account | null>;
|
||||
|
||||
let singleUserStateProvider: DefaultSingleUserStateProvider;
|
||||
|
||||
@@ -63,7 +63,7 @@ describe("DefaultActiveUserState", () => {
|
||||
logService,
|
||||
);
|
||||
|
||||
activeAccountSubject = new BehaviorSubject<{ id: UserId } & AccountInfo>(undefined);
|
||||
activeAccountSubject = new BehaviorSubject<Account | null>(null);
|
||||
|
||||
userState = new DefaultActiveUserState(
|
||||
testKeyDefinition,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from "./search";
|
||||
export * from "./security";
|
||||
export * from "./no-access";
|
||||
export * from "./no-results";
|
||||
|
||||
50
libs/components/src/icon/icons/security.ts
Normal file
50
libs/components/src/icon/icons/security.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { svgIcon } from "../icon";
|
||||
|
||||
export const Security = svgIcon`
|
||||
<svg width="96" height="96" viewBox="0 0 96 96" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="96" height="96" class="tw-fill-background"/>
|
||||
<rect x="5" y="5" width="86" height="77" rx="7" class="tw-stroke-art-primary" stroke-width="2" stroke-linecap="round"/>
|
||||
<rect x="63" y="15" width="18" height="18" rx="3" class="tw-stroke-art-primary" stroke-width="2" stroke-linecap="round"/>
|
||||
<rect x="39" y="15" width="18" height="18" rx="3" class="tw-stroke-art-primary" stroke-width="2" stroke-linecap="round"/>
|
||||
<rect x="15" y="15" width="18" height="18" rx="3" class="tw-stroke-art-primary" stroke-width="2" stroke-linecap="round"/>
|
||||
<rect x="13" y="41" width="70" height="14" rx="7" class="tw-stroke-art-primary tw-fill-background" stroke-width="2" stroke-linecap="round"/>
|
||||
<path d="M21.0039 48.3526V45.5728" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M21.0039 48.3525L23.6272 47.4933" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M21.0039 48.3524L22.6279 50.6268" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M21.0029 48.3524L19.3789 50.6268" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M21.0022 48.3525L18.3789 47.4933" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M30.0039 48.3526V45.5728" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M30.0039 48.3525L32.6272 47.4933" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M30.0039 48.3524L31.6279 50.6268" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M30.0029 48.3524L28.3789 50.6268" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M30.0022 48.3525L27.3789 47.4933" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M39.0039 48.3526V45.5728" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M39.0039 48.3525L41.6272 47.4933" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M39.0039 48.3524L40.6279 50.6268" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M39.0029 48.3524L37.3789 50.6268" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M39.0022 48.3525L36.3789 47.4933" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M48.0039 48.3526V45.5728" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M48.0039 48.3525L50.6272 47.4933" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M48.0039 48.3524L49.6279 50.6268" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M48.0029 48.3524L46.3789 50.6268" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M48.0022 48.3525L45.3789 47.4933" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M57.0039 48.3526V45.5728" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M57.0039 48.3525L59.6272 47.4933" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M57.0039 48.3524L58.6279 50.6268" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M57.0029 48.3524L55.3789 50.6268" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M57.0022 48.3525L54.3789 47.4933" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M66.0039 48.3526V45.5728" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M66.0039 48.3525L68.6272 47.4933" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M66.0039 48.3524L67.6279 50.6268" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M66.0029 48.3524L64.3789 50.6268" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M66.0022 48.3525L63.3789 47.4933" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M75.0039 48.3526V45.5728" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M75.0039 48.3525L77.6272 47.4933" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M75.0039 48.3524L76.6279 50.6268" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M75.0029 48.3524L73.3789 50.6268" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M75.0022 48.3525L72.3789 47.4933" class="tw-stroke-art-accent" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<rect x="35" y="72" width="26" height="20" rx="2" class="tw-stroke-art-primary tw-fill-background" stroke-width="2"/>
|
||||
<rect x="47" y="78" width="2" height="8" rx="1" class="tw-stroke-art-accent"/>
|
||||
<path d="M55 71V69C55 65.134 51.866 62 48 62V62C44.134 62 41 65.134 41 69V71" class="tw-stroke-art-primary" stroke-width="2"/>
|
||||
</svg>
|
||||
`;
|
||||
@@ -12,7 +12,13 @@
|
||||
|
||||
<bit-form-field>
|
||||
<bit-label>{{ "number" | i18n }}</bit-label>
|
||||
<input id="cardNumber" bitInput formControlName="number" type="password" />
|
||||
<input
|
||||
id="cardNumber"
|
||||
bitInput
|
||||
formControlName="number"
|
||||
type="password"
|
||||
class="tw-font-mono"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
bitIconButton
|
||||
@@ -54,7 +60,7 @@
|
||||
|
||||
<bit-form-field disableMargin>
|
||||
<bit-label>{{ "securityCode" | i18n }}</bit-label>
|
||||
<input id="cardCode" bitInput formControlName="code" type="password" />
|
||||
<input id="cardCode" bitInput formControlName="code" type="password" class="tw-font-mono" />
|
||||
<button
|
||||
type="button"
|
||||
bitIconButton
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
formControlName="value"
|
||||
type="password"
|
||||
data-testid="custom-hidden-field"
|
||||
class="tw-font-mono"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
<bit-form-field>
|
||||
<bit-label>{{ "password" | i18n }}</bit-label>
|
||||
<input bitInput formControlName="password" type="password" />
|
||||
<input bitInput formControlName="password" type="password" class="tw-font-mono" />
|
||||
<bit-hint *ngIf="loginDetailsForm.controls.password.enabled">
|
||||
<ng-container *ngIf="newPasswordGenerated">
|
||||
{{ "securePasswordGenerated" | i18n }}
|
||||
@@ -106,7 +106,7 @@
|
||||
<p>{{ (canCaptureTotp ? "totpHelperWithCapture" : "totpHelper") | i18n }}</p>
|
||||
</bit-popover>
|
||||
</bit-label>
|
||||
<input bitInput formControlName="totp" type="password" />
|
||||
<input bitInput formControlName="totp" type="password" class="tw-font-mono" />
|
||||
<button
|
||||
type="button"
|
||||
bitIconButton
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
[value]="card.number"
|
||||
aria-readonly="true"
|
||||
data-testid="cardholder-number"
|
||||
class="tw-font-mono"
|
||||
/>
|
||||
<button
|
||||
bitSuffix
|
||||
@@ -63,6 +64,7 @@
|
||||
[value]="card.code"
|
||||
aria-readonly="true"
|
||||
data-testid="cardholder-code"
|
||||
class="tw-font-mono"
|
||||
/>
|
||||
<button
|
||||
bitSuffix
|
||||
|
||||
@@ -25,7 +25,14 @@
|
||||
</bit-form-field>
|
||||
<bit-form-field *ngIf="field.type === fieldType.Hidden" [disableReadOnlyBorder]="last">
|
||||
<bit-label>{{ field.name }}</bit-label>
|
||||
<input readonly bitInput type="password" [value]="field.value" aria-readonly="true" />
|
||||
<input
|
||||
readonly
|
||||
bitInput
|
||||
type="password"
|
||||
[value]="field.value"
|
||||
aria-readonly="true"
|
||||
class="tw-font-mono"
|
||||
/>
|
||||
<button
|
||||
bitSuffix
|
||||
type="button"
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
[value]="cipher.login.password"
|
||||
aria-readonly="true"
|
||||
data-testid="login-password"
|
||||
class="tw-font-mono"
|
||||
/>
|
||||
<button
|
||||
*ngIf="cipher.viewPassword && passwordRevealed"
|
||||
|
||||
Reference in New Issue
Block a user