Compare commits
136 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d7674f5c91 | ||
|
9852f2ec22 | ||
|
fec6838f90 | ||
|
55a9403ee3 | ||
|
817856bc82 | ||
|
508292ae39 | ||
|
00fd2ec03f | ||
|
9a954710d9 | ||
|
a81c3c95a4 | ||
|
75470dc169 | ||
|
18b5e4adfd | ||
|
0396d682b1 | ||
|
ef60112855 | ||
|
b467206448 | ||
|
55b301c267 | ||
|
a5ebb9fb52 | ||
|
2764c9610b | ||
|
241e08b7ff | ||
|
865e92c94c | ||
|
c3d0a529fb | ||
|
1315b3c6cd | ||
|
9f77dd9d09 | ||
|
5082c7708a | ||
|
10d35d863b | ||
|
caafbc2b73 | ||
|
a4ca9bf64c | ||
|
3862a19571 | ||
|
8be88a731c | ||
|
2b0d7ac72c | ||
|
e0d7d2b43a | ||
|
70db11e659 | ||
|
2e3c89269d | ||
|
31523bdf0e | ||
|
6b6666cd0d | ||
|
be1ab221f4 | ||
|
78986023e7 | ||
|
14b9decf21 | ||
|
0e9465601a | ||
|
52bb77fb66 | ||
|
b4cec5b46f | ||
|
72405ebe87 | ||
|
4379274154 | ||
|
9e0cc45704 | ||
|
bc21703a2b | ||
|
4ddeff2eee | ||
|
75af5b94d4 | ||
|
cbadcccc85 | ||
|
21167301f1 | ||
|
ad6308eb48 | ||
|
fec023866e | ||
|
d2a7012d3f | ||
|
6555312034 | ||
|
e2fe0c8b09 | ||
|
3b2427e913 | ||
|
37e9523f00 | ||
|
09d7376f39 | ||
|
be0b6113e4 | ||
|
75f11cdbf1 | ||
|
e5feda0fa6 | ||
|
5ebed777c2 | ||
|
e49d317d19 | ||
|
114d7455b8 | ||
|
d1146acb1e | ||
|
703d390566 | ||
|
c0170563f2 | ||
|
f46405a508 | ||
|
6d429465fb | ||
|
81457f6c05 | ||
|
aee27f9570 | ||
|
f845bcf6c1 | ||
|
b134eba27b | ||
|
e84be59075 | ||
|
edc5245173 | ||
|
7bad97dd82 | ||
|
3071bec03f | ||
|
80415f8cd5 | ||
|
03c279865f | ||
|
54025f269a | ||
|
4ce5e5fbdc | ||
|
c738366eef | ||
|
0114d96e18 | ||
|
1eac8f0c0f | ||
|
8880e9700e | ||
|
2f289ebd1f | ||
|
3aa52a5537 | ||
|
233f876bbb | ||
|
d7276850a2 | ||
|
e570551a5a | ||
|
7401204b70 | ||
|
685ffbcac5 | ||
|
f9e6d13708 | ||
|
f798995764 | ||
|
f6298b2684 | ||
|
3881223a73 | ||
|
d2df8dacad | ||
|
10ffdce5b9 | ||
|
d6d74e178c | ||
|
2e09265d3a | ||
|
659c9ea78d | ||
|
884615c23a | ||
|
2470d8ce25 | ||
|
6b6468e061 | ||
|
45b144361c | ||
|
881bb3cb49 | ||
|
fd4c41b043 | ||
|
7a8a78b4df | ||
|
f82e2fbb03 | ||
|
e9a3c586f8 | ||
|
f54a614d6b | ||
|
95b5d68566 | ||
|
3ffb658db6 | ||
|
530f25c88a | ||
|
97d367dab8 | ||
|
0a545c88b2 | ||
|
0f6ee08dd5 | ||
|
b227ae13f6 | ||
|
79f6a33596 | ||
|
1e80c4335f | ||
|
c51b8523b7 | ||
|
bd2ed43498 | ||
|
243afc9da0 | ||
|
762e3f8198 | ||
|
4e75a25492 | ||
|
143a262743 | ||
|
c1a3178538 | ||
|
166c459da4 | ||
|
94b561382d | ||
|
2b58861296 | ||
|
3e8705d548 | ||
|
1e877f6cf8 | ||
|
9151fc0164 | ||
|
03eed41d86 | ||
|
cad6e9481f | ||
|
270411dff7 | ||
|
7c68e3802e | ||
|
48ff9f61ae |
9
.eslintignore
Normal file
@ -0,0 +1,9 @@
|
||||
dist
|
||||
build
|
||||
jslib
|
||||
webpack.main.js
|
||||
webpack.renderer.js
|
||||
src/scripts/duo.js
|
||||
desktop_native
|
||||
|
||||
**/node_modules
|
32
.eslintrc.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"root": true,
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": ["./jslib/shared/eslintrc.json"],
|
||||
"rules": {
|
||||
"import/order": [
|
||||
"error",
|
||||
{
|
||||
"alphabetize": {
|
||||
"order": "asc"
|
||||
},
|
||||
"newlines-between": "always",
|
||||
"pathGroups": [
|
||||
{
|
||||
"pattern": "jslib-*/**",
|
||||
"group": "external",
|
||||
"position": "after"
|
||||
},
|
||||
{
|
||||
"pattern": "src/**/*",
|
||||
"group": "parent",
|
||||
"position": "before"
|
||||
}
|
||||
],
|
||||
"pathGroupsExcludedImportTypes": ["builtin"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
BIN
.github/secrets/appstore-app-cert.p12.gpg
vendored
BIN
.github/secrets/appstore-installer-cert.p12.gpg
vendored
BIN
.github/secrets/bitwarden-desktop-key.p12.gpg
vendored
BIN
.github/secrets/macdev-cert.p12.gpg
vendored
414
.github/workflows/build.yml
vendored
@ -6,6 +6,10 @@ on:
|
||||
branches-ignore:
|
||||
- 'l10n_master'
|
||||
- 'gh-pages'
|
||||
paths-ignore:
|
||||
- '.github/workflows/**'
|
||||
workflow_dispatch:
|
||||
inputs: {}
|
||||
|
||||
jobs:
|
||||
cloc:
|
||||
@ -13,7 +17,7 @@ jobs:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
|
||||
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
|
||||
|
||||
- name: Set up cloc
|
||||
run: |
|
||||
@ -35,7 +39,7 @@ jobs:
|
||||
hotfix_branch_exists: ${{ steps.branch-check.outputs.hotfix_branch_exists }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
|
||||
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
|
||||
|
||||
- name: Get Package Version
|
||||
id: retrieve-version
|
||||
@ -55,8 +59,8 @@ jobs:
|
||||
run: |
|
||||
SAFARI_REF=master
|
||||
|
||||
if [[ "$GITHUB_REF" == "refs/heads/hotfix" ]]; then
|
||||
SAFARI_REF=hotfix
|
||||
if [[ "$GITHUB_REF" == "refs/heads/hotfix-rc" ]]; then
|
||||
SAFARI_REF=hotfix-rc
|
||||
elif [[ "$GITHUB_REF" == "refs/heads/rc" ]]; then
|
||||
SAFARI_REF=rc
|
||||
fi
|
||||
@ -73,12 +77,34 @@ jobs:
|
||||
echo "::set-output name=rc_branch_exists::0"
|
||||
fi
|
||||
|
||||
if [[ $(git ls-remote --heads origin hotfix) ]]; then
|
||||
if [[ $(git ls-remote --heads origin hotfix-rc) ]]; then
|
||||
echo "::set-output name=hotfix_branch_exists::1"
|
||||
else
|
||||
echo "::set-output name=hotfix_branch_exists::0"
|
||||
fi
|
||||
|
||||
lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
|
||||
|
||||
- name: Cache npm
|
||||
id: npm-cache
|
||||
uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed
|
||||
with:
|
||||
path: '~/.npm'
|
||||
key: ${{ runner.os }}-npm-${{ hashFiles('package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-npm-
|
||||
|
||||
- name: Install Node dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run linter
|
||||
run: npm run lint
|
||||
|
||||
|
||||
linux:
|
||||
name: Linux Build
|
||||
@ -88,20 +114,15 @@ jobs:
|
||||
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
|
||||
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea # v2.1.5
|
||||
uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
node-version: '16'
|
||||
|
||||
- name: Cache npm
|
||||
id: npm-cache
|
||||
uses: actions/cache@c64c572235d810460d0d6876e9c705ad5002b353 # v2.1.6
|
||||
with:
|
||||
path: '~/.npm'
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-npm-${{ hashFiles('**/package-lock.json') }}
|
||||
|
||||
- name: Set Node options
|
||||
run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV
|
||||
|
||||
@ -128,49 +149,60 @@ jobs:
|
||||
- name: Install Node dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run linter
|
||||
run: npm run lint
|
||||
- name: Cache Native Module
|
||||
uses: actions/cache@48af2dc4a9e8278b89d7fa154b955c30c6aaab09 # v3.0.2
|
||||
id: cache
|
||||
with:
|
||||
path: desktop_native/*.node
|
||||
key: rust-${{ runner.os }}-${{ hashFiles('desktop_native/**/*') }}
|
||||
|
||||
- name: Build Native Module
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
working-directory: './desktop_native'
|
||||
run: |
|
||||
npm ci
|
||||
npm run build:cross-platform
|
||||
|
||||
- name: Build application
|
||||
run: npm run dist:lin
|
||||
|
||||
- name: Upload .deb artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: Bitwarden-${{ env._PACKAGE_VERSION }}-amd64.deb
|
||||
path: ./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-amd64.deb
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload .rpm artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: Bitwarden-${{ env._PACKAGE_VERSION }}-x86_64.rpm
|
||||
path: ./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x86_64.rpm
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload .freebsd artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: Bitwarden-${{ env._PACKAGE_VERSION }}-x64.freebsd
|
||||
path: ./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x64.freebsd
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload .snap artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: bitwarden_${{ env._PACKAGE_VERSION }}_amd64.snap
|
||||
path: ./dist/bitwarden_${{ env._PACKAGE_VERSION }}_amd64.snap
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload .AppImage artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: Bitwarden-${{ env._PACKAGE_VERSION }}-x86_64.AppImage
|
||||
path: ./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x86_64.AppImage
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload latest auto-update artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: latest-linux.yml
|
||||
path: ./dist/latest-linux.yml
|
||||
@ -185,20 +217,15 @@ jobs:
|
||||
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
|
||||
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea # v2.1.5
|
||||
uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
node-version: '16'
|
||||
|
||||
- name: Cache npm
|
||||
id: npm-cache
|
||||
uses: actions/cache@c64c572235d810460d0d6876e9c705ad5002b353 # v2.1.6
|
||||
with:
|
||||
path: '%AppData%/npm-cache'
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-npm-${{ hashFiles('**/package-lock.json') }}
|
||||
|
||||
- name: Set Node options
|
||||
run: echo "NODE_OPTIONS=--max_old_space_size=4096" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
shell: pwsh
|
||||
@ -215,20 +242,27 @@ jobs:
|
||||
shell: pwsh
|
||||
run: choco install checksum --no-progress
|
||||
|
||||
- name: Rust
|
||||
shell: pwsh
|
||||
run: |
|
||||
rustup target install i686-pc-windows-msvc
|
||||
rustup target install aarch64-pc-windows-msvc
|
||||
|
||||
- name: Print environment
|
||||
run: |
|
||||
node --version
|
||||
npm --version
|
||||
choco --version
|
||||
rustup show
|
||||
|
||||
- name: Login to Azure
|
||||
uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a
|
||||
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
|
||||
|
||||
- name: Retrieve secrets
|
||||
id: retrieve-secrets
|
||||
uses: Azure/get-keyvault-secrets@80ccd3fafe5662407cc2e55f202ee34bfff8c403
|
||||
uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f
|
||||
with:
|
||||
keyvault: "bitwarden-prod-kv"
|
||||
secrets: "code-signing-vault-url,
|
||||
@ -240,8 +274,19 @@ jobs:
|
||||
- name: Install Node dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run linter
|
||||
run: npm run lint
|
||||
- name: Cache Native Module
|
||||
uses: actions/cache@48af2dc4a9e8278b89d7fa154b955c30c6aaab09 # v3.0.2
|
||||
id: cache
|
||||
with:
|
||||
path: desktop_native/*.node
|
||||
key: rust-${{ runner.os }}-${{ hashFiles('desktop_native/**/*') }}
|
||||
|
||||
- name: Build Native Module
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
working-directory: './desktop_native'
|
||||
run: |
|
||||
npm ci
|
||||
npm run build:cross-platform
|
||||
|
||||
- name: Build & Sign (dev)
|
||||
env:
|
||||
@ -278,91 +323,91 @@ jobs:
|
||||
choco pack ./dist/chocolatey/bitwarden.nuspec --version "$env:_PACKAGE_VERSION" --out ./dist/chocolatey
|
||||
|
||||
- name: Upload portable exe artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: Bitwarden-Portable-${{ env._PACKAGE_VERSION }}.exe
|
||||
path: ./dist/Bitwarden-Portable-${{ env._PACKAGE_VERSION }}.exe
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload installer exe artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: Bitwarden-Installer-${{ env._PACKAGE_VERSION }}.exe
|
||||
path: ./dist/nsis-web/Bitwarden-Installer-${{ env._PACKAGE_VERSION }}.exe
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload appx ia32 artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: Bitwarden-${{ env._PACKAGE_VERSION }}-ia32.appx
|
||||
path: ./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-ia32.appx
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload store appx ia32 artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: Bitwarden-${{ env._PACKAGE_VERSION }}-ia32-store.appx
|
||||
path: ./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-ia32-store.appx
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload NSIS ia32 artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: Bitwarden-${{ env._PACKAGE_VERSION }}-ia32.nsis.7z
|
||||
path: ./dist/nsis-web/Bitwarden-${{ env._PACKAGE_VERSION }}-ia32.nsis.7z
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload appx x64 artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: Bitwarden-${{ env._PACKAGE_VERSION }}-x64.appx
|
||||
path: ./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x64.appx
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload store appx x64 artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: Bitwarden-${{ env._PACKAGE_VERSION }}-x64-store.appx
|
||||
path: ./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x64-store.appx
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload NSIS x64 artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: Bitwarden-${{ env._PACKAGE_VERSION }}-x64.nsis.7z
|
||||
path: ./dist/nsis-web/Bitwarden-${{ env._PACKAGE_VERSION }}-x64.nsis.7z
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload appx ARM64 artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: Bitwarden-${{ env._PACKAGE_VERSION }}-arm64.appx
|
||||
path: ./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-arm64.appx
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload store appx ARM64 artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: Bitwarden-${{ env._PACKAGE_VERSION }}-arm64-store.appx
|
||||
path: ./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-arm64-store.appx
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload NSIS ARM64 artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: Bitwarden-${{ env._PACKAGE_VERSION }}-arm64.nsis.7z
|
||||
path: ./dist/nsis-web/Bitwarden-${{ env._PACKAGE_VERSION }}-arm64.nsis.7z
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload nupkg artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: bitwarden.${{ env._PACKAGE_VERSION }}.nupkg
|
||||
path: ./dist/chocolatey/bitwarden.${{ env._PACKAGE_VERSION }}.nupkg
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload latest auto-update artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: latest.yml
|
||||
path: ./dist/nsis-web/latest.yml
|
||||
@ -377,20 +422,15 @@ jobs:
|
||||
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
|
||||
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea # v2.1.5
|
||||
uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
node-version: '16'
|
||||
|
||||
- name: Cache npm
|
||||
id: npm-cache
|
||||
uses: actions/cache@c64c572235d810460d0d6876e9c705ad5002b353 # v2.1.6
|
||||
with:
|
||||
path: '~/.npm'
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-npm-${{ hashFiles('**/package-lock.json') }}
|
||||
|
||||
- name: Set Node options
|
||||
run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV
|
||||
|
||||
@ -399,23 +439,28 @@ jobs:
|
||||
npm install -g node-gyp
|
||||
node-gyp install $(node -v)
|
||||
|
||||
- name: Rust
|
||||
shell: pwsh
|
||||
run: rustup target install aarch64-apple-darwin
|
||||
|
||||
- name: Print environment
|
||||
run: |
|
||||
node --version
|
||||
npm --version
|
||||
rustup show
|
||||
echo "GitHub ref: $GITHUB_REF"
|
||||
echo "GitHub event: $GITHUB_EVENT"
|
||||
|
||||
- name: Cache Build
|
||||
id: build-cache
|
||||
uses: actions/cache@c64c572235d810460d0d6876e9c705ad5002b353 # v2.1.6
|
||||
uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed
|
||||
with:
|
||||
path: build
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-build
|
||||
|
||||
- name: Cache Safari
|
||||
id: safari-cache
|
||||
uses: actions/cache@c64c572235d810460d0d6876e9c705ad5002b353 # v2.1.6
|
||||
uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed
|
||||
with:
|
||||
path: dist-safari
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-safari-extension
|
||||
@ -487,16 +532,27 @@ jobs:
|
||||
env:
|
||||
BUILD_NUMBER: ${{ needs.setup.outputs.build_number }}
|
||||
run: |
|
||||
$package = Get-Content -Raw -Path $env:GITHUB_WORKSPACE\package.json | ConvertFrom-Json;
|
||||
$package.build | Add-Member -MemberType NoteProperty -Name buildVersion -Value "$env:BUILD_NUMBER";
|
||||
$package | ConvertTo-Json -Depth 32 | Set-Content $env:GITHUB_WORKSPACE\package.json;
|
||||
$package = Get-Content -Raw -Path $env:GITHUB_WORKSPACE\electron-builder.json | ConvertFrom-Json;
|
||||
$package | Add-Member -MemberType NoteProperty -Name buildVersion -Value "$env:BUILD_NUMBER";
|
||||
$package | ConvertTo-Json -Depth 32 | Set-Content $env:GITHUB_WORKSPACE\electron-builder.json;
|
||||
|
||||
- name: Cache Native Module
|
||||
uses: actions/cache@48af2dc4a9e8278b89d7fa154b955c30c6aaab09 # v3.0.2
|
||||
id: cache
|
||||
with:
|
||||
path: desktop_native/*.node
|
||||
key: rust-${{ runner.os }}-${{ hashFiles('desktop_native/**/*') }}
|
||||
|
||||
- name: Build Native Module
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
working-directory: './desktop_native'
|
||||
run: |
|
||||
npm ci
|
||||
npm run build:cross-platform
|
||||
|
||||
- name: Install Node dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run linter
|
||||
run: npm run lint
|
||||
|
||||
- name: Build application (dev)
|
||||
run: npm run build
|
||||
|
||||
@ -505,39 +561,39 @@ jobs:
|
||||
run: New-Item ./dist-safari -ItemType Directory -ea 0
|
||||
|
||||
- name: Checkout browser extension
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
|
||||
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
|
||||
with:
|
||||
repository: 'bitwarden/browser'
|
||||
path: 'dist-safari/browser'
|
||||
path: 'dist-safari/bitwarden'
|
||||
ref: ${{ needs.setup.outputs.safari_ref }}
|
||||
|
||||
- name: Build Safari extension
|
||||
shell: pwsh
|
||||
run: ./scripts/safari-build.ps1 -skipcheckout -skipoutcopy
|
||||
run: |
|
||||
npm install
|
||||
npm run dist:safari
|
||||
working-directory: dist-safari/bitwarden/apps/browser
|
||||
|
||||
|
||||
macos-package-github:
|
||||
name: MacOS Package GitHub Release Assets
|
||||
runs-on: macos-11
|
||||
needs: [setup, macos-build]
|
||||
needs:
|
||||
- setup
|
||||
- macos-build
|
||||
- lint
|
||||
env:
|
||||
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
|
||||
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea # v2.1.5
|
||||
uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
node-version: '16'
|
||||
|
||||
- name: Cache npm
|
||||
id: npm-cache
|
||||
uses: actions/cache@c64c572235d810460d0d6876e9c705ad5002b353 # v2.1.6
|
||||
with:
|
||||
path: '~/.npm'
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-npm-${{ hashFiles('**/package-lock.json') }}
|
||||
|
||||
- name: Set Node options
|
||||
run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV
|
||||
|
||||
@ -546,23 +602,28 @@ jobs:
|
||||
npm install -g node-gyp
|
||||
node-gyp install $(node -v)
|
||||
|
||||
- name: Rust
|
||||
shell: pwsh
|
||||
run: rustup target install aarch64-apple-darwin
|
||||
|
||||
- name: Print environment
|
||||
run: |
|
||||
node --version
|
||||
npm --version
|
||||
rustup show
|
||||
echo "GitHub ref: $GITHUB_REF"
|
||||
echo "GitHub event: $GITHUB_EVENT"
|
||||
|
||||
- name: Get Build Cache
|
||||
id: build-cache
|
||||
uses: actions/cache@c64c572235d810460d0d6876e9c705ad5002b353 # v2.1.6
|
||||
uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed
|
||||
with:
|
||||
path: build
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-build
|
||||
|
||||
- name: Setup Safari Cache
|
||||
id: safari-cache
|
||||
uses: actions/cache@c64c572235d810460d0d6876e9c705ad5002b353 # v2.1.6
|
||||
uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed
|
||||
with:
|
||||
path: dist-safari
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-safari-extension
|
||||
@ -634,9 +695,23 @@ jobs:
|
||||
env:
|
||||
BUILD_NUMBER: ${{ needs.setup.outputs.build_number }}
|
||||
run: |
|
||||
$package = Get-Content -Raw -Path $env:GITHUB_WORKSPACE\package.json | ConvertFrom-Json;
|
||||
$package.build | Add-Member -MemberType NoteProperty -Name buildVersion -Value "$env:BUILD_NUMBER";
|
||||
$package | ConvertTo-Json -Depth 32 | Set-Content $env:GITHUB_WORKSPACE\package.json;
|
||||
$package = Get-Content -Raw -Path $env:GITHUB_WORKSPACE\electron-builder.json | ConvertFrom-Json;
|
||||
$package | Add-Member -MemberType NoteProperty -Name buildVersion -Value "$env:BUILD_NUMBER";
|
||||
$package | ConvertTo-Json -Depth 32 | Set-Content $env:GITHUB_WORKSPACE\electron-builder.json;
|
||||
|
||||
- name: Cache Native Module
|
||||
uses: actions/cache@48af2dc4a9e8278b89d7fa154b955c30c6aaab09 # v3.0.2
|
||||
id: cache
|
||||
with:
|
||||
path: desktop_native/*.node
|
||||
key: rust-${{ runner.os }}-${{ hashFiles('desktop_native/**/*') }}
|
||||
|
||||
- name: Build Native Module
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
working-directory: './desktop_native'
|
||||
run: |
|
||||
npm ci
|
||||
npm run build:cross-platform
|
||||
|
||||
- name: NPM install
|
||||
run: npm ci
|
||||
@ -652,20 +727,24 @@ jobs:
|
||||
|
||||
- name: Checkout browser extension
|
||||
if: steps.safari-cache.outputs.cache-hit != 'true'
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
|
||||
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
|
||||
with:
|
||||
repository: 'bitwarden/browser'
|
||||
path: 'dist-safari/browser'
|
||||
repository: 'bitwarden/bitwarden'
|
||||
path: 'dist-safari/bitwarden'
|
||||
ref: ${{ needs.setup.outputs.safari_ref }}
|
||||
|
||||
- name: Build Safari extension
|
||||
if: steps.safari-cache.outputs.cache-hit != 'true'
|
||||
shell: pwsh
|
||||
run: ./scripts/safari-build.ps1 -skipcheckout -skipoutcopy
|
||||
run: |
|
||||
npm install
|
||||
npm run dist:safari
|
||||
working-directory: dist-safari/bitwarden/apps/browser
|
||||
|
||||
- name: Load Safari extension for .dmg
|
||||
shell: pwsh
|
||||
run: ./scripts/safari-build.ps1 -copyonly
|
||||
working-directory: dist-safari/bitwarden/apps/browser
|
||||
run: |
|
||||
mkdir PlugIns
|
||||
cp -r dist/Safari/dmg/build/Release/safari.appex PlugIns/safari.appex
|
||||
|
||||
- name: Build application (dist)
|
||||
env:
|
||||
@ -674,28 +753,28 @@ jobs:
|
||||
run: npm run pack:mac
|
||||
|
||||
- name: Upload .zip artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: Bitwarden-${{ env._PACKAGE_VERSION }}-universal-mac.zip
|
||||
path: ./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-universal-mac.zip
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload .dmg artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: Bitwarden-${{ env._PACKAGE_VERSION }}-universal.dmg
|
||||
path: ./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-universal.dmg
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload .dmg blockmap artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: Bitwarden-${{ env._PACKAGE_VERSION }}-universal.dmg.blockmap
|
||||
path: ./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-universal.dmg.blockmap
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload latest auto-update artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: latest-mac.yml
|
||||
path: ./dist/latest-mac.yml
|
||||
@ -705,25 +784,23 @@ jobs:
|
||||
macos-package-mas:
|
||||
name: MacOS Package Prod Release Asset
|
||||
runs-on: macos-11
|
||||
needs: [setup, macos-build]
|
||||
needs:
|
||||
- setup
|
||||
- macos-build
|
||||
- lint
|
||||
env:
|
||||
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
|
||||
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea # v2.1.5
|
||||
uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
node-version: '16'
|
||||
|
||||
- name: Cache npm
|
||||
id: npm-cache
|
||||
uses: actions/cache@c64c572235d810460d0d6876e9c705ad5002b353 # v2.1.6
|
||||
with:
|
||||
path: '~/.npm'
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-npm-${{ hashFiles('**/package-lock.json') }}
|
||||
|
||||
- name: Set Node options
|
||||
run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV
|
||||
|
||||
@ -732,23 +809,28 @@ jobs:
|
||||
npm install -g node-gyp
|
||||
node-gyp install $(node -v)
|
||||
|
||||
- name: Rust
|
||||
shell: pwsh
|
||||
run: rustup target install aarch64-apple-darwin
|
||||
|
||||
- name: Print environment
|
||||
run: |
|
||||
node --version
|
||||
npm --version
|
||||
rustup show
|
||||
echo "GitHub ref: $GITHUB_REF"
|
||||
echo "GitHub event: $GITHUB_EVENT"
|
||||
|
||||
- name: Get Build Cache
|
||||
id: build-cache
|
||||
uses: actions/cache@c64c572235d810460d0d6876e9c705ad5002b353 # v2.1.6
|
||||
uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed
|
||||
with:
|
||||
path: build
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-build
|
||||
|
||||
- name: Setup Safari Cache
|
||||
id: safari-cache
|
||||
uses: actions/cache@c64c572235d810460d0d6876e9c705ad5002b353 # v2.1.6
|
||||
uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed
|
||||
with:
|
||||
path: dist-safari
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-safari-extension
|
||||
@ -820,9 +902,23 @@ jobs:
|
||||
env:
|
||||
BUILD_NUMBER: ${{ needs.setup.outputs.build_number }}
|
||||
run: |
|
||||
$package = Get-Content -Raw -Path $env:GITHUB_WORKSPACE\package.json | ConvertFrom-Json;
|
||||
$package.build | Add-Member -MemberType NoteProperty -Name buildVersion -Value "$env:BUILD_NUMBER";
|
||||
$package | ConvertTo-Json -Depth 32 | Set-Content $env:GITHUB_WORKSPACE\package.json;
|
||||
$package = Get-Content -Raw -Path $env:GITHUB_WORKSPACE\electron-builder.json | ConvertFrom-Json;
|
||||
$package | Add-Member -MemberType NoteProperty -Name buildVersion -Value "$env:BUILD_NUMBER";
|
||||
$package | ConvertTo-Json -Depth 32 | Set-Content $env:GITHUB_WORKSPACE\electron-builder.json;
|
||||
|
||||
- name: Cache Native Module
|
||||
uses: actions/cache@48af2dc4a9e8278b89d7fa154b955c30c6aaab09 # v3.0.2
|
||||
id: cache
|
||||
with:
|
||||
path: desktop_native/*.node
|
||||
key: rust-${{ runner.os }}-${{ hashFiles('desktop_native/**/*') }}
|
||||
|
||||
- name: Build Native Module
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
working-directory: './desktop_native'
|
||||
run: |
|
||||
npm ci
|
||||
npm run build:cross-platform
|
||||
|
||||
- name: NPM install
|
||||
run: npm ci
|
||||
@ -838,20 +934,24 @@ jobs:
|
||||
|
||||
- name: Checkout browser extension
|
||||
if: steps.safari-cache.outputs.cache-hit != 'true'
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
|
||||
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
|
||||
with:
|
||||
repository: 'bitwarden/browser'
|
||||
path: 'dist-safari/browser'
|
||||
path: 'dist-safari/bitwarden'
|
||||
ref: ${{ needs.setup.outputs.safari_ref }}
|
||||
|
||||
- name: Build Safari extension
|
||||
if: steps.safari-cache.outputs.cache-hit != 'true'
|
||||
shell: pwsh
|
||||
run: ./scripts/safari-build.ps1 -skipcheckout -skipoutcopy
|
||||
run: |
|
||||
npm install
|
||||
npm run dist:safari
|
||||
working-directory: dist-safari/bitwarden/apps/browser
|
||||
|
||||
- name: Load Safari extension for App Store
|
||||
shell: pwsh
|
||||
run: ./scripts/safari-build.ps1 -mas -copyonly
|
||||
working-directory: dist-safari/bitwarden/apps/browser
|
||||
run: |
|
||||
mkdir PlugIns
|
||||
cp -r dist/Safari/mas/build/Release/safari.appex PlugIns/safari.appex
|
||||
|
||||
- name: Build application for App Store
|
||||
run: npm run pack:mac:mas
|
||||
@ -860,7 +960,7 @@ jobs:
|
||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||
|
||||
- name: Upload .pkg artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: Bitwarden-${{ env._PACKAGE_VERSION }}-universal.pkg
|
||||
path: ./dist/mas-universal/Bitwarden-${{ env._PACKAGE_VERSION }}-universal.pkg
|
||||
@ -875,7 +975,7 @@ jobs:
|
||||
&& needs.setup.outputs.rc_branch_exists == 0
|
||||
&& needs.setup.outputs.hotfix_branch_exists == 0)
|
||||
|| (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0)
|
||||
|| github.ref == 'refs/heads/hotfix'
|
||||
|| github.ref == 'refs/heads/hotfix-rc'
|
||||
run: npm run upload:mas
|
||||
|
||||
|
||||
@ -883,25 +983,23 @@ jobs:
|
||||
name: MacOS Package Dev Release Asset
|
||||
if: false # We need to look into how code signing works for dev
|
||||
runs-on: macos-11
|
||||
needs: [setup, macos-build]
|
||||
needs:
|
||||
- setup
|
||||
- macos-build
|
||||
- lint
|
||||
env:
|
||||
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
|
||||
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea # v2.1.5
|
||||
uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: '**/package-lock.json'
|
||||
node-version: '16'
|
||||
|
||||
- name: Cache npm
|
||||
id: npm-cache
|
||||
uses: actions/cache@c64c572235d810460d0d6876e9c705ad5002b353 # v2.1.6
|
||||
with:
|
||||
path: '~/.npm'
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-npm-${{ hashFiles('**/package-lock.json') }}
|
||||
|
||||
- name: Set Node options
|
||||
run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV
|
||||
|
||||
@ -919,14 +1017,14 @@ jobs:
|
||||
|
||||
- name: Get Build Cache
|
||||
id: build-cache
|
||||
uses: actions/cache@c64c572235d810460d0d6876e9c705ad5002b353 # v2.1.6
|
||||
uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed
|
||||
with:
|
||||
path: build
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-build
|
||||
|
||||
- name: Setup Safari Cache
|
||||
id: safari-cache
|
||||
uses: actions/cache@c64c572235d810460d0d6876e9c705ad5002b353 # v2.1.6
|
||||
uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed
|
||||
with:
|
||||
path: dist-safari
|
||||
key: ${{ runner.os }}-${{ github.run_id }}-safari-extension
|
||||
@ -998,9 +1096,23 @@ jobs:
|
||||
env:
|
||||
BUILD_NUMBER: ${{ needs.setup.outputs.build_number }}
|
||||
run: |
|
||||
$package = Get-Content -Raw -Path $env:GITHUB_WORKSPACE\package.json | ConvertFrom-Json;
|
||||
$package.build | Add-Member -MemberType NoteProperty -Name buildVersion -Value "$env:BUILD_NUMBER";
|
||||
$package | ConvertTo-Json -Depth 32 | Set-Content $env:GITHUB_WORKSPACE\package.json;
|
||||
$package = Get-Content -Raw -Path $env:GITHUB_WORKSPACE\electron-builder.json | ConvertFrom-Json;
|
||||
$package | Add-Member -MemberType NoteProperty -Name buildVersion -Value "$env:BUILD_NUMBER";
|
||||
$package | ConvertTo-Json -Depth 32 | Set-Content $env:GITHUB_WORKSPACE\electron-builder.json;
|
||||
|
||||
- name: Cache Native Module
|
||||
uses: actions/cache@48af2dc4a9e8278b89d7fa154b955c30c6aaab09 # v3.0.2
|
||||
id: cache
|
||||
with:
|
||||
path: desktop_native/*.node
|
||||
key: rust-${{ runner.os }}-${{ hashFiles('desktop_native/**/*') }}
|
||||
|
||||
- name: Build Native Module
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
working-directory: './desktop_native'
|
||||
run: |
|
||||
npm ci
|
||||
npm run build:cross-platform
|
||||
|
||||
- name: NPM install
|
||||
run: npm ci
|
||||
@ -1016,20 +1128,24 @@ jobs:
|
||||
|
||||
- name: Checkout browser extension
|
||||
if: steps.safari-cache.outputs.cache-hit != 'true'
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
|
||||
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
|
||||
with:
|
||||
repository: 'bitwarden/browser'
|
||||
path: 'dist-safari/browser'
|
||||
path: 'dist-safari/bitwarden'
|
||||
ref: ${{ needs.setup.outputs.safari_ref }}
|
||||
|
||||
- name: Build Safari extension
|
||||
if: steps.safari-cache.outputs.cache-hit != 'true'
|
||||
shell: pwsh
|
||||
run: ./scripts/safari-build.ps1 -skipcheckout -skipoutcopy
|
||||
run: |
|
||||
npm install
|
||||
npm run dist:safari
|
||||
working-directory: dist-safari/bitwarden/apps/browser
|
||||
|
||||
- name: Load Safari extension for App Store
|
||||
shell: pwsh
|
||||
run: ./scripts/safari-build.ps1 -masdev -copyonly
|
||||
working-directory: dist-safari/bitwarden/apps/browser
|
||||
run: |
|
||||
mkdir PlugIns
|
||||
cp -r dist/Safari/masdev/build/Release/safari.appex PlugIns/safari.appex
|
||||
|
||||
- name: Build dev application for App Store
|
||||
run: npm run pack:mac:masdev
|
||||
@ -1042,7 +1158,7 @@ jobs:
|
||||
run: zip -r Bitwarden-${{ env.PACKAGE_VERSION }}-masdev-universal.zip Bitwarden.app
|
||||
|
||||
- name: Upload masdev artifact
|
||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||
with:
|
||||
name: Bitwarden-${{ env._PACKAGE_VERSION }}-masdev-universal.zip
|
||||
path: ./dist/mas-universal/Bitwarden-${{ env._PACKAGE_VERSION }}-masdev-universal.zip
|
||||
@ -1062,22 +1178,22 @@ jobs:
|
||||
_CROWDIN_PROJECT_ID: "299360"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
|
||||
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
|
||||
|
||||
- name: Login to Azure
|
||||
uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a
|
||||
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
|
||||
|
||||
- name: Retrieve secrets
|
||||
id: retrieve-secrets
|
||||
uses: Azure/get-keyvault-secrets@80ccd3fafe5662407cc2e55f202ee34bfff8c403
|
||||
uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f
|
||||
with:
|
||||
keyvault: "bitwarden-prod-kv"
|
||||
secrets: "crowdin-api-token"
|
||||
|
||||
- name: Upload Sources
|
||||
uses: crowdin/github-action@e39093fd75daae7859c68eded4b43d42ec78d8ea # v1.3.2
|
||||
uses: crowdin/github-action@9237b4cb361788dfce63feb2e2f15c09e2fe7415
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
|
||||
@ -1095,6 +1211,7 @@ jobs:
|
||||
needs:
|
||||
- cloc
|
||||
- setup
|
||||
- lint
|
||||
- linux
|
||||
- windows
|
||||
- macos-build
|
||||
@ -1107,6 +1224,7 @@ jobs:
|
||||
env:
|
||||
CLOC_STATUS: ${{ needs.cloc.result }}
|
||||
SETUP_STATUS: ${{ needs.setup.result }}
|
||||
LINT_STATUS: ${{ needs.lint.result }}
|
||||
LINUX_STATUS: ${{ needs.linux.result }}
|
||||
WINDOWS_STATUS: ${{ needs.windows.result }}
|
||||
MACOS_BUILD_STATUS: ${{ needs.macos-build.result }}
|
||||
@ -1118,6 +1236,8 @@ jobs:
|
||||
exit 1
|
||||
elif [ "$SETUP_STATUS" = "failure" ]; then
|
||||
exit 1
|
||||
elif [ "$LINT_STATUS" = "failure" ]; then
|
||||
exit 1
|
||||
elif [ "$LINUX_STATUS" = "failure" ]; then
|
||||
exit 1
|
||||
elif [ "$WINDOWS_STATUS" = "failure" ]; then
|
||||
@ -1133,21 +1253,21 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Login to Azure - Prod Subscription
|
||||
uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a
|
||||
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf
|
||||
if: failure()
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
|
||||
|
||||
- name: Retrieve secrets
|
||||
id: retrieve-secrets
|
||||
uses: Azure/get-keyvault-secrets@80ccd3fafe5662407cc2e55f202ee34bfff8c403
|
||||
uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f
|
||||
if: failure()
|
||||
with:
|
||||
keyvault: "bitwarden-prod-kv"
|
||||
secrets: "devops-alerts-slack-webhook-url"
|
||||
|
||||
- name: Notify Slack on failure
|
||||
uses: act10ns/slack@e4e71685b9b239384b0f676a63c32367f59c2522 # v1.2.2
|
||||
uses: act10ns/slack@da3191ebe2e67f49b46880b4633f5591a96d1d33
|
||||
if: failure()
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }}
|
||||
|
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-20.04
|
||||
steps:
|
||||
- name: Enforce Label
|
||||
uses: yogevbd/enforce-label-action@8d1e1709b1011e6d90400a0e6cf7c0b77aa5efeb
|
||||
with:
|
||||
BANNED_LABELS: "hold"
|
||||
BANNED_LABELS_DESCRIPTION: "PRs on hold cannot be merged"
|
87
.github/workflows/release.yml
vendored
@ -12,6 +12,7 @@ on:
|
||||
options:
|
||||
- Initial Release
|
||||
- Redeploy
|
||||
- Dry Run
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
@ -22,10 +23,11 @@ jobs:
|
||||
branch-name: ${{ steps.branch.outputs.branch-name }}
|
||||
steps:
|
||||
- name: Branch check
|
||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||
run: |
|
||||
if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix" ]]; then
|
||||
if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix-rc" ]]; then
|
||||
echo "==================================="
|
||||
echo "[!] Can only release from the 'rc' or 'hotfix' branches"
|
||||
echo "[!] Can only release from the 'rc' or 'hotfix-rc' branches"
|
||||
echo "==================================="
|
||||
exit 1
|
||||
fi
|
||||
@ -60,47 +62,69 @@ jobs:
|
||||
BRANCH_NAME=$(basename ${{ github.ref }})
|
||||
echo "::set-output name=branch-name::$BRANCH_NAME"
|
||||
|
||||
- name: Login to Azure
|
||||
uses: Azure/login@ec3c14589bd3e9312b3cc8c41e6860e258df9010
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
|
||||
|
||||
- name: Retrieve secrets
|
||||
id: retrieve-secrets
|
||||
uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f
|
||||
with:
|
||||
keyvault: "bitwarden-prod-kv"
|
||||
secrets: "aws-electron-access-id, aws-electron-access-key"
|
||||
|
||||
- name: Download all artifacts
|
||||
uses: bitwarden/gh-actions/download-artifacts@23433be15ed6fd046ce12b6889c5184a8d9c8783
|
||||
uses: bitwarden/gh-actions/download-artifacts@c1fa8e09871a860862d6bbe36184b06d2c7e35a8
|
||||
with:
|
||||
workflow: build.yml
|
||||
workflow_conclusion: success
|
||||
branch: ${{ steps.branch.outputs.branch-name }}
|
||||
path: ./artifacts
|
||||
|
||||
- name: Rename .pkg to .pkg.archive
|
||||
env:
|
||||
PKG_VERSION: ${{ steps.retrieve-version.outputs.package_version }}
|
||||
working-directory: ./artifacts
|
||||
run: mv Bitwarden-${{ env.PKG_VERSION }}-universal.pkg Bitwarden-${{ env.PKG_VERSION }}-universal.pkg.archive
|
||||
|
||||
- name: Publish artifacts to S3
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ steps.retrieve-secrets.outputs.aws-electron-access-id }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ steps.retrieve-secrets.outputs.aws-electron-access-key }}
|
||||
AWS_DEFAULT_REGION: 'us-west-2'
|
||||
run: |
|
||||
aws s3 cp ./artifacts s3://public-s3-electron-artifacts/desktop/ \
|
||||
--acl "public-read" \
|
||||
--recursive \
|
||||
--quiet
|
||||
|
||||
- name: Create release
|
||||
uses: ncipollo/release-action@95215a3cb6e6a1908b3c44e00b4fdb15548b1e09 # v2.8.5
|
||||
env:
|
||||
PKG_VERSION: ${{ steps.retrieve-version.outputs.package_version }}
|
||||
with:
|
||||
artifacts: "Bitwarden-${{ env.PKG_VERSION }}-amd64.deb,
|
||||
Bitwarden-${{ env.PKG_VERSION }}-x86_64.rpm,
|
||||
Bitwarden-${{ env.PKG_VERSION }}-x64.freebsd,
|
||||
bitwarden_${{ env.PKG_VERSION }}_amd64.snap,
|
||||
Bitwarden-${{ env.PKG_VERSION }}-x86_64.AppImage,
|
||||
latest-linux.yml,
|
||||
Bitwarden-Portable-${{ env.PKG_VERSION }}.exe,
|
||||
Bitwarden-Installer-${{ env.PKG_VERSION }}.exe,
|
||||
Bitwarden-${{ env.PKG_VERSION }}-ia32-store.appx,
|
||||
Bitwarden-${{ env.PKG_VERSION }}-ia32.appx,
|
||||
Bitwarden-${{ env.PKG_VERSION }}-ia32.nsis.7z,
|
||||
Bitwarden-${{ env.PKG_VERSION }}-x64-store.appx,
|
||||
Bitwarden-${{ env.PKG_VERSION }}-x64.appx,
|
||||
Bitwarden-${{ env.PKG_VERSION }}-x64.nsis.7z,
|
||||
Bitwarden-${{ env.PKG_VERSION }}-arm64-store.appx,
|
||||
Bitwarden-${{ env.PKG_VERSION }}-arm64.appx,
|
||||
Bitwarden-${{ env.PKG_VERSION }}-arm64.nsis.7z,
|
||||
bitwarden.${{ env.PKG_VERSION }}.nupkg,
|
||||
latest.yml,
|
||||
Bitwarden-${{ env.PKG_VERSION }}-universal-mac.zip,
|
||||
Bitwarden-${{ env.PKG_VERSION }}-universal.dmg,
|
||||
Bitwarden-${{ env.PKG_VERSION }}-universal.dmg.blockmap,
|
||||
latest-mac.yml,
|
||||
Bitwarden-${{ env.PKG_VERSION }}-universal.pkg.archive"
|
||||
artifacts: "artifacts/Bitwarden-${{ env.PKG_VERSION }}-amd64.deb,
|
||||
artifacts/Bitwarden-${{ env.PKG_VERSION }}-x86_64.rpm,
|
||||
artifacts/Bitwarden-${{ env.PKG_VERSION }}-x64.freebsd,
|
||||
artifacts/bitwarden_${{ env.PKG_VERSION }}_amd64.snap,
|
||||
artifacts/Bitwarden-${{ env.PKG_VERSION }}-x86_64.AppImage,
|
||||
artifacts/Bitwarden-Portable-${{ env.PKG_VERSION }}.exe,
|
||||
artifacts/Bitwarden-Installer-${{ env.PKG_VERSION }}.exe,
|
||||
artifacts/Bitwarden-${{ env.PKG_VERSION }}-ia32-store.appx,
|
||||
artifacts/Bitwarden-${{ env.PKG_VERSION }}-ia32.appx,
|
||||
artifacts/Bitwarden-${{ env.PKG_VERSION }}-ia32.nsis.7z,
|
||||
artifacts/Bitwarden-${{ env.PKG_VERSION }}-x64-store.appx,
|
||||
artifacts/Bitwarden-${{ env.PKG_VERSION }}-x64.appx,
|
||||
artifacts/Bitwarden-${{ env.PKG_VERSION }}-x64.nsis.7z,
|
||||
artifacts/Bitwarden-${{ env.PKG_VERSION }}-arm64-store.appx,
|
||||
artifacts/Bitwarden-${{ env.PKG_VERSION }}-arm64.appx,
|
||||
artifacts/Bitwarden-${{ env.PKG_VERSION }}-arm64.nsis.7z,
|
||||
artifacts/bitwarden.${{ env.PKG_VERSION }}.nupkg,
|
||||
artifacts/Bitwarden-${{ env.PKG_VERSION }}-universal-mac.zip,
|
||||
artifacts/Bitwarden-${{ env.PKG_VERSION }}-universal.dmg,
|
||||
artifacts/Bitwarden-${{ env.PKG_VERSION }}-universal.dmg.blockmap,
|
||||
artifacts/Bitwarden-${{ env.PKG_VERSION }}-universal.pkg.archive"
|
||||
commit: ${{ github.sha }}
|
||||
tag: v${{ env.PKG_VERSION }}
|
||||
name: Version ${{ env.PKG_VERSION }}
|
||||
@ -139,7 +163,7 @@ jobs:
|
||||
run: mkdir dist
|
||||
|
||||
- name: Download Snap artifact
|
||||
uses: bitwarden/gh-actions/download-artifacts@23433be15ed6fd046ce12b6889c5184a8d9c8783
|
||||
uses: bitwarden/gh-actions/download-artifacts@c1fa8e09871a860862d6bbe36184b06d2c7e35a8
|
||||
with:
|
||||
workflow: build.yml
|
||||
workflow_conclusion: success
|
||||
@ -147,10 +171,8 @@ jobs:
|
||||
artifacts: bitwarden_${{ env._PKG_VERSION }}_amd64.snap
|
||||
path: ./dist
|
||||
|
||||
- name: Test
|
||||
run: ls -alht dist
|
||||
|
||||
- name: Deploy to Snap Store
|
||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||
run: |
|
||||
snapcraft upload dist/bitwarden_${{ env._PKG_VERSION }}_amd64.snap --release stable
|
||||
snapcraft logout
|
||||
@ -175,7 +197,7 @@ jobs:
|
||||
run: New-Item -ItemType directory -Path ./dist
|
||||
|
||||
- name: Download choco artifact
|
||||
uses: bitwarden/gh-actions/download-artifacts@23433be15ed6fd046ce12b6889c5184a8d9c8783
|
||||
uses: bitwarden/gh-actions/download-artifacts@c1fa8e09871a860862d6bbe36184b06d2c7e35a8
|
||||
with:
|
||||
workflow: build.yml
|
||||
workflow_conclusion: success
|
||||
@ -184,6 +206,7 @@ jobs:
|
||||
path: ./dist
|
||||
|
||||
- name: Push to Chocolatey
|
||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||
shell: pwsh
|
||||
run: |
|
||||
cd dist
|
||||
|
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@master
|
0
.husky/pre-commit
Normal file → Executable file
@ -2,6 +2,7 @@
|
||||
build
|
||||
dist
|
||||
dist-safari
|
||||
desktop_native
|
||||
|
||||
jslib
|
||||
|
||||
|
@ -10,7 +10,7 @@ Here is how you can get involved:
|
||||
- **Write code for a new feature:** Make a new post in the [Github Contributions category](https://community.bitwarden.com/c/github-contributions/) of the Community Forums. Include a description of your proposed contribution, screeshots, and links to any relevant feature requests. This helps get feedback from the community and Bitwarden team members before you start writing code
|
||||
- **Report a bug or submit a bugfix:** Use Github issues and pull requests
|
||||
- **Write documentation:** Submit a pull request to the [Bitwarden help repository](https://github.com/bitwarden/help)
|
||||
- **Help other users:** Go to the [User-to-User Support category](https://community.bitwarden.com/c/support/) on the Community Forums
|
||||
- **Help other users:** Go to the [Ask the Bitwarden Community category](https://community.bitwarden.com/c/support/) on the Community Forums
|
||||
- **Translate:** See the localization (l10n) section below
|
||||
|
||||
## Contributor Agreement
|
||||
@ -31,6 +31,6 @@ We use a translation tool called [Crowdin](https://crowdin.com) to help manage o
|
||||
|
||||
If you are interested in helping translate the Bitwarden desktop app into another language (or make a translation correction), please register an account at Crowdin and join our project here: https://crowdin.com/project/bitwarden-desktop
|
||||
|
||||
If the language that you are interested in translating is not already listed, create a new account on Crowdin, join the project, and contact the project owner (https://crowdin.com/profile/kspearrin).
|
||||
If the language that you are interested in translating is not already listed, create a new account on Crowdin, join the project, and contact the project owner (https://crowdin.com/profile/dwbit).
|
||||
|
||||
You can read Crowdin's getting started guide for translators here: https://support.crowdin.com/crowdin-intro/
|
||||
|
21
README.md
@ -2,6 +2,10 @@
|
||||
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/bitwarden-desktop/localized.svg)](https://crowdin.com/project/bitwarden-desktop)
|
||||
[![Join the chat at https://gitter.im/bitwarden/Lobby](https://badges.gitter.im/bitwarden/Lobby.svg)](https://gitter.im/bitwarden/Lobby)
|
||||
|
||||
> **Archived**
|
||||
>
|
||||
> This repository is archived, please go to https://github.com/bitwarden/clients for future development.
|
||||
|
||||
# Bitwarden Desktop Application
|
||||
|
||||
[![Platforms](https://imgur.com/SLv9paA.png "Windows, macOS, and Linux")](https://bitwarden.com/download/)
|
||||
@ -12,20 +16,23 @@ The Bitwarden desktop app is written using Electron and Angular. The application
|
||||
|
||||
# Build/Run
|
||||
|
||||
**Requirements**
|
||||
## Requirements
|
||||
|
||||
- [Node.js](https://nodejs.org) v16.13.1 (LTS) or greater
|
||||
- NPM v8
|
||||
- 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. You will also need to install the _Microsoft Build Tools 2015_ and _Windows 10 SDK 17134_ as additional dependencies in the Visual Studio installer.
|
||||
- Windows:
|
||||
- To compile the native node modules used in the app you will need the _Visual C++ toolset_, available through the standard Visual Studio installer. You will also need to install the _Microsoft Build Tools 2015_ and _Windows 10 SDK 17134_ as additional dependencies in the Visual Studio installer.
|
||||
- Linux:
|
||||
- The following packages `build-essential libsecret-1-dev libglib2.0-dev`
|
||||
|
||||
**Run the app**
|
||||
## Run the app
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm ci
|
||||
npm run electron
|
||||
```
|
||||
|
||||
**Debug Native Messaging**
|
||||
### Debug Native Messaging
|
||||
|
||||
Native Messaging (communication with the browser extension) works by having the browser start a lightweight proxy application baked into our desktop binary. To setup an environment which allows
|
||||
for easy debugging you will need to build the application for distribution, i.e. `npm run dist:<platform>`, start the dist version and enable desktop integration. This will write some manifests
|
||||
@ -37,6 +44,10 @@ needs to be added to the `allowed_extensions` section of the manifest. These IDs
|
||||
|
||||
It will then be possible to run the desktop application as usual using `npm run electron` and communicate with the browser.
|
||||
|
||||
# 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.
|
||||
|
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!
|
||||
|
6
desktop_native/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
target
|
||||
index.node
|
||||
**/node_modules
|
||||
**/.DS_Store
|
||||
npm-debug.log*
|
||||
*.node
|
946
desktop_native/Cargo.lock
generated
Normal file
@ -0,0 +1,946 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.55"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "159bb86af3a200e19a068f4224eae4c8bb2d0fa054c7e5d1cacd5cef95e684cd"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-expr"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e068cb2806bbc15b439846dc16c5f89f8599f2c3e4d73d4449d38f9b2f0b6c5"
|
||||
dependencies = [
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "codespan-reporting"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
|
||||
dependencies = [
|
||||
"termcolor",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "convert_case"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb4a24b1aaf0fd0ce8b45161144d6f42cd91677fd5940fd431183eb023b3a2b8"
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
|
||||
|
||||
[[package]]
|
||||
name = "ctor"
|
||||
version = "0.1.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxx"
|
||||
version = "1.0.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce2295fe8865279f404147e9b2328e5af0ad11a2c016e58c13acfd48a07d8a55"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cxxbridge-flags",
|
||||
"cxxbridge-macro",
|
||||
"link-cplusplus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxx-build"
|
||||
version = "1.0.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0aaaa055d4908326f1b4524b23ae53758019b806c0c4f382ea240982e9766b26"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"codespan-reporting",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"scratch",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-flags"
|
||||
version = "1.0.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a670224c6686471df12560a0b97a08145082e70bd38e2b0b5383b79e46c3da7"
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-macro"
|
||||
version = "1.0.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b700096ca0dece28d9535fdb17ab784a8ae155d7f29d39c273643e6292c9620"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "desktop_native"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"core-foundation",
|
||||
"gio",
|
||||
"keytar",
|
||||
"libsecret",
|
||||
"napi",
|
||||
"napi-build",
|
||||
"napi-derive",
|
||||
"scopeguard",
|
||||
"security-framework",
|
||||
"security-framework-sys",
|
||||
"tokio",
|
||||
"widestring",
|
||||
"windows 0.32.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gio"
|
||||
version = "0.15.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96efd8a1c00d890f6b45671916e165b5e43ccec61957d443aff6d7e44f62d348"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"gio-sys",
|
||||
"glib",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gio-sys"
|
||||
version = "0.15.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d0fa5052773f5a56b8ae47dab09d040f5d9ce1311f4f99006e16e9a08269296"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glib"
|
||||
version = "0.15.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa570813c504bdf7539a9400180c2dd4b789a819556fb86da7226d7d1b037b49"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-executor",
|
||||
"futures-task",
|
||||
"glib-macros",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"smallvec",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glib-macros"
|
||||
version = "0.15.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41bfd8d227dead0829ac142454e97531b93f576d0805d779c42bfd799c65c572"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"heck",
|
||||
"proc-macro-crate",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glib-sys"
|
||||
version = "0.15.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4366377bd56697de8aaee24e673c575d2694d72e7756324ded2b0428829a7b8"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gobject-sys"
|
||||
version = "0.15.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df6859463843c20cf3837e3a9069b6ab2051aeeadf4c899d33344f4aea83189a"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "keytar"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d361c55fba09829ac620b040f5425bf239b1030c3d6820a84acac8da867dca4d"
|
||||
dependencies = [
|
||||
"keytar-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "keytar-sys"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe908c6896705a1cb516cd6a5d956c63f08d95ace81b93253a98cd93e1e6a65a"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cxx",
|
||||
"cxx-build",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.119"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4"
|
||||
|
||||
[[package]]
|
||||
name = "libsecret"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4af5a2342942fa42d706a424e9f9914287fb8317132750fd73a241140ac38c1"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"gio",
|
||||
"glib",
|
||||
"libc",
|
||||
"libsecret-sys",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libsecret-sys"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "287d2a0fcd95e4d7b0ac6fc9f802691a790d7e522138713b0cacebc4e63cab91"
|
||||
dependencies = [
|
||||
"gio-sys",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "link-cplusplus"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8cae2cd7ba2f3f63938b9c724475dfb7b9861b545a90324476324ed21dbc8c8"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b"
|
||||
dependencies = [
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"miow",
|
||||
"ntapi",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miow"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "napi"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17ec66e60f000c78dd7c6215b6fa260e0591e09805024332bc5b3f55acc12244"
|
||||
dependencies = [
|
||||
"ctor",
|
||||
"lazy_static",
|
||||
"napi-sys",
|
||||
"tokio",
|
||||
"windows 0.30.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "napi-build"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebd4419172727423cf30351406c54f6cc1b354a2cfb4f1dba3e6cd07f6d5522b"
|
||||
|
||||
[[package]]
|
||||
name = "napi-derive"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74ac5287a5e94a8728fc82d16c5127acc5eb5b8ad6404ef5f82d6a4ce8d5bdd2"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"napi-derive-backend",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "napi-derive-backend"
|
||||
version = "1.0.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "427f4f04525635cdf22005d1be62d6d671bcb5550d694a1efb480a315422b4af"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "napi-sys"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a385494dac3c52cbcacb393bb3b42669e7db8ab240c7ad5115f549eb061f2cc"
|
||||
|
||||
[[package]]
|
||||
name = "ntapi"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "scratch"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96311ef4a16462c757bb6a39152c40f58f31cd2602a40fceb937e2bc34e6cbab"
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"core-foundation",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
"security-framework-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework-sys"
|
||||
version = "2.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.136"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-deps"
|
||||
version = "6.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1a45a1c4c9015217e12347f2a411b57ce2c4fc543913b14b6fe40483328e709"
|
||||
dependencies = [
|
||||
"cfg-expr",
|
||||
"heck",
|
||||
"pkg-config",
|
||||
"toml",
|
||||
"version-compare",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
"memchr",
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||
|
||||
[[package]]
|
||||
name = "version-compare"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "widestring"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b749ebd2304aa012c5992d11a25d07b406bdbe5f79d371cb7a918ce501a19eb0"
|
||||
dependencies = [
|
||||
"windows_aarch64_msvc 0.30.0",
|
||||
"windows_i686_gnu 0.30.0",
|
||||
"windows_i686_msvc 0.30.0",
|
||||
"windows_x86_64_gnu 0.30.0",
|
||||
"windows_x86_64_msvc 0.30.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbedf6db9096bc2364adce0ae0aa636dcd89f3c3f2cd67947062aaf0ca2a10ec"
|
||||
dependencies = [
|
||||
"windows_aarch64_msvc 0.32.0",
|
||||
"windows_i686_gnu 0.32.0",
|
||||
"windows_i686_msvc 0.32.0",
|
||||
"windows_x86_64_gnu 0.32.0",
|
||||
"windows_x86_64_msvc 0.32.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6"
|
||||
dependencies = [
|
||||
"windows_aarch64_msvc 0.32.0",
|
||||
"windows_i686_gnu 0.32.0",
|
||||
"windows_i686_msvc 0.32.0",
|
||||
"windows_x86_64_gnu 0.32.0",
|
||||
"windows_x86_64_msvc 0.32.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29277a4435d642f775f63c7d1faeb927adba532886ce0287bd985bffb16b6bca"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1145e1989da93956c68d1864f32fb97c8f561a8f89a5125f6a2b7ea75524e4b8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4a09e3a0d4753b73019db171c1339cd4362c8c44baf1bcea336235e955954a6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ca64fcb0220d58db4c119e050e7af03c69e6f4f415ef69ec1773d9aab422d5a"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08cabc9f0066848fef4bc6a1c1668e6efce38b661d2aeec75d18d8617eebb5f1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316"
|
43
desktop_native/Cargo.toml
Normal file
@ -0,0 +1,43 @@
|
||||
[package]
|
||||
edition = "2021"
|
||||
exclude = ["index.node"]
|
||||
license = "GPL-3.0"
|
||||
name = "desktop_native"
|
||||
version = "0.0.0"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0"
|
||||
napi = {version = "2", features = ["async"]}
|
||||
napi-derive = "2"
|
||||
scopeguard = "1.1.0"
|
||||
tokio = {version = "1.17.0", features = ["full"]}
|
||||
|
||||
[build-dependencies]
|
||||
napi-build = "1"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
widestring = "0.5.1"
|
||||
windows = {version = "0.32.0", features = [
|
||||
"alloc",
|
||||
"Foundation",
|
||||
"Storage_Streams",
|
||||
"Win32_Foundation",
|
||||
"Win32_Security_Credentials",
|
||||
]}
|
||||
|
||||
[target.'cfg(windows)'.dev-dependencies]
|
||||
keytar = "0.1.6"
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
core-foundation = "0.9.3"
|
||||
security-framework = "2.6.1"
|
||||
security-framework-sys = "2.6.1"
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
gio = "0.15.6"
|
||||
libsecret = "0.1.4"
|
22
desktop_native/build.js
Normal file
@ -0,0 +1,22 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const child_process = require("child_process");
|
||||
const process = require("process");
|
||||
|
||||
let targets = [];
|
||||
switch (process.platform) {
|
||||
case "win32":
|
||||
targets = ["i686-pc-windows-msvc", "x86_64-pc-windows-msvc", "aarch64-pc-windows-msvc"];
|
||||
break;
|
||||
|
||||
case "darwin":
|
||||
targets = ["x86_64-apple-darwin", "aarch64-apple-darwin"];
|
||||
break;
|
||||
|
||||
default:
|
||||
targets = ['x86_64-unknown-linux-gnu'];
|
||||
break;
|
||||
}
|
||||
|
||||
targets.forEach(target => {
|
||||
child_process.execSync(`npm run build -- --target ${target}`, {stdio: 'inherit'});
|
||||
});
|
5
desktop_native/build.rs
Normal file
@ -0,0 +1,5 @@
|
||||
extern crate napi_build;
|
||||
|
||||
fn main() {
|
||||
napi_build::setup();
|
||||
}
|
15
desktop_native/index.d.ts
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
/* auto-generated by NAPI-RS */
|
||||
|
||||
export namespace passwords {
|
||||
/** Fetch the stored password from the keychain. */
|
||||
export function getPassword(service: string, account: string): Promise<string>
|
||||
/** Fetch the stored password from the keychain that was stored with Keytar. */
|
||||
export function getPasswordKeytar(service: string, account: string): Promise<string>
|
||||
/** Save the password to the keychain. Adds an entry if none exists otherwise updates the existing entry. */
|
||||
export function setPassword(service: string, account: string, password: string): Promise<void>
|
||||
/** Delete the stored password from the keychain. */
|
||||
export function deletePassword(service: string, account: string): Promise<void>
|
||||
}
|
241
desktop_native/index.js
Normal file
@ -0,0 +1,241 @@
|
||||
const { existsSync, readFileSync } = require('fs')
|
||||
const { join } = require('path')
|
||||
|
||||
const { platform, arch } = process
|
||||
|
||||
let nativeBinding = null
|
||||
let localFileExisted = false
|
||||
let loadError = null
|
||||
|
||||
function isMusl() {
|
||||
// For Node 10
|
||||
if (!process.report || typeof process.report.getReport !== 'function') {
|
||||
try {
|
||||
return readFileSync('/usr/bin/ldd', 'utf8').includes('musl')
|
||||
} catch (e) {
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
const { glibcVersionRuntime } = process.report.getReport().header
|
||||
return !glibcVersionRuntime
|
||||
}
|
||||
}
|
||||
|
||||
switch (platform) {
|
||||
case 'android':
|
||||
switch (arch) {
|
||||
case 'arm64':
|
||||
localFileExisted = existsSync(join(__dirname, 'desktop_native.android-arm64.node'))
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./desktop_native.android-arm64.node')
|
||||
} else {
|
||||
nativeBinding = require('@bitwarden/desktop_native-android-arm64')
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
}
|
||||
break
|
||||
case 'arm':
|
||||
localFileExisted = existsSync(join(__dirname, 'desktop_native.android-arm-eabi.node'))
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./desktop_native.android-arm-eabi.node')
|
||||
} else {
|
||||
nativeBinding = require('@bitwarden/desktop_native-android-arm-eabi')
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
}
|
||||
break
|
||||
default:
|
||||
throw new Error(`Unsupported architecture on Android ${arch}`)
|
||||
}
|
||||
break
|
||||
case 'win32':
|
||||
switch (arch) {
|
||||
case 'x64':
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, 'desktop_native.win32-x64-msvc.node')
|
||||
)
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./desktop_native.win32-x64-msvc.node')
|
||||
} else {
|
||||
nativeBinding = require('@bitwarden/desktop_native-win32-x64-msvc')
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
}
|
||||
break
|
||||
case 'ia32':
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, 'desktop_native.win32-ia32-msvc.node')
|
||||
)
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./desktop_native.win32-ia32-msvc.node')
|
||||
} else {
|
||||
nativeBinding = require('@bitwarden/desktop_native-win32-ia32-msvc')
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
}
|
||||
break
|
||||
case 'arm64':
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, 'desktop_native.win32-arm64-msvc.node')
|
||||
)
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./desktop_native.win32-arm64-msvc.node')
|
||||
} else {
|
||||
nativeBinding = require('@bitwarden/desktop_native-win32-arm64-msvc')
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
}
|
||||
break
|
||||
default:
|
||||
throw new Error(`Unsupported architecture on Windows: ${arch}`)
|
||||
}
|
||||
break
|
||||
case 'darwin':
|
||||
switch (arch) {
|
||||
case 'x64':
|
||||
localFileExisted = existsSync(join(__dirname, 'desktop_native.darwin-x64.node'))
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./desktop_native.darwin-x64.node')
|
||||
} else {
|
||||
nativeBinding = require('@bitwarden/desktop_native-darwin-x64')
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
}
|
||||
break
|
||||
case 'arm64':
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, 'desktop_native.darwin-arm64.node')
|
||||
)
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./desktop_native.darwin-arm64.node')
|
||||
} else {
|
||||
nativeBinding = require('@bitwarden/desktop_native-darwin-arm64')
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
}
|
||||
break
|
||||
default:
|
||||
throw new Error(`Unsupported architecture on macOS: ${arch}`)
|
||||
}
|
||||
break
|
||||
case 'freebsd':
|
||||
if (arch !== 'x64') {
|
||||
throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)
|
||||
}
|
||||
localFileExisted = existsSync(join(__dirname, 'desktop_native.freebsd-x64.node'))
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./desktop_native.freebsd-x64.node')
|
||||
} else {
|
||||
nativeBinding = require('@bitwarden/desktop_native-freebsd-x64')
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
}
|
||||
break
|
||||
case 'linux':
|
||||
switch (arch) {
|
||||
case 'x64':
|
||||
if (isMusl()) {
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, 'desktop_native.linux-x64-musl.node')
|
||||
)
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./desktop_native.linux-x64-musl.node')
|
||||
} else {
|
||||
nativeBinding = require('@bitwarden/desktop_native-linux-x64-musl')
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
}
|
||||
} else {
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, 'desktop_native.linux-x64-gnu.node')
|
||||
)
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./desktop_native.linux-x64-gnu.node')
|
||||
} else {
|
||||
nativeBinding = require('@bitwarden/desktop_native-linux-x64-gnu')
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
}
|
||||
}
|
||||
break
|
||||
case 'arm64':
|
||||
if (isMusl()) {
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, 'desktop_native.linux-arm64-musl.node')
|
||||
)
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./desktop_native.linux-arm64-musl.node')
|
||||
} else {
|
||||
nativeBinding = require('@bitwarden/desktop_native-linux-arm64-musl')
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
}
|
||||
} else {
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, 'desktop_native.linux-arm64-gnu.node')
|
||||
)
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./desktop_native.linux-arm64-gnu.node')
|
||||
} else {
|
||||
nativeBinding = require('@bitwarden/desktop_native-linux-arm64-gnu')
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
}
|
||||
}
|
||||
break
|
||||
case 'arm':
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, 'desktop_native.linux-arm-gnueabihf.node')
|
||||
)
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./desktop_native.linux-arm-gnueabihf.node')
|
||||
} else {
|
||||
nativeBinding = require('@bitwarden/desktop_native-linux-arm-gnueabihf')
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
}
|
||||
break
|
||||
default:
|
||||
throw new Error(`Unsupported architecture on Linux: ${arch}`)
|
||||
}
|
||||
break
|
||||
default:
|
||||
throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
|
||||
}
|
||||
|
||||
if (!nativeBinding) {
|
||||
if (loadError) {
|
||||
throw loadError
|
||||
}
|
||||
throw new Error(`Failed to load native binding`)
|
||||
}
|
||||
|
||||
const { passwords } = nativeBinding
|
||||
|
||||
module.exports.passwords = passwords
|
41
desktop_native/package-lock.json
generated
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "@bitwarden/desktop_native",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@bitwarden/desktop_native",
|
||||
"version": "0.1.0",
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0",
|
||||
"devDependencies": {
|
||||
"@napi-rs/cli": "^2.6.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/cli": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.6.2.tgz",
|
||||
"integrity": "sha512-EmH+DQDEBUIoqMim0cc+X96ImtcIZLFjgW5WWORpzYnA9Ug7zNPO7jCLMhIQRd/p5AdWaXrT4SVXc/aip09rKQ==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"napi": "scripts/index.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/Brooooooklyn"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@napi-rs/cli": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.6.2.tgz",
|
||||
"integrity": "sha512-EmH+DQDEBUIoqMim0cc+X96ImtcIZLFjgW5WWORpzYnA9Ug7zNPO7jCLMhIQRd/p5AdWaXrT4SVXc/aip09rKQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
32
desktop_native/package.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "@bitwarden/desktop_native",
|
||||
"version": "0.1.0",
|
||||
"description": "",
|
||||
"main": "index.node",
|
||||
"scripts": {
|
||||
"build": "napi build --release --platform",
|
||||
"build:debug": "napi build --platform",
|
||||
"build:cross-platform": "node build.js",
|
||||
"test": "cargo test"
|
||||
},
|
||||
"author": "",
|
||||
"license": "GPL-3.0",
|
||||
"devDependencies": {
|
||||
"@napi-rs/cli": "^2.6.2"
|
||||
},
|
||||
"napi": {
|
||||
"name": "desktop_native",
|
||||
"triples": {
|
||||
"defaults": true,
|
||||
"additional": [
|
||||
"x86_64-unknown-linux-musl",
|
||||
"aarch64-unknown-linux-gnu",
|
||||
"i686-pc-windows-msvc",
|
||||
"armv7-unknown-linux-gnueabihf",
|
||||
"aarch64-apple-darwin",
|
||||
"aarch64-unknown-linux-musl",
|
||||
"aarch64-pc-windows-msvc"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
39
desktop_native/src/lib.rs
Normal file
@ -0,0 +1,39 @@
|
||||
#[macro_use]
|
||||
extern crate napi_derive;
|
||||
|
||||
mod password;
|
||||
|
||||
#[napi]
|
||||
pub mod passwords {
|
||||
/// Fetch the stored password from the keychain.
|
||||
#[napi]
|
||||
pub async fn get_password(service: String, account: String) -> napi::Result<String> {
|
||||
super::password::get_password(&service, &account)
|
||||
.map_err(|e| napi::Error::from_reason(e.to_string()))
|
||||
}
|
||||
|
||||
/// Fetch the stored password from the keychain that was stored with Keytar.
|
||||
#[napi]
|
||||
pub async fn get_password_keytar(service: String, account: String) -> napi::Result<String> {
|
||||
super::password::get_password_keytar(&service, &account)
|
||||
.map_err(|e| napi::Error::from_reason(e.to_string()))
|
||||
}
|
||||
|
||||
/// Save the password to the keychain. Adds an entry if none exists otherwise updates the existing entry.
|
||||
#[napi]
|
||||
pub async fn set_password(
|
||||
service: String,
|
||||
account: String,
|
||||
password: String,
|
||||
) -> napi::Result<()> {
|
||||
super::password::set_password(&service, &account, &password)
|
||||
.map_err(|e| napi::Error::from_reason(e.to_string()))
|
||||
}
|
||||
|
||||
/// Delete the stored password from the keychain.
|
||||
#[napi]
|
||||
pub async fn delete_password(service: String, account: String) -> napi::Result<()> {
|
||||
super::password::delete_password(&service, &account)
|
||||
.map_err(|e| napi::Error::from_reason(e.to_string()))
|
||||
}
|
||||
}
|
59
desktop_native/src/password/macos.rs
Normal file
@ -0,0 +1,59 @@
|
||||
use anyhow::Result;
|
||||
use security_framework::passwords::{
|
||||
delete_generic_password, get_generic_password, set_generic_password,
|
||||
};
|
||||
|
||||
pub fn get_password(service: &str, account: &str) -> Result<String> {
|
||||
let result = String::from_utf8(get_generic_password(&service, &account)?)?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn get_password_keytar(service: &str, account: &str) -> Result<String> {
|
||||
get_password(service, account)
|
||||
}
|
||||
|
||||
pub fn set_password(service: &str, account: &str, password: &str) -> Result<()> {
|
||||
let result = set_generic_password(&service, &account, password.as_bytes())?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn delete_password(service: &str, account: &str) -> Result<()> {
|
||||
let result = delete_generic_password(&service, &account)?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
scopeguard::defer!(delete_password("BitwardenTest", "BitwardenTest").unwrap_or({}););
|
||||
set_password("BitwardenTest", "BitwardenTest", "Random").unwrap();
|
||||
assert_eq!(
|
||||
"Random",
|
||||
get_password("BitwardenTest", "BitwardenTest").unwrap()
|
||||
);
|
||||
delete_password("BitwardenTest", "BitwardenTest").unwrap();
|
||||
|
||||
// Ensure password is deleted
|
||||
match get_password("BitwardenTest", "BitwardenTest") {
|
||||
Ok(_) => panic!("Got a result"),
|
||||
Err(e) => assert_eq!(
|
||||
"The specified item could not be found in the keychain.",
|
||||
e.to_string()
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_error_no_password() {
|
||||
match get_password("Unknown", "Unknown") {
|
||||
Ok(_) => panic!("Got a result"),
|
||||
Err(e) => assert_eq!(
|
||||
"The specified item could not be found in the keychain.",
|
||||
e.to_string()
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
5
desktop_native/src/password/mod.rs
Normal file
@ -0,0 +1,5 @@
|
||||
#[cfg_attr(target_os = "linux", path = "unix.rs")]
|
||||
#[cfg_attr(target_os = "windows", path = "windows.rs")]
|
||||
#[cfg_attr(target_os = "macos", path = "macos.rs")]
|
||||
mod password;
|
||||
pub use password::*;
|
91
desktop_native/src/password/unix.rs
Normal file
@ -0,0 +1,91 @@
|
||||
use anyhow::{anyhow, Result};
|
||||
use libsecret::{password_clear_sync, password_lookup_sync, password_store_sync, Schema};
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub fn get_password(service: &str, account: &str) -> Result<String> {
|
||||
let res = password_lookup_sync(
|
||||
Some(&get_schema()),
|
||||
build_attributes(service, account),
|
||||
gio::Cancellable::NONE,
|
||||
)?;
|
||||
|
||||
match res {
|
||||
Some(s) => Ok(String::from(s)),
|
||||
None => Err(anyhow!("No password found")),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_password_keytar(service: &str, account: &str) -> Result<String> {
|
||||
get_password(service, account)
|
||||
}
|
||||
|
||||
pub fn set_password(service: &str, account: &str, password: &str) -> Result<()> {
|
||||
let result = password_store_sync(
|
||||
Some(&get_schema()),
|
||||
build_attributes(service, account),
|
||||
Some(&libsecret::COLLECTION_DEFAULT),
|
||||
&format!("{}/{}", service, account),
|
||||
password,
|
||||
gio::Cancellable::NONE,
|
||||
)?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn delete_password(service: &str, account: &str) -> Result<()> {
|
||||
let result = password_clear_sync(
|
||||
Some(&get_schema()),
|
||||
build_attributes(service, account),
|
||||
gio::Cancellable::NONE,
|
||||
)?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn get_schema() -> Schema {
|
||||
let mut attributes = std::collections::HashMap::new();
|
||||
attributes.insert("service", libsecret::SchemaAttributeType::String);
|
||||
attributes.insert("account", libsecret::SchemaAttributeType::String);
|
||||
|
||||
libsecret::Schema::new(
|
||||
"org.freedesktop.Secret.Generic",
|
||||
libsecret::SchemaFlags::NONE,
|
||||
attributes,
|
||||
)
|
||||
}
|
||||
|
||||
fn build_attributes<'a>(service: &'a str, account: &'a str) -> HashMap<&'a str, &'a str> {
|
||||
let mut attributes = HashMap::new();
|
||||
attributes.insert("service", service);
|
||||
attributes.insert("account", account);
|
||||
|
||||
attributes
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
scopeguard::defer!(delete_password("BitwardenTest", "BitwardenTest").unwrap_or({}););
|
||||
set_password("BitwardenTest", "BitwardenTest", "Random").unwrap();
|
||||
assert_eq!(
|
||||
"Random",
|
||||
get_password("BitwardenTest", "BitwardenTest").unwrap()
|
||||
);
|
||||
delete_password("BitwardenTest", "BitwardenTest").unwrap();
|
||||
|
||||
// Ensure password is deleted
|
||||
match get_password("BitwardenTest", "BitwardenTest") {
|
||||
Ok(_) => panic!("Got a result"),
|
||||
Err(e) => assert_eq!("No password found", e.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_error_no_password() {
|
||||
match get_password("BitwardenTest", "BitwardenTest") {
|
||||
Ok(_) => panic!("Got a result"),
|
||||
Err(e) => assert_eq!("No password found", e.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
180
desktop_native/src/password/windows.rs
Normal file
@ -0,0 +1,180 @@
|
||||
use anyhow::{anyhow, Result};
|
||||
use widestring::{U16CString, U16String};
|
||||
use windows::Win32::{
|
||||
Foundation::{GetLastError, ERROR_NOT_FOUND, FILETIME, PWSTR, WIN32_ERROR},
|
||||
Security::Credentials::{
|
||||
CredDeleteW, CredFree, CredReadW, CredWriteW, CREDENTIALW, CRED_FLAGS,
|
||||
CRED_PERSIST_ENTERPRISE, CRED_TYPE_GENERIC,
|
||||
},
|
||||
};
|
||||
|
||||
const CRED_FLAGS_NONE: u32 = 0;
|
||||
|
||||
pub fn get_password<'a>(service: &str, account: &str) -> Result<String> {
|
||||
let target_name = U16CString::from_str(target_name(service, account))?;
|
||||
|
||||
let mut credential: *mut CREDENTIALW = std::ptr::null_mut();
|
||||
let credential_ptr = &mut credential;
|
||||
|
||||
let result = unsafe {
|
||||
CredReadW(
|
||||
PWSTR(target_name.as_ptr()),
|
||||
CRED_TYPE_GENERIC.0,
|
||||
CRED_FLAGS_NONE,
|
||||
credential_ptr,
|
||||
)
|
||||
};
|
||||
|
||||
scopeguard::defer!({
|
||||
unsafe { CredFree(credential as *mut _) };
|
||||
});
|
||||
|
||||
if !result.as_bool() {
|
||||
return Err(anyhow!(convert_error(unsafe { GetLastError() })));
|
||||
}
|
||||
|
||||
let password = unsafe {
|
||||
U16String::from_ptr(
|
||||
(*credential).CredentialBlob as *const u16,
|
||||
(*credential).CredentialBlobSize as usize / 2,
|
||||
)
|
||||
.to_string_lossy()
|
||||
};
|
||||
|
||||
Ok(String::from(password))
|
||||
}
|
||||
|
||||
// Remove this after sufficient releases
|
||||
pub fn get_password_keytar<'a>(service: &str, account: &str) -> Result<String> {
|
||||
let target_name = U16CString::from_str(target_name(service, account))?;
|
||||
|
||||
let mut credential: *mut CREDENTIALW = std::ptr::null_mut();
|
||||
let credential_ptr = &mut credential;
|
||||
|
||||
let result = unsafe {
|
||||
CredReadW(
|
||||
PWSTR(target_name.as_ptr()),
|
||||
CRED_TYPE_GENERIC.0,
|
||||
CRED_FLAGS_NONE,
|
||||
credential_ptr,
|
||||
)
|
||||
};
|
||||
|
||||
scopeguard::defer!({
|
||||
unsafe { CredFree(credential as *mut _) };
|
||||
});
|
||||
|
||||
if !result.as_bool() {
|
||||
return Err(anyhow!(unsafe { GetLastError() }.0.to_string()));
|
||||
}
|
||||
|
||||
let password = unsafe {
|
||||
std::str::from_utf8_unchecked(std::slice::from_raw_parts(
|
||||
(*credential).CredentialBlob,
|
||||
(*credential).CredentialBlobSize as usize,
|
||||
))
|
||||
};
|
||||
|
||||
Ok(String::from(password))
|
||||
}
|
||||
|
||||
pub fn set_password(service: &str, account: &str, password: &str) -> Result<()> {
|
||||
let target_name = U16CString::from_str(target_name(service, account))?;
|
||||
let user_name = U16CString::from_str(account)?;
|
||||
let last_written = FILETIME {
|
||||
dwLowDateTime: 0,
|
||||
dwHighDateTime: 0,
|
||||
};
|
||||
|
||||
let credential = U16CString::from_str(password)?;
|
||||
let credential_len = password.len() as u32 * 2;
|
||||
|
||||
let credential = CREDENTIALW {
|
||||
Flags: CRED_FLAGS(CRED_FLAGS_NONE),
|
||||
Type: CRED_TYPE_GENERIC,
|
||||
TargetName: PWSTR(target_name.as_ptr()),
|
||||
Comment: PWSTR::default(),
|
||||
LastWritten: last_written,
|
||||
CredentialBlobSize: credential_len,
|
||||
CredentialBlob: credential.as_ptr() as *mut u8,
|
||||
Persist: CRED_PERSIST_ENTERPRISE,
|
||||
AttributeCount: 0,
|
||||
Attributes: std::ptr::null_mut(),
|
||||
TargetAlias: PWSTR::default(),
|
||||
UserName: PWSTR(user_name.as_ptr()),
|
||||
};
|
||||
|
||||
let result = unsafe { CredWriteW(&credential, 0) };
|
||||
if !result.as_bool() {
|
||||
return Err(anyhow!(unsafe { GetLastError() }.0.to_string()));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn delete_password(service: &str, account: &str) -> Result<()> {
|
||||
let target_name = U16CString::from_str(target_name(service, account))?;
|
||||
|
||||
unsafe {
|
||||
CredDeleteW(
|
||||
PWSTR(target_name.as_ptr()),
|
||||
CRED_TYPE_GENERIC.0,
|
||||
CRED_FLAGS_NONE,
|
||||
)
|
||||
.ok()?
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn target_name(service: &str, account: &str) -> String {
|
||||
format!("{}/{}", service, account)
|
||||
}
|
||||
|
||||
// Convert the internal WIN32 errors to descriptive messages
|
||||
fn convert_error(code: WIN32_ERROR) -> String {
|
||||
match code {
|
||||
ERROR_NOT_FOUND => String::from("Password not found."),
|
||||
_ => code.0.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
scopeguard::defer!(delete_password("BitwardenTest", "BitwardenTest").unwrap_or({}););
|
||||
set_password("BitwardenTest", "BitwardenTest", "Random").unwrap();
|
||||
assert_eq!(
|
||||
"Random",
|
||||
get_password("BitwardenTest", "BitwardenTest").unwrap()
|
||||
);
|
||||
delete_password("BitwardenTest", "BitwardenTest").unwrap();
|
||||
|
||||
// Ensure password is deleted
|
||||
match get_password("BitwardenTest", "BitwardenTest") {
|
||||
Ok(_) => panic!("Got a result"),
|
||||
Err(e) => assert_eq!("Password not found.", e.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_password_keytar() {
|
||||
scopeguard::defer!(delete_password("BitwardenTest", "BitwardenTest").unwrap_or({}););
|
||||
keytar::set_password("BitwardenTest", "BitwardenTest", "HelloFromKeytar").unwrap();
|
||||
assert_eq!(
|
||||
"HelloFromKeytar",
|
||||
get_password_keytar("BitwardenTest", "BitwardenTest").unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_error_no_password() {
|
||||
match get_password("BitwardenTest", "BitwardenTest") {
|
||||
Ok(_) => panic!("Got a result"),
|
||||
Err(e) => assert_eq!("Password not found.", e.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
121
electron-builder.json
Normal file
@ -0,0 +1,121 @@
|
||||
{
|
||||
"extraMetadata": { "name": "bitwarden" },
|
||||
"productName": "Bitwarden",
|
||||
"appId": "com.bitwarden.desktop",
|
||||
"buildDependenciesFromSource": true,
|
||||
"copyright": "Copyright © 2015-2022 Bitwarden Inc.",
|
||||
"directories": { "buildResources": "resources", "output": "dist", "app": "build" },
|
||||
"afterSign": "scripts/after-sign.js",
|
||||
"asarUnpack": ["**/*.node"],
|
||||
"files": ["**/*", "!**/node_modules/@bitwarden/desktop-native/**/*"],
|
||||
"publish": {
|
||||
"provider": "generic",
|
||||
"url": "https://artifacts.bitwarden.com/desktop"
|
||||
},
|
||||
"mac": {
|
||||
"electronUpdaterCompatibility": ">=0.0.1",
|
||||
"category": "public.app-category.productivity",
|
||||
"darkModeSupport": true,
|
||||
"gatekeeperAssess": false,
|
||||
"hardenedRuntime": true,
|
||||
"entitlements": "resources/entitlements.mac.plist",
|
||||
"entitlementsInherit": "resources/entitlements.mac.plist",
|
||||
"extendInfo": {
|
||||
"ITSAppUsesNonExemptEncryption": false,
|
||||
"CFBundleLocalizations": [
|
||||
"en",
|
||||
"cs",
|
||||
"da",
|
||||
"de",
|
||||
"es",
|
||||
"et",
|
||||
"fi",
|
||||
"fr",
|
||||
"hr",
|
||||
"hu",
|
||||
"id",
|
||||
"it",
|
||||
"ja",
|
||||
"nb",
|
||||
"nl",
|
||||
"pl",
|
||||
"pt-BR",
|
||||
"pt-PT",
|
||||
"ro",
|
||||
"ru",
|
||||
"sk",
|
||||
"sv",
|
||||
"tr",
|
||||
"uk",
|
||||
"vi",
|
||||
"zh-Hans",
|
||||
"zh-Hant"
|
||||
],
|
||||
"CFBundleDevelopmentRegion": "en"
|
||||
},
|
||||
"target": ["dmg", "zip"]
|
||||
},
|
||||
"win": {
|
||||
"electronUpdaterCompatibility": ">=0.0.1",
|
||||
"target": ["portable", "nsis-web", "appx"],
|
||||
"sign": "./sign.js",
|
||||
"extraResources": [
|
||||
{ "from": "node_modules/regedit/vbs", "to": "regedit/vbs", "filter": ["**/*"] },
|
||||
{ "from": "resources/native-messaging.bat", "to": "native-messaging.bat" }
|
||||
]
|
||||
},
|
||||
"linux": {
|
||||
"category": "Utility",
|
||||
"synopsis": "A secure and free password manager for all of your devices.",
|
||||
"target": ["deb", "freebsd", "rpm", "AppImage", "snap"],
|
||||
"desktop": { "Name": "Bitwarden", "Type": "Application", "GenericName": "Password Manager" }
|
||||
},
|
||||
"dmg": {
|
||||
"icon": "dmg.icns",
|
||||
"contents": [
|
||||
{ "x": 150, "y": 185, "type": "file" },
|
||||
{ "x": 390, "y": 180, "type": "link", "path": "/Applications" }
|
||||
],
|
||||
"window": { "width": 540, "height": 380 }
|
||||
},
|
||||
"mas": {
|
||||
"entitlements": "resources/entitlements.mas.plist",
|
||||
"entitlementsInherit": "resources/entitlements.mas.inherit.plist",
|
||||
"hardenedRuntime": false,
|
||||
"extendInfo": { "LSMinimumSystemVersion": "10.14.0" }
|
||||
},
|
||||
"nsisWeb": {
|
||||
"oneClick": false,
|
||||
"perMachine": false,
|
||||
"allowToChangeInstallationDirectory": false,
|
||||
"artifactName": "${productName}-Installer-${version}.${ext}",
|
||||
"uninstallDisplayName": "${productName}",
|
||||
"deleteAppDataOnUninstall": true
|
||||
},
|
||||
"portable": { "artifactName": "${productName}-Portable-${version}.${ext}" },
|
||||
"appx": {
|
||||
"artifactName": "${productName}-${version}-${arch}.${ext}",
|
||||
"backgroundColor": "#175DDC",
|
||||
"applicationId": "bitwardendesktop",
|
||||
"identityName": "8bitSolutionsLLC.bitwardendesktop",
|
||||
"publisher": "CN=14D52771-DE3C-4886-B8BF-825BA7690418",
|
||||
"publisherDisplayName": "8bit Solutions LLC",
|
||||
"languages": ["en-US"]
|
||||
},
|
||||
"deb": {
|
||||
"artifactName": "${productName}-${version}-${arch}.${ext}",
|
||||
"depends": ["libnotify4", "libxtst6", "libnss3", "libsecret-1-0", "libxss1"]
|
||||
},
|
||||
"appImage": {
|
||||
"artifactName": "${productName}-${version}-${arch}.${ext}"
|
||||
},
|
||||
"rpm": { "artifactName": "${productName}-${version}-${arch}.${ext}" },
|
||||
"freebsd": { "artifactName": "${productName}-${version}-${arch}.${ext}" },
|
||||
"snap": {
|
||||
"autoStart": true,
|
||||
"confinement": "strict",
|
||||
"plugs": ["default", "password-manager-service"],
|
||||
"stagePackages": ["default"]
|
||||
},
|
||||
"protocols": [{ "name": "Bitwarden", "schemes": ["bitwarden"] }]
|
||||
}
|
2
jslib
@ -1 +1 @@
|
||||
Subproject commit 1e9c4cacce34b1c21a878bf6b5ca2c0dc3926cf8
|
||||
Subproject commit 80c834b52a8b00f88250a47a9bbd40c269fc2cba
|
6252
package-lock.json
generated
213
package.json
@ -26,8 +26,8 @@
|
||||
"symlink:win": "rm -rf ./jslib && cmd /c mklink /J .\\jslib ..\\jslib",
|
||||
"symlink:mac": "npm run symlink:lin",
|
||||
"symlink:lin": "rm -rf ./jslib && ln -s ../jslib ./jslib",
|
||||
"lint": "tslint 'src/**/*.ts' && prettier --check .",
|
||||
"lint:fix": "tslint 'src/**/*.ts' --fix",
|
||||
"lint": "eslint . && prettier --check .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
"build": "concurrently -n Main,Rend -c yellow,cyan \"npm run build:main\" \"npm run build:renderer\"",
|
||||
"build:dev": "concurrently -n Main,Rend -c yellow,cyan \"npm run build:main:dev\" \"npm run build:renderer:dev\"",
|
||||
"build:main": "cross-env NODE_ENV=production webpack --config webpack.main.js",
|
||||
@ -36,6 +36,7 @@
|
||||
"build:renderer:dev": "cross-env NODE_ENV=development webpack --config webpack.renderer.js",
|
||||
"build:renderer:watch": "cross-env NODE_ENV=development webpack --config webpack.renderer.js --watch",
|
||||
"electron": "npm run build:main:dev && concurrently -k -n Main,Rend -c yellow,cyan \"electron --inspect=5858 ./build --watch\" \"npm run build:renderer:watch\"",
|
||||
"electron:ignore": "npm run build:main:dev && concurrently -k -n Main,Rend -c yellow,cyan \"electron --inspect=5858 --ignore-certificate-errors ./build --watch\" \"npm run build:renderer:watch\"",
|
||||
"clean:dist": "rimraf ./dist/*",
|
||||
"clean:l10n": "git push origin --delete l10n_master",
|
||||
"pack:dir": "npm run clean:dist && electron-builder --dir -p never",
|
||||
@ -57,205 +58,18 @@
|
||||
"publish:mac": "npm run build && npm run clean:dist && electron-builder --mac -p always",
|
||||
"publish:mac:mas": "npm run dist:mac:mas && npm run upload:mas",
|
||||
"publish:win": "npm run build && npm run clean:dist && electron-builder --win --x64 --arm64 --ia32 -p always -c.win.certificateSubjectName=\"8bit Solutions LLC\"",
|
||||
"publish:win:dev": "npm run build && npm run clean:dist && electron-builder --win --x64 --arm64 --ia32 -p always",
|
||||
"upload:mas": "xcrun altool --upload-app --type osx --file \"$(find ./dist/mas-universal/Bitwarden*.pkg)\" --username $APPLE_ID_USERNAME --password $APPLE_ID_PASSWORD",
|
||||
"prettier": "prettier --write .",
|
||||
"prepare": "husky install"
|
||||
},
|
||||
"build": {
|
||||
"extraMetadata": {
|
||||
"name": "bitwarden"
|
||||
},
|
||||
"productName": "Bitwarden",
|
||||
"appId": "com.bitwarden.desktop",
|
||||
"buildDependenciesFromSource": true,
|
||||
"copyright": "Copyright © 2015-2022 Bitwarden Inc.",
|
||||
"directories": {
|
||||
"buildResources": "resources",
|
||||
"output": "dist",
|
||||
"app": "build"
|
||||
},
|
||||
"afterSign": "scripts/after-sign.js",
|
||||
"asarUnpack": [
|
||||
"**/*.node"
|
||||
],
|
||||
"mac": {
|
||||
"electronUpdaterCompatibility": ">=0.0.1",
|
||||
"category": "public.app-category.productivity",
|
||||
"darkModeSupport": true,
|
||||
"gatekeeperAssess": false,
|
||||
"hardenedRuntime": true,
|
||||
"entitlements": "resources/entitlements.mac.plist",
|
||||
"entitlementsInherit": "resources/entitlements.mac.plist",
|
||||
"extendInfo": {
|
||||
"ITSAppUsesNonExemptEncryption": false,
|
||||
"CFBundleLocalizations": [
|
||||
"en",
|
||||
"cs",
|
||||
"da",
|
||||
"de",
|
||||
"es",
|
||||
"et",
|
||||
"fi",
|
||||
"fr",
|
||||
"hr",
|
||||
"hu",
|
||||
"id",
|
||||
"it",
|
||||
"ja",
|
||||
"nb",
|
||||
"nl",
|
||||
"pl",
|
||||
"pt-BR",
|
||||
"pt-PT",
|
||||
"ro",
|
||||
"ru",
|
||||
"sk",
|
||||
"sv",
|
||||
"tr",
|
||||
"uk",
|
||||
"vi",
|
||||
"zh-Hans",
|
||||
"zh-Hant"
|
||||
],
|
||||
"CFBundleDevelopmentRegion": "en"
|
||||
},
|
||||
"target": [
|
||||
"dmg",
|
||||
"zip"
|
||||
]
|
||||
},
|
||||
"win": {
|
||||
"electronUpdaterCompatibility": ">=0.0.1",
|
||||
"target": [
|
||||
"portable",
|
||||
"nsis-web",
|
||||
"appx"
|
||||
],
|
||||
"sign": "./sign.js",
|
||||
"extraResources": [
|
||||
{
|
||||
"from": "node_modules/regedit/vbs",
|
||||
"to": "regedit/vbs",
|
||||
"filter": [
|
||||
"**/*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"from": "resources/native-messaging.bat",
|
||||
"to": "native-messaging.bat"
|
||||
}
|
||||
]
|
||||
},
|
||||
"linux": {
|
||||
"category": "Utility",
|
||||
"synopsis": "A secure and free password manager for all of your devices.",
|
||||
"target": [
|
||||
"deb",
|
||||
"freebsd",
|
||||
"rpm",
|
||||
"AppImage",
|
||||
"snap"
|
||||
],
|
||||
"desktop": {
|
||||
"Name": "Bitwarden",
|
||||
"Type": "Application",
|
||||
"GenericName": "Password Manager"
|
||||
}
|
||||
},
|
||||
"dmg": {
|
||||
"icon": "dmg.icns",
|
||||
"contents": [
|
||||
{
|
||||
"x": 150,
|
||||
"y": 185,
|
||||
"type": "file"
|
||||
},
|
||||
{
|
||||
"x": 390,
|
||||
"y": 180,
|
||||
"type": "link",
|
||||
"path": "/Applications"
|
||||
}
|
||||
],
|
||||
"window": {
|
||||
"width": 540,
|
||||
"height": 380
|
||||
}
|
||||
},
|
||||
"mas": {
|
||||
"entitlements": "resources/entitlements.mas.plist",
|
||||
"entitlementsInherit": "resources/entitlements.mas.inherit.plist",
|
||||
"hardenedRuntime": false
|
||||
},
|
||||
"nsisWeb": {
|
||||
"oneClick": false,
|
||||
"perMachine": true,
|
||||
"allowToChangeInstallationDirectory": true,
|
||||
"artifactName": "${productName}-Installer-${version}.${ext}",
|
||||
"uninstallDisplayName": "${productName}",
|
||||
"deleteAppDataOnUninstall": true
|
||||
},
|
||||
"portable": {
|
||||
"artifactName": "${productName}-Portable-${version}.${ext}"
|
||||
},
|
||||
"appx": {
|
||||
"artifactName": "${productName}-${version}-${arch}.${ext}",
|
||||
"backgroundColor": "#175DDC",
|
||||
"applicationId": "bitwardendesktop",
|
||||
"identityName": "8bitSolutionsLLC.bitwardendesktop",
|
||||
"publisher": "CN=14D52771-DE3C-4886-B8BF-825BA7690418",
|
||||
"publisherDisplayName": "8bit Solutions LLC",
|
||||
"languages": [
|
||||
"en-US"
|
||||
]
|
||||
},
|
||||
"deb": {
|
||||
"artifactName": "${productName}-${version}-${arch}.${ext}",
|
||||
"depends": [
|
||||
"libnotify4",
|
||||
"libxtst6",
|
||||
"libnss3",
|
||||
"libsecret-1-0",
|
||||
"libxss1"
|
||||
]
|
||||
},
|
||||
"appImage": {
|
||||
"artifactName": "${productName}-${version}-${arch}.${ext}"
|
||||
},
|
||||
"rpm": {
|
||||
"artifactName": "${productName}-${version}-${arch}.${ext}"
|
||||
},
|
||||
"freebsd": {
|
||||
"artifactName": "${productName}-${version}-${arch}.${ext}"
|
||||
},
|
||||
"snap": {
|
||||
"autoStart": true,
|
||||
"confinement": "strict",
|
||||
"plugs": [
|
||||
"default",
|
||||
"password-manager-service"
|
||||
],
|
||||
"stagePackages": [
|
||||
"default"
|
||||
],
|
||||
"publish": [
|
||||
"github"
|
||||
]
|
||||
},
|
||||
"protocols": [
|
||||
{
|
||||
"name": "Bitwarden",
|
||||
"schemes": [
|
||||
"bitwarden"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular/compiler-cli": "^12.2.13",
|
||||
"@ngtools/webpack": "^12.2.13",
|
||||
"@types/node": "^16.11.12",
|
||||
"@types/node-ipc": "^9.1.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.12.1",
|
||||
"@typescript-eslint/parser": "^5.12.1",
|
||||
"clean-webpack-plugin": "^4.0.0",
|
||||
"concurrently": "^6.0.2",
|
||||
"copy-webpack-plugin": "^10.0.0",
|
||||
@ -265,6 +79,10 @@
|
||||
"electron-notarize": "^1.1.1",
|
||||
"electron-rebuild": "^3.2.5",
|
||||
"electron-reload": "^1.5.0",
|
||||
"eslint": "^8.9.0",
|
||||
"eslint-config-prettier": "^8.4.0",
|
||||
"eslint-import-resolver-typescript": "^2.5.0",
|
||||
"eslint-plugin-import": "^2.25.4",
|
||||
"html-loader": "^3.0.1",
|
||||
"html-webpack-plugin": "^5.5.0",
|
||||
"husky": "^7.0.4",
|
||||
@ -278,8 +96,6 @@
|
||||
"tapable": "^1.1.3",
|
||||
"ts-loader": "^9.2.5",
|
||||
"tsconfig-paths-webpack-plugin": "^3.5.1",
|
||||
"tslint": "~6.1.0",
|
||||
"tslint-loader": "^3.5.4",
|
||||
"typescript": "4.3.5",
|
||||
"webpack": "^5.64.4",
|
||||
"webpack-cli": "^4.9.1",
|
||||
@ -298,18 +114,23 @@
|
||||
"@bitwarden/jslib-angular": "file:jslib/angular",
|
||||
"@bitwarden/jslib-common": "file:jslib/common",
|
||||
"@bitwarden/jslib-electron": "file:jslib/electron",
|
||||
"@nodert-win10-rs4/windows.security.credentials.ui": "^0.4.4",
|
||||
"forcefocus": "^1.1.0",
|
||||
"keytar": "^7.9.0",
|
||||
"ngx-toastr": "14.1.4",
|
||||
"node-ipc": "^9.1.4",
|
||||
"nord": "^0.2.1",
|
||||
"regedit": "^3.0.3",
|
||||
"rxjs": "^7.4.0",
|
||||
"sweetalert2": "^10.16.6"
|
||||
"sweetalert2": "^10.16.6",
|
||||
"zone.js": "0.11.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "~16",
|
||||
"npm": "~8"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*": "prettier --ignore-unknown --write"
|
||||
"./!(jslib)**": "prettier --ignore-unknown --write",
|
||||
"*.ts": "eslint --fix"
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.disable-library-validation</key>
|
||||
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 717 B After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 345 KiB After Width: | Height: | Size: 252 KiB |
BIN
resources/icon.iconset/icon_64x64.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
resources/icon.iconset/icon_64x64@2x.png
Normal file
After Width: | Height: | Size: 9.4 KiB |
BIN
resources/icons/1024x1024.png
Normal file
After Width: | Height: | Size: 252 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 326 B After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 510 B After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 707 B |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.2 KiB |
@ -1,8 +1,10 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires, no-console */
|
||||
require("dotenv").config();
|
||||
const path = require("path");
|
||||
const fse = require("fs-extra");
|
||||
const { notarize } = require("electron-notarize");
|
||||
|
||||
const { deepAssign } = require("builder-util");
|
||||
const { notarize } = require("electron-notarize");
|
||||
const fse = require("fs-extra");
|
||||
|
||||
exports.default = run;
|
||||
|
||||
|
1
scripts/dev/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
data
|
19
scripts/dev/docker-compose.yml
Normal file
@ -0,0 +1,19 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
minio:
|
||||
image: minio/minio
|
||||
command: server /data --console-address ":9001"
|
||||
ports:
|
||||
- "9000:9000"
|
||||
- "9001:9001"
|
||||
# environment:
|
||||
# MINIO_ROOT_USER: minioadmin
|
||||
# MINIO_ROOT_PASSWORD: minioadmin
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
|
||||
interval: 30s
|
||||
timeout: 20s
|
||||
retries: 3
|
||||
volumes:
|
||||
- ./data:/data
|
2
sign.js
@ -1,3 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires, no-console */
|
||||
|
||||
exports.default = async function (configuration) {
|
||||
if (parseInt(process.env.ELECTRON_BUILDER_SIGN) === 1 && configuration.path.slice(-4) == ".exe") {
|
||||
console.log(`[*] Signing file: ${configuration.path}`);
|
||||
|
@ -25,11 +25,7 @@
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-header">
|
||||
<button
|
||||
type="button"
|
||||
(click)="toggleCustom()"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
>
|
||||
<button type="button" (click)="toggleCustom()" [attr.aria-expanded]="showCustom">
|
||||
<i class="bwi bwi-plus-square" [hidden]="showCustom" aria-hidden="true"></i>
|
||||
<i class="bwi bwi-minus-square" [hidden]="!showCustom" aria-hidden="true"></i>
|
||||
{{ "customEnvironment" | i18n }}
|
||||
@ -87,7 +83,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button appBlurClick type="submit" class="primary" appA11yTitle="{{ 'save' | i18n }}">
|
||||
<button type="submit" class="primary" appA11yTitle="{{ 'save' | i18n }}">
|
||||
<i class="bwi bwi-save-changes bwi-lg bwi-fw" aria-hidden="true"></i>
|
||||
</button>
|
||||
<button type="button" data-dismiss="modal">{{ "close" | i18n }}</button>
|
||||
|
@ -1,11 +1,10 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { EnvironmentComponent as BaseEnvironmentComponent } from "jslib-angular/components/environment.component";
|
||||
import { EnvironmentService } from "jslib-common/abstractions/environment.service";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
|
||||
import { EnvironmentComponent as BaseEnvironmentComponent } from "jslib-angular/components/environment.component";
|
||||
|
||||
@Component({
|
||||
selector: "app-environment",
|
||||
templateUrl: "environment.component.html",
|
||||
|
@ -21,11 +21,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button type="submit" class="btn primary block" [disabled]="form.loading" appBlurClick>
|
||||
<button type="submit" class="btn primary block" [disabled]="form.loading">
|
||||
<b [hidden]="form.loading">{{ "submit" | i18n }}</b>
|
||||
<i class="bwi bwi-spinner bwi-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
</button>
|
||||
<a routerLink="/login" class="btn block">{{ "cancel" | i18n }}</a>
|
||||
<button type="button" routerLink="/login" class="btn block">{{ "cancel" | i18n }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -1,13 +1,12 @@
|
||||
import { Component } from "@angular/core";
|
||||
import { Router } from "@angular/router";
|
||||
|
||||
import { HintComponent as BaseHintComponent } from "jslib-angular/components/hint.component";
|
||||
import { ApiService } from "jslib-common/abstractions/api.service";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { LogService } from "jslib-common/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
|
||||
import { HintComponent as BaseHintComponent } from "jslib-angular/components/hint.component";
|
||||
|
||||
@Component({
|
||||
selector: "app-hint",
|
||||
templateUrl: "hint.component.html",
|
||||
|
@ -30,13 +30,12 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
(click)="togglePassword()"
|
||||
>
|
||||
<i
|
||||
@ -44,7 +43,7 @@
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -58,17 +57,16 @@
|
||||
type="button"
|
||||
class="btn block"
|
||||
[ngClass]="{ 'primary font-weight-bold': hideInput }"
|
||||
appBlurClick
|
||||
(click)="unlockBiometric()"
|
||||
>
|
||||
{{ biometricText | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="buttons-row">
|
||||
<button type="submit" class="btn primary block" appBlurClick *ngIf="!hideInput">
|
||||
<button type="submit" class="btn primary block" *ngIf="!hideInput">
|
||||
<i class="bwi bwi-unlock" aria-hidden="true"></i> <b>{{ "unlock" | i18n }}</b>
|
||||
</button>
|
||||
<button type="button" class="btn block" appBlurClick (click)="logOut()">
|
||||
<button type="button" class="btn block" (click)="logOut()">
|
||||
{{ "logOut" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
|
@ -2,6 +2,7 @@ import { Component, NgZone, OnDestroy } from "@angular/core";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { ipcRenderer } from "electron";
|
||||
|
||||
import { LockComponent as BaseLockComponent } from "jslib-angular/components/lock.component";
|
||||
import { ApiService } from "jslib-common/abstractions/api.service";
|
||||
import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service";
|
||||
import { CryptoService } from "jslib-common/abstractions/crypto.service";
|
||||
@ -14,8 +15,6 @@ import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.se
|
||||
import { StateService } from "jslib-common/abstractions/state.service";
|
||||
import { VaultTimeoutService } from "jslib-common/abstractions/vaultTimeout.service";
|
||||
|
||||
import { LockComponent as BaseLockComponent } from "jslib-angular/components/lock.component";
|
||||
|
||||
const BroadcasterSubscriptionId = "LockComponent";
|
||||
|
||||
@Component({
|
||||
|
@ -1,7 +1,7 @@
|
||||
<div id="login-page">
|
||||
<div class="login-header">
|
||||
<a
|
||||
href="#"
|
||||
<button
|
||||
type="button"
|
||||
appStopClick
|
||||
(click)="settings()"
|
||||
class="environment-urls-settings-icon"
|
||||
@ -9,7 +9,7 @@
|
||||
>
|
||||
<i class="bwi bwi-cog bwi-lg" aria-hidden="true"></i>
|
||||
{{ "settings" | i18n }}
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
<form
|
||||
id="login-page"
|
||||
@ -48,13 +48,12 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
(click)="togglePassword()"
|
||||
>
|
||||
<i
|
||||
@ -62,35 +61,42 @@
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content-row" [hidden]="!showCaptcha()">
|
||||
</div>
|
||||
</div>
|
||||
<div class="box last" [hidden]="!showCaptcha()">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row">
|
||||
<iframe id="hcaptcha_iframe" height="80"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="buttons with-rows">
|
||||
<div class="buttons-row">
|
||||
<button type="submit" class="btn primary block" [disabled]="form.loading" appBlurClick>
|
||||
<button type="submit" class="btn primary block" [disabled]="form.loading">
|
||||
<b [hidden]="form.loading"
|
||||
><i class="bwi bwi-sign-in" aria-hidden="true"></i> {{ "logIn" | i18n }}</b
|
||||
>
|
||||
<i class="bwi bwi-spinner bwi-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
</button>
|
||||
<a routerLink="/register" class="btn block">
|
||||
<button type="button" routerLink="/register" class="btn block">
|
||||
<i class="bwi bwi-pencil-square" aria-hidden="true"></i> {{ "createAccount" | i18n }}
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
<div class="buttons-row">
|
||||
<a (click)="launchSsoBrowser('desktop', 'bitwarden://sso-callback')" class="btn block">
|
||||
<button
|
||||
type="button"
|
||||
(click)="launchSsoBrowser('desktop', 'bitwarden://sso-callback')"
|
||||
class="btn block"
|
||||
>
|
||||
<i class="bwi bwi-bank" aria-hidden="true"></i> {{ "enterpriseSingleSignOn" | i18n }}
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sub-options">
|
||||
<a routerLink="/hint">{{ "getMasterPasswordHint" | i18n }}</a>
|
||||
<button type="button" routerLink="/hint">{{ "getMasterPasswordHint" | i18n }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { Component, NgZone, OnDestroy, ViewChild, ViewContainerRef } from "@angular/core";
|
||||
|
||||
import { Router } from "@angular/router";
|
||||
|
||||
import { EnvironmentComponent } from "./environment.component";
|
||||
|
||||
import { LoginComponent as BaseLoginComponent } from "jslib-angular/components/login.component";
|
||||
import { ModalService } from "jslib-angular/services/modal.service";
|
||||
import { AuthService } from "jslib-common/abstractions/auth.service";
|
||||
import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service";
|
||||
import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service";
|
||||
@ -16,9 +15,7 @@ import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.se
|
||||
import { StateService } from "jslib-common/abstractions/state.service";
|
||||
import { SyncService } from "jslib-common/abstractions/sync.service";
|
||||
|
||||
import { ModalService } from "jslib-angular/services/modal.service";
|
||||
|
||||
import { LoginComponent as BaseLoginComponent } from "jslib-angular/components/login.component";
|
||||
import { EnvironmentComponent } from "./environment.component";
|
||||
|
||||
const BroadcasterSubscriptionId = "LoginComponent";
|
||||
|
||||
@ -32,7 +29,7 @@ export class LoginComponent extends BaseLoginComponent implements OnDestroy {
|
||||
|
||||
showingModal = false;
|
||||
|
||||
protected alwaysRememberEmail: boolean = true;
|
||||
protected alwaysRememberEmail = true;
|
||||
|
||||
private deferFocus: boolean = null;
|
||||
|
||||
|
@ -48,14 +48,13 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="primary" appBlurClick (click)="manage()" *ngIf="isPremium">
|
||||
<button type="button" class="primary" (click)="manage()" *ngIf="isPremium">
|
||||
<b>{{ "premiumManage" | i18n }}</b>
|
||||
</button>
|
||||
<button
|
||||
#purchaseBtn
|
||||
type="button"
|
||||
class="primary"
|
||||
appBlurClick
|
||||
(click)="purchase()"
|
||||
*ngIf="!isPremium"
|
||||
[disabled]="purchaseBtn.loading"
|
||||
@ -67,7 +66,6 @@
|
||||
<button
|
||||
#refreshBtn
|
||||
type="button"
|
||||
appBlurClick
|
||||
(click)="refresh()"
|
||||
[disabled]="refreshBtn.loading"
|
||||
appA11yTitle="{{ 'premiumRefresh' | i18n }}"
|
||||
|
@ -1,13 +1,12 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { PremiumComponent as BasePremiumComponent } from "jslib-angular/components/premium.component";
|
||||
import { ApiService } from "jslib-common/abstractions/api.service";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { LogService } from "jslib-common/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
import { StateService } from "jslib-common/abstractions/state.service";
|
||||
|
||||
import { PremiumComponent as BasePremiumComponent } from "jslib-angular/components/premium.component";
|
||||
|
||||
@Component({
|
||||
selector: "app-premium",
|
||||
templateUrl: "premium.component.html",
|
||||
|
@ -40,13 +40,12 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
(click)="togglePassword(false)"
|
||||
>
|
||||
<i
|
||||
@ -54,7 +53,7 @@
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
@ -90,13 +89,12 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
(click)="togglePassword(true)"
|
||||
>
|
||||
<i
|
||||
@ -104,7 +102,7 @@
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
@ -140,11 +138,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button type="submit" class="btn primary block" [disabled]="form.loading" appBlurClick>
|
||||
<button type="submit" class="btn primary block" [disabled]="form.loading">
|
||||
<b [hidden]="form.loading">{{ "submit" | i18n }}</b>
|
||||
<i class="bwi bwi-spinner bwi-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
</button>
|
||||
<a routerLink="/login" class="btn block">{{ "cancel" | i18n }}</a>
|
||||
<button type="button" routerLink="/login" class="btn block">{{ "cancel" | i18n }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Component, NgZone, OnDestroy, OnInit } from "@angular/core";
|
||||
import { Router } from "@angular/router";
|
||||
|
||||
import { RegisterComponent as BaseRegisterComponent } from "jslib-angular/components/register.component";
|
||||
import { ApiService } from "jslib-common/abstractions/api.service";
|
||||
import { AuthService } from "jslib-common/abstractions/auth.service";
|
||||
import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service";
|
||||
@ -12,8 +13,6 @@ import { PasswordGenerationService } from "jslib-common/abstractions/passwordGen
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
import { StateService } from "jslib-common/abstractions/state.service";
|
||||
|
||||
import { RegisterComponent as BaseRegisterComponent } from "jslib-angular/components/register.component";
|
||||
|
||||
const BroadcasterSubscriptionId = "RegisterComponent";
|
||||
|
||||
@Component({
|
||||
|
@ -7,7 +7,6 @@
|
||||
type="submit"
|
||||
class="btn primary block"
|
||||
[disabled]="actionPromise"
|
||||
appBlurClick
|
||||
(click)="convert()"
|
||||
>
|
||||
<b [hidden]="continuing">{{ "removeMasterPassword" | i18n }}</b>
|
||||
@ -17,7 +16,6 @@
|
||||
type="button"
|
||||
class="btn secondary block"
|
||||
[disabled]="actionPromise"
|
||||
appBlurClick
|
||||
(click)="leave()"
|
||||
>
|
||||
<b [hidden]="leaving">{{ "leaveOrganization" | i18n }}</b>
|
||||
|
@ -56,13 +56,12 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
(click)="togglePassword(false)"
|
||||
>
|
||||
<i
|
||||
@ -70,7 +69,7 @@
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
@ -108,13 +107,12 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
(click)="togglePassword(true)"
|
||||
>
|
||||
<i
|
||||
@ -122,7 +120,7 @@
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Component, NgZone, OnDestroy } from "@angular/core";
|
||||
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
|
||||
import { SetPasswordComponent as BaseSetPasswordComponent } from "jslib-angular/components/set-password.component";
|
||||
import { ApiService } from "jslib-common/abstractions/api.service";
|
||||
import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service";
|
||||
import { CryptoService } from "jslib-common/abstractions/crypto.service";
|
||||
@ -15,8 +15,6 @@ import { SyncService } from "jslib-common/abstractions/sync.service";
|
||||
|
||||
const BroadcasterSubscriptionId = "SetPasswordComponent";
|
||||
|
||||
import { SetPasswordComponent as BaseSetPasswordComponent } from "jslib-angular/components/set-password.component";
|
||||
|
||||
@Component({
|
||||
selector: "app-set-password",
|
||||
templateUrl: "set-password.component.html",
|
||||
|
@ -3,7 +3,9 @@
|
||||
<div class="modal-content">
|
||||
<div class="modal-body form">
|
||||
<div class="box">
|
||||
<label class="settingsTitle">{{ "settingsTitle" | i18n: currentUserEmail }} </label>
|
||||
<div class="box-header">
|
||||
{{ "settingsTitle" | i18n: currentUserEmail }}
|
||||
</div>
|
||||
<div class="box-content box-content-padded">
|
||||
<h2>
|
||||
<button
|
||||
|
@ -2,24 +2,20 @@ import { Component, OnInit } from "@angular/core";
|
||||
import { FormControl } from "@angular/forms";
|
||||
import { debounceTime } from "rxjs/operators";
|
||||
|
||||
import { DeviceType } from "jslib-common/enums/deviceType";
|
||||
import { ThemeType } from "jslib-common/enums/themeType";
|
||||
|
||||
import { ModalService } from "jslib-angular/services/modal.service";
|
||||
import { CryptoService } from "jslib-common/abstractions/crypto.service";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { MessagingService } from "jslib-common/abstractions/messaging.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
import { StateService } from "jslib-common/abstractions/state.service";
|
||||
import { VaultTimeoutService } from "jslib-common/abstractions/vaultTimeout.service";
|
||||
|
||||
import { ModalService } from "jslib-angular/services/modal.service";
|
||||
|
||||
import { SetPinComponent } from "../components/set-pin.component";
|
||||
|
||||
import { DeviceType } from "jslib-common/enums/deviceType";
|
||||
import { StorageLocation } from "jslib-common/enums/storageLocation";
|
||||
import { ThemeType } from "jslib-common/enums/themeType";
|
||||
import { Utils } from "jslib-common/misc/utils";
|
||||
import { isWindowsStore } from "jslib-electron/utils";
|
||||
|
||||
import { StorageLocation } from "jslib-common/enums/storageLocation";
|
||||
import { SetPinComponent } from "../components/set-pin.component";
|
||||
|
||||
@Component({
|
||||
selector: "app-settings",
|
||||
@ -28,15 +24,15 @@ import { StorageLocation } from "jslib-common/enums/storageLocation";
|
||||
export class SettingsComponent implements OnInit {
|
||||
vaultTimeoutAction: string;
|
||||
pin: boolean = null;
|
||||
disableFavicons: boolean = false;
|
||||
enableBrowserIntegration: boolean = false;
|
||||
enableBrowserIntegrationFingerprint: boolean = false;
|
||||
enableMinToTray: boolean = false;
|
||||
enableCloseToTray: boolean = false;
|
||||
enableTray: boolean = false;
|
||||
showMinToTray: boolean = false;
|
||||
startToTray: boolean = false;
|
||||
minimizeOnCopyToClipboard: boolean = false;
|
||||
disableFavicons = false;
|
||||
enableBrowserIntegration = false;
|
||||
enableBrowserIntegrationFingerprint = false;
|
||||
enableMinToTray = false;
|
||||
enableCloseToTray = false;
|
||||
enableTray = false;
|
||||
showMinToTray = false;
|
||||
startToTray = false;
|
||||
minimizeOnCopyToClipboard = false;
|
||||
locale: string;
|
||||
vaultTimeouts: any[];
|
||||
localeOptions: any[];
|
||||
@ -50,9 +46,9 @@ export class SettingsComponent implements OnInit {
|
||||
noAutoPromptBiometrics: boolean;
|
||||
noAutoPromptBiometricsText: string;
|
||||
alwaysShowDock: boolean;
|
||||
showAlwaysShowDock: boolean = false;
|
||||
showAlwaysShowDock = false;
|
||||
openAtLogin: boolean;
|
||||
requireEnableTray: boolean = false;
|
||||
requireEnableTray = false;
|
||||
|
||||
enableTrayText: string;
|
||||
enableTrayDescText: string;
|
||||
@ -65,9 +61,9 @@ export class SettingsComponent implements OnInit {
|
||||
|
||||
vaultTimeout: FormControl = new FormControl(null);
|
||||
|
||||
showSecurity: boolean = true;
|
||||
showAccountPreferences: boolean = true;
|
||||
showAppPreferences: boolean = true;
|
||||
showSecurity = true;
|
||||
showAccountPreferences = true;
|
||||
showAppPreferences = true;
|
||||
|
||||
currentUserEmail: string;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
|
||||
import { SsoComponent as BaseSsoComponent } from "jslib-angular/components/sso.component";
|
||||
import { ApiService } from "jslib-common/abstractions/api.service";
|
||||
import { AuthService } from "jslib-common/abstractions/auth.service";
|
||||
import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service";
|
||||
@ -13,8 +13,6 @@ import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.se
|
||||
import { StateService } from "jslib-common/abstractions/state.service";
|
||||
import { SyncService } from "jslib-common/abstractions/sync.service";
|
||||
|
||||
import { SsoComponent as BaseSsoComponent } from "jslib-angular/components/sso.component";
|
||||
|
||||
@Component({
|
||||
selector: "app-sso",
|
||||
templateUrl: "sso.component.html",
|
||||
|
@ -7,8 +7,8 @@
|
||||
{{ "twoStepOptions" | i18n }}
|
||||
</div>
|
||||
<div class="box-content">
|
||||
<a
|
||||
href="#"
|
||||
<button
|
||||
type="button"
|
||||
appStopClick
|
||||
*ngFor="let p of providers"
|
||||
class="box-content-row"
|
||||
@ -17,11 +17,11 @@
|
||||
<img [src]="'images/two-factor/' + p.type + '.png'" alt="" class="img-right" />
|
||||
<span class="text">{{ p.name }}</span>
|
||||
<span class="detail">{{ p.description }}</span>
|
||||
</a>
|
||||
<a href="#" appStopClick class="box-content-row" (click)="recover()">
|
||||
</button>
|
||||
<button type="button" appStopClick class="box-content-row" (click)="recover()">
|
||||
<span class="text">{{ "recoveryCodeTitle" | i18n }}</span>
|
||||
<span class="detail">{{ "recoveryCodeDesc" | i18n }}</span>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,11 +1,10 @@
|
||||
import { Component } from "@angular/core";
|
||||
import { Router } from "@angular/router";
|
||||
|
||||
import { AuthService } from "jslib-common/abstractions/auth.service";
|
||||
import { TwoFactorOptionsComponent as BaseTwoFactorOptionsComponent } from "jslib-angular/components/two-factor-options.component";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
|
||||
import { TwoFactorOptionsComponent as BaseTwoFactorOptionsComponent } from "jslib-angular/components/two-factor-options.component";
|
||||
import { TwoFactorService } from "jslib-common/abstractions/twoFactor.service";
|
||||
|
||||
@Component({
|
||||
selector: "app-two-factor-options",
|
||||
@ -13,11 +12,11 @@ import { TwoFactorOptionsComponent as BaseTwoFactorOptionsComponent } from "jsli
|
||||
})
|
||||
export class TwoFactorOptionsComponent extends BaseTwoFactorOptionsComponent {
|
||||
constructor(
|
||||
authService: AuthService,
|
||||
twoFactorService: TwoFactorService,
|
||||
router: Router,
|
||||
i18nService: I18nService,
|
||||
platformUtilsService: PlatformUtilsService
|
||||
) {
|
||||
super(authService, router, i18nService, platformUtilsService, window);
|
||||
super(twoFactorService, router, i18nService, platformUtilsService, window);
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
[appApiAction]="formPromise"
|
||||
attr.aria-hidden="{{ showingModal }}"
|
||||
>
|
||||
<div class="content">
|
||||
<div id="content" class="content">
|
||||
<h1>{{ title }}</h1>
|
||||
<p *ngIf="selectedProviderType === providerType.Authenticator">
|
||||
{{ "enterVerificationCodeApp" | i18n }}
|
||||
@ -100,12 +100,18 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box last" [hidden]="!showCaptcha()">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row">
|
||||
<iframe id="hcaptcha_iframe" height="80"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button
|
||||
type="submit"
|
||||
class="btn primary block"
|
||||
[disabled]="form.loading"
|
||||
appBlurClick
|
||||
*ngIf="
|
||||
selectedProviderType != null &&
|
||||
selectedProviderType !== providerType.Duo &&
|
||||
@ -117,22 +123,21 @@
|
||||
>
|
||||
<i class="bwi bwi-spinner bwi-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
</button>
|
||||
<a routerLink="/login" class="btn block">{{ "cancel" | i18n }}</a>
|
||||
<button type="button" routerLink="/login" class="btn block">{{ "cancel" | i18n }}</button>
|
||||
</div>
|
||||
<div class="sub-options">
|
||||
<a href="#" appStopClick (click)="anotherMethod()" role="button">{{
|
||||
"useAnotherTwoStepMethod" | i18n
|
||||
}}</a>
|
||||
<a
|
||||
href="#"
|
||||
<button type="button" appStopClick (click)="anotherMethod()">
|
||||
{{ "useAnotherTwoStepMethod" | i18n }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
appStopClick
|
||||
(click)="sendEmail(true)"
|
||||
[appApiAction]="emailPromise"
|
||||
role="button"
|
||||
*ngIf="selectedProviderType === providerType.Email"
|
||||
>
|
||||
{{ "sendVerificationCodeEmailAgain" | i18n }}
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -1,12 +1,10 @@
|
||||
import { Component, ViewChild, ViewContainerRef } from "@angular/core";
|
||||
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
|
||||
import { TwoFactorOptionsComponent } from "./two-factor-options.component";
|
||||
|
||||
import { TwoFactorProviderType } from "jslib-common/enums/twoFactorProviderType";
|
||||
|
||||
import { TwoFactorComponent as BaseTwoFactorComponent } from "jslib-angular/components/two-factor.component";
|
||||
import { ModalService } from "jslib-angular/services/modal.service";
|
||||
import { ApiService } from "jslib-common/abstractions/api.service";
|
||||
import { AppIdService } from "jslib-common/abstractions/appId.service";
|
||||
import { AuthService } from "jslib-common/abstractions/auth.service";
|
||||
import { EnvironmentService } from "jslib-common/abstractions/environment.service";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
@ -14,10 +12,10 @@ import { LogService } from "jslib-common/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
import { StateService } from "jslib-common/abstractions/state.service";
|
||||
import { SyncService } from "jslib-common/abstractions/sync.service";
|
||||
import { TwoFactorService } from "jslib-common/abstractions/twoFactor.service";
|
||||
import { TwoFactorProviderType } from "jslib-common/enums/twoFactorProviderType";
|
||||
|
||||
import { ModalService } from "jslib-angular/services/modal.service";
|
||||
|
||||
import { TwoFactorComponent as BaseTwoFactorComponent } from "jslib-angular/components/two-factor.component";
|
||||
import { TwoFactorOptionsComponent } from "./two-factor-options.component";
|
||||
|
||||
@Component({
|
||||
selector: "app-two-factor",
|
||||
@ -40,7 +38,9 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
|
||||
private modalService: ModalService,
|
||||
stateService: StateService,
|
||||
route: ActivatedRoute,
|
||||
logService: LogService
|
||||
logService: LogService,
|
||||
twoFactorService: TwoFactorService,
|
||||
appIdService: AppIdService
|
||||
) {
|
||||
super(
|
||||
authService,
|
||||
@ -52,7 +52,9 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
|
||||
environmentService,
|
||||
stateService,
|
||||
route,
|
||||
logService
|
||||
logService,
|
||||
twoFactorService,
|
||||
appIdService
|
||||
);
|
||||
super.onSuccessfulLogin = () => {
|
||||
return syncService.fullSync(true);
|
||||
@ -81,4 +83,12 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
|
||||
modal.close();
|
||||
});
|
||||
}
|
||||
|
||||
async submit() {
|
||||
await super.submit();
|
||||
if (this.captchaSiteKey) {
|
||||
const content = document.getElementById("content") as HTMLDivElement;
|
||||
content.setAttribute("style", "width:335px");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,13 +36,12 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
(click)="togglePassword(false)"
|
||||
>
|
||||
<i
|
||||
@ -50,7 +49,7 @@
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
@ -83,13 +82,12 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
(click)="togglePassword(true)"
|
||||
>
|
||||
<i
|
||||
@ -97,7 +95,7 @@
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -114,11 +112,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button type="submit" class="btn primary block" [disabled]="form.loading" appBlurClick>
|
||||
<button type="submit" class="btn primary block" [disabled]="form.loading">
|
||||
<b [hidden]="form.loading">{{ "submit" | i18n }}</b>
|
||||
<i class="bwi bwi-spinner bwi-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
</button>
|
||||
<a (click)="logOut()" class="btn block">{{ "logOut" | i18n }}</a>
|
||||
<button type="button" (click)="logOut()" class="btn block">{{ "logOut" | i18n }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { UpdateTempPasswordComponent as BaseUpdateTempPasswordComponent } from "jslib-angular/components/update-temp-password.component";
|
||||
import { ApiService } from "jslib-common/abstractions/api.service";
|
||||
import { CryptoService } from "jslib-common/abstractions/crypto.service";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
@ -11,8 +12,6 @@ import { PolicyService } from "jslib-common/abstractions/policy.service";
|
||||
import { StateService } from "jslib-common/abstractions/state.service";
|
||||
import { SyncService } from "jslib-common/abstractions/sync.service";
|
||||
|
||||
import { UpdateTempPasswordComponent as BaseUpdateTempPasswordComponent } from "jslib-angular/components/update-temp-password.component";
|
||||
|
||||
interface MasterPasswordScore {
|
||||
Color: string;
|
||||
Text: string;
|
||||
|
@ -3,6 +3,7 @@ import { RouterModule, Routes } from "@angular/router";
|
||||
|
||||
import { AuthGuardService } from "jslib-angular/services/auth-guard.service";
|
||||
import { LockGuardService } from "jslib-angular/services/lock-guard.service";
|
||||
|
||||
import { LoginGuardService } from "../services/loginGuard.service";
|
||||
|
||||
import { HintComponent } from "./accounts/hint.component";
|
||||
@ -14,9 +15,7 @@ import { SetPasswordComponent } from "./accounts/set-password.component";
|
||||
import { SsoComponent } from "./accounts/sso.component";
|
||||
import { TwoFactorComponent } from "./accounts/two-factor.component";
|
||||
import { UpdateTempPasswordComponent } from "./accounts/update-temp-password.component";
|
||||
|
||||
import { SendComponent } from "./send/send.component";
|
||||
|
||||
import { VaultComponent } from "./vault/vault.component";
|
||||
|
||||
const routes: Routes = [
|
||||
|
@ -11,10 +11,8 @@ import { DomSanitizer } from "@angular/platform-browser";
|
||||
import { Router } from "@angular/router";
|
||||
import { IndividualConfig, ToastrService } from "ngx-toastr";
|
||||
|
||||
import { PremiumComponent } from "./accounts/premium.component";
|
||||
import { SettingsComponent } from "./accounts/settings.component";
|
||||
import { PasswordGeneratorHistoryComponent } from "./vault/password-generator-history.component";
|
||||
|
||||
import { ModalRef } from "jslib-angular/components/modal/modal.ref";
|
||||
import { ModalService } from "jslib-angular/services/modal.service";
|
||||
import { AuthService } from "jslib-common/abstractions/auth.service";
|
||||
import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service";
|
||||
import { CipherService } from "jslib-common/abstractions/cipher.service";
|
||||
@ -37,17 +35,17 @@ import { SyncService } from "jslib-common/abstractions/sync.service";
|
||||
import { SystemService } from "jslib-common/abstractions/system.service";
|
||||
import { TokenService } from "jslib-common/abstractions/token.service";
|
||||
import { VaultTimeoutService } from "jslib-common/abstractions/vaultTimeout.service";
|
||||
|
||||
import { AuthenticationStatus } from "jslib-common/enums/authenticationStatus";
|
||||
import { CipherType } from "jslib-common/enums/cipherType";
|
||||
|
||||
import { MenuUpdateRequest } from "../main/menu/menu.updater";
|
||||
|
||||
import { PremiumComponent } from "./accounts/premium.component";
|
||||
import { SettingsComponent } from "./accounts/settings.component";
|
||||
import { ExportComponent } from "./vault/export.component";
|
||||
import { FolderAddEditComponent } from "./vault/folder-add-edit.component";
|
||||
import { PasswordGeneratorComponent } from "./vault/password-generator.component";
|
||||
|
||||
import { ModalRef } from "jslib-angular/components/modal/modal.ref";
|
||||
|
||||
import { ModalService } from "jslib-angular/services/modal.service";
|
||||
import { MenuUpdateRequest } from "src/main/menu.updater";
|
||||
import { GeneratorComponent } from "./vault/generator.component";
|
||||
import { PasswordGeneratorHistoryComponent } from "./vault/password-generator-history.component";
|
||||
|
||||
const BroadcasterSubscriptionId = "AppComponent";
|
||||
const IdleTimeout = 60000 * 10; // 10 minutes
|
||||
@ -68,7 +66,7 @@ const systemTimeoutOptions = {
|
||||
<ng-template #passwordHistory></ng-template>
|
||||
<ng-template #appFolderAddEdit></ng-template>
|
||||
<ng-template #exportVault></ng-template>
|
||||
<ng-template #appPasswordGenerator></ng-template>
|
||||
<ng-template #appGenerator></ng-template>
|
||||
<app-header></app-header>
|
||||
<div id="container">
|
||||
<div class="loading" *ngIf="loading">
|
||||
@ -87,8 +85,8 @@ export class AppComponent implements OnInit {
|
||||
exportVaultModalRef: ViewContainerRef;
|
||||
@ViewChild("appFolderAddEdit", { read: ViewContainerRef, static: true })
|
||||
folderAddEditModalRef: ViewContainerRef;
|
||||
@ViewChild("appPasswordGenerator", { read: ViewContainerRef, static: true })
|
||||
passwordGeneratorModalRef: ViewContainerRef;
|
||||
@ViewChild("appGenerator", { read: ViewContainerRef, static: true })
|
||||
generatorModalRef: ViewContainerRef;
|
||||
|
||||
loading = false;
|
||||
|
||||
@ -208,7 +206,7 @@ export class AppComponent implements OnInit {
|
||||
case "openPremium":
|
||||
await this.openModal<PremiumComponent>(PremiumComponent, this.premiumRef);
|
||||
break;
|
||||
case "showFingerprintPhrase":
|
||||
case "showFingerprintPhrase": {
|
||||
const fingerprint = await this.cryptoService.getFingerprint(
|
||||
await this.stateService.getUserId()
|
||||
);
|
||||
@ -219,11 +217,10 @@ export class AppComponent implements OnInit {
|
||||
this.i18nService.t("close")
|
||||
);
|
||||
if (result) {
|
||||
this.platformUtilsService.launchUri(
|
||||
"https://help.bitwarden.com/article/fingerprint-phrase/"
|
||||
);
|
||||
this.platformUtilsService.launchUri("https://bitwarden.com/help/fingerprint-phrase/");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "openPasswordHistory":
|
||||
await this.openModal<PasswordGeneratorHistoryComponent>(
|
||||
PasswordGeneratorHistoryComponent,
|
||||
@ -243,7 +240,7 @@ export class AppComponent implements OnInit {
|
||||
queryParams: { code: message.code, state: message.state },
|
||||
});
|
||||
break;
|
||||
case "premiumRequired":
|
||||
case "premiumRequired": {
|
||||
const premiumConfirmed = await this.platformUtilsService.showDialog(
|
||||
this.i18nService.t("premiumRequiredDesc"),
|
||||
this.i18nService.t("premiumRequired"),
|
||||
@ -254,7 +251,8 @@ export class AppComponent implements OnInit {
|
||||
await this.openModal<PremiumComponent>(PremiumComponent, this.premiumRef);
|
||||
}
|
||||
break;
|
||||
case "emailVerificationRequired":
|
||||
}
|
||||
case "emailVerificationRequired": {
|
||||
const emailVerificationConfirmed = await this.platformUtilsService.showDialog(
|
||||
this.i18nService.t("emailVerificationRequiredDesc"),
|
||||
this.i18nService.t("emailVerificationRequired"),
|
||||
@ -263,10 +261,11 @@ export class AppComponent implements OnInit {
|
||||
);
|
||||
if (emailVerificationConfirmed) {
|
||||
this.platformUtilsService.launchUri(
|
||||
"https://bitwarden.com/help/article/create-bitwarden-account/"
|
||||
"https://bitwarden.com/help/create-bitwarden-account/"
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "syncVault":
|
||||
try {
|
||||
await this.syncService.fullSync(true, true);
|
||||
@ -319,20 +318,22 @@ export class AppComponent implements OnInit {
|
||||
case "newFolder":
|
||||
await this.addFolder();
|
||||
break;
|
||||
case "openPasswordGenerator":
|
||||
// openPasswordGenerator has extended functionality if called in the vault
|
||||
case "openGenerator":
|
||||
// openGenerator has extended functionality if called in the vault
|
||||
if (!this.router.url.includes("vault")) {
|
||||
await this.openPasswordGenerator();
|
||||
await this.openGenerator();
|
||||
}
|
||||
break;
|
||||
case "convertAccountToKeyConnector":
|
||||
this.router.navigate(["/remove-password"]);
|
||||
break;
|
||||
case "switchAccount":
|
||||
case "switchAccount": {
|
||||
if (message.userId != null) {
|
||||
await this.stateService.setActiveUser(message.userId);
|
||||
}
|
||||
const locked = await this.vaultTimeoutService.isLocked(message.userId);
|
||||
const locked =
|
||||
(await this.authService.getAuthStatus(message.userId)) ===
|
||||
AuthenticationStatus.Locked;
|
||||
if (locked) {
|
||||
this.messagingService.send("locked", { userId: message.userId });
|
||||
} else {
|
||||
@ -343,12 +344,16 @@ export class AppComponent implements OnInit {
|
||||
this.router.navigate(["vault"]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "systemSuspended":
|
||||
await this.checkForSystemTimeout(systemTimeoutOptions.onSuspend);
|
||||
break;
|
||||
case "systemLocked":
|
||||
await this.checkForSystemTimeout(systemTimeoutOptions.onLock);
|
||||
break;
|
||||
case "systemIdle":
|
||||
await this.checkForSystemTimeout(systemTimeoutOptions.onIdle);
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -400,15 +405,15 @@ export class AppComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
async openPasswordGenerator() {
|
||||
async openGenerator() {
|
||||
if (this.modal != null) {
|
||||
this.modal.close();
|
||||
}
|
||||
|
||||
[this.modal] = await this.modalService.openViewRef(
|
||||
PasswordGeneratorComponent,
|
||||
this.folderAddEditModalRef,
|
||||
(comp) => (comp.showSelect = false)
|
||||
GeneratorComponent,
|
||||
this.generatorModalRef,
|
||||
(comp) => (comp.comingFromAddEdit = false)
|
||||
);
|
||||
|
||||
this.modal.onClosed.subscribe(() => {
|
||||
@ -434,7 +439,8 @@ export class AppComponent implements OnInit {
|
||||
isAuthenticated: await this.stateService.getIsAuthenticated({
|
||||
userId: userId,
|
||||
}),
|
||||
isLocked: await this.vaultTimeoutService.isLocked(userId),
|
||||
isLocked:
|
||||
(await this.authService.getAuthStatus(userId)) === AuthenticationStatus.Locked,
|
||||
email: stateAccounts[i].profile.email,
|
||||
userId: stateAccounts[i].profile.userId,
|
||||
};
|
||||
@ -584,14 +590,17 @@ export class AppComponent implements OnInit {
|
||||
}
|
||||
|
||||
private async reloadProcess(): Promise<void> {
|
||||
const accounts = Object.keys(this.stateService.accounts.getValue());
|
||||
if (accounts.length > 0) {
|
||||
for (const userId of accounts) {
|
||||
if (!(await this.vaultTimeoutService.isLocked(userId))) {
|
||||
const accounts = this.stateService.accounts.getValue();
|
||||
if (accounts != null) {
|
||||
const keys = Object.keys(accounts);
|
||||
if (keys.length > 0) {
|
||||
for (const userId of keys) {
|
||||
if ((await this.authService.getAuthStatus(userId)) === AuthenticationStatus.Unlocked) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
await this.systemService.startProcessReload();
|
||||
}
|
||||
|
||||
|
@ -4,17 +4,66 @@ import { A11yModule } from "@angular/cdk/a11y";
|
||||
import { DragDropModule } from "@angular/cdk/drag-drop";
|
||||
import { OverlayModule } from "@angular/cdk/overlay";
|
||||
import { ScrollingModule } from "@angular/cdk/scrolling";
|
||||
import { DatePipe } from "@angular/common";
|
||||
import { DatePipe, registerLocaleData } from "@angular/common";
|
||||
import localeAf from "@angular/common/locales/af";
|
||||
import localeAz from "@angular/common/locales/az";
|
||||
import localeBe from "@angular/common/locales/be";
|
||||
import localeBg from "@angular/common/locales/bg";
|
||||
import localeBn from "@angular/common/locales/bn";
|
||||
import localeBs from "@angular/common/locales/bs";
|
||||
import localeCa from "@angular/common/locales/ca";
|
||||
import localeCs from "@angular/common/locales/cs";
|
||||
import localeDa from "@angular/common/locales/da";
|
||||
import localeDe from "@angular/common/locales/de";
|
||||
import localeEl from "@angular/common/locales/el";
|
||||
import localeEnGb from "@angular/common/locales/en-GB";
|
||||
import localeEnIn from "@angular/common/locales/en-IN";
|
||||
import localeEo from "@angular/common/locales/eo";
|
||||
import localeEs from "@angular/common/locales/es";
|
||||
import localeEt from "@angular/common/locales/et";
|
||||
import localeFa from "@angular/common/locales/fa";
|
||||
import localeFi from "@angular/common/locales/fi";
|
||||
import localeFil from "@angular/common/locales/fil";
|
||||
import localeFr from "@angular/common/locales/fr";
|
||||
import localeHe from "@angular/common/locales/he";
|
||||
import localeHi from "@angular/common/locales/hi";
|
||||
import localeHr from "@angular/common/locales/hr";
|
||||
import localeHu from "@angular/common/locales/hu";
|
||||
import localeId from "@angular/common/locales/id";
|
||||
import localeIt from "@angular/common/locales/it";
|
||||
import localeJa from "@angular/common/locales/ja";
|
||||
import localeKa from "@angular/common/locales/ka";
|
||||
import localeKm from "@angular/common/locales/km";
|
||||
import localeKn from "@angular/common/locales/kn";
|
||||
import localeKo from "@angular/common/locales/ko";
|
||||
import localeLv from "@angular/common/locales/lv";
|
||||
import localeMl from "@angular/common/locales/ml";
|
||||
import localeNb from "@angular/common/locales/nb";
|
||||
import localeNl from "@angular/common/locales/nl";
|
||||
import localeNn from "@angular/common/locales/nn";
|
||||
import localePl from "@angular/common/locales/pl";
|
||||
import localePtBr from "@angular/common/locales/pt";
|
||||
import localePtPt from "@angular/common/locales/pt-PT";
|
||||
import localeRo from "@angular/common/locales/ro";
|
||||
import localeRu from "@angular/common/locales/ru";
|
||||
import localeSi from "@angular/common/locales/si";
|
||||
import localeSk from "@angular/common/locales/sk";
|
||||
import localeSl from "@angular/common/locales/sl";
|
||||
import localeSr from "@angular/common/locales/sr";
|
||||
import localeMe from "@angular/common/locales/sr-Latn-ME";
|
||||
import localeSv from "@angular/common/locales/sv";
|
||||
import localeTh from "@angular/common/locales/th";
|
||||
import localeTr from "@angular/common/locales/tr";
|
||||
import localeUk from "@angular/common/locales/uk";
|
||||
import localeVi from "@angular/common/locales/vi";
|
||||
import localeZhCn from "@angular/common/locales/zh-Hans";
|
||||
import localeZhTw from "@angular/common/locales/zh-Hant";
|
||||
import { NgModule } from "@angular/core";
|
||||
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
|
||||
import { BrowserModule } from "@angular/platform-browser";
|
||||
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
||||
import "zone.js/dist/zone";
|
||||
|
||||
import { AppRoutingModule } from "./app-routing.module";
|
||||
import { ServicesModule } from "./services.module";
|
||||
|
||||
import { AppComponent } from "./app.component";
|
||||
import { JslibModule } from "jslib-angular/jslib.module";
|
||||
|
||||
import { EnvironmentComponent } from "./accounts/environment.component";
|
||||
import { HintComponent } from "./accounts/hint.component";
|
||||
@ -30,29 +79,19 @@ import { TwoFactorOptionsComponent } from "./accounts/two-factor-options.compone
|
||||
import { TwoFactorComponent } from "./accounts/two-factor.component";
|
||||
import { UpdateTempPasswordComponent } from "./accounts/update-temp-password.component";
|
||||
import { VaultTimeoutInputComponent } from "./accounts/vault-timeout-input.component";
|
||||
|
||||
import { AvatarComponent } from "jslib-angular/components/avatar.component";
|
||||
import { CalloutComponent } from "jslib-angular/components/callout.component";
|
||||
import { IconComponent } from "jslib-angular/components/icon.component";
|
||||
import { BitwardenToastModule } from "jslib-angular/components/toastr.component";
|
||||
|
||||
import { A11yTitleDirective } from "jslib-angular/directives/a11y-title.directive";
|
||||
import { ApiActionDirective } from "jslib-angular/directives/api-action.directive";
|
||||
import { AutofocusDirective } from "jslib-angular/directives/autofocus.directive";
|
||||
import { BlurClickDirective } from "jslib-angular/directives/blur-click.directive";
|
||||
import { BoxRowDirective } from "jslib-angular/directives/box-row.directive";
|
||||
import { CipherListVirtualScroll } from "jslib-angular/directives/cipherListVirtualScroll.directive";
|
||||
import { FallbackSrcDirective } from "jslib-angular/directives/fallback-src.directive";
|
||||
import { InputVerbatimDirective } from "jslib-angular/directives/input-verbatim.directive";
|
||||
import { SelectCopyDirective } from "jslib-angular/directives/select-copy.directive";
|
||||
import { StopClickDirective } from "jslib-angular/directives/stop-click.directive";
|
||||
import { StopPropDirective } from "jslib-angular/directives/stop-prop.directive";
|
||||
import { TrueFalseValueDirective } from "jslib-angular/directives/true-false-value.directive";
|
||||
|
||||
import { ColorPasswordPipe } from "jslib-angular/pipes/color-password.pipe";
|
||||
import { I18nPipe } from "jslib-angular/pipes/i18n.pipe";
|
||||
import { SearchCiphersPipe } from "jslib-angular/pipes/search-ciphers.pipe";
|
||||
|
||||
import { AppRoutingModule } from "./app-routing.module";
|
||||
import { AppComponent } from "./app.component";
|
||||
import { PasswordRepromptComponent } from "./components/password-reprompt.component";
|
||||
import { SetPinComponent } from "./components/set-pin.component";
|
||||
import { UserVerificationComponent } from "./components/user-verification.component";
|
||||
import { AccountSwitcherComponent } from "./layout/account-switcher.component";
|
||||
import { HeaderComponent } from "./layout/header.component";
|
||||
import { NavComponent } from "./layout/nav.component";
|
||||
import { SearchComponent } from "./layout/search/search.component";
|
||||
import { AddEditComponent as SendAddEditComponent } from "./send/add-edit.component";
|
||||
import { EffluxDatesComponent as SendEffluxDatesComponent } from "./send/efflux-dates.component";
|
||||
import { SendComponent } from "./send/send.component";
|
||||
import { ServicesModule } from "./services/services.module";
|
||||
import { AddEditCustomFieldsComponent } from "./vault/add-edit-custom-fields.component";
|
||||
import { AddEditComponent } from "./vault/add-edit.component";
|
||||
import { AttachmentsComponent } from "./vault/attachments.component";
|
||||
@ -60,79 +99,21 @@ import { CiphersComponent } from "./vault/ciphers.component";
|
||||
import { CollectionsComponent } from "./vault/collections.component";
|
||||
import { ExportComponent } from "./vault/export.component";
|
||||
import { FolderAddEditComponent } from "./vault/folder-add-edit.component";
|
||||
import { GeneratorComponent } from "./vault/generator.component";
|
||||
import { GroupingsComponent } from "./vault/groupings.component";
|
||||
import { PasswordGeneratorHistoryComponent } from "./vault/password-generator-history.component";
|
||||
import { PasswordGeneratorComponent } from "./vault/password-generator.component";
|
||||
import { PasswordHistoryComponent } from "./vault/password-history.component";
|
||||
import { ShareComponent } from "./vault/share.component";
|
||||
import { VaultComponent } from "./vault/vault.component";
|
||||
import { ViewCustomFieldsComponent } from "./vault/view-custom-fields.component";
|
||||
import { ViewComponent } from "./vault/view.component";
|
||||
|
||||
import { AddEditComponent as SendAddEditComponent } from "./send/add-edit.component";
|
||||
import { EffluxDatesComponent as SendEffluxDatesComponent } from "./send/efflux-dates.component";
|
||||
import { SendComponent } from "./send/send.component";
|
||||
|
||||
import { AccountSwitcherComponent } from "./layout/account-switcher.component";
|
||||
import { HeaderComponent } from "./layout/header.component";
|
||||
import { NavComponent } from "./layout/nav.component";
|
||||
import { SearchComponent } from "./layout/search/search.component";
|
||||
|
||||
import { PasswordRepromptComponent } from "./components/password-reprompt.component";
|
||||
import { SetPinComponent } from "./components/set-pin.component";
|
||||
import { VerifyMasterPasswordComponent } from "./components/verify-master-password.component";
|
||||
|
||||
import { registerLocaleData } from "@angular/common";
|
||||
import localeAf from "@angular/common/locales/af";
|
||||
import localeAz from "@angular/common/locales/az";
|
||||
import localeBe from "@angular/common/locales/be";
|
||||
import localeBg from "@angular/common/locales/bg";
|
||||
import localeBn from "@angular/common/locales/bn";
|
||||
import localeCa from "@angular/common/locales/ca";
|
||||
import localeCs from "@angular/common/locales/cs";
|
||||
import localeDa from "@angular/common/locales/da";
|
||||
import localeDe from "@angular/common/locales/de";
|
||||
import localeEl from "@angular/common/locales/el";
|
||||
import localeEnGb from "@angular/common/locales/en-GB";
|
||||
import localeEnIn from "@angular/common/locales/en-IN";
|
||||
import localeEs from "@angular/common/locales/es";
|
||||
import localeEt from "@angular/common/locales/et";
|
||||
import localeFa from "@angular/common/locales/fa";
|
||||
import localeFi from "@angular/common/locales/fi";
|
||||
import localeFr from "@angular/common/locales/fr";
|
||||
import localeHe from "@angular/common/locales/he";
|
||||
import localeHr from "@angular/common/locales/hr";
|
||||
import localeHu from "@angular/common/locales/hu";
|
||||
import localeId from "@angular/common/locales/id";
|
||||
import localeIt from "@angular/common/locales/it";
|
||||
import localeJa from "@angular/common/locales/ja";
|
||||
import localeKn from "@angular/common/locales/kn";
|
||||
import localeKo from "@angular/common/locales/ko";
|
||||
import localeLv from "@angular/common/locales/lv";
|
||||
import localeMl from "@angular/common/locales/ml";
|
||||
import localeNb from "@angular/common/locales/nb";
|
||||
import localeNl from "@angular/common/locales/nl";
|
||||
import localePl from "@angular/common/locales/pl";
|
||||
import localePtBr from "@angular/common/locales/pt";
|
||||
import localePtPt from "@angular/common/locales/pt-PT";
|
||||
import localeRo from "@angular/common/locales/ro";
|
||||
import localeRu from "@angular/common/locales/ru";
|
||||
import localeSk from "@angular/common/locales/sk";
|
||||
import localeSr from "@angular/common/locales/sr";
|
||||
import localeMe from "@angular/common/locales/sr-Latn-ME";
|
||||
import localeSv from "@angular/common/locales/sv";
|
||||
import localeTh from "@angular/common/locales/th";
|
||||
import localeTr from "@angular/common/locales/tr";
|
||||
import localeUk from "@angular/common/locales/uk";
|
||||
import localeVi from "@angular/common/locales/vi";
|
||||
import localeZhCn from "@angular/common/locales/zh-Hans";
|
||||
import localeZhTw from "@angular/common/locales/zh-Hant";
|
||||
|
||||
registerLocaleData(localeAf, "af");
|
||||
registerLocaleData(localeAz, "az");
|
||||
registerLocaleData(localeBe, "be");
|
||||
registerLocaleData(localeBg, "bg");
|
||||
registerLocaleData(localeBn, "bn");
|
||||
registerLocaleData(localeBs, "bs");
|
||||
registerLocaleData(localeCa, "ca");
|
||||
registerLocaleData(localeCs, "cs");
|
||||
registerLocaleData(localeDa, "da");
|
||||
@ -140,17 +121,22 @@ registerLocaleData(localeDe, "de");
|
||||
registerLocaleData(localeEl, "el");
|
||||
registerLocaleData(localeEnGb, "en-GB");
|
||||
registerLocaleData(localeEnIn, "en-IN");
|
||||
registerLocaleData(localeEo, "eo");
|
||||
registerLocaleData(localeEs, "es");
|
||||
registerLocaleData(localeEt, "et");
|
||||
registerLocaleData(localeFa, "fa");
|
||||
registerLocaleData(localeFi, "fi");
|
||||
registerLocaleData(localeFil, "fil");
|
||||
registerLocaleData(localeFr, "fr");
|
||||
registerLocaleData(localeHe, "he");
|
||||
registerLocaleData(localeHi, "hi");
|
||||
registerLocaleData(localeHr, "hr");
|
||||
registerLocaleData(localeHu, "hu");
|
||||
registerLocaleData(localeId, "id");
|
||||
registerLocaleData(localeIt, "it");
|
||||
registerLocaleData(localeJa, "ja");
|
||||
registerLocaleData(localeKa, "ka");
|
||||
registerLocaleData(localeKm, "km");
|
||||
registerLocaleData(localeKn, "kn");
|
||||
registerLocaleData(localeKo, "ko");
|
||||
registerLocaleData(localeLv, "lv");
|
||||
@ -158,12 +144,15 @@ registerLocaleData(localeMe, "me");
|
||||
registerLocaleData(localeMl, "ml");
|
||||
registerLocaleData(localeNb, "nb");
|
||||
registerLocaleData(localeNl, "nl");
|
||||
registerLocaleData(localeNn, "nn");
|
||||
registerLocaleData(localePl, "pl");
|
||||
registerLocaleData(localePtBr, "pt-BR");
|
||||
registerLocaleData(localePtPt, "pt-PT");
|
||||
registerLocaleData(localeRo, "ro");
|
||||
registerLocaleData(localeRu, "ru");
|
||||
registerLocaleData(localeSi, "si");
|
||||
registerLocaleData(localeSk, "sk");
|
||||
registerLocaleData(localeSl, "sl");
|
||||
registerLocaleData(localeSr, "sr");
|
||||
registerLocaleData(localeSv, "sv");
|
||||
registerLocaleData(localeTh, "th");
|
||||
@ -175,58 +164,43 @@ registerLocaleData(localeZhTw, "zh-TW");
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
A11yModule,
|
||||
AppRoutingModule,
|
||||
BrowserAnimationsModule,
|
||||
BrowserModule,
|
||||
DragDropModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
ServicesModule,
|
||||
BitwardenToastModule.forRoot({
|
||||
maxOpened: 5,
|
||||
autoDismiss: true,
|
||||
closeButton: true,
|
||||
}),
|
||||
ScrollingModule,
|
||||
A11yModule,
|
||||
JslibModule,
|
||||
OverlayModule,
|
||||
ReactiveFormsModule,
|
||||
ScrollingModule,
|
||||
ServicesModule,
|
||||
],
|
||||
declarations: [
|
||||
A11yTitleDirective,
|
||||
AccountSwitcherComponent,
|
||||
AddEditComponent,
|
||||
AddEditCustomFieldsComponent,
|
||||
ApiActionDirective,
|
||||
AppComponent,
|
||||
AttachmentsComponent,
|
||||
AutofocusDirective,
|
||||
BlurClickDirective,
|
||||
BoxRowDirective,
|
||||
CalloutComponent,
|
||||
CipherListVirtualScroll,
|
||||
CiphersComponent,
|
||||
CollectionsComponent,
|
||||
ColorPasswordPipe,
|
||||
EnvironmentComponent,
|
||||
ExportComponent,
|
||||
FallbackSrcDirective,
|
||||
FolderAddEditComponent,
|
||||
GroupingsComponent,
|
||||
HeaderComponent,
|
||||
HintComponent,
|
||||
I18nPipe,
|
||||
IconComponent,
|
||||
InputVerbatimDirective,
|
||||
LockComponent,
|
||||
LoginComponent,
|
||||
NavComponent,
|
||||
PasswordGeneratorComponent,
|
||||
GeneratorComponent,
|
||||
PasswordGeneratorHistoryComponent,
|
||||
PasswordHistoryComponent,
|
||||
PasswordRepromptComponent,
|
||||
PremiumComponent,
|
||||
RegisterComponent,
|
||||
RemovePasswordComponent,
|
||||
SearchCiphersPipe,
|
||||
SelectCopyDirective,
|
||||
SearchComponent,
|
||||
SendAddEditComponent,
|
||||
SendComponent,
|
||||
SendEffluxDatesComponent,
|
||||
@ -235,21 +209,14 @@ registerLocaleData(localeZhTw, "zh-TW");
|
||||
SettingsComponent,
|
||||
ShareComponent,
|
||||
SsoComponent,
|
||||
StopClickDirective,
|
||||
StopPropDirective,
|
||||
TrueFalseValueDirective,
|
||||
TwoFactorComponent,
|
||||
TwoFactorOptionsComponent,
|
||||
UpdateTempPasswordComponent,
|
||||
UserVerificationComponent,
|
||||
VaultComponent,
|
||||
VaultTimeoutInputComponent,
|
||||
VerifyMasterPasswordComponent,
|
||||
ViewComponent,
|
||||
ViewCustomFieldsComponent,
|
||||
HeaderComponent,
|
||||
AccountSwitcherComponent,
|
||||
AvatarComponent,
|
||||
SearchComponent,
|
||||
],
|
||||
providers: [DatePipe],
|
||||
bootstrap: [AppComponent],
|
||||
|
@ -19,13 +19,12 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
(click)="togglePassword()"
|
||||
>
|
||||
<i
|
||||
@ -33,7 +32,7 @@
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -43,7 +42,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary btn-submit" appBlurClick>
|
||||
<button type="submit" class="btn btn-primary btn-submit">
|
||||
<span>{{ "ok" | i18n }}</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">
|
||||
|
@ -22,12 +22,12 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showPin"
|
||||
(click)="toggleVisibility()"
|
||||
>
|
||||
<i
|
||||
@ -35,7 +35,7 @@
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPin, 'bwi-eye-slash': showPin }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -2,16 +2,16 @@ import { animate, style, transition, trigger } from "@angular/animations";
|
||||
import { Component } from "@angular/core";
|
||||
import { NG_VALUE_ACCESSOR } from "@angular/forms";
|
||||
|
||||
import { VerifyMasterPasswordComponent as BaseComponent } from "jslib-angular/components/verify-master-password.component";
|
||||
import { UserVerificationComponent as BaseComponent } from "jslib-angular/components/user-verification.component";
|
||||
|
||||
@Component({
|
||||
selector: "app-verify-master-password",
|
||||
templateUrl: "verify-master-password.component.html",
|
||||
selector: "app-user-verification",
|
||||
templateUrl: "user-verification.component.html",
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
multi: true,
|
||||
useExisting: VerifyMasterPasswordComponent,
|
||||
useExisting: UserVerificationComponent,
|
||||
},
|
||||
],
|
||||
animations: [
|
||||
@ -20,4 +20,4 @@ import { VerifyMasterPasswordComponent as BaseComponent } from "jslib-angular/co
|
||||
]),
|
||||
],
|
||||
})
|
||||
export class VerifyMasterPasswordComponent extends BaseComponent {}
|
||||
export class UserVerificationComponent extends BaseComponent {}
|
@ -5,8 +5,8 @@
|
||||
#trigger="cdkOverlayOrigin"
|
||||
[hidden]="!showSwitcher"
|
||||
aria-haspopup="menu"
|
||||
aria-expanded="isOpen"
|
||||
aria-controls="cdk-overlay-container"
|
||||
[attr.aria-expanded]="isOpen"
|
||||
>
|
||||
<ng-container *ngIf="activeAccountEmail != null; else noActiveAccount">
|
||||
<app-avatar
|
||||
@ -46,12 +46,13 @@
|
||||
[@transformPanel]="'open'"
|
||||
cdkTrapFocus
|
||||
cdkTrapFocusAutoCapture
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
>
|
||||
<div class="accounts" *ngIf="numberOfAccounts > 0">
|
||||
<button
|
||||
*ngFor="let a of accounts | keyvalue"
|
||||
class="account"
|
||||
[ngClass]="{ active: a.value.profile.authenticationStatus == 'active' }"
|
||||
(click)="switch(a.key)"
|
||||
appA11yTitle="{{ 'loggedInAsOn' | i18n: a.value.profile.email:a.value.serverUrl }}"
|
||||
attr.aria-label="{{ 'switchAccount' | i18n }}"
|
||||
@ -70,17 +71,17 @@
|
||||
<span class="server" aria-hidden="true" *ngIf="a.value.serverUrl != 'bitwarden.com'">{{
|
||||
a.value.serverUrl
|
||||
}}</span>
|
||||
<span class="status" aria-hidden="true">{{ a.value.profile.authenticationStatus }}</span>
|
||||
<span class="status" aria-hidden="true">{{
|
||||
(a.value.profile.authenticationStatus === authStatus.Unlocked ? "unlocked" : "locked")
|
||||
| i18n
|
||||
}}</span>
|
||||
</div>
|
||||
<i
|
||||
class="bwi bwi-unlock bwi-2x text-muted"
|
||||
class="bwi bwi-2x text-muted"
|
||||
[ngClass]="
|
||||
a.value.profile.authenticationStatus == authStatus.Unlocked ? 'bwi-unlock' : 'bwi-lock'
|
||||
"
|
||||
aria-hidden="true"
|
||||
*ngIf="a.value.profile.authenticationStatus == 'unlocked'"
|
||||
></i>
|
||||
<i
|
||||
class="bwi bwi-lock bwi-2x text-muted"
|
||||
aria-hidden="true"
|
||||
*ngIf="a.value.profile.authenticationStatus == 'locked'"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -2,13 +2,11 @@ import { animate, state, style, transition, trigger } from "@angular/animations"
|
||||
import { ConnectedPosition } from "@angular/cdk/overlay";
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
|
||||
import { AuthService } from "jslib-common/abstractions/auth.service";
|
||||
import { MessagingService } from "jslib-common/abstractions/messaging.service";
|
||||
import { StateService } from "jslib-common/abstractions/state.service";
|
||||
import { VaultTimeoutService } from "jslib-common/abstractions/vaultTimeout.service";
|
||||
|
||||
import { AuthenticationStatus } from "jslib-common/enums/authenticationStatus";
|
||||
import { Utils } from "jslib-common/misc/utils";
|
||||
|
||||
import { Account } from "jslib-common/models/domain/account";
|
||||
|
||||
export class SwitcherAccount extends Account {
|
||||
@ -51,10 +49,11 @@ export class SwitcherAccount extends Account {
|
||||
],
|
||||
})
|
||||
export class AccountSwitcherComponent implements OnInit {
|
||||
isOpen: boolean = false;
|
||||
isOpen = false;
|
||||
accounts: { [userId: string]: SwitcherAccount } = {};
|
||||
activeAccountEmail: string;
|
||||
serverUrl: string;
|
||||
authStatus = AuthenticationStatus;
|
||||
overlayPostition: ConnectedPosition[] = [
|
||||
{
|
||||
originX: "end",
|
||||
@ -80,22 +79,16 @@ export class AccountSwitcherComponent implements OnInit {
|
||||
|
||||
constructor(
|
||||
private stateService: StateService,
|
||||
private vaultTimeoutService: VaultTimeoutService,
|
||||
private authService: AuthService,
|
||||
private messagingService: MessagingService
|
||||
) {}
|
||||
|
||||
async ngOnInit(): Promise<void> {
|
||||
this.stateService.accounts.subscribe(async (accounts) => {
|
||||
this.stateService.accounts.subscribe(async (accounts: { [userId: string]: Account }) => {
|
||||
for (const userId in accounts) {
|
||||
if (userId === (await this.stateService.getUserId())) {
|
||||
accounts[userId].profile.authenticationStatus = AuthenticationStatus.Active;
|
||||
} else {
|
||||
accounts[userId].profile.authenticationStatus = (await this.vaultTimeoutService.isLocked(
|
||||
accounts[userId].profile.authenticationStatus = await this.authService.getAuthStatus(
|
||||
userId
|
||||
))
|
||||
? AuthenticationStatus.Locked
|
||||
: AuthenticationStatus.Unlocked;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
this.accounts = await this.createSwitcherAccounts(accounts);
|
||||
|
@ -1,5 +1,13 @@
|
||||
<ng-container *ngFor="let item of items">
|
||||
<a [routerLink]="item.link" class="btn primary" routerLinkActive="active" [title]="item.label">
|
||||
<button
|
||||
type="button"
|
||||
[routerLink]="item.link"
|
||||
class="btn primary"
|
||||
routerLinkActive="active"
|
||||
[title]="item.label"
|
||||
#rla="routerLinkActive"
|
||||
[attr.aria-pressed]="rla.isActive"
|
||||
>
|
||||
<i class="bwi" [ngClass]="item.icon"></i>{{ item.label }}
|
||||
</a>
|
||||
</button>
|
||||
</ng-container>
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
|
||||
@Component({
|
||||
|
@ -93,21 +93,20 @@
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-header">
|
||||
{{ "options" | i18n }}
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="toggle"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
(click)="toggleOptions()"
|
||||
[attr.aria-expanded]="showOptions"
|
||||
>
|
||||
{{ "options" | i18n }}
|
||||
<i
|
||||
class="bwi bwi-lg"
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-angle-down': !showOptions, 'bwi-chevron-up': showOptions }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div [hidden]="!showOptions">
|
||||
@ -157,13 +156,12 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
(click)="togglePasswordVisible()"
|
||||
[disabled]="disableSend"
|
||||
>
|
||||
@ -172,7 +170,7 @@
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -253,7 +251,6 @@
|
||||
</div>
|
||||
<div class="footer">
|
||||
<button
|
||||
appBlurClick
|
||||
type="submit"
|
||||
class="primary btn-submit"
|
||||
appA11yTitle="{{ 'save' | i18n }}"
|
||||
@ -263,12 +260,11 @@
|
||||
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
|
||||
<span><i class="bwi bwi-save-changes bwi-lg bwi-fw" aria-hidden="true"></i></span>
|
||||
</button>
|
||||
<button appBlurClick type="button" (click)="cancel()" [disabled]="form.loading">
|
||||
<button type="button" (click)="cancel()" [disabled]="form.loading">
|
||||
{{ "cancel" | i18n }}
|
||||
</button>
|
||||
<div class="right">
|
||||
<button
|
||||
appBlurClick
|
||||
type="button"
|
||||
(click)="copyLinkToClipboard(link)"
|
||||
appA11yTitle="{{ 'copySendLinkToClipboard' | i18n }}"
|
||||
@ -278,7 +274,6 @@
|
||||
</button>
|
||||
<button
|
||||
#deleteBtn
|
||||
appBlurClick
|
||||
type="button"
|
||||
(click)="delete()"
|
||||
class="danger"
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { DatePipe } from "@angular/common";
|
||||
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { AddEditComponent as BaseAddEditComponent } from "jslib-angular/components/send/add-edit.component";
|
||||
import { EnvironmentService } from "jslib-common/abstractions/environment.service";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { LogService } from "jslib-common/abstractions/log.service";
|
||||
@ -11,8 +11,6 @@ import { PolicyService } from "jslib-common/abstractions/policy.service";
|
||||
import { SendService } from "jslib-common/abstractions/send.service";
|
||||
import { StateService } from "jslib-common/abstractions/state.service";
|
||||
|
||||
import { AddEditComponent as BaseAddEditComponent } from "jslib-angular/components/send/add-edit.component";
|
||||
|
||||
@Component({
|
||||
selector: "app-send-add-edit",
|
||||
templateUrl: "add-edit.component.html",
|
||||
|
@ -1,14 +1,11 @@
|
||||
import { DatePipe } from "@angular/common";
|
||||
|
||||
import { Component, OnChanges } from "@angular/core";
|
||||
|
||||
import { ControlContainer, NgForm } from "@angular/forms";
|
||||
|
||||
import { EffluxDatesComponent as BaseEffluxDatesComponent } from "jslib-angular/components/send/efflux-dates.component";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
|
||||
import { EffluxDatesComponent as BaseEffluxDatesComponent } from "jslib-angular/components/send/efflux-dates.component";
|
||||
|
||||
@Component({
|
||||
selector: "app-send-efflux-dates",
|
||||
templateUrl: "efflux-dates.component.html",
|
||||
|
@ -5,26 +5,41 @@
|
||||
<h2 class="sr-only">{{ "filters" | i18n }}</h2>
|
||||
<ul>
|
||||
<li [ngClass]="{ active: selectedAll }">
|
||||
<a href="#" appStopClick appBlurClick (click)="selectAll()">
|
||||
<button
|
||||
type="button"
|
||||
appStopClick
|
||||
(click)="selectAll()"
|
||||
[attr.aria-pressed]="selectedAll"
|
||||
>
|
||||
<i class="bwi bwi-fw bwi-filter" aria-hidden="true"></i> {{ "allSends" | i18n }}
|
||||
</a>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
<h2>{{ "types" | i18n }}</h2>
|
||||
<ul>
|
||||
<li [ngClass]="{ active: selectedType === sendType.Text }">
|
||||
<a href="#" appStopClick appBlurClick (click)="selectType(sendType.Text)">
|
||||
<button
|
||||
type="button"
|
||||
appStopClick
|
||||
(click)="selectType(sendType.Text)"
|
||||
[attr.aria-pressed]="selectedType === sendType.Text"
|
||||
>
|
||||
<i class="bwi bwi-fw bwi-file-text" aria-hidden="true"></i> {{
|
||||
"sendTypeText" | i18n
|
||||
}}
|
||||
</a>
|
||||
</button>
|
||||
</li>
|
||||
<li [ngClass]="{ active: selectedType === sendType.File }">
|
||||
<a href="#" appStopClick appBlurClick (click)="selectType(sendType.File)">
|
||||
<button
|
||||
type="button"
|
||||
appStopClick
|
||||
(click)="selectType(sendType.File)"
|
||||
[attr.aria-pressed]="selectedType === sendType.File"
|
||||
>
|
||||
<i class="bwi bwi-fw bwi-file" aria-hidden="true"></i> {{
|
||||
"sendTypeFile" | i18n
|
||||
}}
|
||||
</a>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -36,20 +51,21 @@
|
||||
<div id="items" class="items">
|
||||
<div class="content">
|
||||
<div class="list" *ngIf="filteredSends.length">
|
||||
<a
|
||||
<button
|
||||
*ngFor="let s of filteredSends"
|
||||
appStopClick
|
||||
(click)="selectSend(s.id)"
|
||||
title="{{ 'viewItem' | i18n }}"
|
||||
(contextmenu)="viewSendMenu(s)"
|
||||
[ngClass]="{ active: s.id === sendId }"
|
||||
[attr.aria-pressed]="s.id === sendId"
|
||||
class="flex-list-item"
|
||||
>
|
||||
<div class="item-icon" aria-hidden="true">
|
||||
<span class="item-icon" aria-hidden="true">
|
||||
<i class="bwi bwi-fw bwi-lg" [ngClass]="s.type == 0 ? 'bwi-file-text' : 'bwi-file'"></i>
|
||||
</div>
|
||||
<div class="item-content">
|
||||
<div class="item-title">
|
||||
</span>
|
||||
<span class="item-content">
|
||||
<span class="item-title">
|
||||
{{ s.name }}
|
||||
<span class="title-badges">
|
||||
<ng-container *ngIf="s.disabled">
|
||||
@ -98,10 +114,10 @@
|
||||
<span class="sr-only">{{ "pendingDeletion" | i18n }}</span>
|
||||
</ng-container>
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
<span class="item-details">{{ s.deletionDate | date }}</span>
|
||||
</div>
|
||||
</a>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="no-items" *ngIf="!filteredSends.length">
|
||||
<i class="bwi bwi-spinner bwi-spin bwi-3x" *ngIf="!loaded" aria-hidden="true"></i>
|
||||
@ -112,12 +128,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<button
|
||||
appBlurClick
|
||||
(click)="addSend()"
|
||||
class="block primary"
|
||||
appA11yTitle="{{ 'addItem' | i18n }}"
|
||||
>
|
||||
<button (click)="addSend()" class="block primary" appA11yTitle="{{ 'addItem' | i18n }}">
|
||||
<i class="bwi bwi-plus bwi-lg" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Component, NgZone, OnDestroy, OnInit, ViewChild } from "@angular/core";
|
||||
|
||||
import { SendComponent as BaseSendComponent } from "jslib-angular/components/send/send.component";
|
||||
import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service";
|
||||
import { EnvironmentService } from "jslib-common/abstractions/environment.service";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
@ -8,14 +9,11 @@ import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.se
|
||||
import { PolicyService } from "jslib-common/abstractions/policy.service";
|
||||
import { SearchService } from "jslib-common/abstractions/search.service";
|
||||
import { SendService } from "jslib-common/abstractions/send.service";
|
||||
|
||||
import { SendComponent as BaseSendComponent } from "jslib-angular/components/send/send.component";
|
||||
|
||||
import { SendView } from "jslib-common/models/view/sendView";
|
||||
import { invokeMenu, RendererMenuItem } from "jslib-electron/utils";
|
||||
|
||||
import { SendView } from "jslib-common/models/view/sendView";
|
||||
|
||||
import { SearchBarService } from "../layout/search/search-bar.service";
|
||||
|
||||
import { AddEditComponent } from "./add-edit.component";
|
||||
|
||||
enum Action {
|
||||
|