mirror of
https://github.com/bitwarden/directory-connector
synced 2025-12-05 23:53:21 +00:00
Compare commits
1 Commits
ac/pm-1528
...
v2024.3.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1909194d5a |
7
.github/CODEOWNERS
vendored
7
.github/CODEOWNERS
vendored
@@ -6,3 +6,10 @@
|
|||||||
|
|
||||||
# Default file owners.
|
# Default file owners.
|
||||||
* @bitwarden/team-admin-console-dev
|
* @bitwarden/team-admin-console-dev
|
||||||
|
|
||||||
|
# DevOps for Actions and other workflow changes.
|
||||||
|
.github/workflows @bitwarden/dept-devops
|
||||||
|
.github/secrets @bitwarden/dept-devops
|
||||||
|
|
||||||
|
# Multiple Owners
|
||||||
|
**/package.json
|
||||||
47
.github/PULL_REQUEST_TEMPLATE.md
vendored
47
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,34 +1,33 @@
|
|||||||
## 🎟️ Tracking
|
## Type of change
|
||||||
|
|
||||||
<!-- Paste the link to the Jira or GitHub issue or otherwise describe / point to where this change is coming from. -->
|
- [ ] Bug fix
|
||||||
|
- [ ] New feature development
|
||||||
|
- [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc)
|
||||||
|
- [ ] Build/deploy pipeline (DevOps)
|
||||||
|
- [ ] Other
|
||||||
|
|
||||||
## 📔 Objective
|
## Objective
|
||||||
|
|
||||||
<!-- Describe what the purpose of this PR is, for example what bug you're fixing or new feature you're adding. -->
|
<!--Describe what the purpose of this PR is. For example: what bug you're fixing or what new feature you're adding-->
|
||||||
|
|
||||||
## 📸 Screenshots
|
## Code changes
|
||||||
|
|
||||||
<!-- Required for any UI changes; delete if not applicable. Use fixed width images for better display. -->
|
<!--Explain the changes you've made to each file or major component. This should help the reviewer understand your changes-->
|
||||||
|
<!--Also refer to any related changes or PRs in other repositories-->
|
||||||
|
|
||||||
## ⏰ Reminders before review
|
- **file.ext:** Description of what was changed and why
|
||||||
|
|
||||||
- Contributor guidelines followed
|
## Screenshots
|
||||||
- All formatters and local linters executed and passed
|
|
||||||
- Written new unit and / or integration tests where applicable
|
|
||||||
- Used internationalization (i18n) for all UI strings
|
|
||||||
- CI builds passed
|
|
||||||
- Communicated to DevOps any deployment requirements
|
|
||||||
- Updated any necessary documentation (Confluence, contributing docs) or informed the documentation team
|
|
||||||
|
|
||||||
## 🦮 Reviewer guidelines
|
<!--Required for any UI changes. Delete if not applicable-->
|
||||||
|
|
||||||
<!-- Suggested interactions but feel free to use (or not) as you desire! -->
|
## Testing requirements
|
||||||
|
|
||||||
- 👍 (`:+1:`) or similar for great changes
|
<!--What functionality requires testing by QA? This includes testing new behavior and regression testing-->
|
||||||
- 📝 (`:memo:`) or ℹ️ (`:information_source:`) for notes or general info
|
|
||||||
- ❓ (`:question:`) for questions
|
## Before you submit
|
||||||
- 🤔 (`:thinking:`) or 💭 (`:thought_balloon:`) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion
|
|
||||||
- 🎨 (`:art:`) for suggestions / improvements
|
- [ ] I have checked for **linting** errors (`npm run lint`) (required)
|
||||||
- ❌ (`:x:`) or ⚠️ (`:warning:`) for more significant problems or concerns needing attention
|
- [ ] I have added **unit tests** where it makes sense to do so (encouraged but not required)
|
||||||
- 🌱 (`:seedling:`) or ♻️ (`:recycle:`) for future improvements or indications of technical debt
|
- [ ] This change requires a **documentation update** (notify the documentation team)
|
||||||
- ⛏ (`:pick:`) for minor or nitpick changes
|
- [ ] This change has particular **deployment requirements** (notify the DevOps team)
|
||||||
|
|||||||
25
.github/renovate.json
vendored
25
.github/renovate.json
vendored
@@ -1,12 +1,31 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||||
"extends": ["github>bitwarden/renovate-config"],
|
"extends": [
|
||||||
|
"config:base",
|
||||||
|
"github>bitwarden/renovate-config:pin-actions",
|
||||||
|
":combinePatchMinorReleases",
|
||||||
|
":dependencyDashboard",
|
||||||
|
":maintainLockFilesWeekly",
|
||||||
|
":pinAllExceptPeerDependencies",
|
||||||
|
":prConcurrentLimit10",
|
||||||
|
":rebaseStalePrs",
|
||||||
|
":separateMajorReleases",
|
||||||
|
"group:monorepos",
|
||||||
|
"schedule:weekends"
|
||||||
|
],
|
||||||
"enabledManagers": ["github-actions", "npm"],
|
"enabledManagers": ["github-actions", "npm"],
|
||||||
|
"commitMessagePrefix": "[deps]:",
|
||||||
|
"commitMessageTopic": "{{depName}}",
|
||||||
"packageRules": [
|
"packageRules": [
|
||||||
{
|
{
|
||||||
"groupName": "gh minor",
|
"groupName": "npm minor",
|
||||||
"matchManagers": ["github-actions"],
|
"matchManagers": ["npm"],
|
||||||
"matchUpdateTypes": ["minor", "patch"]
|
"matchUpdateTypes": ["minor", "patch"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"matchFileNames": ["package.json"],
|
||||||
|
"description": "Admin Console owns general dependencies",
|
||||||
|
"reviewers": ["team:team-admin-console-dev"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
94
.github/workflows/build.yml
vendored
94
.github/workflows/build.yml
vendored
@@ -1,19 +1,17 @@
|
|||||||
|
---
|
||||||
name: Build
|
name: Build
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request: {}
|
pull_request: {}
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- "main"
|
|
||||||
workflow_dispatch: {}
|
workflow_dispatch: {}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
cloc:
|
cloc:
|
||||||
name: CLOC
|
name: CLOC
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
|
|
||||||
- name: Set up CLOC
|
- name: Set up CLOC
|
||||||
run: |
|
run: |
|
||||||
@@ -26,12 +24,12 @@ jobs:
|
|||||||
|
|
||||||
setup:
|
setup:
|
||||||
name: Setup
|
name: Setup
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-22.04
|
||||||
outputs:
|
outputs:
|
||||||
package_version: ${{ steps.retrieve-version.outputs.package_version }}
|
package_version: ${{ steps.retrieve-version.outputs.package_version }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
|
|
||||||
- name: Get Package Version
|
- name: Get Package Version
|
||||||
id: retrieve-version
|
id: retrieve-version
|
||||||
@@ -42,7 +40,7 @@ jobs:
|
|||||||
|
|
||||||
linux-cli:
|
linux-cli:
|
||||||
name: Build Linux CLI
|
name: Build Linux CLI
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-22.04
|
||||||
needs: setup
|
needs: setup
|
||||||
env:
|
env:
|
||||||
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||||
@@ -50,10 +48,10 @@ jobs:
|
|||||||
_PKG_FETCH_VERSION: 3.4
|
_PKG_FETCH_VERSION: 3.4
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
|
|
||||||
- name: Set up Node
|
- name: Set up Node
|
||||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||||
with:
|
with:
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/package-lock.json'
|
||||||
@@ -121,14 +119,14 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Upload Linux Zip to GitHub
|
- name: Upload Linux Zip to GitHub
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||||
with:
|
with:
|
||||||
name: bwdc-linux-${{ env._PACKAGE_VERSION }}.zip
|
name: bwdc-linux-${{ env._PACKAGE_VERSION }}.zip
|
||||||
path: ./dist-cli/bwdc-linux-${{ env._PACKAGE_VERSION }}.zip
|
path: ./dist-cli/bwdc-linux-${{ env._PACKAGE_VERSION }}.zip
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload Linux checksum to GitHub
|
- name: Upload Linux checksum to GitHub
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||||
with:
|
with:
|
||||||
name: bwdc-linux-sha256-${{ env._PACKAGE_VERSION }}.txt
|
name: bwdc-linux-sha256-${{ env._PACKAGE_VERSION }}.txt
|
||||||
path: ./dist-cli/bwdc-linux-sha256-${{ env._PACKAGE_VERSION }}.txt
|
path: ./dist-cli/bwdc-linux-sha256-${{ env._PACKAGE_VERSION }}.txt
|
||||||
@@ -137,7 +135,7 @@ jobs:
|
|||||||
|
|
||||||
macos-cli:
|
macos-cli:
|
||||||
name: Build Mac CLI
|
name: Build Mac CLI
|
||||||
runs-on: macos-13
|
runs-on: macos-12
|
||||||
needs: setup
|
needs: setup
|
||||||
env:
|
env:
|
||||||
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||||
@@ -145,10 +143,10 @@ jobs:
|
|||||||
_PKG_FETCH_VERSION: 3.4
|
_PKG_FETCH_VERSION: 3.4
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
|
|
||||||
- name: Set up Node
|
- name: Set up Node
|
||||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||||
with:
|
with:
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/package-lock.json'
|
||||||
@@ -209,14 +207,14 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Upload Mac Zip to GitHub
|
- name: Upload Mac Zip to GitHub
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||||
with:
|
with:
|
||||||
name: bwdc-macos-${{ env._PACKAGE_VERSION }}.zip
|
name: bwdc-macos-${{ env._PACKAGE_VERSION }}.zip
|
||||||
path: ./dist-cli/bwdc-macos-${{ env._PACKAGE_VERSION }}.zip
|
path: ./dist-cli/bwdc-macos-${{ env._PACKAGE_VERSION }}.zip
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload Mac checksum to GitHub
|
- name: Upload Mac checksum to GitHub
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||||
with:
|
with:
|
||||||
name: bwdc-macos-sha256-${{ env._PACKAGE_VERSION }}.txt
|
name: bwdc-macos-sha256-${{ env._PACKAGE_VERSION }}.txt
|
||||||
path: ./dist-cli/bwdc-macos-sha256-${{ env._PACKAGE_VERSION }}.txt
|
path: ./dist-cli/bwdc-macos-sha256-${{ env._PACKAGE_VERSION }}.txt
|
||||||
@@ -232,7 +230,7 @@ jobs:
|
|||||||
_WIN_PKG_VERSION: 3.4
|
_WIN_PKG_VERSION: 3.4
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
|
|
||||||
- name: Setup Windows builder
|
- name: Setup Windows builder
|
||||||
run: |
|
run: |
|
||||||
@@ -240,7 +238,7 @@ jobs:
|
|||||||
choco install reshack --no-progress
|
choco install reshack --no-progress
|
||||||
|
|
||||||
- name: Set up Node
|
- name: Set up Node
|
||||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||||
with:
|
with:
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/package-lock.json'
|
||||||
@@ -353,14 +351,14 @@ jobs:
|
|||||||
-t sha256 | Out-File ./dist-cli/bwdc-windows-sha256-${env:_PACKAGE_VERSION}.txt
|
-t sha256 | Out-File ./dist-cli/bwdc-windows-sha256-${env:_PACKAGE_VERSION}.txt
|
||||||
|
|
||||||
- name: Upload Windows Zip to GitHub
|
- name: Upload Windows Zip to GitHub
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||||
with:
|
with:
|
||||||
name: bwdc-windows-${{ env._PACKAGE_VERSION }}.zip
|
name: bwdc-windows-${{ env._PACKAGE_VERSION }}.zip
|
||||||
path: ./dist-cli/bwdc-windows-${{ env._PACKAGE_VERSION }}.zip
|
path: ./dist-cli/bwdc-windows-${{ env._PACKAGE_VERSION }}.zip
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload Windows checksum to GitHub
|
- name: Upload Windows checksum to GitHub
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||||
with:
|
with:
|
||||||
name: bwdc-windows-sha256-${{ env._PACKAGE_VERSION }}.txt
|
name: bwdc-windows-sha256-${{ env._PACKAGE_VERSION }}.txt
|
||||||
path: ./dist-cli/bwdc-windows-sha256-${{ env._PACKAGE_VERSION }}.txt
|
path: ./dist-cli/bwdc-windows-sha256-${{ env._PACKAGE_VERSION }}.txt
|
||||||
@@ -377,10 +375,10 @@ jobs:
|
|||||||
HUSKY: 0
|
HUSKY: 0
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
|
|
||||||
- name: Set up Node
|
- name: Set up Node
|
||||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||||
with:
|
with:
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/package-lock.json'
|
||||||
@@ -413,28 +411,28 @@ jobs:
|
|||||||
SIGNING_CERT_NAME: ${{ secrets.SIGNING_CERT_NAME }}
|
SIGNING_CERT_NAME: ${{ secrets.SIGNING_CERT_NAME }}
|
||||||
|
|
||||||
- name: Upload Portable Executable to GitHub
|
- name: Upload Portable Executable to GitHub
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||||
with:
|
with:
|
||||||
name: Bitwarden-Connector-Portable-${{ env._PACKAGE_VERSION }}.exe
|
name: Bitwarden-Connector-Portable-${{ env._PACKAGE_VERSION }}.exe
|
||||||
path: ./dist/Bitwarden-Connector-Portable-${{ env._PACKAGE_VERSION }}.exe
|
path: ./dist/Bitwarden-Connector-Portable-${{ env._PACKAGE_VERSION }}.exe
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload Installer Executable to GitHub
|
- name: Upload Installer Executable to GitHub
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||||
with:
|
with:
|
||||||
name: Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe
|
name: Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe
|
||||||
path: ./dist/Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe
|
path: ./dist/Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload Installer Executable Blockmap to GitHub
|
- name: Upload Installer Executable Blockmap to GitHub
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||||
with:
|
with:
|
||||||
name: Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe.blockmap
|
name: Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe.blockmap
|
||||||
path: ./dist/Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe.blockmap
|
path: ./dist/Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe.blockmap
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload latest auto-update artifact
|
- name: Upload latest auto-update artifact
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||||
with:
|
with:
|
||||||
name: latest.yml
|
name: latest.yml
|
||||||
path: ./dist/latest.yml
|
path: ./dist/latest.yml
|
||||||
@@ -443,7 +441,7 @@ jobs:
|
|||||||
|
|
||||||
linux-gui:
|
linux-gui:
|
||||||
name: Build Linux GUI
|
name: Build Linux GUI
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-22.04
|
||||||
needs: setup
|
needs: setup
|
||||||
env:
|
env:
|
||||||
NODE_OPTIONS: --max_old_space_size=4096
|
NODE_OPTIONS: --max_old_space_size=4096
|
||||||
@@ -451,10 +449,10 @@ jobs:
|
|||||||
HUSKY: 0
|
HUSKY: 0
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
|
|
||||||
- name: Set up Node
|
- name: Set up Node
|
||||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||||
with:
|
with:
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/package-lock.json'
|
||||||
@@ -481,14 +479,14 @@ jobs:
|
|||||||
run: npm run dist:lin
|
run: npm run dist:lin
|
||||||
|
|
||||||
- name: Upload AppImage
|
- name: Upload AppImage
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||||
with:
|
with:
|
||||||
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-x86_64.AppImage
|
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-x86_64.AppImage
|
||||||
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-x86_64.AppImage
|
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-x86_64.AppImage
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload latest auto-update artifact
|
- name: Upload latest auto-update artifact
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||||
with:
|
with:
|
||||||
name: latest-linux.yml
|
name: latest-linux.yml
|
||||||
path: ./dist/latest-linux.yml
|
path: ./dist/latest-linux.yml
|
||||||
@@ -497,7 +495,7 @@ jobs:
|
|||||||
|
|
||||||
macos-gui:
|
macos-gui:
|
||||||
name: Build MacOS GUI
|
name: Build MacOS GUI
|
||||||
runs-on: macos-13
|
runs-on: macos-12
|
||||||
needs: setup
|
needs: setup
|
||||||
env:
|
env:
|
||||||
NODE_OPTIONS: --max_old_space_size=4096
|
NODE_OPTIONS: --max_old_space_size=4096
|
||||||
@@ -505,10 +503,10 @@ jobs:
|
|||||||
HUSKY: 0
|
HUSKY: 0
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
|
|
||||||
- name: Set up Node
|
- name: Set up Node
|
||||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||||
with:
|
with:
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/package-lock.json'
|
||||||
@@ -575,45 +573,37 @@ jobs:
|
|||||||
|
|
||||||
- name: Install Node dependencies
|
- name: Install Node dependencies
|
||||||
run: npm install
|
run: npm install
|
||||||
|
|
||||||
- name: Set up private auth key
|
|
||||||
run: |
|
|
||||||
mkdir ~/private_keys
|
|
||||||
cat << EOF > ~/private_keys/AuthKey_UFD296548T.p8
|
|
||||||
${{ secrets.APP_STORE_CONNECT_AUTH_KEY }}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
- name: Build application
|
- name: Build application
|
||||||
run: npm run dist:mac
|
run: npm run dist:mac
|
||||||
env:
|
env:
|
||||||
APP_STORE_CONNECT_TEAM_ISSUER: ${{ secrets.APP_STORE_CONNECT_TEAM_ISSUER }}
|
APPLE_ID_USERNAME: ${{ secrets.APPLE_ID_USERNAME }}
|
||||||
APP_STORE_CONNECT_AUTH_KEY: UFD296548T
|
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||||
APP_STORE_CONNECT_AUTH_KEY_PATH: ~/private_keys/AuthKey_UFD296548T.p8
|
|
||||||
CSC_FOR_PULL_REQUEST: true
|
CSC_FOR_PULL_REQUEST: true
|
||||||
|
|
||||||
- name: Upload .zip artifact
|
- name: Upload .zip artifact
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||||
with:
|
with:
|
||||||
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-mac.zip
|
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-mac.zip
|
||||||
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-mac.zip
|
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-mac.zip
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload .dmg artifact
|
- name: Upload .dmg artifact
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||||
with:
|
with:
|
||||||
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg
|
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg
|
||||||
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg
|
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload .dmg Blockmap artifact
|
- name: Upload .dmg Blockmap artifact
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||||
with:
|
with:
|
||||||
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg.blockmap
|
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg.blockmap
|
||||||
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg.blockmap
|
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg.blockmap
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload latest auto-update artifact
|
- name: Upload latest auto-update artifact
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||||
with:
|
with:
|
||||||
name: latest-mac.yml
|
name: latest-mac.yml
|
||||||
path: ./dist/latest-mac.yml
|
path: ./dist/latest-mac.yml
|
||||||
@@ -622,7 +612,7 @@ jobs:
|
|||||||
|
|
||||||
check-failures:
|
check-failures:
|
||||||
name: Check for failures
|
name: Check for failures
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-22.04
|
||||||
needs:
|
needs:
|
||||||
- cloc
|
- cloc
|
||||||
- setup
|
- setup
|
||||||
@@ -634,7 +624,7 @@ jobs:
|
|||||||
- macos-gui
|
- macos-gui
|
||||||
steps:
|
steps:
|
||||||
- name: Check if any job failed
|
- name: Check if any job failed
|
||||||
if: github.ref == 'refs/heads/main' && contains(needs.*.result, 'failure')
|
if: (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/rc') && contains(needs.*.result, 'failure')
|
||||||
run: exit 1
|
run: exit 1
|
||||||
|
|
||||||
- name: Login to Azure - CI subscription
|
- name: Login to Azure - CI subscription
|
||||||
@@ -652,7 +642,7 @@ jobs:
|
|||||||
secrets: "devops-alerts-slack-webhook-url"
|
secrets: "devops-alerts-slack-webhook-url"
|
||||||
|
|
||||||
- name: Notify Slack on failure
|
- name: Notify Slack on failure
|
||||||
uses: act10ns/slack@44541246747a30eb3102d87f7a4cc5471b0ffb7d # v2.1.0
|
uses: act10ns/slack@ed1309ab9862e57e9e583e51c7889486b9a00b0f # v2.0.0
|
||||||
if: failure()
|
if: failure()
|
||||||
env:
|
env:
|
||||||
SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }}
|
SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }}
|
||||||
|
|||||||
53
.github/workflows/cleanup-rc-branch.yml
vendored
Normal file
53
.github/workflows/cleanup-rc-branch.yml
vendored
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
---
|
||||||
|
name: Cleanup RC Branch
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- v**
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
delete-rc:
|
||||||
|
name: Delete RC Branch
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- name: Login to Azure - CI Subscription
|
||||||
|
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
||||||
|
with:
|
||||||
|
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
||||||
|
|
||||||
|
- name: Retrieve bot secrets
|
||||||
|
id: retrieve-bot-secrets
|
||||||
|
uses: bitwarden/gh-actions/get-keyvault-secrets@main
|
||||||
|
with:
|
||||||
|
keyvault: bitwarden-ci
|
||||||
|
secrets: "github-pat-bitwarden-devops-bot-repo-scope"
|
||||||
|
|
||||||
|
- name: Checkout main
|
||||||
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
|
with:
|
||||||
|
ref: main
|
||||||
|
token: ${{ steps.retrieve-bot-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }}
|
||||||
|
|
||||||
|
- name: Check if a RC branch exists
|
||||||
|
id: branch-check
|
||||||
|
run: |
|
||||||
|
hotfix_rc_branch_check=$(git ls-remote --heads origin hotfix-rc | wc -l)
|
||||||
|
rc_branch_check=$(git ls-remote --heads origin rc | wc -l)
|
||||||
|
|
||||||
|
if [[ "${hotfix_rc_branch_check}" -gt 0 ]]; then
|
||||||
|
echo "hotfix-rc branch exists." | tee -a $GITHUB_STEP_SUMMARY
|
||||||
|
echo "name=hotfix-rc" >> $GITHUB_OUTPUT
|
||||||
|
elif [[ "${rc_branch_check}" -gt 0 ]]; then
|
||||||
|
echo "rc branch exists." | tee -a $GITHUB_STEP_SUMMARY
|
||||||
|
echo "name=rc" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Delete RC branch
|
||||||
|
env:
|
||||||
|
BRANCH_NAME: ${{ steps.branch-check.outputs.name }}
|
||||||
|
run: |
|
||||||
|
if ! [[ -z "$BRANCH_NAME" ]]; then
|
||||||
|
git push --quiet origin --delete $BRANCH_NAME
|
||||||
|
echo "Deleted $BRANCH_NAME branch." | tee -a $GITHUB_STEP_SUMMARY
|
||||||
|
fi
|
||||||
3
.github/workflows/enforce-labels.yml
vendored
3
.github/workflows/enforce-labels.yml
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
---
|
||||||
name: Enforce PR labels
|
name: Enforce PR labels
|
||||||
|
|
||||||
on:
|
on:
|
||||||
@@ -6,7 +7,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
enforce-label:
|
enforce-label:
|
||||||
name: EnforceLabel
|
name: EnforceLabel
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- name: Enforce Label
|
- name: Enforce Label
|
||||||
uses: yogevbd/enforce-label-action@a3c219da6b8fa73f6ba62b68ff09c469b3a1c024 # 2.2.2
|
uses: yogevbd/enforce-label-action@a3c219da6b8fa73f6ba62b68ff09c469b3a1c024 # 2.2.2
|
||||||
|
|||||||
100
.github/workflows/integration-test.yml
vendored
100
.github/workflows/integration-test.yml
vendored
@@ -1,100 +0,0 @@
|
|||||||
name: Integration Testing
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- "main"
|
|
||||||
paths:
|
|
||||||
- ".github/workflows/integration-test.yml" # this file
|
|
||||||
- "src/services/ldap-directory.service*" # we only have integration for LDAP testing at the moment
|
|
||||||
- "./openldap*" # any change to test fixtures
|
|
||||||
- "./docker-compose.yml" # any change to Docker configuration
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- ".github/workflows/integration-test.yml" # this file
|
|
||||||
- "src/services/ldap-directory.service*" # we only have integration for LDAP testing at the moment
|
|
||||||
- "./openldap*" # any change to test fixtures
|
|
||||||
- "./docker-compose.yml" # any change to Docker configuration
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check-test-secrets:
|
|
||||||
name: Check for test secrets
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
outputs:
|
|
||||||
available: ${{ steps.check-test-secrets.outputs.available }}
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Check
|
|
||||||
id: check-test-secrets
|
|
||||||
run: |
|
|
||||||
if [ "${{ secrets.CODECOV_TOKEN }}" != '' ]; then
|
|
||||||
echo "available=true" >> $GITHUB_OUTPUT;
|
|
||||||
else
|
|
||||||
echo "available=false" >> $GITHUB_OUTPUT;
|
|
||||||
fi
|
|
||||||
|
|
||||||
testing:
|
|
||||||
name: Run tests
|
|
||||||
if: ${{ startsWith(github.head_ref, 'version_bump_') == false }}
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
needs: check-test-secrets
|
|
||||||
permissions:
|
|
||||||
checks: write
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Check out repo
|
|
||||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
|
||||||
|
|
||||||
- name: Get Node version
|
|
||||||
id: retrieve-node-version
|
|
||||||
run: |
|
|
||||||
NODE_NVMRC=$(cat .nvmrc)
|
|
||||||
NODE_VERSION=${NODE_NVMRC/v/''}
|
|
||||||
echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Set up Node
|
|
||||||
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
|
||||||
with:
|
|
||||||
cache: 'npm'
|
|
||||||
cache-dependency-path: '**/package-lock.json'
|
|
||||||
node-version: ${{ steps.retrieve-node-version.outputs.node_version }}
|
|
||||||
|
|
||||||
- name: Install Node dependencies
|
|
||||||
run: npm ci
|
|
||||||
|
|
||||||
- name: Install mkcert
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get -y install mkcert
|
|
||||||
|
|
||||||
- name: Setup integration tests
|
|
||||||
run: npm run test:integration:setup
|
|
||||||
|
|
||||||
- name: Run integration tests
|
|
||||||
run: npm run test:integration --coverage
|
|
||||||
|
|
||||||
- name: Report test results
|
|
||||||
uses: dorny/test-reporter@31a54ee7ebcacc03a09ea97a7e5465a47b84aea5 # v1.9.1
|
|
||||||
if: ${{ needs.check-test-secrets.outputs.available == 'true' && !cancelled() }}
|
|
||||||
with:
|
|
||||||
name: Test Results
|
|
||||||
path: "junit.xml"
|
|
||||||
reporter: jest-junit
|
|
||||||
fail-on-error: true
|
|
||||||
|
|
||||||
- name: Upload coverage to codecov.io
|
|
||||||
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0
|
|
||||||
if: ${{ needs.check-test-secrets.outputs.available == 'true' }}
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|
||||||
- name: Upload results to codecov.io
|
|
||||||
uses: codecov/test-results-action@1b5b448b98e58ba90d1a1a1d9fcb72ca2263be46 # v1.0.0
|
|
||||||
if: ${{ needs.check-test-secrets.outputs.available == 'true' }}
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
39
.github/workflows/release.yml
vendored
39
.github/workflows/release.yml
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
---
|
||||||
name: Release
|
name: Release
|
||||||
|
|
||||||
on:
|
on:
|
||||||
@@ -16,19 +17,19 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
setup:
|
setup:
|
||||||
name: Setup
|
name: Setup
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-22.04
|
||||||
outputs:
|
outputs:
|
||||||
release-version: ${{ steps.version.outputs.version }}
|
release-version: ${{ steps.version.outputs.version }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
|
|
||||||
- name: Branch check
|
- name: Branch check
|
||||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||||
run: |
|
run: |
|
||||||
if [[ "$GITHUB_REF" != "refs/heads/main" ]]; then
|
if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix-rc" ]]; then
|
||||||
echo "==================================="
|
echo "==================================="
|
||||||
echo "[!] Can only release from the 'main' branch"
|
echo "[!] Can only release from the 'rc' or 'hotfix-rc' branches"
|
||||||
echo "==================================="
|
echo "==================================="
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -43,9 +44,19 @@ jobs:
|
|||||||
|
|
||||||
release:
|
release:
|
||||||
name: Release
|
name: Release
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-22.04
|
||||||
needs: setup
|
needs: setup
|
||||||
steps:
|
steps:
|
||||||
|
- name: Create GitHub deployment
|
||||||
|
uses: chrnorm/deployment-action@55729fcebec3d284f60f5bcabbd8376437d696b1 # v2.0.7
|
||||||
|
id: deployment
|
||||||
|
with:
|
||||||
|
token: '${{ secrets.GITHUB_TOKEN }}'
|
||||||
|
initial-status: 'in_progress'
|
||||||
|
environment: 'production'
|
||||||
|
description: 'Deployment ${{ needs.setup.outputs.release-version }} from branch ${{ github.ref_name }}'
|
||||||
|
task: release
|
||||||
|
|
||||||
- name: Download all artifacts
|
- name: Download all artifacts
|
||||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||||
uses: bitwarden/gh-actions/download-artifacts@main
|
uses: bitwarden/gh-actions/download-artifacts@main
|
||||||
@@ -54,7 +65,7 @@ jobs:
|
|||||||
workflow_conclusion: success
|
workflow_conclusion: success
|
||||||
branch: ${{ github.ref_name }}
|
branch: ${{ github.ref_name }}
|
||||||
|
|
||||||
- name: Dry Run - Download all artifacts
|
- name: Download all artifacts
|
||||||
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
||||||
uses: bitwarden/gh-actions/download-artifacts@main
|
uses: bitwarden/gh-actions/download-artifacts@main
|
||||||
with:
|
with:
|
||||||
@@ -90,3 +101,19 @@ jobs:
|
|||||||
body: "<insert release notes here>"
|
body: "<insert release notes here>"
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
draft: true
|
draft: true
|
||||||
|
|
||||||
|
- name: Update deployment status to Success
|
||||||
|
if: ${{ success() }}
|
||||||
|
uses: chrnorm/deployment-status@9a72af4586197112e0491ea843682b5dc280d806 # v2.0.3
|
||||||
|
with:
|
||||||
|
token: '${{ secrets.GITHUB_TOKEN }}'
|
||||||
|
state: 'success'
|
||||||
|
deployment-id: ${{ steps.deployment.outputs.deployment_id }}
|
||||||
|
|
||||||
|
- name: Update deployment status to Failure
|
||||||
|
if: ${{ failure() }}
|
||||||
|
uses: chrnorm/deployment-status@9a72af4586197112e0491ea843682b5dc280d806 # v2.0.3
|
||||||
|
with:
|
||||||
|
token: '${{ secrets.GITHUB_TOKEN }}'
|
||||||
|
state: 'failure'
|
||||||
|
deployment-id: ${{ steps.deployment.outputs.deployment_id }}
|
||||||
|
|||||||
78
.github/workflows/scan.yml
vendored
78
.github/workflows/scan.yml
vendored
@@ -1,78 +0,0 @@
|
|||||||
name: Scan
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- "main"
|
|
||||||
pull_request_target:
|
|
||||||
types: [opened, synchronize]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check-run:
|
|
||||||
name: Check PR run
|
|
||||||
uses: bitwarden/gh-actions/.github/workflows/check-run.yml@main
|
|
||||||
|
|
||||||
sast:
|
|
||||||
name: SAST scan
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
needs: check-run
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
security-events: write
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Check out repo
|
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
|
||||||
with:
|
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
|
||||||
|
|
||||||
- name: Scan with Checkmarx
|
|
||||||
uses: checkmarx/ast-github-action@ed196cdaec9cd1bc5aacac4ca2010dd773b20893 # 2.0.35
|
|
||||||
env:
|
|
||||||
INCREMENTAL: "${{ contains(github.event_name, 'pull_request') && '--sast-incremental' || '' }}"
|
|
||||||
with:
|
|
||||||
project_name: ${{ github.repository }}
|
|
||||||
cx_tenant: ${{ secrets.CHECKMARX_TENANT }}
|
|
||||||
base_uri: https://ast.checkmarx.net/
|
|
||||||
cx_client_id: ${{ secrets.CHECKMARX_CLIENT_ID }}
|
|
||||||
cx_client_secret: ${{ secrets.CHECKMARX_SECRET }}
|
|
||||||
additional_params: |
|
|
||||||
--report-format sarif \
|
|
||||||
--filter "state=TO_VERIFY;PROPOSED_NOT_EXPLOITABLE;CONFIRMED;URGENT" \
|
|
||||||
--output-path . ${{ env.INCREMENTAL }}
|
|
||||||
|
|
||||||
- name: Upload Checkmarx results to GitHub
|
|
||||||
uses: github/codeql-action/upload-sarif@e2b3eafc8d227b0241d48be5f425d47c2d750a13 # v3.26.10
|
|
||||||
with:
|
|
||||||
sarif_file: cx_result.sarif
|
|
||||||
|
|
||||||
quality:
|
|
||||||
name: Quality scan
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
needs: check-run
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Check out repo
|
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
|
||||||
|
|
||||||
- name: Scan with SonarCloud
|
|
||||||
uses: sonarsource/sonarcloud-github-action@eb211723266fe8e83102bac7361f0a05c3ac1d1b # v3.0.0
|
|
||||||
env:
|
|
||||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
args: >
|
|
||||||
-Dsonar.organization=${{ github.repository_owner }}
|
|
||||||
-Dsonar.projectKey=${{ github.repository_owner }}_${{ github.event.repository.name }}
|
|
||||||
-Dsonar.tests=.
|
|
||||||
-Dsonar.sources=.
|
|
||||||
-Dsonar.test.inclusions=**/*.spec.ts
|
|
||||||
-Dsonar.exclusions=**/*.spec.ts
|
|
||||||
76
.github/workflows/test.yml
vendored
76
.github/workflows/test.yml
vendored
@@ -1,46 +1,28 @@
|
|||||||
name: Testing
|
---
|
||||||
|
name: Run tests
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- "main"
|
- "main"
|
||||||
pull_request:
|
- "rc"
|
||||||
|
- "hotfix-rc-*"
|
||||||
|
pull_request: {}
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check-test-secrets:
|
test:
|
||||||
name: Check for test secrets
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
outputs:
|
|
||||||
available: ${{ steps.check-test-secrets.outputs.available }}
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Check
|
|
||||||
id: check-test-secrets
|
|
||||||
run: |
|
|
||||||
if [ "${{ secrets.CODECOV_TOKEN }}" != '' ]; then
|
|
||||||
echo "available=true" >> $GITHUB_OUTPUT;
|
|
||||||
else
|
|
||||||
echo "available=false" >> $GITHUB_OUTPUT;
|
|
||||||
fi
|
|
||||||
|
|
||||||
testing:
|
|
||||||
name: Run tests
|
name: Run tests
|
||||||
if: ${{ startsWith(github.head_ref, 'version_bump_') == false }}
|
runs-on: ubuntu-22.04
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
needs: check-test-secrets
|
|
||||||
permissions:
|
|
||||||
checks: write
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
|
|
||||||
- name: Get Node version
|
- name: Get Node Version
|
||||||
id: retrieve-node-version
|
id: retrieve-node-version
|
||||||
run: |
|
run: |
|
||||||
NODE_NVMRC=$(cat .nvmrc)
|
NODE_NVMRC=$(cat .nvmrc)
|
||||||
@@ -48,12 +30,17 @@ jobs:
|
|||||||
echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT
|
echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Set up Node
|
- name: Set up Node
|
||||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||||
with:
|
with:
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/package-lock.json'
|
||||||
node-version: ${{ steps.retrieve-node-version.outputs.node_version }}
|
node-version: ${{ steps.retrieve-node-version.outputs.node_version }}
|
||||||
|
|
||||||
|
- name: Print environment
|
||||||
|
run: |
|
||||||
|
node --version
|
||||||
|
npm --version
|
||||||
|
|
||||||
- name: Install Node dependencies
|
- name: Install Node dependencies
|
||||||
run: npm ci
|
run: npm ci
|
||||||
|
|
||||||
@@ -64,25 +51,4 @@ jobs:
|
|||||||
run: npm run test:types --coverage
|
run: npm run test:types --coverage
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: npm run test --coverage
|
run: npm run test
|
||||||
|
|
||||||
- name: Report test results
|
|
||||||
uses: dorny/test-reporter@31a54ee7ebcacc03a09ea97a7e5465a47b84aea5 # v1.9.1
|
|
||||||
if: ${{ needs.check-test-secrets.outputs.available == 'true' && !cancelled() }}
|
|
||||||
with:
|
|
||||||
name: Test Results
|
|
||||||
path: "junit.xml"
|
|
||||||
reporter: jest-junit
|
|
||||||
fail-on-error: true
|
|
||||||
|
|
||||||
- name: Upload coverage to codecov.io
|
|
||||||
uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4.6.0
|
|
||||||
if: ${{ needs.check-test-secrets.outputs.available == 'true' }}
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|
||||||
- name: Upload results to codecov.io
|
|
||||||
uses: codecov/test-results-action@1b5b448b98e58ba90d1a1a1d9fcb72ca2263be46 # v1.0.0
|
|
||||||
if: ${{ needs.check-test-secrets.outputs.available == 'true' }}
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|||||||
137
.github/workflows/version-bump.yml
vendored
137
.github/workflows/version-bump.yml
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
---
|
||||||
name: Version Bump
|
name: Version Bump
|
||||||
|
|
||||||
on:
|
on:
|
||||||
@@ -7,11 +8,17 @@ on:
|
|||||||
description: "New version override (leave blank for automatic calculation, example: '2024.1.0')"
|
description: "New version override (leave blank for automatic calculation, example: '2024.1.0')"
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
|
cut_rc_branch:
|
||||||
|
description: "Cut RC branch?"
|
||||||
|
default: true
|
||||||
|
type: boolean
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
bump_version:
|
bump_version:
|
||||||
name: Bump Version
|
name: Bump Version
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-22.04
|
||||||
|
outputs:
|
||||||
|
version: ${{ steps.set-final-version-output.outputs.version }}
|
||||||
steps:
|
steps:
|
||||||
- name: Validate version input
|
- name: Validate version input
|
||||||
if: ${{ inputs.version_number_override != '' }}
|
if: ${{ inputs.version_number_override != '' }}
|
||||||
@@ -19,22 +26,54 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
version: ${{ inputs.version_number_override }}
|
version: ${{ inputs.version_number_override }}
|
||||||
|
|
||||||
- name: Generate GH App token
|
|
||||||
uses: actions/create-github-app-token@5d869da34e18e7287c1daad50e0b8ea0f506ce69 # v1.11.0
|
|
||||||
id: app-token
|
|
||||||
with:
|
|
||||||
app-id: ${{ secrets.BW_GHAPP_ID }}
|
|
||||||
private-key: ${{ secrets.BW_GHAPP_KEY }}
|
|
||||||
|
|
||||||
- name: Checkout Branch
|
- name: Checkout Branch
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
with:
|
with:
|
||||||
token: ${{ steps.app-token.outputs.token }}
|
ref: main
|
||||||
|
|
||||||
|
- name: Check if RC branch exists
|
||||||
|
if: ${{ inputs.cut_rc_branch == true }}
|
||||||
|
run: |
|
||||||
|
remote_rc_branch_check=$(git ls-remote --heads origin rc | wc -l)
|
||||||
|
if [[ "${remote_rc_branch_check}" -gt 0 ]]; then
|
||||||
|
echo "Remote RC branch exists."
|
||||||
|
echo "Please delete current RC branch before running again."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Login to Azure - CI Subscription
|
||||||
|
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
||||||
|
with:
|
||||||
|
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
||||||
|
|
||||||
|
- name: Retrieve secrets
|
||||||
|
id: retrieve-secrets
|
||||||
|
uses: bitwarden/gh-actions/get-keyvault-secrets@main
|
||||||
|
with:
|
||||||
|
keyvault: "bitwarden-ci"
|
||||||
|
secrets: "github-gpg-private-key,
|
||||||
|
github-gpg-private-key-passphrase,
|
||||||
|
github-pat-bitwarden-devops-bot-repo-scope"
|
||||||
|
|
||||||
|
- name: Import GPG key
|
||||||
|
uses: crazy-max/ghaction-import-gpg@01dd5d3ca463c7f10f7f4f7b4f177225ac661ee4 # v6.1.0
|
||||||
|
with:
|
||||||
|
gpg_private_key: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key }}
|
||||||
|
passphrase: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key-passphrase }}
|
||||||
|
git_user_signingkey: true
|
||||||
|
git_commit_gpgsign: true
|
||||||
|
|
||||||
- name: Setup git
|
- name: Setup git
|
||||||
run: |
|
run: |
|
||||||
git config user.name github-actions
|
git config --local user.email "106330231+bitwarden-devops-bot@users.noreply.github.com"
|
||||||
git config user.email github-actions@github.com
|
git config --local user.name "bitwarden-devops-bot"
|
||||||
|
|
||||||
|
- name: Create Version Branch
|
||||||
|
id: create-branch
|
||||||
|
run: |
|
||||||
|
NAME=version_bump_${{ github.ref_name }}_$(date +"%Y-%m-%d")
|
||||||
|
git switch -c $NAME
|
||||||
|
echo "name=$NAME" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Get current version
|
- name: Get current version
|
||||||
id: current-version
|
id: current-version
|
||||||
@@ -111,4 +150,76 @@ jobs:
|
|||||||
|
|
||||||
- name: Push changes
|
- name: Push changes
|
||||||
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
|
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
|
||||||
run: git push
|
env:
|
||||||
|
PR_BRANCH: ${{ steps.create-branch.outputs.name }}
|
||||||
|
run: git push -u origin $PR_BRANCH
|
||||||
|
|
||||||
|
- name: Create Version PR
|
||||||
|
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
|
||||||
|
id: create-pr
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }}
|
||||||
|
PR_BRANCH: ${{ steps.create-branch.outputs.name }}
|
||||||
|
TITLE: "Bump version to ${{ steps.set-final-version-output.outputs.version }}"
|
||||||
|
run: |
|
||||||
|
PR_URL=$(gh pr create --title "$TITLE" \
|
||||||
|
--base "main" \
|
||||||
|
--head "$PR_BRANCH" \
|
||||||
|
--label "version update" \
|
||||||
|
--label "automated pr" \
|
||||||
|
--body "
|
||||||
|
## Type of change
|
||||||
|
- [ ] Bug fix
|
||||||
|
- [ ] New feature development
|
||||||
|
- [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc)
|
||||||
|
- [ ] Build/deploy pipeline (DevOps)
|
||||||
|
- [X] Other
|
||||||
|
|
||||||
|
## Objective
|
||||||
|
Automated version bump to ${{ steps.set-final-version-output.outputs.version }}")
|
||||||
|
echo "pr_number=${PR_URL##*/}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Approve PR
|
||||||
|
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
PR_NUMBER: ${{ steps.create-pr.outputs.pr_number }}
|
||||||
|
run: gh pr review $PR_NUMBER --approve
|
||||||
|
|
||||||
|
- name: Merge PR
|
||||||
|
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }}
|
||||||
|
PR_NUMBER: ${{ steps.create-pr.outputs.pr_number }}
|
||||||
|
run: gh pr merge $PR_NUMBER --squash --auto --delete-branch
|
||||||
|
|
||||||
|
cut_rc:
|
||||||
|
name: Cut RC branch
|
||||||
|
if: ${{ inputs.cut_rc_branch == true }}
|
||||||
|
needs: bump_version
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout Branch
|
||||||
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
|
with:
|
||||||
|
ref: main
|
||||||
|
|
||||||
|
- name: Verify version has been updated
|
||||||
|
env:
|
||||||
|
NEW_VERSION: ${{ needs.bump_version.outputs.version }}
|
||||||
|
run: |
|
||||||
|
# Wait for version to change.
|
||||||
|
while : ; do
|
||||||
|
echo "Waiting for version to be updated..."
|
||||||
|
git pull --force
|
||||||
|
CURRENT_VERSION=$(cat package.json | jq -r '.version')
|
||||||
|
|
||||||
|
# If the versions don't match we continue the loop, otherwise we break out of the loop.
|
||||||
|
[[ "$NEW_VERSION" != "$CURRENT_VERSION" ]] || break
|
||||||
|
sleep 10
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Cut RC branch
|
||||||
|
run: |
|
||||||
|
git switch --quiet --create rc
|
||||||
|
git push --quiet --set-upstream origin rc
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -26,7 +26,6 @@ npm-debug.log
|
|||||||
# Build directories
|
# Build directories
|
||||||
dist
|
dist
|
||||||
build
|
build
|
||||||
build-cli
|
|
||||||
.angular/cache
|
.angular/cache
|
||||||
|
|
||||||
# Testing
|
# Testing
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
# Bitwarden Directory Connector
|
# Bitwarden Directory Connector
|
||||||
|
|
||||||
The Bitwarden Directory Connector is a desktop application used to sync your Bitwarden enterprise organization to an existing directory of users and groups.
|
The Bitwarden Directory Connector is a a desktop application used to sync your Bitwarden enterprise organization to an existing directory of users and groups.
|
||||||
|
|
||||||
Supported directories:
|
Supported directories:
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
services:
|
|
||||||
open-ldap:
|
|
||||||
image: bitnami/openldap:latest
|
|
||||||
hostname: openldap
|
|
||||||
environment:
|
|
||||||
- LDAP_ADMIN_USERNAME=admin
|
|
||||||
- LDAP_ADMIN_PASSWORD=admin
|
|
||||||
- LDAP_ROOT=dc=bitwarden,dc=com
|
|
||||||
- LDAP_ENABLE_TLS=yes
|
|
||||||
- LDAP_TLS_CERT_FILE=/certs/openldap.pem
|
|
||||||
- LDAP_TLS_KEY_FILE=/certs/openldap-key.pem
|
|
||||||
- LDAP_TLS_CA_FILE=/certs/rootCA.pem
|
|
||||||
volumes:
|
|
||||||
- "./openldap/ldifs:/ldifs"
|
|
||||||
- "./openldap/certs:/certs"
|
|
||||||
ports:
|
|
||||||
- "1389:1389"
|
|
||||||
- "1636:1636"
|
|
||||||
@@ -11,14 +11,6 @@ module.exports = {
|
|||||||
// ...angularPreset,
|
// ...angularPreset,
|
||||||
preset: "jest-preset-angular",
|
preset: "jest-preset-angular",
|
||||||
|
|
||||||
reporters: ["default", "jest-junit"],
|
|
||||||
|
|
||||||
collectCoverage: true,
|
|
||||||
// Ensure we collect coverage from files without tests
|
|
||||||
collectCoverageFrom: ["src/**/*.ts"],
|
|
||||||
coverageReporters: ["html", "lcov"],
|
|
||||||
coverageDirectory: "coverage",
|
|
||||||
|
|
||||||
testEnvironment: "jsdom",
|
testEnvironment: "jsdom",
|
||||||
testMatch: ["**/+(*.)+(spec).+(ts)"],
|
testMatch: ["**/+(*.)+(spec).+(ts)"],
|
||||||
|
|
||||||
|
|||||||
45
jslib/angular/src/services/auth-guard.service.ts
Normal file
45
jslib/angular/src/services/auth-guard.service.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import { Injectable } from "@angular/core";
|
||||||
|
import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from "@angular/router";
|
||||||
|
|
||||||
|
import { KeyConnectorService } from "@/jslib/common/src/abstractions/keyConnector.service";
|
||||||
|
import { MessagingService } from "@/jslib/common/src/abstractions/messaging.service";
|
||||||
|
import { StateService } from "@/jslib/common/src/abstractions/state.service";
|
||||||
|
import { VaultTimeoutService } from "@/jslib/common/src/abstractions/vaultTimeout.service";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AuthGuardService {
|
||||||
|
constructor(
|
||||||
|
private vaultTimeoutService: VaultTimeoutService,
|
||||||
|
private router: Router,
|
||||||
|
private messagingService: MessagingService,
|
||||||
|
private keyConnectorService: KeyConnectorService,
|
||||||
|
private stateService: StateService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async canActivate(route: ActivatedRouteSnapshot, routerState: RouterStateSnapshot) {
|
||||||
|
const isAuthed = await this.stateService.getIsAuthenticated();
|
||||||
|
if (!isAuthed) {
|
||||||
|
this.messagingService.send("authBlocked");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const locked = await this.vaultTimeoutService.isLocked();
|
||||||
|
if (locked) {
|
||||||
|
if (routerState != null) {
|
||||||
|
this.messagingService.send("lockedUrl", { url: routerState.url });
|
||||||
|
}
|
||||||
|
this.router.navigate(["lock"], { queryParams: { promptBiometric: true } });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!routerState.url.includes("remove-password") &&
|
||||||
|
(await this.keyConnectorService.getConvertAccountRequired())
|
||||||
|
) {
|
||||||
|
this.router.navigate(["/remove-password"]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,70 +1,188 @@
|
|||||||
import { LOCALE_ID, NgModule } from "@angular/core";
|
import { Injector, LOCALE_ID, NgModule } from "@angular/core";
|
||||||
|
|
||||||
import { ApiService as ApiServiceAbstraction } from "@/jslib/common/src/abstractions/api.service";
|
import { ApiService as ApiServiceAbstraction } from "@/jslib/common/src/abstractions/api.service";
|
||||||
import { AppIdService as AppIdServiceAbstraction } from "@/jslib/common/src/abstractions/appId.service";
|
import { AppIdService as AppIdServiceAbstraction } from "@/jslib/common/src/abstractions/appId.service";
|
||||||
|
import { AuditService as AuditServiceAbstraction } from "@/jslib/common/src/abstractions/audit.service";
|
||||||
|
import { AuthService as AuthServiceAbstraction } from "@/jslib/common/src/abstractions/auth.service";
|
||||||
import { BroadcasterService as BroadcasterServiceAbstraction } from "@/jslib/common/src/abstractions/broadcaster.service";
|
import { BroadcasterService as BroadcasterServiceAbstraction } from "@/jslib/common/src/abstractions/broadcaster.service";
|
||||||
|
import { CipherService as CipherServiceAbstraction } from "@/jslib/common/src/abstractions/cipher.service";
|
||||||
|
import { CollectionService as CollectionServiceAbstraction } from "@/jslib/common/src/abstractions/collection.service";
|
||||||
import { CryptoService as CryptoServiceAbstraction } from "@/jslib/common/src/abstractions/crypto.service";
|
import { CryptoService as CryptoServiceAbstraction } from "@/jslib/common/src/abstractions/crypto.service";
|
||||||
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@/jslib/common/src/abstractions/cryptoFunction.service";
|
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@/jslib/common/src/abstractions/cryptoFunction.service";
|
||||||
import { EnvironmentService as EnvironmentServiceAbstraction } from "@/jslib/common/src/abstractions/environment.service";
|
import { EnvironmentService as EnvironmentServiceAbstraction } from "@/jslib/common/src/abstractions/environment.service";
|
||||||
|
import { EventService as EventServiceAbstraction } from "@/jslib/common/src/abstractions/event.service";
|
||||||
|
import { FileUploadService as FileUploadServiceAbstraction } from "@/jslib/common/src/abstractions/fileUpload.service";
|
||||||
|
import { FolderService as FolderServiceAbstraction } from "@/jslib/common/src/abstractions/folder.service";
|
||||||
import { I18nService as I18nServiceAbstraction } from "@/jslib/common/src/abstractions/i18n.service";
|
import { I18nService as I18nServiceAbstraction } from "@/jslib/common/src/abstractions/i18n.service";
|
||||||
|
import { KeyConnectorService as KeyConnectorServiceAbstraction } from "@/jslib/common/src/abstractions/keyConnector.service";
|
||||||
import { LogService } from "@/jslib/common/src/abstractions/log.service";
|
import { LogService } from "@/jslib/common/src/abstractions/log.service";
|
||||||
import { MessagingService as MessagingServiceAbstraction } from "@/jslib/common/src/abstractions/messaging.service";
|
import { MessagingService as MessagingServiceAbstraction } from "@/jslib/common/src/abstractions/messaging.service";
|
||||||
|
import { NotificationsService as NotificationsServiceAbstraction } from "@/jslib/common/src/abstractions/notifications.service";
|
||||||
|
import { OrganizationService as OrganizationServiceAbstraction } from "@/jslib/common/src/abstractions/organization.service";
|
||||||
|
import { PasswordGenerationService as PasswordGenerationServiceAbstraction } from "@/jslib/common/src/abstractions/passwordGeneration.service";
|
||||||
|
import { PasswordRepromptService as PasswordRepromptServiceAbstraction } from "@/jslib/common/src/abstractions/passwordReprompt.service";
|
||||||
import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "@/jslib/common/src/abstractions/platformUtils.service";
|
import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "@/jslib/common/src/abstractions/platformUtils.service";
|
||||||
|
import { PolicyService as PolicyServiceAbstraction } from "@/jslib/common/src/abstractions/policy.service";
|
||||||
|
import { ProviderService as ProviderServiceAbstraction } from "@/jslib/common/src/abstractions/provider.service";
|
||||||
|
import { SearchService as SearchServiceAbstraction } from "@/jslib/common/src/abstractions/search.service";
|
||||||
|
import { SendService as SendServiceAbstraction } from "@/jslib/common/src/abstractions/send.service";
|
||||||
|
import { SettingsService as SettingsServiceAbstraction } from "@/jslib/common/src/abstractions/settings.service";
|
||||||
import { StateService as StateServiceAbstraction } from "@/jslib/common/src/abstractions/state.service";
|
import { StateService as StateServiceAbstraction } from "@/jslib/common/src/abstractions/state.service";
|
||||||
import { StateMigrationService as StateMigrationServiceAbstraction } from "@/jslib/common/src/abstractions/stateMigration.service";
|
import { StateMigrationService as StateMigrationServiceAbstraction } from "@/jslib/common/src/abstractions/stateMigration.service";
|
||||||
import { StorageService as StorageServiceAbstraction } from "@/jslib/common/src/abstractions/storage.service";
|
import { StorageService as StorageServiceAbstraction } from "@/jslib/common/src/abstractions/storage.service";
|
||||||
|
import { SyncService as SyncServiceAbstraction } from "@/jslib/common/src/abstractions/sync.service";
|
||||||
import { TokenService as TokenServiceAbstraction } from "@/jslib/common/src/abstractions/token.service";
|
import { TokenService as TokenServiceAbstraction } from "@/jslib/common/src/abstractions/token.service";
|
||||||
|
import { TotpService as TotpServiceAbstraction } from "@/jslib/common/src/abstractions/totp.service";
|
||||||
|
import { TwoFactorService as TwoFactorServiceAbstraction } from "@/jslib/common/src/abstractions/twoFactor.service";
|
||||||
|
import { UserVerificationService as UserVerificationServiceAbstraction } from "@/jslib/common/src/abstractions/userVerification.service";
|
||||||
|
import { UsernameGenerationService as UsernameGenerationServiceAbstraction } from "@/jslib/common/src/abstractions/usernameGeneration.service";
|
||||||
|
import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "@/jslib/common/src/abstractions/vaultTimeout.service";
|
||||||
import { StateFactory } from "@/jslib/common/src/factories/stateFactory";
|
import { StateFactory } from "@/jslib/common/src/factories/stateFactory";
|
||||||
import { Account } from "@/jslib/common/src/models/domain/account";
|
import { Account } from "@/jslib/common/src/models/domain/account";
|
||||||
import { GlobalState } from "@/jslib/common/src/models/domain/globalState";
|
import { GlobalState } from "@/jslib/common/src/models/domain/globalState";
|
||||||
import { ApiService } from "@/jslib/common/src/services/api.service";
|
import { ApiService } from "@/jslib/common/src/services/api.service";
|
||||||
import { AppIdService } from "@/jslib/common/src/services/appId.service";
|
import { AppIdService } from "@/jslib/common/src/services/appId.service";
|
||||||
|
import { AuditService } from "@/jslib/common/src/services/audit.service";
|
||||||
|
import { AuthService } from "@/jslib/common/src/services/auth.service";
|
||||||
|
import { CipherService } from "@/jslib/common/src/services/cipher.service";
|
||||||
|
import { CollectionService } from "@/jslib/common/src/services/collection.service";
|
||||||
import { ConsoleLogService } from "@/jslib/common/src/services/consoleLog.service";
|
import { ConsoleLogService } from "@/jslib/common/src/services/consoleLog.service";
|
||||||
import { CryptoService } from "@/jslib/common/src/services/crypto.service";
|
import { CryptoService } from "@/jslib/common/src/services/crypto.service";
|
||||||
import { EnvironmentService } from "@/jslib/common/src/services/environment.service";
|
import { EnvironmentService } from "@/jslib/common/src/services/environment.service";
|
||||||
|
import { EventService } from "@/jslib/common/src/services/event.service";
|
||||||
|
import { FileUploadService } from "@/jslib/common/src/services/fileUpload.service";
|
||||||
|
import { FolderService } from "@/jslib/common/src/services/folder.service";
|
||||||
|
import { KeyConnectorService } from "@/jslib/common/src/services/keyConnector.service";
|
||||||
|
import { NotificationsService } from "@/jslib/common/src/services/notifications.service";
|
||||||
|
import { OrganizationService } from "@/jslib/common/src/services/organization.service";
|
||||||
|
import { PasswordGenerationService } from "@/jslib/common/src/services/passwordGeneration.service";
|
||||||
|
import { PolicyService } from "@/jslib/common/src/services/policy.service";
|
||||||
|
import { ProviderService } from "@/jslib/common/src/services/provider.service";
|
||||||
|
import { SearchService } from "@/jslib/common/src/services/search.service";
|
||||||
|
import { SendService } from "@/jslib/common/src/services/send.service";
|
||||||
|
import { SettingsService } from "@/jslib/common/src/services/settings.service";
|
||||||
import { StateService } from "@/jslib/common/src/services/state.service";
|
import { StateService } from "@/jslib/common/src/services/state.service";
|
||||||
import { StateMigrationService } from "@/jslib/common/src/services/stateMigration.service";
|
import { StateMigrationService } from "@/jslib/common/src/services/stateMigration.service";
|
||||||
|
import { SyncService } from "@/jslib/common/src/services/sync.service";
|
||||||
import { TokenService } from "@/jslib/common/src/services/token.service";
|
import { TokenService } from "@/jslib/common/src/services/token.service";
|
||||||
|
import { TotpService } from "@/jslib/common/src/services/totp.service";
|
||||||
|
import { TwoFactorService } from "@/jslib/common/src/services/twoFactor.service";
|
||||||
|
import { UserVerificationService } from "@/jslib/common/src/services/userVerification.service";
|
||||||
|
import { UsernameGenerationService } from "@/jslib/common/src/services/usernameGeneration.service";
|
||||||
|
import { VaultTimeoutService } from "@/jslib/common/src/services/vaultTimeout.service";
|
||||||
|
|
||||||
import {
|
import { AuthGuardService } from "./auth-guard.service";
|
||||||
SafeInjectionToken,
|
|
||||||
SECURE_STORAGE,
|
|
||||||
WINDOW,
|
|
||||||
} from "../../../../src/app/services/injection-tokens";
|
|
||||||
import { SafeProvider, safeProvider } from "../../../../src/app/services/safe-provider";
|
|
||||||
|
|
||||||
import { BroadcasterService } from "./broadcaster.service";
|
import { BroadcasterService } from "./broadcaster.service";
|
||||||
|
import { LockGuardService } from "./lock-guard.service";
|
||||||
import { ModalService } from "./modal.service";
|
import { ModalService } from "./modal.service";
|
||||||
|
import { PasswordRepromptService } from "./passwordReprompt.service";
|
||||||
|
import { UnauthGuardService } from "./unauth-guard.service";
|
||||||
import { ValidationService } from "./validation.service";
|
import { ValidationService } from "./validation.service";
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [],
|
declarations: [],
|
||||||
providers: [
|
providers: [
|
||||||
safeProvider({ provide: WINDOW, useValue: window }),
|
{ provide: "WINDOW", useValue: window },
|
||||||
safeProvider({
|
{
|
||||||
provide: LOCALE_ID as SafeInjectionToken<string>,
|
provide: LOCALE_ID,
|
||||||
useFactory: (i18nService: I18nServiceAbstraction) => i18nService.translationLocale,
|
useFactory: (i18nService: I18nServiceAbstraction) => i18nService.translationLocale,
|
||||||
deps: [I18nServiceAbstraction],
|
deps: [I18nServiceAbstraction],
|
||||||
}),
|
},
|
||||||
safeProvider(ValidationService),
|
ValidationService,
|
||||||
safeProvider(ModalService),
|
AuthGuardService,
|
||||||
safeProvider({
|
UnauthGuardService,
|
||||||
|
LockGuardService,
|
||||||
|
ModalService,
|
||||||
|
{
|
||||||
provide: AppIdServiceAbstraction,
|
provide: AppIdServiceAbstraction,
|
||||||
useClass: AppIdService,
|
useClass: AppIdService,
|
||||||
deps: [StorageServiceAbstraction],
|
deps: [StorageServiceAbstraction],
|
||||||
}),
|
},
|
||||||
safeProvider({ provide: LogService, useFactory: () => new ConsoleLogService(false), deps: [] }),
|
{
|
||||||
safeProvider({
|
provide: AuditServiceAbstraction,
|
||||||
|
useClass: AuditService,
|
||||||
|
deps: [CryptoFunctionServiceAbstraction, ApiServiceAbstraction],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: AuthServiceAbstraction,
|
||||||
|
useClass: AuthService,
|
||||||
|
deps: [
|
||||||
|
CryptoServiceAbstraction,
|
||||||
|
ApiServiceAbstraction,
|
||||||
|
TokenServiceAbstraction,
|
||||||
|
AppIdServiceAbstraction,
|
||||||
|
PlatformUtilsServiceAbstraction,
|
||||||
|
MessagingServiceAbstraction,
|
||||||
|
LogService,
|
||||||
|
KeyConnectorServiceAbstraction,
|
||||||
|
EnvironmentServiceAbstraction,
|
||||||
|
StateServiceAbstraction,
|
||||||
|
TwoFactorServiceAbstraction,
|
||||||
|
I18nServiceAbstraction,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: CipherServiceAbstraction,
|
||||||
|
useFactory: (
|
||||||
|
cryptoService: CryptoServiceAbstraction,
|
||||||
|
settingsService: SettingsServiceAbstraction,
|
||||||
|
apiService: ApiServiceAbstraction,
|
||||||
|
fileUploadService: FileUploadServiceAbstraction,
|
||||||
|
i18nService: I18nServiceAbstraction,
|
||||||
|
injector: Injector,
|
||||||
|
logService: LogService,
|
||||||
|
stateService: StateServiceAbstraction,
|
||||||
|
) =>
|
||||||
|
new CipherService(
|
||||||
|
cryptoService,
|
||||||
|
settingsService,
|
||||||
|
apiService,
|
||||||
|
fileUploadService,
|
||||||
|
i18nService,
|
||||||
|
() => injector.get(SearchServiceAbstraction),
|
||||||
|
logService,
|
||||||
|
stateService,
|
||||||
|
),
|
||||||
|
deps: [
|
||||||
|
CryptoServiceAbstraction,
|
||||||
|
SettingsServiceAbstraction,
|
||||||
|
ApiServiceAbstraction,
|
||||||
|
FileUploadServiceAbstraction,
|
||||||
|
I18nServiceAbstraction,
|
||||||
|
Injector, // TODO: Get rid of this circular dependency!
|
||||||
|
LogService,
|
||||||
|
StateServiceAbstraction,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: FolderServiceAbstraction,
|
||||||
|
useClass: FolderService,
|
||||||
|
deps: [
|
||||||
|
CryptoServiceAbstraction,
|
||||||
|
ApiServiceAbstraction,
|
||||||
|
I18nServiceAbstraction,
|
||||||
|
CipherServiceAbstraction,
|
||||||
|
StateServiceAbstraction,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ provide: LogService, useFactory: () => new ConsoleLogService(false) },
|
||||||
|
{
|
||||||
|
provide: CollectionServiceAbstraction,
|
||||||
|
useClass: CollectionService,
|
||||||
|
deps: [CryptoServiceAbstraction, I18nServiceAbstraction, StateServiceAbstraction],
|
||||||
|
},
|
||||||
|
{
|
||||||
provide: EnvironmentServiceAbstraction,
|
provide: EnvironmentServiceAbstraction,
|
||||||
useClass: EnvironmentService,
|
useClass: EnvironmentService,
|
||||||
deps: [StateServiceAbstraction],
|
deps: [StateServiceAbstraction],
|
||||||
}),
|
},
|
||||||
safeProvider({
|
{
|
||||||
provide: TokenServiceAbstraction,
|
provide: TotpServiceAbstraction,
|
||||||
useClass: TokenService,
|
useClass: TotpService,
|
||||||
deps: [StateServiceAbstraction],
|
deps: [CryptoFunctionServiceAbstraction, LogService, StateServiceAbstraction],
|
||||||
}),
|
},
|
||||||
safeProvider({
|
{ provide: TokenServiceAbstraction, useClass: TokenService, deps: [StateServiceAbstraction] },
|
||||||
|
{
|
||||||
provide: CryptoServiceAbstraction,
|
provide: CryptoServiceAbstraction,
|
||||||
useClass: CryptoService,
|
useClass: CryptoService,
|
||||||
deps: [
|
deps: [
|
||||||
@@ -73,8 +191,18 @@ import { ValidationService } from "./validation.service";
|
|||||||
LogService,
|
LogService,
|
||||||
StateServiceAbstraction,
|
StateServiceAbstraction,
|
||||||
],
|
],
|
||||||
}),
|
},
|
||||||
safeProvider({
|
{
|
||||||
|
provide: PasswordGenerationServiceAbstraction,
|
||||||
|
useClass: PasswordGenerationService,
|
||||||
|
deps: [CryptoServiceAbstraction, PolicyServiceAbstraction, StateServiceAbstraction],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: UsernameGenerationServiceAbstraction,
|
||||||
|
useClass: UsernameGenerationService,
|
||||||
|
deps: [CryptoServiceAbstraction, StateServiceAbstraction],
|
||||||
|
},
|
||||||
|
{
|
||||||
provide: ApiServiceAbstraction,
|
provide: ApiServiceAbstraction,
|
||||||
useFactory: (
|
useFactory: (
|
||||||
tokenService: TokenServiceAbstraction,
|
tokenService: TokenServiceAbstraction,
|
||||||
@@ -97,13 +225,116 @@ import { ValidationService } from "./validation.service";
|
|||||||
MessagingServiceAbstraction,
|
MessagingServiceAbstraction,
|
||||||
AppIdServiceAbstraction,
|
AppIdServiceAbstraction,
|
||||||
],
|
],
|
||||||
}),
|
},
|
||||||
safeProvider({
|
{
|
||||||
provide: BroadcasterServiceAbstraction,
|
provide: FileUploadServiceAbstraction,
|
||||||
useClass: BroadcasterService,
|
useClass: FileUploadService,
|
||||||
useAngularDecorators: true,
|
deps: [LogService, ApiServiceAbstraction],
|
||||||
}),
|
},
|
||||||
safeProvider({
|
{
|
||||||
|
provide: SyncServiceAbstraction,
|
||||||
|
useFactory: (
|
||||||
|
apiService: ApiServiceAbstraction,
|
||||||
|
settingsService: SettingsServiceAbstraction,
|
||||||
|
folderService: FolderServiceAbstraction,
|
||||||
|
cipherService: CipherServiceAbstraction,
|
||||||
|
cryptoService: CryptoServiceAbstraction,
|
||||||
|
collectionService: CollectionServiceAbstraction,
|
||||||
|
messagingService: MessagingServiceAbstraction,
|
||||||
|
policyService: PolicyServiceAbstraction,
|
||||||
|
sendService: SendServiceAbstraction,
|
||||||
|
logService: LogService,
|
||||||
|
keyConnectorService: KeyConnectorServiceAbstraction,
|
||||||
|
stateService: StateServiceAbstraction,
|
||||||
|
organizationService: OrganizationServiceAbstraction,
|
||||||
|
providerService: ProviderServiceAbstraction,
|
||||||
|
) =>
|
||||||
|
new SyncService(
|
||||||
|
apiService,
|
||||||
|
settingsService,
|
||||||
|
folderService,
|
||||||
|
cipherService,
|
||||||
|
cryptoService,
|
||||||
|
collectionService,
|
||||||
|
messagingService,
|
||||||
|
policyService,
|
||||||
|
sendService,
|
||||||
|
logService,
|
||||||
|
keyConnectorService,
|
||||||
|
stateService,
|
||||||
|
organizationService,
|
||||||
|
providerService,
|
||||||
|
async (expired: boolean) => messagingService.send("logout", { expired: expired }),
|
||||||
|
),
|
||||||
|
deps: [
|
||||||
|
ApiServiceAbstraction,
|
||||||
|
SettingsServiceAbstraction,
|
||||||
|
FolderServiceAbstraction,
|
||||||
|
CipherServiceAbstraction,
|
||||||
|
CryptoServiceAbstraction,
|
||||||
|
CollectionServiceAbstraction,
|
||||||
|
MessagingServiceAbstraction,
|
||||||
|
PolicyServiceAbstraction,
|
||||||
|
SendServiceAbstraction,
|
||||||
|
LogService,
|
||||||
|
KeyConnectorServiceAbstraction,
|
||||||
|
StateServiceAbstraction,
|
||||||
|
OrganizationServiceAbstraction,
|
||||||
|
ProviderServiceAbstraction,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ provide: BroadcasterServiceAbstraction, useClass: BroadcasterService },
|
||||||
|
{
|
||||||
|
provide: SettingsServiceAbstraction,
|
||||||
|
useClass: SettingsService,
|
||||||
|
deps: [StateServiceAbstraction],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: VaultTimeoutServiceAbstraction,
|
||||||
|
useFactory: (
|
||||||
|
cipherService: CipherServiceAbstraction,
|
||||||
|
folderService: FolderServiceAbstraction,
|
||||||
|
collectionService: CollectionServiceAbstraction,
|
||||||
|
cryptoService: CryptoServiceAbstraction,
|
||||||
|
platformUtilsService: PlatformUtilsServiceAbstraction,
|
||||||
|
messagingService: MessagingServiceAbstraction,
|
||||||
|
searchService: SearchServiceAbstraction,
|
||||||
|
tokenService: TokenServiceAbstraction,
|
||||||
|
policyService: PolicyServiceAbstraction,
|
||||||
|
keyConnectorService: KeyConnectorServiceAbstraction,
|
||||||
|
stateService: StateServiceAbstraction,
|
||||||
|
) =>
|
||||||
|
new VaultTimeoutService(
|
||||||
|
cipherService,
|
||||||
|
folderService,
|
||||||
|
collectionService,
|
||||||
|
cryptoService,
|
||||||
|
platformUtilsService,
|
||||||
|
messagingService,
|
||||||
|
searchService,
|
||||||
|
tokenService,
|
||||||
|
policyService,
|
||||||
|
keyConnectorService,
|
||||||
|
stateService,
|
||||||
|
null,
|
||||||
|
async (userId?: string) =>
|
||||||
|
messagingService.send("logout", { expired: false, userId: userId }),
|
||||||
|
),
|
||||||
|
deps: [
|
||||||
|
CipherServiceAbstraction,
|
||||||
|
FolderServiceAbstraction,
|
||||||
|
CollectionServiceAbstraction,
|
||||||
|
CryptoServiceAbstraction,
|
||||||
|
PlatformUtilsServiceAbstraction,
|
||||||
|
MessagingServiceAbstraction,
|
||||||
|
SearchServiceAbstraction,
|
||||||
|
TokenServiceAbstraction,
|
||||||
|
PolicyServiceAbstraction,
|
||||||
|
KeyConnectorServiceAbstraction,
|
||||||
|
StateServiceAbstraction,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
provide: StateServiceAbstraction,
|
provide: StateServiceAbstraction,
|
||||||
useFactory: (
|
useFactory: (
|
||||||
storageService: StorageServiceAbstraction,
|
storageService: StorageServiceAbstraction,
|
||||||
@@ -120,12 +351,12 @@ import { ValidationService } from "./validation.service";
|
|||||||
),
|
),
|
||||||
deps: [
|
deps: [
|
||||||
StorageServiceAbstraction,
|
StorageServiceAbstraction,
|
||||||
SECURE_STORAGE,
|
"SECURE_STORAGE",
|
||||||
LogService,
|
LogService,
|
||||||
StateMigrationServiceAbstraction,
|
StateMigrationServiceAbstraction,
|
||||||
],
|
],
|
||||||
}),
|
},
|
||||||
safeProvider({
|
{
|
||||||
provide: StateMigrationServiceAbstraction,
|
provide: StateMigrationServiceAbstraction,
|
||||||
useFactory: (
|
useFactory: (
|
||||||
storageService: StorageServiceAbstraction,
|
storageService: StorageServiceAbstraction,
|
||||||
@@ -136,8 +367,108 @@ import { ValidationService } from "./validation.service";
|
|||||||
secureStorageService,
|
secureStorageService,
|
||||||
new StateFactory(GlobalState, Account),
|
new StateFactory(GlobalState, Account),
|
||||||
),
|
),
|
||||||
deps: [StorageServiceAbstraction, SECURE_STORAGE],
|
deps: [StorageServiceAbstraction, "SECURE_STORAGE"],
|
||||||
}),
|
},
|
||||||
] satisfies SafeProvider[],
|
{
|
||||||
|
provide: SearchServiceAbstraction,
|
||||||
|
useClass: SearchService,
|
||||||
|
deps: [CipherServiceAbstraction, LogService, I18nServiceAbstraction],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: NotificationsServiceAbstraction,
|
||||||
|
useFactory: (
|
||||||
|
syncService: SyncServiceAbstraction,
|
||||||
|
appIdService: AppIdServiceAbstraction,
|
||||||
|
apiService: ApiServiceAbstraction,
|
||||||
|
vaultTimeoutService: VaultTimeoutServiceAbstraction,
|
||||||
|
environmentService: EnvironmentServiceAbstraction,
|
||||||
|
messagingService: MessagingServiceAbstraction,
|
||||||
|
logService: LogService,
|
||||||
|
stateService: StateServiceAbstraction,
|
||||||
|
) =>
|
||||||
|
new NotificationsService(
|
||||||
|
syncService,
|
||||||
|
appIdService,
|
||||||
|
apiService,
|
||||||
|
vaultTimeoutService,
|
||||||
|
environmentService,
|
||||||
|
async () => messagingService.send("logout", { expired: true }),
|
||||||
|
logService,
|
||||||
|
stateService,
|
||||||
|
),
|
||||||
|
deps: [
|
||||||
|
SyncServiceAbstraction,
|
||||||
|
AppIdServiceAbstraction,
|
||||||
|
ApiServiceAbstraction,
|
||||||
|
VaultTimeoutServiceAbstraction,
|
||||||
|
EnvironmentServiceAbstraction,
|
||||||
|
MessagingServiceAbstraction,
|
||||||
|
LogService,
|
||||||
|
StateServiceAbstraction,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: EventServiceAbstraction,
|
||||||
|
useClass: EventService,
|
||||||
|
deps: [
|
||||||
|
ApiServiceAbstraction,
|
||||||
|
CipherServiceAbstraction,
|
||||||
|
StateServiceAbstraction,
|
||||||
|
LogService,
|
||||||
|
OrganizationServiceAbstraction,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: PolicyServiceAbstraction,
|
||||||
|
useClass: PolicyService,
|
||||||
|
deps: [StateServiceAbstraction, OrganizationServiceAbstraction, ApiServiceAbstraction],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: SendServiceAbstraction,
|
||||||
|
useClass: SendService,
|
||||||
|
deps: [
|
||||||
|
CryptoServiceAbstraction,
|
||||||
|
ApiServiceAbstraction,
|
||||||
|
FileUploadServiceAbstraction,
|
||||||
|
I18nServiceAbstraction,
|
||||||
|
CryptoFunctionServiceAbstraction,
|
||||||
|
StateServiceAbstraction,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: KeyConnectorServiceAbstraction,
|
||||||
|
useClass: KeyConnectorService,
|
||||||
|
deps: [
|
||||||
|
StateServiceAbstraction,
|
||||||
|
CryptoServiceAbstraction,
|
||||||
|
ApiServiceAbstraction,
|
||||||
|
TokenServiceAbstraction,
|
||||||
|
LogService,
|
||||||
|
OrganizationServiceAbstraction,
|
||||||
|
CryptoFunctionServiceAbstraction,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: UserVerificationServiceAbstraction,
|
||||||
|
useClass: UserVerificationService,
|
||||||
|
deps: [CryptoServiceAbstraction, I18nServiceAbstraction, ApiServiceAbstraction],
|
||||||
|
},
|
||||||
|
{ provide: PasswordRepromptServiceAbstraction, useClass: PasswordRepromptService },
|
||||||
|
{
|
||||||
|
provide: OrganizationServiceAbstraction,
|
||||||
|
useClass: OrganizationService,
|
||||||
|
deps: [StateServiceAbstraction],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: ProviderServiceAbstraction,
|
||||||
|
useClass: ProviderService,
|
||||||
|
deps: [StateServiceAbstraction],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: TwoFactorServiceAbstraction,
|
||||||
|
useClass: TwoFactorService,
|
||||||
|
deps: [I18nServiceAbstraction, PlatformUtilsServiceAbstraction],
|
||||||
|
},
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class JslibServicesModule {}
|
export class JslibServicesModule {}
|
||||||
|
|||||||
29
jslib/angular/src/services/lock-guard.service.ts
Normal file
29
jslib/angular/src/services/lock-guard.service.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { Injectable } from "@angular/core";
|
||||||
|
import { Router } from "@angular/router";
|
||||||
|
|
||||||
|
import { StateService } from "@/jslib/common/src/abstractions/state.service";
|
||||||
|
import { VaultTimeoutService } from "@/jslib/common/src/abstractions/vaultTimeout.service";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class LockGuardService {
|
||||||
|
protected homepage = "vault";
|
||||||
|
protected loginpage = "login";
|
||||||
|
constructor(
|
||||||
|
private vaultTimeoutService: VaultTimeoutService,
|
||||||
|
private router: Router,
|
||||||
|
private stateService: StateService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async canActivate() {
|
||||||
|
if (await this.vaultTimeoutService.isLocked()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const redirectUrl = (await this.stateService.getIsAuthenticated())
|
||||||
|
? [this.homepage]
|
||||||
|
: [this.loginpage];
|
||||||
|
|
||||||
|
this.router.navigate(redirectUrl);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -143,7 +143,7 @@ export class ModalService {
|
|||||||
dialogEl.style.zIndex = `${this.modalCount}050`;
|
dialogEl.style.zIndex = `${this.modalCount}050`;
|
||||||
|
|
||||||
const modals = Array.from(
|
const modals = Array.from(
|
||||||
el.querySelectorAll('.modal-backdrop, .modal *[data-bs-dismiss="modal"]'),
|
el.querySelectorAll('.modal-backdrop, .modal *[data-dismiss="modal"]'),
|
||||||
);
|
);
|
||||||
for (const closeElement of modals) {
|
for (const closeElement of modals) {
|
||||||
closeElement.addEventListener("click", () => {
|
closeElement.addEventListener("click", () => {
|
||||||
|
|||||||
45
jslib/angular/src/services/passwordReprompt.service.ts
Normal file
45
jslib/angular/src/services/passwordReprompt.service.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import { Injectable } from "@angular/core";
|
||||||
|
|
||||||
|
import { KeyConnectorService } from "@/jslib/common/src/abstractions/keyConnector.service";
|
||||||
|
import { PasswordRepromptService as PasswordRepromptServiceAbstraction } from "@/jslib/common/src/abstractions/passwordReprompt.service";
|
||||||
|
|
||||||
|
import { PasswordRepromptComponent } from "../components/password-reprompt.component";
|
||||||
|
|
||||||
|
import { ModalService } from "./modal.service";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to verify the user's Master Password for the "Master Password Re-prompt" feature only.
|
||||||
|
* See UserVerificationService for any other situation where you need to verify the user's identity.
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class PasswordRepromptService implements PasswordRepromptServiceAbstraction {
|
||||||
|
protected component = PasswordRepromptComponent;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private modalService: ModalService,
|
||||||
|
private keyConnectorService: KeyConnectorService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
protectedFields() {
|
||||||
|
return ["TOTP", "Password", "H_Field", "Card Number", "Security Code"];
|
||||||
|
}
|
||||||
|
|
||||||
|
async showPasswordPrompt() {
|
||||||
|
if (!(await this.enabled())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ref = this.modalService.open(this.component, { allowMultipleModals: true });
|
||||||
|
|
||||||
|
if (ref == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await ref.onClosedPromise();
|
||||||
|
return result === true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async enabled() {
|
||||||
|
return !(await this.keyConnectorService.getUsesKeyConnector());
|
||||||
|
}
|
||||||
|
}
|
||||||
29
jslib/angular/src/services/unauth-guard.service.ts
Normal file
29
jslib/angular/src/services/unauth-guard.service.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { Injectable } from "@angular/core";
|
||||||
|
import { Router } from "@angular/router";
|
||||||
|
|
||||||
|
import { StateService } from "@/jslib/common/src/abstractions/state.service";
|
||||||
|
import { VaultTimeoutService } from "@/jslib/common/src/abstractions/vaultTimeout.service";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UnauthGuardService {
|
||||||
|
protected homepage = "vault";
|
||||||
|
constructor(
|
||||||
|
private vaultTimeoutService: VaultTimeoutService,
|
||||||
|
private router: Router,
|
||||||
|
private stateService: StateService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async canActivate() {
|
||||||
|
const isAuthed = await this.stateService.getIsAuthenticated();
|
||||||
|
if (isAuthed) {
|
||||||
|
const locked = await this.vaultTimeoutService.isLocked();
|
||||||
|
if (locked) {
|
||||||
|
this.router.navigate(["lock"]);
|
||||||
|
} else {
|
||||||
|
this.router.navigate([this.homepage]);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
114
jslib/common/spec/misc/logInStrategies/apiLogIn.strategy.spec.ts
Normal file
114
jslib/common/spec/misc/logInStrategies/apiLogIn.strategy.spec.ts
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
import { Arg, Substitute, SubstituteOf } from "@fluffy-spoon/substitute";
|
||||||
|
|
||||||
|
import { ApiService } from "@/jslib/common/src/abstractions/api.service";
|
||||||
|
import { AppIdService } from "@/jslib/common/src/abstractions/appId.service";
|
||||||
|
import { CryptoService } from "@/jslib/common/src/abstractions/crypto.service";
|
||||||
|
import { EnvironmentService } from "@/jslib/common/src/abstractions/environment.service";
|
||||||
|
import { KeyConnectorService } from "@/jslib/common/src/abstractions/keyConnector.service";
|
||||||
|
import { LogService } from "@/jslib/common/src/abstractions/log.service";
|
||||||
|
import { MessagingService } from "@/jslib/common/src/abstractions/messaging.service";
|
||||||
|
import { PlatformUtilsService } from "@/jslib/common/src/abstractions/platformUtils.service";
|
||||||
|
import { StateService } from "@/jslib/common/src/abstractions/state.service";
|
||||||
|
import { TokenService } from "@/jslib/common/src/abstractions/token.service";
|
||||||
|
import { TwoFactorService } from "@/jslib/common/src/abstractions/twoFactor.service";
|
||||||
|
import { ApiLogInStrategy } from "@/jslib/common/src/misc/logInStrategies/apiLogin.strategy";
|
||||||
|
import { Utils } from "@/jslib/common/src/misc/utils";
|
||||||
|
import { ApiLogInCredentials } from "@/jslib/common/src/models/domain/logInCredentials";
|
||||||
|
|
||||||
|
import { identityTokenResponseFactory } from "./logIn.strategy.spec";
|
||||||
|
|
||||||
|
describe("ApiLogInStrategy", () => {
|
||||||
|
let cryptoService: SubstituteOf<CryptoService>;
|
||||||
|
let apiService: SubstituteOf<ApiService>;
|
||||||
|
let tokenService: SubstituteOf<TokenService>;
|
||||||
|
let appIdService: SubstituteOf<AppIdService>;
|
||||||
|
let platformUtilsService: SubstituteOf<PlatformUtilsService>;
|
||||||
|
let messagingService: SubstituteOf<MessagingService>;
|
||||||
|
let logService: SubstituteOf<LogService>;
|
||||||
|
let environmentService: SubstituteOf<EnvironmentService>;
|
||||||
|
let keyConnectorService: SubstituteOf<KeyConnectorService>;
|
||||||
|
let stateService: SubstituteOf<StateService>;
|
||||||
|
let twoFactorService: SubstituteOf<TwoFactorService>;
|
||||||
|
|
||||||
|
let apiLogInStrategy: ApiLogInStrategy;
|
||||||
|
let credentials: ApiLogInCredentials;
|
||||||
|
|
||||||
|
const deviceId = Utils.newGuid();
|
||||||
|
const keyConnectorUrl = "KEY_CONNECTOR_URL";
|
||||||
|
const apiClientId = "API_CLIENT_ID";
|
||||||
|
const apiClientSecret = "API_CLIENT_SECRET";
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
cryptoService = Substitute.for<CryptoService>();
|
||||||
|
apiService = Substitute.for<ApiService>();
|
||||||
|
tokenService = Substitute.for<TokenService>();
|
||||||
|
appIdService = Substitute.for<AppIdService>();
|
||||||
|
platformUtilsService = Substitute.for<PlatformUtilsService>();
|
||||||
|
messagingService = Substitute.for<MessagingService>();
|
||||||
|
logService = Substitute.for<LogService>();
|
||||||
|
environmentService = Substitute.for<EnvironmentService>();
|
||||||
|
stateService = Substitute.for<StateService>();
|
||||||
|
keyConnectorService = Substitute.for<KeyConnectorService>();
|
||||||
|
twoFactorService = Substitute.for<TwoFactorService>();
|
||||||
|
|
||||||
|
appIdService.getAppId().resolves(deviceId);
|
||||||
|
tokenService.getTwoFactorToken().resolves(null);
|
||||||
|
|
||||||
|
apiLogInStrategy = new ApiLogInStrategy(
|
||||||
|
cryptoService,
|
||||||
|
apiService,
|
||||||
|
tokenService,
|
||||||
|
appIdService,
|
||||||
|
platformUtilsService,
|
||||||
|
messagingService,
|
||||||
|
logService,
|
||||||
|
stateService,
|
||||||
|
twoFactorService,
|
||||||
|
environmentService,
|
||||||
|
keyConnectorService,
|
||||||
|
);
|
||||||
|
|
||||||
|
credentials = new ApiLogInCredentials(apiClientId, apiClientSecret);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sends api key credentials to the server", async () => {
|
||||||
|
apiService.postIdentityToken(Arg.any()).resolves(identityTokenResponseFactory());
|
||||||
|
await apiLogInStrategy.logIn(credentials);
|
||||||
|
|
||||||
|
apiService.received(1).postIdentityToken(
|
||||||
|
Arg.is((actual) => {
|
||||||
|
const apiTokenRequest = actual as any;
|
||||||
|
return (
|
||||||
|
apiTokenRequest.clientId === apiClientId &&
|
||||||
|
apiTokenRequest.clientSecret === apiClientSecret &&
|
||||||
|
apiTokenRequest.device.identifier === deviceId &&
|
||||||
|
apiTokenRequest.twoFactor.provider == null &&
|
||||||
|
apiTokenRequest.twoFactor.token == null &&
|
||||||
|
apiTokenRequest.captchaResponse == null
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sets the local environment after a successful login", async () => {
|
||||||
|
apiService.postIdentityToken(Arg.any()).resolves(identityTokenResponseFactory());
|
||||||
|
|
||||||
|
await apiLogInStrategy.logIn(credentials);
|
||||||
|
|
||||||
|
stateService.received(1).setApiKeyClientId(apiClientId);
|
||||||
|
stateService.received(1).setApiKeyClientSecret(apiClientSecret);
|
||||||
|
stateService.received(1).addAccount(Arg.any());
|
||||||
|
});
|
||||||
|
|
||||||
|
it("gets and sets the Key Connector key from environmentUrl", async () => {
|
||||||
|
const tokenResponse = identityTokenResponseFactory();
|
||||||
|
tokenResponse.apiUseKeyConnector = true;
|
||||||
|
|
||||||
|
apiService.postIdentityToken(Arg.any()).resolves(tokenResponse);
|
||||||
|
environmentService.getKeyConnectorUrl().returns(keyConnectorUrl);
|
||||||
|
|
||||||
|
await apiLogInStrategy.logIn(credentials);
|
||||||
|
|
||||||
|
keyConnectorService.received(1).getAndSetKey(keyConnectorUrl);
|
||||||
|
});
|
||||||
|
});
|
||||||
288
jslib/common/spec/misc/logInStrategies/logIn.strategy.spec.ts
Normal file
288
jslib/common/spec/misc/logInStrategies/logIn.strategy.spec.ts
Normal file
@@ -0,0 +1,288 @@
|
|||||||
|
import { Arg, Substitute, SubstituteOf } from "@fluffy-spoon/substitute";
|
||||||
|
|
||||||
|
import { ApiService } from "@/jslib/common/src/abstractions/api.service";
|
||||||
|
import { AppIdService } from "@/jslib/common/src/abstractions/appId.service";
|
||||||
|
import { AuthService } from "@/jslib/common/src/abstractions/auth.service";
|
||||||
|
import { CryptoService } from "@/jslib/common/src/abstractions/crypto.service";
|
||||||
|
import { LogService } from "@/jslib/common/src/abstractions/log.service";
|
||||||
|
import { MessagingService } from "@/jslib/common/src/abstractions/messaging.service";
|
||||||
|
import { PlatformUtilsService } from "@/jslib/common/src/abstractions/platformUtils.service";
|
||||||
|
import { StateService } from "@/jslib/common/src/abstractions/state.service";
|
||||||
|
import { TokenService } from "@/jslib/common/src/abstractions/token.service";
|
||||||
|
import { TwoFactorService } from "@/jslib/common/src/abstractions/twoFactor.service";
|
||||||
|
import { TwoFactorProviderType } from "@/jslib/common/src/enums/twoFactorProviderType";
|
||||||
|
import { PasswordLogInStrategy } from "@/jslib/common/src/misc/logInStrategies/passwordLogin.strategy";
|
||||||
|
import { Utils } from "@/jslib/common/src/misc/utils";
|
||||||
|
import { Account, AccountProfile, AccountTokens } from "@/jslib/common/src/models/domain/account";
|
||||||
|
import { AuthResult } from "@/jslib/common/src/models/domain/authResult";
|
||||||
|
import { EncString } from "@/jslib/common/src/models/domain/encString";
|
||||||
|
import { PasswordLogInCredentials } from "@/jslib/common/src/models/domain/logInCredentials";
|
||||||
|
import { PasswordTokenRequest } from "@/jslib/common/src/models/request/identityToken/passwordTokenRequest";
|
||||||
|
import { TokenRequestTwoFactor } from "@/jslib/common/src/models/request/identityToken/tokenRequestTwoFactor";
|
||||||
|
import { IdentityCaptchaResponse } from "@/jslib/common/src/models/response/identityCaptchaResponse";
|
||||||
|
import { IdentityTokenResponse } from "@/jslib/common/src/models/response/identityTokenResponse";
|
||||||
|
import { IdentityTwoFactorResponse } from "@/jslib/common/src/models/response/identityTwoFactorResponse";
|
||||||
|
|
||||||
|
const email = "hello@world.com";
|
||||||
|
const masterPassword = "password";
|
||||||
|
|
||||||
|
const deviceId = Utils.newGuid();
|
||||||
|
const accessToken = "ACCESS_TOKEN";
|
||||||
|
const refreshToken = "REFRESH_TOKEN";
|
||||||
|
const encKey = "ENC_KEY";
|
||||||
|
const privateKey = "PRIVATE_KEY";
|
||||||
|
const captchaSiteKey = "CAPTCHA_SITE_KEY";
|
||||||
|
const kdf = 0;
|
||||||
|
const kdfIterations = 10000;
|
||||||
|
const userId = Utils.newGuid();
|
||||||
|
const masterPasswordHash = "MASTER_PASSWORD_HASH";
|
||||||
|
|
||||||
|
const decodedToken = {
|
||||||
|
sub: userId,
|
||||||
|
email: email,
|
||||||
|
premium: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const twoFactorProviderType = TwoFactorProviderType.Authenticator;
|
||||||
|
const twoFactorToken = "TWO_FACTOR_TOKEN";
|
||||||
|
const twoFactorRemember = true;
|
||||||
|
|
||||||
|
export function identityTokenResponseFactory() {
|
||||||
|
return new IdentityTokenResponse({
|
||||||
|
ForcePasswordReset: false,
|
||||||
|
Kdf: kdf,
|
||||||
|
KdfIterations: kdfIterations,
|
||||||
|
Key: encKey,
|
||||||
|
PrivateKey: privateKey,
|
||||||
|
ResetMasterPassword: false,
|
||||||
|
access_token: accessToken,
|
||||||
|
expires_in: 3600,
|
||||||
|
refresh_token: refreshToken,
|
||||||
|
scope: "api offline_access",
|
||||||
|
token_type: "Bearer",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("LogInStrategy", () => {
|
||||||
|
let cryptoService: SubstituteOf<CryptoService>;
|
||||||
|
let apiService: SubstituteOf<ApiService>;
|
||||||
|
let tokenService: SubstituteOf<TokenService>;
|
||||||
|
let appIdService: SubstituteOf<AppIdService>;
|
||||||
|
let platformUtilsService: SubstituteOf<PlatformUtilsService>;
|
||||||
|
let messagingService: SubstituteOf<MessagingService>;
|
||||||
|
let logService: SubstituteOf<LogService>;
|
||||||
|
let stateService: SubstituteOf<StateService>;
|
||||||
|
let twoFactorService: SubstituteOf<TwoFactorService>;
|
||||||
|
let authService: SubstituteOf<AuthService>;
|
||||||
|
|
||||||
|
let passwordLogInStrategy: PasswordLogInStrategy;
|
||||||
|
let credentials: PasswordLogInCredentials;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
cryptoService = Substitute.for<CryptoService>();
|
||||||
|
apiService = Substitute.for<ApiService>();
|
||||||
|
tokenService = Substitute.for<TokenService>();
|
||||||
|
appIdService = Substitute.for<AppIdService>();
|
||||||
|
platformUtilsService = Substitute.for<PlatformUtilsService>();
|
||||||
|
messagingService = Substitute.for<MessagingService>();
|
||||||
|
logService = Substitute.for<LogService>();
|
||||||
|
stateService = Substitute.for<StateService>();
|
||||||
|
twoFactorService = Substitute.for<TwoFactorService>();
|
||||||
|
authService = Substitute.for<AuthService>();
|
||||||
|
|
||||||
|
appIdService.getAppId().resolves(deviceId);
|
||||||
|
|
||||||
|
// The base class is abstract so we test it via PasswordLogInStrategy
|
||||||
|
passwordLogInStrategy = new PasswordLogInStrategy(
|
||||||
|
cryptoService,
|
||||||
|
apiService,
|
||||||
|
tokenService,
|
||||||
|
appIdService,
|
||||||
|
platformUtilsService,
|
||||||
|
messagingService,
|
||||||
|
logService,
|
||||||
|
stateService,
|
||||||
|
twoFactorService,
|
||||||
|
authService,
|
||||||
|
);
|
||||||
|
credentials = new PasswordLogInCredentials(email, masterPassword);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("base class", () => {
|
||||||
|
it("sets the local environment after a successful login", async () => {
|
||||||
|
apiService.postIdentityToken(Arg.any()).resolves(identityTokenResponseFactory());
|
||||||
|
tokenService.decodeToken(accessToken).resolves(decodedToken);
|
||||||
|
|
||||||
|
await passwordLogInStrategy.logIn(credentials);
|
||||||
|
|
||||||
|
stateService.received(1).addAccount(
|
||||||
|
new Account({
|
||||||
|
profile: {
|
||||||
|
...new AccountProfile(),
|
||||||
|
...{
|
||||||
|
userId: userId,
|
||||||
|
email: email,
|
||||||
|
hasPremiumPersonally: false,
|
||||||
|
kdfIterations: kdfIterations,
|
||||||
|
kdfType: kdf,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tokens: {
|
||||||
|
...new AccountTokens(),
|
||||||
|
...{
|
||||||
|
accessToken: accessToken,
|
||||||
|
refreshToken: refreshToken,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
cryptoService.received(1).setEncKey(encKey);
|
||||||
|
cryptoService.received(1).setEncPrivateKey(privateKey);
|
||||||
|
|
||||||
|
stateService.received(1).setBiometricLocked(false);
|
||||||
|
messagingService.received(1).send("loggedIn");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("builds AuthResult", async () => {
|
||||||
|
const tokenResponse = identityTokenResponseFactory();
|
||||||
|
tokenResponse.forcePasswordReset = true;
|
||||||
|
tokenResponse.resetMasterPassword = true;
|
||||||
|
|
||||||
|
apiService.postIdentityToken(Arg.any()).resolves(tokenResponse);
|
||||||
|
|
||||||
|
const result = await passwordLogInStrategy.logIn(credentials);
|
||||||
|
|
||||||
|
const expected = new AuthResult();
|
||||||
|
expected.forcePasswordReset = true;
|
||||||
|
expected.resetMasterPassword = true;
|
||||||
|
expected.twoFactorProviders = null;
|
||||||
|
expected.captchaSiteKey = "";
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("rejects login if CAPTCHA is required", async () => {
|
||||||
|
// Sample CAPTCHA response
|
||||||
|
const tokenResponse = new IdentityCaptchaResponse({
|
||||||
|
error: "invalid_grant",
|
||||||
|
error_description: "Captcha required.",
|
||||||
|
HCaptcha_SiteKey: captchaSiteKey,
|
||||||
|
});
|
||||||
|
|
||||||
|
apiService.postIdentityToken(Arg.any()).resolves(tokenResponse);
|
||||||
|
|
||||||
|
const result = await passwordLogInStrategy.logIn(credentials);
|
||||||
|
|
||||||
|
stateService.didNotReceive().addAccount(Arg.any());
|
||||||
|
messagingService.didNotReceive().send(Arg.any());
|
||||||
|
|
||||||
|
const expected = new AuthResult();
|
||||||
|
expected.captchaSiteKey = captchaSiteKey;
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("makes a new public and private key for an old account", async () => {
|
||||||
|
const tokenResponse = identityTokenResponseFactory();
|
||||||
|
tokenResponse.privateKey = null;
|
||||||
|
cryptoService.makeKeyPair(Arg.any()).resolves(["PUBLIC_KEY", new EncString("PRIVATE_KEY")]);
|
||||||
|
|
||||||
|
apiService.postIdentityToken(Arg.any()).resolves(tokenResponse);
|
||||||
|
|
||||||
|
await passwordLogInStrategy.logIn(credentials);
|
||||||
|
|
||||||
|
apiService.received(1).postAccountKeys(Arg.any());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Two-factor authentication", () => {
|
||||||
|
it("rejects login if 2FA is required", async () => {
|
||||||
|
// Sample response where TOTP 2FA required
|
||||||
|
const tokenResponse = new IdentityTwoFactorResponse({
|
||||||
|
TwoFactorProviders: ["0"],
|
||||||
|
TwoFactorProviders2: { 0: null },
|
||||||
|
error: "invalid_grant",
|
||||||
|
error_description: "Two factor required.",
|
||||||
|
});
|
||||||
|
|
||||||
|
apiService.postIdentityToken(Arg.any()).resolves(tokenResponse);
|
||||||
|
|
||||||
|
const result = await passwordLogInStrategy.logIn(credentials);
|
||||||
|
|
||||||
|
stateService.didNotReceive().addAccount(Arg.any());
|
||||||
|
messagingService.didNotReceive().send(Arg.any());
|
||||||
|
|
||||||
|
const expected = new AuthResult();
|
||||||
|
expected.twoFactorProviders = new Map<TwoFactorProviderType, { [key: string]: string }>();
|
||||||
|
expected.twoFactorProviders.set(0, null);
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sends stored 2FA token to server", async () => {
|
||||||
|
tokenService.getTwoFactorToken().resolves(twoFactorToken);
|
||||||
|
apiService.postIdentityToken(Arg.any()).resolves(identityTokenResponseFactory());
|
||||||
|
|
||||||
|
await passwordLogInStrategy.logIn(credentials);
|
||||||
|
|
||||||
|
apiService.received(1).postIdentityToken(
|
||||||
|
Arg.is((actual) => {
|
||||||
|
const passwordTokenRequest = actual as any;
|
||||||
|
return (
|
||||||
|
passwordTokenRequest.twoFactor.provider === TwoFactorProviderType.Remember &&
|
||||||
|
passwordTokenRequest.twoFactor.token === twoFactorToken &&
|
||||||
|
passwordTokenRequest.twoFactor.remember === false
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sends 2FA token provided by user to server (single step)", async () => {
|
||||||
|
// This occurs if the user enters the 2FA code as an argument in the CLI
|
||||||
|
apiService.postIdentityToken(Arg.any()).resolves(identityTokenResponseFactory());
|
||||||
|
credentials.twoFactor = new TokenRequestTwoFactor(
|
||||||
|
twoFactorProviderType,
|
||||||
|
twoFactorToken,
|
||||||
|
twoFactorRemember,
|
||||||
|
);
|
||||||
|
|
||||||
|
await passwordLogInStrategy.logIn(credentials);
|
||||||
|
|
||||||
|
apiService.received(1).postIdentityToken(
|
||||||
|
Arg.is((actual) => {
|
||||||
|
const passwordTokenRequest = actual as any;
|
||||||
|
return (
|
||||||
|
passwordTokenRequest.twoFactor.provider === twoFactorProviderType &&
|
||||||
|
passwordTokenRequest.twoFactor.token === twoFactorToken &&
|
||||||
|
passwordTokenRequest.twoFactor.remember === twoFactorRemember
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sends 2FA token provided by user to server (two-step)", async () => {
|
||||||
|
// Simulate a partially completed login
|
||||||
|
passwordLogInStrategy.tokenRequest = new PasswordTokenRequest(
|
||||||
|
email,
|
||||||
|
masterPasswordHash,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
|
||||||
|
apiService.postIdentityToken(Arg.any()).resolves(identityTokenResponseFactory());
|
||||||
|
|
||||||
|
await passwordLogInStrategy.logInTwoFactor(
|
||||||
|
new TokenRequestTwoFactor(twoFactorProviderType, twoFactorToken, twoFactorRemember),
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
|
||||||
|
apiService.received(1).postIdentityToken(
|
||||||
|
Arg.is((actual) => {
|
||||||
|
const passwordTokenRequest = actual as any;
|
||||||
|
return (
|
||||||
|
passwordTokenRequest.twoFactor.provider === twoFactorProviderType &&
|
||||||
|
passwordTokenRequest.twoFactor.token === twoFactorToken &&
|
||||||
|
passwordTokenRequest.twoFactor.remember === twoFactorRemember
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
import { Arg, Substitute, SubstituteOf } from "@fluffy-spoon/substitute";
|
||||||
|
|
||||||
|
import { ApiService } from "@/jslib/common/src/abstractions/api.service";
|
||||||
|
import { AppIdService } from "@/jslib/common/src/abstractions/appId.service";
|
||||||
|
import { AuthService } from "@/jslib/common/src/abstractions/auth.service";
|
||||||
|
import { CryptoService } from "@/jslib/common/src/abstractions/crypto.service";
|
||||||
|
import { LogService } from "@/jslib/common/src/abstractions/log.service";
|
||||||
|
import { MessagingService } from "@/jslib/common/src/abstractions/messaging.service";
|
||||||
|
import { PlatformUtilsService } from "@/jslib/common/src/abstractions/platformUtils.service";
|
||||||
|
import { StateService } from "@/jslib/common/src/abstractions/state.service";
|
||||||
|
import { TokenService } from "@/jslib/common/src/abstractions/token.service";
|
||||||
|
import { TwoFactorService } from "@/jslib/common/src/abstractions/twoFactor.service";
|
||||||
|
import { HashPurpose } from "@/jslib/common/src/enums/hashPurpose";
|
||||||
|
import { PasswordLogInStrategy } from "@/jslib/common/src/misc/logInStrategies/passwordLogin.strategy";
|
||||||
|
import { Utils } from "@/jslib/common/src/misc/utils";
|
||||||
|
import { PasswordLogInCredentials } from "@/jslib/common/src/models/domain/logInCredentials";
|
||||||
|
import { SymmetricCryptoKey } from "@/jslib/common/src/models/domain/symmetricCryptoKey";
|
||||||
|
|
||||||
|
import { identityTokenResponseFactory } from "./logIn.strategy.spec";
|
||||||
|
|
||||||
|
const email = "hello@world.com";
|
||||||
|
const masterPassword = "password";
|
||||||
|
const hashedPassword = "HASHED_PASSWORD";
|
||||||
|
const localHashedPassword = "LOCAL_HASHED_PASSWORD";
|
||||||
|
const preloginKey = new SymmetricCryptoKey(
|
||||||
|
Utils.fromB64ToArray(
|
||||||
|
"N2KWjlLpfi5uHjv+YcfUKIpZ1l+W+6HRensmIqD+BFYBf6N/dvFpJfWwYnVBdgFCK2tJTAIMLhqzIQQEUmGFgg==",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
const deviceId = Utils.newGuid();
|
||||||
|
|
||||||
|
describe("PasswordLogInStrategy", () => {
|
||||||
|
let cryptoService: SubstituteOf<CryptoService>;
|
||||||
|
let apiService: SubstituteOf<ApiService>;
|
||||||
|
let tokenService: SubstituteOf<TokenService>;
|
||||||
|
let appIdService: SubstituteOf<AppIdService>;
|
||||||
|
let platformUtilsService: SubstituteOf<PlatformUtilsService>;
|
||||||
|
let messagingService: SubstituteOf<MessagingService>;
|
||||||
|
let logService: SubstituteOf<LogService>;
|
||||||
|
let stateService: SubstituteOf<StateService>;
|
||||||
|
let twoFactorService: SubstituteOf<TwoFactorService>;
|
||||||
|
let authService: SubstituteOf<AuthService>;
|
||||||
|
|
||||||
|
let passwordLogInStrategy: PasswordLogInStrategy;
|
||||||
|
let credentials: PasswordLogInCredentials;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
cryptoService = Substitute.for<CryptoService>();
|
||||||
|
apiService = Substitute.for<ApiService>();
|
||||||
|
tokenService = Substitute.for<TokenService>();
|
||||||
|
appIdService = Substitute.for<AppIdService>();
|
||||||
|
platformUtilsService = Substitute.for<PlatformUtilsService>();
|
||||||
|
messagingService = Substitute.for<MessagingService>();
|
||||||
|
logService = Substitute.for<LogService>();
|
||||||
|
stateService = Substitute.for<StateService>();
|
||||||
|
twoFactorService = Substitute.for<TwoFactorService>();
|
||||||
|
authService = Substitute.for<AuthService>();
|
||||||
|
|
||||||
|
appIdService.getAppId().resolves(deviceId);
|
||||||
|
tokenService.getTwoFactorToken().resolves(null);
|
||||||
|
|
||||||
|
authService.makePreloginKey(Arg.any(), Arg.any()).resolves(preloginKey);
|
||||||
|
|
||||||
|
cryptoService.hashPassword(masterPassword, Arg.any()).resolves(hashedPassword);
|
||||||
|
cryptoService
|
||||||
|
.hashPassword(masterPassword, Arg.any(), HashPurpose.LocalAuthorization)
|
||||||
|
.resolves(localHashedPassword);
|
||||||
|
|
||||||
|
passwordLogInStrategy = new PasswordLogInStrategy(
|
||||||
|
cryptoService,
|
||||||
|
apiService,
|
||||||
|
tokenService,
|
||||||
|
appIdService,
|
||||||
|
platformUtilsService,
|
||||||
|
messagingService,
|
||||||
|
logService,
|
||||||
|
stateService,
|
||||||
|
twoFactorService,
|
||||||
|
authService,
|
||||||
|
);
|
||||||
|
credentials = new PasswordLogInCredentials(email, masterPassword);
|
||||||
|
|
||||||
|
apiService.postIdentityToken(Arg.any()).resolves(identityTokenResponseFactory());
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sends master password credentials to the server", async () => {
|
||||||
|
await passwordLogInStrategy.logIn(credentials);
|
||||||
|
|
||||||
|
apiService.received(1).postIdentityToken(
|
||||||
|
Arg.is((actual) => {
|
||||||
|
const passwordTokenRequest = actual as any; // Need to access private fields
|
||||||
|
return (
|
||||||
|
passwordTokenRequest.email === email &&
|
||||||
|
passwordTokenRequest.masterPasswordHash === hashedPassword &&
|
||||||
|
passwordTokenRequest.device.identifier === deviceId &&
|
||||||
|
passwordTokenRequest.twoFactor.provider == null &&
|
||||||
|
passwordTokenRequest.twoFactor.token == null &&
|
||||||
|
passwordTokenRequest.captchaResponse == null
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sets the local environment after a successful login", async () => {
|
||||||
|
await passwordLogInStrategy.logIn(credentials);
|
||||||
|
|
||||||
|
cryptoService.received(1).setKey(preloginKey);
|
||||||
|
cryptoService.received(1).setKeyHash(localHashedPassword);
|
||||||
|
});
|
||||||
|
});
|
||||||
127
jslib/common/spec/misc/logInStrategies/ssoLogIn.strategy.spec.ts
Normal file
127
jslib/common/spec/misc/logInStrategies/ssoLogIn.strategy.spec.ts
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
import { Arg, Substitute, SubstituteOf } from "@fluffy-spoon/substitute";
|
||||||
|
|
||||||
|
import { ApiService } from "@/jslib/common/src/abstractions/api.service";
|
||||||
|
import { AppIdService } from "@/jslib/common/src/abstractions/appId.service";
|
||||||
|
import { CryptoService } from "@/jslib/common/src/abstractions/crypto.service";
|
||||||
|
import { KeyConnectorService } from "@/jslib/common/src/abstractions/keyConnector.service";
|
||||||
|
import { LogService } from "@/jslib/common/src/abstractions/log.service";
|
||||||
|
import { MessagingService } from "@/jslib/common/src/abstractions/messaging.service";
|
||||||
|
import { PlatformUtilsService } from "@/jslib/common/src/abstractions/platformUtils.service";
|
||||||
|
import { StateService } from "@/jslib/common/src/abstractions/state.service";
|
||||||
|
import { TokenService } from "@/jslib/common/src/abstractions/token.service";
|
||||||
|
import { TwoFactorService } from "@/jslib/common/src/abstractions/twoFactor.service";
|
||||||
|
import { SsoLogInStrategy } from "@/jslib/common/src/misc/logInStrategies/ssoLogin.strategy";
|
||||||
|
import { Utils } from "@/jslib/common/src/misc/utils";
|
||||||
|
import { SsoLogInCredentials } from "@/jslib/common/src/models/domain/logInCredentials";
|
||||||
|
|
||||||
|
import { identityTokenResponseFactory } from "./logIn.strategy.spec";
|
||||||
|
|
||||||
|
describe("SsoLogInStrategy", () => {
|
||||||
|
let cryptoService: SubstituteOf<CryptoService>;
|
||||||
|
let apiService: SubstituteOf<ApiService>;
|
||||||
|
let tokenService: SubstituteOf<TokenService>;
|
||||||
|
let appIdService: SubstituteOf<AppIdService>;
|
||||||
|
let platformUtilsService: SubstituteOf<PlatformUtilsService>;
|
||||||
|
let messagingService: SubstituteOf<MessagingService>;
|
||||||
|
let logService: SubstituteOf<LogService>;
|
||||||
|
let keyConnectorService: SubstituteOf<KeyConnectorService>;
|
||||||
|
let stateService: SubstituteOf<StateService>;
|
||||||
|
let twoFactorService: SubstituteOf<TwoFactorService>;
|
||||||
|
|
||||||
|
let ssoLogInStrategy: SsoLogInStrategy;
|
||||||
|
let credentials: SsoLogInCredentials;
|
||||||
|
|
||||||
|
const deviceId = Utils.newGuid();
|
||||||
|
const encKey = "ENC_KEY";
|
||||||
|
const privateKey = "PRIVATE_KEY";
|
||||||
|
const keyConnectorUrl = "KEY_CONNECTOR_URL";
|
||||||
|
|
||||||
|
const ssoCode = "SSO_CODE";
|
||||||
|
const ssoCodeVerifier = "SSO_CODE_VERIFIER";
|
||||||
|
const ssoRedirectUrl = "SSO_REDIRECT_URL";
|
||||||
|
const ssoOrgId = "SSO_ORG_ID";
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
cryptoService = Substitute.for<CryptoService>();
|
||||||
|
apiService = Substitute.for<ApiService>();
|
||||||
|
tokenService = Substitute.for<TokenService>();
|
||||||
|
appIdService = Substitute.for<AppIdService>();
|
||||||
|
platformUtilsService = Substitute.for<PlatformUtilsService>();
|
||||||
|
messagingService = Substitute.for<MessagingService>();
|
||||||
|
logService = Substitute.for<LogService>();
|
||||||
|
stateService = Substitute.for<StateService>();
|
||||||
|
keyConnectorService = Substitute.for<KeyConnectorService>();
|
||||||
|
twoFactorService = Substitute.for<TwoFactorService>();
|
||||||
|
|
||||||
|
tokenService.getTwoFactorToken().resolves(null);
|
||||||
|
appIdService.getAppId().resolves(deviceId);
|
||||||
|
|
||||||
|
ssoLogInStrategy = new SsoLogInStrategy(
|
||||||
|
cryptoService,
|
||||||
|
apiService,
|
||||||
|
tokenService,
|
||||||
|
appIdService,
|
||||||
|
platformUtilsService,
|
||||||
|
messagingService,
|
||||||
|
logService,
|
||||||
|
stateService,
|
||||||
|
twoFactorService,
|
||||||
|
keyConnectorService,
|
||||||
|
);
|
||||||
|
credentials = new SsoLogInCredentials(ssoCode, ssoCodeVerifier, ssoRedirectUrl, ssoOrgId);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sends SSO information to server", async () => {
|
||||||
|
apiService.postIdentityToken(Arg.any()).resolves(identityTokenResponseFactory());
|
||||||
|
|
||||||
|
await ssoLogInStrategy.logIn(credentials);
|
||||||
|
|
||||||
|
apiService.received(1).postIdentityToken(
|
||||||
|
Arg.is((actual) => {
|
||||||
|
const ssoTokenRequest = actual as any;
|
||||||
|
return (
|
||||||
|
ssoTokenRequest.code === ssoCode &&
|
||||||
|
ssoTokenRequest.codeVerifier === ssoCodeVerifier &&
|
||||||
|
ssoTokenRequest.redirectUri === ssoRedirectUrl &&
|
||||||
|
ssoTokenRequest.device.identifier === deviceId &&
|
||||||
|
ssoTokenRequest.twoFactor.provider == null &&
|
||||||
|
ssoTokenRequest.twoFactor.token == null
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not set keys for new SSO user flow", async () => {
|
||||||
|
const tokenResponse = identityTokenResponseFactory();
|
||||||
|
tokenResponse.key = null;
|
||||||
|
apiService.postIdentityToken(Arg.any()).resolves(tokenResponse);
|
||||||
|
|
||||||
|
await ssoLogInStrategy.logIn(credentials);
|
||||||
|
|
||||||
|
cryptoService.didNotReceive().setEncPrivateKey(privateKey);
|
||||||
|
cryptoService.didNotReceive().setEncKey(encKey);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("gets and sets KeyConnector key for enrolled user", async () => {
|
||||||
|
const tokenResponse = identityTokenResponseFactory();
|
||||||
|
tokenResponse.keyConnectorUrl = keyConnectorUrl;
|
||||||
|
|
||||||
|
apiService.postIdentityToken(Arg.any()).resolves(tokenResponse);
|
||||||
|
|
||||||
|
await ssoLogInStrategy.logIn(credentials);
|
||||||
|
|
||||||
|
keyConnectorService.received(1).getAndSetKey(keyConnectorUrl);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("converts new SSO user to Key Connector on first login", async () => {
|
||||||
|
const tokenResponse = identityTokenResponseFactory();
|
||||||
|
tokenResponse.keyConnectorUrl = keyConnectorUrl;
|
||||||
|
tokenResponse.key = null;
|
||||||
|
|
||||||
|
apiService.postIdentityToken(Arg.any()).resolves(tokenResponse);
|
||||||
|
|
||||||
|
await ssoLogInStrategy.logIn(credentials);
|
||||||
|
|
||||||
|
keyConnectorService.received(1).convertNewSsoUserToKeyConnector(tokenResponse, ssoOrgId);
|
||||||
|
});
|
||||||
|
});
|
||||||
69
jslib/common/spec/services/cipher.service.spec.ts
Normal file
69
jslib/common/spec/services/cipher.service.spec.ts
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import { Arg, Substitute, SubstituteOf } from "@fluffy-spoon/substitute";
|
||||||
|
|
||||||
|
import { ApiService } from "@/jslib/common/src/abstractions/api.service";
|
||||||
|
import { CryptoService } from "@/jslib/common/src/abstractions/crypto.service";
|
||||||
|
import { FileUploadService } from "@/jslib/common/src/abstractions/fileUpload.service";
|
||||||
|
import { I18nService } from "@/jslib/common/src/abstractions/i18n.service";
|
||||||
|
import { LogService } from "@/jslib/common/src/abstractions/log.service";
|
||||||
|
import { SearchService } from "@/jslib/common/src/abstractions/search.service";
|
||||||
|
import { SettingsService } from "@/jslib/common/src/abstractions/settings.service";
|
||||||
|
import { StateService } from "@/jslib/common/src/abstractions/state.service";
|
||||||
|
import { Utils } from "@/jslib/common/src/misc/utils";
|
||||||
|
import { Cipher } from "@/jslib/common/src/models/domain/cipher";
|
||||||
|
import { EncArrayBuffer } from "@/jslib/common/src/models/domain/encArrayBuffer";
|
||||||
|
import { EncString } from "@/jslib/common/src/models/domain/encString";
|
||||||
|
import { SymmetricCryptoKey } from "@/jslib/common/src/models/domain/symmetricCryptoKey";
|
||||||
|
import { CipherService } from "@/jslib/common/src/services/cipher.service";
|
||||||
|
|
||||||
|
const ENCRYPTED_TEXT = "This data has been encrypted";
|
||||||
|
const ENCRYPTED_BYTES = new EncArrayBuffer(Utils.fromUtf8ToArray(ENCRYPTED_TEXT).buffer);
|
||||||
|
|
||||||
|
describe("Cipher Service", () => {
|
||||||
|
let cryptoService: SubstituteOf<CryptoService>;
|
||||||
|
let stateService: SubstituteOf<StateService>;
|
||||||
|
let settingsService: SubstituteOf<SettingsService>;
|
||||||
|
let apiService: SubstituteOf<ApiService>;
|
||||||
|
let fileUploadService: SubstituteOf<FileUploadService>;
|
||||||
|
let i18nService: SubstituteOf<I18nService>;
|
||||||
|
let searchService: SubstituteOf<SearchService>;
|
||||||
|
let logService: SubstituteOf<LogService>;
|
||||||
|
|
||||||
|
let cipherService: CipherService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
cryptoService = Substitute.for<CryptoService>();
|
||||||
|
stateService = Substitute.for<StateService>();
|
||||||
|
settingsService = Substitute.for<SettingsService>();
|
||||||
|
apiService = Substitute.for<ApiService>();
|
||||||
|
fileUploadService = Substitute.for<FileUploadService>();
|
||||||
|
i18nService = Substitute.for<I18nService>();
|
||||||
|
searchService = Substitute.for<SearchService>();
|
||||||
|
logService = Substitute.for<LogService>();
|
||||||
|
|
||||||
|
cryptoService.encryptToBytes(Arg.any(), Arg.any()).resolves(ENCRYPTED_BYTES);
|
||||||
|
cryptoService.encrypt(Arg.any(), Arg.any()).resolves(new EncString(ENCRYPTED_TEXT));
|
||||||
|
|
||||||
|
cipherService = new CipherService(
|
||||||
|
cryptoService,
|
||||||
|
settingsService,
|
||||||
|
apiService,
|
||||||
|
fileUploadService,
|
||||||
|
i18nService,
|
||||||
|
() => searchService,
|
||||||
|
logService,
|
||||||
|
stateService,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("attachments upload encrypted file contents", async () => {
|
||||||
|
const fileName = "filename";
|
||||||
|
const fileData = new Uint8Array(10).buffer;
|
||||||
|
cryptoService.getOrgKey(Arg.any()).resolves(new SymmetricCryptoKey(new Uint8Array(32).buffer));
|
||||||
|
|
||||||
|
await cipherService.saveAttachmentRawWithServer(new Cipher(), fileName, fileData);
|
||||||
|
|
||||||
|
fileUploadService
|
||||||
|
.received(1)
|
||||||
|
.uploadCipherAttachment(Arg.any(), Arg.any(), new EncString(ENCRYPTED_TEXT), ENCRYPTED_BYTES);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,14 +1,679 @@
|
|||||||
|
import { PolicyType } from "../enums/policyType";
|
||||||
|
import { SetKeyConnectorKeyRequest } from "../models/request/account/setKeyConnectorKeyRequest";
|
||||||
|
import { VerifyOTPRequest } from "../models/request/account/verifyOTPRequest";
|
||||||
|
import { AttachmentRequest } from "../models/request/attachmentRequest";
|
||||||
|
import { BitPayInvoiceRequest } from "../models/request/bitPayInvoiceRequest";
|
||||||
|
import { CipherBulkDeleteRequest } from "../models/request/cipherBulkDeleteRequest";
|
||||||
|
import { CipherBulkMoveRequest } from "../models/request/cipherBulkMoveRequest";
|
||||||
|
import { CipherBulkRestoreRequest } from "../models/request/cipherBulkRestoreRequest";
|
||||||
|
import { CipherBulkShareRequest } from "../models/request/cipherBulkShareRequest";
|
||||||
|
import { CipherCollectionsRequest } from "../models/request/cipherCollectionsRequest";
|
||||||
|
import { CipherCreateRequest } from "../models/request/cipherCreateRequest";
|
||||||
|
import { CipherRequest } from "../models/request/cipherRequest";
|
||||||
|
import { CipherShareRequest } from "../models/request/cipherShareRequest";
|
||||||
|
import { CollectionRequest } from "../models/request/collectionRequest";
|
||||||
|
import { DeleteRecoverRequest } from "../models/request/deleteRecoverRequest";
|
||||||
|
import { EmailRequest } from "../models/request/emailRequest";
|
||||||
|
import { EmailTokenRequest } from "../models/request/emailTokenRequest";
|
||||||
|
import { EmergencyAccessAcceptRequest } from "../models/request/emergencyAccessAcceptRequest";
|
||||||
|
import { EmergencyAccessConfirmRequest } from "../models/request/emergencyAccessConfirmRequest";
|
||||||
|
import { EmergencyAccessInviteRequest } from "../models/request/emergencyAccessInviteRequest";
|
||||||
|
import { EmergencyAccessPasswordRequest } from "../models/request/emergencyAccessPasswordRequest";
|
||||||
|
import { EmergencyAccessUpdateRequest } from "../models/request/emergencyAccessUpdateRequest";
|
||||||
|
import { EventRequest } from "../models/request/eventRequest";
|
||||||
|
import { FolderRequest } from "../models/request/folderRequest";
|
||||||
|
import { GroupRequest } from "../models/request/groupRequest";
|
||||||
|
import { IapCheckRequest } from "../models/request/iapCheckRequest";
|
||||||
import { ApiTokenRequest } from "../models/request/identityToken/apiTokenRequest";
|
import { ApiTokenRequest } from "../models/request/identityToken/apiTokenRequest";
|
||||||
import { PasswordTokenRequest } from "../models/request/identityToken/passwordTokenRequest";
|
import { PasswordTokenRequest } from "../models/request/identityToken/passwordTokenRequest";
|
||||||
import { SsoTokenRequest } from "../models/request/identityToken/ssoTokenRequest";
|
import { SsoTokenRequest } from "../models/request/identityToken/ssoTokenRequest";
|
||||||
|
import { ImportCiphersRequest } from "../models/request/importCiphersRequest";
|
||||||
|
import { ImportDirectoryRequest } from "../models/request/importDirectoryRequest";
|
||||||
|
import { ImportOrganizationCiphersRequest } from "../models/request/importOrganizationCiphersRequest";
|
||||||
|
import { KdfRequest } from "../models/request/kdfRequest";
|
||||||
|
import { KeyConnectorUserKeyRequest } from "../models/request/keyConnectorUserKeyRequest";
|
||||||
|
import { KeysRequest } from "../models/request/keysRequest";
|
||||||
|
import { OrganizationSponsorshipCreateRequest } from "../models/request/organization/organizationSponsorshipCreateRequest";
|
||||||
|
import { OrganizationSponsorshipRedeemRequest } from "../models/request/organization/organizationSponsorshipRedeemRequest";
|
||||||
|
import { OrganizationSsoRequest } from "../models/request/organization/organizationSsoRequest";
|
||||||
|
import { OrganizationCreateRequest } from "../models/request/organizationCreateRequest";
|
||||||
import { OrganizationImportRequest } from "../models/request/organizationImportRequest";
|
import { OrganizationImportRequest } from "../models/request/organizationImportRequest";
|
||||||
import { IdentityCaptchaResponse } from '../models/response/identityCaptchaResponse';
|
import { OrganizationKeysRequest } from "../models/request/organizationKeysRequest";
|
||||||
import { IdentityTokenResponse } from '../models/response/identityTokenResponse';
|
import { OrganizationSubscriptionUpdateRequest } from "../models/request/organizationSubscriptionUpdateRequest";
|
||||||
import { IdentityTwoFactorResponse } from '../models/response/identityTwoFactorResponse';
|
import { OrganizationTaxInfoUpdateRequest } from "../models/request/organizationTaxInfoUpdateRequest";
|
||||||
|
import { OrganizationUpdateRequest } from "../models/request/organizationUpdateRequest";
|
||||||
|
import { OrganizationUpgradeRequest } from "../models/request/organizationUpgradeRequest";
|
||||||
|
import { OrganizationUserAcceptRequest } from "../models/request/organizationUserAcceptRequest";
|
||||||
|
import { OrganizationUserBulkConfirmRequest } from "../models/request/organizationUserBulkConfirmRequest";
|
||||||
|
import { OrganizationUserBulkRequest } from "../models/request/organizationUserBulkRequest";
|
||||||
|
import { OrganizationUserConfirmRequest } from "../models/request/organizationUserConfirmRequest";
|
||||||
|
import { OrganizationUserInviteRequest } from "../models/request/organizationUserInviteRequest";
|
||||||
|
import { OrganizationUserResetPasswordEnrollmentRequest } from "../models/request/organizationUserResetPasswordEnrollmentRequest";
|
||||||
|
import { OrganizationUserResetPasswordRequest } from "../models/request/organizationUserResetPasswordRequest";
|
||||||
|
import { OrganizationUserUpdateGroupsRequest } from "../models/request/organizationUserUpdateGroupsRequest";
|
||||||
|
import { OrganizationUserUpdateRequest } from "../models/request/organizationUserUpdateRequest";
|
||||||
|
import { PasswordHintRequest } from "../models/request/passwordHintRequest";
|
||||||
|
import { PasswordRequest } from "../models/request/passwordRequest";
|
||||||
|
import { PaymentRequest } from "../models/request/paymentRequest";
|
||||||
|
import { PolicyRequest } from "../models/request/policyRequest";
|
||||||
|
import { PreloginRequest } from "../models/request/preloginRequest";
|
||||||
|
import { ProviderAddOrganizationRequest } from "../models/request/provider/providerAddOrganizationRequest";
|
||||||
|
import { ProviderOrganizationCreateRequest } from "../models/request/provider/providerOrganizationCreateRequest";
|
||||||
|
import { ProviderSetupRequest } from "../models/request/provider/providerSetupRequest";
|
||||||
|
import { ProviderUpdateRequest } from "../models/request/provider/providerUpdateRequest";
|
||||||
|
import { ProviderUserAcceptRequest } from "../models/request/provider/providerUserAcceptRequest";
|
||||||
|
import { ProviderUserBulkConfirmRequest } from "../models/request/provider/providerUserBulkConfirmRequest";
|
||||||
|
import { ProviderUserBulkRequest } from "../models/request/provider/providerUserBulkRequest";
|
||||||
|
import { ProviderUserConfirmRequest } from "../models/request/provider/providerUserConfirmRequest";
|
||||||
|
import { ProviderUserInviteRequest } from "../models/request/provider/providerUserInviteRequest";
|
||||||
|
import { ProviderUserUpdateRequest } from "../models/request/provider/providerUserUpdateRequest";
|
||||||
|
import { RegisterRequest } from "../models/request/registerRequest";
|
||||||
|
import { SeatRequest } from "../models/request/seatRequest";
|
||||||
|
import { SecretVerificationRequest } from "../models/request/secretVerificationRequest";
|
||||||
|
import { SelectionReadOnlyRequest } from "../models/request/selectionReadOnlyRequest";
|
||||||
|
import { SendAccessRequest } from "../models/request/sendAccessRequest";
|
||||||
|
import { SendRequest } from "../models/request/sendRequest";
|
||||||
|
import { SetPasswordRequest } from "../models/request/setPasswordRequest";
|
||||||
|
import { StorageRequest } from "../models/request/storageRequest";
|
||||||
|
import { TaxInfoUpdateRequest } from "../models/request/taxInfoUpdateRequest";
|
||||||
|
import { TwoFactorEmailRequest } from "../models/request/twoFactorEmailRequest";
|
||||||
|
import { TwoFactorProviderRequest } from "../models/request/twoFactorProviderRequest";
|
||||||
|
import { TwoFactorRecoveryRequest } from "../models/request/twoFactorRecoveryRequest";
|
||||||
|
import { UpdateDomainsRequest } from "../models/request/updateDomainsRequest";
|
||||||
|
import { UpdateKeyRequest } from "../models/request/updateKeyRequest";
|
||||||
|
import { UpdateProfileRequest } from "../models/request/updateProfileRequest";
|
||||||
|
import { UpdateTempPasswordRequest } from "../models/request/updateTempPasswordRequest";
|
||||||
|
import { UpdateTwoFactorAuthenticatorRequest } from "../models/request/updateTwoFactorAuthenticatorRequest";
|
||||||
|
import { UpdateTwoFactorDuoRequest } from "../models/request/updateTwoFactorDuoRequest";
|
||||||
|
import { UpdateTwoFactorEmailRequest } from "../models/request/updateTwoFactorEmailRequest";
|
||||||
|
import { UpdateTwoFactorWebAuthnDeleteRequest } from "../models/request/updateTwoFactorWebAuthnDeleteRequest";
|
||||||
|
import { UpdateTwoFactorWebAuthnRequest } from "../models/request/updateTwoFactorWebAuthnRequest";
|
||||||
|
import { UpdateTwoFactorYubioOtpRequest } from "../models/request/updateTwoFactorYubioOtpRequest";
|
||||||
|
import { VerifyBankRequest } from "../models/request/verifyBankRequest";
|
||||||
|
import { VerifyDeleteRecoverRequest } from "../models/request/verifyDeleteRecoverRequest";
|
||||||
|
import { VerifyEmailRequest } from "../models/request/verifyEmailRequest";
|
||||||
|
import { ApiKeyResponse } from "../models/response/apiKeyResponse";
|
||||||
|
import { AttachmentResponse } from "../models/response/attachmentResponse";
|
||||||
|
import { AttachmentUploadDataResponse } from "../models/response/attachmentUploadDataResponse";
|
||||||
|
import { BillingResponse } from "../models/response/billingResponse";
|
||||||
|
import { BreachAccountResponse } from "../models/response/breachAccountResponse";
|
||||||
|
import { CipherResponse } from "../models/response/cipherResponse";
|
||||||
|
import {
|
||||||
|
CollectionGroupDetailsResponse,
|
||||||
|
CollectionResponse,
|
||||||
|
} from "../models/response/collectionResponse";
|
||||||
|
import { DomainsResponse } from "../models/response/domainsResponse";
|
||||||
|
import {
|
||||||
|
EmergencyAccessGranteeDetailsResponse,
|
||||||
|
EmergencyAccessGrantorDetailsResponse,
|
||||||
|
EmergencyAccessTakeoverResponse,
|
||||||
|
EmergencyAccessViewResponse,
|
||||||
|
} from "../models/response/emergencyAccessResponse";
|
||||||
|
import { EventResponse } from "../models/response/eventResponse";
|
||||||
|
import { FolderResponse } from "../models/response/folderResponse";
|
||||||
|
import { GroupDetailsResponse, GroupResponse } from "../models/response/groupResponse";
|
||||||
|
import { IdentityCaptchaResponse } from "../models/response/identityCaptchaResponse";
|
||||||
|
import { IdentityTokenResponse } from "../models/response/identityTokenResponse";
|
||||||
|
import { IdentityTwoFactorResponse } from "../models/response/identityTwoFactorResponse";
|
||||||
|
import { KeyConnectorUserKeyResponse } from "../models/response/keyConnectorUserKeyResponse";
|
||||||
|
import { ListResponse } from "../models/response/listResponse";
|
||||||
|
import { OrganizationSsoResponse } from "../models/response/organization/organizationSsoResponse";
|
||||||
|
import { OrganizationAutoEnrollStatusResponse } from "../models/response/organizationAutoEnrollStatusResponse";
|
||||||
|
import { OrganizationKeysResponse } from "../models/response/organizationKeysResponse";
|
||||||
|
import { OrganizationResponse } from "../models/response/organizationResponse";
|
||||||
|
import { OrganizationSubscriptionResponse } from "../models/response/organizationSubscriptionResponse";
|
||||||
|
import { OrganizationUserBulkPublicKeyResponse } from "../models/response/organizationUserBulkPublicKeyResponse";
|
||||||
|
import { OrganizationUserBulkResponse } from "../models/response/organizationUserBulkResponse";
|
||||||
|
import {
|
||||||
|
OrganizationUserDetailsResponse,
|
||||||
|
OrganizationUserResetPasswordDetailsReponse,
|
||||||
|
OrganizationUserUserDetailsResponse,
|
||||||
|
} from "../models/response/organizationUserResponse";
|
||||||
|
import { PaymentResponse } from "../models/response/paymentResponse";
|
||||||
|
import { PlanResponse } from "../models/response/planResponse";
|
||||||
|
import { PolicyResponse } from "../models/response/policyResponse";
|
||||||
|
import { PreloginResponse } from "../models/response/preloginResponse";
|
||||||
|
import { ProfileResponse } from "../models/response/profileResponse";
|
||||||
|
import {
|
||||||
|
ProviderOrganizationOrganizationDetailsResponse,
|
||||||
|
ProviderOrganizationResponse,
|
||||||
|
} from "../models/response/provider/providerOrganizationResponse";
|
||||||
|
import { ProviderResponse } from "../models/response/provider/providerResponse";
|
||||||
|
import { ProviderUserBulkPublicKeyResponse } from "../models/response/provider/providerUserBulkPublicKeyResponse";
|
||||||
|
import { ProviderUserBulkResponse } from "../models/response/provider/providerUserBulkResponse";
|
||||||
|
import {
|
||||||
|
ProviderUserResponse,
|
||||||
|
ProviderUserUserDetailsResponse,
|
||||||
|
} from "../models/response/provider/providerUserResponse";
|
||||||
|
import { SelectionReadOnlyResponse } from "../models/response/selectionReadOnlyResponse";
|
||||||
|
import { SendAccessResponse } from "../models/response/sendAccessResponse";
|
||||||
|
import { SendFileDownloadDataResponse } from "../models/response/sendFileDownloadDataResponse";
|
||||||
|
import { SendFileUploadDataResponse } from "../models/response/sendFileUploadDataResponse";
|
||||||
|
import { SendResponse } from "../models/response/sendResponse";
|
||||||
|
import { SubscriptionResponse } from "../models/response/subscriptionResponse";
|
||||||
|
import { SyncResponse } from "../models/response/syncResponse";
|
||||||
|
import { TaxInfoResponse } from "../models/response/taxInfoResponse";
|
||||||
|
import { TaxRateResponse } from "../models/response/taxRateResponse";
|
||||||
|
import { TwoFactorAuthenticatorResponse } from "../models/response/twoFactorAuthenticatorResponse";
|
||||||
|
import { TwoFactorDuoResponse } from "../models/response/twoFactorDuoResponse";
|
||||||
|
import { TwoFactorEmailResponse } from "../models/response/twoFactorEmailResponse";
|
||||||
|
import { TwoFactorProviderResponse } from "../models/response/twoFactorProviderResponse";
|
||||||
|
import { TwoFactorRecoverResponse } from "../models/response/twoFactorRescoverResponse";
|
||||||
|
import {
|
||||||
|
ChallengeResponse,
|
||||||
|
TwoFactorWebAuthnResponse,
|
||||||
|
} from "../models/response/twoFactorWebAuthnResponse";
|
||||||
|
import { TwoFactorYubiKeyResponse } from "../models/response/twoFactorYubiKeyResponse";
|
||||||
|
import { UserKeyResponse } from "../models/response/userKeyResponse";
|
||||||
|
import { SendAccessView } from "../models/view/sendAccessView";
|
||||||
|
|
||||||
export abstract class ApiService {
|
export abstract class ApiService {
|
||||||
postIdentityToken: (
|
postIdentityToken: (
|
||||||
request: PasswordTokenRequest | SsoTokenRequest | ApiTokenRequest,
|
request: PasswordTokenRequest | SsoTokenRequest | ApiTokenRequest,
|
||||||
) => Promise<IdentityTokenResponse | IdentityTwoFactorResponse | IdentityCaptchaResponse>;
|
) => Promise<IdentityTokenResponse | IdentityTwoFactorResponse | IdentityCaptchaResponse>;
|
||||||
|
refreshIdentityToken: () => Promise<any>;
|
||||||
|
|
||||||
|
getProfile: () => Promise<ProfileResponse>;
|
||||||
|
getUserBilling: () => Promise<BillingResponse>;
|
||||||
|
getUserSubscription: () => Promise<SubscriptionResponse>;
|
||||||
|
getTaxInfo: () => Promise<TaxInfoResponse>;
|
||||||
|
putProfile: (request: UpdateProfileRequest) => Promise<ProfileResponse>;
|
||||||
|
putTaxInfo: (request: TaxInfoUpdateRequest) => Promise<any>;
|
||||||
|
postPrelogin: (request: PreloginRequest) => Promise<PreloginResponse>;
|
||||||
|
postEmailToken: (request: EmailTokenRequest) => Promise<any>;
|
||||||
|
postEmail: (request: EmailRequest) => Promise<any>;
|
||||||
|
postPassword: (request: PasswordRequest) => Promise<any>;
|
||||||
|
setPassword: (request: SetPasswordRequest) => Promise<any>;
|
||||||
|
postSetKeyConnectorKey: (request: SetKeyConnectorKeyRequest) => Promise<any>;
|
||||||
|
postSecurityStamp: (request: SecretVerificationRequest) => Promise<any>;
|
||||||
|
deleteAccount: (request: SecretVerificationRequest) => Promise<any>;
|
||||||
|
getAccountRevisionDate: () => Promise<number>;
|
||||||
|
postPasswordHint: (request: PasswordHintRequest) => Promise<any>;
|
||||||
|
postRegister: (request: RegisterRequest) => Promise<any>;
|
||||||
|
postPremium: (data: FormData) => Promise<PaymentResponse>;
|
||||||
|
postIapCheck: (request: IapCheckRequest) => Promise<any>;
|
||||||
|
postReinstatePremium: () => Promise<any>;
|
||||||
|
postCancelPremium: () => Promise<any>;
|
||||||
|
postAccountStorage: (request: StorageRequest) => Promise<PaymentResponse>;
|
||||||
|
postAccountPayment: (request: PaymentRequest) => Promise<any>;
|
||||||
|
postAccountLicense: (data: FormData) => Promise<any>;
|
||||||
|
postAccountKey: (request: UpdateKeyRequest) => Promise<any>;
|
||||||
|
postAccountKeys: (request: KeysRequest) => Promise<any>;
|
||||||
|
postAccountVerifyEmail: () => Promise<any>;
|
||||||
|
postAccountVerifyEmailToken: (request: VerifyEmailRequest) => Promise<any>;
|
||||||
|
postAccountVerifyPassword: (request: SecretVerificationRequest) => Promise<any>;
|
||||||
|
postAccountRecoverDelete: (request: DeleteRecoverRequest) => Promise<any>;
|
||||||
|
postAccountRecoverDeleteToken: (request: VerifyDeleteRecoverRequest) => Promise<any>;
|
||||||
|
postAccountKdf: (request: KdfRequest) => Promise<any>;
|
||||||
|
postUserApiKey: (id: string, request: SecretVerificationRequest) => Promise<ApiKeyResponse>;
|
||||||
|
postUserRotateApiKey: (id: string, request: SecretVerificationRequest) => Promise<ApiKeyResponse>;
|
||||||
|
putUpdateTempPassword: (request: UpdateTempPasswordRequest) => Promise<any>;
|
||||||
|
postAccountRequestOTP: () => Promise<void>;
|
||||||
|
postAccountVerifyOTP: (request: VerifyOTPRequest) => Promise<void>;
|
||||||
|
postConvertToKeyConnector: () => Promise<void>;
|
||||||
|
|
||||||
|
getFolder: (id: string) => Promise<FolderResponse>;
|
||||||
|
postFolder: (request: FolderRequest) => Promise<FolderResponse>;
|
||||||
|
putFolder: (id: string, request: FolderRequest) => Promise<FolderResponse>;
|
||||||
|
deleteFolder: (id: string) => Promise<any>;
|
||||||
|
|
||||||
|
getSend: (id: string) => Promise<SendResponse>;
|
||||||
|
postSendAccess: (
|
||||||
|
id: string,
|
||||||
|
request: SendAccessRequest,
|
||||||
|
apiUrl?: string,
|
||||||
|
) => Promise<SendAccessResponse>;
|
||||||
|
getSends: () => Promise<ListResponse<SendResponse>>;
|
||||||
|
postSend: (request: SendRequest) => Promise<SendResponse>;
|
||||||
|
postFileTypeSend: (request: SendRequest) => Promise<SendFileUploadDataResponse>;
|
||||||
|
postSendFile: (sendId: string, fileId: string, data: FormData) => Promise<any>;
|
||||||
|
/**
|
||||||
|
* @deprecated Mar 25 2021: This method has been deprecated in favor of direct uploads.
|
||||||
|
* This method still exists for backward compatibility with old server versions.
|
||||||
|
*/
|
||||||
|
postSendFileLegacy: (data: FormData) => Promise<SendResponse>;
|
||||||
|
putSend: (id: string, request: SendRequest) => Promise<SendResponse>;
|
||||||
|
putSendRemovePassword: (id: string) => Promise<SendResponse>;
|
||||||
|
deleteSend: (id: string) => Promise<any>;
|
||||||
|
getSendFileDownloadData: (
|
||||||
|
send: SendAccessView,
|
||||||
|
request: SendAccessRequest,
|
||||||
|
apiUrl?: string,
|
||||||
|
) => Promise<SendFileDownloadDataResponse>;
|
||||||
|
renewSendFileUploadUrl: (sendId: string, fileId: string) => Promise<SendFileUploadDataResponse>;
|
||||||
|
|
||||||
|
getCipher: (id: string) => Promise<CipherResponse>;
|
||||||
|
getCipherAdmin: (id: string) => Promise<CipherResponse>;
|
||||||
|
getAttachmentData: (
|
||||||
|
cipherId: string,
|
||||||
|
attachmentId: string,
|
||||||
|
emergencyAccessId?: string,
|
||||||
|
) => Promise<AttachmentResponse>;
|
||||||
|
getCiphersOrganization: (organizationId: string) => Promise<ListResponse<CipherResponse>>;
|
||||||
|
postCipher: (request: CipherRequest) => Promise<CipherResponse>;
|
||||||
|
postCipherCreate: (request: CipherCreateRequest) => Promise<CipherResponse>;
|
||||||
|
postCipherAdmin: (request: CipherCreateRequest) => Promise<CipherResponse>;
|
||||||
|
putCipher: (id: string, request: CipherRequest) => Promise<CipherResponse>;
|
||||||
|
putCipherAdmin: (id: string, request: CipherRequest) => Promise<CipherResponse>;
|
||||||
|
deleteCipher: (id: string) => Promise<any>;
|
||||||
|
deleteCipherAdmin: (id: string) => Promise<any>;
|
||||||
|
deleteManyCiphers: (request: CipherBulkDeleteRequest) => Promise<any>;
|
||||||
|
deleteManyCiphersAdmin: (request: CipherBulkDeleteRequest) => Promise<any>;
|
||||||
|
putMoveCiphers: (request: CipherBulkMoveRequest) => Promise<any>;
|
||||||
|
putShareCipher: (id: string, request: CipherShareRequest) => Promise<CipherResponse>;
|
||||||
|
putShareCiphers: (request: CipherBulkShareRequest) => Promise<any>;
|
||||||
|
putCipherCollections: (id: string, request: CipherCollectionsRequest) => Promise<any>;
|
||||||
|
putCipherCollectionsAdmin: (id: string, request: CipherCollectionsRequest) => Promise<any>;
|
||||||
|
postPurgeCiphers: (request: SecretVerificationRequest, organizationId?: string) => Promise<any>;
|
||||||
|
postImportCiphers: (request: ImportCiphersRequest) => Promise<any>;
|
||||||
|
postImportOrganizationCiphers: (
|
||||||
|
organizationId: string,
|
||||||
|
request: ImportOrganizationCiphersRequest,
|
||||||
|
) => Promise<any>;
|
||||||
|
putDeleteCipher: (id: string) => Promise<any>;
|
||||||
|
putDeleteCipherAdmin: (id: string) => Promise<any>;
|
||||||
|
putDeleteManyCiphers: (request: CipherBulkDeleteRequest) => Promise<any>;
|
||||||
|
putDeleteManyCiphersAdmin: (request: CipherBulkDeleteRequest) => Promise<any>;
|
||||||
|
putRestoreCipher: (id: string) => Promise<CipherResponse>;
|
||||||
|
putRestoreCipherAdmin: (id: string) => Promise<CipherResponse>;
|
||||||
|
putRestoreManyCiphers: (
|
||||||
|
request: CipherBulkRestoreRequest,
|
||||||
|
) => Promise<ListResponse<CipherResponse>>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Mar 25 2021: This method has been deprecated in favor of direct uploads.
|
||||||
|
* This method still exists for backward compatibility with old server versions.
|
||||||
|
*/
|
||||||
|
postCipherAttachmentLegacy: (id: string, data: FormData) => Promise<CipherResponse>;
|
||||||
|
/**
|
||||||
|
* @deprecated Mar 25 2021: This method has been deprecated in favor of direct uploads.
|
||||||
|
* This method still exists for backward compatibility with old server versions.
|
||||||
|
*/
|
||||||
|
postCipherAttachmentAdminLegacy: (id: string, data: FormData) => Promise<CipherResponse>;
|
||||||
|
postCipherAttachment: (
|
||||||
|
id: string,
|
||||||
|
request: AttachmentRequest,
|
||||||
|
) => Promise<AttachmentUploadDataResponse>;
|
||||||
|
deleteCipherAttachment: (id: string, attachmentId: string) => Promise<any>;
|
||||||
|
deleteCipherAttachmentAdmin: (id: string, attachmentId: string) => Promise<any>;
|
||||||
|
postShareCipherAttachment: (
|
||||||
|
id: string,
|
||||||
|
attachmentId: string,
|
||||||
|
data: FormData,
|
||||||
|
organizationId: string,
|
||||||
|
) => Promise<any>;
|
||||||
|
renewAttachmentUploadUrl: (
|
||||||
|
id: string,
|
||||||
|
attachmentId: string,
|
||||||
|
) => Promise<AttachmentUploadDataResponse>;
|
||||||
|
postAttachmentFile: (id: string, attachmentId: string, data: FormData) => Promise<any>;
|
||||||
|
|
||||||
|
getCollectionDetails: (
|
||||||
|
organizationId: string,
|
||||||
|
id: string,
|
||||||
|
) => Promise<CollectionGroupDetailsResponse>;
|
||||||
|
getUserCollections: () => Promise<ListResponse<CollectionResponse>>;
|
||||||
|
getCollections: (organizationId: string) => Promise<ListResponse<CollectionResponse>>;
|
||||||
|
getCollectionUsers: (organizationId: string, id: string) => Promise<SelectionReadOnlyResponse[]>;
|
||||||
|
postCollection: (
|
||||||
|
organizationId: string,
|
||||||
|
request: CollectionRequest,
|
||||||
|
) => Promise<CollectionResponse>;
|
||||||
|
putCollectionUsers: (
|
||||||
|
organizationId: string,
|
||||||
|
id: string,
|
||||||
|
request: SelectionReadOnlyRequest[],
|
||||||
|
) => Promise<any>;
|
||||||
|
putCollection: (
|
||||||
|
organizationId: string,
|
||||||
|
id: string,
|
||||||
|
request: CollectionRequest,
|
||||||
|
) => Promise<CollectionResponse>;
|
||||||
|
deleteCollection: (organizationId: string, id: string) => Promise<any>;
|
||||||
|
deleteCollectionUser: (
|
||||||
|
organizationId: string,
|
||||||
|
id: string,
|
||||||
|
organizationUserId: string,
|
||||||
|
) => Promise<any>;
|
||||||
|
|
||||||
|
getGroupDetails: (organizationId: string, id: string) => Promise<GroupDetailsResponse>;
|
||||||
|
getGroups: (organizationId: string) => Promise<ListResponse<GroupResponse>>;
|
||||||
|
getGroupUsers: (organizationId: string, id: string) => Promise<string[]>;
|
||||||
|
postGroup: (organizationId: string, request: GroupRequest) => Promise<GroupResponse>;
|
||||||
|
putGroup: (organizationId: string, id: string, request: GroupRequest) => Promise<GroupResponse>;
|
||||||
|
putGroupUsers: (organizationId: string, id: string, request: string[]) => Promise<any>;
|
||||||
|
deleteGroup: (organizationId: string, id: string) => Promise<any>;
|
||||||
|
deleteGroupUser: (organizationId: string, id: string, organizationUserId: string) => Promise<any>;
|
||||||
|
|
||||||
|
getPolicy: (organizationId: string, type: PolicyType) => Promise<PolicyResponse>;
|
||||||
|
getPolicies: (organizationId: string) => Promise<ListResponse<PolicyResponse>>;
|
||||||
|
getPoliciesByToken: (
|
||||||
|
organizationId: string,
|
||||||
|
token: string,
|
||||||
|
email: string,
|
||||||
|
organizationUserId: string,
|
||||||
|
) => Promise<ListResponse<PolicyResponse>>;
|
||||||
|
getPoliciesByInvitedUser: (
|
||||||
|
organizationId: string,
|
||||||
|
userId: string,
|
||||||
|
) => Promise<ListResponse<PolicyResponse>>;
|
||||||
|
putPolicy: (
|
||||||
|
organizationId: string,
|
||||||
|
type: PolicyType,
|
||||||
|
request: PolicyRequest,
|
||||||
|
) => Promise<PolicyResponse>;
|
||||||
|
|
||||||
|
getOrganizationUser: (
|
||||||
|
organizationId: string,
|
||||||
|
id: string,
|
||||||
|
) => Promise<OrganizationUserDetailsResponse>;
|
||||||
|
getOrganizationUserGroups: (organizationId: string, id: string) => Promise<string[]>;
|
||||||
|
getOrganizationUsers: (
|
||||||
|
organizationId: string,
|
||||||
|
) => Promise<ListResponse<OrganizationUserUserDetailsResponse>>;
|
||||||
|
getOrganizationUserResetPasswordDetails: (
|
||||||
|
organizationId: string,
|
||||||
|
id: string,
|
||||||
|
) => Promise<OrganizationUserResetPasswordDetailsReponse>;
|
||||||
|
postOrganizationUserInvite: (
|
||||||
|
organizationId: string,
|
||||||
|
request: OrganizationUserInviteRequest,
|
||||||
|
) => Promise<any>;
|
||||||
|
postOrganizationUserReinvite: (organizationId: string, id: string) => Promise<any>;
|
||||||
|
postManyOrganizationUserReinvite: (
|
||||||
|
organizationId: string,
|
||||||
|
request: OrganizationUserBulkRequest,
|
||||||
|
) => Promise<ListResponse<OrganizationUserBulkResponse>>;
|
||||||
|
postOrganizationUserAccept: (
|
||||||
|
organizationId: string,
|
||||||
|
id: string,
|
||||||
|
request: OrganizationUserAcceptRequest,
|
||||||
|
) => Promise<any>;
|
||||||
|
postOrganizationUserConfirm: (
|
||||||
|
organizationId: string,
|
||||||
|
id: string,
|
||||||
|
request: OrganizationUserConfirmRequest,
|
||||||
|
) => Promise<any>;
|
||||||
|
postOrganizationUsersPublicKey: (
|
||||||
|
organizationId: string,
|
||||||
|
request: OrganizationUserBulkRequest,
|
||||||
|
) => Promise<ListResponse<OrganizationUserBulkPublicKeyResponse>>;
|
||||||
|
postOrganizationUserBulkConfirm: (
|
||||||
|
organizationId: string,
|
||||||
|
request: OrganizationUserBulkConfirmRequest,
|
||||||
|
) => Promise<ListResponse<OrganizationUserBulkResponse>>;
|
||||||
|
|
||||||
|
putOrganizationUser: (
|
||||||
|
organizationId: string,
|
||||||
|
id: string,
|
||||||
|
request: OrganizationUserUpdateRequest,
|
||||||
|
) => Promise<any>;
|
||||||
|
putOrganizationUserGroups: (
|
||||||
|
organizationId: string,
|
||||||
|
id: string,
|
||||||
|
request: OrganizationUserUpdateGroupsRequest,
|
||||||
|
) => Promise<any>;
|
||||||
|
putOrganizationUserResetPasswordEnrollment: (
|
||||||
|
organizationId: string,
|
||||||
|
userId: string,
|
||||||
|
request: OrganizationUserResetPasswordEnrollmentRequest,
|
||||||
|
) => Promise<any>;
|
||||||
|
putOrganizationUserResetPassword: (
|
||||||
|
organizationId: string,
|
||||||
|
id: string,
|
||||||
|
request: OrganizationUserResetPasswordRequest,
|
||||||
|
) => Promise<any>;
|
||||||
|
deleteOrganizationUser: (organizationId: string, id: string) => Promise<any>;
|
||||||
|
deleteManyOrganizationUsers: (
|
||||||
|
organizationId: string,
|
||||||
|
request: OrganizationUserBulkRequest,
|
||||||
|
) => Promise<ListResponse<OrganizationUserBulkResponse>>;
|
||||||
|
|
||||||
|
getSync: () => Promise<SyncResponse>;
|
||||||
|
postImportDirectory: (organizationId: string, request: ImportDirectoryRequest) => Promise<any>;
|
||||||
postPublicImportDirectory: (request: OrganizationImportRequest) => Promise<any>;
|
postPublicImportDirectory: (request: OrganizationImportRequest) => Promise<any>;
|
||||||
|
|
||||||
|
getSettingsDomains: () => Promise<DomainsResponse>;
|
||||||
|
putSettingsDomains: (request: UpdateDomainsRequest) => Promise<DomainsResponse>;
|
||||||
|
|
||||||
|
getTwoFactorProviders: () => Promise<ListResponse<TwoFactorProviderResponse>>;
|
||||||
|
getTwoFactorOrganizationProviders: (
|
||||||
|
organizationId: string,
|
||||||
|
) => Promise<ListResponse<TwoFactorProviderResponse>>;
|
||||||
|
getTwoFactorAuthenticator: (
|
||||||
|
request: SecretVerificationRequest,
|
||||||
|
) => Promise<TwoFactorAuthenticatorResponse>;
|
||||||
|
getTwoFactorEmail: (request: SecretVerificationRequest) => Promise<TwoFactorEmailResponse>;
|
||||||
|
getTwoFactorDuo: (request: SecretVerificationRequest) => Promise<TwoFactorDuoResponse>;
|
||||||
|
getTwoFactorOrganizationDuo: (
|
||||||
|
organizationId: string,
|
||||||
|
request: SecretVerificationRequest,
|
||||||
|
) => Promise<TwoFactorDuoResponse>;
|
||||||
|
getTwoFactorYubiKey: (request: SecretVerificationRequest) => Promise<TwoFactorYubiKeyResponse>;
|
||||||
|
getTwoFactorWebAuthn: (request: SecretVerificationRequest) => Promise<TwoFactorWebAuthnResponse>;
|
||||||
|
getTwoFactorWebAuthnChallenge: (request: SecretVerificationRequest) => Promise<ChallengeResponse>;
|
||||||
|
getTwoFactorRecover: (request: SecretVerificationRequest) => Promise<TwoFactorRecoverResponse>;
|
||||||
|
putTwoFactorAuthenticator: (
|
||||||
|
request: UpdateTwoFactorAuthenticatorRequest,
|
||||||
|
) => Promise<TwoFactorAuthenticatorResponse>;
|
||||||
|
putTwoFactorEmail: (request: UpdateTwoFactorEmailRequest) => Promise<TwoFactorEmailResponse>;
|
||||||
|
putTwoFactorDuo: (request: UpdateTwoFactorDuoRequest) => Promise<TwoFactorDuoResponse>;
|
||||||
|
putTwoFactorOrganizationDuo: (
|
||||||
|
organizationId: string,
|
||||||
|
request: UpdateTwoFactorDuoRequest,
|
||||||
|
) => Promise<TwoFactorDuoResponse>;
|
||||||
|
putTwoFactorYubiKey: (
|
||||||
|
request: UpdateTwoFactorYubioOtpRequest,
|
||||||
|
) => Promise<TwoFactorYubiKeyResponse>;
|
||||||
|
putTwoFactorWebAuthn: (
|
||||||
|
request: UpdateTwoFactorWebAuthnRequest,
|
||||||
|
) => Promise<TwoFactorWebAuthnResponse>;
|
||||||
|
deleteTwoFactorWebAuthn: (
|
||||||
|
request: UpdateTwoFactorWebAuthnDeleteRequest,
|
||||||
|
) => Promise<TwoFactorWebAuthnResponse>;
|
||||||
|
putTwoFactorDisable: (request: TwoFactorProviderRequest) => Promise<TwoFactorProviderResponse>;
|
||||||
|
putTwoFactorOrganizationDisable: (
|
||||||
|
organizationId: string,
|
||||||
|
request: TwoFactorProviderRequest,
|
||||||
|
) => Promise<TwoFactorProviderResponse>;
|
||||||
|
postTwoFactorRecover: (request: TwoFactorRecoveryRequest) => Promise<any>;
|
||||||
|
postTwoFactorEmailSetup: (request: TwoFactorEmailRequest) => Promise<any>;
|
||||||
|
postTwoFactorEmail: (request: TwoFactorEmailRequest) => Promise<any>;
|
||||||
|
|
||||||
|
getEmergencyAccessTrusted: () => Promise<ListResponse<EmergencyAccessGranteeDetailsResponse>>;
|
||||||
|
getEmergencyAccessGranted: () => Promise<ListResponse<EmergencyAccessGrantorDetailsResponse>>;
|
||||||
|
getEmergencyAccess: (id: string) => Promise<EmergencyAccessGranteeDetailsResponse>;
|
||||||
|
getEmergencyGrantorPolicies: (id: string) => Promise<ListResponse<PolicyResponse>>;
|
||||||
|
putEmergencyAccess: (id: string, request: EmergencyAccessUpdateRequest) => Promise<any>;
|
||||||
|
deleteEmergencyAccess: (id: string) => Promise<any>;
|
||||||
|
postEmergencyAccessInvite: (request: EmergencyAccessInviteRequest) => Promise<any>;
|
||||||
|
postEmergencyAccessReinvite: (id: string) => Promise<any>;
|
||||||
|
postEmergencyAccessAccept: (id: string, request: EmergencyAccessAcceptRequest) => Promise<any>;
|
||||||
|
postEmergencyAccessConfirm: (id: string, request: EmergencyAccessConfirmRequest) => Promise<any>;
|
||||||
|
postEmergencyAccessInitiate: (id: string) => Promise<any>;
|
||||||
|
postEmergencyAccessApprove: (id: string) => Promise<any>;
|
||||||
|
postEmergencyAccessReject: (id: string) => Promise<any>;
|
||||||
|
postEmergencyAccessTakeover: (id: string) => Promise<EmergencyAccessTakeoverResponse>;
|
||||||
|
postEmergencyAccessPassword: (
|
||||||
|
id: string,
|
||||||
|
request: EmergencyAccessPasswordRequest,
|
||||||
|
) => Promise<any>;
|
||||||
|
postEmergencyAccessView: (id: string) => Promise<EmergencyAccessViewResponse>;
|
||||||
|
|
||||||
|
getOrganization: (id: string) => Promise<OrganizationResponse>;
|
||||||
|
getOrganizationBilling: (id: string) => Promise<BillingResponse>;
|
||||||
|
getOrganizationSubscription: (id: string) => Promise<OrganizationSubscriptionResponse>;
|
||||||
|
getOrganizationLicense: (id: string, installationId: string) => Promise<any>;
|
||||||
|
getOrganizationTaxInfo: (id: string) => Promise<TaxInfoResponse>;
|
||||||
|
getOrganizationAutoEnrollStatus: (
|
||||||
|
identifier: string,
|
||||||
|
) => Promise<OrganizationAutoEnrollStatusResponse>;
|
||||||
|
getOrganizationSso: (id: string) => Promise<OrganizationSsoResponse>;
|
||||||
|
postOrganization: (request: OrganizationCreateRequest) => Promise<OrganizationResponse>;
|
||||||
|
putOrganization: (
|
||||||
|
id: string,
|
||||||
|
request: OrganizationUpdateRequest,
|
||||||
|
) => Promise<OrganizationResponse>;
|
||||||
|
putOrganizationTaxInfo: (id: string, request: OrganizationTaxInfoUpdateRequest) => Promise<any>;
|
||||||
|
postLeaveOrganization: (id: string) => Promise<any>;
|
||||||
|
postOrganizationLicense: (data: FormData) => Promise<OrganizationResponse>;
|
||||||
|
postOrganizationLicenseUpdate: (id: string, data: FormData) => Promise<any>;
|
||||||
|
postOrganizationApiKey: (
|
||||||
|
id: string,
|
||||||
|
request: SecretVerificationRequest,
|
||||||
|
) => Promise<ApiKeyResponse>;
|
||||||
|
postOrganizationRotateApiKey: (
|
||||||
|
id: string,
|
||||||
|
request: SecretVerificationRequest,
|
||||||
|
) => Promise<ApiKeyResponse>;
|
||||||
|
postOrganizationSso: (
|
||||||
|
id: string,
|
||||||
|
request: OrganizationSsoRequest,
|
||||||
|
) => Promise<OrganizationSsoResponse>;
|
||||||
|
postOrganizationUpgrade: (
|
||||||
|
id: string,
|
||||||
|
request: OrganizationUpgradeRequest,
|
||||||
|
) => Promise<PaymentResponse>;
|
||||||
|
postOrganizationUpdateSubscription: (
|
||||||
|
id: string,
|
||||||
|
request: OrganizationSubscriptionUpdateRequest,
|
||||||
|
) => Promise<void>;
|
||||||
|
postOrganizationSeat: (id: string, request: SeatRequest) => Promise<PaymentResponse>;
|
||||||
|
postOrganizationStorage: (id: string, request: StorageRequest) => Promise<any>;
|
||||||
|
postOrganizationPayment: (id: string, request: PaymentRequest) => Promise<any>;
|
||||||
|
postOrganizationVerifyBank: (id: string, request: VerifyBankRequest) => Promise<any>;
|
||||||
|
postOrganizationCancel: (id: string) => Promise<any>;
|
||||||
|
postOrganizationReinstate: (id: string) => Promise<any>;
|
||||||
|
deleteOrganization: (id: string, request: SecretVerificationRequest) => Promise<any>;
|
||||||
|
getPlans: () => Promise<ListResponse<PlanResponse>>;
|
||||||
|
getTaxRates: () => Promise<ListResponse<TaxRateResponse>>;
|
||||||
|
getOrganizationKeys: (id: string) => Promise<OrganizationKeysResponse>;
|
||||||
|
postOrganizationKeys: (
|
||||||
|
id: string,
|
||||||
|
request: OrganizationKeysRequest,
|
||||||
|
) => Promise<OrganizationKeysResponse>;
|
||||||
|
|
||||||
|
postProviderSetup: (id: string, request: ProviderSetupRequest) => Promise<ProviderResponse>;
|
||||||
|
getProvider: (id: string) => Promise<ProviderResponse>;
|
||||||
|
putProvider: (id: string, request: ProviderUpdateRequest) => Promise<ProviderResponse>;
|
||||||
|
|
||||||
|
getProviderUsers: (providerId: string) => Promise<ListResponse<ProviderUserUserDetailsResponse>>;
|
||||||
|
getProviderUser: (providerId: string, id: string) => Promise<ProviderUserResponse>;
|
||||||
|
postProviderUserInvite: (providerId: string, request: ProviderUserInviteRequest) => Promise<any>;
|
||||||
|
postProviderUserReinvite: (providerId: string, id: string) => Promise<any>;
|
||||||
|
postManyProviderUserReinvite: (
|
||||||
|
providerId: string,
|
||||||
|
request: ProviderUserBulkRequest,
|
||||||
|
) => Promise<ListResponse<ProviderUserBulkResponse>>;
|
||||||
|
postProviderUserAccept: (
|
||||||
|
providerId: string,
|
||||||
|
id: string,
|
||||||
|
request: ProviderUserAcceptRequest,
|
||||||
|
) => Promise<any>;
|
||||||
|
postProviderUserConfirm: (
|
||||||
|
providerId: string,
|
||||||
|
id: string,
|
||||||
|
request: ProviderUserConfirmRequest,
|
||||||
|
) => Promise<any>;
|
||||||
|
postProviderUsersPublicKey: (
|
||||||
|
providerId: string,
|
||||||
|
request: ProviderUserBulkRequest,
|
||||||
|
) => Promise<ListResponse<ProviderUserBulkPublicKeyResponse>>;
|
||||||
|
postProviderUserBulkConfirm: (
|
||||||
|
providerId: string,
|
||||||
|
request: ProviderUserBulkConfirmRequest,
|
||||||
|
) => Promise<ListResponse<ProviderUserBulkResponse>>;
|
||||||
|
putProviderUser: (
|
||||||
|
providerId: string,
|
||||||
|
id: string,
|
||||||
|
request: ProviderUserUpdateRequest,
|
||||||
|
) => Promise<any>;
|
||||||
|
deleteProviderUser: (organizationId: string, id: string) => Promise<any>;
|
||||||
|
deleteManyProviderUsers: (
|
||||||
|
providerId: string,
|
||||||
|
request: ProviderUserBulkRequest,
|
||||||
|
) => Promise<ListResponse<ProviderUserBulkResponse>>;
|
||||||
|
getProviderClients: (
|
||||||
|
providerId: string,
|
||||||
|
) => Promise<ListResponse<ProviderOrganizationOrganizationDetailsResponse>>;
|
||||||
|
postProviderAddOrganization: (
|
||||||
|
providerId: string,
|
||||||
|
request: ProviderAddOrganizationRequest,
|
||||||
|
) => Promise<any>;
|
||||||
|
postProviderCreateOrganization: (
|
||||||
|
providerId: string,
|
||||||
|
request: ProviderOrganizationCreateRequest,
|
||||||
|
) => Promise<ProviderOrganizationResponse>;
|
||||||
|
deleteProviderOrganization: (providerId: string, organizationId: string) => Promise<any>;
|
||||||
|
|
||||||
|
getEvents: (start: string, end: string, token: string) => Promise<ListResponse<EventResponse>>;
|
||||||
|
getEventsCipher: (
|
||||||
|
id: string,
|
||||||
|
start: string,
|
||||||
|
end: string,
|
||||||
|
token: string,
|
||||||
|
) => Promise<ListResponse<EventResponse>>;
|
||||||
|
getEventsOrganization: (
|
||||||
|
id: string,
|
||||||
|
start: string,
|
||||||
|
end: string,
|
||||||
|
token: string,
|
||||||
|
) => Promise<ListResponse<EventResponse>>;
|
||||||
|
getEventsOrganizationUser: (
|
||||||
|
organizationId: string,
|
||||||
|
id: string,
|
||||||
|
start: string,
|
||||||
|
end: string,
|
||||||
|
token: string,
|
||||||
|
) => Promise<ListResponse<EventResponse>>;
|
||||||
|
getEventsProvider: (
|
||||||
|
id: string,
|
||||||
|
start: string,
|
||||||
|
end: string,
|
||||||
|
token: string,
|
||||||
|
) => Promise<ListResponse<EventResponse>>;
|
||||||
|
getEventsProviderUser: (
|
||||||
|
providerId: string,
|
||||||
|
id: string,
|
||||||
|
start: string,
|
||||||
|
end: string,
|
||||||
|
token: string,
|
||||||
|
) => Promise<ListResponse<EventResponse>>;
|
||||||
|
postEventsCollect: (request: EventRequest[]) => Promise<any>;
|
||||||
|
|
||||||
|
deleteSsoUser: (organizationId: string) => Promise<any>;
|
||||||
|
getSsoUserIdentifier: () => Promise<string>;
|
||||||
|
|
||||||
|
getUserPublicKey: (id: string) => Promise<UserKeyResponse>;
|
||||||
|
|
||||||
|
getHibpBreach: (username: string) => Promise<BreachAccountResponse[]>;
|
||||||
|
|
||||||
|
postBitPayInvoice: (request: BitPayInvoiceRequest) => Promise<string>;
|
||||||
|
postSetupPayment: () => Promise<string>;
|
||||||
|
|
||||||
|
getActiveBearerToken: () => Promise<string>;
|
||||||
|
fetch: (request: Request) => Promise<Response>;
|
||||||
|
nativeFetch: (request: Request) => Promise<Response>;
|
||||||
|
|
||||||
|
preValidateSso: (identifier: string) => Promise<boolean>;
|
||||||
|
|
||||||
|
postCreateSponsorship: (
|
||||||
|
sponsorshipOrgId: string,
|
||||||
|
request: OrganizationSponsorshipCreateRequest,
|
||||||
|
) => Promise<void>;
|
||||||
|
deleteRevokeSponsorship: (sponsoringOrganizationId: string) => Promise<void>;
|
||||||
|
deleteRemoveSponsorship: (sponsoringOrgId: string) => Promise<void>;
|
||||||
|
postPreValidateSponsorshipToken: (sponsorshipToken: string) => Promise<boolean>;
|
||||||
|
postRedeemSponsorship: (
|
||||||
|
sponsorshipToken: string,
|
||||||
|
request: OrganizationSponsorshipRedeemRequest,
|
||||||
|
) => Promise<void>;
|
||||||
|
postResendSponsorshipOffer: (sponsoringOrgId: string) => Promise<void>;
|
||||||
|
|
||||||
|
getUserKeyFromKeyConnector: (keyConnectorUrl: string) => Promise<KeyConnectorUserKeyResponse>;
|
||||||
|
postUserKeyToKeyConnector: (
|
||||||
|
keyConnectorUrl: string,
|
||||||
|
request: KeyConnectorUserKeyRequest,
|
||||||
|
) => Promise<void>;
|
||||||
|
getKeyConnectorAlive: (keyConnectorUrl: string) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|||||||
6
jslib/common/src/abstractions/audit.service.ts
Normal file
6
jslib/common/src/abstractions/audit.service.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { BreachAccountResponse } from "../models/response/breachAccountResponse";
|
||||||
|
|
||||||
|
export abstract class AuditService {
|
||||||
|
passwordLeaked: (password: string) => Promise<number>;
|
||||||
|
breachedAccounts: (username: string) => Promise<BreachAccountResponse[]>;
|
||||||
|
}
|
||||||
25
jslib/common/src/abstractions/auth.service.ts
Normal file
25
jslib/common/src/abstractions/auth.service.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { AuthResult } from "../models/domain/authResult";
|
||||||
|
import {
|
||||||
|
ApiLogInCredentials,
|
||||||
|
PasswordLogInCredentials,
|
||||||
|
SsoLogInCredentials,
|
||||||
|
} from "../models/domain/logInCredentials";
|
||||||
|
import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey";
|
||||||
|
import { TokenRequestTwoFactor } from "../models/request/identityToken/tokenRequestTwoFactor";
|
||||||
|
|
||||||
|
export abstract class AuthService {
|
||||||
|
masterPasswordHash: string;
|
||||||
|
email: string;
|
||||||
|
logIn: (
|
||||||
|
credentials: ApiLogInCredentials | PasswordLogInCredentials | SsoLogInCredentials,
|
||||||
|
) => Promise<AuthResult>;
|
||||||
|
logInTwoFactor: (
|
||||||
|
twoFactor: TokenRequestTwoFactor,
|
||||||
|
captchaResponse: string,
|
||||||
|
) => Promise<AuthResult>;
|
||||||
|
logOut: (callback: () => void) => void;
|
||||||
|
makePreloginKey: (masterPassword: string, email: string) => Promise<SymmetricCryptoKey>;
|
||||||
|
authingWithApiKey: () => boolean;
|
||||||
|
authingWithSso: () => boolean;
|
||||||
|
authingWithPassword: () => boolean;
|
||||||
|
}
|
||||||
79
jslib/common/src/abstractions/cipher.service.ts
Normal file
79
jslib/common/src/abstractions/cipher.service.ts
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import { CipherType } from "../enums/cipherType";
|
||||||
|
import { UriMatchType } from "../enums/uriMatchType";
|
||||||
|
import { CipherData } from "../models/data/cipherData";
|
||||||
|
import { Cipher } from "../models/domain/cipher";
|
||||||
|
import { Field } from "../models/domain/field";
|
||||||
|
import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey";
|
||||||
|
import { CipherView } from "../models/view/cipherView";
|
||||||
|
import { FieldView } from "../models/view/fieldView";
|
||||||
|
|
||||||
|
export abstract class CipherService {
|
||||||
|
clearCache: (userId?: string) => Promise<void>;
|
||||||
|
encrypt: (
|
||||||
|
model: CipherView,
|
||||||
|
key?: SymmetricCryptoKey,
|
||||||
|
originalCipher?: Cipher,
|
||||||
|
) => Promise<Cipher>;
|
||||||
|
encryptFields: (fieldsModel: FieldView[], key: SymmetricCryptoKey) => Promise<Field[]>;
|
||||||
|
encryptField: (fieldModel: FieldView, key: SymmetricCryptoKey) => Promise<Field>;
|
||||||
|
get: (id: string) => Promise<Cipher>;
|
||||||
|
getAll: () => Promise<Cipher[]>;
|
||||||
|
getAllDecrypted: () => Promise<CipherView[]>;
|
||||||
|
getAllDecryptedForGrouping: (groupingId: string, folder?: boolean) => Promise<CipherView[]>;
|
||||||
|
getAllDecryptedForUrl: (
|
||||||
|
url: string,
|
||||||
|
includeOtherTypes?: CipherType[],
|
||||||
|
defaultMatch?: UriMatchType,
|
||||||
|
) => Promise<CipherView[]>;
|
||||||
|
getAllFromApiForOrganization: (organizationId: string) => Promise<CipherView[]>;
|
||||||
|
getLastUsedForUrl: (url: string, autofillOnPageLoad: boolean) => Promise<CipherView>;
|
||||||
|
getLastLaunchedForUrl: (url: string, autofillOnPageLoad: boolean) => Promise<CipherView>;
|
||||||
|
getNextCipherForUrl: (url: string) => Promise<CipherView>;
|
||||||
|
updateLastUsedIndexForUrl: (url: string) => void;
|
||||||
|
updateLastUsedDate: (id: string) => Promise<void>;
|
||||||
|
updateLastLaunchedDate: (id: string) => Promise<void>;
|
||||||
|
saveNeverDomain: (domain: string) => Promise<void>;
|
||||||
|
saveWithServer: (cipher: Cipher) => Promise<any>;
|
||||||
|
shareWithServer: (
|
||||||
|
cipher: CipherView,
|
||||||
|
organizationId: string,
|
||||||
|
collectionIds: string[],
|
||||||
|
) => Promise<any>;
|
||||||
|
shareManyWithServer: (
|
||||||
|
ciphers: CipherView[],
|
||||||
|
organizationId: string,
|
||||||
|
collectionIds: string[],
|
||||||
|
) => Promise<any>;
|
||||||
|
saveAttachmentWithServer: (
|
||||||
|
cipher: Cipher,
|
||||||
|
unencryptedFile: any,
|
||||||
|
admin?: boolean,
|
||||||
|
) => Promise<Cipher>;
|
||||||
|
saveAttachmentRawWithServer: (
|
||||||
|
cipher: Cipher,
|
||||||
|
filename: string,
|
||||||
|
data: ArrayBuffer,
|
||||||
|
admin?: boolean,
|
||||||
|
) => Promise<Cipher>;
|
||||||
|
saveCollectionsWithServer: (cipher: Cipher) => Promise<any>;
|
||||||
|
upsert: (cipher: CipherData | CipherData[]) => Promise<any>;
|
||||||
|
replace: (ciphers: { [id: string]: CipherData }) => Promise<any>;
|
||||||
|
clear: (userId: string) => Promise<any>;
|
||||||
|
moveManyWithServer: (ids: string[], folderId: string) => Promise<any>;
|
||||||
|
delete: (id: string | string[]) => Promise<any>;
|
||||||
|
deleteWithServer: (id: string) => Promise<any>;
|
||||||
|
deleteManyWithServer: (ids: string[]) => Promise<any>;
|
||||||
|
deleteAttachment: (id: string, attachmentId: string) => Promise<void>;
|
||||||
|
deleteAttachmentWithServer: (id: string, attachmentId: string) => Promise<void>;
|
||||||
|
sortCiphersByLastUsed: (a: any, b: any) => number;
|
||||||
|
sortCiphersByLastUsedThenName: (a: any, b: any) => number;
|
||||||
|
getLocaleSortingFunction: () => (a: CipherView, b: CipherView) => number;
|
||||||
|
softDelete: (id: string | string[]) => Promise<any>;
|
||||||
|
softDeleteWithServer: (id: string) => Promise<any>;
|
||||||
|
softDeleteManyWithServer: (ids: string[]) => Promise<any>;
|
||||||
|
restore: (
|
||||||
|
cipher: { id: string; revisionDate: string } | { id: string; revisionDate: string }[],
|
||||||
|
) => Promise<any>;
|
||||||
|
restoreWithServer: (id: string) => Promise<any>;
|
||||||
|
restoreManyWithServer: (ids: string[]) => Promise<any>;
|
||||||
|
}
|
||||||
19
jslib/common/src/abstractions/collection.service.ts
Normal file
19
jslib/common/src/abstractions/collection.service.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { CollectionData } from "../models/data/collectionData";
|
||||||
|
import { Collection } from "../models/domain/collection";
|
||||||
|
import { TreeNode } from "../models/domain/treeNode";
|
||||||
|
import { CollectionView } from "../models/view/collectionView";
|
||||||
|
|
||||||
|
export abstract class CollectionService {
|
||||||
|
clearCache: (userId?: string) => Promise<void>;
|
||||||
|
encrypt: (model: CollectionView) => Promise<Collection>;
|
||||||
|
decryptMany: (collections: Collection[]) => Promise<CollectionView[]>;
|
||||||
|
get: (id: string) => Promise<Collection>;
|
||||||
|
getAll: () => Promise<Collection[]>;
|
||||||
|
getAllDecrypted: () => Promise<CollectionView[]>;
|
||||||
|
getAllNested: (collections?: CollectionView[]) => Promise<TreeNode<CollectionView>[]>;
|
||||||
|
getNested: (id: string) => Promise<TreeNode<CollectionView>>;
|
||||||
|
upsert: (collection: CollectionData | CollectionData[]) => Promise<any>;
|
||||||
|
replace: (collections: { [id: string]: CollectionData }) => Promise<any>;
|
||||||
|
clear: (userId: string) => Promise<any>;
|
||||||
|
delete: (id: string | string[]) => Promise<any>;
|
||||||
|
}
|
||||||
7
jslib/common/src/abstractions/event.service.ts
Normal file
7
jslib/common/src/abstractions/event.service.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { EventType } from "../enums/eventType";
|
||||||
|
|
||||||
|
export abstract class EventService {
|
||||||
|
collect: (eventType: EventType, cipherId?: string, uploadImmediately?: boolean) => Promise<any>;
|
||||||
|
uploadEvents: (userId?: string) => Promise<any>;
|
||||||
|
clearEvents: (userId?: string) => Promise<any>;
|
||||||
|
}
|
||||||
18
jslib/common/src/abstractions/fileUpload.service.ts
Normal file
18
jslib/common/src/abstractions/fileUpload.service.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { EncArrayBuffer } from "../models/domain/encArrayBuffer";
|
||||||
|
import { EncString } from "../models/domain/encString";
|
||||||
|
import { AttachmentUploadDataResponse } from "../models/response/attachmentUploadDataResponse";
|
||||||
|
import { SendFileUploadDataResponse } from "../models/response/sendFileUploadDataResponse";
|
||||||
|
|
||||||
|
export abstract class FileUploadService {
|
||||||
|
uploadSendFile: (
|
||||||
|
uploadData: SendFileUploadDataResponse,
|
||||||
|
fileName: EncString,
|
||||||
|
encryptedFileData: EncArrayBuffer,
|
||||||
|
) => Promise<any>;
|
||||||
|
uploadCipherAttachment: (
|
||||||
|
admin: boolean,
|
||||||
|
uploadData: AttachmentUploadDataResponse,
|
||||||
|
fileName: EncString,
|
||||||
|
encryptedFileData: EncArrayBuffer,
|
||||||
|
) => Promise<any>;
|
||||||
|
}
|
||||||
21
jslib/common/src/abstractions/folder.service.ts
Normal file
21
jslib/common/src/abstractions/folder.service.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { FolderData } from "../models/data/folderData";
|
||||||
|
import { Folder } from "../models/domain/folder";
|
||||||
|
import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey";
|
||||||
|
import { TreeNode } from "../models/domain/treeNode";
|
||||||
|
import { FolderView } from "../models/view/folderView";
|
||||||
|
|
||||||
|
export abstract class FolderService {
|
||||||
|
clearCache: (userId?: string) => Promise<void>;
|
||||||
|
encrypt: (model: FolderView, key?: SymmetricCryptoKey) => Promise<Folder>;
|
||||||
|
get: (id: string) => Promise<Folder>;
|
||||||
|
getAll: () => Promise<Folder[]>;
|
||||||
|
getAllDecrypted: () => Promise<FolderView[]>;
|
||||||
|
getAllNested: () => Promise<TreeNode<FolderView>[]>;
|
||||||
|
getNested: (id: string) => Promise<TreeNode<FolderView>>;
|
||||||
|
saveWithServer: (folder: Folder) => Promise<any>;
|
||||||
|
upsert: (folder: FolderData | FolderData[]) => Promise<any>;
|
||||||
|
replace: (folders: { [id: string]: FolderData }) => Promise<any>;
|
||||||
|
clear: (userId: string) => Promise<any>;
|
||||||
|
delete: (id: string | string[]) => Promise<any>;
|
||||||
|
deleteWithServer: (id: string) => Promise<any>;
|
||||||
|
}
|
||||||
19
jslib/common/src/abstractions/keyConnector.service.ts
Normal file
19
jslib/common/src/abstractions/keyConnector.service.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { Organization } from "../models/domain/organization";
|
||||||
|
import { IdentityTokenResponse } from "../models/response/identityTokenResponse";
|
||||||
|
|
||||||
|
export abstract class KeyConnectorService {
|
||||||
|
getAndSetKey: (url?: string) => Promise<void>;
|
||||||
|
getManagingOrganization: () => Promise<Organization>;
|
||||||
|
getUsesKeyConnector: () => Promise<boolean>;
|
||||||
|
migrateUser: () => Promise<void>;
|
||||||
|
userNeedsMigration: () => Promise<boolean>;
|
||||||
|
convertNewSsoUserToKeyConnector: (
|
||||||
|
tokenResponse: IdentityTokenResponse,
|
||||||
|
orgId: string,
|
||||||
|
) => Promise<void>;
|
||||||
|
setUsesKeyConnector: (enabled: boolean) => Promise<void>;
|
||||||
|
setConvertAccountRequired: (status: boolean) => Promise<void>;
|
||||||
|
getConvertAccountRequired: () => Promise<boolean>;
|
||||||
|
removeConvertAccountRequired: () => Promise<void>;
|
||||||
|
clear: () => Promise<void>;
|
||||||
|
}
|
||||||
6
jslib/common/src/abstractions/notifications.service.ts
Normal file
6
jslib/common/src/abstractions/notifications.service.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export abstract class NotificationsService {
|
||||||
|
init: () => Promise<void>;
|
||||||
|
updateConnection: (sync?: boolean) => Promise<void>;
|
||||||
|
reconnectFromActivity: () => Promise<void>;
|
||||||
|
disconnectFromInactivity: () => Promise<void>;
|
||||||
|
}
|
||||||
11
jslib/common/src/abstractions/organization.service.ts
Normal file
11
jslib/common/src/abstractions/organization.service.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { OrganizationData } from "../models/data/organizationData";
|
||||||
|
import { Organization } from "../models/domain/organization";
|
||||||
|
|
||||||
|
export abstract class OrganizationService {
|
||||||
|
get: (id: string) => Promise<Organization>;
|
||||||
|
getByIdentifier: (identifier: string) => Promise<Organization>;
|
||||||
|
getAll: (userId?: string) => Promise<Organization[]>;
|
||||||
|
save: (orgs: { [id: string]: OrganizationData }) => Promise<any>;
|
||||||
|
canManageSponsorships: () => Promise<boolean>;
|
||||||
|
hasOrganizations: (userId?: string) => Promise<boolean>;
|
||||||
|
}
|
||||||
20
jslib/common/src/abstractions/passwordGeneration.service.ts
Normal file
20
jslib/common/src/abstractions/passwordGeneration.service.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import * as zxcvbn from "zxcvbn";
|
||||||
|
|
||||||
|
import { GeneratedPasswordHistory } from "../models/domain/generatedPasswordHistory";
|
||||||
|
import { PasswordGeneratorPolicyOptions } from "../models/domain/passwordGeneratorPolicyOptions";
|
||||||
|
|
||||||
|
export abstract class PasswordGenerationService {
|
||||||
|
generatePassword: (options: any) => Promise<string>;
|
||||||
|
generatePassphrase: (options: any) => Promise<string>;
|
||||||
|
getOptions: () => Promise<[any, PasswordGeneratorPolicyOptions]>;
|
||||||
|
enforcePasswordGeneratorPoliciesOnOptions: (
|
||||||
|
options: any,
|
||||||
|
) => Promise<[any, PasswordGeneratorPolicyOptions]>;
|
||||||
|
getPasswordGeneratorPolicyOptions: () => Promise<PasswordGeneratorPolicyOptions>;
|
||||||
|
saveOptions: (options: any) => Promise<any>;
|
||||||
|
getHistory: () => Promise<GeneratedPasswordHistory[]>;
|
||||||
|
addHistory: (password: string) => Promise<any>;
|
||||||
|
clear: (userId?: string) => Promise<any>;
|
||||||
|
passwordStrength: (password: string, userInputs?: string[]) => zxcvbn.ZXCVBNResult;
|
||||||
|
normalizeOptions: (options: any, enforcedPolicyOptions: PasswordGeneratorPolicyOptions) => void;
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
export abstract class PasswordRepromptService {
|
||||||
|
protectedFields: () => string[];
|
||||||
|
showPasswordPrompt: () => Promise<boolean>;
|
||||||
|
enabled: () => Promise<boolean>;
|
||||||
|
}
|
||||||
32
jslib/common/src/abstractions/policy.service.ts
Normal file
32
jslib/common/src/abstractions/policy.service.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { PolicyType } from "../enums/policyType";
|
||||||
|
import { PolicyData } from "../models/data/policyData";
|
||||||
|
import { MasterPasswordPolicyOptions } from "../models/domain/masterPasswordPolicyOptions";
|
||||||
|
import { Policy } from "../models/domain/policy";
|
||||||
|
import { ResetPasswordPolicyOptions } from "../models/domain/resetPasswordPolicyOptions";
|
||||||
|
import { ListResponse } from "../models/response/listResponse";
|
||||||
|
import { PolicyResponse } from "../models/response/policyResponse";
|
||||||
|
|
||||||
|
export abstract class PolicyService {
|
||||||
|
clearCache: () => void;
|
||||||
|
getAll: (type?: PolicyType, userId?: string) => Promise<Policy[]>;
|
||||||
|
getPolicyForOrganization: (policyType: PolicyType, organizationId: string) => Promise<Policy>;
|
||||||
|
replace: (policies: { [id: string]: PolicyData }) => Promise<any>;
|
||||||
|
clear: (userId?: string) => Promise<any>;
|
||||||
|
getMasterPasswordPoliciesForInvitedUsers: (orgId: string) => Promise<MasterPasswordPolicyOptions>;
|
||||||
|
getMasterPasswordPolicyOptions: (policies?: Policy[]) => Promise<MasterPasswordPolicyOptions>;
|
||||||
|
evaluateMasterPassword: (
|
||||||
|
passwordStrength: number,
|
||||||
|
newPassword: string,
|
||||||
|
enforcedPolicyOptions?: MasterPasswordPolicyOptions,
|
||||||
|
) => boolean;
|
||||||
|
getResetPasswordPolicyOptions: (
|
||||||
|
policies: Policy[],
|
||||||
|
orgId: string,
|
||||||
|
) => [ResetPasswordPolicyOptions, boolean];
|
||||||
|
mapPoliciesFromToken: (policiesResponse: ListResponse<PolicyResponse>) => Policy[];
|
||||||
|
policyAppliesToUser: (
|
||||||
|
policyType: PolicyType,
|
||||||
|
policyFilter?: (policy: Policy) => boolean,
|
||||||
|
userId?: string,
|
||||||
|
) => Promise<boolean>;
|
||||||
|
}
|
||||||
8
jslib/common/src/abstractions/provider.service.ts
Normal file
8
jslib/common/src/abstractions/provider.service.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { ProviderData } from "../models/data/providerData";
|
||||||
|
import { Provider } from "../models/domain/provider";
|
||||||
|
|
||||||
|
export abstract class ProviderService {
|
||||||
|
get: (id: string) => Promise<Provider>;
|
||||||
|
getAll: () => Promise<Provider[]>;
|
||||||
|
save: (providers: { [id: string]: ProviderData }) => Promise<any>;
|
||||||
|
}
|
||||||
16
jslib/common/src/abstractions/search.service.ts
Normal file
16
jslib/common/src/abstractions/search.service.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { CipherView } from "../models/view/cipherView";
|
||||||
|
import { SendView } from "../models/view/sendView";
|
||||||
|
|
||||||
|
export abstract class SearchService {
|
||||||
|
indexedEntityId?: string = null;
|
||||||
|
clearIndex: () => void;
|
||||||
|
isSearchable: (query: string) => boolean;
|
||||||
|
indexCiphers: (indexedEntityGuid?: string, ciphersToIndex?: CipherView[]) => Promise<void>;
|
||||||
|
searchCiphers: (
|
||||||
|
query: string,
|
||||||
|
filter?: ((cipher: CipherView) => boolean) | ((cipher: CipherView) => boolean)[],
|
||||||
|
ciphers?: CipherView[],
|
||||||
|
) => Promise<CipherView[]>;
|
||||||
|
searchCiphersBasic: (ciphers: CipherView[], query: string, deleted?: boolean) => CipherView[];
|
||||||
|
searchSends: (sends: SendView[], query: string) => SendView[];
|
||||||
|
}
|
||||||
25
jslib/common/src/abstractions/send.service.ts
Normal file
25
jslib/common/src/abstractions/send.service.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { SendData } from "../models/data/sendData";
|
||||||
|
import { EncArrayBuffer } from "../models/domain/encArrayBuffer";
|
||||||
|
import { Send } from "../models/domain/send";
|
||||||
|
import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey";
|
||||||
|
import { SendView } from "../models/view/sendView";
|
||||||
|
|
||||||
|
export abstract class SendService {
|
||||||
|
clearCache: () => Promise<void>;
|
||||||
|
encrypt: (
|
||||||
|
model: SendView,
|
||||||
|
file: File | ArrayBuffer,
|
||||||
|
password: string,
|
||||||
|
key?: SymmetricCryptoKey,
|
||||||
|
) => Promise<[Send, EncArrayBuffer]>;
|
||||||
|
get: (id: string) => Promise<Send>;
|
||||||
|
getAll: () => Promise<Send[]>;
|
||||||
|
getAllDecrypted: () => Promise<SendView[]>;
|
||||||
|
saveWithServer: (sendData: [Send, EncArrayBuffer]) => Promise<any>;
|
||||||
|
upsert: (send: SendData | SendData[]) => Promise<any>;
|
||||||
|
replace: (sends: { [id: string]: SendData }) => Promise<any>;
|
||||||
|
clear: (userId: string) => Promise<any>;
|
||||||
|
delete: (id: string | string[]) => Promise<any>;
|
||||||
|
deleteWithServer: (id: string) => Promise<any>;
|
||||||
|
removePasswordWithServer: (id: string) => Promise<any>;
|
||||||
|
}
|
||||||
6
jslib/common/src/abstractions/settings.service.ts
Normal file
6
jslib/common/src/abstractions/settings.service.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export abstract class SettingsService {
|
||||||
|
clearCache: () => Promise<void>;
|
||||||
|
getEquivalentDomains: () => Promise<any>;
|
||||||
|
setEquivalentDomains: (equivalentDomains: string[][]) => Promise<any>;
|
||||||
|
clear: (userId?: string) => Promise<void>;
|
||||||
|
}
|
||||||
19
jslib/common/src/abstractions/sync.service.ts
Normal file
19
jslib/common/src/abstractions/sync.service.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import {
|
||||||
|
SyncCipherNotification,
|
||||||
|
SyncFolderNotification,
|
||||||
|
SyncSendNotification,
|
||||||
|
} from "../models/response/notificationResponse";
|
||||||
|
|
||||||
|
export abstract class SyncService {
|
||||||
|
syncInProgress: boolean;
|
||||||
|
|
||||||
|
getLastSync: () => Promise<Date>;
|
||||||
|
setLastSync: (date: Date, userId?: string) => Promise<any>;
|
||||||
|
fullSync: (forceSync: boolean, allowThrowOnError?: boolean) => Promise<boolean>;
|
||||||
|
syncUpsertFolder: (notification: SyncFolderNotification, isEdit: boolean) => Promise<boolean>;
|
||||||
|
syncDeleteFolder: (notification: SyncFolderNotification) => Promise<boolean>;
|
||||||
|
syncUpsertCipher: (notification: SyncCipherNotification, isEdit: boolean) => Promise<boolean>;
|
||||||
|
syncDeleteCipher: (notification: SyncFolderNotification) => Promise<boolean>;
|
||||||
|
syncUpsertSend: (notification: SyncSendNotification, isEdit: boolean) => Promise<boolean>;
|
||||||
|
syncDeleteSend: (notification: SyncSendNotification) => Promise<boolean>;
|
||||||
|
}
|
||||||
6
jslib/common/src/abstractions/system.service.ts
Normal file
6
jslib/common/src/abstractions/system.service.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export abstract class SystemService {
|
||||||
|
startProcessReload: () => Promise<void>;
|
||||||
|
cancelProcessReload: () => void;
|
||||||
|
clearClipboard: (clipboardValue: string, timeoutMs?: number) => Promise<void>;
|
||||||
|
clearPendingClipboard: () => Promise<any>;
|
||||||
|
}
|
||||||
5
jslib/common/src/abstractions/totp.service.ts
Normal file
5
jslib/common/src/abstractions/totp.service.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export abstract class TotpService {
|
||||||
|
getCode: (key: string) => Promise<string>;
|
||||||
|
getTimeInterval: (key: string) => number;
|
||||||
|
isAutoCopyEnabled: () => Promise<boolean>;
|
||||||
|
}
|
||||||
23
jslib/common/src/abstractions/twoFactor.service.ts
Normal file
23
jslib/common/src/abstractions/twoFactor.service.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { TwoFactorProviderType } from "../enums/twoFactorProviderType";
|
||||||
|
import { IdentityTwoFactorResponse } from "../models/response/identityTwoFactorResponse";
|
||||||
|
|
||||||
|
export interface TwoFactorProviderDetails {
|
||||||
|
type: TwoFactorProviderType;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
priority: number;
|
||||||
|
sort: number;
|
||||||
|
premium: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class TwoFactorService {
|
||||||
|
init: () => void;
|
||||||
|
getSupportedProviders: (win: Window) => TwoFactorProviderDetails[];
|
||||||
|
getDefaultProvider: (webAuthnSupported: boolean) => TwoFactorProviderType;
|
||||||
|
setSelectedProvider: (type: TwoFactorProviderType) => void;
|
||||||
|
clearSelectedProvider: () => void;
|
||||||
|
|
||||||
|
setProviders: (response: IdentityTwoFactorResponse) => void;
|
||||||
|
clearProviders: () => void;
|
||||||
|
getProviders: () => Map<TwoFactorProviderType, { [key: string]: string }>;
|
||||||
|
}
|
||||||
12
jslib/common/src/abstractions/userVerification.service.ts
Normal file
12
jslib/common/src/abstractions/userVerification.service.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { SecretVerificationRequest } from "../models/request/secretVerificationRequest";
|
||||||
|
import { Verification } from "../types/verification";
|
||||||
|
|
||||||
|
export abstract class UserVerificationService {
|
||||||
|
buildRequest: <T extends SecretVerificationRequest>(
|
||||||
|
verification: Verification,
|
||||||
|
requestClass?: new () => T,
|
||||||
|
alreadyHashed?: boolean,
|
||||||
|
) => Promise<T>;
|
||||||
|
verifyUser: (verification: Verification) => Promise<boolean>;
|
||||||
|
requestOTP: () => Promise<void>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export abstract class UsernameGenerationService {
|
||||||
|
generateUsername: (options: any) => Promise<string>;
|
||||||
|
generateWord: (options: any) => Promise<string>;
|
||||||
|
generateSubaddress: (options: any) => Promise<string>;
|
||||||
|
generateCatchall: (options: any) => Promise<string>;
|
||||||
|
getOptions: () => Promise<any>;
|
||||||
|
saveOptions: (options: any) => Promise<void>;
|
||||||
|
}
|
||||||
11
jslib/common/src/abstractions/vaultTimeout.service.ts
Normal file
11
jslib/common/src/abstractions/vaultTimeout.service.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
export abstract class VaultTimeoutService {
|
||||||
|
isLocked: (userId?: string) => Promise<boolean>;
|
||||||
|
checkVaultTimeout: () => Promise<void>;
|
||||||
|
lock: (allowSoftLock?: boolean, userId?: string) => Promise<void>;
|
||||||
|
logOut: (userId?: string) => Promise<void>;
|
||||||
|
setVaultTimeoutOptions: (vaultTimeout: number, vaultTimeoutAction: string) => Promise<void>;
|
||||||
|
getVaultTimeout: () => Promise<number>;
|
||||||
|
isPinLockSet: () => Promise<[boolean, boolean]>;
|
||||||
|
isBiometricLockSet: () => Promise<boolean>;
|
||||||
|
clear: (userId?: string) => Promise<any>;
|
||||||
|
}
|
||||||
5
jslib/common/src/enums/authenticationType.ts
Normal file
5
jslib/common/src/enums/authenticationType.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export enum AuthenticationType {
|
||||||
|
Password = 0,
|
||||||
|
Sso = 1,
|
||||||
|
Api = 2,
|
||||||
|
}
|
||||||
70
jslib/common/src/misc/logInStrategies/apiLogin.strategy.ts
Normal file
70
jslib/common/src/misc/logInStrategies/apiLogin.strategy.ts
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import { ApiService } from "../../abstractions/api.service";
|
||||||
|
import { AppIdService } from "../../abstractions/appId.service";
|
||||||
|
import { CryptoService } from "../../abstractions/crypto.service";
|
||||||
|
import { EnvironmentService } from "../../abstractions/environment.service";
|
||||||
|
import { KeyConnectorService } from "../../abstractions/keyConnector.service";
|
||||||
|
import { LogService } from "../../abstractions/log.service";
|
||||||
|
import { MessagingService } from "../../abstractions/messaging.service";
|
||||||
|
import { PlatformUtilsService } from "../../abstractions/platformUtils.service";
|
||||||
|
import { StateService } from "../../abstractions/state.service";
|
||||||
|
import { TokenService } from "../../abstractions/token.service";
|
||||||
|
import { TwoFactorService } from "../../abstractions/twoFactor.service";
|
||||||
|
import { ApiLogInCredentials } from "../../models/domain/logInCredentials";
|
||||||
|
import { ApiTokenRequest } from "../../models/request/identityToken/apiTokenRequest";
|
||||||
|
import { IdentityTokenResponse } from "../../models/response/identityTokenResponse";
|
||||||
|
|
||||||
|
import { LogInStrategy } from "./logIn.strategy";
|
||||||
|
|
||||||
|
export class ApiLogInStrategy extends LogInStrategy {
|
||||||
|
tokenRequest: ApiTokenRequest;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
cryptoService: CryptoService,
|
||||||
|
apiService: ApiService,
|
||||||
|
tokenService: TokenService,
|
||||||
|
appIdService: AppIdService,
|
||||||
|
platformUtilsService: PlatformUtilsService,
|
||||||
|
messagingService: MessagingService,
|
||||||
|
logService: LogService,
|
||||||
|
stateService: StateService,
|
||||||
|
twoFactorService: TwoFactorService,
|
||||||
|
private environmentService: EnvironmentService,
|
||||||
|
private keyConnectorService: KeyConnectorService,
|
||||||
|
) {
|
||||||
|
super(
|
||||||
|
cryptoService,
|
||||||
|
apiService,
|
||||||
|
tokenService,
|
||||||
|
appIdService,
|
||||||
|
platformUtilsService,
|
||||||
|
messagingService,
|
||||||
|
logService,
|
||||||
|
stateService,
|
||||||
|
twoFactorService,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async onSuccessfulLogin(tokenResponse: IdentityTokenResponse) {
|
||||||
|
if (tokenResponse.apiUseKeyConnector) {
|
||||||
|
const keyConnectorUrl = this.environmentService.getKeyConnectorUrl();
|
||||||
|
await this.keyConnectorService.getAndSetKey(keyConnectorUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async logIn(credentials: ApiLogInCredentials) {
|
||||||
|
this.tokenRequest = new ApiTokenRequest(
|
||||||
|
credentials.clientId,
|
||||||
|
credentials.clientSecret,
|
||||||
|
await this.buildTwoFactor(),
|
||||||
|
await this.buildDeviceRequest(),
|
||||||
|
);
|
||||||
|
|
||||||
|
return this.startLogIn();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async saveAccountInformation(tokenResponse: IdentityTokenResponse) {
|
||||||
|
await super.saveAccountInformation(tokenResponse);
|
||||||
|
await this.stateService.setApiKeyClientId(this.tokenRequest.clientId);
|
||||||
|
await this.stateService.setApiKeyClientSecret(this.tokenRequest.clientSecret);
|
||||||
|
}
|
||||||
|
}
|
||||||
170
jslib/common/src/misc/logInStrategies/logIn.strategy.ts
Normal file
170
jslib/common/src/misc/logInStrategies/logIn.strategy.ts
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
import { ApiService } from "../../abstractions/api.service";
|
||||||
|
import { AppIdService } from "../../abstractions/appId.service";
|
||||||
|
import { CryptoService } from "../../abstractions/crypto.service";
|
||||||
|
import { LogService } from "../../abstractions/log.service";
|
||||||
|
import { MessagingService } from "../../abstractions/messaging.service";
|
||||||
|
import { PlatformUtilsService } from "../../abstractions/platformUtils.service";
|
||||||
|
import { StateService } from "../../abstractions/state.service";
|
||||||
|
import { TokenService } from "../../abstractions/token.service";
|
||||||
|
import { TwoFactorService } from "../../abstractions/twoFactor.service";
|
||||||
|
import { TwoFactorProviderType } from "../../enums/twoFactorProviderType";
|
||||||
|
import { Account, AccountProfile, AccountTokens } from "../../models/domain/account";
|
||||||
|
import { AuthResult } from "../../models/domain/authResult";
|
||||||
|
import {
|
||||||
|
ApiLogInCredentials,
|
||||||
|
PasswordLogInCredentials,
|
||||||
|
SsoLogInCredentials,
|
||||||
|
} from "../../models/domain/logInCredentials";
|
||||||
|
import { DeviceRequest } from "../../models/request/deviceRequest";
|
||||||
|
import { ApiTokenRequest } from "../../models/request/identityToken/apiTokenRequest";
|
||||||
|
import { PasswordTokenRequest } from "../../models/request/identityToken/passwordTokenRequest";
|
||||||
|
import { SsoTokenRequest } from "../../models/request/identityToken/ssoTokenRequest";
|
||||||
|
import { TokenRequestTwoFactor } from "../../models/request/identityToken/tokenRequestTwoFactor";
|
||||||
|
import { KeysRequest } from "../../models/request/keysRequest";
|
||||||
|
import { IdentityCaptchaResponse } from "../../models/response/identityCaptchaResponse";
|
||||||
|
import { IdentityTokenResponse } from "../../models/response/identityTokenResponse";
|
||||||
|
import { IdentityTwoFactorResponse } from "../../models/response/identityTwoFactorResponse";
|
||||||
|
|
||||||
|
export abstract class LogInStrategy {
|
||||||
|
protected abstract tokenRequest: ApiTokenRequest | PasswordTokenRequest | SsoTokenRequest;
|
||||||
|
protected captchaBypassToken: string = null;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected cryptoService: CryptoService,
|
||||||
|
protected apiService: ApiService,
|
||||||
|
protected tokenService: TokenService,
|
||||||
|
protected appIdService: AppIdService,
|
||||||
|
protected platformUtilsService: PlatformUtilsService,
|
||||||
|
protected messagingService: MessagingService,
|
||||||
|
protected logService: LogService,
|
||||||
|
protected stateService: StateService,
|
||||||
|
protected twoFactorService: TwoFactorService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
abstract logIn(
|
||||||
|
credentials: ApiLogInCredentials | PasswordLogInCredentials | SsoLogInCredentials,
|
||||||
|
): Promise<AuthResult>;
|
||||||
|
|
||||||
|
async logInTwoFactor(
|
||||||
|
twoFactor: TokenRequestTwoFactor,
|
||||||
|
captchaResponse: string = null,
|
||||||
|
): Promise<AuthResult> {
|
||||||
|
this.tokenRequest.setTwoFactor(twoFactor);
|
||||||
|
return this.startLogIn();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async startLogIn(): Promise<AuthResult> {
|
||||||
|
this.twoFactorService.clearSelectedProvider();
|
||||||
|
|
||||||
|
const response = await this.apiService.postIdentityToken(this.tokenRequest);
|
||||||
|
|
||||||
|
if (response instanceof IdentityTwoFactorResponse) {
|
||||||
|
return this.processTwoFactorResponse(response);
|
||||||
|
} else if (response instanceof IdentityCaptchaResponse) {
|
||||||
|
return this.processCaptchaResponse(response);
|
||||||
|
} else if (response instanceof IdentityTokenResponse) {
|
||||||
|
return this.processTokenResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error("Invalid response object.");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected onSuccessfulLogin(response: IdentityTokenResponse): Promise<void> {
|
||||||
|
// Implemented in subclass if required
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async buildDeviceRequest() {
|
||||||
|
const appId = await this.appIdService.getAppId();
|
||||||
|
return new DeviceRequest(appId, this.platformUtilsService);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async buildTwoFactor(userProvidedTwoFactor?: TokenRequestTwoFactor) {
|
||||||
|
if (userProvidedTwoFactor != null) {
|
||||||
|
return userProvidedTwoFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
const storedTwoFactorToken = await this.tokenService.getTwoFactorToken();
|
||||||
|
if (storedTwoFactorToken != null) {
|
||||||
|
return new TokenRequestTwoFactor(TwoFactorProviderType.Remember, storedTwoFactorToken, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TokenRequestTwoFactor();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async saveAccountInformation(tokenResponse: IdentityTokenResponse) {
|
||||||
|
const accountInformation = await this.tokenService.decodeToken(tokenResponse.accessToken);
|
||||||
|
await this.stateService.addAccount(
|
||||||
|
new Account({
|
||||||
|
profile: {
|
||||||
|
...new AccountProfile(),
|
||||||
|
...{
|
||||||
|
userId: accountInformation.sub,
|
||||||
|
email: accountInformation.email,
|
||||||
|
hasPremiumPersonally: accountInformation.premium,
|
||||||
|
kdfIterations: tokenResponse.kdfIterations,
|
||||||
|
kdfType: tokenResponse.kdf,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tokens: {
|
||||||
|
...new AccountTokens(),
|
||||||
|
...{
|
||||||
|
accessToken: tokenResponse.accessToken,
|
||||||
|
refreshToken: tokenResponse.refreshToken,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async processTokenResponse(response: IdentityTokenResponse): Promise<AuthResult> {
|
||||||
|
const result = new AuthResult();
|
||||||
|
result.resetMasterPassword = response.resetMasterPassword;
|
||||||
|
result.forcePasswordReset = response.forcePasswordReset;
|
||||||
|
|
||||||
|
await this.saveAccountInformation(response);
|
||||||
|
|
||||||
|
if (response.twoFactorToken != null) {
|
||||||
|
await this.tokenService.setTwoFactorToken(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
const newSsoUser = response.key == null;
|
||||||
|
if (!newSsoUser) {
|
||||||
|
await this.cryptoService.setEncKey(response.key);
|
||||||
|
await this.cryptoService.setEncPrivateKey(
|
||||||
|
response.privateKey ?? (await this.createKeyPairForOldAccount()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.onSuccessfulLogin(response);
|
||||||
|
|
||||||
|
await this.stateService.setBiometricLocked(false);
|
||||||
|
this.messagingService.send("loggedIn");
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async processTwoFactorResponse(response: IdentityTwoFactorResponse): Promise<AuthResult> {
|
||||||
|
const result = new AuthResult();
|
||||||
|
result.twoFactorProviders = response.twoFactorProviders2;
|
||||||
|
this.twoFactorService.setProviders(response);
|
||||||
|
this.captchaBypassToken = response.captchaToken ?? null;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async processCaptchaResponse(response: IdentityCaptchaResponse): Promise<AuthResult> {
|
||||||
|
const result = new AuthResult();
|
||||||
|
result.captchaSiteKey = response.siteKey;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async createKeyPairForOldAccount() {
|
||||||
|
try {
|
||||||
|
const [publicKey, privateKey] = await this.cryptoService.makeKeyPair();
|
||||||
|
await this.apiService.postAccountKeys(new KeysRequest(publicKey, privateKey.encryptedString));
|
||||||
|
return privateKey.encryptedString;
|
||||||
|
} catch (e) {
|
||||||
|
this.logService.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
import { ApiService } from "../../abstractions/api.service";
|
||||||
|
import { AppIdService } from "../../abstractions/appId.service";
|
||||||
|
import { AuthService } from "../../abstractions/auth.service";
|
||||||
|
import { CryptoService } from "../../abstractions/crypto.service";
|
||||||
|
import { LogService } from "../../abstractions/log.service";
|
||||||
|
import { MessagingService } from "../../abstractions/messaging.service";
|
||||||
|
import { PlatformUtilsService } from "../../abstractions/platformUtils.service";
|
||||||
|
import { StateService } from "../../abstractions/state.service";
|
||||||
|
import { TokenService } from "../../abstractions/token.service";
|
||||||
|
import { TwoFactorService } from "../../abstractions/twoFactor.service";
|
||||||
|
import { HashPurpose } from "../../enums/hashPurpose";
|
||||||
|
import { AuthResult } from "../../models/domain/authResult";
|
||||||
|
import { PasswordLogInCredentials } from "../../models/domain/logInCredentials";
|
||||||
|
import { SymmetricCryptoKey } from "../../models/domain/symmetricCryptoKey";
|
||||||
|
import { PasswordTokenRequest } from "../../models/request/identityToken/passwordTokenRequest";
|
||||||
|
import { TokenRequestTwoFactor } from "../../models/request/identityToken/tokenRequestTwoFactor";
|
||||||
|
|
||||||
|
import { LogInStrategy } from "./logIn.strategy";
|
||||||
|
|
||||||
|
export class PasswordLogInStrategy extends LogInStrategy {
|
||||||
|
get email() {
|
||||||
|
return this.tokenRequest.email;
|
||||||
|
}
|
||||||
|
|
||||||
|
get masterPasswordHash() {
|
||||||
|
return this.tokenRequest.masterPasswordHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenRequest: PasswordTokenRequest;
|
||||||
|
|
||||||
|
private localHashedPassword: string;
|
||||||
|
private key: SymmetricCryptoKey;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
cryptoService: CryptoService,
|
||||||
|
apiService: ApiService,
|
||||||
|
tokenService: TokenService,
|
||||||
|
appIdService: AppIdService,
|
||||||
|
platformUtilsService: PlatformUtilsService,
|
||||||
|
messagingService: MessagingService,
|
||||||
|
logService: LogService,
|
||||||
|
stateService: StateService,
|
||||||
|
twoFactorService: TwoFactorService,
|
||||||
|
private authService: AuthService,
|
||||||
|
) {
|
||||||
|
super(
|
||||||
|
cryptoService,
|
||||||
|
apiService,
|
||||||
|
tokenService,
|
||||||
|
appIdService,
|
||||||
|
platformUtilsService,
|
||||||
|
messagingService,
|
||||||
|
logService,
|
||||||
|
stateService,
|
||||||
|
twoFactorService,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async onSuccessfulLogin() {
|
||||||
|
await this.cryptoService.setKey(this.key);
|
||||||
|
await this.cryptoService.setKeyHash(this.localHashedPassword);
|
||||||
|
}
|
||||||
|
|
||||||
|
async logInTwoFactor(
|
||||||
|
twoFactor: TokenRequestTwoFactor,
|
||||||
|
captchaResponse: string,
|
||||||
|
): Promise<AuthResult> {
|
||||||
|
this.tokenRequest.captchaResponse = captchaResponse ?? this.captchaBypassToken;
|
||||||
|
return super.logInTwoFactor(twoFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
async logIn(credentials: PasswordLogInCredentials) {
|
||||||
|
const { email, masterPassword, captchaToken, twoFactor } = credentials;
|
||||||
|
|
||||||
|
this.key = await this.authService.makePreloginKey(masterPassword, email);
|
||||||
|
|
||||||
|
// Hash the password early (before authentication) so we don't persist it in memory in plaintext
|
||||||
|
this.localHashedPassword = await this.cryptoService.hashPassword(
|
||||||
|
masterPassword,
|
||||||
|
this.key,
|
||||||
|
HashPurpose.LocalAuthorization,
|
||||||
|
);
|
||||||
|
const hashedPassword = await this.cryptoService.hashPassword(masterPassword, this.key);
|
||||||
|
|
||||||
|
this.tokenRequest = new PasswordTokenRequest(
|
||||||
|
email,
|
||||||
|
hashedPassword,
|
||||||
|
captchaToken,
|
||||||
|
await this.buildTwoFactor(twoFactor),
|
||||||
|
await this.buildDeviceRequest(),
|
||||||
|
);
|
||||||
|
|
||||||
|
return this.startLogIn();
|
||||||
|
}
|
||||||
|
}
|
||||||
70
jslib/common/src/misc/logInStrategies/ssoLogin.strategy.ts
Normal file
70
jslib/common/src/misc/logInStrategies/ssoLogin.strategy.ts
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import { ApiService } from "../../abstractions/api.service";
|
||||||
|
import { AppIdService } from "../../abstractions/appId.service";
|
||||||
|
import { CryptoService } from "../../abstractions/crypto.service";
|
||||||
|
import { KeyConnectorService } from "../../abstractions/keyConnector.service";
|
||||||
|
import { LogService } from "../../abstractions/log.service";
|
||||||
|
import { MessagingService } from "../../abstractions/messaging.service";
|
||||||
|
import { PlatformUtilsService } from "../../abstractions/platformUtils.service";
|
||||||
|
import { StateService } from "../../abstractions/state.service";
|
||||||
|
import { TokenService } from "../../abstractions/token.service";
|
||||||
|
import { TwoFactorService } from "../../abstractions/twoFactor.service";
|
||||||
|
import { SsoLogInCredentials } from "../../models/domain/logInCredentials";
|
||||||
|
import { SsoTokenRequest } from "../../models/request/identityToken/ssoTokenRequest";
|
||||||
|
import { IdentityTokenResponse } from "../../models/response/identityTokenResponse";
|
||||||
|
|
||||||
|
import { LogInStrategy } from "./logIn.strategy";
|
||||||
|
|
||||||
|
export class SsoLogInStrategy extends LogInStrategy {
|
||||||
|
tokenRequest: SsoTokenRequest;
|
||||||
|
orgId: string;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
cryptoService: CryptoService,
|
||||||
|
apiService: ApiService,
|
||||||
|
tokenService: TokenService,
|
||||||
|
appIdService: AppIdService,
|
||||||
|
platformUtilsService: PlatformUtilsService,
|
||||||
|
messagingService: MessagingService,
|
||||||
|
logService: LogService,
|
||||||
|
stateService: StateService,
|
||||||
|
twoFactorService: TwoFactorService,
|
||||||
|
private keyConnectorService: KeyConnectorService,
|
||||||
|
) {
|
||||||
|
super(
|
||||||
|
cryptoService,
|
||||||
|
apiService,
|
||||||
|
tokenService,
|
||||||
|
appIdService,
|
||||||
|
platformUtilsService,
|
||||||
|
messagingService,
|
||||||
|
logService,
|
||||||
|
stateService,
|
||||||
|
twoFactorService,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async onSuccessfulLogin(tokenResponse: IdentityTokenResponse) {
|
||||||
|
const newSsoUser = tokenResponse.key == null;
|
||||||
|
|
||||||
|
if (tokenResponse.keyConnectorUrl != null) {
|
||||||
|
if (!newSsoUser) {
|
||||||
|
await this.keyConnectorService.getAndSetKey(tokenResponse.keyConnectorUrl);
|
||||||
|
} else {
|
||||||
|
await this.keyConnectorService.convertNewSsoUserToKeyConnector(tokenResponse, this.orgId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async logIn(credentials: SsoLogInCredentials) {
|
||||||
|
this.orgId = credentials.orgId;
|
||||||
|
this.tokenRequest = new SsoTokenRequest(
|
||||||
|
credentials.code,
|
||||||
|
credentials.codeVerifier,
|
||||||
|
credentials.redirectUrl,
|
||||||
|
await this.buildTwoFactor(credentials.twoFactor),
|
||||||
|
await this.buildDeviceRequest(),
|
||||||
|
);
|
||||||
|
|
||||||
|
return this.startLogIn();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import { I18nService } from "../abstractions/i18n.service";
|
|||||||
|
|
||||||
import * as tldjs from "tldjs";
|
import * as tldjs from "tldjs";
|
||||||
|
|
||||||
|
|
||||||
const nodeURL = typeof window === "undefined" ? require("url") : null;
|
const nodeURL = typeof window === "undefined" ? require("url") : null;
|
||||||
|
|
||||||
export class Utils {
|
export class Utils {
|
||||||
|
|||||||
17
jslib/common/src/models/domain/authResult.ts
Normal file
17
jslib/common/src/models/domain/authResult.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { TwoFactorProviderType } from "../../enums/twoFactorProviderType";
|
||||||
|
import { Utils } from "../../misc/utils";
|
||||||
|
|
||||||
|
export class AuthResult {
|
||||||
|
captchaSiteKey = "";
|
||||||
|
resetMasterPassword = false;
|
||||||
|
forcePasswordReset = false;
|
||||||
|
twoFactorProviders: Map<TwoFactorProviderType, { [key: string]: string }> = null;
|
||||||
|
|
||||||
|
get requiresCaptcha() {
|
||||||
|
return !Utils.isNullOrWhitespace(this.captchaSiteKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
get requiresTwoFactor() {
|
||||||
|
return this.twoFactorProviders != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
34
jslib/common/src/models/domain/logInCredentials.ts
Normal file
34
jslib/common/src/models/domain/logInCredentials.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { AuthenticationType } from "../../enums/authenticationType";
|
||||||
|
import { TokenRequestTwoFactor } from "../request/identityToken/tokenRequestTwoFactor";
|
||||||
|
|
||||||
|
export class PasswordLogInCredentials {
|
||||||
|
readonly type = AuthenticationType.Password;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public email: string,
|
||||||
|
public masterPassword: string,
|
||||||
|
public captchaToken?: string,
|
||||||
|
public twoFactor?: TokenRequestTwoFactor,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SsoLogInCredentials {
|
||||||
|
readonly type = AuthenticationType.Sso;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public code: string,
|
||||||
|
public codeVerifier: string,
|
||||||
|
public redirectUrl: string,
|
||||||
|
public orgId: string,
|
||||||
|
public twoFactor?: TokenRequestTwoFactor,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ApiLogInCredentials {
|
||||||
|
readonly type = AuthenticationType.Api;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public clientId: string,
|
||||||
|
public clientSecret: string,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import { KdfType } from "../../../enums/kdfType";
|
||||||
|
import { KeysRequest } from "../keysRequest";
|
||||||
|
|
||||||
|
export class SetKeyConnectorKeyRequest {
|
||||||
|
key: string;
|
||||||
|
keys: KeysRequest;
|
||||||
|
kdf: KdfType;
|
||||||
|
kdfIterations: number;
|
||||||
|
orgIdentifier: string;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
key: string,
|
||||||
|
kdf: KdfType,
|
||||||
|
kdfIterations: number,
|
||||||
|
orgIdentifier: string,
|
||||||
|
keys: KeysRequest,
|
||||||
|
) {
|
||||||
|
this.key = key;
|
||||||
|
this.kdf = kdf;
|
||||||
|
this.kdfIterations = kdfIterations;
|
||||||
|
this.orgIdentifier = orgIdentifier;
|
||||||
|
this.keys = keys;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
export class VerifyOTPRequest {
|
||||||
|
OTP: string;
|
||||||
|
|
||||||
|
constructor(OTP: string) {
|
||||||
|
this.OTP = OTP;
|
||||||
|
}
|
||||||
|
}
|
||||||
6
jslib/common/src/models/request/attachmentRequest.ts
Normal file
6
jslib/common/src/models/request/attachmentRequest.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export class AttachmentRequest {
|
||||||
|
fileName: string;
|
||||||
|
key: string;
|
||||||
|
fileSize: number;
|
||||||
|
adminRequest: boolean;
|
||||||
|
}
|
||||||
9
jslib/common/src/models/request/bitPayInvoiceRequest.ts
Normal file
9
jslib/common/src/models/request/bitPayInvoiceRequest.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export class BitPayInvoiceRequest {
|
||||||
|
userId: string;
|
||||||
|
organizationId: string;
|
||||||
|
credit: boolean;
|
||||||
|
amount: number;
|
||||||
|
returnUrl: string;
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
export class CipherBulkDeleteRequest {
|
||||||
|
ids: string[];
|
||||||
|
organizationId: string;
|
||||||
|
|
||||||
|
constructor(ids: string[], organizationId?: string) {
|
||||||
|
this.ids = ids == null ? [] : ids;
|
||||||
|
this.organizationId = organizationId;
|
||||||
|
}
|
||||||
|
}
|
||||||
9
jslib/common/src/models/request/cipherBulkMoveRequest.ts
Normal file
9
jslib/common/src/models/request/cipherBulkMoveRequest.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export class CipherBulkMoveRequest {
|
||||||
|
ids: string[];
|
||||||
|
folderId: string;
|
||||||
|
|
||||||
|
constructor(ids: string[], folderId: string) {
|
||||||
|
this.ids = ids == null ? [] : ids;
|
||||||
|
this.folderId = folderId;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
export class CipherBulkRestoreRequest {
|
||||||
|
ids: string[];
|
||||||
|
|
||||||
|
constructor(ids: string[]) {
|
||||||
|
this.ids = ids == null ? [] : ids;
|
||||||
|
}
|
||||||
|
}
|
||||||
18
jslib/common/src/models/request/cipherBulkShareRequest.ts
Normal file
18
jslib/common/src/models/request/cipherBulkShareRequest.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { Cipher } from "../domain/cipher";
|
||||||
|
|
||||||
|
import { CipherWithIdRequest } from "./cipherWithIdRequest";
|
||||||
|
|
||||||
|
export class CipherBulkShareRequest {
|
||||||
|
ciphers: CipherWithIdRequest[];
|
||||||
|
collectionIds: string[];
|
||||||
|
|
||||||
|
constructor(ciphers: Cipher[], collectionIds: string[]) {
|
||||||
|
if (ciphers != null) {
|
||||||
|
this.ciphers = [];
|
||||||
|
ciphers.forEach((c) => {
|
||||||
|
this.ciphers.push(new CipherWithIdRequest(c));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.collectionIds = collectionIds;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
export class CipherCollectionsRequest {
|
||||||
|
collectionIds: string[];
|
||||||
|
|
||||||
|
constructor(collectionIds: string[]) {
|
||||||
|
this.collectionIds = collectionIds == null ? [] : collectionIds;
|
||||||
|
}
|
||||||
|
}
|
||||||
13
jslib/common/src/models/request/cipherCreateRequest.ts
Normal file
13
jslib/common/src/models/request/cipherCreateRequest.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { Cipher } from "../domain/cipher";
|
||||||
|
|
||||||
|
import { CipherRequest } from "./cipherRequest";
|
||||||
|
|
||||||
|
export class CipherCreateRequest {
|
||||||
|
cipher: CipherRequest;
|
||||||
|
collectionIds: string[];
|
||||||
|
|
||||||
|
constructor(cipher: Cipher) {
|
||||||
|
this.cipher = new CipherRequest(cipher);
|
||||||
|
this.collectionIds = cipher.collectionIds;
|
||||||
|
}
|
||||||
|
}
|
||||||
164
jslib/common/src/models/request/cipherRequest.ts
Normal file
164
jslib/common/src/models/request/cipherRequest.ts
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
import { CipherRepromptType } from "../../enums/cipherRepromptType";
|
||||||
|
import { CipherType } from "../../enums/cipherType";
|
||||||
|
import { CardApi } from "../api/cardApi";
|
||||||
|
import { FieldApi } from "../api/fieldApi";
|
||||||
|
import { IdentityApi } from "../api/identityApi";
|
||||||
|
import { LoginApi } from "../api/loginApi";
|
||||||
|
import { LoginUriApi } from "../api/loginUriApi";
|
||||||
|
import { SecureNoteApi } from "../api/secureNoteApi";
|
||||||
|
import { Cipher } from "../domain/cipher";
|
||||||
|
|
||||||
|
import { AttachmentRequest } from "./attachmentRequest";
|
||||||
|
import { PasswordHistoryRequest } from "./passwordHistoryRequest";
|
||||||
|
|
||||||
|
export class CipherRequest {
|
||||||
|
type: CipherType;
|
||||||
|
folderId: string;
|
||||||
|
organizationId: string;
|
||||||
|
name: string;
|
||||||
|
notes: string;
|
||||||
|
favorite: boolean;
|
||||||
|
login: LoginApi;
|
||||||
|
secureNote: SecureNoteApi;
|
||||||
|
card: CardApi;
|
||||||
|
identity: IdentityApi;
|
||||||
|
fields: FieldApi[];
|
||||||
|
passwordHistory: PasswordHistoryRequest[];
|
||||||
|
// Deprecated, remove at some point and rename attachments2 to attachments
|
||||||
|
attachments: { [id: string]: string };
|
||||||
|
attachments2: { [id: string]: AttachmentRequest };
|
||||||
|
lastKnownRevisionDate: Date;
|
||||||
|
reprompt: CipherRepromptType;
|
||||||
|
|
||||||
|
constructor(cipher: Cipher) {
|
||||||
|
this.type = cipher.type;
|
||||||
|
this.folderId = cipher.folderId;
|
||||||
|
this.organizationId = cipher.organizationId;
|
||||||
|
this.name = cipher.name ? cipher.name.encryptedString : null;
|
||||||
|
this.notes = cipher.notes ? cipher.notes.encryptedString : null;
|
||||||
|
this.favorite = cipher.favorite;
|
||||||
|
this.lastKnownRevisionDate = cipher.revisionDate;
|
||||||
|
this.reprompt = cipher.reprompt;
|
||||||
|
|
||||||
|
switch (this.type) {
|
||||||
|
case CipherType.Login:
|
||||||
|
this.login = new LoginApi();
|
||||||
|
this.login.uris = null;
|
||||||
|
this.login.username = cipher.login.username ? cipher.login.username.encryptedString : null;
|
||||||
|
this.login.password = cipher.login.password ? cipher.login.password.encryptedString : null;
|
||||||
|
this.login.passwordRevisionDate =
|
||||||
|
cipher.login.passwordRevisionDate != null
|
||||||
|
? cipher.login.passwordRevisionDate.toISOString()
|
||||||
|
: null;
|
||||||
|
this.login.totp = cipher.login.totp ? cipher.login.totp.encryptedString : null;
|
||||||
|
this.login.autofillOnPageLoad = cipher.login.autofillOnPageLoad;
|
||||||
|
|
||||||
|
if (cipher.login.uris != null) {
|
||||||
|
this.login.uris = cipher.login.uris.map((u) => {
|
||||||
|
const uri = new LoginUriApi();
|
||||||
|
uri.uri = u.uri != null ? u.uri.encryptedString : null;
|
||||||
|
uri.match = u.match != null ? u.match : null;
|
||||||
|
return uri;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CipherType.SecureNote:
|
||||||
|
this.secureNote = new SecureNoteApi();
|
||||||
|
this.secureNote.type = cipher.secureNote.type;
|
||||||
|
break;
|
||||||
|
case CipherType.Card:
|
||||||
|
this.card = new CardApi();
|
||||||
|
this.card.cardholderName =
|
||||||
|
cipher.card.cardholderName != null ? cipher.card.cardholderName.encryptedString : null;
|
||||||
|
this.card.brand = cipher.card.brand != null ? cipher.card.brand.encryptedString : null;
|
||||||
|
this.card.number = cipher.card.number != null ? cipher.card.number.encryptedString : null;
|
||||||
|
this.card.expMonth =
|
||||||
|
cipher.card.expMonth != null ? cipher.card.expMonth.encryptedString : null;
|
||||||
|
this.card.expYear =
|
||||||
|
cipher.card.expYear != null ? cipher.card.expYear.encryptedString : null;
|
||||||
|
this.card.code = cipher.card.code != null ? cipher.card.code.encryptedString : null;
|
||||||
|
break;
|
||||||
|
case CipherType.Identity:
|
||||||
|
this.identity = new IdentityApi();
|
||||||
|
this.identity.title =
|
||||||
|
cipher.identity.title != null ? cipher.identity.title.encryptedString : null;
|
||||||
|
this.identity.firstName =
|
||||||
|
cipher.identity.firstName != null ? cipher.identity.firstName.encryptedString : null;
|
||||||
|
this.identity.middleName =
|
||||||
|
cipher.identity.middleName != null ? cipher.identity.middleName.encryptedString : null;
|
||||||
|
this.identity.lastName =
|
||||||
|
cipher.identity.lastName != null ? cipher.identity.lastName.encryptedString : null;
|
||||||
|
this.identity.address1 =
|
||||||
|
cipher.identity.address1 != null ? cipher.identity.address1.encryptedString : null;
|
||||||
|
this.identity.address2 =
|
||||||
|
cipher.identity.address2 != null ? cipher.identity.address2.encryptedString : null;
|
||||||
|
this.identity.address3 =
|
||||||
|
cipher.identity.address3 != null ? cipher.identity.address3.encryptedString : null;
|
||||||
|
this.identity.city =
|
||||||
|
cipher.identity.city != null ? cipher.identity.city.encryptedString : null;
|
||||||
|
this.identity.state =
|
||||||
|
cipher.identity.state != null ? cipher.identity.state.encryptedString : null;
|
||||||
|
this.identity.postalCode =
|
||||||
|
cipher.identity.postalCode != null ? cipher.identity.postalCode.encryptedString : null;
|
||||||
|
this.identity.country =
|
||||||
|
cipher.identity.country != null ? cipher.identity.country.encryptedString : null;
|
||||||
|
this.identity.company =
|
||||||
|
cipher.identity.company != null ? cipher.identity.company.encryptedString : null;
|
||||||
|
this.identity.email =
|
||||||
|
cipher.identity.email != null ? cipher.identity.email.encryptedString : null;
|
||||||
|
this.identity.phone =
|
||||||
|
cipher.identity.phone != null ? cipher.identity.phone.encryptedString : null;
|
||||||
|
this.identity.ssn =
|
||||||
|
cipher.identity.ssn != null ? cipher.identity.ssn.encryptedString : null;
|
||||||
|
this.identity.username =
|
||||||
|
cipher.identity.username != null ? cipher.identity.username.encryptedString : null;
|
||||||
|
this.identity.passportNumber =
|
||||||
|
cipher.identity.passportNumber != null
|
||||||
|
? cipher.identity.passportNumber.encryptedString
|
||||||
|
: null;
|
||||||
|
this.identity.licenseNumber =
|
||||||
|
cipher.identity.licenseNumber != null
|
||||||
|
? cipher.identity.licenseNumber.encryptedString
|
||||||
|
: null;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cipher.fields != null) {
|
||||||
|
this.fields = cipher.fields.map((f) => {
|
||||||
|
const field = new FieldApi();
|
||||||
|
field.type = f.type;
|
||||||
|
field.name = f.name ? f.name.encryptedString : null;
|
||||||
|
field.value = f.value ? f.value.encryptedString : null;
|
||||||
|
field.linkedId = f.linkedId;
|
||||||
|
return field;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cipher.passwordHistory != null) {
|
||||||
|
this.passwordHistory = [];
|
||||||
|
cipher.passwordHistory.forEach((ph) => {
|
||||||
|
this.passwordHistory.push({
|
||||||
|
lastUsedDate: ph.lastUsedDate,
|
||||||
|
password: ph.password ? ph.password.encryptedString : null,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cipher.attachments != null) {
|
||||||
|
this.attachments = {};
|
||||||
|
this.attachments2 = {};
|
||||||
|
cipher.attachments.forEach((attachment) => {
|
||||||
|
const fileName = attachment.fileName ? attachment.fileName.encryptedString : null;
|
||||||
|
this.attachments[attachment.id] = fileName;
|
||||||
|
const attachmentRequest = new AttachmentRequest();
|
||||||
|
attachmentRequest.fileName = fileName;
|
||||||
|
if (attachment.key != null) {
|
||||||
|
attachmentRequest.key = attachment.key.encryptedString;
|
||||||
|
}
|
||||||
|
this.attachments2[attachment.id] = attachmentRequest;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
jslib/common/src/models/request/cipherShareRequest.ts
Normal file
13
jslib/common/src/models/request/cipherShareRequest.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { Cipher } from "../domain/cipher";
|
||||||
|
|
||||||
|
import { CipherRequest } from "./cipherRequest";
|
||||||
|
|
||||||
|
export class CipherShareRequest {
|
||||||
|
cipher: CipherRequest;
|
||||||
|
collectionIds: string[];
|
||||||
|
|
||||||
|
constructor(cipher: Cipher) {
|
||||||
|
this.cipher = new CipherRequest(cipher);
|
||||||
|
this.collectionIds = cipher.collectionIds;
|
||||||
|
}
|
||||||
|
}
|
||||||
12
jslib/common/src/models/request/cipherWithIdRequest.ts
Normal file
12
jslib/common/src/models/request/cipherWithIdRequest.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { Cipher } from "../domain/cipher";
|
||||||
|
|
||||||
|
import { CipherRequest } from "./cipherRequest";
|
||||||
|
|
||||||
|
export class CipherWithIdRequest extends CipherRequest {
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
constructor(cipher: Cipher) {
|
||||||
|
super(cipher);
|
||||||
|
this.id = cipher.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
17
jslib/common/src/models/request/collectionRequest.ts
Normal file
17
jslib/common/src/models/request/collectionRequest.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { Collection } from "../domain/collection";
|
||||||
|
|
||||||
|
import { SelectionReadOnlyRequest } from "./selectionReadOnlyRequest";
|
||||||
|
|
||||||
|
export class CollectionRequest {
|
||||||
|
name: string;
|
||||||
|
externalId: string;
|
||||||
|
groups: SelectionReadOnlyRequest[] = [];
|
||||||
|
|
||||||
|
constructor(collection?: Collection) {
|
||||||
|
if (collection == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.name = collection.name ? collection.name.encryptedString : null;
|
||||||
|
this.externalId = collection.externalId;
|
||||||
|
}
|
||||||
|
}
|
||||||
3
jslib/common/src/models/request/deleteRecoverRequest.ts
Normal file
3
jslib/common/src/models/request/deleteRecoverRequest.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export class DeleteRecoverRequest {
|
||||||
|
email: string;
|
||||||
|
}
|
||||||
7
jslib/common/src/models/request/deviceTokenRequest.ts
Normal file
7
jslib/common/src/models/request/deviceTokenRequest.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export class DeviceTokenRequest {
|
||||||
|
pushToken: string;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.pushToken = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
7
jslib/common/src/models/request/emailRequest.ts
Normal file
7
jslib/common/src/models/request/emailRequest.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { EmailTokenRequest } from "./emailTokenRequest";
|
||||||
|
|
||||||
|
export class EmailRequest extends EmailTokenRequest {
|
||||||
|
newMasterPasswordHash: string;
|
||||||
|
token: string;
|
||||||
|
key: string;
|
||||||
|
}
|
||||||
6
jslib/common/src/models/request/emailTokenRequest.ts
Normal file
6
jslib/common/src/models/request/emailTokenRequest.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { SecretVerificationRequest } from "./secretVerificationRequest";
|
||||||
|
|
||||||
|
export class EmailTokenRequest extends SecretVerificationRequest {
|
||||||
|
newEmail: string;
|
||||||
|
masterPasswordHash: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export class EmergencyAccessAcceptRequest {
|
||||||
|
token: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export class EmergencyAccessConfirmRequest {
|
||||||
|
key: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { EmergencyAccessType } from "../../enums/emergencyAccessType";
|
||||||
|
|
||||||
|
export class EmergencyAccessInviteRequest {
|
||||||
|
email: string;
|
||||||
|
type: EmergencyAccessType;
|
||||||
|
waitTimeDays: number;
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export class EmergencyAccessPasswordRequest {
|
||||||
|
newMasterPasswordHash: string;
|
||||||
|
key: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { EmergencyAccessType } from "../../enums/emergencyAccessType";
|
||||||
|
|
||||||
|
export class EmergencyAccessUpdateRequest {
|
||||||
|
type: EmergencyAccessType;
|
||||||
|
waitTimeDays: number;
|
||||||
|
keyEncrypted?: string;
|
||||||
|
}
|
||||||
7
jslib/common/src/models/request/eventRequest.ts
Normal file
7
jslib/common/src/models/request/eventRequest.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { EventType } from "../../enums/eventType";
|
||||||
|
|
||||||
|
export class EventRequest {
|
||||||
|
type: EventType;
|
||||||
|
cipherId: string;
|
||||||
|
date: string;
|
||||||
|
}
|
||||||
9
jslib/common/src/models/request/folderRequest.ts
Normal file
9
jslib/common/src/models/request/folderRequest.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { Folder } from "../domain/folder";
|
||||||
|
|
||||||
|
export class FolderRequest {
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
constructor(folder: Folder) {
|
||||||
|
this.name = folder.name ? folder.name.encryptedString : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
12
jslib/common/src/models/request/folderWithIdRequest.ts
Normal file
12
jslib/common/src/models/request/folderWithIdRequest.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { Folder } from "../domain/folder";
|
||||||
|
|
||||||
|
import { FolderRequest } from "./folderRequest";
|
||||||
|
|
||||||
|
export class FolderWithIdRequest extends FolderRequest {
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
constructor(folder: Folder) {
|
||||||
|
super(folder);
|
||||||
|
this.id = folder.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
8
jslib/common/src/models/request/groupRequest.ts
Normal file
8
jslib/common/src/models/request/groupRequest.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { SelectionReadOnlyRequest } from "./selectionReadOnlyRequest";
|
||||||
|
|
||||||
|
export class GroupRequest {
|
||||||
|
name: string;
|
||||||
|
accessAll: boolean;
|
||||||
|
externalId: string;
|
||||||
|
collections: SelectionReadOnlyRequest[] = [];
|
||||||
|
}
|
||||||
5
jslib/common/src/models/request/iapCheckRequest.ts
Normal file
5
jslib/common/src/models/request/iapCheckRequest.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { PaymentMethodType } from "../../enums/paymentMethodType";
|
||||||
|
|
||||||
|
export class IapCheckRequest {
|
||||||
|
paymentMethodType: PaymentMethodType;
|
||||||
|
}
|
||||||
9
jslib/common/src/models/request/importCiphersRequest.ts
Normal file
9
jslib/common/src/models/request/importCiphersRequest.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { CipherRequest } from "./cipherRequest";
|
||||||
|
import { FolderRequest } from "./folderRequest";
|
||||||
|
import { KvpRequest } from "./kvpRequest";
|
||||||
|
|
||||||
|
export class ImportCiphersRequest {
|
||||||
|
ciphers: CipherRequest[] = [];
|
||||||
|
folders: FolderRequest[] = [];
|
||||||
|
folderRelationships: KvpRequest<number, number>[] = [];
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { CipherRequest } from "./cipherRequest";
|
||||||
|
import { CollectionRequest } from "./collectionRequest";
|
||||||
|
import { KvpRequest } from "./kvpRequest";
|
||||||
|
|
||||||
|
export class ImportOrganizationCiphersRequest {
|
||||||
|
ciphers: CipherRequest[] = [];
|
||||||
|
collections: CollectionRequest[] = [];
|
||||||
|
collectionRelationships: KvpRequest<number, number>[] = [];
|
||||||
|
}
|
||||||
8
jslib/common/src/models/request/kdfRequest.ts
Normal file
8
jslib/common/src/models/request/kdfRequest.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { KdfType } from "../../enums/kdfType";
|
||||||
|
|
||||||
|
import { PasswordRequest } from "./passwordRequest";
|
||||||
|
|
||||||
|
export class KdfRequest extends PasswordRequest {
|
||||||
|
kdf: KdfType;
|
||||||
|
kdfIterations: number;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
export class KeyConnectorUserKeyRequest {
|
||||||
|
key: string;
|
||||||
|
|
||||||
|
constructor(key: string) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
}
|
||||||
9
jslib/common/src/models/request/keysRequest.ts
Normal file
9
jslib/common/src/models/request/keysRequest.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export class KeysRequest {
|
||||||
|
publicKey: string;
|
||||||
|
encryptedPrivateKey: string;
|
||||||
|
|
||||||
|
constructor(publicKey: string, encryptedPrivateKey: string) {
|
||||||
|
this.publicKey = publicKey;
|
||||||
|
this.encryptedPrivateKey = encryptedPrivateKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
9
jslib/common/src/models/request/kvpRequest.ts
Normal file
9
jslib/common/src/models/request/kvpRequest.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export class KvpRequest<TK, TV> {
|
||||||
|
key: TK;
|
||||||
|
value: TV;
|
||||||
|
|
||||||
|
constructor(key: TK, value: TV) {
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { PlanSponsorshipType } from "../../../enums/planSponsorshipType";
|
||||||
|
|
||||||
|
export class OrganizationSponsorshipCreateRequest {
|
||||||
|
sponsoredEmail: string;
|
||||||
|
planSponsorshipType: PlanSponsorshipType;
|
||||||
|
friendlyName: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { PlanSponsorshipType } from "../../../enums/planSponsorshipType";
|
||||||
|
|
||||||
|
export class OrganizationSponsorshipRedeemRequest {
|
||||||
|
planSponsorshipType: PlanSponsorshipType;
|
||||||
|
sponsoredOrganizationId: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { SsoConfigApi } from "../../api/ssoConfigApi";
|
||||||
|
|
||||||
|
export class OrganizationSsoRequest {
|
||||||
|
enabled = false;
|
||||||
|
data: SsoConfigApi;
|
||||||
|
}
|
||||||
27
jslib/common/src/models/request/organizationCreateRequest.ts
Normal file
27
jslib/common/src/models/request/organizationCreateRequest.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { PaymentMethodType } from "../../enums/paymentMethodType";
|
||||||
|
import { PlanType } from "../../enums/planType";
|
||||||
|
|
||||||
|
import { OrganizationKeysRequest } from "./organizationKeysRequest";
|
||||||
|
|
||||||
|
export class OrganizationCreateRequest {
|
||||||
|
name: string;
|
||||||
|
businessName: string;
|
||||||
|
billingEmail: string;
|
||||||
|
planType: PlanType;
|
||||||
|
key: string;
|
||||||
|
keys: OrganizationKeysRequest;
|
||||||
|
paymentMethodType: PaymentMethodType;
|
||||||
|
paymentToken: string;
|
||||||
|
additionalSeats: number;
|
||||||
|
maxAutoscaleSeats: number;
|
||||||
|
additionalStorageGb: number;
|
||||||
|
premiumAccessAddon: boolean;
|
||||||
|
collectionName: string;
|
||||||
|
taxIdNumber: string;
|
||||||
|
billingAddressLine1: string;
|
||||||
|
billingAddressLine2: string;
|
||||||
|
billingAddressCity: string;
|
||||||
|
billingAddressState: string;
|
||||||
|
billingAddressPostalCode: string;
|
||||||
|
billingAddressCountry: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { KeysRequest } from "./keysRequest";
|
||||||
|
|
||||||
|
export class OrganizationKeysRequest extends KeysRequest {
|
||||||
|
constructor(publicKey: string, encryptedPrivateKey: string) {
|
||||||
|
super(publicKey, encryptedPrivateKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
export class OrganizationSubscriptionUpdateRequest {
|
||||||
|
constructor(
|
||||||
|
public seatAdjustment: number,
|
||||||
|
public maxAutoscaleSeats?: number,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { TaxInfoUpdateRequest } from "./taxInfoUpdateRequest";
|
||||||
|
|
||||||
|
export class OrganizationTaxInfoUpdateRequest extends TaxInfoUpdateRequest {
|
||||||
|
taxId: string;
|
||||||
|
line1: string;
|
||||||
|
line2: string;
|
||||||
|
city: string;
|
||||||
|
state: string;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user