mirror of
https://github.com/bitwarden/directory-connector
synced 2026-01-06 18:44:04 +00:00
Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
def3caa93b | ||
|
|
0b881a63d4 | ||
|
|
9dadfbd037 | ||
|
|
b0bf07d70e | ||
|
|
9136e3936b | ||
|
|
35aead6c0e | ||
|
|
615f3b82db | ||
|
|
baa441cb90 | ||
|
|
9ad683ca09 | ||
|
|
c2d1d12cd2 | ||
|
|
3b6bac7668 | ||
|
|
2be879548d | ||
|
|
033c346042 | ||
|
|
32a8e65fe8 | ||
|
|
b2d4d80181 | ||
|
|
56c1cb23a0 | ||
|
|
ba26f70d1a | ||
|
|
e5589e7664 | ||
|
|
4e82486784 | ||
|
|
bb1cdebaf4 | ||
|
|
01405f47c9 | ||
|
|
5e64dc9262 | ||
|
|
9c7cd943b3 | ||
|
|
7cf3166169 | ||
|
|
9bdb77a573 | ||
|
|
3b8ee5ec0d | ||
|
|
6e7e09064f | ||
|
|
dfcb450a8a | ||
|
|
b192c34c15 | ||
|
|
f813dbb690 | ||
|
|
16deafca76 | ||
|
|
647b087fa7 | ||
|
|
4bd1387b83 | ||
|
|
a6aafe7593 |
29
.github/scripts/decrypt-secret.ps1
vendored
29
.github/scripts/decrypt-secret.ps1
vendored
@@ -1,29 +0,0 @@
|
|||||||
param (
|
|
||||||
[Parameter(Mandatory=$true)]
|
|
||||||
[string] $filename,
|
|
||||||
[string] $output
|
|
||||||
)
|
|
||||||
|
|
||||||
$homePath = Resolve-Path "~" | Select-Object -ExpandProperty Path
|
|
||||||
$rootPath = $env:GITHUB_WORKSPACE
|
|
||||||
|
|
||||||
$secretInputPath = $rootPath + "/.github/secrets"
|
|
||||||
$input = $secretInputPath + "/" + $filename
|
|
||||||
|
|
||||||
$passphrase = $env:DECRYPT_FILE_PASSWORD
|
|
||||||
$secretOutputPath = $homePath + "/secrets"
|
|
||||||
|
|
||||||
if ([string]::IsNullOrEmpty($output)) {
|
|
||||||
if ($filename.EndsWith(".gpg")) {
|
|
||||||
$output = $secretOutputPath + "/" + $filename.TrimEnd(".gpg")
|
|
||||||
} else {
|
|
||||||
$output = $secretOutputPath + "/" + $filename + ".plaintext"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(Test-Path -Path $secretOutputPath))
|
|
||||||
{
|
|
||||||
New-Item -ItemType Directory -Path $secretOutputPath
|
|
||||||
}
|
|
||||||
|
|
||||||
gpg --quiet --batch --yes --decrypt --passphrase="$passphrase" --output $output $input
|
|
||||||
5
.github/scripts/load-version.ps1
vendored
5
.github/scripts/load-version.ps1
vendored
@@ -1,5 +0,0 @@
|
|||||||
$rootPath = $env:GITHUB_WORKSPACE;
|
|
||||||
$packageVersion = (Get-Content -Raw -Path $rootPath\src\package.json | ConvertFrom-Json).version;
|
|
||||||
|
|
||||||
Write-Output "Setting package version to $packageVersion";
|
|
||||||
Write-Output "PACKAGE_VERSION=$packageVersion" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append;
|
|
||||||
7
.github/scripts/macos/decrypt-secrets.ps1
vendored
7
.github/scripts/macos/decrypt-secrets.ps1
vendored
@@ -1,7 +0,0 @@
|
|||||||
$rootPath = $env:GITHUB_WORKSPACE;
|
|
||||||
|
|
||||||
$decryptSecretPath = $($rootPath + "/.github/scripts/decrypt-secret.ps1");
|
|
||||||
|
|
||||||
Invoke-Expression "& `"$decryptSecretPath`" -filename devid-app-cert.p12.gpg"
|
|
||||||
Invoke-Expression "& `"$decryptSecretPath`" -filename devid-installer-cert.p12.gpg"
|
|
||||||
Invoke-Expression "& `"$decryptSecretPath`" -filename macdev-cert.p12.gpg"
|
|
||||||
15
.github/scripts/macos/setup-keychain.ps1
vendored
15
.github/scripts/macos/setup-keychain.ps1
vendored
@@ -1,15 +0,0 @@
|
|||||||
$homePath = Resolve-Path "~" | Select-Object -ExpandProperty Path;
|
|
||||||
$secretsPath = $homePath + "/secrets"
|
|
||||||
|
|
||||||
$devidAppCertPath = $($secretsPath + "/devid-app-cert.p12");
|
|
||||||
$devidInstallerCertPath = $($secretsPath + "/devid-installer-cert.p12");
|
|
||||||
$macdevCertPath = $($secretsPath + "/macdev-cert.p12");
|
|
||||||
|
|
||||||
security create-keychain -p $env:KEYCHAIN_PASSWORD build.keychain
|
|
||||||
security default-keychain -s build.keychain
|
|
||||||
security unlock-keychain -p $env:KEYCHAIN_PASSWORD build.keychain
|
|
||||||
security set-keychain-settings -lut 1200 build.keychain
|
|
||||||
security import $devidAppCertPath -k build.keychain -P $env:DEVID_CERT_PASSWORD -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
|
|
||||||
security import $devidInstallerCertPath -k build.keychain -P $env:DEVID_CERT_PASSWORD -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
|
|
||||||
security import $macdevCertPath -k build.keychain -P $env:MACDEV_CERT_PASSWORD -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
|
|
||||||
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $env:KEYCHAIN_PASSWORD build.keychain
|
|
||||||
414
.github/workflows/build.yml
vendored
414
.github/workflows/build.yml
vendored
@@ -1,52 +1,56 @@
|
|||||||
|
---
|
||||||
name: Build
|
name: Build
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches-ignore:
|
branches-ignore:
|
||||||
- 'l10n_master'
|
- 'l10n_master'
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
cloc:
|
cloc:
|
||||||
runs-on: ubuntu-latest
|
name: CLOC
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
|
||||||
|
|
||||||
- name: Set up cloc
|
- name: Set up CLOC
|
||||||
run: |
|
run: |
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt -y install cloc
|
sudo apt -y install cloc
|
||||||
|
|
||||||
- name: Print lines of code
|
- name: Print lines of code
|
||||||
run: cloc --include-lang TypeScript,JavaScript,HTML,Sass,CSS --vcs git
|
run: cloc --include-lang TypeScript,JavaScript,HTML,Sass,CSS --vcs git
|
||||||
|
|
||||||
|
|
||||||
setup:
|
setup:
|
||||||
runs-on: ubuntu-latest
|
name: Setup
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
outputs:
|
outputs:
|
||||||
package_version: ${{ steps.get_version.outputs.package_version }}
|
package_version: ${{ steps.retrieve-version.outputs.package_version }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
|
||||||
|
|
||||||
- name: Get Package Version
|
- name: Get Package Version
|
||||||
id: get_version
|
id: retrieve-version
|
||||||
shell: pwsh
|
|
||||||
run: |
|
run: |
|
||||||
$env:pkgVersion = (Get-Content -Raw -Path ./src/package.json | ConvertFrom-Json).version
|
PKG_VERSION=$(jq -r .version src/package.json)
|
||||||
echo "::set-output name=PACKAGE_VERSION::$env:pkgVersion"
|
echo "::set-output name=package_version::$PKG_VERSION"
|
||||||
|
|
||||||
|
|
||||||
cli:
|
cli:
|
||||||
runs-on: windows-latest
|
name: CLI
|
||||||
|
runs-on: windows-2019
|
||||||
needs: setup
|
needs: setup
|
||||||
env:
|
env:
|
||||||
PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||||
|
_WIN_PKG_FETCH_VERSION: 14.17.6
|
||||||
|
_WIN_PKG_VERSION: 3.2
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
|
||||||
|
|
||||||
- name: Setup Windows builder
|
- name: Setup Windows builder
|
||||||
run: |
|
run: |
|
||||||
@@ -56,7 +60,7 @@ jobs:
|
|||||||
- name: Set up Node
|
- name: Set up Node
|
||||||
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea
|
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea
|
||||||
with:
|
with:
|
||||||
node-version: '14.x'
|
node-version: '14'
|
||||||
|
|
||||||
- name: Update NPM
|
- name: Update NPM
|
||||||
run: |
|
run: |
|
||||||
@@ -71,17 +75,16 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
WIN_PKG: C:\Users\runneradmin\.pkg-cache\v3.0\fetched-v14.16.1-win-x64
|
WIN_PKG: C:\Users\runneradmin\.pkg-cache\v3.0\fetched-v14.16.1-win-x64
|
||||||
|
|
||||||
- name: get pkg-fetch
|
- name: Get pkg-fetch
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: |
|
run: |
|
||||||
cd $HOME
|
cd $HOME
|
||||||
$fetchedUrl = "https://github.com/vercel/pkg-fetch/releases/download/v3.0/node-v14.16.1-win-x64"
|
$fetchedUrl = "https://github.com/vercel/pkg-fetch/releases/download/v$env:_WIN_PKG_VERSION/node-v$env:_WIN_PKG_FETCH_VERSION-win-x64"
|
||||||
|
|
||||||
New-Item -ItemType directory -Path ./.pkg-cache
|
New-Item -ItemType directory -Path ./.pkg-cache
|
||||||
New-Item -ItemType directory -Path ./.pkg-cache/v3.0
|
New-Item -ItemType directory -Path ./.pkg-cache/v$env:_WIN_PKG_VERSION
|
||||||
Invoke-RestMethod -Uri $fetchedUrl -OutFile "./.pkg-cache/v3.0/fetched-v14.16.1-win-x64"
|
Invoke-RestMethod -Uri $fetchedUrl `
|
||||||
env:
|
-OutFile "./.pkg-cache/v$env:_WIN_PKG_VERSION/fetched-v$env:_WIN_PKG_FETCH_VERSION-win-x64"
|
||||||
WIN_PKG: C:\Users\runneradmin\.pkg-cache\v3.0\fetched-v14.16.1-win-x64
|
|
||||||
|
|
||||||
- name: Keytar
|
- name: Keytar
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
@@ -110,12 +113,48 @@ jobs:
|
|||||||
|
|
||||||
- name: Setup Version Info
|
- name: Setup Version Info
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: ./scripts/make-versioninfo.ps1
|
run: |
|
||||||
|
$major, $minor, $patch = $env:_PACKAGE_VERSION.split('.')
|
||||||
|
|
||||||
|
$versionInfo = @"
|
||||||
|
|
||||||
|
1 VERSIONINFO
|
||||||
|
FILEVERSION $major,$minor,$patch,0
|
||||||
|
PRODUCTVERSION $major,$minor,$patch,0
|
||||||
|
FILEOS 0x40004
|
||||||
|
FILETYPE 0x1
|
||||||
|
{
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
{
|
||||||
|
BLOCK "040904b0"
|
||||||
|
{
|
||||||
|
VALUE "CompanyName", "Bitwarden Inc."
|
||||||
|
VALUE "ProductName", "Bitwarden"
|
||||||
|
VALUE "FileDescription", "Bitwarden Directory Connector CLI"
|
||||||
|
VALUE "FileVersion", "$env:_PACKAGE_VERSION"
|
||||||
|
VALUE "ProductVersion", "$env:_PACKAGE_VERSION"
|
||||||
|
VALUE "OriginalFilename", "bwdc.exe"
|
||||||
|
VALUE "InternalName", "bwdc"
|
||||||
|
VALUE "LegalCopyright", "Copyright Bitwarden Inc."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
{
|
||||||
|
VALUE "Translation", 0x0409 0x04B0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"@
|
||||||
|
|
||||||
|
$versionInfo | Out-File ./version-info.rc
|
||||||
|
|
||||||
- name: Resource Hacker
|
- name: Resource Hacker
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
set PATH=%PATH%;C:\Program Files (x86)\Resource Hacker
|
set PATH=%PATH%;C:\Program Files (x86)\Resource Hacker
|
||||||
|
set WIN_PKG=C:\Users\runneradmin\.pkg-cache\v%_WIN_PKG_VERSION%\fetched-v%_WIN_PKG_FETCH_VERSION%-win-x64
|
||||||
|
set WIN_PKG_BUILT=C:\Users\runneradmin\.pkg-cache\v%_WIN_PKG_VERSION%\built-v%_WIN_PKG_FETCH_VERSION%-win-x64
|
||||||
|
|
||||||
ResourceHacker -open %WIN_PKG% -save %WIN_PKG% -action delete -mask ICONGROUP,1,
|
ResourceHacker -open %WIN_PKG% -save %WIN_PKG% -action delete -mask ICONGROUP,1,
|
||||||
ResourceHacker -open version-info.rc -save version-info.res -action compile
|
ResourceHacker -open version-info.rc -save version-info.res -action compile
|
||||||
ResourceHacker -open %WIN_PKG% -save %WIN_PKG% -action addoverwrite -resource version-info.res
|
ResourceHacker -open %WIN_PKG% -save %WIN_PKG% -action addoverwrite -resource version-info.res
|
||||||
@@ -129,79 +168,80 @@ jobs:
|
|||||||
- name: Zip
|
- name: Zip
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
7z a ./dist-cli/bwdc-windows-%PACKAGE_VERSION%.zip ./dist-cli/windows/bwdc.exe ./keytar/windows/keytar.node
|
7z a ./dist-cli/bwdc-windows-%_PACKAGE_VERSION%.zip ./dist-cli/windows/bwdc.exe ./keytar/windows/keytar.node
|
||||||
7z a ./dist-cli/bwdc-macos-%PACKAGE_VERSION%.zip ./dist-cli/macos/bwdc ./keytar/macos/keytar.node
|
7z a ./dist-cli/bwdc-macos-%_PACKAGE_VERSION%.zip ./dist-cli/macos/bwdc ./keytar/macos/keytar.node
|
||||||
7z a ./dist-cli/bwdc-linux-%PACKAGE_VERSION%.zip ./dist-cli/linux/bwdc ./keytar/linux/keytar.node
|
7z a ./dist-cli/bwdc-linux-%_PACKAGE_VERSION%.zip ./dist-cli/linux/bwdc ./keytar/linux/keytar.node
|
||||||
|
|
||||||
- name: Version Test
|
- name: Version Test
|
||||||
run: |
|
run: |
|
||||||
Expand-Archive -Path "./dist-cli/bwdc-windows-${env:PACKAGE_VERSION}.zip" -DestinationPath "./test/windows"
|
Expand-Archive -Path "./dist-cli/bwdc-windows-${env:_PACKAGE_VERSION}.zip" -DestinationPath "./test/windows"
|
||||||
$testVersion = Invoke-Expression '& ./test/windows/bwdc.exe -v'
|
$testVersion = Invoke-Expression '& ./test/windows/bwdc.exe -v'
|
||||||
echo "version: $env:PACKAGE_VERSION"
|
echo "version: $env:_PACKAGE_VERSION"
|
||||||
echo "testVersion: $testVersion"
|
echo "testVersion: $testVersion"
|
||||||
if($testVersion -ne $env:PACKAGE_VERSION) {
|
if($testVersion -ne $env:_PACKAGE_VERSION) {
|
||||||
Throw "Version test failed."
|
Throw "Version test failed."
|
||||||
}
|
}
|
||||||
|
|
||||||
- name: Create checksums
|
- name: Create checksums
|
||||||
run: |
|
run: |
|
||||||
checksum -f="./dist-cli/bwdc-windows-${env:PACKAGE_VERSION}.zip" `
|
checksum -f="./dist-cli/bwdc-windows-${env:_PACKAGE_VERSION}.zip" `
|
||||||
-t sha256 | Out-File ./dist-cli/bwdc-windows-sha256-${env:PACKAGE_VERSION}.txt
|
-t sha256 | Out-File ./dist-cli/bwdc-windows-sha256-${env:_PACKAGE_VERSION}.txt
|
||||||
checksum -f="./dist-cli/bwdc-macos-${env:PACKAGE_VERSION}.zip" `
|
checksum -f="./dist-cli/bwdc-macos-${env:_PACKAGE_VERSION}.zip" `
|
||||||
-t sha256 | Out-File ./dist-cli/bwdc-macos-sha256-${env:PACKAGE_VERSION}.txt
|
-t sha256 | Out-File ./dist-cli/bwdc-macos-sha256-${env:_PACKAGE_VERSION}.txt
|
||||||
checksum -f="./dist-cli/bwdc-linux-${env:PACKAGE_VERSION}.zip" `
|
checksum -f="./dist-cli/bwdc-linux-${env:_PACKAGE_VERSION}.zip" `
|
||||||
-t sha256 | Out-File ./dist-cli/bwdc-linux-sha256-${env:PACKAGE_VERSION}.txt
|
-t sha256 | Out-File ./dist-cli/bwdc-linux-sha256-${env:_PACKAGE_VERSION}.txt
|
||||||
|
|
||||||
- name: Upload windows zip to GitHub
|
- name: Upload Windows Zip to GitHub
|
||||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc'
|
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
|
|
||||||
with:
|
with:
|
||||||
name: bwdc-windows-${{ env.PACKAGE_VERSION }}.zip
|
name: bwdc-windows-${{ env._PACKAGE_VERSION }}.zip
|
||||||
path: ./dist-cli/bwdc-windows-${{ env.PACKAGE_VERSION }}.zip
|
path: ./dist-cli/bwdc-windows-${{ env._PACKAGE_VERSION }}.zip
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload mac zip to GitHub
|
- name: Upload Mac Zip to GitHub
|
||||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc'
|
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
|
|
||||||
with:
|
with:
|
||||||
name: bwdc-macos-${{ env.PACKAGE_VERSION }}.zip
|
name: bwdc-macos-${{ env._PACKAGE_VERSION }}.zip
|
||||||
path: ./dist-cli/bwdc-macos-${{ env.PACKAGE_VERSION }}.zip
|
path: ./dist-cli/bwdc-macos-${{ env._PACKAGE_VERSION }}.zip
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload linux zip to GitHub
|
- name: Upload Linux Zip to GitHub
|
||||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc'
|
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
|
|
||||||
with:
|
with:
|
||||||
name: bwdc-linux-${{ env.PACKAGE_VERSION }}.zip
|
name: bwdc-linux-${{ env._PACKAGE_VERSION }}.zip
|
||||||
path: ./dist-cli/bwdc-linux-${{ env.PACKAGE_VERSION }}.zip
|
path: ./dist-cli/bwdc-linux-${{ env._PACKAGE_VERSION }}.zip
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload windows checksum to GitHub
|
- name: Upload Windows checksum to GitHub
|
||||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc'
|
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
|
|
||||||
with:
|
with:
|
||||||
name: bwdc-windows-sha256-${{ env.PACKAGE_VERSION }}.txt
|
name: bwdc-windows-sha256-${{ env._PACKAGE_VERSION }}.txt
|
||||||
path: ./dist-cli/bwdc-windows-sha256-${{ env.PACKAGE_VERSION }}.txt
|
path: ./dist-cli/bwdc-windows-sha256-${{ env._PACKAGE_VERSION }}.txt
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload mac checksum to GitHub
|
- name: Upload Mac checksum to GitHub
|
||||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc'
|
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
|
|
||||||
with:
|
with:
|
||||||
name: bwdc-macos-sha256-${{ env.PACKAGE_VERSION }}.txt
|
name: bwdc-macos-sha256-${{ env._PACKAGE_VERSION }}.txt
|
||||||
path: ./dist-cli/bwdc-macos-sha256-${{ env.PACKAGE_VERSION }}.txt
|
path: ./dist-cli/bwdc-macos-sha256-${{ env._PACKAGE_VERSION }}.txt
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload linux checksum to GitHub
|
- name: Upload Linux checksum to GitHub
|
||||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc'
|
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
|
|
||||||
with:
|
with:
|
||||||
name: bwdc-linux-sha256-${{ env.PACKAGE_VERSION }}.txt
|
name: bwdc-linux-sha256-${{ env._PACKAGE_VERSION }}.txt
|
||||||
path: ./dist-cli/bwdc-linux-sha256-${{ env.PACKAGE_VERSION }}.txt
|
path: ./dist-cli/bwdc-linux-sha256-${{ env._PACKAGE_VERSION }}.txt
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
|
||||||
windows_gui:
|
windows-gui:
|
||||||
runs-on: windows-latest
|
name: Windows GUI
|
||||||
|
runs-on: windows-2019
|
||||||
needs: setup
|
needs: setup
|
||||||
env:
|
env:
|
||||||
PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||||
steps:
|
steps:
|
||||||
- name: Set up dotnet
|
- name: Set up .NET
|
||||||
uses: actions/setup-dotnet@a71d1eb2c86af85faa8c772c03fb365e377e45ea
|
uses: actions/setup-dotnet@a71d1eb2c86af85faa8c772c03fb365e377e45ea
|
||||||
with:
|
with:
|
||||||
dotnet-version: "3.1.x"
|
dotnet-version: "3.1.x"
|
||||||
@@ -209,7 +249,7 @@ jobs:
|
|||||||
- name: Set up Node
|
- name: Set up Node
|
||||||
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea
|
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea
|
||||||
with:
|
with:
|
||||||
node-version: '14.x'
|
node-version: '14'
|
||||||
|
|
||||||
- name: Update NPM
|
- name: Update NPM
|
||||||
run: |
|
run: |
|
||||||
@@ -228,27 +268,10 @@ jobs:
|
|||||||
dotnet --version
|
dotnet --version
|
||||||
|
|
||||||
- name: Install AST
|
- name: Install AST
|
||||||
shell: pwsh
|
uses: bitwarden/gh-actions/install-ast@f135c42c8596cb535c5bcb7523c0b2eef89709ac
|
||||||
run: |
|
|
||||||
cd $HOME
|
|
||||||
|
|
||||||
git clone https://github.com/vcsjones/AzureSignTool.git
|
|
||||||
cd AzureSignTool
|
|
||||||
$latest_head = $(git rev-parse HEAD)[0..9] -join ""
|
|
||||||
$latest_version = "0.0.0-g$latest_head"
|
|
||||||
|
|
||||||
Write-Host "--------"
|
|
||||||
Write-Host "git commit - $(git rev-parse HEAD)"
|
|
||||||
Write-Host "latest_head - $latest_head"
|
|
||||||
Write-Host "PACKAGE VERSION TO BUILD - $latest_version"
|
|
||||||
Write-Host "--------"
|
|
||||||
|
|
||||||
dotnet restore
|
|
||||||
dotnet pack --output ./nupkg
|
|
||||||
dotnet tool install --global --ignore-failed-sources --add-source ./nupkg --version $latest_version azuresigntool
|
|
||||||
|
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
|
||||||
|
|
||||||
- name: Install Node dependencies
|
- name: Install Node dependencies
|
||||||
run: npm install
|
run: npm install
|
||||||
@@ -269,31 +292,39 @@ jobs:
|
|||||||
- name: List Dist
|
- name: List Dist
|
||||||
run: dir ./dist
|
run: dir ./dist
|
||||||
|
|
||||||
- name: Publish Portable Exe to GitHub
|
- name: Upload Portable Executable to GitHub
|
||||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc'
|
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
|
|
||||||
with:
|
with:
|
||||||
name: Bitwarden-Connector-Portable-${{ env.PACKAGE_VERSION }}.exe
|
name: Bitwarden-Connector-Portable-${{ env._PACKAGE_VERSION }}.exe
|
||||||
path: ./dist/Bitwarden-Connector-Portable-${{ env.PACKAGE_VERSION }}.exe
|
path: ./dist/Bitwarden-Connector-Portable-${{ env._PACKAGE_VERSION }}.exe
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Publish Installer Exe to GitHub
|
- name: Upload Installer Executable to GitHub
|
||||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc'
|
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
|
|
||||||
with:
|
with:
|
||||||
name: Bitwarden-Connector-Installer-${{ env.PACKAGE_VERSION }}.exe
|
name: Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe
|
||||||
path: ./dist/Bitwarden-Connector-Installer-${{ env.PACKAGE_VERSION }}.exe
|
path: ./dist/Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
- name: Upload latest auto-update artifact
|
||||||
|
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||||
|
with:
|
||||||
|
name: latest.yml
|
||||||
|
path: ./dist/latest.yml
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
|
||||||
linux:
|
linux:
|
||||||
runs-on: ubuntu-latest
|
name: Linux
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
needs: setup
|
needs: setup
|
||||||
env:
|
env:
|
||||||
PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Node
|
- name: Set up Node
|
||||||
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea
|
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea
|
||||||
with:
|
with:
|
||||||
node-version: '14.x'
|
node-version: '14'
|
||||||
|
|
||||||
- name: Update NPM
|
- name: Update NPM
|
||||||
run: |
|
run: |
|
||||||
@@ -307,39 +338,47 @@ jobs:
|
|||||||
- name: Set up environment
|
- name: Set up environment
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get -y install pkg-config libxss-dev libsecret-1-dev
|
sudo apt-get -y install pkg-config libxss-dev libsecret-1-dev
|
||||||
sudo apt-get -y install rpm
|
sudo apt-get -y install rpm
|
||||||
|
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
|
||||||
|
|
||||||
- name: npm install
|
- name: NPM Install
|
||||||
run: npm install
|
run: npm install
|
||||||
|
|
||||||
- name: npm rebuild
|
- name: NPM Rebuild
|
||||||
run: npm run rebuild
|
run: npm run rebuild
|
||||||
|
|
||||||
- name: npm package
|
- name: NPM Package
|
||||||
run: npm run dist:lin
|
run: npm run dist:lin
|
||||||
|
|
||||||
- name: Publish AppImage
|
- name: Upload AppImage
|
||||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc'
|
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
|
|
||||||
with:
|
with:
|
||||||
name: Bitwarden-Connector-${{ env.PACKAGE_VERSION }}-x86_64.AppImage
|
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-x86_64.AppImage
|
||||||
path: ./dist/Bitwarden-Connector-${{ env.PACKAGE_VERSION }}-x86_64.AppImage
|
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-x86_64.AppImage
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
- name: Upload latest auto-update artifact
|
||||||
|
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||||
|
with:
|
||||||
|
name: latest-linux.yml
|
||||||
|
path: ./dist/latest-linux.yml
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
|
||||||
macos:
|
macos:
|
||||||
runs-on: macos-latest
|
name: MacOS
|
||||||
|
runs-on: macos-11
|
||||||
needs: setup
|
needs: setup
|
||||||
env:
|
env:
|
||||||
PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Node
|
- name: Set up Node
|
||||||
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea
|
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea
|
||||||
with:
|
with:
|
||||||
node-version: '14.x'
|
node-version: '14'
|
||||||
|
|
||||||
- name: Update NPM
|
- name: Update NPM
|
||||||
run: |
|
run: |
|
||||||
@@ -354,32 +393,58 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
node --version
|
node --version
|
||||||
npm --version
|
npm --version
|
||||||
Write-Output "GitHub ref: $env:GITHUB_REF"
|
echo "GitHub ref: $GITHUB_REF"
|
||||||
Write-Output "GitHub event: $env:GITHUB_EVENT"
|
echo "GitHub event: $GITHUB_EVENT"
|
||||||
shell: pwsh
|
shell: bash
|
||||||
env:
|
|
||||||
GITHUB_REF: ${{ github.ref }}
|
|
||||||
GITHUB_EVENT: ${{ github.event_name }}
|
|
||||||
|
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
|
||||||
|
|
||||||
- name: Decrypt secrets
|
- name: Decrypt secrets
|
||||||
run: ./.github/scripts/macos/decrypt-secrets.ps1
|
|
||||||
shell: pwsh
|
|
||||||
env:
|
env:
|
||||||
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }}
|
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
mkdir -p $HOME/secrets
|
||||||
|
|
||||||
|
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||||
|
--output "$HOME/secrets/devid-app-cert.p12" \
|
||||||
|
"$GITHUB_WORKSPACE/.github/secrets/devid-app-cert.p12.gpg"
|
||||||
|
|
||||||
|
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||||
|
--output "$HOME/secrets/devid-installer-cert.p12" \
|
||||||
|
"$GITHUB_WORKSPACE/.github/secrets/devid-installer-cert.p12.gpg"
|
||||||
|
|
||||||
|
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||||
|
--output "$HOME/secrets/macdev-cert.p12" \
|
||||||
|
"$GITHUB_WORKSPACE/.github/secrets/macdev-cert.p12.gpg"
|
||||||
|
|
||||||
- name: Set up keychain
|
- name: Set up keychain
|
||||||
run: ./.github/scripts/macos/setup-keychain.ps1
|
|
||||||
shell: pwsh
|
|
||||||
env:
|
env:
|
||||||
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
||||||
DEVID_CERT_PASSWORD: ${{ secrets.DEVID_CERT_PASSWORD }}
|
DEVID_CERT_PASSWORD: ${{ secrets.DEVID_CERT_PASSWORD }}
|
||||||
MACDEV_CERT_PASSWORD: ${{ secrets.MACDEV_CERT_PASSWORD }}
|
MACDEV_CERT_PASSWORD: ${{ secrets.MACDEV_CERT_PASSWORD }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
security create-keychain -p $KEYCHAIN_PASSWORD build.keychain
|
||||||
|
security default-keychain -s build.keychain
|
||||||
|
security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain
|
||||||
|
security set-keychain-settings -lut 1200 build.keychain
|
||||||
|
security import "$HOME/secrets/devid-app-cert.p12" -k build.keychain -P $DEVID_CERT_PASSWORD \
|
||||||
|
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
|
||||||
|
security import "$HOME/secrets/devid-installer-cert.p12" -k build.keychain -P $DEVID_CERT_PASSWORD \
|
||||||
|
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
|
||||||
|
security import "$HOME/secrets/macdev-cert.p12" -k build.keychain -P $MACDEV_CERT_PASSWORD \
|
||||||
|
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
|
||||||
|
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain
|
||||||
|
|
||||||
- name: Load package version
|
- name: Load package version
|
||||||
run: ./.github/scripts/load-version.ps1
|
run: |
|
||||||
|
$rootPath = $env:GITHUB_WORKSPACE;
|
||||||
|
$packageVersion = (Get-Content -Raw -Path $rootPath\src\package.json | ConvertFrom-Json).version;
|
||||||
|
|
||||||
|
Write-Output "Setting package version to $packageVersion";
|
||||||
|
Write-Output "PACKAGE_VERSION=$packageVersion" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append;
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
|
|
||||||
- name: Install Node dependencies
|
- name: Install Node dependencies
|
||||||
@@ -388,27 +453,94 @@ jobs:
|
|||||||
- name: Run linter
|
- name: Run linter
|
||||||
run: npm run lint
|
run: npm run lint
|
||||||
|
|
||||||
- name: Build application (dev)
|
- name: Build application
|
||||||
if: github.ref != 'refs/heads/master'
|
|
||||||
run: npm run build
|
|
||||||
|
|
||||||
- name: Build application (dist)
|
|
||||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc'
|
|
||||||
run: npm run dist:mac
|
run: npm run dist:mac
|
||||||
env:
|
env:
|
||||||
APPLE_ID_USERNAME: ${{ secrets.APPLE_ID_USERNAME }}
|
APPLE_ID_USERNAME: ${{ secrets.APPLE_ID_USERNAME }}
|
||||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Rename Zip Artifact
|
||||||
|
run: |
|
||||||
|
cd dist
|
||||||
|
mv "Bitwarden Directory Connector-${{ env._PACKAGE_VERSION }}-mac.zip" \
|
||||||
|
"Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-mac.zip"
|
||||||
|
|
||||||
- name: Upload .zip artifact
|
- name: Upload .zip artifact
|
||||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc'
|
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
|
|
||||||
with:
|
with:
|
||||||
name: Bitwarden-Connector-${{ env.PACKAGE_VERSION }}-mac.zip
|
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-mac.zip
|
||||||
path: ./dist/Bitwarden-Connector-${{ env.PACKAGE_VERSION }}-mac.zip
|
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-mac.zip
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload .dmg artifact
|
- name: Upload .dmg artifact
|
||||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc'
|
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||||
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700
|
|
||||||
with:
|
with:
|
||||||
name: Bitwarden-Connector-${{ env.PACKAGE_VERSION }}.dmg
|
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg
|
||||||
path: ./dist/Bitwarden-Connector-${{ env.PACKAGE_VERSION }}.dmg
|
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
- name: Upload latest auto-update artifact
|
||||||
|
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3
|
||||||
|
with:
|
||||||
|
name: latest-mac.yml
|
||||||
|
path: ./dist/latest-mac.yml
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
|
||||||
|
check-failures:
|
||||||
|
name: Check for failures
|
||||||
|
if: always()
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
needs:
|
||||||
|
- cloc
|
||||||
|
- setup
|
||||||
|
- cli
|
||||||
|
- windows-gui
|
||||||
|
- linux
|
||||||
|
- macos
|
||||||
|
steps:
|
||||||
|
- name: Check if any job failed
|
||||||
|
if: ${{ (github.ref == 'refs/heads/master') || (github.ref == 'refs/heads/rc') }}
|
||||||
|
env:
|
||||||
|
CLOC_STATUS: ${{ needs.cloc.result }}
|
||||||
|
SETUP_STATUS: ${{ needs.setup.result }}
|
||||||
|
CLI_STATUS: ${{ needs.cli.result }}
|
||||||
|
WINDOWS_GUI_STATUS: ${{ needs.windows-gui.result }}
|
||||||
|
LINUX_STATUS: ${{ needs.linux.result }}
|
||||||
|
MACOS_STATUS: ${{ needs.macos.result }}
|
||||||
|
run: |
|
||||||
|
if [ "$CLOC_STATUS" = "failure" ]; then
|
||||||
|
exit 1
|
||||||
|
elif [ "$SETUP_STATUS" = "failure" ]; then
|
||||||
|
exit 1
|
||||||
|
elif [ "$CLI_STATUS" = "failure" ]; then
|
||||||
|
exit 1
|
||||||
|
elif [ "$WINDOWS_GUI_STATUS" = "failure" ]; then
|
||||||
|
exit 1
|
||||||
|
elif [ "$LINUX_STATUS" = "failure" ]; then
|
||||||
|
exit 1
|
||||||
|
elif [ "$MACOS_STATUS" = "failure" ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Login to Azure - Prod Subscription
|
||||||
|
uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a
|
||||||
|
if: failure()
|
||||||
|
with:
|
||||||
|
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
|
||||||
|
|
||||||
|
- name: Retrieve secrets
|
||||||
|
id: retrieve-secrets
|
||||||
|
uses: Azure/get-keyvault-secrets@80ccd3fafe5662407cc2e55f202ee34bfff8c403
|
||||||
|
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
|
||||||
|
if: failure()
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }}
|
||||||
|
with:
|
||||||
|
status: ${{ job.status }}
|
||||||
|
|||||||
455
.github/workflows/release.yml
vendored
455
.github/workflows/release.yml
vendored
@@ -1,425 +1,78 @@
|
|||||||
|
---
|
||||||
name: Release
|
name: Release
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
|
||||||
release_tag_name_input:
|
|
||||||
description: "Release Tag Name <X.X.X>"
|
|
||||||
required: true
|
|
||||||
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
setup:
|
setup:
|
||||||
runs-on: ubuntu-latest
|
name: Setup
|
||||||
outputs:
|
runs-on: ubuntu-20.04
|
||||||
package_version: ${{ steps.create_tags.outputs.package_version }}
|
|
||||||
tag_version: ${{ steps.create_tags.outputs.tag_version }}
|
|
||||||
release_upload_url: ${{ steps.create_release.outputs.upload_url }}
|
|
||||||
steps:
|
steps:
|
||||||
- name: Branch check
|
- name: Branch check
|
||||||
run: |
|
run: |
|
||||||
if [[ "$GITHUB_REF" != "refs/heads/rc" ]]; then
|
if [[ "$GITHUB_REF" != "refs/heads/release" ]]; then
|
||||||
echo "==================================="
|
echo "==================================="
|
||||||
echo "[!] Can only release from rc branch"
|
echo "[!] Can only release from the 'release' branch"
|
||||||
echo "==================================="
|
echo "==================================="
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
||||||
|
with:
|
||||||
|
ref: release
|
||||||
|
|
||||||
- name: Create Release Vars
|
- name: Retrieve Directory Connector release version
|
||||||
id: create_tags
|
id: retrieve-version
|
||||||
run: |
|
run: |
|
||||||
case "${RELEASE_TAG_NAME_INPUT:0:1}" in
|
PKG_VERSION=$(jq -r .version src/package.json)
|
||||||
v)
|
echo "::set-output name=package_version::$PKG_VERSION"
|
||||||
echo "RELEASE_NAME=${RELEASE_TAG_NAME_INPUT:1}" >> $GITHUB_ENV
|
|
||||||
echo "RELEASE_TAG_NAME=$RELEASE_TAG_NAME_INPUT" >> $GITHUB_ENV
|
|
||||||
echo "::set-output name=package_version::${RELEASE_TAG_NAME_INPUT:1}"
|
|
||||||
echo "::set-output name=tag_version::$RELEASE_TAG_NAME_INPUT"
|
|
||||||
;;
|
|
||||||
[0-9])
|
|
||||||
echo "RELEASE_NAME=$RELEASE_TAG_NAME_INPUT" >> $GITHUB_ENV
|
|
||||||
echo "RELEASE_TAG_NAME=v$RELEASE_TAG_NAME_INPUT" >> $GITHUB_ENV
|
|
||||||
echo "::set-output name=package_version::$RELEASE_TAG_NAME_INPUT"
|
|
||||||
echo "::set-output name=tag_version::v$RELEASE_TAG_NAME_INPUT"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
env:
|
|
||||||
RELEASE_TAG_NAME_INPUT: ${{ github.event.inputs.release_tag_name_input }}
|
|
||||||
|
|
||||||
- name: Create Draft Release
|
- name: Check to make sure Mobile release version has been bumped
|
||||||
id: create_release
|
|
||||||
uses: actions/create-release@0cb9c9b65d5d1901c1f53e5e66eaf4afd303e70e
|
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
latest_ver=$(hub release -L 1 -f '%T')
|
||||||
|
latest_ver=${latest_ver:1}
|
||||||
|
echo "Latest version: $latest_ver"
|
||||||
|
ver=${{ steps.retrieve-version.outputs.package_version }}
|
||||||
|
echo "Version: $ver"
|
||||||
|
if [ "$latest_ver" = "$ver" ]; then
|
||||||
|
echo "Version has not been bumped!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Download all artifacts
|
||||||
|
uses: bitwarden/gh-actions/download-artifacts@23433be15ed6fd046ce12b6889c5184a8d9c8783
|
||||||
with:
|
with:
|
||||||
tag_name: ${{ env.RELEASE_TAG_NAME }}
|
workflow: build.yml
|
||||||
release_name: ${{ env.RELEASE_NAME }}
|
workflow_conclusion: success
|
||||||
|
branch: release
|
||||||
|
|
||||||
|
- name: Create release
|
||||||
|
uses: ncipollo/release-action@95215a3cb6e6a1908b3c44e00b4fdb15548b1e09 # v2.8.5
|
||||||
|
env:
|
||||||
|
PKG_VERSION: ${{ steps.retrieve-version.outputs.package_version }}
|
||||||
|
with:
|
||||||
|
artifacts: "./bwdc-windows-${{ env.PKG_VERSION }}.zip,
|
||||||
|
./bwdc-macos-${{ env.PKG_VERSION }}.zip,
|
||||||
|
./bwdc-linux-${{ env.PKG_VERSION }}.zip,
|
||||||
|
./bwdc-windows-sha256-${{ env.PKG_VERSION }}.txt,
|
||||||
|
./bwdc-macos-sha256-${{ env.PKG_VERSION }}.txt,
|
||||||
|
./bwdc-linux-sha256-${{ env.PKG_VERSION }}.txt,
|
||||||
|
./Bitwarden-Connector-Portable-${{ env.PKG_VERSION }}.exe,
|
||||||
|
./Bitwarden-Connector-Installer-${{ env.PKG_VERSION }}.exe,
|
||||||
|
./Bitwarden-Connector-${{ env.PKG_VERSION }}-x86_64.AppImage,
|
||||||
|
./Bitwarden-Connector-${{ env.PKG_VERSION }}-mac.zip,
|
||||||
|
./Bitwarden-Connector-${{ env.PKG_VERSION }}.dmg,
|
||||||
|
./latest-linux.yml,
|
||||||
|
./latest-mac.yml,
|
||||||
|
./latest.yml"
|
||||||
|
commit: ${{ github.sha }}
|
||||||
|
tag: v${{ env.PKG_VERSION }}
|
||||||
|
name: Version ${{ env.PKG_VERSION }}
|
||||||
|
body: "<insert release notes here>"
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
draft: true
|
draft: true
|
||||||
prerelease: false
|
|
||||||
|
|
||||||
|
|
||||||
cli:
|
|
||||||
runs-on: windows-latest
|
|
||||||
needs: setup
|
|
||||||
env:
|
|
||||||
PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repo
|
|
||||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
|
||||||
|
|
||||||
- name: Setup Windows builder
|
|
||||||
run: |
|
|
||||||
choco install checksum --no-progress
|
|
||||||
choco install reshack --no-progress
|
|
||||||
|
|
||||||
- name: Set up Node
|
|
||||||
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea
|
|
||||||
with:
|
|
||||||
node-version: '14.x'
|
|
||||||
|
|
||||||
- name: Update NPM
|
|
||||||
run: |
|
|
||||||
npm install -g npm@7
|
|
||||||
npm install -g node-gyp
|
|
||||||
node-gyp install $(node -v)
|
|
||||||
|
|
||||||
- name: Set VER_INFO
|
|
||||||
run: |
|
|
||||||
echo "WIN_PKG=$env:WIN_PKG" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
|
||||||
env:
|
|
||||||
WIN_PKG: C:\Users\runneradmin\.pkg-cache\v3.0\fetched-v14.16.1-win-x64
|
|
||||||
|
|
||||||
- name: get pkg-fetch
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
cd $HOME
|
|
||||||
$fetchedUrl = "https://github.com/vercel/pkg-fetch/releases/download/v3.0/node-v14.16.1-win-x64"
|
|
||||||
|
|
||||||
New-Item -ItemType directory -Path ./.pkg-cache
|
|
||||||
New-Item -ItemType directory -Path ./.pkg-cache/v3.0
|
|
||||||
Invoke-RestMethod -Uri $fetchedUrl -OutFile "./.pkg-cache/v3.0/fetched-v14.16.1-win-x64"
|
|
||||||
env:
|
|
||||||
WIN_PKG: C:\Users\runneradmin\.pkg-cache\v3.0\fetched-v14.16.1-win-x64
|
|
||||||
|
|
||||||
- name: Keytar
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
$keytarVersion = (Get-Content -Raw -Path ./src/package.json | ConvertFrom-Json).dependencies.keytar
|
|
||||||
$nodeModVersion = node -e "console.log(process.config.variables.node_module_version)"
|
|
||||||
$keytarTar = "keytar-v${keytarVersion}-node-v${nodeModVersion}-{0}-x64.tar"
|
|
||||||
$keytarTarGz = "${keytarTar}.gz"
|
|
||||||
$keytarUrl = "https://github.com/atom/node-keytar/releases/download/v${keytarVersion}/${keytarTarGz}"
|
|
||||||
|
|
||||||
New-Item -ItemType directory -Path ./keytar/macos | Out-Null
|
|
||||||
New-Item -ItemType directory -Path ./keytar/linux | Out-Null
|
|
||||||
New-Item -ItemType directory -Path ./keytar/windows | Out-Null
|
|
||||||
|
|
||||||
Invoke-RestMethod -Uri $($keytarUrl -f "darwin") -OutFile "./keytar/macos/$($keytarTarGz -f "darwin")"
|
|
||||||
Invoke-RestMethod -Uri $($keytarUrl -f "linux") -OutFile "./keytar/linux/$($keytarTarGz -f "linux")"
|
|
||||||
Invoke-RestMethod -Uri $($keytarUrl -f "win32") -OutFile "./keytar/windows/$($keytarTarGz -f "win32")"
|
|
||||||
|
|
||||||
7z e "./keytar/macos/$($keytarTarGz -f "darwin")" -o"./keytar/macos"
|
|
||||||
7z e "./keytar/linux/$($keytarTarGz -f "linux")" -o"./keytar/linux"
|
|
||||||
7z e "./keytar/windows/$($keytarTarGz -f "win32")" -o"./keytar/windows"
|
|
||||||
|
|
||||||
7z e "./keytar/macos/$($keytarTar -f "darwin")" -o"./keytar/macos"
|
|
||||||
7z e "./keytar/linux/$($keytarTar -f "linux")" -o"./keytar/linux"
|
|
||||||
7z e "./keytar/windows/$($keytarTar -f "win32")" -o"./keytar/windows"
|
|
||||||
|
|
||||||
- name: Setup Version Info
|
|
||||||
shell: pwsh
|
|
||||||
run: ./scripts/make-versioninfo.ps1
|
|
||||||
|
|
||||||
- name: Resource Hacker
|
|
||||||
shell: cmd
|
|
||||||
run: |
|
|
||||||
set PATH=%PATH%;C:\Program Files (x86)\Resource Hacker
|
|
||||||
ResourceHacker -open %WIN_PKG% -save %WIN_PKG% -action delete -mask ICONGROUP,1,
|
|
||||||
ResourceHacker -open version-info.rc -save version-info.res -action compile
|
|
||||||
ResourceHacker -open %WIN_PKG% -save %WIN_PKG% -action addoverwrite -resource version-info.res
|
|
||||||
|
|
||||||
- name: Install
|
|
||||||
run: npm install
|
|
||||||
|
|
||||||
- name: Package CLI
|
|
||||||
run: npm run dist:cli
|
|
||||||
|
|
||||||
- name: Zip
|
|
||||||
shell: cmd
|
|
||||||
run: |
|
|
||||||
7z a ./dist-cli/bwdc-windows-%PACKAGE_VERSION%.zip ./dist-cli/windows/bwdc.exe ./keytar/windows/keytar.node
|
|
||||||
7z a ./dist-cli/bwdc-macos-%PACKAGE_VERSION%.zip ./dist-cli/macos/bwdc ./keytar/macos/keytar.node
|
|
||||||
7z a ./dist-cli/bwdc-linux-%PACKAGE_VERSION%.zip ./dist-cli/linux/bwdc ./keytar/linux/keytar.node
|
|
||||||
|
|
||||||
- name: Version Test
|
|
||||||
run: |
|
|
||||||
Expand-Archive -Path "./dist-cli/bwdc-windows-${env:PACKAGE_VERSION}.zip" -DestinationPath "./test/windows"
|
|
||||||
$testVersion = Invoke-Expression '& ./test/windows/bwdc.exe -v'
|
|
||||||
echo "version: $env:PACKAGE_VERSION"
|
|
||||||
echo "testVersion: $testVersion"
|
|
||||||
if($testVersion -ne $env:PACKAGE_VERSION) {
|
|
||||||
Throw "Version test failed."
|
|
||||||
}
|
|
||||||
|
|
||||||
- name: Create checksums
|
|
||||||
run: |
|
|
||||||
checksum -f="./dist-cli/bwdc-windows-${env:PACKAGE_VERSION}.zip" `
|
|
||||||
-t sha256 | Out-File ./dist-cli/bwdc-windows-sha256-${env:PACKAGE_VERSION}.txt
|
|
||||||
checksum -f="./dist-cli/bwdc-macos-${env:PACKAGE_VERSION}.zip" `
|
|
||||||
-t sha256 | Out-File ./dist-cli/bwdc-macos-sha256-${env:PACKAGE_VERSION}.txt
|
|
||||||
checksum -f="./dist-cli/bwdc-linux-${env:PACKAGE_VERSION}.zip" `
|
|
||||||
-t sha256 | Out-File ./dist-cli/bwdc-linux-sha256-${env:PACKAGE_VERSION}.txt
|
|
||||||
|
|
||||||
- name: upload windows zip release asset
|
|
||||||
uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
upload_url: ${{ needs.setup.outputs.release_upload_url }}
|
|
||||||
asset_path: ./dist-cli/bwdc-windows-${{ env.PACKAGE_VERSION }}.zip
|
|
||||||
asset_name: bwdc-windows-${{ env.PACKAGE_VERSION }}.zip
|
|
||||||
asset_content_type: application/zip
|
|
||||||
|
|
||||||
- name: upload macos zip release asset
|
|
||||||
uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
upload_url: ${{ needs.setup.outputs.release_upload_url }}
|
|
||||||
asset_path: ./dist-cli/bwdc-macos-${{ env.PACKAGE_VERSION }}.zip
|
|
||||||
asset_name: bwdc-macos-${{ env.PACKAGE_VERSION }}.zip
|
|
||||||
asset_content_type: application/zip
|
|
||||||
|
|
||||||
- name: upload linux zip release asset
|
|
||||||
uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
upload_url: ${{ needs.setup.outputs.release_upload_url }}
|
|
||||||
asset_path: ./dist-cli/bwdc-linux-${{ env.PACKAGE_VERSION }}.zip
|
|
||||||
asset_name: bwdc-linux-${{ env.PACKAGE_VERSION }}.zip
|
|
||||||
asset_content_type: application/zip
|
|
||||||
|
|
||||||
- name: upload windows checksum release asset
|
|
||||||
uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
upload_url: ${{ needs.setup.outputs.release_upload_url }}
|
|
||||||
asset_path: ./dist-cli/bwdc-windows-sha256-${{ env.PACKAGE_VERSION }}.txt
|
|
||||||
asset_name: bwdc-windows-sha256-${{ env.PACKAGE_VERSION }}.txt
|
|
||||||
asset_content_type: text/plain
|
|
||||||
|
|
||||||
- name: upload macos checksum release asset
|
|
||||||
uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
upload_url: ${{ needs.setup.outputs.release_upload_url }}
|
|
||||||
asset_path: ./dist-cli/bwdc-macos-sha256-${{ env.PACKAGE_VERSION }}.txt
|
|
||||||
asset_name: bwdc-macos-sha256-${{ env.PACKAGE_VERSION }}.txt
|
|
||||||
asset_content_type: text/plain
|
|
||||||
|
|
||||||
- name: upload linux checksum release asset
|
|
||||||
uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
upload_url: ${{ needs.setup.outputs.release_upload_url }}
|
|
||||||
asset_path: ./dist-cli/bwdc-linux-sha256-${{ env.PACKAGE_VERSION }}.txt
|
|
||||||
asset_name: bwdc-linux-sha256-${{ env.PACKAGE_VERSION }}.txt
|
|
||||||
asset_content_type: text/plain
|
|
||||||
|
|
||||||
|
|
||||||
windows-gui:
|
|
||||||
runs-on: windows-latest
|
|
||||||
needs: setup
|
|
||||||
env:
|
|
||||||
PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
|
||||||
steps:
|
|
||||||
- name: Set up dotnet
|
|
||||||
uses: actions/setup-dotnet@a71d1eb2c86af85faa8c772c03fb365e377e45ea
|
|
||||||
with:
|
|
||||||
dotnet-version: "3.1.x"
|
|
||||||
|
|
||||||
- name: Set up Node
|
|
||||||
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea
|
|
||||||
with:
|
|
||||||
node-version: '14.x'
|
|
||||||
|
|
||||||
- name: Update NPM
|
|
||||||
run: |
|
|
||||||
npm install -g npm@7
|
|
||||||
npm install -g node-gyp
|
|
||||||
node-gyp install $(node -v)
|
|
||||||
|
|
||||||
- name: Set Node options
|
|
||||||
run: echo "NODE_OPTIONS=--max_old_space_size=4096" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
|
||||||
shell: pwsh
|
|
||||||
|
|
||||||
- name: Print environment
|
|
||||||
run: |
|
|
||||||
node --version
|
|
||||||
npm --version
|
|
||||||
dotnet --version
|
|
||||||
|
|
||||||
- name: Install AST
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
cd $HOME
|
|
||||||
git clone https://github.com/vcsjones/AzureSignTool.git
|
|
||||||
cd AzureSignTool
|
|
||||||
$latest_head = $(git rev-parse HEAD)[0..9] -join ""
|
|
||||||
$latest_version = "0.0.0-g$latest_head"
|
|
||||||
Write-Host "--------"
|
|
||||||
Write-Host "git commit - $(git rev-parse HEAD)"
|
|
||||||
Write-Host "latest_head - $latest_head"
|
|
||||||
Write-Host "PACKAGE VERSION TO BUILD - $latest_version"
|
|
||||||
Write-Host "--------"
|
|
||||||
dotnet restore
|
|
||||||
dotnet pack --output ./nupkg
|
|
||||||
dotnet tool install --global --ignore-failed-sources --add-source ./nupkg --version $latest_version azuresigntool
|
|
||||||
cd $HOME
|
|
||||||
|
|
||||||
- name: Checkout repo
|
|
||||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
|
||||||
|
|
||||||
- name: Install Node dependencies
|
|
||||||
run: npm install
|
|
||||||
|
|
||||||
- name: Run linter
|
|
||||||
run: npm run lint
|
|
||||||
|
|
||||||
- name: npm rebuild
|
|
||||||
run: npm run rebuild
|
|
||||||
|
|
||||||
- name: Build & Sign
|
|
||||||
run: |
|
|
||||||
npm run publish:win
|
|
||||||
env:
|
|
||||||
ELECTRON_BUILDER_SIGN: 1
|
|
||||||
SIGNING_VAULT_URL: ${{ secrets.SIGNING_VAULT_URL }}
|
|
||||||
SIGNING_CLIENT_ID: ${{ secrets.SIGNING_CLIENT_ID }}
|
|
||||||
SIGNING_TENANT_ID: ${{ secrets.SIGNING_TENANT_ID }}
|
|
||||||
SIGNING_CLIENT_SECRET: ${{ secrets.SIGNING_CLIENT_SECRET }}
|
|
||||||
SIGNING_CERT_NAME: ${{ secrets.SIGNING_CERT_NAME }}
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
|
|
||||||
linux:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: setup
|
|
||||||
env:
|
|
||||||
PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
|
||||||
steps:
|
|
||||||
- name: Set up Node
|
|
||||||
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea
|
|
||||||
with:
|
|
||||||
node-version: '14.x'
|
|
||||||
|
|
||||||
- name: Update NPM
|
|
||||||
run: |
|
|
||||||
npm install -g npm@7
|
|
||||||
npm install -g node-gyp
|
|
||||||
node-gyp install $(node -v)
|
|
||||||
|
|
||||||
- name: Set Node options
|
|
||||||
run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Set up environment
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get -y install pkg-config libxss-dev libsecret-1-dev
|
|
||||||
sudo apt-get -y install rpm
|
|
||||||
|
|
||||||
- name: Checkout repo
|
|
||||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
|
||||||
|
|
||||||
- name: Set PACKAGE_VERSION
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
$env:pkgVersion = (Get-Content -Raw -Path ./src/package.json | ConvertFrom-Json).version
|
|
||||||
echo "PACKAGE_VERSION=$env:pkgVersion" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
|
||||||
echo "version: $env:pkgVersion"
|
|
||||||
|
|
||||||
- name: npm install
|
|
||||||
run: npm install
|
|
||||||
|
|
||||||
- name: npm rebuild
|
|
||||||
run: npm run rebuild
|
|
||||||
|
|
||||||
- name: npm package
|
|
||||||
run: npm run publish:lin
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
|
|
||||||
macos:
|
|
||||||
runs-on: macos-latest
|
|
||||||
needs: setup
|
|
||||||
env:
|
|
||||||
PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
|
||||||
steps:
|
|
||||||
- name: Set up Node
|
|
||||||
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea
|
|
||||||
with:
|
|
||||||
node-version: '14.x'
|
|
||||||
|
|
||||||
- name: Update NPM
|
|
||||||
run: |
|
|
||||||
npm install -g npm@7
|
|
||||||
npm install -g node-gyp
|
|
||||||
node-gyp install $(node -v)
|
|
||||||
|
|
||||||
- name: Set Node options
|
|
||||||
run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Print environment
|
|
||||||
run: |
|
|
||||||
node --version
|
|
||||||
npm --version
|
|
||||||
Write-Output "GitHub ref: $env:GITHUB_REF"
|
|
||||||
Write-Output "GitHub event: $env:GITHUB_EVENT"
|
|
||||||
shell: pwsh
|
|
||||||
env:
|
|
||||||
GITHUB_REF: ${{ github.ref }}
|
|
||||||
GITHUB_EVENT: ${{ github.event_name }}
|
|
||||||
|
|
||||||
- name: Checkout repo
|
|
||||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
|
||||||
|
|
||||||
- name: Decrypt secrets
|
|
||||||
run: ./.github/scripts/macos/decrypt-secrets.ps1
|
|
||||||
shell: pwsh
|
|
||||||
env:
|
|
||||||
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }}
|
|
||||||
|
|
||||||
- name: Set up keychain
|
|
||||||
run: ./.github/scripts/macos/setup-keychain.ps1
|
|
||||||
shell: pwsh
|
|
||||||
env:
|
|
||||||
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
|
||||||
DEVID_CERT_PASSWORD: ${{ secrets.DEVID_CERT_PASSWORD }}
|
|
||||||
MACDEV_CERT_PASSWORD: ${{ secrets.MACDEV_CERT_PASSWORD }}
|
|
||||||
|
|
||||||
- name: Load package version
|
|
||||||
run: ./.github/scripts/load-version.ps1
|
|
||||||
shell: pwsh
|
|
||||||
|
|
||||||
- name: Install Node dependencies
|
|
||||||
run: npm install
|
|
||||||
|
|
||||||
- name: Run linter
|
|
||||||
run: npm run lint
|
|
||||||
|
|
||||||
- name: Build application (dist)
|
|
||||||
run: npm run publish:mac
|
|
||||||
env:
|
|
||||||
APPLE_ID_USERNAME: ${{ secrets.APPLE_ID_USERNAME }}
|
|
||||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ We provide detailed documentation and examples for using the Directory Connector
|
|||||||
|
|
||||||
**Requirements**
|
**Requirements**
|
||||||
|
|
||||||
- [Node.js](https://nodejs.org/)
|
- [Node.js](https://nodejs.org) v14
|
||||||
- Windows users: To compile the native node modules used in the app you will need the Visual C++ toolset, available through the standard Visual Studio installer (recommended) or by installing [`windows-build-tools`](https://github.com/felixrieseberg/windows-build-tools) through `npm`. See more at [Compiling native Addon modules](https://github.com/Microsoft/nodejs-guidelines/blob/master/windows-environment.md#compiling-native-addon-modules).
|
- Windows users: To compile the native node modules used in the app you will need the Visual C++ toolset, available through the standard Visual Studio installer (recommended) or by installing [`windows-build-tools`](https://github.com/felixrieseberg/windows-build-tools) through `npm`. See more at [Compiling native Addon modules](https://github.com/Microsoft/nodejs-guidelines/blob/master/windows-environment.md#compiling-native-addon-modules).
|
||||||
|
|
||||||
**Run the app**
|
**Run the app**
|
||||||
|
|||||||
25
gulpfile.js
25
gulpfile.js
@@ -1,25 +0,0 @@
|
|||||||
const gulp = require('gulp');
|
|
||||||
const googleWebFonts = require('gulp-google-webfonts');
|
|
||||||
const del = require('del');
|
|
||||||
|
|
||||||
const paths = {
|
|
||||||
cssDir: './src/css/',
|
|
||||||
};
|
|
||||||
|
|
||||||
function clean() {
|
|
||||||
return del([paths.cssDir]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function webfonts() {
|
|
||||||
return gulp.src('./webfonts.list')
|
|
||||||
.pipe(googleWebFonts({
|
|
||||||
fontsDir: 'webfonts',
|
|
||||||
cssFilename: 'webfonts.css',
|
|
||||||
format: 'woff',
|
|
||||||
}))
|
|
||||||
.pipe(gulp.dest(paths.cssDir));
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.clean = clean;
|
|
||||||
exports.webfonts = gulp.series(clean, webfonts);
|
|
||||||
exports['prebuild:renderer'] = webfonts;;
|
|
||||||
2
jslib
2
jslib
Submodule jslib updated: 55a9ea9e18...cb00604617
13188
package-lock.json
generated
13188
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@@ -31,8 +31,8 @@
|
|||||||
"lint:fix": "tslint 'src/**/*.ts' --fix",
|
"lint:fix": "tslint 'src/**/*.ts' --fix",
|
||||||
"build": "concurrently -n Main,Rend -c yellow,cyan \"npm run build:main\" \"npm run build:renderer\"",
|
"build": "concurrently -n Main,Rend -c yellow,cyan \"npm run build:main\" \"npm run build:renderer\"",
|
||||||
"build:main": "webpack --config webpack.main.js",
|
"build:main": "webpack --config webpack.main.js",
|
||||||
"build:renderer": "gulp prebuild:renderer && webpack --config webpack.renderer.js",
|
"build:renderer": "webpack --config webpack.renderer.js",
|
||||||
"build:renderer:watch": "gulp prebuild:renderer && webpack --config webpack.renderer.js --watch",
|
"build:renderer:watch": "webpack --config webpack.renderer.js --watch",
|
||||||
"build:dist": "npm run reset && npm run rebuild && npm run build",
|
"build:dist": "npm run reset && npm run rebuild && npm run build",
|
||||||
"build:cli": "webpack --config webpack.cli.js",
|
"build:cli": "webpack --config webpack.cli.js",
|
||||||
"build:cli:watch": "webpack --config webpack.cli.js --watch",
|
"build:cli:watch": "webpack --config webpack.cli.js --watch",
|
||||||
@@ -144,14 +144,12 @@
|
|||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"css-loader": "^5.2.4",
|
"css-loader": "^5.2.4",
|
||||||
"del": "^6.0.0",
|
"del": "^6.0.0",
|
||||||
"electron-builder": "^22.10.5",
|
"electron-builder": "^22.11.7",
|
||||||
"electron-notarize": "^1.0.0",
|
"electron-notarize": "^1.1.1",
|
||||||
"electron-rebuild": "^2.3.5",
|
"electron-rebuild": "^3.2.3",
|
||||||
"electron-reload": "^1.5.0",
|
"electron-reload": "^1.5.0",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
"font-awesome": "4.7.0",
|
"font-awesome": "4.7.0",
|
||||||
"gulp": "^4.0.2",
|
|
||||||
"gulp-google-webfonts": "^4.0.0",
|
|
||||||
"html-loader": "^1.3.2",
|
"html-loader": "^1.3.2",
|
||||||
"html-webpack-plugin": "^4.5.1",
|
"html-webpack-plugin": "^4.5.1",
|
||||||
"mini-css-extract-plugin": "^1.5.0",
|
"mini-css-extract-plugin": "^1.5.0",
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
$major,$minor,$patch = $env:PACKAGE_VERSION.split('.')
|
|
||||||
|
|
||||||
$versionInfo = @"
|
|
||||||
|
|
||||||
1 VERSIONINFO
|
|
||||||
FILEVERSION $major,$minor,$patch,0
|
|
||||||
PRODUCTVERSION $major,$minor,$patch,0
|
|
||||||
FILEOS 0x40004
|
|
||||||
FILETYPE 0x1
|
|
||||||
{
|
|
||||||
BLOCK "StringFileInfo"
|
|
||||||
{
|
|
||||||
BLOCK "040904b0"
|
|
||||||
{
|
|
||||||
VALUE "CompanyName", "Bitwarden Inc."
|
|
||||||
VALUE "ProductName", "Bitwarden"
|
|
||||||
VALUE "FileDescription", "Bitwarden Directory Connector CLI"
|
|
||||||
VALUE "FileVersion", "$env:PACKAGE_VERSION"
|
|
||||||
VALUE "ProductVersion", "$env:PACKAGE_VERSION"
|
|
||||||
VALUE "OriginalFilename", "bwdc.exe"
|
|
||||||
VALUE "InternalName", "bwdc"
|
|
||||||
VALUE "LegalCopyright", "Copyright Bitwarden Inc."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BLOCK "VarFileInfo"
|
|
||||||
{
|
|
||||||
VALUE "Translation", 0x0409 0x04B0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"@
|
|
||||||
|
|
||||||
$versionInfo | Out-File ./version-info.rc
|
|
||||||
@@ -2,23 +2,23 @@
|
|||||||
"name": "bitwarden-directory-connector",
|
"name": "bitwarden-directory-connector",
|
||||||
"productName": "Bitwarden Directory Connector",
|
"productName": "Bitwarden Directory Connector",
|
||||||
"description": "Sync your user directory to your Bitwarden organization.",
|
"description": "Sync your user directory to your Bitwarden organization.",
|
||||||
"version": "2.9.0",
|
"version": "2.9.5",
|
||||||
"author": "Bitwarden Inc. <hello@bitwarden.com> (https://bitwarden.com)",
|
"author": "Bitwarden Inc. <hello@bitwarden.com> (https://bitwarden.com)",
|
||||||
"homepage": "https://bitwarden.com",
|
"homepage": "https://bitwarden.com",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/bitwarden/directory-connector"
|
"url": "https://github.com/bitwarden/directory-connector"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"bwdc": "../build-cli/bwdc.js"
|
"bwdc": "../build-cli/bwdc.js"
|
||||||
},
|
},
|
||||||
"pkg": {
|
"pkg": {
|
||||||
"assets": "../build-cli/**/*"
|
"assets": "../build-cli/**/*"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"browser-hrtime": "^1.1.8",
|
"browser-hrtime": "^1.1.8",
|
||||||
"keytar": "7.6.0"
|
"keytar": "7.6.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,8 +15,15 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="row-main">
|
<div class="row-main">
|
||||||
<label for="client_secret">{{'clientSecret' | i18n}}</label>
|
<label for="client_secret">{{'clientSecret' | i18n}}</label>
|
||||||
<input id="client_secret" name="ClientSecret"
|
<div class="input-group">
|
||||||
|
<input type="{{showSecret ? 'text' : 'password'}}" id="client_secret" name="ClientSecret"
|
||||||
[(ngModel)]="clientSecret" class="form-control">
|
[(ngModel)]="clientSecret" class="form-control">
|
||||||
|
<div class="input-group-append">
|
||||||
|
<button type="button" class="ml-1 btn btn-link" appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="toggleSecret()">
|
||||||
|
<i class="fa fa-lg" aria-hidden="true"[ngClass]="showSecret ? 'fa-eye-slash' : 'fa-eye'"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ import { AuthService } from 'jslib-common/abstractions/auth.service';
|
|||||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||||
|
|
||||||
import { ModalComponent } from 'jslib-angular/components/modal.component';
|
import { ModalService } from 'jslib-angular/services/modal.service';
|
||||||
|
|
||||||
import { Utils } from 'jslib-common/misc/utils';
|
import { Utils } from 'jslib-common/misc/utils';
|
||||||
import { ConfigurationService } from '../../services/configuration.service';
|
import { ConfigurationService } from '../../services/configuration.service';
|
||||||
|
|
||||||
@@ -29,10 +30,12 @@ export class ApiKeyComponent {
|
|||||||
|
|
||||||
formPromise: Promise<any>;
|
formPromise: Promise<any>;
|
||||||
successRoute = '/tabs/dashboard';
|
successRoute = '/tabs/dashboard';
|
||||||
|
showSecret: boolean = false;
|
||||||
|
|
||||||
constructor(private authService: AuthService, private apiKeyService: ApiKeyService, private router: Router,
|
constructor(private authService: AuthService, private apiKeyService: ApiKeyService, private router: Router,
|
||||||
private i18nService: I18nService, private componentFactoryResolver: ComponentFactoryResolver,
|
private i18nService: I18nService, private componentFactoryResolver: ComponentFactoryResolver,
|
||||||
private configurationService: ConfigurationService, private platformUtilsService: PlatformUtilsService) { }
|
private configurationService: ConfigurationService, private platformUtilsService: PlatformUtilsService,
|
||||||
|
private modalService: ModalService) { }
|
||||||
|
|
||||||
async submit() {
|
async submit() {
|
||||||
if (this.clientId == null || this.clientId === '') {
|
if (this.clientId == null || this.clientId === '') {
|
||||||
@@ -67,14 +70,15 @@ export class ApiKeyComponent {
|
|||||||
} catch { }
|
} catch { }
|
||||||
}
|
}
|
||||||
|
|
||||||
settings() {
|
async settings() {
|
||||||
const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent);
|
const [modalRef, childComponent] = await this.modalService.openViewRef(EnvironmentComponent, this.environmentModal);
|
||||||
const modal = this.environmentModal.createComponent(factory).instance;
|
|
||||||
const childComponent = modal.show<EnvironmentComponent>(EnvironmentComponent,
|
|
||||||
this.environmentModal);
|
|
||||||
|
|
||||||
childComponent.onSaved.subscribe(() => {
|
childComponent.onSaved.subscribe(() => {
|
||||||
modal.close();
|
modalRef.close();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
toggleSecret() {
|
||||||
|
this.showSecret = !this.showSecret;
|
||||||
|
document.getElementById('client_secret').focus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ import {
|
|||||||
import { DomSanitizer } from '@angular/platform-browser';
|
import { DomSanitizer } from '@angular/platform-browser';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
import { ModalComponent } from 'jslib-angular/components/modal.component';
|
|
||||||
|
|
||||||
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
|
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
|
||||||
|
|
||||||
import { ApiService } from 'jslib-common/abstractions/api.service';
|
import { ApiService } from 'jslib-common/abstractions/api.service';
|
||||||
@@ -56,7 +54,6 @@ export class AppComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
|
|
||||||
private lastActivity: number = null;
|
private lastActivity: number = null;
|
||||||
private modal: ModalComponent = null;
|
|
||||||
|
|
||||||
constructor(private broadcasterService: BroadcasterService, private userService: UserService,
|
constructor(private broadcasterService: BroadcasterService, private userService: UserService,
|
||||||
private tokenService: TokenService, private storageService: StorageService,
|
private tokenService: TokenService, private storageService: StorageService,
|
||||||
@@ -146,20 +143,6 @@ export class AppComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private openModal<T>(type: Type<T>, ref: ViewContainerRef) {
|
|
||||||
if (this.modal != null) {
|
|
||||||
this.modal.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent);
|
|
||||||
this.modal = ref.createComponent(factory).instance;
|
|
||||||
const childComponent = this.modal.show<T>(type, ref);
|
|
||||||
|
|
||||||
this.modal.onClosed.subscribe(() => {
|
|
||||||
this.modal = null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private showToast(msg: any) {
|
private showToast(msg: any) {
|
||||||
const toast: Toast = {
|
const toast: Toast = {
|
||||||
type: msg.type,
|
type: msg.type,
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import { AppComponent } from './app.component';
|
|||||||
|
|
||||||
import { CalloutComponent } from 'jslib-angular/components/callout.component';
|
import { CalloutComponent } from 'jslib-angular/components/callout.component';
|
||||||
import { IconComponent } from 'jslib-angular/components/icon.component';
|
import { IconComponent } from 'jslib-angular/components/icon.component';
|
||||||
import { ModalComponent } from 'jslib-angular/components/modal.component';
|
|
||||||
|
|
||||||
import { ApiKeyComponent } from './accounts/apiKey.component';
|
import { ApiKeyComponent } from './accounts/apiKey.component';
|
||||||
import { EnvironmentComponent } from './accounts/environment.component';
|
import { EnvironmentComponent } from './accounts/environment.component';
|
||||||
@@ -59,7 +58,6 @@ import { SearchCiphersPipe } from 'jslib-angular/pipes/search-ciphers.pipe';
|
|||||||
FallbackSrcDirective,
|
FallbackSrcDirective,
|
||||||
I18nPipe,
|
I18nPipe,
|
||||||
IconComponent,
|
IconComponent,
|
||||||
ModalComponent,
|
|
||||||
MoreComponent,
|
MoreComponent,
|
||||||
SearchCiphersPipe,
|
SearchCiphersPipe,
|
||||||
SettingsComponent,
|
SettingsComponent,
|
||||||
@@ -67,10 +65,6 @@ import { SearchCiphersPipe } from 'jslib-angular/pipes/search-ciphers.pipe';
|
|||||||
StopPropDirective,
|
StopPropDirective,
|
||||||
TabsComponent,
|
TabsComponent,
|
||||||
],
|
],
|
||||||
entryComponents: [
|
|
||||||
EnvironmentComponent,
|
|
||||||
ModalComponent,
|
|
||||||
],
|
|
||||||
providers: [],
|
providers: [],
|
||||||
bootstrap: [AppComponent],
|
bootstrap: [AppComponent],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import { I18nService } from '../../services/i18n.service';
|
|||||||
import { SyncService } from '../../services/sync.service';
|
import { SyncService } from '../../services/sync.service';
|
||||||
|
|
||||||
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
|
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
|
||||||
|
import { ModalService } from 'jslib-angular/services/modal.service';
|
||||||
import { ValidationService } from 'jslib-angular/services/validation.service';
|
import { ValidationService } from 'jslib-angular/services/validation.service';
|
||||||
|
|
||||||
import { ApiKeyService } from 'jslib-common/services/apiKey.service';
|
import { ApiKeyService } from 'jslib-common/services/apiKey.service';
|
||||||
@@ -70,9 +71,9 @@ const cryptoService = new CryptoService(storageService, secureStorageService, cr
|
|||||||
platformUtilsService, logService);
|
platformUtilsService, logService);
|
||||||
const appIdService = new AppIdService(storageService);
|
const appIdService = new AppIdService(storageService);
|
||||||
const tokenService = new TokenService(storageService);
|
const tokenService = new TokenService(storageService);
|
||||||
const apiService = new ApiService(tokenService, platformUtilsService, refreshTokenCallback,
|
const environmentService = new EnvironmentService(storageService);
|
||||||
|
const apiService = new ApiService(tokenService, platformUtilsService, environmentService, refreshTokenCallback,
|
||||||
async (expired: boolean) => messagingService.send('logout', { expired: expired }));
|
async (expired: boolean) => messagingService.send('logout', { expired: expired }));
|
||||||
const environmentService = new EnvironmentService(apiService, storageService, null);
|
|
||||||
const userService = new UserService(tokenService, storageService);
|
const userService = new UserService(tokenService, storageService);
|
||||||
const apiKeyService = new ApiKeyService(tokenService, storageService);
|
const apiKeyService = new ApiKeyService(tokenService, storageService);
|
||||||
const containerService = new ContainerService(cryptoService);
|
const containerService = new ContainerService(cryptoService);
|
||||||
@@ -80,7 +81,7 @@ const authService = new AuthService(cryptoService, apiService, userService, toke
|
|||||||
i18nService, platformUtilsService, messagingService, null, logService, apiKeyService, false);
|
i18nService, platformUtilsService, messagingService, null, logService, apiKeyService, false);
|
||||||
const configurationService = new ConfigurationService(storageService, secureStorageService);
|
const configurationService = new ConfigurationService(storageService, secureStorageService);
|
||||||
const syncService = new SyncService(configurationService, logService, cryptoFunctionService, apiService,
|
const syncService = new SyncService(configurationService, logService, cryptoFunctionService, apiService,
|
||||||
messagingService, i18nService);
|
messagingService, i18nService, environmentService);
|
||||||
const passwordGenerationService = new PasswordGenerationService(cryptoService, storageService, null);
|
const passwordGenerationService = new PasswordGenerationService(cryptoService, storageService, null);
|
||||||
const policyService = new PolicyService(userService, storageService);
|
const policyService = new PolicyService(userService, storageService);
|
||||||
|
|
||||||
@@ -131,6 +132,7 @@ export function initFactory(): Function {
|
|||||||
ValidationService,
|
ValidationService,
|
||||||
AuthGuardService,
|
AuthGuardService,
|
||||||
LaunchGuardService,
|
LaunchGuardService,
|
||||||
|
ModalService,
|
||||||
{ provide: AuthServiceAbstraction, useValue: authService },
|
{ provide: AuthServiceAbstraction, useValue: authService },
|
||||||
{ provide: EnvironmentServiceAbstraction, useValue: environmentService },
|
{ provide: EnvironmentServiceAbstraction, useValue: environmentService },
|
||||||
{ provide: TokenServiceAbstraction, useValue: tokenService },
|
{ provide: TokenServiceAbstraction, useValue: tokenService },
|
||||||
|
|||||||
@@ -121,8 +121,15 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="password">{{'password' | i18n}}</label>
|
<label for="password">{{'password' | i18n}}</label>
|
||||||
<input type="password" class="form-control" id="password" name="Password"
|
<div class="input-group">
|
||||||
|
<input type="{{showLdapPassword ? 'text' : 'password'}}" class="form-control" id="password" name="Password"
|
||||||
[(ngModel)]="ldap.password">
|
[(ngModel)]="ldap.password">
|
||||||
|
<div class="input-group-append">
|
||||||
|
<button type="button" class="btn btn-outline-secondary" appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="toggleLdapPassword()">
|
||||||
|
<i class="fa fa-lg" aria-hidden="true"[ngClass]="showLdapPassword ? 'fa-eye-slash' : 'fa-eye'"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -139,7 +146,15 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="secretKey">{{'secretKey' | i18n}}</label>
|
<label for="secretKey">{{'secretKey' | i18n}}</label>
|
||||||
<input type="text" class="form-control" id="secretKey" name="SecretKey" [(ngModel)]="azure.key">
|
<div class="input-group">
|
||||||
|
<input type="{{showAzureKey ? 'text' : 'password'}}" class="form-control" id="secretKey" name="SecretKey"
|
||||||
|
[(ngModel)]="azure.key">
|
||||||
|
<div class="input-group-append">
|
||||||
|
<button type="button" class="btn btn-outline-secondary" appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="toggleAzureKey()">
|
||||||
|
<i class="fa fa-lg" aria-hidden="true"[ngClass]="showAzureKey ? 'fa-eye-slash' : 'fa-eye'"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div [hidden]="directory != directoryType.Okta">
|
<div [hidden]="directory != directoryType.Okta">
|
||||||
@@ -150,8 +165,15 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="oktaToken">{{'token' | i18n}}</label>
|
<label for="oktaToken">{{'token' | i18n}}</label>
|
||||||
<input type="text" class="form-control" id="oktaToken" name="OktaToken"
|
<div class="input-group">
|
||||||
|
<input type="{{showOktaKey ? 'text' : 'password'}}" class="form-control" id="oktaToken" name="OktaToken"
|
||||||
[(ngModel)]="okta.token">
|
[(ngModel)]="okta.token">
|
||||||
|
<div class="input-group-append">
|
||||||
|
<button type="button" class="btn btn-outline-secondary" appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="toggleOktaKey()">
|
||||||
|
<i class="fa fa-lg" aria-hidden="true"[ngClass]="showOktaKey ? 'fa-eye-slash' : 'fa-eye'"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div [hidden]="directory != directoryType.OneLogin">
|
<div [hidden]="directory != directoryType.OneLogin">
|
||||||
@@ -162,8 +184,15 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="oneLoginClientSecret">{{'clientSecret' | i18n}}</label>
|
<label for="oneLoginClientSecret">{{'clientSecret' | i18n}}</label>
|
||||||
<input type="text" class="form-control" id="oneLoginClientSecret" name="OneLoginClientSecret"
|
<div class="input-group">
|
||||||
|
<input type="{{showOneLoginSecret ? 'text' : 'password'}}" class="form-control" id="oneLoginClientSecret" name="OneLoginClientSecret"
|
||||||
[(ngModel)]="oneLogin.clientSecret">
|
[(ngModel)]="oneLogin.clientSecret">
|
||||||
|
<div class="input-group-append">
|
||||||
|
<button type="button" class="btn btn-outline-secondary" appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="toggleOneLoginSecret()">
|
||||||
|
<i class="fa fa-lg" aria-hidden="true"[ngClass]="showOneLoginSecret ? 'fa-eye-slash' : 'fa-eye'"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="oneLoginRegion">{{'region' | i18n}}</label>
|
<label for="oneLoginRegion">{{'region' | i18n}}</label>
|
||||||
|
|||||||
@@ -38,6 +38,10 @@ export class SettingsComponent implements OnInit, OnDestroy {
|
|||||||
oneLogin = new OneLoginConfiguration();
|
oneLogin = new OneLoginConfiguration();
|
||||||
sync = new SyncConfiguration();
|
sync = new SyncConfiguration();
|
||||||
directoryOptions: any[];
|
directoryOptions: any[];
|
||||||
|
showLdapPassword: boolean = false;
|
||||||
|
showAzureKey: boolean = false;
|
||||||
|
showOktaKey: boolean = false;
|
||||||
|
showOneLoginSecret: boolean = false;
|
||||||
|
|
||||||
constructor(private i18nService: I18nService, private configurationService: ConfigurationService,
|
constructor(private i18nService: I18nService, private configurationService: ConfigurationService,
|
||||||
private changeDetectorRef: ChangeDetectorRef, private ngZone: NgZone,
|
private changeDetectorRef: ChangeDetectorRef, private ngZone: NgZone,
|
||||||
@@ -126,4 +130,24 @@ export class SettingsComponent implements OnInit, OnDestroy {
|
|||||||
filePicker.type = 'file';
|
filePicker.type = 'file';
|
||||||
filePicker.value = '';
|
filePicker.value = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleLdapPassword() {
|
||||||
|
this.showLdapPassword = !this.showLdapPassword;
|
||||||
|
document.getElementById('password').focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleAzureKey() {
|
||||||
|
this.showAzureKey = !this.showAzureKey;
|
||||||
|
document.getElementById('secretKey').focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleOktaKey() {
|
||||||
|
this.showOktaKey = !this.showOktaKey;
|
||||||
|
document.getElementById('oktaToken').focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleOneLoginSecret() {
|
||||||
|
this.showOneLoginSecret = !this.showOneLoginSecret;
|
||||||
|
document.getElementById('oneLoginClientSecret').focus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
15
src/bwdc.ts
15
src/bwdc.ts
@@ -91,9 +91,12 @@ export class Main {
|
|||||||
this.appIdService = new AppIdService(this.storageService);
|
this.appIdService = new AppIdService(this.storageService);
|
||||||
this.tokenService = new TokenService(this.storageService);
|
this.tokenService = new TokenService(this.storageService);
|
||||||
this.messagingService = new NoopMessagingService();
|
this.messagingService = new NoopMessagingService();
|
||||||
this.apiService = new NodeApiService(this.tokenService, this.platformUtilsService, this.refreshTokenCallback,
|
this.environmentService = new EnvironmentService(this.storageService);
|
||||||
async (expired: boolean) => await this.logout());
|
this.apiService = new NodeApiService(this.tokenService, this.platformUtilsService, this.environmentService,
|
||||||
this.environmentService = new EnvironmentService(this.apiService, this.storageService, null);
|
() => refreshToken(this.apiKeyService, this.authService), async (expired: boolean) => await this.logout(),
|
||||||
|
'Bitwarden_DC/' + this.platformUtilsService.getApplicationVersion() +
|
||||||
|
' (' + this.platformUtilsService.getDeviceString().toUpperCase() + ')', (clientId, clientSecret) =>
|
||||||
|
this.authService.logInApiKey(clientId, clientSecret));
|
||||||
this.apiKeyService = new ApiKeyService(this.tokenService, this.storageService);
|
this.apiKeyService = new ApiKeyService(this.tokenService, this.storageService);
|
||||||
this.userService = new UserService(this.tokenService, this.storageService);
|
this.userService = new UserService(this.tokenService, this.storageService);
|
||||||
this.containerService = new ContainerService(this.cryptoService);
|
this.containerService = new ContainerService(this.cryptoService);
|
||||||
@@ -103,7 +106,7 @@ export class Main {
|
|||||||
this.configurationService = new ConfigurationService(this.storageService, this.secureStorageService,
|
this.configurationService = new ConfigurationService(this.storageService, this.secureStorageService,
|
||||||
process.env.BITWARDENCLI_CONNECTOR_PLAINTEXT_SECRETS !== 'true');
|
process.env.BITWARDENCLI_CONNECTOR_PLAINTEXT_SECRETS !== 'true');
|
||||||
this.syncService = new SyncService(this.configurationService, this.logService, this.cryptoFunctionService,
|
this.syncService = new SyncService(this.configurationService, this.logService, this.cryptoFunctionService,
|
||||||
this.apiService, this.messagingService, this.i18nService);
|
this.apiService, this.messagingService, this.i18nService, this.environmentService);
|
||||||
this.passwordGenerationService = new PasswordGenerationService(this.cryptoService, this.storageService, null);
|
this.passwordGenerationService = new PasswordGenerationService(this.cryptoService, this.storageService, null);
|
||||||
this.program = new Program(this);
|
this.program = new Program(this);
|
||||||
}
|
}
|
||||||
@@ -118,10 +121,6 @@ export class Main {
|
|||||||
await this.apiKeyService.clear();
|
await this.apiKeyService.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshTokenCallback() {
|
|
||||||
return refreshToken(this.apiKeyService, this.authService);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async init() {
|
private async init() {
|
||||||
await this.storageService.init();
|
await this.storageService.init();
|
||||||
this.containerService.attachToWindow(global);
|
this.containerService.attachToWindow(global);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "bitwarden-directory-connector",
|
"name": "bitwarden-directory-connector",
|
||||||
"productName": "Bitwarden Directory Connector",
|
"productName": "Bitwarden Directory Connector",
|
||||||
"description": "Sync your user directory to your Bitwarden organization.",
|
"description": "Sync your user directory to your Bitwarden organization.",
|
||||||
"version": "2.9.3",
|
"version": "2.9.7",
|
||||||
"author": "Bitwarden Inc. <hello@bitwarden.com> (https://bitwarden.com)",
|
"author": "Bitwarden Inc. <hello@bitwarden.com> (https://bitwarden.com)",
|
||||||
"homepage": "https://bitwarden.com",
|
"homepage": "https://bitwarden.com",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
|
|||||||
@@ -118,3 +118,27 @@ ul.testing-list {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn[class*="btn-outline-"] {
|
||||||
|
&:not(:hover) {
|
||||||
|
border-color: $secondary;
|
||||||
|
background-color: #fbfbfb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-outline-secondary {
|
||||||
|
color: $text-muted;
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
color: $body-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus,
|
||||||
|
&.focus {
|
||||||
|
box-shadow: 0 0 0 $btn-focus-width rgba(mix(color-yiq($primary), $primary, 15%), .5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@import "../css/webfonts.css";
|
@import "../../jslib/angular/src/scss/webfonts.css";
|
||||||
@import "bootstrap.scss";
|
@import "bootstrap.scss";
|
||||||
@import "pages.scss";
|
@import "pages.scss";
|
||||||
@import "misc.scss";
|
@import "misc.scss";
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { ApiKeyService } from 'jslib-common/abstractions/apiKey.service';
|
import { ApiKeyService } from 'jslib-common/abstractions/apiKey.service';
|
||||||
import { AuthService } from 'jslib-common/abstractions/auth.service';
|
import { AuthService } from 'jslib-common/abstractions/auth.service';
|
||||||
|
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
|
||||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||||
import { TokenService } from 'jslib-common/abstractions/token.service';
|
import { TokenService } from 'jslib-common/abstractions/token.service';
|
||||||
|
|
||||||
@@ -18,10 +19,10 @@ export async function refreshToken(apiKeyService: ApiKeyService, authService: Au
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class ApiService extends ApiServiceBase {
|
export class ApiService extends ApiServiceBase {
|
||||||
constructor(tokenService: TokenService, platformUtilsService: PlatformUtilsService,
|
constructor(tokenService: TokenService, platformUtilsService: PlatformUtilsService, environmentService: EnvironmentService,
|
||||||
private refreshTokenCallback: () => Promise<void>, logoutCallback: (expired: boolean) => Promise<void>,
|
private refreshTokenCallback: () => Promise<void>, logoutCallback: (expired: boolean) => Promise<void>,
|
||||||
customUserAgent: string = null) {
|
customUserAgent: string = null) {
|
||||||
super(tokenService, platformUtilsService, logoutCallback, customUserAgent);
|
super(tokenService, platformUtilsService, environmentService, logoutCallback, customUserAgent);
|
||||||
}
|
}
|
||||||
|
|
||||||
doRefreshToken(): Promise<void> {
|
doRefreshToken(): Promise<void> {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.serv
|
|||||||
|
|
||||||
import { AuthService as AuthServiceBase } from 'jslib-common/services/auth.service';
|
import { AuthService as AuthServiceBase } from 'jslib-common/services/auth.service';
|
||||||
|
|
||||||
import { AuthResult } from 'jslib-common/models/domain';
|
import { AuthResult } from 'jslib-common/models/domain/authResult';
|
||||||
import { DeviceRequest } from 'jslib-common/models/request/deviceRequest';
|
import { DeviceRequest } from 'jslib-common/models/request/deviceRequest';
|
||||||
import { TokenRequest } from 'jslib-common/models/request/tokenRequest';
|
import { TokenRequest } from 'jslib-common/models/request/tokenRequest';
|
||||||
import { IdentityTokenResponse } from 'jslib-common/models/response/identityTokenResponse';
|
import { IdentityTokenResponse } from 'jslib-common/models/response/identityTokenResponse';
|
||||||
@@ -45,7 +45,7 @@ export class AuthService extends AuthServiceBase {
|
|||||||
const appId = await this.appIdService.getAppId();
|
const appId = await this.appIdService.getAppId();
|
||||||
const deviceRequest = new DeviceRequest(appId, this.platformUtilsService);
|
const deviceRequest = new DeviceRequest(appId, this.platformUtilsService);
|
||||||
const request = new TokenRequest(null, null, [clientId, clientSecret], null,
|
const request = new TokenRequest(null, null, [clientId, clientSecret], null,
|
||||||
null, false, deviceRequest);
|
null, false, null, deviceRequest);
|
||||||
|
|
||||||
const response = await this.apiService.postIdentityToken(request);
|
const response = await this.apiService.postIdentityToken(request);
|
||||||
const result = new AuthResult();
|
const result = new AuthResult();
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ export class AzureDirectoryService extends BaseDirectoryService implements IDire
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const entry = this.buildUser(user);
|
const entry = this.buildUser(user);
|
||||||
if (!entry.disabled && !entry.deleted) {
|
if (!entry.deleted) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (await this.filterOutUserResult(setFilter, entry, false)) {
|
if (await this.filterOutUserResult(setFilter, entry, false)) {
|
||||||
@@ -204,7 +204,7 @@ export class AzureDirectoryService extends BaseDirectoryService implements IDire
|
|||||||
if (keyword === 'excludeadministrativeunit' || keyword === 'includeadministrativeunit') {
|
if (keyword === 'excludeadministrativeunit' || keyword === 'includeadministrativeunit') {
|
||||||
for (const p of pieces) {
|
for (const p of pieces) {
|
||||||
const auMembers = await this.client
|
const auMembers = await this.client
|
||||||
.api(`https://graph.microsoft.com/beta/administrativeUnits/${p}/members`).get();
|
.api(`https://graph.microsoft.com/v1.0/directory/administrativeUnits/${p}/members`).get();
|
||||||
for (const auMember of auMembers.value) {
|
for (const auMember of auMembers.value) {
|
||||||
if (auMember['@odata.type'] === '#microsoft.graph.group') {
|
if (auMember['@odata.type'] === '#microsoft.graph.group') {
|
||||||
set.add(auMember.displayName.toLowerCase());
|
set.add(auMember.displayName.toLowerCase());
|
||||||
@@ -386,7 +386,7 @@ export class AzureDirectoryService extends BaseDirectoryService implements IDire
|
|||||||
authProvider: done => {
|
authProvider: done => {
|
||||||
if (this.dirConfig.applicationId == null || this.dirConfig.key == null ||
|
if (this.dirConfig.applicationId == null || this.dirConfig.key == null ||
|
||||||
this.dirConfig.tenant == null) {
|
this.dirConfig.tenant == null) {
|
||||||
done(this.i18nService.t('dirConfigIncomplete'), null);
|
done(new Error(this.i18nService.t('dirConfigIncomplete')), null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,9 +421,14 @@ export class AzureDirectoryService extends BaseDirectoryService implements IDire
|
|||||||
this.setAccessTokenExpiration(d.access_token, d.expires_in);
|
this.setAccessTokenExpiration(d.access_token, d.expires_in);
|
||||||
done(null, d.access_token);
|
done(null, d.access_token);
|
||||||
} else if (d.error != null && d.error_description != null) {
|
} else if (d.error != null && d.error_description != null) {
|
||||||
done(d.error + ' (' + res.statusCode + '): ' + d.error_description, null);
|
const shortError = d.error_description?.split('\n', 1)[0];
|
||||||
|
const err = new Error(d.error + ' (' + res.statusCode + '): ' + shortError);
|
||||||
|
// tslint: disable-next-line
|
||||||
|
console.error(d.error_description);
|
||||||
|
done(err, null);
|
||||||
} else {
|
} else {
|
||||||
done('Unknown error (' + res.statusCode + ').', null);
|
const err = new Error('Unknown error (' + res.statusCode + ').');
|
||||||
|
done(err, null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}).on('error', err => {
|
}).on('error', err => {
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
|
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
|
||||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||||
import { TokenService } from 'jslib-common/abstractions/token.service';
|
import { TokenService } from 'jslib-common/abstractions/token.service';
|
||||||
|
|
||||||
import { NodeApiService as NodeApiServiceBase } from 'jslib-node/services/nodeApi.service';
|
import { NodeApiService as NodeApiServiceBase } from 'jslib-node/services/nodeApi.service';
|
||||||
|
|
||||||
export class NodeApiService extends NodeApiServiceBase {
|
export class NodeApiService extends NodeApiServiceBase {
|
||||||
constructor(tokenService: TokenService, platformUtilsService: PlatformUtilsService,
|
constructor(tokenService: TokenService, platformUtilsService: PlatformUtilsService, environmentService: EnvironmentService,
|
||||||
private refreshTokenCallback: () => Promise<void>, logoutCallback: (expired: boolean) => Promise<void>,
|
private refreshTokenCallback: () => Promise<void>, logoutCallback: (expired: boolean) => Promise<void>,
|
||||||
customUserAgent: string = null) {
|
customUserAgent: string = null, apiKeyRefresh: (clientId: string, clientSecret: string) => Promise<any>) {
|
||||||
super(tokenService, platformUtilsService, logoutCallback, customUserAgent);
|
super(tokenService, platformUtilsService, environmentService, logoutCallback, customUserAgent, apiKeyRefresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
doRefreshToken(): Promise<void> {
|
doRefreshToken(): Promise<void> {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { OrganizationImportRequest } from 'jslib-common/models/request/organizat
|
|||||||
|
|
||||||
import { ApiService } from 'jslib-common/abstractions/api.service';
|
import { ApiService } from 'jslib-common/abstractions/api.service';
|
||||||
import { CryptoFunctionService } from 'jslib-common/abstractions/cryptoFunction.service';
|
import { CryptoFunctionService } from 'jslib-common/abstractions/cryptoFunction.service';
|
||||||
|
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
|
||||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||||
import { LogService } from 'jslib-common/abstractions/log.service';
|
import { LogService } from 'jslib-common/abstractions/log.service';
|
||||||
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
|
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
|
||||||
@@ -27,7 +28,8 @@ export class SyncService {
|
|||||||
|
|
||||||
constructor(private configurationService: ConfigurationService, private logService: LogService,
|
constructor(private configurationService: ConfigurationService, private logService: LogService,
|
||||||
private cryptoFunctionService: CryptoFunctionService, private apiService: ApiService,
|
private cryptoFunctionService: CryptoFunctionService, private apiService: ApiService,
|
||||||
private messagingService: MessagingService, private i18nService: I18nService) { }
|
private messagingService: MessagingService, private i18nService: I18nService,
|
||||||
|
private environmentService: EnvironmentService) { }
|
||||||
|
|
||||||
async sync(force: boolean, test: boolean): Promise<[GroupEntry[], UserEntry[]]> {
|
async sync(force: boolean, test: boolean): Promise<[GroupEntry[], UserEntry[]]> {
|
||||||
this.dirType = await this.configurationService.getDirectoryType();
|
this.dirType = await this.configurationService.getDirectoryType();
|
||||||
@@ -55,13 +57,7 @@ export class SyncService {
|
|||||||
this.flattenUsersToGroups(groups, groups);
|
this.flattenUsersToGroups(groups, groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
const duplicateEmails = this.findDuplicateUserEmails(users);
|
users = this.removeDuplicateUsers(users);
|
||||||
if (duplicateEmails.length > 0) {
|
|
||||||
const emailsMessage = duplicateEmails.length < 4 ?
|
|
||||||
duplicateEmails.join('\n') :
|
|
||||||
duplicateEmails.slice(0, 3).join('\n') + '\n' + this.i18nService.t('andMore', `${duplicateEmails.length - 3}`);
|
|
||||||
throw new Error(this.i18nService.t('duplicateEmails') + '\n' + emailsMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (test || (!syncConfig.overwriteExisting &&
|
if (test || (!syncConfig.overwriteExisting &&
|
||||||
(groups == null || groups.length === 0) && (users == null || users.length === 0))) {
|
(groups == null || groups.length === 0) && (users == null || users.length === 0))) {
|
||||||
@@ -83,12 +79,12 @@ export class SyncService {
|
|||||||
|
|
||||||
// TODO: Remove hashLegacy once we're sure clients have had time to sync new hashes
|
// TODO: Remove hashLegacy once we're sure clients have had time to sync new hashes
|
||||||
let hashLegacy: string = null;
|
let hashLegacy: string = null;
|
||||||
const hashBuffLegacy = await this.cryptoFunctionService.hash(this.apiService.apiBaseUrl + reqJson, 'sha256');
|
const hashBuffLegacy = await this.cryptoFunctionService.hash(this.environmentService.getApiUrl() + reqJson, 'sha256');
|
||||||
if (hashBuffLegacy != null) {
|
if (hashBuffLegacy != null) {
|
||||||
hashLegacy = Utils.fromBufferToB64(hashBuffLegacy);
|
hashLegacy = Utils.fromBufferToB64(hashBuffLegacy);
|
||||||
}
|
}
|
||||||
let hash: string = null;
|
let hash: string = null;
|
||||||
const hashBuff = await this.cryptoFunctionService.hash(this.apiService.apiBaseUrl + orgId + reqJson, 'sha256');
|
const hashBuff = await this.cryptoFunctionService.hash(this.environmentService.getApiUrl() + orgId + reqJson, 'sha256');
|
||||||
if (hashBuff != null) {
|
if (hashBuff != null) {
|
||||||
hash = Utils.fromBufferToB64(hashBuff);
|
hash = Utils.fromBufferToB64(hashBuff);
|
||||||
}
|
}
|
||||||
@@ -116,17 +112,32 @@ export class SyncService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private findDuplicateUserEmails(users: UserEntry[]) {
|
private removeDuplicateUsers(users: UserEntry[]) {
|
||||||
const duplicatedEmails = new Array<string>();
|
const uniqueUsers = new Array<UserEntry>();
|
||||||
users.reduce((agg, user) => {
|
const processedUsers = new Map<string, string>();
|
||||||
if (agg.includes(user.email) && !duplicatedEmails.includes(user.email)) {
|
const duplicateEmails = new Array<string>();
|
||||||
duplicatedEmails.push(user.email);
|
|
||||||
|
// UserEntrys with the same email are ignored if their properties are the same
|
||||||
|
// UserEntrys with the same email but different properties will throw an error
|
||||||
|
users.forEach(u => {
|
||||||
|
if (processedUsers.has(u.email)) {
|
||||||
|
if (processedUsers.get(u.email) != JSON.stringify(u)) {
|
||||||
|
duplicateEmails.push(u.email);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
agg.push(user.email);
|
uniqueUsers.push(u);
|
||||||
|
processedUsers.set(u.email, JSON.stringify(u));
|
||||||
}
|
}
|
||||||
return agg;
|
});
|
||||||
}, new Array<string>());
|
|
||||||
return duplicatedEmails;
|
if (duplicateEmails.length > 0) {
|
||||||
|
const emailsMessage = duplicateEmails.length < 4 ?
|
||||||
|
duplicateEmails.join('\n') :
|
||||||
|
duplicateEmails.slice(0, 3).join('\n') + '\n' + this.i18nService.t('andMore', `${duplicateEmails.length - 3}`);
|
||||||
|
throw new Error(this.i18nService.t('duplicateEmails') + '\n' + emailsMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
return uniqueUsers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private filterUnsupportedUsers(users: UserEntry[]): UserEntry[] {
|
private filterUnsupportedUsers(users: UserEntry[]): UserEntry[] {
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
Open+Sans:300,300i,400,400i,600,600i,700,700i,800,800i&subset=cyrillic,cyrillic-ext,greek,greek-ext,latin-ext
|
|
||||||
Reference in New Issue
Block a user