mirror of
https://github.com/bitwarden/directory-connector
synced 2025-12-05 23:53:21 +00:00
Compare commits
201 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
83c521987e | ||
|
|
cd71a7a0ae | ||
|
|
c0bdb67ce9 | ||
|
|
ae8ce6643d | ||
|
|
9e131dc9c8 | ||
|
|
ebe5eaedb2 | ||
|
|
a098620b95 | ||
|
|
d222a26eb6 | ||
|
|
d50e10bb55 | ||
|
|
aca1daa58f | ||
|
|
5bd63c6d90 | ||
|
|
f71f6db0e5 | ||
|
|
8ef50234c8 | ||
|
|
caa846f065 | ||
|
|
6c553a020c | ||
|
|
3c2caf0ef5 | ||
|
|
74b7287ba7 | ||
|
|
48ee5eb4da | ||
|
|
ce80c031db | ||
|
|
0ec615e16b | ||
|
|
3a2f0988a5 | ||
|
|
de4431a559 | ||
|
|
928785493b | ||
|
|
df696ec9d3 | ||
|
|
0debaf1237 | ||
|
|
23f4ef0bd1 | ||
|
|
c8d9a6aed9 | ||
|
|
92fb2be27c | ||
|
|
3dc66d0a9a | ||
|
|
b10ee28bfe | ||
|
|
b3d25a9615 | ||
|
|
9392e513a0 | ||
|
|
57c55d7f3c | ||
|
|
7d04a0d1eb | ||
|
|
9b043c122f | ||
|
|
9a89e95918 | ||
|
|
013c8a5293 | ||
|
|
a5f779c231 | ||
|
|
dd7df6504b | ||
|
|
f064de83e8 | ||
|
|
e27bdbc561 | ||
|
|
93407d061b | ||
|
|
8848edbb40 | ||
|
|
33da38a3f3 | ||
|
|
26e4930a9e | ||
|
|
4dba787df2 | ||
|
|
2e2b5d988c | ||
|
|
d0c126cf3e | ||
|
|
8700332d13 | ||
|
|
0e4f9c0de5 | ||
|
|
c76033b8ad | ||
|
|
50cfc50ed7 | ||
|
|
739ab3d2dd | ||
|
|
1ac402ca06 | ||
|
|
a3c8629f6d | ||
|
|
161c5f82be | ||
|
|
0476c97f5f | ||
|
|
41967d6dc1 | ||
|
|
40908e4b88 | ||
|
|
9e7a11a27c | ||
|
|
a491e2691d | ||
|
|
2c65003cf9 | ||
|
|
0d78b33ae1 | ||
|
|
a3939a31a9 | ||
|
|
3540a2741e | ||
|
|
0ddf81f644 | ||
|
|
83d527a83e | ||
|
|
63b7b9124f | ||
|
|
5d85df2105 | ||
|
|
dbc3c8795d | ||
|
|
f09f7a0e51 | ||
|
|
e3afe9fb69 | ||
|
|
1a6c51b3aa | ||
|
|
107d7afb26 | ||
|
|
0959e58dc9 | ||
|
|
911f9c0dfc | ||
|
|
7cf518edb5 | ||
|
|
4234b3b1cf | ||
|
|
0f5cdd53df | ||
|
|
50bd7ca2b3 | ||
|
|
8531a64568 | ||
|
|
c1cec89995 | ||
|
|
3d214dbedc | ||
|
|
a528480e07 | ||
|
|
af5c863f1f | ||
|
|
365bda7e21 | ||
|
|
f1b533f7b6 | ||
|
|
5bf9b128d4 | ||
|
|
0a8c4d30bb | ||
|
|
1b3f277c1f | ||
|
|
8039f93434 | ||
|
|
d05e8ab7af | ||
|
|
fb3d082b88 | ||
|
|
8541a4252b | ||
|
|
e0d36a7407 | ||
|
|
73b031b884 | ||
|
|
167c5e0108 | ||
|
|
f67f113fe1 | ||
|
|
073126949b | ||
|
|
45d0192f82 | ||
|
|
2d02d54b56 | ||
|
|
8f4da6d490 | ||
|
|
7753749b62 | ||
|
|
c5cc8eab0a | ||
|
|
8981b97632 | ||
|
|
c75d26b618 | ||
|
|
13a13dd18f | ||
|
|
954b23d91f | ||
|
|
b9d35c3dc7 | ||
|
|
536f48b3c7 | ||
|
|
8cd768c7c2 | ||
|
|
b233d2e87d | ||
|
|
1f6d8c1458 | ||
|
|
ae05183aa3 | ||
|
|
8374103a15 | ||
|
|
dd9e03843a | ||
|
|
e38ce53ed5 | ||
|
|
0c21bcf847 | ||
|
|
1c6b94e640 | ||
|
|
ef1c47ab19 | ||
|
|
64ff16e895 | ||
|
|
89860d6770 | ||
|
|
91ff43a17f | ||
|
|
0f19ebc928 | ||
|
|
b48a1d5856 | ||
|
|
7776009a31 | ||
|
|
ff816035ce | ||
|
|
fe384b14f0 | ||
|
|
adeb84f44e | ||
|
|
dc2e17c5db | ||
|
|
f3d8b39ac5 | ||
|
|
3be1f2eac6 | ||
|
|
1146c8f5bf | ||
|
|
910bfb945d | ||
|
|
4e886c1c15 | ||
|
|
a4b85f1e30 | ||
|
|
7c85c9fddd | ||
|
|
68c964acaa | ||
|
|
1be64836f4 | ||
|
|
f2389189a3 | ||
|
|
bb4be6022b | ||
|
|
f85a0c5ea5 | ||
|
|
5afae04b1d | ||
|
|
d1b182d20b | ||
|
|
9e3d1caee4 | ||
|
|
9a78956b23 | ||
|
|
822655b944 | ||
|
|
6dfbe505d9 | ||
|
|
0809c2c104 | ||
|
|
e30000bd00 | ||
|
|
90a7601960 | ||
|
|
8a800c6d33 | ||
|
|
d0021c9306 | ||
|
|
97673c84da | ||
|
|
771a182235 | ||
|
|
857d725a77 | ||
|
|
25b3e0f691 | ||
|
|
d2ba7631b5 | ||
|
|
a893c78c74 | ||
|
|
5ff041aa7b | ||
|
|
096196fcd5 | ||
|
|
225073aa33 | ||
|
|
f8b26d82d8 | ||
|
|
6b98a46b94 | ||
|
|
13572b94ee | ||
|
|
999b790557 | ||
|
|
7c93d59a42 | ||
|
|
9bec2aa2f0 | ||
|
|
240e1d5813 | ||
|
|
d82f4d90c1 | ||
|
|
abc68e8ef9 | ||
|
|
660ee538ce | ||
|
|
a96144d6dc | ||
|
|
e43d192007 | ||
|
|
74a018edb8 | ||
|
|
07d0049183 | ||
|
|
5f5358ea0f | ||
|
|
36cc6552bf | ||
|
|
05b5fd2eb4 | ||
|
|
95f1e86509 | ||
|
|
378dd06274 | ||
|
|
314adeb164 | ||
|
|
cc4f8c9f8d | ||
|
|
35b0e81beb | ||
|
|
9136e3936b | ||
|
|
35aead6c0e | ||
|
|
615f3b82db | ||
|
|
baa441cb90 | ||
|
|
9ad683ca09 | ||
|
|
c2d1d12cd2 | ||
|
|
3b6bac7668 | ||
|
|
2be879548d | ||
|
|
033c346042 | ||
|
|
32a8e65fe8 | ||
|
|
b2d4d80181 | ||
|
|
56c1cb23a0 | ||
|
|
ba26f70d1a | ||
|
|
e5589e7664 | ||
|
|
4e82486784 | ||
|
|
bb1cdebaf4 | ||
|
|
01405f47c9 |
@@ -7,10 +7,9 @@ root = true
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
quote_type = single
|
||||
|
||||
# Set default charset
|
||||
[*.{js,ts,scss,html}]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
indent_size = 2
|
||||
|
||||
8
.eslintignore
Normal file
8
.eslintignore
Normal file
@@ -0,0 +1,8 @@
|
||||
dist
|
||||
build
|
||||
build-cli
|
||||
**/webpack**.config.js
|
||||
|
||||
**/node_modules
|
||||
|
||||
**/jest.config.js
|
||||
92
.eslintrc.json
Normal file
92
.eslintrc.json
Normal file
@@ -0,0 +1,92 @@
|
||||
{
|
||||
"root": true,
|
||||
"env": {
|
||||
"browser": true,
|
||||
"webextensions": true,
|
||||
"node": true
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.js"],
|
||||
"plugins": ["@typescript-eslint", "rxjs", "rxjs-angular", "import"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": ["./tsconfig.json"],
|
||||
"sourceType": "module",
|
||||
"ecmaVersion": 2020
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:import/recommended",
|
||||
"plugin:import/typescript",
|
||||
"prettier",
|
||||
"plugin:rxjs/recommended"
|
||||
],
|
||||
"settings": {
|
||||
"import/parsers": {
|
||||
"@typescript-eslint/parser": [".ts"]
|
||||
},
|
||||
"import/resolver": {
|
||||
"typescript": {
|
||||
"alwaysTryTypes": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"@typescript-eslint/explicit-member-accessibility": [
|
||||
"error",
|
||||
{ "accessibility": "no-public" }
|
||||
],
|
||||
"@typescript-eslint/no-explicit-any": "off", // TODO: This should be re-enabled
|
||||
"@typescript-eslint/no-misused-promises": ["error", { "checksVoidReturn": false }],
|
||||
"@typescript-eslint/no-this-alias": ["error", { "allowedNames": ["self"] }],
|
||||
"@typescript-eslint/no-unused-vars": ["error", { "args": "none" }],
|
||||
"no-console": "error",
|
||||
"import/no-unresolved": "off", // TODO: Look into turning off once each package is an actual package.
|
||||
"import/order": [
|
||||
"error",
|
||||
{
|
||||
"alphabetize": {
|
||||
"order": "asc"
|
||||
},
|
||||
"newlines-between": "always",
|
||||
"pathGroups": [
|
||||
{
|
||||
"pattern": "@bitwarden/**",
|
||||
"group": "external",
|
||||
"position": "after"
|
||||
},
|
||||
{
|
||||
"pattern": "src/**/*",
|
||||
"group": "parent",
|
||||
"position": "before"
|
||||
}
|
||||
],
|
||||
"pathGroupsExcludedImportTypes": ["builtin"]
|
||||
}
|
||||
],
|
||||
"rxjs-angular/prefer-takeuntil": "error",
|
||||
"rxjs/no-exposed-subjects": ["error", { "allowProtected": true }],
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
"message": "Calling `svgIcon` directly is not allowed",
|
||||
"selector": "CallExpression[callee.name='svgIcon']"
|
||||
},
|
||||
{
|
||||
"message": "Accessing FormGroup using `get` is not allowed, use `.value` instead",
|
||||
"selector": "ChainExpression[expression.object.callee.property.name='get'][expression.property.name='value']"
|
||||
}
|
||||
],
|
||||
"curly": ["error", "all"],
|
||||
"import/namespace": ["off"], // This doesn't resolve namespace imports correctly, but TS will throw for this anyway
|
||||
"no-restricted-imports": ["error", { "patterns": ["src/**/*"] }]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["*.html"],
|
||||
"parser": "@angular-eslint/template-parser"
|
||||
}
|
||||
]
|
||||
}
|
||||
2
.git-blame-ignore-revs
Normal file
2
.git-blame-ignore-revs
Normal file
@@ -0,0 +1,2 @@
|
||||
# Apply Prettier https://github.com/bitwarden/directory-connector/pull/194
|
||||
096196fcd512944d1c3d9c007647a1319b032639
|
||||
15
.github/CODEOWNERS
vendored
Normal file
15
.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
# Please sort into logical groups with comment headers. Sort groups in order of specificity.
|
||||
# For example, default owners should always be the first group.
|
||||
# Sort lines alphabetically within these groups to avoid accidentally adding duplicates.
|
||||
#
|
||||
# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
|
||||
|
||||
# Default file owners.
|
||||
* @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
|
||||
33
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
33
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
## Type of change
|
||||
|
||||
- [ ] Bug fix
|
||||
- [ ] New feature development
|
||||
- [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc)
|
||||
- [ ] Build/deploy pipeline (DevOps)
|
||||
- [ ] Other
|
||||
|
||||
## Objective
|
||||
|
||||
<!--Describe what the purpose of this PR is. For example: what bug you're fixing or what new feature you're adding-->
|
||||
|
||||
## Code changes
|
||||
|
||||
<!--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-->
|
||||
|
||||
- **file.ext:** Description of what was changed and why
|
||||
|
||||
## Screenshots
|
||||
|
||||
<!--Required for any UI changes. Delete if not applicable-->
|
||||
|
||||
## Testing requirements
|
||||
|
||||
<!--What functionality requires testing by QA? This includes testing new behavior and regression testing-->
|
||||
|
||||
## Before you submit
|
||||
|
||||
- [ ] I have checked for **linting** errors (`npm run lint`) (required)
|
||||
- [ ] I have added **unit tests** where it makes sense to do so (encouraged but not required)
|
||||
- [ ] This change requires a **documentation update** (notify the documentation team)
|
||||
- [ ] This change has particular **deployment requirements** (notify the DevOps team)
|
||||
41
.github/renovate.json
vendored
Normal file
41
.github/renovate.json
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:base",
|
||||
":combinePatchMinorReleases",
|
||||
":dependencyDashboard",
|
||||
":maintainLockFilesWeekly",
|
||||
":pinAllExceptPeerDependencies",
|
||||
":prConcurrentLimit10",
|
||||
":rebaseStalePrs",
|
||||
"schedule:weekends",
|
||||
":separateMajorReleases"
|
||||
],
|
||||
"enabledManagers": ["github-actions", "npm"],
|
||||
"packageRules": [
|
||||
{
|
||||
"groupName": "gh minor",
|
||||
"matchManagers": ["github-actions"],
|
||||
"matchUpdateTypes": ["minor", "patch"]
|
||||
},
|
||||
{
|
||||
"groupName": "npm minor",
|
||||
"matchManagers": ["npm"],
|
||||
"matchUpdateTypes": ["minor", "patch"]
|
||||
},
|
||||
{
|
||||
"packageNames": ["typescript"],
|
||||
"matchUpdateTypes": ["major", "minor"],
|
||||
"enabled": false
|
||||
},
|
||||
{
|
||||
"packageNames": ["typescript"],
|
||||
"matchUpdateTypes": "patch"
|
||||
},
|
||||
{
|
||||
"groupName": "jest",
|
||||
"packageNames": ["@types/jest", "jest", "ts-jest", "jest-preset-angular"],
|
||||
"matchUpdateTypes": "major"
|
||||
}
|
||||
]
|
||||
}
|
||||
29
.github/scripts/decrypt-secret.ps1
vendored
29
.github/scripts/decrypt-secret.ps1
vendored
@@ -1,29 +0,0 @@
|
||||
param (
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string] $filename,
|
||||
[string] $output
|
||||
)
|
||||
|
||||
$homePath = Resolve-Path "~" | Select-Object -ExpandProperty Path
|
||||
$rootPath = $env:GITHUB_WORKSPACE
|
||||
|
||||
$secretInputPath = $rootPath + "/.github/secrets"
|
||||
$input = $secretInputPath + "/" + $filename
|
||||
|
||||
$passphrase = $env:DECRYPT_FILE_PASSWORD
|
||||
$secretOutputPath = $homePath + "/secrets"
|
||||
|
||||
if ([string]::IsNullOrEmpty($output)) {
|
||||
if ($filename.EndsWith(".gpg")) {
|
||||
$output = $secretOutputPath + "/" + $filename.TrimEnd(".gpg")
|
||||
} else {
|
||||
$output = $secretOutputPath + "/" + $filename + ".plaintext"
|
||||
}
|
||||
}
|
||||
|
||||
if (!(Test-Path -Path $secretOutputPath))
|
||||
{
|
||||
New-Item -ItemType Directory -Path $secretOutputPath
|
||||
}
|
||||
|
||||
gpg --quiet --batch --yes --decrypt --passphrase="$passphrase" --output $output $input
|
||||
5
.github/scripts/load-version.ps1
vendored
5
.github/scripts/load-version.ps1
vendored
@@ -1,5 +0,0 @@
|
||||
$rootPath = $env:GITHUB_WORKSPACE;
|
||||
$packageVersion = (Get-Content -Raw -Path $rootPath\src\package.json | ConvertFrom-Json).version;
|
||||
|
||||
Write-Output "Setting package version to $packageVersion";
|
||||
Write-Output "PACKAGE_VERSION=$packageVersion" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append;
|
||||
7
.github/scripts/macos/decrypt-secrets.ps1
vendored
7
.github/scripts/macos/decrypt-secrets.ps1
vendored
@@ -1,7 +0,0 @@
|
||||
$rootPath = $env:GITHUB_WORKSPACE;
|
||||
|
||||
$decryptSecretPath = $($rootPath + "/.github/scripts/decrypt-secret.ps1");
|
||||
|
||||
Invoke-Expression "& `"$decryptSecretPath`" -filename devid-app-cert.p12.gpg"
|
||||
Invoke-Expression "& `"$decryptSecretPath`" -filename devid-installer-cert.p12.gpg"
|
||||
Invoke-Expression "& `"$decryptSecretPath`" -filename macdev-cert.p12.gpg"
|
||||
15
.github/scripts/macos/setup-keychain.ps1
vendored
15
.github/scripts/macos/setup-keychain.ps1
vendored
@@ -1,15 +0,0 @@
|
||||
$homePath = Resolve-Path "~" | Select-Object -ExpandProperty Path;
|
||||
$secretsPath = $homePath + "/secrets"
|
||||
|
||||
$devidAppCertPath = $($secretsPath + "/devid-app-cert.p12");
|
||||
$devidInstallerCertPath = $($secretsPath + "/devid-installer-cert.p12");
|
||||
$macdevCertPath = $($secretsPath + "/macdev-cert.p12");
|
||||
|
||||
security create-keychain -p $env:KEYCHAIN_PASSWORD build.keychain
|
||||
security default-keychain -s build.keychain
|
||||
security unlock-keychain -p $env:KEYCHAIN_PASSWORD build.keychain
|
||||
security set-keychain-settings -lut 1200 build.keychain
|
||||
security import $devidAppCertPath -k build.keychain -P $env:DEVID_CERT_PASSWORD -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
|
||||
security import $devidInstallerCertPath -k build.keychain -P $env:DEVID_CERT_PASSWORD -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
|
||||
security import $macdevCertPath -k build.keychain -P $env:MACDEV_CERT_PASSWORD -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
|
||||
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $env:KEYCHAIN_PASSWORD build.keychain
|
||||
686
.github/workflows/build.yml
vendored
686
.github/workflows/build.yml
vendored
@@ -1,52 +1,241 @@
|
||||
---
|
||||
name: Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches-ignore:
|
||||
- 'l10n_master'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
paths-ignore:
|
||||
- '.github/workflows/**'
|
||||
workflow_dispatch: {}
|
||||
|
||||
|
||||
jobs:
|
||||
cloc:
|
||||
runs-on: ubuntu-latest
|
||||
name: CLOC
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
|
||||
- name: Set up cloc
|
||||
- name: Set up CLOC
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt -y install cloc
|
||||
|
||||
- name: Print lines of code
|
||||
run: cloc --include-lang TypeScript,JavaScript,HTML,Sass,CSS --vcs git
|
||||
|
||||
|
||||
setup:
|
||||
runs-on: ubuntu-latest
|
||||
name: Setup
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
package_version: ${{ steps.get_version.outputs.package_version }}
|
||||
package_version: ${{ steps.retrieve-version.outputs.package_version }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
|
||||
- name: Get Package Version
|
||||
id: get_version
|
||||
shell: pwsh
|
||||
id: retrieve-version
|
||||
run: |
|
||||
$env:pkgVersion = (Get-Content -Raw -Path ./src/package.json | ConvertFrom-Json).version
|
||||
echo "::set-output name=PACKAGE_VERSION::$env:pkgVersion"
|
||||
PKG_VERSION=$(jq -r .version package.json)
|
||||
echo "package_version=$PKG_VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
|
||||
cli:
|
||||
runs-on: windows-latest
|
||||
linux-cli:
|
||||
name: Build Linux CLI
|
||||
runs-on: ubuntu-22.04
|
||||
needs: setup
|
||||
env:
|
||||
PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||
_PKG_FETCH_NODE_VERSION: 18.5.0
|
||||
_PKG_FETCH_VERSION: 3.4
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
node-version: '18'
|
||||
|
||||
- name: Update NPM
|
||||
run: |
|
||||
npm install -g node-gyp
|
||||
node-gyp install $(node -v)
|
||||
|
||||
- name: Get pkg-fetch
|
||||
run: |
|
||||
cd $HOME
|
||||
fetchedUrl="https://github.com/vercel/pkg-fetch/releases/download/v$_PKG_FETCH_VERSION/node-v$_PKG_FETCH_NODE_VERSION-linux-x64"
|
||||
|
||||
mkdir -p .pkg-cache/v$_PKG_FETCH_VERSION
|
||||
wget $fetchedUrl -O "./.pkg-cache/v$_PKG_FETCH_VERSION/fetched-v$_PKG_FETCH_NODE_VERSION-linux-x64"
|
||||
|
||||
- name: Keytar
|
||||
run: |
|
||||
keytarVersion=$(cat package.json | jq -r '.dependencies.keytar')
|
||||
keytarTar="keytar-v$keytarVersion-napi-v3-linux-x64.tar"
|
||||
|
||||
keytarTarGz="$keytarTar.gz"
|
||||
keytarUrl="https://github.com/atom/node-keytar/releases/download/v$keytarVersion/$keytarTarGz"
|
||||
|
||||
mkdir -p ./keytar/linux
|
||||
wget $keytarUrl -O ./keytar/linux/$keytarTarGz
|
||||
tar -xvf ./keytar/linux/$keytarTarGz -C ./keytar/linux
|
||||
|
||||
- name: Install
|
||||
run: npm install
|
||||
|
||||
- name: Package CLI
|
||||
run: npm run dist:cli:lin
|
||||
|
||||
- name: Zip
|
||||
run: zip -j dist-cli/bwdc-linux-$_PACKAGE_VERSION.zip dist-cli/linux/bwdc keytar/linux/build/Release/keytar.node
|
||||
|
||||
- name: Create checksums
|
||||
run: |
|
||||
shasum -a 256 dist-cli/bwdc-linux-$_PACKAGE_VERSION.zip | \
|
||||
cut -d " " -f 1 > dist-cli/bwdc-linux-sha256-$_PACKAGE_VERSION.txt
|
||||
|
||||
- name: Version Test
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt install libsecret-1-0 dbus-x11 gnome-keyring
|
||||
eval $(dbus-launch --sh-syntax)
|
||||
|
||||
eval $(echo -n "" | /usr/bin/gnome-keyring-daemon --login)
|
||||
eval $(/usr/bin/gnome-keyring-daemon --components=secrets --start)
|
||||
|
||||
mkdir -p test/linux
|
||||
unzip ./dist-cli/bwdc-linux-$_PACKAGE_VERSION.zip -d ./test/linux
|
||||
|
||||
testVersion=$(./test/linux/bwdc -v)
|
||||
|
||||
echo "version: $_PACKAGE_VERSION"
|
||||
echo "testVersion: $testVersion"
|
||||
|
||||
if [ "$testVersion" != "$_PACKAGE_VERSION" ]; then
|
||||
echo "Version test failed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Upload Linux Zip to GitHub
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: bwdc-linux-${{ env._PACKAGE_VERSION }}.zip
|
||||
path: ./dist-cli/bwdc-linux-${{ env._PACKAGE_VERSION }}.zip
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload Linux checksum to GitHub
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: bwdc-linux-sha256-${{ env._PACKAGE_VERSION }}.txt
|
||||
path: ./dist-cli/bwdc-linux-sha256-${{ env._PACKAGE_VERSION }}.txt
|
||||
if-no-files-found: error
|
||||
|
||||
|
||||
macos-cli:
|
||||
name: Build Mac CLI
|
||||
runs-on: macos-12
|
||||
needs: setup
|
||||
env:
|
||||
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||
_PKG_FETCH_NODE_VERSION: 18.5.0
|
||||
_PKG_FETCH_VERSION: 3.4
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
node-version: '18'
|
||||
|
||||
- name: Update NPM
|
||||
run: |
|
||||
npm install -g node-gyp
|
||||
node-gyp install $(node -v)
|
||||
|
||||
- name: Get pkg-fetch
|
||||
run: |
|
||||
cd $HOME
|
||||
fetchedUrl="https://github.com/vercel/pkg-fetch/releases/download/v$_PKG_FETCH_VERSION/node-v$_PKG_FETCH_NODE_VERSION-macos-x64"
|
||||
|
||||
mkdir -p .pkg-cache/v$_PKG_FETCH_VERSION
|
||||
wget $fetchedUrl -O "./.pkg-cache/v$_PKG_FETCH_VERSION/fetched-v$_PKG_FETCH_NODE_VERSION-macos-x64"
|
||||
|
||||
- name: Keytar
|
||||
run: |
|
||||
keytarVersion=$(cat package.json | jq -r '.dependencies.keytar')
|
||||
keytarTar="keytar-v$keytarVersion-napi-v3-darwin-x64.tar"
|
||||
|
||||
keytarTarGz="$keytarTar.gz"
|
||||
keytarUrl="https://github.com/atom/node-keytar/releases/download/v$keytarVersion/$keytarTarGz"
|
||||
|
||||
mkdir -p ./keytar/macos
|
||||
wget $keytarUrl -O ./keytar/macos/$keytarTarGz
|
||||
tar -xvf ./keytar/macos/$keytarTarGz -C ./keytar/macos
|
||||
|
||||
- name: Install
|
||||
run: npm install
|
||||
|
||||
- name: Package CLI
|
||||
run: npm run dist:cli:mac
|
||||
|
||||
- name: Zip
|
||||
run: zip -j dist-cli/bwdc-macos-$_PACKAGE_VERSION.zip dist-cli/macos/bwdc keytar/macos/build/Release/keytar.node
|
||||
|
||||
- name: Create checksums
|
||||
run: |
|
||||
shasum -a 256 dist-cli/bwdc-macos-$_PACKAGE_VERSION.zip | \
|
||||
cut -d " " -f 1 > dist-cli/bwdc-macos-sha256-$_PACKAGE_VERSION.txt
|
||||
|
||||
- name: Version Test
|
||||
run: |
|
||||
mkdir -p test/macos
|
||||
unzip ./dist-cli/bwdc-macos-$_PACKAGE_VERSION.zip -d ./test/macos
|
||||
|
||||
testVersion=$(./test/macos/bwdc -v)
|
||||
|
||||
echo "version: $_PACKAGE_VERSION"
|
||||
echo "testVersion: $testVersion"
|
||||
|
||||
if [ "$testVersion" != "$_PACKAGE_VERSION" ]; then
|
||||
echo "Version test failed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Upload Mac Zip to GitHub
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: bwdc-macos-${{ env._PACKAGE_VERSION }}.zip
|
||||
path: ./dist-cli/bwdc-macos-${{ env._PACKAGE_VERSION }}.zip
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload Mac checksum to GitHub
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: bwdc-macos-sha256-${{ env._PACKAGE_VERSION }}.txt
|
||||
path: ./dist-cli/bwdc-macos-sha256-${{ env._PACKAGE_VERSION }}.txt
|
||||
if-no-files-found: error
|
||||
|
||||
windows-cli:
|
||||
name: Build Windows CLI
|
||||
runs-on: windows-2022
|
||||
needs: setup
|
||||
env:
|
||||
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||
_WIN_PKG_FETCH_VERSION: 18.5.0
|
||||
_WIN_PKG_VERSION: 3.4
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
|
||||
- name: Setup Windows builder
|
||||
run: |
|
||||
@@ -54,68 +243,88 @@ jobs:
|
||||
choco install reshack --no-progress
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea
|
||||
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
|
||||
with:
|
||||
node-version: '14.x'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
node-version: '18'
|
||||
|
||||
- name: Update NPM
|
||||
run: |
|
||||
npm install -g npm@7
|
||||
npm install -g node-gyp
|
||||
node-gyp install $(node -v)
|
||||
|
||||
- name: Setting WIN_PKG
|
||||
run: |
|
||||
echo "WIN_PKG=$env:WIN_PKG" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
echo "version: $env:pkgVersion"
|
||||
env:
|
||||
WIN_PKG: C:\Users\runneradmin\.pkg-cache\v3.0\fetched-v14.16.1-win-x64
|
||||
|
||||
- name: get pkg-fetch
|
||||
- name: Get pkg-fetch
|
||||
shell: pwsh
|
||||
run: |
|
||||
cd $HOME
|
||||
$fetchedUrl = "https://github.com/vercel/pkg-fetch/releases/download/v3.0/node-v14.16.1-win-x64"
|
||||
$fetchedUrl = "https://github.com/vercel/pkg-fetch/releases/download/v$env:_WIN_PKG_VERSION/node-v$env:_WIN_PKG_FETCH_VERSION-win-x64"
|
||||
|
||||
New-Item -ItemType directory -Path ./.pkg-cache
|
||||
New-Item -ItemType directory -Path ./.pkg-cache/v3.0
|
||||
Invoke-RestMethod -Uri $fetchedUrl -OutFile "./.pkg-cache/v3.0/fetched-v14.16.1-win-x64"
|
||||
env:
|
||||
WIN_PKG: C:\Users\runneradmin\.pkg-cache\v3.0\fetched-v14.16.1-win-x64
|
||||
New-Item -ItemType directory -Path ./.pkg-cache/v$env:_WIN_PKG_VERSION
|
||||
Invoke-RestMethod -Uri $fetchedUrl `
|
||||
-OutFile "./.pkg-cache/v$env:_WIN_PKG_VERSION/fetched-v$env:_WIN_PKG_FETCH_VERSION-win-x64"
|
||||
|
||||
- name: Keytar
|
||||
shell: pwsh
|
||||
run: |
|
||||
$keytarVersion = (Get-Content -Raw -Path ./src/package.json | ConvertFrom-Json).dependencies.keytar
|
||||
$nodeModVersion = node -e "console.log(process.config.variables.node_module_version)"
|
||||
$keytarTar = "keytar-v${keytarVersion}-node-v${nodeModVersion}-{0}-x64.tar"
|
||||
$keytarVersion = (Get-Content -Raw -Path ./package.json | ConvertFrom-Json).dependencies.keytar
|
||||
$keytarTar = "keytar-v${keytarVersion}-napi-v3-{0}-x64.tar"
|
||||
$keytarTarGz = "${keytarTar}.gz"
|
||||
$keytarUrl = "https://github.com/atom/node-keytar/releases/download/v${keytarVersion}/${keytarTarGz}"
|
||||
|
||||
New-Item -ItemType directory -Path ./keytar/macos | Out-Null
|
||||
New-Item -ItemType directory -Path ./keytar/linux | Out-Null
|
||||
New-Item -ItemType directory -Path ./keytar/windows | Out-Null
|
||||
|
||||
Invoke-RestMethod -Uri $($keytarUrl -f "darwin") -OutFile "./keytar/macos/$($keytarTarGz -f "darwin")"
|
||||
Invoke-RestMethod -Uri $($keytarUrl -f "linux") -OutFile "./keytar/linux/$($keytarTarGz -f "linux")"
|
||||
Invoke-RestMethod -Uri $($keytarUrl -f "win32") -OutFile "./keytar/windows/$($keytarTarGz -f "win32")"
|
||||
|
||||
7z e "./keytar/macos/$($keytarTarGz -f "darwin")" -o"./keytar/macos"
|
||||
7z e "./keytar/linux/$($keytarTarGz -f "linux")" -o"./keytar/linux"
|
||||
7z e "./keytar/windows/$($keytarTarGz -f "win32")" -o"./keytar/windows"
|
||||
|
||||
7z e "./keytar/macos/$($keytarTar -f "darwin")" -o"./keytar/macos"
|
||||
7z e "./keytar/linux/$($keytarTar -f "linux")" -o"./keytar/linux"
|
||||
7z e "./keytar/windows/$($keytarTar -f "win32")" -o"./keytar/windows"
|
||||
|
||||
- name: Setup Version Info
|
||||
shell: pwsh
|
||||
run: ./scripts/make-versioninfo.ps1
|
||||
run: |
|
||||
$major, $minor, $patch = $env:_PACKAGE_VERSION.split('.')
|
||||
|
||||
$versionInfo = @"
|
||||
|
||||
1 VERSIONINFO
|
||||
FILEVERSION $major,$minor,$patch,0
|
||||
PRODUCTVERSION $major,$minor,$patch,0
|
||||
FILEOS 0x40004
|
||||
FILETYPE 0x1
|
||||
{
|
||||
BLOCK "StringFileInfo"
|
||||
{
|
||||
BLOCK "040904b0"
|
||||
{
|
||||
VALUE "CompanyName", "Bitwarden Inc."
|
||||
VALUE "ProductName", "Bitwarden"
|
||||
VALUE "FileDescription", "Bitwarden Directory Connector CLI"
|
||||
VALUE "FileVersion", "$env:_PACKAGE_VERSION"
|
||||
VALUE "ProductVersion", "$env:_PACKAGE_VERSION"
|
||||
VALUE "OriginalFilename", "bwdc.exe"
|
||||
VALUE "InternalName", "bwdc"
|
||||
VALUE "LegalCopyright", "Copyright Bitwarden Inc."
|
||||
}
|
||||
}
|
||||
|
||||
BLOCK "VarFileInfo"
|
||||
{
|
||||
VALUE "Translation", 0x0409 0x04B0
|
||||
}
|
||||
}
|
||||
"@
|
||||
|
||||
$versionInfo | Out-File ./version-info.rc
|
||||
|
||||
- name: Resource Hacker
|
||||
shell: cmd
|
||||
run: |
|
||||
set PATH=%PATH%;C:\Program Files (x86)\Resource Hacker
|
||||
set WIN_PKG=C:\Users\runneradmin\.pkg-cache\v%_WIN_PKG_VERSION%\fetched-v%_WIN_PKG_FETCH_VERSION%-win-x64
|
||||
set WIN_PKG_BUILT=C:\Users\runneradmin\.pkg-cache\v%_WIN_PKG_VERSION%\built-v%_WIN_PKG_FETCH_VERSION%-win-x64
|
||||
|
||||
ResourceHacker -open %WIN_PKG% -save %WIN_PKG% -action delete -mask ICONGROUP,1,
|
||||
ResourceHacker -open version-info.rc -save version-info.res -action compile
|
||||
ResourceHacker -open %WIN_PKG% -save %WIN_PKG% -action addoverwrite -resource version-info.res
|
||||
@@ -124,138 +333,79 @@ jobs:
|
||||
run: npm install
|
||||
|
||||
- name: Package CLI
|
||||
run: npm run dist:cli
|
||||
run: npm run dist:cli:win
|
||||
|
||||
- name: Zip
|
||||
shell: cmd
|
||||
run: |
|
||||
7z a ./dist-cli/bwdc-windows-%PACKAGE_VERSION%.zip ./dist-cli/windows/bwdc.exe ./keytar/windows/keytar.node
|
||||
7z a ./dist-cli/bwdc-macos-%PACKAGE_VERSION%.zip ./dist-cli/macos/bwdc ./keytar/macos/keytar.node
|
||||
7z a ./dist-cli/bwdc-linux-%PACKAGE_VERSION%.zip ./dist-cli/linux/bwdc ./keytar/linux/keytar.node
|
||||
7z a .\dist-cli\bwdc-windows-%_PACKAGE_VERSION%.zip .\dist-cli\windows\bwdc.exe .\keytar\windows\keytar.node
|
||||
|
||||
- name: Version Test
|
||||
shell: pwsh
|
||||
run: |
|
||||
Expand-Archive -Path "./dist-cli/bwdc-windows-${env:PACKAGE_VERSION}.zip" -DestinationPath "./test/windows"
|
||||
$testVersion = Invoke-Expression '& ./test/windows/bwdc.exe -v'
|
||||
echo "version: $env:PACKAGE_VERSION"
|
||||
Expand-Archive -Path "dist-cli\bwdc-windows-${{ env._PACKAGE_VERSION }}.zip" -DestinationPath "test\windows"
|
||||
$testVersion = Invoke-Expression '& .\test\windows\bwdc.exe -v'
|
||||
echo "version: ${env:_PACKAGE_VERSION}"
|
||||
echo "testVersion: $testVersion"
|
||||
if($testVersion -ne $env:PACKAGE_VERSION) {
|
||||
if ($testVersion -ne ${env:_PACKAGE_VERSION}) {
|
||||
Throw "Version test failed."
|
||||
}
|
||||
|
||||
- name: Create checksums
|
||||
run: |
|
||||
checksum -f="./dist-cli/bwdc-windows-${env:PACKAGE_VERSION}.zip" `
|
||||
-t sha256 | Out-File ./dist-cli/bwdc-windows-sha256-${env:PACKAGE_VERSION}.txt
|
||||
checksum -f="./dist-cli/bwdc-macos-${env:PACKAGE_VERSION}.zip" `
|
||||
-t sha256 | Out-File ./dist-cli/bwdc-macos-sha256-${env:PACKAGE_VERSION}.txt
|
||||
checksum -f="./dist-cli/bwdc-linux-${env:PACKAGE_VERSION}.zip" `
|
||||
-t sha256 | Out-File ./dist-cli/bwdc-linux-sha256-${env:PACKAGE_VERSION}.txt
|
||||
checksum -f="./dist-cli/bwdc-windows-${env:_PACKAGE_VERSION}.zip" `
|
||||
-t sha256 | Out-File ./dist-cli/bwdc-windows-sha256-${env:_PACKAGE_VERSION}.txt
|
||||
|
||||
- name: Upload windows zip to GitHub
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc'
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
|
||||
- name: Upload Windows Zip to GitHub
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: bwdc-windows-${{ env.PACKAGE_VERSION }}.zip
|
||||
path: ./dist-cli/bwdc-windows-${{ env.PACKAGE_VERSION }}.zip
|
||||
name: bwdc-windows-${{ env._PACKAGE_VERSION }}.zip
|
||||
path: ./dist-cli/bwdc-windows-${{ env._PACKAGE_VERSION }}.zip
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload mac zip to GitHub
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc'
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
|
||||
- name: Upload Windows checksum to GitHub
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: bwdc-macos-${{ env.PACKAGE_VERSION }}.zip
|
||||
path: ./dist-cli/bwdc-macos-${{ env.PACKAGE_VERSION }}.zip
|
||||
|
||||
- name: Upload linux zip to GitHub
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc'
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
|
||||
with:
|
||||
name: bwdc-linux-${{ env.PACKAGE_VERSION }}.zip
|
||||
path: ./dist-cli/bwdc-linux-${{ env.PACKAGE_VERSION }}.zip
|
||||
|
||||
- name: Upload windows checksum to GitHub
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc'
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
|
||||
with:
|
||||
name: bwdc-windows-sha256-${{ env.PACKAGE_VERSION }}.txt
|
||||
path: ./dist-cli/bwdc-windows-sha256-${{ env.PACKAGE_VERSION }}.txt
|
||||
|
||||
- name: Upload mac checksum to GitHub
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc'
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
|
||||
with:
|
||||
name: bwdc-macos-sha256-${{ env.PACKAGE_VERSION }}.txt
|
||||
path: ./dist-cli/bwdc-macos-sha256-${{ env.PACKAGE_VERSION }}.txt
|
||||
|
||||
- name: Upload linux checksum to GitHub
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc'
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
|
||||
with:
|
||||
name: bwdc-linux-sha256-${{ env.PACKAGE_VERSION }}.txt
|
||||
path: ./dist-cli/bwdc-linux-sha256-${{ env.PACKAGE_VERSION }}.txt
|
||||
name: bwdc-windows-sha256-${{ env._PACKAGE_VERSION }}.txt
|
||||
path: ./dist-cli/bwdc-windows-sha256-${{ env._PACKAGE_VERSION }}.txt
|
||||
if-no-files-found: error
|
||||
|
||||
|
||||
windows_gui:
|
||||
runs-on: windows-latest
|
||||
windows-gui:
|
||||
name: Build Windows GUI
|
||||
runs-on: windows-2022
|
||||
needs: setup
|
||||
env:
|
||||
PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||
NODE_OPTIONS: --max_old_space_size=4096
|
||||
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||
HUSKY: 0
|
||||
steps:
|
||||
- name: Set up dotnet
|
||||
uses: actions/setup-dotnet@a71d1eb2c86af85faa8c772c03fb365e377e45ea
|
||||
with:
|
||||
dotnet-version: "3.1.x"
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea
|
||||
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
|
||||
with:
|
||||
node-version: '14.x'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
node-version: '18'
|
||||
|
||||
- name: Update NPM
|
||||
run: |
|
||||
npm install -g npm@7
|
||||
npm install -g node-gyp
|
||||
node-gyp install $(node -v)
|
||||
|
||||
- name: Set Node options
|
||||
run: echo "NODE_OPTIONS=--max_old_space_size=4096" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
shell: pwsh
|
||||
|
||||
- name: Print environment
|
||||
run: |
|
||||
node --version
|
||||
npm --version
|
||||
dotnet --version
|
||||
|
||||
- name: Install AST
|
||||
shell: pwsh
|
||||
run: |
|
||||
cd $HOME
|
||||
|
||||
git clone https://github.com/vcsjones/AzureSignTool.git
|
||||
cd AzureSignTool
|
||||
$latest_head = $(git rev-parse HEAD)[0..9] -join ""
|
||||
$latest_version = "0.0.0-g$latest_head"
|
||||
|
||||
Write-Host "--------"
|
||||
Write-Host "git commit - $(git rev-parse HEAD)"
|
||||
Write-Host "latest_head - $latest_head"
|
||||
Write-Host "PACKAGE VERSION TO BUILD - $latest_version"
|
||||
Write-Host "--------"
|
||||
|
||||
dotnet restore
|
||||
dotnet pack --output ./nupkg
|
||||
dotnet tool install --global --ignore-failed-sources --add-source ./nupkg --version $latest_version azuresigntool
|
||||
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
||||
run: dotnet tool install --global AzureSignTool --version 4.0.1
|
||||
|
||||
- name: Install Node dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Run linter
|
||||
run: npm run lint
|
||||
|
||||
- name: Build & Sign
|
||||
run: npm run dist:win
|
||||
env:
|
||||
@@ -266,149 +416,267 @@ jobs:
|
||||
SIGNING_CLIENT_SECRET: ${{ secrets.SIGNING_CLIENT_SECRET }}
|
||||
SIGNING_CERT_NAME: ${{ secrets.SIGNING_CERT_NAME }}
|
||||
|
||||
- name: List Dist
|
||||
run: dir ./dist
|
||||
|
||||
- name: Publish Portable Exe to GitHub
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc'
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
|
||||
- name: Upload Portable Executable to GitHub
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: Bitwarden-Connector-Portable-${{ env.PACKAGE_VERSION }}.exe
|
||||
path: ./dist/Bitwarden-Connector-Portable-${{ env.PACKAGE_VERSION }}.exe
|
||||
name: Bitwarden-Connector-Portable-${{ env._PACKAGE_VERSION }}.exe
|
||||
path: ./dist/Bitwarden-Connector-Portable-${{ env._PACKAGE_VERSION }}.exe
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Publish Installer Exe to GitHub
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc'
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
|
||||
- name: Upload Installer Executable to GitHub
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: Bitwarden-Connector-Installer-${{ env.PACKAGE_VERSION }}.exe
|
||||
path: ./dist/Bitwarden-Connector-Installer-${{ env.PACKAGE_VERSION }}.exe
|
||||
name: Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe
|
||||
path: ./dist/Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload Installer Executable Blockmap to GitHub
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe.blockmap
|
||||
path: ./dist/Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe.blockmap
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload latest auto-update artifact
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: latest.yml
|
||||
path: ./dist/latest.yml
|
||||
if-no-files-found: error
|
||||
|
||||
|
||||
linux:
|
||||
runs-on: ubuntu-latest
|
||||
linux-gui:
|
||||
name: Build Linux GUI
|
||||
runs-on: ubuntu-22.04
|
||||
needs: setup
|
||||
env:
|
||||
PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||
NODE_OPTIONS: --max_old_space_size=4096
|
||||
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||
HUSKY: 0
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea
|
||||
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
|
||||
with:
|
||||
node-version: '14.x'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
node-version: '18'
|
||||
|
||||
- name: Update NPM
|
||||
run: |
|
||||
npm install -g npm@7
|
||||
npm install -g node-gyp
|
||||
node-gyp install $(node -v)
|
||||
|
||||
- name: Set Node options
|
||||
run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV
|
||||
|
||||
- name: Set up environment
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install pkg-config libxss-dev libsecret-1-dev
|
||||
sudo apt-get -y install pkg-config libxss-dev libsecret-1-dev
|
||||
sudo apt-get -y install rpm
|
||||
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
||||
|
||||
- name: npm install
|
||||
- name: NPM Install
|
||||
run: npm install
|
||||
|
||||
- name: npm rebuild
|
||||
- name: NPM Rebuild
|
||||
run: npm run rebuild
|
||||
|
||||
- name: npm package
|
||||
- name: NPM Package
|
||||
run: npm run dist:lin
|
||||
|
||||
- name: Publish AppImage
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc'
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
|
||||
- name: Upload AppImage
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: Bitwarden-Connector-${{ env.PACKAGE_VERSION }}-x86_64.AppImage
|
||||
path: ./dist/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
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload latest auto-update artifact
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: latest-linux.yml
|
||||
path: ./dist/latest-linux.yml
|
||||
if-no-files-found: error
|
||||
|
||||
|
||||
macos:
|
||||
runs-on: macos-latest
|
||||
macos-gui:
|
||||
name: Build MacOS GUI
|
||||
runs-on: macos-12
|
||||
needs: setup
|
||||
env:
|
||||
PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||
NODE_OPTIONS: --max_old_space_size=4096
|
||||
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||
HUSKY: 0
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea
|
||||
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
|
||||
with:
|
||||
node-version: '14.x'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
node-version: '18'
|
||||
|
||||
- name: Update NPM
|
||||
run: |
|
||||
npm install -g npm@7
|
||||
npm install -g node-gyp
|
||||
node-gyp install $(node -v)
|
||||
|
||||
- name: Set Node options
|
||||
run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV
|
||||
|
||||
- name: Print environment
|
||||
run: |
|
||||
node --version
|
||||
npm --version
|
||||
Write-Output "GitHub ref: $env:GITHUB_REF"
|
||||
Write-Output "GitHub event: $env:GITHUB_EVENT"
|
||||
shell: pwsh
|
||||
env:
|
||||
GITHUB_REF: ${{ github.ref }}
|
||||
GITHUB_EVENT: ${{ github.event_name }}
|
||||
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
||||
echo "GitHub ref: $GITHUB_REF"
|
||||
echo "GitHub event: $GITHUB_EVENT"
|
||||
shell: bash
|
||||
|
||||
- name: Decrypt secrets
|
||||
run: ./.github/scripts/macos/decrypt-secrets.ps1
|
||||
shell: pwsh
|
||||
env:
|
||||
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }}
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p $HOME/secrets
|
||||
|
||||
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||
--output "$HOME/secrets/devid-app-cert.p12" \
|
||||
"$GITHUB_WORKSPACE/.github/secrets/devid-app-cert.p12.gpg"
|
||||
|
||||
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||
--output "$HOME/secrets/devid-installer-cert.p12" \
|
||||
"$GITHUB_WORKSPACE/.github/secrets/devid-installer-cert.p12.gpg"
|
||||
|
||||
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||
--output "$HOME/secrets/macdev-cert.p12" \
|
||||
"$GITHUB_WORKSPACE/.github/secrets/macdev-cert.p12.gpg"
|
||||
|
||||
- name: Set up keychain
|
||||
run: ./.github/scripts/macos/setup-keychain.ps1
|
||||
shell: pwsh
|
||||
env:
|
||||
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
||||
DEVID_CERT_PASSWORD: ${{ secrets.DEVID_CERT_PASSWORD }}
|
||||
MACDEV_CERT_PASSWORD: ${{ secrets.MACDEV_CERT_PASSWORD }}
|
||||
shell: bash
|
||||
run: |
|
||||
security create-keychain -p $KEYCHAIN_PASSWORD build.keychain
|
||||
security default-keychain -s build.keychain
|
||||
security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain
|
||||
security set-keychain-settings -lut 1200 build.keychain
|
||||
security import "$HOME/secrets/devid-app-cert.p12" -k build.keychain -P $DEVID_CERT_PASSWORD \
|
||||
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
|
||||
security import "$HOME/secrets/devid-installer-cert.p12" -k build.keychain -P $DEVID_CERT_PASSWORD \
|
||||
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
|
||||
security import "$HOME/secrets/macdev-cert.p12" -k build.keychain -P $MACDEV_CERT_PASSWORD \
|
||||
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
|
||||
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain
|
||||
|
||||
- name: Load package version
|
||||
run: ./.github/scripts/load-version.ps1
|
||||
run: |
|
||||
$rootPath = $env:GITHUB_WORKSPACE;
|
||||
$packageVersion = (Get-Content -Raw -Path $rootPath\package.json | ConvertFrom-Json).version;
|
||||
|
||||
Write-Output "Setting package version to $packageVersion";
|
||||
Write-Output "PACKAGE_VERSION=$packageVersion" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append;
|
||||
shell: pwsh
|
||||
|
||||
- name: Install Node dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Run linter
|
||||
run: npm run lint
|
||||
|
||||
- name: Build application (dev)
|
||||
if: github.ref != 'refs/heads/master'
|
||||
run: npm run build
|
||||
|
||||
- name: Build application (dist)
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc'
|
||||
- name: Build application
|
||||
run: npm run dist:mac
|
||||
env:
|
||||
APPLE_ID_USERNAME: ${{ secrets.APPLE_ID_USERNAME }}
|
||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||
|
||||
- name: Upload .zip artifact
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc'
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: Bitwarden-Connector-${{ env.PACKAGE_VERSION }}-mac.zip
|
||||
path: ./dist/Bitwarden-Connector-${{ env.PACKAGE_VERSION }}-mac.zip
|
||||
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-mac.zip
|
||||
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-mac.zip
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload .dmg artifact
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc'
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: Bitwarden-Connector-${{ env.PACKAGE_VERSION }}.dmg
|
||||
path: ./dist/Bitwarden-Connector-${{ env.PACKAGE_VERSION }}.dmg
|
||||
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg
|
||||
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload .dmg Blockmap artifact
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg.blockmap
|
||||
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg.blockmap
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload latest auto-update artifact
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: latest-mac.yml
|
||||
path: ./dist/latest-mac.yml
|
||||
if-no-files-found: error
|
||||
|
||||
|
||||
check-failures:
|
||||
name: Check for failures
|
||||
runs-on: ubuntu-22.04
|
||||
needs:
|
||||
- cloc
|
||||
- setup
|
||||
- linux-cli
|
||||
- macos-cli
|
||||
- windows-cli
|
||||
- windows-gui
|
||||
- linux-gui
|
||||
- macos-gui
|
||||
steps:
|
||||
- name: Check if any job failed
|
||||
if: ${{ (github.ref == 'refs/heads/master') || (github.ref == 'refs/heads/rc') }}
|
||||
env:
|
||||
CLOC_STATUS: ${{ needs.cloc.result }}
|
||||
SETUP_STATUS: ${{ needs.setup.result }}
|
||||
LINUX_CLI_STATUS: ${{ needs.linux-cli.result }}
|
||||
MACOS_CLI_STATUS: ${{ needs.macos-cli.result }}
|
||||
WINDOWS_CLI_STATUS: ${{ needs.windows-cli.result }}
|
||||
WINDOWS_GUI_STATUS: ${{ needs.windows-gui.result }}
|
||||
LINUX_GUI_STATUS: ${{ needs.linux-gui.result }}
|
||||
MACOS_GUI_STATUS: ${{ needs.macos-gui.result }}
|
||||
run: |
|
||||
if [ "$CLOC_STATUS" = "failure" ]; then
|
||||
exit 1
|
||||
elif [ "$SETUP_STATUS" = "failure" ]; then
|
||||
exit 1
|
||||
elif [ "$LINUX_CLI_STATUS" = "failure" ]; then
|
||||
exit 1
|
||||
elif [ "$MACOS_CLI_STATUS" = "failure" ]; then
|
||||
exit 1
|
||||
elif [ "$WINDOWS_CLI_STATUS" = "failure" ]; then
|
||||
exit 1
|
||||
elif [ "$WINDOWS_GUI_STATUS" = "failure" ]; then
|
||||
exit 1
|
||||
elif [ "$LINUX_GUI_STATUS" = "failure" ]; then
|
||||
exit 1
|
||||
elif [ "$MACOS_GUI_STATUS" = "failure" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Login to Azure - CI subscription
|
||||
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
|
||||
if: failure()
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
||||
|
||||
- name: Retrieve secrets
|
||||
id: retrieve-secrets
|
||||
uses: bitwarden/gh-actions/get-keyvault-secrets@main
|
||||
if: failure()
|
||||
with:
|
||||
keyvault: "bitwarden-ci"
|
||||
secrets: "devops-alerts-slack-webhook-url"
|
||||
|
||||
- name: Notify Slack on failure
|
||||
uses: act10ns/slack@ed1309ab9862e57e9e583e51c7889486b9a00b0f # v2.0.0
|
||||
if: failure()
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }}
|
||||
with:
|
||||
status: ${{ job.status }}
|
||||
|
||||
16
.github/workflows/enforce-labels.yml
vendored
Normal file
16
.github/workflows/enforce-labels.yml
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
name: Enforce PR labels
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [labeled, unlabeled, opened, edited, synchronize]
|
||||
jobs:
|
||||
enforce-label:
|
||||
name: EnforceLabel
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Enforce Label
|
||||
uses: yogevbd/enforce-label-action@a3c219da6b8fa73f6ba62b68ff09c469b3a1c024 # 2.2.2
|
||||
with:
|
||||
BANNED_LABELS: "hold"
|
||||
BANNED_LABELS_DESCRIPTION: "PRs on hold cannot be merged"
|
||||
496
.github/workflows/release.yml
vendored
496
.github/workflows/release.yml
vendored
@@ -1,425 +1,119 @@
|
||||
---
|
||||
name: Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release_tag_name_input:
|
||||
description: "Release Tag Name <X.X.X>"
|
||||
release_type:
|
||||
description: 'Release Options'
|
||||
required: true
|
||||
|
||||
default: 'Initial Release'
|
||||
type: choice
|
||||
options:
|
||||
- Initial Release
|
||||
- Redeploy
|
||||
- Dry Run
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
runs-on: ubuntu-latest
|
||||
name: Setup
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
package_version: ${{ steps.create_tags.outputs.package_version }}
|
||||
tag_version: ${{ steps.create_tags.outputs.tag_version }}
|
||||
release_upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
release-version: ${{ steps.version.outputs.version }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
|
||||
- name: Branch check
|
||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||
run: |
|
||||
if [[ "$GITHUB_REF" != "refs/heads/rc" ]]; then
|
||||
if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix-rc" ]]; then
|
||||
echo "==================================="
|
||||
echo "[!] Can only release from rc branch"
|
||||
echo "[!] Can only release from the 'rc' or 'hotfix-rc' branches"
|
||||
echo "==================================="
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
||||
|
||||
- name: Create Release Vars
|
||||
id: create_tags
|
||||
run: |
|
||||
case "${RELEASE_TAG_NAME_INPUT:0:1}" in
|
||||
v)
|
||||
echo "RELEASE_NAME=${RELEASE_TAG_NAME_INPUT:1}" >> $GITHUB_ENV
|
||||
echo "RELEASE_TAG_NAME=$RELEASE_TAG_NAME_INPUT" >> $GITHUB_ENV
|
||||
echo "::set-output name=package_version::${RELEASE_TAG_NAME_INPUT:1}"
|
||||
echo "::set-output name=tag_version::$RELEASE_TAG_NAME_INPUT"
|
||||
;;
|
||||
[0-9])
|
||||
echo "RELEASE_NAME=$RELEASE_TAG_NAME_INPUT" >> $GITHUB_ENV
|
||||
echo "RELEASE_TAG_NAME=v$RELEASE_TAG_NAME_INPUT" >> $GITHUB_ENV
|
||||
echo "::set-output name=package_version::$RELEASE_TAG_NAME_INPUT"
|
||||
echo "::set-output name=tag_version::v$RELEASE_TAG_NAME_INPUT"
|
||||
;;
|
||||
*)
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
env:
|
||||
RELEASE_TAG_NAME_INPUT: ${{ github.event.inputs.release_tag_name_input }}
|
||||
|
||||
- name: Create Draft Release
|
||||
id: create_release
|
||||
uses: actions/create-release@0cb9c9b65d5d1901c1f53e5e66eaf4afd303e70e
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Check Release Version
|
||||
id: version
|
||||
uses: bitwarden/gh-actions/release-version-check@main
|
||||
with:
|
||||
tag_name: ${{ env.RELEASE_TAG_NAME }}
|
||||
release_name: ${{ env.RELEASE_NAME }}
|
||||
release-type: ${{ github.event.inputs.release_type }}
|
||||
project-type: ts
|
||||
file: package.json
|
||||
|
||||
release:
|
||||
name: Release
|
||||
runs-on: ubuntu-22.04
|
||||
needs: setup
|
||||
steps:
|
||||
- name: Create GitHub deployment
|
||||
uses: chrnorm/deployment-action@d42cde7132fcec920de534fffc3be83794335c00 # v2.0.5
|
||||
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
|
||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||
uses: bitwarden/gh-actions/download-artifacts@main
|
||||
with:
|
||||
workflow: build.yml
|
||||
workflow_conclusion: success
|
||||
branch: ${{ github.ref_name }}
|
||||
|
||||
- name: Download all artifacts
|
||||
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
||||
uses: bitwarden/gh-actions/download-artifacts@main
|
||||
with:
|
||||
workflow: build.yml
|
||||
workflow_conclusion: success
|
||||
branch: master
|
||||
|
||||
- name: Create release
|
||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||
uses: ncipollo/release-action@6c75be85e571768fa31b40abf38de58ba0397db5 # v1.13.0
|
||||
env:
|
||||
PKG_VERSION: ${{ needs.setup.outputs.release-version }}
|
||||
with:
|
||||
artifacts: "./bwdc-windows-${{ env.PKG_VERSION }}.zip,
|
||||
./bwdc-macos-${{ env.PKG_VERSION }}.zip,
|
||||
./bwdc-linux-${{ env.PKG_VERSION }}.zip,
|
||||
./bwdc-windows-sha256-${{ env.PKG_VERSION }}.txt,
|
||||
./bwdc-macos-sha256-${{ env.PKG_VERSION }}.txt,
|
||||
./bwdc-linux-sha256-${{ env.PKG_VERSION }}.txt,
|
||||
./Bitwarden-Connector-Portable-${{ env.PKG_VERSION }}.exe,
|
||||
./Bitwarden-Connector-Installer-${{ env.PKG_VERSION }}.exe,
|
||||
./Bitwarden-Connector-Installer-${{ env.PKG_VERSION }}.exe.blockmap,
|
||||
./Bitwarden-Connector-${{ env.PKG_VERSION }}-x86_64.AppImage,
|
||||
./Bitwarden-Connector-${{ env.PKG_VERSION }}-mac.zip,
|
||||
./Bitwarden-Connector-${{ env.PKG_VERSION }}.dmg,
|
||||
./Bitwarden-Connector-${{ env.PKG_VERSION }}.dmg.blockmap,
|
||||
./latest-linux.yml,
|
||||
./latest-mac.yml,
|
||||
./latest.yml"
|
||||
commit: ${{ github.sha }}
|
||||
tag: v${{ env.PKG_VERSION }}
|
||||
name: Version ${{ env.PKG_VERSION }}
|
||||
body: "<insert release notes here>"
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
draft: true
|
||||
prerelease: false
|
||||
|
||||
|
||||
cli:
|
||||
runs-on: windows-latest
|
||||
needs: setup
|
||||
env:
|
||||
PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
||||
|
||||
- name: Setup Windows builder
|
||||
run: |
|
||||
choco install checksum --no-progress
|
||||
choco install reshack --no-progress
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea
|
||||
- name: Update deployment status to Success
|
||||
if: ${{ success() }}
|
||||
uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1
|
||||
with:
|
||||
node-version: '14.x'
|
||||
token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
state: 'success'
|
||||
deployment-id: ${{ steps.deployment.outputs.deployment_id }}
|
||||
|
||||
- name: Update NPM
|
||||
run: |
|
||||
npm install -g npm@7
|
||||
npm install -g node-gyp
|
||||
node-gyp install $(node -v)
|
||||
|
||||
- name: Set VER_INFO
|
||||
run: |
|
||||
echo "WIN_PKG=$env:WIN_PKG" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
env:
|
||||
WIN_PKG: C:\Users\runneradmin\.pkg-cache\v3.0\fetched-v14.16.1-win-x64
|
||||
|
||||
- name: get pkg-fetch
|
||||
shell: pwsh
|
||||
run: |
|
||||
cd $HOME
|
||||
$fetchedUrl = "https://github.com/vercel/pkg-fetch/releases/download/v3.0/node-v14.16.1-win-x64"
|
||||
|
||||
New-Item -ItemType directory -Path ./.pkg-cache
|
||||
New-Item -ItemType directory -Path ./.pkg-cache/v3.0
|
||||
Invoke-RestMethod -Uri $fetchedUrl -OutFile "./.pkg-cache/v3.0/fetched-v14.16.1-win-x64"
|
||||
env:
|
||||
WIN_PKG: C:\Users\runneradmin\.pkg-cache\v3.0\fetched-v14.16.1-win-x64
|
||||
|
||||
- name: Keytar
|
||||
shell: pwsh
|
||||
run: |
|
||||
$keytarVersion = (Get-Content -Raw -Path ./src/package.json | ConvertFrom-Json).dependencies.keytar
|
||||
$nodeModVersion = node -e "console.log(process.config.variables.node_module_version)"
|
||||
$keytarTar = "keytar-v${keytarVersion}-node-v${nodeModVersion}-{0}-x64.tar"
|
||||
$keytarTarGz = "${keytarTar}.gz"
|
||||
$keytarUrl = "https://github.com/atom/node-keytar/releases/download/v${keytarVersion}/${keytarTarGz}"
|
||||
|
||||
New-Item -ItemType directory -Path ./keytar/macos | Out-Null
|
||||
New-Item -ItemType directory -Path ./keytar/linux | Out-Null
|
||||
New-Item -ItemType directory -Path ./keytar/windows | Out-Null
|
||||
|
||||
Invoke-RestMethod -Uri $($keytarUrl -f "darwin") -OutFile "./keytar/macos/$($keytarTarGz -f "darwin")"
|
||||
Invoke-RestMethod -Uri $($keytarUrl -f "linux") -OutFile "./keytar/linux/$($keytarTarGz -f "linux")"
|
||||
Invoke-RestMethod -Uri $($keytarUrl -f "win32") -OutFile "./keytar/windows/$($keytarTarGz -f "win32")"
|
||||
|
||||
7z e "./keytar/macos/$($keytarTarGz -f "darwin")" -o"./keytar/macos"
|
||||
7z e "./keytar/linux/$($keytarTarGz -f "linux")" -o"./keytar/linux"
|
||||
7z e "./keytar/windows/$($keytarTarGz -f "win32")" -o"./keytar/windows"
|
||||
|
||||
7z e "./keytar/macos/$($keytarTar -f "darwin")" -o"./keytar/macos"
|
||||
7z e "./keytar/linux/$($keytarTar -f "linux")" -o"./keytar/linux"
|
||||
7z e "./keytar/windows/$($keytarTar -f "win32")" -o"./keytar/windows"
|
||||
|
||||
- name: Setup Version Info
|
||||
shell: pwsh
|
||||
run: ./scripts/make-versioninfo.ps1
|
||||
|
||||
- name: Resource Hacker
|
||||
shell: cmd
|
||||
run: |
|
||||
set PATH=%PATH%;C:\Program Files (x86)\Resource Hacker
|
||||
ResourceHacker -open %WIN_PKG% -save %WIN_PKG% -action delete -mask ICONGROUP,1,
|
||||
ResourceHacker -open version-info.rc -save version-info.res -action compile
|
||||
ResourceHacker -open %WIN_PKG% -save %WIN_PKG% -action addoverwrite -resource version-info.res
|
||||
|
||||
- name: Install
|
||||
run: npm install
|
||||
|
||||
- name: Package CLI
|
||||
run: npm run dist:cli
|
||||
|
||||
- name: Zip
|
||||
shell: cmd
|
||||
run: |
|
||||
7z a ./dist-cli/bwdc-windows-%PACKAGE_VERSION%.zip ./dist-cli/windows/bwdc.exe ./keytar/windows/keytar.node
|
||||
7z a ./dist-cli/bwdc-macos-%PACKAGE_VERSION%.zip ./dist-cli/macos/bwdc ./keytar/macos/keytar.node
|
||||
7z a ./dist-cli/bwdc-linux-%PACKAGE_VERSION%.zip ./dist-cli/linux/bwdc ./keytar/linux/keytar.node
|
||||
|
||||
- name: Version Test
|
||||
run: |
|
||||
Expand-Archive -Path "./dist-cli/bwdc-windows-${env:PACKAGE_VERSION}.zip" -DestinationPath "./test/windows"
|
||||
$testVersion = Invoke-Expression '& ./test/windows/bwdc.exe -v'
|
||||
echo "version: $env:PACKAGE_VERSION"
|
||||
echo "testVersion: $testVersion"
|
||||
if($testVersion -ne $env:PACKAGE_VERSION) {
|
||||
Throw "Version test failed."
|
||||
}
|
||||
|
||||
- name: Create checksums
|
||||
run: |
|
||||
checksum -f="./dist-cli/bwdc-windows-${env:PACKAGE_VERSION}.zip" `
|
||||
-t sha256 | Out-File ./dist-cli/bwdc-windows-sha256-${env:PACKAGE_VERSION}.txt
|
||||
checksum -f="./dist-cli/bwdc-macos-${env:PACKAGE_VERSION}.zip" `
|
||||
-t sha256 | Out-File ./dist-cli/bwdc-macos-sha256-${env:PACKAGE_VERSION}.txt
|
||||
checksum -f="./dist-cli/bwdc-linux-${env:PACKAGE_VERSION}.zip" `
|
||||
-t sha256 | Out-File ./dist-cli/bwdc-linux-sha256-${env:PACKAGE_VERSION}.txt
|
||||
|
||||
- name: upload windows zip release asset
|
||||
uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Update deployment status to Failure
|
||||
if: ${{ failure() }}
|
||||
uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1
|
||||
with:
|
||||
upload_url: ${{ needs.setup.outputs.release_upload_url }}
|
||||
asset_path: ./dist-cli/bwdc-windows-${{ env.PACKAGE_VERSION }}.zip
|
||||
asset_name: bwdc-windows-${{ env.PACKAGE_VERSION }}.zip
|
||||
asset_content_type: application/zip
|
||||
|
||||
- name: upload macos zip release asset
|
||||
uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ needs.setup.outputs.release_upload_url }}
|
||||
asset_path: ./dist-cli/bwdc-macos-${{ env.PACKAGE_VERSION }}.zip
|
||||
asset_name: bwdc-macos-${{ env.PACKAGE_VERSION }}.zip
|
||||
asset_content_type: application/zip
|
||||
|
||||
- name: upload linux zip release asset
|
||||
uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ needs.setup.outputs.release_upload_url }}
|
||||
asset_path: ./dist-cli/bwdc-linux-${{ env.PACKAGE_VERSION }}.zip
|
||||
asset_name: bwdc-linux-${{ env.PACKAGE_VERSION }}.zip
|
||||
asset_content_type: application/zip
|
||||
|
||||
- name: upload windows checksum release asset
|
||||
uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ needs.setup.outputs.release_upload_url }}
|
||||
asset_path: ./dist-cli/bwdc-windows-sha256-${{ env.PACKAGE_VERSION }}.txt
|
||||
asset_name: bwdc-windows-sha256-${{ env.PACKAGE_VERSION }}.txt
|
||||
asset_content_type: text/plain
|
||||
|
||||
- name: upload macos checksum release asset
|
||||
uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ needs.setup.outputs.release_upload_url }}
|
||||
asset_path: ./dist-cli/bwdc-macos-sha256-${{ env.PACKAGE_VERSION }}.txt
|
||||
asset_name: bwdc-macos-sha256-${{ env.PACKAGE_VERSION }}.txt
|
||||
asset_content_type: text/plain
|
||||
|
||||
- name: upload linux checksum release asset
|
||||
uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ needs.setup.outputs.release_upload_url }}
|
||||
asset_path: ./dist-cli/bwdc-linux-sha256-${{ env.PACKAGE_VERSION }}.txt
|
||||
asset_name: bwdc-linux-sha256-${{ env.PACKAGE_VERSION }}.txt
|
||||
asset_content_type: text/plain
|
||||
|
||||
|
||||
windows-gui:
|
||||
runs-on: windows-latest
|
||||
needs: setup
|
||||
env:
|
||||
PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||
steps:
|
||||
- name: Set up dotnet
|
||||
uses: actions/setup-dotnet@a71d1eb2c86af85faa8c772c03fb365e377e45ea
|
||||
with:
|
||||
dotnet-version: "3.1.x"
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea
|
||||
with:
|
||||
node-version: '14.x'
|
||||
|
||||
- name: Update NPM
|
||||
run: |
|
||||
npm install -g npm@7
|
||||
npm install -g node-gyp
|
||||
node-gyp install $(node -v)
|
||||
|
||||
- name: Set Node options
|
||||
run: echo "NODE_OPTIONS=--max_old_space_size=4096" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
shell: pwsh
|
||||
|
||||
- name: Print environment
|
||||
run: |
|
||||
node --version
|
||||
npm --version
|
||||
dotnet --version
|
||||
|
||||
- name: Install AST
|
||||
shell: pwsh
|
||||
run: |
|
||||
cd $HOME
|
||||
git clone https://github.com/vcsjones/AzureSignTool.git
|
||||
cd AzureSignTool
|
||||
$latest_head = $(git rev-parse HEAD)[0..9] -join ""
|
||||
$latest_version = "0.0.0-g$latest_head"
|
||||
Write-Host "--------"
|
||||
Write-Host "git commit - $(git rev-parse HEAD)"
|
||||
Write-Host "latest_head - $latest_head"
|
||||
Write-Host "PACKAGE VERSION TO BUILD - $latest_version"
|
||||
Write-Host "--------"
|
||||
dotnet restore
|
||||
dotnet pack --output ./nupkg
|
||||
dotnet tool install --global --ignore-failed-sources --add-source ./nupkg --version $latest_version azuresigntool
|
||||
cd $HOME
|
||||
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
||||
|
||||
- name: Install Node dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Run linter
|
||||
run: npm run lint
|
||||
|
||||
- name: npm rebuild
|
||||
run: npm run rebuild
|
||||
|
||||
- name: Build & Sign
|
||||
run: |
|
||||
npm run publish:win
|
||||
env:
|
||||
ELECTRON_BUILDER_SIGN: 1
|
||||
SIGNING_VAULT_URL: ${{ secrets.SIGNING_VAULT_URL }}
|
||||
SIGNING_CLIENT_ID: ${{ secrets.SIGNING_CLIENT_ID }}
|
||||
SIGNING_TENANT_ID: ${{ secrets.SIGNING_TENANT_ID }}
|
||||
SIGNING_CLIENT_SECRET: ${{ secrets.SIGNING_CLIENT_SECRET }}
|
||||
SIGNING_CERT_NAME: ${{ secrets.SIGNING_CERT_NAME }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
||||
linux:
|
||||
runs-on: ubuntu-latest
|
||||
needs: setup
|
||||
env:
|
||||
PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||
steps:
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea
|
||||
with:
|
||||
node-version: '14.x'
|
||||
|
||||
- name: Update NPM
|
||||
run: |
|
||||
npm install -g npm@7
|
||||
npm install -g node-gyp
|
||||
node-gyp install $(node -v)
|
||||
|
||||
- name: Set Node options
|
||||
run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV
|
||||
|
||||
- name: Set up environment
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install pkg-config libxss-dev libsecret-1-dev
|
||||
sudo apt-get -y install rpm
|
||||
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
||||
|
||||
- name: Set PACKAGE_VERSION
|
||||
shell: pwsh
|
||||
run: |
|
||||
$env:pkgVersion = (Get-Content -Raw -Path ./src/package.json | ConvertFrom-Json).version
|
||||
echo "PACKAGE_VERSION=$env:pkgVersion" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
echo "version: $env:pkgVersion"
|
||||
|
||||
- name: npm install
|
||||
run: npm install
|
||||
|
||||
- name: npm rebuild
|
||||
run: npm run rebuild
|
||||
|
||||
- name: npm package
|
||||
run: npm run publish:lin
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
||||
macos:
|
||||
runs-on: macos-latest
|
||||
needs: setup
|
||||
env:
|
||||
PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||
steps:
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea
|
||||
with:
|
||||
node-version: '14.x'
|
||||
|
||||
- name: Update NPM
|
||||
run: |
|
||||
npm install -g npm@7
|
||||
npm install -g node-gyp
|
||||
node-gyp install $(node -v)
|
||||
|
||||
- name: Set Node options
|
||||
run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV
|
||||
|
||||
- name: Print environment
|
||||
run: |
|
||||
node --version
|
||||
npm --version
|
||||
Write-Output "GitHub ref: $env:GITHUB_REF"
|
||||
Write-Output "GitHub event: $env:GITHUB_EVENT"
|
||||
shell: pwsh
|
||||
env:
|
||||
GITHUB_REF: ${{ github.ref }}
|
||||
GITHUB_EVENT: ${{ github.event_name }}
|
||||
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
||||
|
||||
- name: Decrypt secrets
|
||||
run: ./.github/scripts/macos/decrypt-secrets.ps1
|
||||
shell: pwsh
|
||||
env:
|
||||
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }}
|
||||
|
||||
- name: Set up keychain
|
||||
run: ./.github/scripts/macos/setup-keychain.ps1
|
||||
shell: pwsh
|
||||
env:
|
||||
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
||||
DEVID_CERT_PASSWORD: ${{ secrets.DEVID_CERT_PASSWORD }}
|
||||
MACDEV_CERT_PASSWORD: ${{ secrets.MACDEV_CERT_PASSWORD }}
|
||||
|
||||
- name: Load package version
|
||||
run: ./.github/scripts/load-version.ps1
|
||||
shell: pwsh
|
||||
|
||||
- name: Install Node dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Run linter
|
||||
run: npm run lint
|
||||
|
||||
- name: Build application (dist)
|
||||
run: npm run publish:mac
|
||||
env:
|
||||
APPLE_ID_USERNAME: ${{ secrets.APPLE_ID_USERNAME }}
|
||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
state: 'failure'
|
||||
deployment-id: ${{ steps.deployment.outputs.deployment_id }}
|
||||
|
||||
85
.github/workflows/version-bump.yml
vendored
Normal file
85
.github/workflows/version-bump.yml
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
---
|
||||
name: Version Bump
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version_number:
|
||||
description: "New Version"
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
bump_version:
|
||||
name: "Create version_bump_${{ github.event.inputs.version_number }} branch"
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout Branch
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
|
||||
- name: Login to Azure - Prod Subscription
|
||||
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
|
||||
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"
|
||||
|
||||
- name: Import GPG key
|
||||
uses: crazy-max/ghaction-import-gpg@82a020f1f7f605c65dd2449b392a52c3fcfef7ef # v6.0.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: Create Version Branch
|
||||
run: |
|
||||
git switch -c version_bump_${{ github.event.inputs.version_number }}
|
||||
git push -u origin version_bump_${{ github.event.inputs.version_number }}
|
||||
|
||||
- name: Checkout Version Branch
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
with:
|
||||
ref: version_bump_${{ github.event.inputs.version_number }}
|
||||
|
||||
- name: Bump Version - Package
|
||||
uses: bitwarden/gh-actions/version-bump@main
|
||||
with:
|
||||
version: ${{ github.event.inputs.version_number }}
|
||||
file_path: "./package.json"
|
||||
|
||||
- name: Commit files
|
||||
run: |
|
||||
git config --local user.email "106330231+bitwarden-devops-bot@users.noreply.github.com"
|
||||
git config --local user.name "bitwarden-devops-bot"
|
||||
git commit -m "Bumped version to ${{ github.event.inputs.version_number }}" -a
|
||||
|
||||
- name: Push changes
|
||||
run: git push -u origin version_bump_${{ github.event.inputs.version_number }}
|
||||
|
||||
- name: Create Version PR
|
||||
env:
|
||||
PR_BRANCH: "version_bump_${{ github.event.inputs.version_number }}"
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
BASE_BRANCH: master
|
||||
TITLE: "Bump version to ${{ github.event.inputs.version_number }}"
|
||||
run: |
|
||||
gh pr create --title "$TITLE" \
|
||||
--base "$BASE" \
|
||||
--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 ${{ github.event.inputs.version_number }}"
|
||||
11
.github/workflows/workflow-linter.yml
vendored
Normal file
11
.github/workflows/workflow-linter.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
name: Workflow Linter
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/**
|
||||
|
||||
jobs:
|
||||
call-workflow:
|
||||
uses: bitwarden/gh-actions/.github/workflows/workflow-linter.yml@c970b0fb89bd966749280e832928db62040812bf
|
||||
47
.gitignore
vendored
47
.gitignore
vendored
@@ -1,17 +1,40 @@
|
||||
.vs
|
||||
.idea
|
||||
# General
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# IDEs and editors
|
||||
.idea/
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
*.launch
|
||||
.settings/
|
||||
*.sublime-workspace
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
.history/*
|
||||
|
||||
# Node
|
||||
node_modules
|
||||
npm-debug.log
|
||||
vwd.webinfo
|
||||
dist/
|
||||
dist-cli/
|
||||
css/
|
||||
|
||||
# Build directories
|
||||
dist
|
||||
build
|
||||
.angular/cache
|
||||
|
||||
# Testing
|
||||
coverage
|
||||
junit.xml
|
||||
|
||||
# Misc
|
||||
*.crx
|
||||
*.pem
|
||||
build-cli/
|
||||
build/
|
||||
yarn-error.log
|
||||
.DS_Store
|
||||
*.nupkg
|
||||
*.zip
|
||||
*.provisionprofile
|
||||
*.env
|
||||
.swp
|
||||
|
||||
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -1,4 +0,0 @@
|
||||
[submodule "jslib"]
|
||||
path = jslib
|
||||
url = https://github.com/bitwarden/jslib.git
|
||||
branch = master
|
||||
1
.husky/.gitignore
vendored
Normal file
1
.husky/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
_
|
||||
4
.husky/pre-commit
Executable file
4
.husky/pre-commit
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npx lint-staged
|
||||
10
.prettierignore
Normal file
10
.prettierignore
Normal file
@@ -0,0 +1,10 @@
|
||||
# Build directories
|
||||
build
|
||||
build-cli
|
||||
dist
|
||||
|
||||
# External libraries / auto synced locales
|
||||
src/locales
|
||||
|
||||
# Github Workflows
|
||||
.github/workflows
|
||||
3
.prettierrc.json
Normal file
3
.prettierrc.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"printWidth": 100
|
||||
}
|
||||
66
.vscode/launch.json
vendored
66
.vscode/launch.json
vendored
@@ -1,48 +1,40 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Electron: Main",
|
||||
"protocol": "inspector",
|
||||
"cwd": "${workspaceRoot}/build",
|
||||
"runtimeArgs": [
|
||||
"--remote-debugging-port=9223",
|
||||
"."
|
||||
],
|
||||
"windows": {
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
|
||||
},
|
||||
"sourceMaps": true
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Electron: Main",
|
||||
"protocol": "inspector",
|
||||
"cwd": "${workspaceRoot}/build",
|
||||
"runtimeArgs": ["--remote-debugging-port=9223", "."],
|
||||
"windows": {
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
|
||||
},
|
||||
{
|
||||
"name": "Electron: Renderer",
|
||||
"type": "chrome",
|
||||
"request": "attach",
|
||||
"port": 9223,
|
||||
"webRoot": "${workspaceFolder}/build",
|
||||
"sourceMaps": true
|
||||
"sourceMaps": true
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Debug CLI",
|
||||
"protocol": "inspector",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"program": "${workspaceFolder}/build-cli/bwdc.js",
|
||||
"args": [
|
||||
"sync"
|
||||
]
|
||||
"name": "Electron: Renderer",
|
||||
"type": "chrome",
|
||||
"request": "attach",
|
||||
"port": 9223,
|
||||
"webRoot": "${workspaceFolder}/build",
|
||||
"sourceMaps": true
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Debug CLI",
|
||||
"protocol": "inspector",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"program": "${workspaceFolder}/build-cli/bwdc.js",
|
||||
"args": ["sync"]
|
||||
}
|
||||
],
|
||||
"compounds": [
|
||||
{
|
||||
"name": "Electron: All",
|
||||
"configurations": [
|
||||
"Electron: Main",
|
||||
"Electron: Renderer"
|
||||
]
|
||||
}
|
||||
{
|
||||
"name": "Electron: All",
|
||||
"configurations": ["Electron: Main", "Electron: Renderer"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
31
README.md
31
README.md
@@ -6,6 +6,7 @@
|
||||
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:
|
||||
|
||||
- Active Directory
|
||||
- Any other LDAP-based directory
|
||||
- Azure Active Directory
|
||||
@@ -14,7 +15,7 @@ Supported directories:
|
||||
|
||||
The application is written using Electron with Angular and installs on Windows, macOS, and Linux distributions.
|
||||
|
||||
[](https://help.bitwarden.com/article/directory-sync/#download-and-install)
|
||||
[](https://bitwarden.com/help/directory-sync/#download-and-install)
|
||||
|
||||

|
||||
|
||||
@@ -41,13 +42,13 @@ bwdc config --help
|
||||
|
||||
**Detailed Documentation**
|
||||
|
||||
We provide detailed documentation and examples for using the Directory Connector CLI in our help center at https://help.bitwarden.com/article/directory-sync/#command-line-interface.
|
||||
We provide detailed documentation and examples for using the Directory Connector CLI in our help center at https://bitwarden.com/help/directory-sync-cli/.
|
||||
|
||||
## Build/Run
|
||||
|
||||
**Requirements**
|
||||
|
||||
- [Node.js](https://nodejs.org) v14
|
||||
- [Node.js](https://nodejs.org) v18 (LTS)
|
||||
- Windows users: To compile the native node modules used in the app you will need the Visual C++ toolset, available through the standard Visual Studio installer (recommended) or by installing [`windows-build-tools`](https://github.com/felixrieseberg/windows-build-tools) through `npm`. See more at [Compiling native Addon modules](https://github.com/Microsoft/nodejs-guidelines/blob/master/windows-environment.md#compiling-native-addon-modules).
|
||||
|
||||
**Run the app**
|
||||
@@ -73,8 +74,32 @@ You can then run commands from the `./build-cli` folder:
|
||||
node ./build-cli/bwdc.js --help
|
||||
```
|
||||
|
||||
## We're Hiring!
|
||||
|
||||
Interested in contributing in a big way? Consider joining our team! We're hiring for many positions. Please take a look at our [Careers page](https://bitwarden.com/careers/) to see what opportunities are currently open as well as what it's like to work at Bitwarden.
|
||||
|
||||
## Contribute
|
||||
|
||||
Code contributions are welcome! Please commit any pull requests against the `master` branch. Learn more about how to contribute by reading the [`CONTRIBUTING.md`](CONTRIBUTING.md) file.
|
||||
|
||||
Security audits and feedback are welcome. Please open an issue or email us privately if the report is sensitive in nature. You can read our security policy in the [`SECURITY.md`](SECURITY.md) file.
|
||||
|
||||
### Prettier
|
||||
|
||||
We recently migrated to using Prettier as code formatter. All previous branches will need to updated to avoid large merge conflicts using the following steps:
|
||||
|
||||
1. Check out your local Branch
|
||||
2. Run `git merge 225073aa335d33ad905877b68336a9288e89ea10`
|
||||
3. Resolve any merge conflicts, commit.
|
||||
4. Run `npm run prettier`
|
||||
5. Commit
|
||||
6. Run `git merge -Xours 096196fcd512944d1c3d9c007647a1319b032639`
|
||||
7. Push
|
||||
|
||||
#### Git blame
|
||||
|
||||
We also recommend that you configure git to ignore the prettier revision using:
|
||||
|
||||
```bash
|
||||
git config blame.ignoreRevsFile .git-blame-ignore-revs
|
||||
```
|
||||
|
||||
42
SECURITY.md
42
SECURITY.md
@@ -1,39 +1,11 @@
|
||||
Bitwarden believes that working with security researchers across the globe is crucial to keeping our
|
||||
users safe. If you believe you've found a security issue in our product or service, we encourage you to
|
||||
notify us. We welcome working with you to resolve the issue promptly. Thanks in advance!
|
||||
Bitwarden believes that working with security researchers across the globe is crucial to keeping our users safe. If you believe you've found a security issue in our product or service, we encourage you to please submit a report through our [HackerOne Program](https://hackerone.com/bitwarden/). We welcome working with you to resolve the issue promptly. Thanks in advance!
|
||||
|
||||
# Disclosure Policy
|
||||
|
||||
- Let us know as soon as possible upon discovery of a potential security issue, and we'll make every
|
||||
effort to quickly resolve the issue.
|
||||
- Provide us a reasonable amount of time to resolve the issue before any disclosure to the public or a
|
||||
third-party. We may publicly disclose the issue before resolving it, if appropriate.
|
||||
- Make a good faith effort to avoid privacy violations, destruction of data, and interruption or
|
||||
degradation of our service. Only interact with accounts you own or with explicit permission of the
|
||||
account holder.
|
||||
- If you would like to encrypt your report, please use the PGP key with long ID
|
||||
`0xDE6887086F892325FEC04CC0D847525B6931381F` (available in the public keyserver pool).
|
||||
|
||||
# In-scope
|
||||
|
||||
- Security issues in any current release of Bitwarden. This includes the web vault, browser extension,
|
||||
and mobile apps (iOS and Android). Product downloads are available at https://bitwarden.com. Source
|
||||
code is available at https://github.com/bitwarden.
|
||||
|
||||
# Exclusions
|
||||
|
||||
The following bug classes are out-of scope:
|
||||
|
||||
- Bugs that are already reported on any of Bitwarden's issue trackers (https://github.com/bitwarden),
|
||||
or that we already know of. Note that some of our issue tracking is private.
|
||||
- Issues in an upstream software dependency (ex: Xamarin, ASP.NET) which are already reported to the
|
||||
upstream maintainer.
|
||||
- Attacks requiring physical access to a user's device.
|
||||
- Self-XSS
|
||||
- Issues related to software or protocols not under Bitwarden's control
|
||||
- Vulnerabilities in outdated versions of Bitwarden
|
||||
- Missing security best practices that do not directly lead to a vulnerability
|
||||
- Issues that do not have any impact on the general public
|
||||
- Let us know as soon as possible upon discovery of a potential security issue, and we'll make every effort to quickly resolve the issue.
|
||||
- Provide us a reasonable amount of time to resolve the issue before any disclosure to the public or a third-party. We may publicly disclose the issue before resolving it, if appropriate.
|
||||
- Make a good faith effort to avoid privacy violations, destruction of data, and interruption or degradation of our service. Only interact with accounts you own or with explicit permission of the account holder.
|
||||
- If you would like to encrypt your report, please use the PGP key with long ID `0xDE6887086F892325FEC04CC0D847525B6931381F` (available in the public keyserver pool).
|
||||
|
||||
While researching, we'd like to ask you to refrain from:
|
||||
|
||||
@@ -42,4 +14,8 @@ While researching, we'd like to ask you to refrain from:
|
||||
- Social engineering (including phishing) of Bitwarden staff or contractors
|
||||
- Any physical attempts against Bitwarden property or data centers
|
||||
|
||||
# We want to help you!
|
||||
|
||||
If you have something that you feel is close to exploitation, or if you'd like some information regarding the internal API, or generally have any questions regarding the app that would help in your efforts, please email us at https://bitwarden.com/contact and ask for that information. As stated above, Bitwarden wants to help you find issues, and is more than willing to help.
|
||||
|
||||
Thank you for helping keep Bitwarden and our users safe!
|
||||
|
||||
35
angular.json
Normal file
35
angular.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"newProjectRoot": "apps",
|
||||
"cli": {
|
||||
"analytics": false
|
||||
},
|
||||
"projects": {
|
||||
"app": {
|
||||
"projectType": "application",
|
||||
"schematics": {
|
||||
"@schematics/angular:application": {
|
||||
"strict": true
|
||||
}
|
||||
},
|
||||
"root": ".",
|
||||
"sourceRoot": "src",
|
||||
"prefix": "app",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"outputPath": "dist",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"tsConfig": "tsconfig.json",
|
||||
"assets": [],
|
||||
"styles": [],
|
||||
"scripts": []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
67
electron-builder.json
Normal file
67
electron-builder.json
Normal file
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"extraMetadata": {
|
||||
"name": "bitwarden-directory-connector"
|
||||
},
|
||||
"productName": "Bitwarden Directory Connector",
|
||||
"appId": "com.bitwarden.directory-connector",
|
||||
"copyright": "Copyright © 2015-2022 Bitwarden Inc.",
|
||||
"directories": {
|
||||
"buildResources": "resources",
|
||||
"output": "dist",
|
||||
"app": "build"
|
||||
},
|
||||
"afterSign": "scripts/notarize.js",
|
||||
"mac": {
|
||||
"artifactName": "Bitwarden-Connector-${version}-mac.${ext}",
|
||||
"category": "public.app-category.productivity",
|
||||
"gatekeeperAssess": false,
|
||||
"hardenedRuntime": true,
|
||||
"entitlements": "resources/entitlements.mac.plist",
|
||||
"entitlementsInherit": "resources/entitlements.mac.plist",
|
||||
"target": ["dmg", "zip"]
|
||||
},
|
||||
"win": {
|
||||
"target": ["portable", "nsis"],
|
||||
"sign": "scripts/sign.js"
|
||||
},
|
||||
"linux": {
|
||||
"category": "Utility",
|
||||
"synopsis": "Sync your user directory to your Bitwarden organization.",
|
||||
"target": ["AppImage"]
|
||||
},
|
||||
"dmg": {
|
||||
"artifactName": "Bitwarden-Connector-${version}.${ext}",
|
||||
"icon": "dmg.icns",
|
||||
"contents": [
|
||||
{
|
||||
"x": 150,
|
||||
"y": 185,
|
||||
"type": "file"
|
||||
},
|
||||
{
|
||||
"x": 390,
|
||||
"y": 180,
|
||||
"type": "link",
|
||||
"path": "/Applications"
|
||||
}
|
||||
],
|
||||
"window": {
|
||||
"width": 540,
|
||||
"height": 380
|
||||
}
|
||||
},
|
||||
"nsis": {
|
||||
"oneClick": false,
|
||||
"perMachine": true,
|
||||
"allowToChangeInstallationDirectory": true,
|
||||
"artifactName": "Bitwarden-Connector-Installer-${version}.${ext}",
|
||||
"uninstallDisplayName": "${productName}",
|
||||
"deleteAppDataOnUninstall": true
|
||||
},
|
||||
"portable": {
|
||||
"artifactName": "Bitwarden-Connector-Portable-${version}.${ext}"
|
||||
},
|
||||
"appImage": {
|
||||
"artifactName": "Bitwarden-Connector-${version}-${arch}.${ext}"
|
||||
}
|
||||
}
|
||||
25
gulpfile.js
25
gulpfile.js
@@ -1,25 +0,0 @@
|
||||
const gulp = require('gulp');
|
||||
const googleWebFonts = require('gulp-google-webfonts');
|
||||
const del = require('del');
|
||||
|
||||
const paths = {
|
||||
cssDir: './src/css/',
|
||||
};
|
||||
|
||||
function clean() {
|
||||
return del([paths.cssDir]);
|
||||
}
|
||||
|
||||
function webfonts() {
|
||||
return gulp.src('./webfonts.list')
|
||||
.pipe(googleWebFonts({
|
||||
fontsDir: 'webfonts',
|
||||
cssFilename: 'webfonts.css',
|
||||
format: 'woff',
|
||||
}))
|
||||
.pipe(gulp.dest(paths.cssDir));
|
||||
}
|
||||
|
||||
exports.clean = clean;
|
||||
exports.webfonts = gulp.series(clean, webfonts);
|
||||
exports['prebuild:renderer'] = webfonts;;
|
||||
1
jslib
1
jslib
Submodule jslib deleted from c70c8ecc24
9
jslib/.gitignore
vendored
Normal file
9
jslib/.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
.vs
|
||||
.idea
|
||||
node_modules
|
||||
npm-debug.log
|
||||
vwd.webinfo
|
||||
*.crx
|
||||
*.pem
|
||||
dist
|
||||
coverage
|
||||
35
jslib/angular/src/components/callout.component.html
Normal file
35
jslib/angular/src/components/callout.component.html
Normal file
@@ -0,0 +1,35 @@
|
||||
<div
|
||||
#callout
|
||||
class="callout callout-{{ calloutStyle }}"
|
||||
[ngClass]="{ clickable: clickable }"
|
||||
[attr.role]="useAlertRole ? 'alert' : null"
|
||||
>
|
||||
<h3 class="callout-heading" *ngIf="title">
|
||||
<i class="bwi {{ icon }}" *ngIf="icon" aria-hidden="true"></i>
|
||||
{{ title }}
|
||||
</h3>
|
||||
<div class="enforced-policy-options" *ngIf="enforcedPolicyOptions">
|
||||
{{ enforcedPolicyMessage }}
|
||||
<ul>
|
||||
<li *ngIf="enforcedPolicyOptions?.minComplexity > 0">
|
||||
{{ "policyInEffectMinComplexity" | i18n : getPasswordScoreAlertDisplay() }}
|
||||
</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.minLength > 0">
|
||||
{{ "policyInEffectMinLength" | i18n : enforcedPolicyOptions?.minLength.toString() }}
|
||||
</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.requireUpper">
|
||||
{{ "policyInEffectUppercase" | i18n }}
|
||||
</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.requireLower">
|
||||
{{ "policyInEffectLowercase" | i18n }}
|
||||
</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.requireNumbers">
|
||||
{{ "policyInEffectNumbers" | i18n }}
|
||||
</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.requireSpecial">
|
||||
{{ "policyInEffectSpecial" | i18n : "!@#$%^&*" }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
78
jslib/angular/src/components/callout.component.ts
Normal file
78
jslib/angular/src/components/callout.component.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import { Component, Input, OnInit } from "@angular/core";
|
||||
|
||||
import { I18nService } from "@/jslib/common/src/abstractions/i18n.service";
|
||||
import { MasterPasswordPolicyOptions } from "@/jslib/common/src/models/domain/masterPasswordPolicyOptions";
|
||||
|
||||
@Component({
|
||||
selector: "app-callout",
|
||||
templateUrl: "callout.component.html",
|
||||
})
|
||||
export class CalloutComponent implements OnInit {
|
||||
@Input() type = "info";
|
||||
@Input() icon: string;
|
||||
@Input() title: string;
|
||||
@Input() clickable: boolean;
|
||||
@Input() enforcedPolicyOptions: MasterPasswordPolicyOptions;
|
||||
@Input() enforcedPolicyMessage: string;
|
||||
@Input() useAlertRole = false;
|
||||
|
||||
calloutStyle: string;
|
||||
|
||||
constructor(private i18nService: I18nService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.calloutStyle = this.type;
|
||||
|
||||
if (this.enforcedPolicyMessage === undefined) {
|
||||
this.enforcedPolicyMessage = this.i18nService.t("masterPasswordPolicyInEffect");
|
||||
}
|
||||
|
||||
if (this.type === "warning" || this.type === "danger") {
|
||||
if (this.type === "danger") {
|
||||
this.calloutStyle = "danger";
|
||||
}
|
||||
if (this.title === undefined) {
|
||||
this.title = this.i18nService.t("warning");
|
||||
}
|
||||
if (this.icon === undefined) {
|
||||
this.icon = "bwi-exclamation-triangle";
|
||||
}
|
||||
} else if (this.type === "error") {
|
||||
this.calloutStyle = "danger";
|
||||
if (this.title === undefined) {
|
||||
this.title = this.i18nService.t("error");
|
||||
}
|
||||
if (this.icon === undefined) {
|
||||
this.icon = "bwi-error";
|
||||
}
|
||||
} else if (this.type === "tip") {
|
||||
this.calloutStyle = "success";
|
||||
if (this.title === undefined) {
|
||||
this.title = this.i18nService.t("tip");
|
||||
}
|
||||
if (this.icon === undefined) {
|
||||
this.icon = "bwi-lightbulb";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getPasswordScoreAlertDisplay() {
|
||||
if (this.enforcedPolicyOptions == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
let str: string;
|
||||
switch (this.enforcedPolicyOptions.minComplexity) {
|
||||
case 4:
|
||||
str = this.i18nService.t("strong");
|
||||
break;
|
||||
case 3:
|
||||
str = this.i18nService.t("good");
|
||||
break;
|
||||
default:
|
||||
str = this.i18nService.t("weak");
|
||||
break;
|
||||
}
|
||||
return str + " (" + this.enforcedPolicyOptions.minComplexity + ")";
|
||||
}
|
||||
}
|
||||
63
jslib/angular/src/components/environment.component.ts
Normal file
63
jslib/angular/src/components/environment.component.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { Directive, EventEmitter, Output } from "@angular/core";
|
||||
|
||||
import { EnvironmentService } from "@/jslib/common/src/abstractions/environment.service";
|
||||
import { I18nService } from "@/jslib/common/src/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@/jslib/common/src/abstractions/platformUtils.service";
|
||||
|
||||
@Directive()
|
||||
export class EnvironmentComponent {
|
||||
@Output() onSaved = new EventEmitter();
|
||||
|
||||
iconsUrl: string;
|
||||
identityUrl: string;
|
||||
apiUrl: string;
|
||||
webVaultUrl: string;
|
||||
notificationsUrl: string;
|
||||
baseUrl: string;
|
||||
showCustom = false;
|
||||
|
||||
constructor(
|
||||
protected platformUtilsService: PlatformUtilsService,
|
||||
protected environmentService: EnvironmentService,
|
||||
protected i18nService: I18nService
|
||||
) {
|
||||
const urls = this.environmentService.getUrls();
|
||||
|
||||
this.baseUrl = urls.base || "";
|
||||
this.webVaultUrl = urls.webVault || "";
|
||||
this.apiUrl = urls.api || "";
|
||||
this.identityUrl = urls.identity || "";
|
||||
this.iconsUrl = urls.icons || "";
|
||||
this.notificationsUrl = urls.notifications || "";
|
||||
}
|
||||
|
||||
async submit() {
|
||||
const resUrls = await this.environmentService.setUrls({
|
||||
base: this.baseUrl,
|
||||
api: this.apiUrl,
|
||||
identity: this.identityUrl,
|
||||
webVault: this.webVaultUrl,
|
||||
icons: this.iconsUrl,
|
||||
notifications: this.notificationsUrl,
|
||||
});
|
||||
|
||||
// re-set urls since service can change them, ex: prefixing https://
|
||||
this.baseUrl = resUrls.base;
|
||||
this.apiUrl = resUrls.api;
|
||||
this.identityUrl = resUrls.identity;
|
||||
this.webVaultUrl = resUrls.webVault;
|
||||
this.iconsUrl = resUrls.icons;
|
||||
this.notificationsUrl = resUrls.notifications;
|
||||
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("environmentSaved"));
|
||||
this.saved();
|
||||
}
|
||||
|
||||
toggleCustom() {
|
||||
this.showCustom = !this.showCustom;
|
||||
}
|
||||
|
||||
protected saved() {
|
||||
this.onSaved.emit();
|
||||
}
|
||||
}
|
||||
11
jslib/angular/src/components/icon.component.html
Normal file
11
jslib/angular/src/components/icon.component.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<div class="icon" aria-hidden="true">
|
||||
<img
|
||||
[src]="image"
|
||||
appFallbackSrc="{{ fallbackImage }}"
|
||||
*ngIf="imageEnabled && image"
|
||||
alt=""
|
||||
decoding="async"
|
||||
loading="lazy"
|
||||
/>
|
||||
<i class="bwi bwi-fw bwi-lg {{ icon }}" *ngIf="!imageEnabled || !image"></i>
|
||||
</div>
|
||||
112
jslib/angular/src/components/icon.component.ts
Normal file
112
jslib/angular/src/components/icon.component.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import { Component, Input, OnChanges } from "@angular/core";
|
||||
|
||||
import { EnvironmentService } from "@/jslib/common/src/abstractions/environment.service";
|
||||
import { StateService } from "@/jslib/common/src/abstractions/state.service";
|
||||
import { CipherType } from "@/jslib/common/src/enums/cipherType";
|
||||
import { Utils } from "@/jslib/common/src/misc/utils";
|
||||
import { CipherView } from "@/jslib/common/src/models/view/cipherView";
|
||||
|
||||
/**
|
||||
* Provides a mapping from supported card brands to
|
||||
* the filenames of icon that should be present in images/cards folder of clients.
|
||||
*/
|
||||
const cardIcons: Record<string, string> = {
|
||||
Visa: "card-visa",
|
||||
Mastercard: "card-mastercard",
|
||||
Amex: "card-amex",
|
||||
Discover: "card-discover",
|
||||
"Diners Club": "card-diners-club",
|
||||
JCB: "card-jcb",
|
||||
Maestro: "card-maestro",
|
||||
UnionPay: "card-union-pay",
|
||||
};
|
||||
|
||||
@Component({
|
||||
selector: "app-vault-icon",
|
||||
templateUrl: "icon.component.html",
|
||||
})
|
||||
export class IconComponent implements OnChanges {
|
||||
@Input() cipher: CipherView;
|
||||
icon: string;
|
||||
image: string;
|
||||
fallbackImage: string;
|
||||
imageEnabled: boolean;
|
||||
|
||||
private iconsUrl: string;
|
||||
|
||||
constructor(environmentService: EnvironmentService, private stateService: StateService) {
|
||||
this.iconsUrl = environmentService.getIconsUrl();
|
||||
}
|
||||
|
||||
async ngOnChanges() {
|
||||
// Components may be re-used when using cdk-virtual-scroll. Which puts the component in a weird state,
|
||||
// to avoid this we reset all state variables.
|
||||
this.image = null;
|
||||
this.fallbackImage = null;
|
||||
this.imageEnabled = !(await this.stateService.getDisableFavicon());
|
||||
this.load();
|
||||
}
|
||||
|
||||
protected load() {
|
||||
switch (this.cipher.type) {
|
||||
case CipherType.Login:
|
||||
this.icon = "bwi-globe";
|
||||
this.setLoginIcon();
|
||||
break;
|
||||
case CipherType.SecureNote:
|
||||
this.icon = "bwi-sticky-note";
|
||||
break;
|
||||
case CipherType.Card:
|
||||
this.icon = "bwi-credit-card";
|
||||
this.setCardIcon();
|
||||
break;
|
||||
case CipherType.Identity:
|
||||
this.icon = "bwi-id-card";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private setLoginIcon() {
|
||||
if (this.cipher.login.uri) {
|
||||
let hostnameUri = this.cipher.login.uri;
|
||||
let isWebsite = false;
|
||||
|
||||
if (hostnameUri.indexOf("androidapp://") === 0) {
|
||||
this.icon = "bwi-android";
|
||||
this.image = null;
|
||||
} else if (hostnameUri.indexOf("iosapp://") === 0) {
|
||||
this.icon = "bwi-apple";
|
||||
this.image = null;
|
||||
} else if (
|
||||
this.imageEnabled &&
|
||||
hostnameUri.indexOf("://") === -1 &&
|
||||
hostnameUri.indexOf(".") > -1
|
||||
) {
|
||||
hostnameUri = "http://" + hostnameUri;
|
||||
isWebsite = true;
|
||||
} else if (this.imageEnabled) {
|
||||
isWebsite = hostnameUri.indexOf("http") === 0 && hostnameUri.indexOf(".") > -1;
|
||||
}
|
||||
|
||||
if (this.imageEnabled && isWebsite) {
|
||||
try {
|
||||
this.image = this.iconsUrl + "/" + Utils.getHostname(hostnameUri) + "/icon.png";
|
||||
this.fallbackImage = "images/bwi-globe.png";
|
||||
} catch (e) {
|
||||
// Ignore error since the fallback icon will be shown if image is null.
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.image = null;
|
||||
}
|
||||
}
|
||||
|
||||
private setCardIcon() {
|
||||
const brand = this.cipher.card.brand;
|
||||
if (this.imageEnabled && brand in cardIcons) {
|
||||
this.icon = "credit-card-icon " + cardIcons[brand];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
import { ConfigurableFocusTrap, ConfigurableFocusTrapFactory } from "@angular/cdk/a11y";
|
||||
import {
|
||||
AfterViewInit,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
ComponentRef,
|
||||
ElementRef,
|
||||
OnDestroy,
|
||||
Type,
|
||||
ViewChild,
|
||||
ViewContainerRef,
|
||||
} from "@angular/core";
|
||||
|
||||
import { ModalService } from "../../services/modal.service";
|
||||
|
||||
import { ModalRef } from "./modal.ref";
|
||||
|
||||
@Component({
|
||||
selector: "app-modal",
|
||||
template: "<ng-template #modalContent></ng-template>",
|
||||
})
|
||||
export class DynamicModalComponent implements AfterViewInit, OnDestroy {
|
||||
componentRef: ComponentRef<any>;
|
||||
|
||||
@ViewChild("modalContent", { read: ViewContainerRef, static: true })
|
||||
modalContentRef: ViewContainerRef;
|
||||
|
||||
childComponentType: Type<any>;
|
||||
setComponentParameters: (component: any) => void;
|
||||
|
||||
private focusTrap: ConfigurableFocusTrap;
|
||||
|
||||
constructor(
|
||||
private modalService: ModalService,
|
||||
private cd: ChangeDetectorRef,
|
||||
private el: ElementRef<HTMLElement>,
|
||||
private focusTrapFactory: ConfigurableFocusTrapFactory,
|
||||
public modalRef: ModalRef
|
||||
) {}
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.loadChildComponent(this.childComponentType);
|
||||
if (this.setComponentParameters != null) {
|
||||
this.setComponentParameters(this.componentRef.instance);
|
||||
}
|
||||
this.cd.detectChanges();
|
||||
|
||||
this.modalRef.created(this.el.nativeElement);
|
||||
this.focusTrap = this.focusTrapFactory.create(
|
||||
this.el.nativeElement.querySelector(".modal-dialog")
|
||||
);
|
||||
if (this.el.nativeElement.querySelector("[appAutoFocus]") == null) {
|
||||
this.focusTrap.focusFirstTabbableElementWhenReady();
|
||||
}
|
||||
}
|
||||
|
||||
loadChildComponent(componentType: Type<any>) {
|
||||
const componentFactory = this.modalService.resolveComponentFactory(componentType);
|
||||
|
||||
this.modalContentRef.clear();
|
||||
this.componentRef = this.modalContentRef.createComponent(componentFactory);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.componentRef) {
|
||||
this.componentRef.destroy();
|
||||
}
|
||||
this.focusTrap.destroy();
|
||||
}
|
||||
|
||||
close() {
|
||||
this.modalRef.close();
|
||||
}
|
||||
|
||||
getFocus() {
|
||||
const autoFocusEl = this.el.nativeElement.querySelector("[appAutoFocus]") as HTMLElement;
|
||||
autoFocusEl?.focus();
|
||||
}
|
||||
}
|
||||
18
jslib/angular/src/components/modal/modal-injector.ts
Normal file
18
jslib/angular/src/components/modal/modal-injector.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { InjectFlags, InjectOptions, Injector, ProviderToken } from "@angular/core";
|
||||
|
||||
export class ModalInjector implements Injector {
|
||||
constructor(private _parentInjector: Injector, private _additionalTokens: WeakMap<any, any>) {}
|
||||
|
||||
get<T>(
|
||||
token: ProviderToken<T>,
|
||||
notFoundValue: undefined,
|
||||
options: InjectOptions & { optional?: false }
|
||||
): T;
|
||||
get<T>(token: ProviderToken<T>, notFoundValue: null, options: InjectOptions): T;
|
||||
get<T>(token: ProviderToken<T>, notFoundValue?: T, options?: InjectOptions | InjectFlags): T;
|
||||
get<T>(token: ProviderToken<T>, notFoundValue?: T, flags?: InjectFlags): T;
|
||||
get(token: any, notFoundValue?: any): any;
|
||||
get(token: any, notFoundValue?: any, flags?: any): any {
|
||||
return this._additionalTokens.get(token) ?? this._parentInjector.get<any>(token, notFoundValue);
|
||||
}
|
||||
}
|
||||
50
jslib/angular/src/components/modal/modal.ref.ts
Normal file
50
jslib/angular/src/components/modal/modal.ref.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { Observable, Subject } from "rxjs";
|
||||
import { first } from "rxjs/operators";
|
||||
|
||||
export class ModalRef {
|
||||
onCreated: Observable<HTMLElement>; // Modal added to the DOM.
|
||||
onClose: Observable<any>; // Initiated close.
|
||||
onClosed: Observable<any>; // Modal was closed (Remove element from DOM)
|
||||
onShow: Observable<void>; // Start showing modal
|
||||
onShown: Observable<void>; // Modal is fully visible
|
||||
|
||||
private readonly _onCreated = new Subject<HTMLElement>();
|
||||
private readonly _onClose = new Subject<any>();
|
||||
private readonly _onClosed = new Subject<any>();
|
||||
private readonly _onShow = new Subject<void>();
|
||||
private readonly _onShown = new Subject<void>();
|
||||
private lastResult: any;
|
||||
|
||||
constructor() {
|
||||
this.onCreated = this._onCreated.asObservable();
|
||||
this.onClose = this._onClose.asObservable();
|
||||
this.onClosed = this._onClosed.asObservable();
|
||||
this.onShow = this._onShow.asObservable();
|
||||
this.onShown = this._onShow.asObservable();
|
||||
}
|
||||
|
||||
show() {
|
||||
this._onShow.next();
|
||||
}
|
||||
|
||||
shown() {
|
||||
this._onShown.next();
|
||||
}
|
||||
|
||||
close(result?: any) {
|
||||
this.lastResult = result;
|
||||
this._onClose.next(result);
|
||||
}
|
||||
|
||||
closed() {
|
||||
this._onClosed.next(this.lastResult);
|
||||
}
|
||||
|
||||
created(el: HTMLElement) {
|
||||
this._onCreated.next(el);
|
||||
}
|
||||
|
||||
onClosedPromise(): Promise<any> {
|
||||
return this.onClosed.pipe(first()).toPromise();
|
||||
}
|
||||
}
|
||||
42
jslib/angular/src/components/password-reprompt.component.ts
Normal file
42
jslib/angular/src/components/password-reprompt.component.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { Directive } from "@angular/core";
|
||||
|
||||
import { ModalRef } from "./modal/modal.ref";
|
||||
|
||||
import { CryptoService } from "@/jslib/common/src/abstractions/crypto.service";
|
||||
import { I18nService } from "@/jslib/common/src/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@/jslib/common/src/abstractions/platformUtils.service";
|
||||
|
||||
|
||||
/**
|
||||
* Used to verify the user's Master Password for the "Master Password Re-prompt" feature only.
|
||||
* See UserVerificationComponent for any other situation where you need to verify the user's identity.
|
||||
*/
|
||||
@Directive()
|
||||
export class PasswordRepromptComponent {
|
||||
showPassword = false;
|
||||
masterPassword = "";
|
||||
|
||||
constructor(
|
||||
private modalRef: ModalRef,
|
||||
private cryptoService: CryptoService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService
|
||||
) {}
|
||||
|
||||
togglePassword() {
|
||||
this.showPassword = !this.showPassword;
|
||||
}
|
||||
|
||||
async submit() {
|
||||
if (!(await this.cryptoService.compareAndUpdateKeyHash(this.masterPassword, null))) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
this.i18nService.t("invalidMasterPassword")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
this.modalRef.close(true);
|
||||
}
|
||||
}
|
||||
95
jslib/angular/src/components/toastr.component.ts
Normal file
95
jslib/angular/src/components/toastr.component.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
import { animate, state, style, transition, trigger } from "@angular/animations";
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { Component, ModuleWithProviders, NgModule } from "@angular/core";
|
||||
import {
|
||||
DefaultNoComponentGlobalConfig,
|
||||
GlobalConfig,
|
||||
Toast as BaseToast,
|
||||
ToastPackage,
|
||||
ToastrService,
|
||||
TOAST_CONFIG,
|
||||
} from "ngx-toastr";
|
||||
|
||||
@Component({
|
||||
selector: "[toast-component2]",
|
||||
template: `
|
||||
<button
|
||||
*ngIf="options.closeButton"
|
||||
(click)="remove()"
|
||||
type="button"
|
||||
class="toast-close-button"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<div class="icon">
|
||||
<i></i>
|
||||
</div>
|
||||
<div>
|
||||
<div *ngIf="title" [class]="options.titleClass" [attr.aria-label]="title">
|
||||
{{ title }} <ng-container *ngIf="duplicatesCount">[{{ duplicatesCount + 1 }}]</ng-container>
|
||||
</div>
|
||||
<div
|
||||
*ngIf="message && options.enableHtml"
|
||||
role="alertdialog"
|
||||
aria-live="polite"
|
||||
[class]="options.messageClass"
|
||||
[innerHTML]="message"
|
||||
></div>
|
||||
<div
|
||||
*ngIf="message && !options.enableHtml"
|
||||
role="alertdialog"
|
||||
aria-live="polite"
|
||||
[class]="options.messageClass"
|
||||
[attr.aria-label]="message"
|
||||
>
|
||||
{{ message }}
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="options.progressBar">
|
||||
<div class="toast-progress" [style.width]="width + '%'"></div>
|
||||
</div>
|
||||
`,
|
||||
animations: [
|
||||
trigger("flyInOut", [
|
||||
state("inactive", style({ opacity: 0 })),
|
||||
state("active", style({ opacity: 1 })),
|
||||
state("removed", style({ opacity: 0 })),
|
||||
transition("inactive => active", animate("{{ easeTime }}ms {{ easing }}")),
|
||||
transition("active => removed", animate("{{ easeTime }}ms {{ easing }}")),
|
||||
]),
|
||||
],
|
||||
preserveWhitespaces: false,
|
||||
})
|
||||
export class BitwardenToast extends BaseToast {
|
||||
constructor(protected toastrService: ToastrService, public toastPackage: ToastPackage) {
|
||||
super(toastrService, toastPackage);
|
||||
}
|
||||
}
|
||||
|
||||
export const BitwardenToastGlobalConfig: GlobalConfig = {
|
||||
...DefaultNoComponentGlobalConfig,
|
||||
toastComponent: BitwardenToast,
|
||||
};
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule],
|
||||
declarations: [BitwardenToast],
|
||||
exports: [BitwardenToast],
|
||||
})
|
||||
export class BitwardenToastModule {
|
||||
static forRoot(config: Partial<GlobalConfig> = {}): ModuleWithProviders<BitwardenToastModule> {
|
||||
return {
|
||||
ngModule: BitwardenToastModule,
|
||||
providers: [
|
||||
{
|
||||
provide: TOAST_CONFIG,
|
||||
useValue: {
|
||||
default: BitwardenToastGlobalConfig,
|
||||
config: config,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
23
jslib/angular/src/directives/a11y-title.directive.ts
Normal file
23
jslib/angular/src/directives/a11y-title.directive.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { Directive, ElementRef, Input, Renderer2 } from "@angular/core";
|
||||
|
||||
@Directive({
|
||||
selector: "[appA11yTitle]",
|
||||
})
|
||||
export class A11yTitleDirective {
|
||||
@Input() set appA11yTitle(title: string) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
private title: string;
|
||||
|
||||
constructor(private el: ElementRef, private renderer: Renderer2) {}
|
||||
|
||||
ngOnInit() {
|
||||
if (!this.el.nativeElement.hasAttribute("title")) {
|
||||
this.renderer.setAttribute(this.el.nativeElement, "title", this.title);
|
||||
}
|
||||
if (!this.el.nativeElement.hasAttribute("aria-label")) {
|
||||
this.renderer.setAttribute(this.el.nativeElement, "aria-label", this.title);
|
||||
}
|
||||
}
|
||||
}
|
||||
50
jslib/angular/src/directives/api-action.directive.ts
Normal file
50
jslib/angular/src/directives/api-action.directive.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { Directive, ElementRef, Input, OnChanges } from "@angular/core";
|
||||
|
||||
import { ValidationService } from "../services/validation.service";
|
||||
|
||||
import { LogService } from "@/jslib/common/src/abstractions/log.service";
|
||||
import { ErrorResponse } from "@/jslib/common/src/models/response/errorResponse";
|
||||
|
||||
|
||||
/**
|
||||
* Provides error handling, in particular for any error returned by the server in an api call.
|
||||
* Attach it to a <form> element and provide the name of the class property that will hold the api call promise.
|
||||
* e.g. <form [appApiAction]="this.formPromise">
|
||||
* Any errors/rejections that occur will be intercepted and displayed as error toasts.
|
||||
*/
|
||||
@Directive({
|
||||
selector: "[appApiAction]",
|
||||
})
|
||||
export class ApiActionDirective implements OnChanges {
|
||||
@Input() appApiAction: Promise<any>;
|
||||
|
||||
constructor(
|
||||
private el: ElementRef,
|
||||
private validationService: ValidationService,
|
||||
private logService: LogService
|
||||
) {}
|
||||
|
||||
ngOnChanges(changes: any) {
|
||||
if (this.appApiAction == null || this.appApiAction.then == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.el.nativeElement.loading = true;
|
||||
|
||||
this.appApiAction.then(
|
||||
(response: any) => {
|
||||
this.el.nativeElement.loading = false;
|
||||
},
|
||||
(e: any) => {
|
||||
this.el.nativeElement.loading = false;
|
||||
|
||||
if ((e as ErrorResponse).captchaRequired) {
|
||||
this.logService.error("Captcha required error response: " + e.getSingleMessage());
|
||||
return;
|
||||
}
|
||||
this.logService?.error(`Received API exception: ${e}`);
|
||||
this.validationService.showError(e);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
27
jslib/angular/src/directives/autofocus.directive.ts
Normal file
27
jslib/angular/src/directives/autofocus.directive.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Directive, ElementRef, Input, NgZone } from "@angular/core";
|
||||
import { take } from "rxjs/operators";
|
||||
|
||||
import { Utils } from "@/jslib/common/src/misc/utils";
|
||||
|
||||
@Directive({
|
||||
selector: "[appAutofocus]",
|
||||
})
|
||||
export class AutofocusDirective {
|
||||
@Input() set appAutofocus(condition: boolean | string) {
|
||||
this.autofocus = condition === "" || condition === true;
|
||||
}
|
||||
|
||||
private autofocus: boolean;
|
||||
|
||||
constructor(private el: ElementRef, private ngZone: NgZone) {}
|
||||
|
||||
ngOnInit() {
|
||||
if (!Utils.isMobileBrowser && this.autofocus) {
|
||||
if (this.ngZone.isStable) {
|
||||
this.el.nativeElement.focus();
|
||||
} else {
|
||||
this.ngZone.onStable.pipe(take(1)).subscribe(() => this.el.nativeElement.focus());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
jslib/angular/src/directives/blur-click.directive.ts
Normal file
12
jslib/angular/src/directives/blur-click.directive.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Directive, ElementRef, HostListener } from "@angular/core";
|
||||
|
||||
@Directive({
|
||||
selector: "[appBlurClick]",
|
||||
})
|
||||
export class BlurClickDirective {
|
||||
constructor(private el: ElementRef) {}
|
||||
|
||||
@HostListener("click") onClick() {
|
||||
this.el.nativeElement.blur();
|
||||
}
|
||||
}
|
||||
59
jslib/angular/src/directives/box-row.directive.ts
Normal file
59
jslib/angular/src/directives/box-row.directive.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { Directive, ElementRef, HostListener, OnInit } from "@angular/core";
|
||||
|
||||
@Directive({
|
||||
selector: "[appBoxRow]",
|
||||
})
|
||||
export class BoxRowDirective implements OnInit {
|
||||
el: HTMLElement = null;
|
||||
formEls: Element[];
|
||||
|
||||
constructor(elRef: ElementRef) {
|
||||
this.el = elRef.nativeElement;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.formEls = Array.from(
|
||||
this.el.querySelectorAll('input:not([type="hidden"]), select, textarea')
|
||||
);
|
||||
this.formEls.forEach((formEl) => {
|
||||
formEl.addEventListener(
|
||||
"focus",
|
||||
() => {
|
||||
this.el.classList.add("active");
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
formEl.addEventListener(
|
||||
"blur",
|
||||
() => {
|
||||
this.el.classList.remove("active");
|
||||
},
|
||||
false
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@HostListener("click", ["$event"]) onClick(event: Event) {
|
||||
const target = event.target as HTMLElement;
|
||||
if (
|
||||
target !== this.el &&
|
||||
!target.classList.contains("progress") &&
|
||||
!target.classList.contains("progress-bar")
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.formEls.length > 0) {
|
||||
const formEl = this.formEls[0] as HTMLElement;
|
||||
if (formEl.tagName.toLowerCase() === "input") {
|
||||
const inputEl = formEl as HTMLInputElement;
|
||||
if (inputEl.type != null && inputEl.type.toLowerCase() === "checkbox") {
|
||||
inputEl.click();
|
||||
return;
|
||||
}
|
||||
}
|
||||
formEl.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
14
jslib/angular/src/directives/fallback-src.directive.ts
Normal file
14
jslib/angular/src/directives/fallback-src.directive.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { Directive, ElementRef, HostListener, Input } from "@angular/core";
|
||||
|
||||
@Directive({
|
||||
selector: "[appFallbackSrc]",
|
||||
})
|
||||
export class FallbackSrcDirective {
|
||||
@Input("appFallbackSrc") appFallbackSrc: string;
|
||||
|
||||
constructor(private el: ElementRef) {}
|
||||
|
||||
@HostListener("error") onError() {
|
||||
this.el.nativeElement.src = this.appFallbackSrc;
|
||||
}
|
||||
}
|
||||
10
jslib/angular/src/directives/stop-click.directive.ts
Normal file
10
jslib/angular/src/directives/stop-click.directive.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Directive, HostListener } from "@angular/core";
|
||||
|
||||
@Directive({
|
||||
selector: "[appStopClick]",
|
||||
})
|
||||
export class StopClickDirective {
|
||||
@HostListener("click", ["$event"]) onClick($event: MouseEvent) {
|
||||
$event.preventDefault();
|
||||
}
|
||||
}
|
||||
10
jslib/angular/src/directives/stop-prop.directive.ts
Normal file
10
jslib/angular/src/directives/stop-prop.directive.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Directive, HostListener } from "@angular/core";
|
||||
|
||||
@Directive({
|
||||
selector: "[appStopProp]",
|
||||
})
|
||||
export class StopPropDirective {
|
||||
@HostListener("click", ["$event"]) onClick($event: MouseEvent) {
|
||||
$event.stopPropagation();
|
||||
}
|
||||
}
|
||||
14
jslib/angular/src/pipes/i18n.pipe.ts
Normal file
14
jslib/angular/src/pipes/i18n.pipe.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { Pipe, PipeTransform } from "@angular/core";
|
||||
|
||||
import { I18nService } from "@/jslib/common/src/abstractions/i18n.service";
|
||||
|
||||
@Pipe({
|
||||
name: "i18n",
|
||||
})
|
||||
export class I18nPipe implements PipeTransform {
|
||||
constructor(private i18nService: I18nService) {}
|
||||
|
||||
transform(id: string, p1?: string, p2?: string, p3?: string): string {
|
||||
return this.i18nService.t(id, p1, p2, p3);
|
||||
}
|
||||
}
|
||||
41
jslib/angular/src/pipes/search-ciphers.pipe.ts
Normal file
41
jslib/angular/src/pipes/search-ciphers.pipe.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { Pipe, PipeTransform } from "@angular/core";
|
||||
|
||||
import { CipherView } from "@/jslib/common/src/models/view/cipherView";
|
||||
|
||||
@Pipe({
|
||||
name: "searchCiphers",
|
||||
})
|
||||
export class SearchCiphersPipe implements PipeTransform {
|
||||
transform(ciphers: CipherView[], searchText: string, deleted = false): CipherView[] {
|
||||
if (ciphers == null || ciphers.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (searchText == null || searchText.length < 2) {
|
||||
return ciphers.filter((c) => {
|
||||
return deleted !== c.isDeleted;
|
||||
});
|
||||
}
|
||||
|
||||
searchText = searchText.trim().toLowerCase();
|
||||
return ciphers.filter((c) => {
|
||||
if (deleted !== c.isDeleted) {
|
||||
return false;
|
||||
}
|
||||
if (c.name != null && c.name.toLowerCase().indexOf(searchText) > -1) {
|
||||
return true;
|
||||
}
|
||||
if (searchText.length >= 8 && c.id.startsWith(searchText)) {
|
||||
return true;
|
||||
}
|
||||
if (c.subTitle != null && c.subTitle.toLowerCase().indexOf(searchText) > -1) {
|
||||
return true;
|
||||
}
|
||||
if (c.login && c.login.uri != null && c.login.uri.toLowerCase().indexOf(searchText) > -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
170
jslib/angular/src/scss/bwicons/fonts/bwi-font.svg
Normal file
170
jslib/angular/src/scss/bwicons/fonts/bwi-font.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 262 KiB |
BIN
jslib/angular/src/scss/bwicons/fonts/bwi-font.ttf
Normal file
BIN
jslib/angular/src/scss/bwicons/fonts/bwi-font.ttf
Normal file
Binary file not shown.
BIN
jslib/angular/src/scss/bwicons/fonts/bwi-font.woff
Normal file
BIN
jslib/angular/src/scss/bwicons/fonts/bwi-font.woff
Normal file
Binary file not shown.
BIN
jslib/angular/src/scss/bwicons/fonts/bwi-font.woff2
Normal file
BIN
jslib/angular/src/scss/bwicons/fonts/bwi-font.woff2
Normal file
Binary file not shown.
250
jslib/angular/src/scss/bwicons/styles/style.scss
Normal file
250
jslib/angular/src/scss/bwicons/styles/style.scss
Normal file
@@ -0,0 +1,250 @@
|
||||
$icomoon-font-family: "bwi-font" !default;
|
||||
$icomoon-font-path: "/jslib/angular/src/scss/bwicons/fonts/" !default;
|
||||
|
||||
// New font sheet? Update the font-face information below
|
||||
@font-face {
|
||||
font-family: "#{$icomoon-font-family}";
|
||||
src: url($icomoon-font-path + "bwi-font.svg") format("svg"),
|
||||
url($icomoon-font-path + "bwi-font.ttf") format("truetype"),
|
||||
url($icomoon-font-path + "bwi-font.woff") format("woff"),
|
||||
url($icomoon-font-path + "bwi-font.woff2") format("woff2");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
}
|
||||
|
||||
// Base Class
|
||||
.bwi {
|
||||
/* use !important to prevent issues with browser extensions that change fonts */
|
||||
font-family: "#{$icomoon-font-family}" !important;
|
||||
speak: never;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
line-height: 1;
|
||||
display: inline-block;
|
||||
/* Better Font Rendering */
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
// Fixed Width Icons
|
||||
.bwi-fw {
|
||||
width: calc(18em / 14);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
// Sizing Changes
|
||||
.bwi-sm {
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
.bwi-lg {
|
||||
font-size: calc(4em / 3);
|
||||
line-height: calc(3em / 4);
|
||||
vertical-align: -15%;
|
||||
}
|
||||
|
||||
.bwi-2x {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
.bwi-3x {
|
||||
font-size: 3em;
|
||||
}
|
||||
|
||||
.bwi-4x {
|
||||
font-size: 4em;
|
||||
}
|
||||
|
||||
// Spin Animations
|
||||
.bwi-spin {
|
||||
animation: bwi-spin 2s infinite linear;
|
||||
}
|
||||
|
||||
@keyframes bwi-spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
|
||||
// List Icons
|
||||
.bwi-ul {
|
||||
padding-left: 0;
|
||||
margin-left: calc(30em / 14);
|
||||
list-style-type: none;
|
||||
> li {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.bwi-li {
|
||||
position: absolute;
|
||||
left: calc(-30em / 14);
|
||||
width: calc(30em / 14);
|
||||
top: calc(2em / 14);
|
||||
text-align: center;
|
||||
&.bwi-lg {
|
||||
left: calc(-30em / 14) + calc(4em / 14);
|
||||
}
|
||||
}
|
||||
|
||||
// Rotation
|
||||
.bwi-rotate-270 {
|
||||
transform: rotate(270deg);
|
||||
}
|
||||
|
||||
// For new icons - add their glyph name and value to the map below
|
||||
$icons: (
|
||||
"save-changes": "\e988",
|
||||
"browser": "\e985",
|
||||
"mobile": "\e986",
|
||||
"cli": "\e987",
|
||||
"providers": "\e983",
|
||||
"vault": "\e984",
|
||||
"folder-closed-f": "\e982",
|
||||
"rocket": "\e9ee",
|
||||
"ellipsis-h": "\e9ef",
|
||||
"ellipsis-v": "\e9f0",
|
||||
"safari": "\e974",
|
||||
"opera": "\e975",
|
||||
"firefox": "\e976",
|
||||
"edge": "\e977",
|
||||
"chrome": "\e978",
|
||||
"star-f": "\e979",
|
||||
"arrow-circle-up": "\e97a",
|
||||
"arrow-circle-right": "\e97b",
|
||||
"arrow-circle-left": "\e97c",
|
||||
"arrow-circle-down": "\e97d",
|
||||
"undo": "\e97e",
|
||||
"bolt": "\e97f",
|
||||
"puzzle": "\e980",
|
||||
"rss": "\e973",
|
||||
"dbl-angle-left": "\e970",
|
||||
"dbl-angle-right": "\e971",
|
||||
"hamburger": "\e972",
|
||||
"bw-folder-open-f": "\e93e",
|
||||
"desktop": "\e96a",
|
||||
"angle-left": "\e96b",
|
||||
"user": "\e900",
|
||||
"user-f": "\e901",
|
||||
"key": "\e902",
|
||||
"share-square": "\e903",
|
||||
"hashtag": "\e904",
|
||||
"clone": "\e905",
|
||||
"list-alt": "\e906",
|
||||
"id-card": "\e907",
|
||||
"credit-card": "\e908",
|
||||
"globe": "\e909",
|
||||
"sticky-note": "\e90a",
|
||||
"folder": "\e90b",
|
||||
"lock": "\e90c",
|
||||
"lock-f": "\e90d",
|
||||
"generate": "\e90e",
|
||||
"generate-f": "\e90f",
|
||||
"cog": "\e910",
|
||||
"cog-f": "\e911",
|
||||
"check-circle": "\e912",
|
||||
"eye": "\e913",
|
||||
"pencil-square": "\e914",
|
||||
"bookmark": "\e915",
|
||||
"files": "\e916",
|
||||
"trash": "\e917",
|
||||
"plus": "\e918",
|
||||
"star": "\e919",
|
||||
"list": "\e91a",
|
||||
"angle-right": "\e91b",
|
||||
"external-link": "\e91c",
|
||||
"refresh": "\e91d",
|
||||
"search": "\e91f",
|
||||
"filter": "\e920",
|
||||
"plus-circle": "\e921",
|
||||
"user-circle": "\e922",
|
||||
"question-circle": "\e923",
|
||||
"cogs": "\e924",
|
||||
"minus-circle": "\e925",
|
||||
"send": "\e926",
|
||||
"send-f": "\e927",
|
||||
"download": "\e928",
|
||||
"pencil": "\e929",
|
||||
"sign-out": "\e92a",
|
||||
"share": "\e92b",
|
||||
"clock": "\e92c",
|
||||
"angle-down": "\e92d",
|
||||
"caret-down": "\e92e",
|
||||
"square": "\e92f",
|
||||
"collection": "\e930",
|
||||
"bank": "\e931",
|
||||
"shield": "\e932",
|
||||
"stop": "\e933",
|
||||
"plus-square": "\e934",
|
||||
"save": "\e935",
|
||||
"sign-in": "\e936",
|
||||
"spinner": "\e937",
|
||||
"dollar": "\e939",
|
||||
"check": "\e93a",
|
||||
"check-square": "\e93b",
|
||||
"minus-square": "\e93c",
|
||||
"close": "\e93d",
|
||||
"share-arrow": "\e96c",
|
||||
"paperclip": "\e93f",
|
||||
"bitcoin": "\e940",
|
||||
"cut": "\e941",
|
||||
"frown": "\e942",
|
||||
"folder-open": "\e943",
|
||||
"bug": "\e946",
|
||||
"chain-broken": "\e947",
|
||||
"dashboard": "\e948",
|
||||
"envelope": "\e949",
|
||||
"exclamation-circle": "\e94a",
|
||||
"exclamation-triangle": "\e94b",
|
||||
"caret-right": "\e94c",
|
||||
"file-pdf": "\e94e",
|
||||
"file-text": "\e94f",
|
||||
"info-circle": "\e952",
|
||||
"lightbulb": "\e953",
|
||||
"link": "\e954",
|
||||
"linux": "\e956",
|
||||
"long-arrow-right": "\e957",
|
||||
"money": "\e958",
|
||||
"play": "\e959",
|
||||
"reddit": "\e95a",
|
||||
"refresh-tab": "\e95b",
|
||||
"sitemap": "\e95c",
|
||||
"sliders": "\e95d",
|
||||
"tag": "\e95e",
|
||||
"thumb-tack": "\e95f",
|
||||
"thumbs-up": "\e960",
|
||||
"unlock": "\e962",
|
||||
"users": "\e963",
|
||||
"wrench": "\e965",
|
||||
"ban": "\e967",
|
||||
"camera": "\e968",
|
||||
"chevron-up": "\e969",
|
||||
"eye-slash": "\e96d",
|
||||
"file": "\e96e",
|
||||
"paste": "\e96f",
|
||||
"github": "\e950",
|
||||
"facebook": "\e94d",
|
||||
"paypal": "\e938",
|
||||
"google": "\e951",
|
||||
"linkedin": "\e955",
|
||||
"discourse": "\e91e",
|
||||
"twitter": "\e961",
|
||||
"youtube": "\e966",
|
||||
"windows": "\e964",
|
||||
"apple": "\e945",
|
||||
"android": "\e944",
|
||||
"error": "\e981",
|
||||
"numbered-list": "\e989",
|
||||
);
|
||||
|
||||
@each $name, $glyph in $icons {
|
||||
.bwi-#{$name}:before {
|
||||
content: $glyph;
|
||||
}
|
||||
}
|
||||
44
jslib/angular/src/scss/icons.scss
Normal file
44
jslib/angular/src/scss/icons.scss
Normal file
@@ -0,0 +1,44 @@
|
||||
$card-icons-base: "~@bitwarden/jslib-angular/src/images/cards/";
|
||||
$card-icons: (
|
||||
"visa": $card-icons-base + "visa-light.png",
|
||||
"amex": $card-icons-base + "amex-light.png",
|
||||
"diners-club": $card-icons-base + "diners_club-light.png",
|
||||
"discover": $card-icons-base + "discover-light.png",
|
||||
"jcb": $card-icons-base + "jcb-light.png",
|
||||
"maestro": $card-icons-base + "maestro-light.png",
|
||||
"mastercard": $card-icons-base + "mastercard-light.png",
|
||||
"union-pay": $card-icons-base + "union_pay-light.png",
|
||||
);
|
||||
|
||||
$card-icons-dark: (
|
||||
"visa": $card-icons-base + "visa-dark.png",
|
||||
"amex": $card-icons-base + "amex-dark.png",
|
||||
"diners-club": $card-icons-base + "diners_club-dark.png",
|
||||
"discover": $card-icons-base + "discover-dark.png",
|
||||
"jcb": $card-icons-base + "jcb-dark.png",
|
||||
"maestro": $card-icons-base + "maestro-dark.png",
|
||||
"mastercard": $card-icons-base + "mastercard-dark.png",
|
||||
"union-pay": $card-icons-base + "union_pay-dark.png",
|
||||
);
|
||||
|
||||
.credit-card-icon {
|
||||
display: block; // Resolves the parent container being slighly to big
|
||||
height: 19px;
|
||||
width: 24px;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
@each $name, $url in $card-icons {
|
||||
.card-#{$name} {
|
||||
background-image: url("#{$url}");
|
||||
}
|
||||
}
|
||||
|
||||
@each $theme in $dark-icon-themes {
|
||||
@each $name, $url in $card-icons-dark {
|
||||
.#{$theme} .card-#{$name} {
|
||||
background-image: url("#{$url}");
|
||||
}
|
||||
}
|
||||
}
|
||||
89
jslib/angular/src/scss/webfonts.css
Normal file
89
jslib/angular/src/scss/webfonts.css
Normal file
@@ -0,0 +1,89 @@
|
||||
@font-face {
|
||||
font-family: "Open Sans";
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
font-display: auto;
|
||||
src: url(webfonts/Open_Sans-italic-300.woff) format("woff");
|
||||
unicode-range: U+0-10FFFF;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Open Sans";
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: auto;
|
||||
src: url(webfonts/Open_Sans-italic-400.woff) format("woff");
|
||||
unicode-range: U+0-10FFFF;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Open Sans";
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
font-display: auto;
|
||||
src: url(webfonts/Open_Sans-italic-600.woff) format("woff");
|
||||
unicode-range: U+0-10FFFF;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Open Sans";
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: auto;
|
||||
src: url(webfonts/Open_Sans-italic-700.woff) format("woff");
|
||||
unicode-range: U+0-10FFFF;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Open Sans";
|
||||
font-style: italic;
|
||||
font-weight: 800;
|
||||
font-display: auto;
|
||||
src: url(webfonts/Open_Sans-italic-800.woff) format("woff");
|
||||
unicode-range: U+0-10FFFF;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-display: auto;
|
||||
src: url(webfonts/Open_Sans-normal-300.woff) format("woff");
|
||||
unicode-range: U+0-10FFFF;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: auto;
|
||||
src: url(webfonts/Open_Sans-normal-400.woff) format("woff");
|
||||
unicode-range: U+0-10FFFF;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: auto;
|
||||
src: url(webfonts/Open_Sans-normal-600.woff) format("woff");
|
||||
unicode-range: U+0-10FFFF;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: auto;
|
||||
src: url(webfonts/Open_Sans-normal-700.woff) format("woff");
|
||||
unicode-range: U+0-10FFFF;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 800;
|
||||
font-display: auto;
|
||||
src: url(webfonts/Open_Sans-normal-800.woff) format("woff");
|
||||
unicode-range: U+0-10FFFF;
|
||||
}
|
||||
BIN
jslib/angular/src/scss/webfonts/Open_Sans-italic-300.woff
Normal file
BIN
jslib/angular/src/scss/webfonts/Open_Sans-italic-300.woff
Normal file
Binary file not shown.
BIN
jslib/angular/src/scss/webfonts/Open_Sans-italic-400.woff
Normal file
BIN
jslib/angular/src/scss/webfonts/Open_Sans-italic-400.woff
Normal file
Binary file not shown.
BIN
jslib/angular/src/scss/webfonts/Open_Sans-italic-600.woff
Normal file
BIN
jslib/angular/src/scss/webfonts/Open_Sans-italic-600.woff
Normal file
Binary file not shown.
BIN
jslib/angular/src/scss/webfonts/Open_Sans-italic-700.woff
Normal file
BIN
jslib/angular/src/scss/webfonts/Open_Sans-italic-700.woff
Normal file
Binary file not shown.
BIN
jslib/angular/src/scss/webfonts/Open_Sans-italic-800.woff
Normal file
BIN
jslib/angular/src/scss/webfonts/Open_Sans-italic-800.woff
Normal file
Binary file not shown.
BIN
jslib/angular/src/scss/webfonts/Open_Sans-normal-300.woff
Normal file
BIN
jslib/angular/src/scss/webfonts/Open_Sans-normal-300.woff
Normal file
Binary file not shown.
BIN
jslib/angular/src/scss/webfonts/Open_Sans-normal-400.woff
Normal file
BIN
jslib/angular/src/scss/webfonts/Open_Sans-normal-400.woff
Normal file
Binary file not shown.
BIN
jslib/angular/src/scss/webfonts/Open_Sans-normal-600.woff
Normal file
BIN
jslib/angular/src/scss/webfonts/Open_Sans-normal-600.woff
Normal file
Binary file not shown.
BIN
jslib/angular/src/scss/webfonts/Open_Sans-normal-700.woff
Normal file
BIN
jslib/angular/src/scss/webfonts/Open_Sans-normal-700.woff
Normal file
Binary file not shown.
BIN
jslib/angular/src/scss/webfonts/Open_Sans-normal-800.woff
Normal file
BIN
jslib/angular/src/scss/webfonts/Open_Sans-normal-800.woff
Normal file
Binary file not shown.
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;
|
||||
}
|
||||
}
|
||||
6
jslib/angular/src/services/broadcaster.service.ts
Normal file
6
jslib/angular/src/services/broadcaster.service.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { BroadcasterService as BaseBroadcasterService } from "@/jslib/common/src/services/broadcaster.service";
|
||||
|
||||
@Injectable()
|
||||
export class BroadcasterService extends BaseBroadcasterService {}
|
||||
493
jslib/angular/src/services/jslib-services.module.ts
Normal file
493
jslib/angular/src/services/jslib-services.module.ts
Normal file
@@ -0,0 +1,493 @@
|
||||
import { Injector, LOCALE_ID, NgModule } from "@angular/core";
|
||||
|
||||
import { AuthGuardService } from "./auth-guard.service";
|
||||
import { BroadcasterService } from "./broadcaster.service";
|
||||
import { LockGuardService } from "./lock-guard.service";
|
||||
import { ModalService } from "./modal.service";
|
||||
import { PasswordRepromptService } from "./passwordReprompt.service";
|
||||
import { UnauthGuardService } from "./unauth-guard.service";
|
||||
import { ValidationService } from "./validation.service";
|
||||
|
||||
import { ApiService as ApiServiceAbstraction } from "@/jslib/common/src/abstractions/api.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 { 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 { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@/jslib/common/src/abstractions/cryptoFunction.service";
|
||||
import { EnvironmentService as EnvironmentServiceAbstraction } from "@/jslib/common/src/abstractions/environment.service";
|
||||
import { EventService as EventServiceAbstraction } from "@/jslib/common/src/abstractions/event.service";
|
||||
import { ExportService as ExportServiceAbstraction } from "@/jslib/common/src/abstractions/export.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 { KeyConnectorService as KeyConnectorServiceAbstraction } from "@/jslib/common/src/abstractions/keyConnector.service";
|
||||
import { LogService } from "@/jslib/common/src/abstractions/log.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 { 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 { StateMigrationService as StateMigrationServiceAbstraction } from "@/jslib/common/src/abstractions/stateMigration.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 { 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 { Account } from "@/jslib/common/src/models/domain/account";
|
||||
import { GlobalState } from "@/jslib/common/src/models/domain/globalState";
|
||||
import { ApiService } from "@/jslib/common/src/services/api.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 { CryptoService } from "@/jslib/common/src/services/crypto.service";
|
||||
import { EnvironmentService } from "@/jslib/common/src/services/environment.service";
|
||||
import { EventService } from "@/jslib/common/src/services/event.service";
|
||||
import { ExportService } from "@/jslib/common/src/services/export.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 { 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 { 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 { WebCryptoFunctionService } from "@/jslib/common/src/services/webCryptoFunction.service";
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
providers: [
|
||||
{ provide: "WINDOW", useValue: window },
|
||||
{
|
||||
provide: LOCALE_ID,
|
||||
useFactory: (i18nService: I18nServiceAbstraction) => i18nService.translationLocale,
|
||||
deps: [I18nServiceAbstraction],
|
||||
},
|
||||
ValidationService,
|
||||
AuthGuardService,
|
||||
UnauthGuardService,
|
||||
LockGuardService,
|
||||
ModalService,
|
||||
{
|
||||
provide: AppIdServiceAbstraction,
|
||||
useClass: AppIdService,
|
||||
deps: [StorageServiceAbstraction],
|
||||
},
|
||||
{
|
||||
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,
|
||||
useClass: EnvironmentService,
|
||||
deps: [StateServiceAbstraction],
|
||||
},
|
||||
{
|
||||
provide: TotpServiceAbstraction,
|
||||
useClass: TotpService,
|
||||
deps: [CryptoFunctionServiceAbstraction, LogService, StateServiceAbstraction],
|
||||
},
|
||||
{ provide: TokenServiceAbstraction, useClass: TokenService, deps: [StateServiceAbstraction] },
|
||||
{
|
||||
provide: CryptoServiceAbstraction,
|
||||
useClass: CryptoService,
|
||||
deps: [
|
||||
CryptoFunctionServiceAbstraction,
|
||||
PlatformUtilsServiceAbstraction,
|
||||
LogService,
|
||||
StateServiceAbstraction,
|
||||
],
|
||||
},
|
||||
{
|
||||
provide: PasswordGenerationServiceAbstraction,
|
||||
useClass: PasswordGenerationService,
|
||||
deps: [CryptoServiceAbstraction, PolicyServiceAbstraction, StateServiceAbstraction],
|
||||
},
|
||||
{
|
||||
provide: UsernameGenerationServiceAbstraction,
|
||||
useClass: UsernameGenerationService,
|
||||
deps: [CryptoServiceAbstraction, StateServiceAbstraction],
|
||||
},
|
||||
{
|
||||
provide: ApiServiceAbstraction,
|
||||
useFactory: (
|
||||
tokenService: TokenServiceAbstraction,
|
||||
platformUtilsService: PlatformUtilsServiceAbstraction,
|
||||
environmentService: EnvironmentServiceAbstraction,
|
||||
messagingService: MessagingServiceAbstraction,
|
||||
appIdService: AppIdServiceAbstraction
|
||||
) =>
|
||||
new ApiService(
|
||||
tokenService,
|
||||
platformUtilsService,
|
||||
environmentService,
|
||||
appIdService,
|
||||
async (expired: boolean) => messagingService.send("logout", { expired: expired })
|
||||
),
|
||||
deps: [
|
||||
TokenServiceAbstraction,
|
||||
PlatformUtilsServiceAbstraction,
|
||||
EnvironmentServiceAbstraction,
|
||||
MessagingServiceAbstraction,
|
||||
AppIdServiceAbstraction,
|
||||
],
|
||||
},
|
||||
{
|
||||
provide: FileUploadServiceAbstraction,
|
||||
useClass: FileUploadService,
|
||||
deps: [LogService, ApiServiceAbstraction],
|
||||
},
|
||||
{
|
||||
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,
|
||||
useFactory: (
|
||||
storageService: StorageServiceAbstraction,
|
||||
secureStorageService: StorageServiceAbstraction,
|
||||
logService: LogService,
|
||||
stateMigrationService: StateMigrationServiceAbstraction
|
||||
) =>
|
||||
new StateService(
|
||||
storageService,
|
||||
secureStorageService,
|
||||
logService,
|
||||
stateMigrationService,
|
||||
new StateFactory(GlobalState, Account)
|
||||
),
|
||||
deps: [
|
||||
StorageServiceAbstraction,
|
||||
"SECURE_STORAGE",
|
||||
LogService,
|
||||
StateMigrationServiceAbstraction,
|
||||
],
|
||||
},
|
||||
{
|
||||
provide: StateMigrationServiceAbstraction,
|
||||
useFactory: (
|
||||
storageService: StorageServiceAbstraction,
|
||||
secureStorageService: StorageServiceAbstraction
|
||||
) =>
|
||||
new StateMigrationService(
|
||||
storageService,
|
||||
secureStorageService,
|
||||
new StateFactory(GlobalState, Account)
|
||||
),
|
||||
deps: [StorageServiceAbstraction, "SECURE_STORAGE"],
|
||||
},
|
||||
{
|
||||
provide: ExportServiceAbstraction,
|
||||
useClass: ExportService,
|
||||
deps: [
|
||||
FolderServiceAbstraction,
|
||||
CipherServiceAbstraction,
|
||||
ApiServiceAbstraction,
|
||||
CryptoServiceAbstraction,
|
||||
],
|
||||
},
|
||||
{
|
||||
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: CryptoFunctionServiceAbstraction,
|
||||
useClass: WebCryptoFunctionService,
|
||||
deps: ["WINDOW"],
|
||||
},
|
||||
{
|
||||
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 {}
|
||||
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;
|
||||
}
|
||||
}
|
||||
180
jslib/angular/src/services/modal.service.ts
Normal file
180
jslib/angular/src/services/modal.service.ts
Normal file
@@ -0,0 +1,180 @@
|
||||
import {
|
||||
ApplicationRef,
|
||||
ComponentFactory,
|
||||
ComponentFactoryResolver,
|
||||
ComponentRef,
|
||||
EmbeddedViewRef,
|
||||
Injectable,
|
||||
Injector,
|
||||
Type,
|
||||
ViewContainerRef,
|
||||
} from "@angular/core";
|
||||
import { first } from "rxjs/operators";
|
||||
|
||||
import { DynamicModalComponent } from "../components/modal/dynamic-modal.component";
|
||||
import { ModalInjector } from "../components/modal/modal-injector";
|
||||
import { ModalRef } from "../components/modal/modal.ref";
|
||||
|
||||
export class ModalConfig<D = any> {
|
||||
data?: D;
|
||||
allowMultipleModals = false;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class ModalService {
|
||||
protected modalList: ComponentRef<DynamicModalComponent>[] = [];
|
||||
|
||||
// Lazy loaded modules are not available in componentFactoryResolver,
|
||||
// therefore modules needs to manually initialize their resolvers.
|
||||
private factoryResolvers: Map<Type<any>, ComponentFactoryResolver> = new Map();
|
||||
|
||||
constructor(
|
||||
private componentFactoryResolver: ComponentFactoryResolver,
|
||||
private applicationRef: ApplicationRef,
|
||||
private injector: Injector
|
||||
) {
|
||||
document.addEventListener("keyup", (event) => {
|
||||
if (event.key === "Escape" && this.modalCount > 0) {
|
||||
this.topModal.instance.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
get modalCount() {
|
||||
return this.modalList.length;
|
||||
}
|
||||
|
||||
private get topModal() {
|
||||
return this.modalList[this.modalCount - 1];
|
||||
}
|
||||
|
||||
async openViewRef<T>(
|
||||
componentType: Type<T>,
|
||||
viewContainerRef: ViewContainerRef,
|
||||
setComponentParameters: (component: T) => void = null
|
||||
): Promise<[ModalRef, T]> {
|
||||
const [modalRef, modalComponentRef] = this.openInternal(componentType, null, false);
|
||||
modalComponentRef.instance.setComponentParameters = setComponentParameters;
|
||||
|
||||
viewContainerRef.insert(modalComponentRef.hostView);
|
||||
|
||||
await modalRef.onCreated.pipe(first()).toPromise();
|
||||
|
||||
return [modalRef, modalComponentRef.instance.componentRef.instance];
|
||||
}
|
||||
|
||||
open(componentType: Type<any>, config?: ModalConfig) {
|
||||
if (!(config?.allowMultipleModals ?? false) && this.modalCount > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line
|
||||
const [modalRef, _] = this.openInternal(componentType, config, true);
|
||||
|
||||
return modalRef;
|
||||
}
|
||||
|
||||
registerComponentFactoryResolver<T>(
|
||||
componentType: Type<T>,
|
||||
componentFactoryResolver: ComponentFactoryResolver
|
||||
): void {
|
||||
this.factoryResolvers.set(componentType, componentFactoryResolver);
|
||||
}
|
||||
|
||||
resolveComponentFactory<T>(componentType: Type<T>): ComponentFactory<T> {
|
||||
if (this.factoryResolvers.has(componentType)) {
|
||||
return this.factoryResolvers.get(componentType).resolveComponentFactory(componentType);
|
||||
}
|
||||
|
||||
return this.componentFactoryResolver.resolveComponentFactory(componentType);
|
||||
}
|
||||
|
||||
protected openInternal(
|
||||
componentType: Type<any>,
|
||||
config?: ModalConfig,
|
||||
attachToDom?: boolean
|
||||
): [ModalRef, ComponentRef<DynamicModalComponent>] {
|
||||
const [modalRef, componentRef] = this.createModalComponent(config);
|
||||
componentRef.instance.childComponentType = componentType;
|
||||
|
||||
if (attachToDom) {
|
||||
this.applicationRef.attachView(componentRef.hostView);
|
||||
const domElem = (componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0] as HTMLElement;
|
||||
document.body.appendChild(domElem);
|
||||
}
|
||||
|
||||
modalRef.onClosed.pipe(first()).subscribe(() => {
|
||||
if (attachToDom) {
|
||||
this.applicationRef.detachView(componentRef.hostView);
|
||||
}
|
||||
componentRef.destroy();
|
||||
|
||||
this.modalList.pop();
|
||||
if (this.modalCount > 0) {
|
||||
this.topModal.instance.getFocus();
|
||||
}
|
||||
});
|
||||
|
||||
this.setupHandlers(modalRef);
|
||||
|
||||
this.modalList.push(componentRef);
|
||||
|
||||
return [modalRef, componentRef];
|
||||
}
|
||||
|
||||
protected setupHandlers(modalRef: ModalRef) {
|
||||
let backdrop: HTMLElement = null;
|
||||
|
||||
// Add backdrop, setup [data-dismiss] handler.
|
||||
modalRef.onCreated.pipe(first()).subscribe((el) => {
|
||||
document.body.classList.add("modal-open");
|
||||
|
||||
const modalEl: HTMLElement = el.querySelector(".modal");
|
||||
const dialogEl = modalEl.querySelector(".modal-dialog") as HTMLElement;
|
||||
|
||||
backdrop = document.createElement("div");
|
||||
backdrop.className = "modal-backdrop fade";
|
||||
backdrop.style.zIndex = `${this.modalCount}040`;
|
||||
modalEl.prepend(backdrop);
|
||||
|
||||
dialogEl.addEventListener("click", (e: Event) => {
|
||||
e.stopPropagation();
|
||||
});
|
||||
dialogEl.style.zIndex = `${this.modalCount}050`;
|
||||
|
||||
const modals = Array.from(
|
||||
el.querySelectorAll('.modal-backdrop, .modal *[data-dismiss="modal"]')
|
||||
);
|
||||
for (const closeElement of modals) {
|
||||
closeElement.addEventListener("click", () => {
|
||||
modalRef.close();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// onClose is used in Web to hook into bootstrap. On other projects we pipe it directly to closed.
|
||||
modalRef.onClose.pipe(first()).subscribe(() => {
|
||||
modalRef.closed();
|
||||
|
||||
if (this.modalCount === 0) {
|
||||
document.body.classList.remove("modal-open");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected createModalComponent(
|
||||
config: ModalConfig
|
||||
): [ModalRef, ComponentRef<DynamicModalComponent>] {
|
||||
const modalRef = new ModalRef();
|
||||
|
||||
const map = new WeakMap();
|
||||
map.set(ModalConfig, config);
|
||||
map.set(ModalRef, modalRef);
|
||||
|
||||
const componentFactory =
|
||||
this.componentFactoryResolver.resolveComponentFactory(DynamicModalComponent);
|
||||
const componentRef = componentFactory.create(new ModalInjector(this.injector, map));
|
||||
|
||||
return [modalRef, componentRef];
|
||||
}
|
||||
}
|
||||
47
jslib/angular/src/services/passwordReprompt.service.ts
Normal file
47
jslib/angular/src/services/passwordReprompt.service.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { PasswordRepromptComponent } from "../components/password-reprompt.component";
|
||||
|
||||
import { ModalService } from "./modal.service";
|
||||
|
||||
import { KeyConnectorService } from "@/jslib/common/src/abstractions/keyConnector.service";
|
||||
import { PasswordRepromptService as PasswordRepromptServiceAbstraction } from "@/jslib/common/src/abstractions/passwordReprompt.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;
|
||||
}
|
||||
}
|
||||
38
jslib/angular/src/services/validation.service.ts
Normal file
38
jslib/angular/src/services/validation.service.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { I18nService } from "@/jslib/common/src/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@/jslib/common/src/abstractions/platformUtils.service";
|
||||
import { ErrorResponse } from "@/jslib/common/src/models/response/errorResponse";
|
||||
|
||||
@Injectable()
|
||||
export class ValidationService {
|
||||
constructor(
|
||||
private i18nService: I18nService,
|
||||
private platformUtilsService: PlatformUtilsService
|
||||
) {}
|
||||
|
||||
showError(data: any): string[] {
|
||||
const defaultErrorMessage = this.i18nService.t("unexpectedError");
|
||||
let errors: string[] = [];
|
||||
|
||||
if (data != null && typeof data === "string") {
|
||||
errors.push(data);
|
||||
} else if (data == null || typeof data !== "object") {
|
||||
errors.push(defaultErrorMessage);
|
||||
} else if (data.validationErrors != null) {
|
||||
errors = errors.concat((data as ErrorResponse).getAllMessages());
|
||||
} else {
|
||||
errors.push(data.message ? data.message : defaultErrorMessage);
|
||||
}
|
||||
|
||||
if (errors.length === 1) {
|
||||
this.platformUtilsService.showToast("error", this.i18nService.t("errorOccurred"), errors[0]);
|
||||
} else if (errors.length > 1) {
|
||||
this.platformUtilsService.showToast("error", this.i18nService.t("errorOccurred"), errors, {
|
||||
timeout: 5000 * errors.length,
|
||||
});
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
}
|
||||
679
jslib/common/src/abstractions/api.service.ts
Normal file
679
jslib/common/src/abstractions/api.service.ts
Normal file
@@ -0,0 +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 { PasswordTokenRequest } from "../models/request/identityToken/passwordTokenRequest";
|
||||
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 { OrganizationKeysRequest } from "../models/request/organizationKeysRequest";
|
||||
import { OrganizationSubscriptionUpdateRequest } from "../models/request/organizationSubscriptionUpdateRequest";
|
||||
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 {
|
||||
postIdentityToken: (
|
||||
request: PasswordTokenRequest | SsoTokenRequest | ApiTokenRequest
|
||||
) => 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>;
|
||||
|
||||
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>;
|
||||
}
|
||||
4
jslib/common/src/abstractions/appId.service.ts
Normal file
4
jslib/common/src/abstractions/appId.service.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export abstract class AppIdService {
|
||||
getAppId: () => Promise<string>;
|
||||
getAnonymousAppId: () => Promise<string>;
|
||||
}
|
||||
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;
|
||||
}
|
||||
5
jslib/common/src/abstractions/broadcaster.service.ts
Normal file
5
jslib/common/src/abstractions/broadcaster.service.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export abstract class BroadcasterService {
|
||||
send: (message: any, id?: string) => void;
|
||||
subscribe: (id: string, messageCallback: (message: any) => any) => void;
|
||||
unsubscribe: (id: string) => void;
|
||||
}
|
||||
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>;
|
||||
}
|
||||
86
jslib/common/src/abstractions/crypto.service.ts
Normal file
86
jslib/common/src/abstractions/crypto.service.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
import { HashPurpose } from "../enums/hashPurpose";
|
||||
import { KdfType } from "../enums/kdfType";
|
||||
import { KeySuffixOptions } from "../enums/keySuffixOptions";
|
||||
import { EncArrayBuffer } from "../models/domain/encArrayBuffer";
|
||||
import { EncString } from "../models/domain/encString";
|
||||
import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey";
|
||||
import { ProfileOrganizationResponse } from "../models/response/profileOrganizationResponse";
|
||||
import { ProfileProviderOrganizationResponse } from "../models/response/profileProviderOrganizationResponse";
|
||||
import { ProfileProviderResponse } from "../models/response/profileProviderResponse";
|
||||
|
||||
export abstract class CryptoService {
|
||||
setKey: (key: SymmetricCryptoKey) => Promise<any>;
|
||||
setKeyHash: (keyHash: string) => Promise<void>;
|
||||
setEncKey: (encKey: string) => Promise<void>;
|
||||
setEncPrivateKey: (encPrivateKey: string) => Promise<void>;
|
||||
setOrgKeys: (
|
||||
orgs: ProfileOrganizationResponse[],
|
||||
providerOrgs: ProfileProviderOrganizationResponse[]
|
||||
) => Promise<void>;
|
||||
setProviderKeys: (orgs: ProfileProviderResponse[]) => Promise<void>;
|
||||
getKey: (keySuffix?: KeySuffixOptions, userId?: string) => Promise<SymmetricCryptoKey>;
|
||||
getKeyFromStorage: (keySuffix: KeySuffixOptions, userId?: string) => Promise<SymmetricCryptoKey>;
|
||||
getKeyHash: () => Promise<string>;
|
||||
compareAndUpdateKeyHash: (masterPassword: string, key: SymmetricCryptoKey) => Promise<boolean>;
|
||||
getEncKey: (key?: SymmetricCryptoKey) => Promise<SymmetricCryptoKey>;
|
||||
getPublicKey: () => Promise<ArrayBuffer>;
|
||||
getPrivateKey: () => Promise<ArrayBuffer>;
|
||||
getFingerprint: (userId: string, publicKey?: ArrayBuffer) => Promise<string[]>;
|
||||
getOrgKeys: () => Promise<Map<string, SymmetricCryptoKey>>;
|
||||
getOrgKey: (orgId: string) => Promise<SymmetricCryptoKey>;
|
||||
getProviderKey: (providerId: string) => Promise<SymmetricCryptoKey>;
|
||||
hasKey: () => Promise<boolean>;
|
||||
hasKeyInMemory: (userId?: string) => Promise<boolean>;
|
||||
hasKeyStored: (keySuffix?: KeySuffixOptions, userId?: string) => Promise<boolean>;
|
||||
hasEncKey: () => Promise<boolean>;
|
||||
clearKey: (clearSecretStorage?: boolean, userId?: string) => Promise<any>;
|
||||
clearKeyHash: () => Promise<any>;
|
||||
clearEncKey: (memoryOnly?: boolean, userId?: string) => Promise<any>;
|
||||
clearKeyPair: (memoryOnly?: boolean, userId?: string) => Promise<any>;
|
||||
clearOrgKeys: (memoryOnly?: boolean, userId?: string) => Promise<any>;
|
||||
clearProviderKeys: (memoryOnly?: boolean) => Promise<any>;
|
||||
clearPinProtectedKey: () => Promise<any>;
|
||||
clearKeys: (userId?: string) => Promise<any>;
|
||||
toggleKey: () => Promise<any>;
|
||||
makeKey: (
|
||||
password: string,
|
||||
salt: string,
|
||||
kdf: KdfType,
|
||||
kdfIterations: number
|
||||
) => Promise<SymmetricCryptoKey>;
|
||||
makeKeyFromPin: (
|
||||
pin: string,
|
||||
salt: string,
|
||||
kdf: KdfType,
|
||||
kdfIterations: number,
|
||||
protectedKeyCs?: EncString
|
||||
) => Promise<SymmetricCryptoKey>;
|
||||
makeShareKey: () => Promise<[EncString, SymmetricCryptoKey]>;
|
||||
makeKeyPair: (key?: SymmetricCryptoKey) => Promise<[string, EncString]>;
|
||||
makePinKey: (
|
||||
pin: string,
|
||||
salt: string,
|
||||
kdf: KdfType,
|
||||
kdfIterations: number
|
||||
) => Promise<SymmetricCryptoKey>;
|
||||
makeSendKey: (keyMaterial: ArrayBuffer) => Promise<SymmetricCryptoKey>;
|
||||
hashPassword: (
|
||||
password: string,
|
||||
key: SymmetricCryptoKey,
|
||||
hashPurpose?: HashPurpose
|
||||
) => Promise<string>;
|
||||
makeEncKey: (key: SymmetricCryptoKey) => Promise<[SymmetricCryptoKey, EncString]>;
|
||||
remakeEncKey: (
|
||||
key: SymmetricCryptoKey,
|
||||
encKey?: SymmetricCryptoKey
|
||||
) => Promise<[SymmetricCryptoKey, EncString]>;
|
||||
encrypt: (plainValue: string | ArrayBuffer, key?: SymmetricCryptoKey) => Promise<EncString>;
|
||||
encryptToBytes: (plainValue: ArrayBuffer, key?: SymmetricCryptoKey) => Promise<EncArrayBuffer>;
|
||||
rsaEncrypt: (data: ArrayBuffer, publicKey?: ArrayBuffer) => Promise<EncString>;
|
||||
rsaDecrypt: (encValue: string, privateKeyValue?: ArrayBuffer) => Promise<ArrayBuffer>;
|
||||
decryptToBytes: (encString: EncString, key?: SymmetricCryptoKey) => Promise<ArrayBuffer>;
|
||||
decryptToUtf8: (encString: EncString, key?: SymmetricCryptoKey) => Promise<string>;
|
||||
decryptFromBytes: (encBuf: ArrayBuffer, key: SymmetricCryptoKey) => Promise<ArrayBuffer>;
|
||||
randomNumber: (min: number, max: number) => Promise<number>;
|
||||
validateKey: (key: SymmetricCryptoKey) => Promise<boolean>;
|
||||
}
|
||||
62
jslib/common/src/abstractions/cryptoFunction.service.ts
Normal file
62
jslib/common/src/abstractions/cryptoFunction.service.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { DecryptParameters } from "../models/domain/decryptParameters";
|
||||
import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey";
|
||||
|
||||
export abstract class CryptoFunctionService {
|
||||
pbkdf2: (
|
||||
password: string | ArrayBuffer,
|
||||
salt: string | ArrayBuffer,
|
||||
algorithm: "sha256" | "sha512",
|
||||
iterations: number
|
||||
) => Promise<ArrayBuffer>;
|
||||
hkdf: (
|
||||
ikm: ArrayBuffer,
|
||||
salt: string | ArrayBuffer,
|
||||
info: string | ArrayBuffer,
|
||||
outputByteSize: number,
|
||||
algorithm: "sha256" | "sha512"
|
||||
) => Promise<ArrayBuffer>;
|
||||
hkdfExpand: (
|
||||
prk: ArrayBuffer,
|
||||
info: string | ArrayBuffer,
|
||||
outputByteSize: number,
|
||||
algorithm: "sha256" | "sha512"
|
||||
) => Promise<ArrayBuffer>;
|
||||
hash: (
|
||||
value: string | ArrayBuffer,
|
||||
algorithm: "sha1" | "sha256" | "sha512" | "md5"
|
||||
) => Promise<ArrayBuffer>;
|
||||
hmac: (
|
||||
value: ArrayBuffer,
|
||||
key: ArrayBuffer,
|
||||
algorithm: "sha1" | "sha256" | "sha512"
|
||||
) => Promise<ArrayBuffer>;
|
||||
compare: (a: ArrayBuffer, b: ArrayBuffer) => Promise<boolean>;
|
||||
hmacFast: (
|
||||
value: ArrayBuffer | string,
|
||||
key: ArrayBuffer | string,
|
||||
algorithm: "sha1" | "sha256" | "sha512"
|
||||
) => Promise<ArrayBuffer | string>;
|
||||
compareFast: (a: ArrayBuffer | string, b: ArrayBuffer | string) => Promise<boolean>;
|
||||
aesEncrypt: (data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer) => Promise<ArrayBuffer>;
|
||||
aesDecryptFastParameters: (
|
||||
data: string,
|
||||
iv: string,
|
||||
mac: string,
|
||||
key: SymmetricCryptoKey
|
||||
) => DecryptParameters<ArrayBuffer | string>;
|
||||
aesDecryptFast: (parameters: DecryptParameters<ArrayBuffer | string>) => Promise<string>;
|
||||
aesDecrypt: (data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer) => Promise<ArrayBuffer>;
|
||||
rsaEncrypt: (
|
||||
data: ArrayBuffer,
|
||||
publicKey: ArrayBuffer,
|
||||
algorithm: "sha1" | "sha256"
|
||||
) => Promise<ArrayBuffer>;
|
||||
rsaDecrypt: (
|
||||
data: ArrayBuffer,
|
||||
privateKey: ArrayBuffer,
|
||||
algorithm: "sha1" | "sha256"
|
||||
) => Promise<ArrayBuffer>;
|
||||
rsaExtractPublicKey: (privateKey: ArrayBuffer) => Promise<ArrayBuffer>;
|
||||
rsaGenerateKeyPair: (length: 1024 | 2048 | 4096) => Promise<[ArrayBuffer, ArrayBuffer]>;
|
||||
randomBytes: (length: number) => Promise<ArrayBuffer>;
|
||||
}
|
||||
34
jslib/common/src/abstractions/environment.service.ts
Normal file
34
jslib/common/src/abstractions/environment.service.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
export type Urls = {
|
||||
base?: string;
|
||||
webVault?: string;
|
||||
api?: string;
|
||||
identity?: string;
|
||||
icons?: string;
|
||||
notifications?: string;
|
||||
events?: string;
|
||||
keyConnector?: string;
|
||||
};
|
||||
|
||||
export type PayPalConfig = {
|
||||
businessId?: string;
|
||||
buttonAction?: string;
|
||||
};
|
||||
|
||||
export abstract class EnvironmentService {
|
||||
urls: Observable<Urls>;
|
||||
|
||||
hasBaseUrl: () => boolean;
|
||||
getNotificationsUrl: () => string;
|
||||
getWebVaultUrl: () => string;
|
||||
getSendUrl: () => string;
|
||||
getIconsUrl: () => string;
|
||||
getApiUrl: () => string;
|
||||
getIdentityUrl: () => string;
|
||||
getEventsUrl: () => string;
|
||||
getKeyConnectorUrl: () => string;
|
||||
setUrlsFromStorage: () => Promise<void>;
|
||||
setUrls: (urls: Urls) => Promise<Urls>;
|
||||
getUrls: () => Urls;
|
||||
}
|
||||
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>;
|
||||
}
|
||||
11
jslib/common/src/abstractions/export.service.ts
Normal file
11
jslib/common/src/abstractions/export.service.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { EventView } from "../models/view/eventView";
|
||||
|
||||
export type ExportFormat = "csv" | "json" | "encrypted_json";
|
||||
|
||||
export abstract class ExportService {
|
||||
getExport: (format?: ExportFormat, organizationId?: string) => Promise<string>;
|
||||
getPasswordProtectedExport: (password: string, organizationId?: string) => Promise<string>;
|
||||
getOrganizationExport: (organizationId: string, format?: ExportFormat) => Promise<string>;
|
||||
getEventExport: (events: EventView[]) => Promise<string>;
|
||||
getFileName: (prefix?: string, extension?: string) => string;
|
||||
}
|
||||
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>;
|
||||
}
|
||||
9
jslib/common/src/abstractions/i18n.service.ts
Normal file
9
jslib/common/src/abstractions/i18n.service.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export abstract class I18nService {
|
||||
locale: string;
|
||||
supportedTranslationLocales: string[];
|
||||
translationLocale: string;
|
||||
collator: Intl.Collator;
|
||||
localeNames: Map<string, string>;
|
||||
t: (id: string, p1?: string, p2?: string, p3?: string) => string;
|
||||
translate: (id: string, p1?: string, p2?: string, p3?: string) => string;
|
||||
}
|
||||
19
jslib/common/src/abstractions/import.service.ts
Normal file
19
jslib/common/src/abstractions/import.service.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { ImportOption, ImportType } from "../enums/importOptions";
|
||||
import { ImportError } from "../importers/importError";
|
||||
import { Importer } from "../importers/importer";
|
||||
|
||||
export abstract class ImportService {
|
||||
featuredImportOptions: readonly ImportOption[];
|
||||
regularImportOptions: readonly ImportOption[];
|
||||
getImportOptions: () => ImportOption[];
|
||||
import: (
|
||||
importer: Importer,
|
||||
fileContents: string,
|
||||
organizationId?: string
|
||||
) => Promise<ImportError>;
|
||||
getImporter: (
|
||||
format: ImportType | "bitwardenpasswordprotected",
|
||||
organizationId: string,
|
||||
password?: string
|
||||
) => Importer;
|
||||
}
|
||||
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>;
|
||||
}
|
||||
11
jslib/common/src/abstractions/log.service.ts
Normal file
11
jslib/common/src/abstractions/log.service.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { LogLevelType } from "../enums/logLevelType";
|
||||
|
||||
export abstract class LogService {
|
||||
debug: (message: string) => void;
|
||||
info: (message: string) => void;
|
||||
warning: (message: string) => void;
|
||||
error: (message: string) => void;
|
||||
write: (level: LogLevelType, message: string) => void;
|
||||
time: (label: string) => void;
|
||||
timeEnd: (label: string) => [number, number];
|
||||
}
|
||||
3
jslib/common/src/abstractions/messaging.service.ts
Normal file
3
jslib/common/src/abstractions/messaging.service.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export abstract class MessagingService {
|
||||
send: (subscriber: string, arg?: any) => 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>;
|
||||
}
|
||||
52
jslib/common/src/abstractions/platformUtils.service.ts
Normal file
52
jslib/common/src/abstractions/platformUtils.service.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { ClientType } from "../enums/clientType";
|
||||
import { DeviceType } from "../enums/deviceType";
|
||||
import { ThemeType } from "../enums/themeType";
|
||||
|
||||
interface ToastOptions {
|
||||
timeout?: number;
|
||||
}
|
||||
|
||||
export abstract class PlatformUtilsService {
|
||||
getDevice: () => DeviceType;
|
||||
getDeviceString: () => string;
|
||||
getClientType: () => ClientType;
|
||||
isFirefox: () => boolean;
|
||||
isChrome: () => boolean;
|
||||
isEdge: () => boolean;
|
||||
isOpera: () => boolean;
|
||||
isVivaldi: () => boolean;
|
||||
isSafari: () => boolean;
|
||||
isMacAppStore: () => boolean;
|
||||
isViewOpen: () => Promise<boolean>;
|
||||
launchUri: (uri: string, options?: any) => void;
|
||||
saveFile: (win: Window, blobData: any, blobOptions: any, fileName: string) => void;
|
||||
getApplicationVersion: () => Promise<string>;
|
||||
supportsWebAuthn: (win: Window) => boolean;
|
||||
supportsDuo: () => boolean;
|
||||
showToast: (
|
||||
type: "error" | "success" | "warning" | "info",
|
||||
title: string,
|
||||
text: string | string[],
|
||||
options?: ToastOptions
|
||||
) => void;
|
||||
showDialog: (
|
||||
body: string,
|
||||
title?: string,
|
||||
confirmText?: string,
|
||||
cancelText?: string,
|
||||
type?: string,
|
||||
bodyIsHtml?: boolean
|
||||
) => Promise<boolean>;
|
||||
isDev: () => boolean;
|
||||
isSelfHost: () => boolean;
|
||||
copyToClipboard: (text: string, options?: any) => void | boolean;
|
||||
readFromClipboard: (options?: any) => Promise<string>;
|
||||
supportsBiometric: () => Promise<boolean>;
|
||||
authenticateBiometric: () => Promise<boolean>;
|
||||
getDefaultSystemTheme: () => Promise<ThemeType.Light | ThemeType.Dark>;
|
||||
onDefaultSystemThemeChange: (
|
||||
callback: (theme: ThemeType.Light | ThemeType.Dark) => unknown
|
||||
) => unknown;
|
||||
getEffectiveTheme: () => Promise<ThemeType>;
|
||||
supportsSecureStorage: () => boolean;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user