1
0
mirror of https://github.com/bitwarden/directory-connector synced 2025-12-05 23:53:21 +00:00

Compare commits

..

3 Commits

Author SHA1 Message Date
Thomas Rittson
01e894b5bc uninstall ldapjs 2024-09-30 11:14:02 +10:00
Thomas Rittson
aa5a9f3e2f Initial implementation of ldapts 2024-09-30 11:13:16 +10:00
Thomas Rittson
f4181b13f7 Install ldapts 2024-09-30 09:54:04 +10:00
159 changed files with 10338 additions and 379399 deletions

View File

@@ -7,12 +7,6 @@
"groupName": "gh minor", "groupName": "gh minor",
"matchManagers": ["github-actions"], "matchManagers": ["github-actions"],
"matchUpdateTypes": ["minor", "patch"] "matchUpdateTypes": ["minor", "patch"]
},
{
"groupName": "Google Libraries",
"matchPackagePatterns": ["google-auth-library", "googleapis"],
"matchManagers": ["npm"],
"groupSlug": "google-libraries"
} }
] ]
} }

View File

@@ -1,377 +0,0 @@
name: Build CLI
on:
pull_request: {}
push:
branches:
- "main"
- "rc"
- "hotfix-rc"
workflow_dispatch: {}
permissions:
contents: read
jobs:
cloc:
name: CLOC
runs-on: ubuntu-24.04
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up CLOC
run: |
sudo apt update
sudo apt -y install cloc
- name: Print lines of code
run: cloc --include-lang TypeScript,JavaScript,HTML,Sass,CSS --vcs git
setup:
name: Setup
runs-on: ubuntu-24.04
outputs:
package_version: ${{ steps.retrieve-version.outputs.package_version }}
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Get Package Version
id: retrieve-version
run: |
PKG_VERSION=$(jq -r .version package.json)
echo "package_version=$PKG_VERSION" >> $GITHUB_OUTPUT
linux-cli:
name: Build Linux CLI
runs-on: ubuntu-24.04
needs: setup
env:
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
_PKG_FETCH_NODE_VERSION: 18.5.0
_PKG_FETCH_VERSION: 3.4
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: '18'
- name: Update NPM
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Get pkg-fetch
run: |
cd $HOME
fetchedUrl="https://github.com/vercel/pkg-fetch/releases/download/v$_PKG_FETCH_VERSION/node-v$_PKG_FETCH_NODE_VERSION-linux-x64"
mkdir -p .pkg-cache/v$_PKG_FETCH_VERSION
wget $fetchedUrl -O "./.pkg-cache/v$_PKG_FETCH_VERSION/fetched-v$_PKG_FETCH_NODE_VERSION-linux-x64"
- name: Keytar
run: |
keytarVersion=$(cat package.json | jq -r '.dependencies.keytar')
keytarTar="keytar-v$keytarVersion-napi-v3-linux-x64.tar"
keytarTarGz="$keytarTar.gz"
keytarUrl="https://github.com/atom/node-keytar/releases/download/v$keytarVersion/$keytarTarGz"
mkdir -p ./keytar/linux
wget $keytarUrl -O ./keytar/linux/$keytarTarGz
tar -xvf ./keytar/linux/$keytarTarGz -C ./keytar/linux
- name: Install
run: npm install
- name: Package CLI
run: npm run dist:cli:lin
- name: Zip
run: zip -j dist-cli/bwdc-linux-$_PACKAGE_VERSION.zip dist-cli/linux/bwdc keytar/linux/build/Release/keytar.node
- name: Version Test
run: |
sudo apt-get update
sudo apt install libsecret-1-0 dbus-x11 gnome-keyring
eval $(dbus-launch --sh-syntax)
eval $(echo -n "" | /usr/bin/gnome-keyring-daemon --login)
eval $(/usr/bin/gnome-keyring-daemon --components=secrets --start)
mkdir -p test/linux
unzip ./dist-cli/bwdc-linux-$_PACKAGE_VERSION.zip -d ./test/linux
testVersion=$(./test/linux/bwdc -v)
echo "version: $_PACKAGE_VERSION"
echo "testVersion: $testVersion"
if [ "$testVersion" != "$_PACKAGE_VERSION" ]; then
echo "Version test failed."
exit 1
fi
- name: Upload Linux Zip to GitHub
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: bwdc-linux-${{ env._PACKAGE_VERSION }}.zip
path: ./dist-cli/bwdc-linux-${{ env._PACKAGE_VERSION }}.zip
if-no-files-found: error
macos-cli:
name: Build Mac CLI
runs-on: macos-13
needs: setup
env:
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
_PKG_FETCH_NODE_VERSION: 18.5.0
_PKG_FETCH_VERSION: 3.4
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: '18'
- name: Update NPM
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Get pkg-fetch
run: |
cd $HOME
fetchedUrl="https://github.com/vercel/pkg-fetch/releases/download/v$_PKG_FETCH_VERSION/node-v$_PKG_FETCH_NODE_VERSION-macos-x64"
mkdir -p .pkg-cache/v$_PKG_FETCH_VERSION
wget $fetchedUrl -O "./.pkg-cache/v$_PKG_FETCH_VERSION/fetched-v$_PKG_FETCH_NODE_VERSION-macos-x64"
- name: Keytar
run: |
keytarVersion=$(cat package.json | jq -r '.dependencies.keytar')
keytarTar="keytar-v$keytarVersion-napi-v3-darwin-x64.tar"
keytarTarGz="$keytarTar.gz"
keytarUrl="https://github.com/atom/node-keytar/releases/download/v$keytarVersion/$keytarTarGz"
mkdir -p ./keytar/macos
wget $keytarUrl -O ./keytar/macos/$keytarTarGz
tar -xvf ./keytar/macos/$keytarTarGz -C ./keytar/macos
- name: Install
run: npm install
- name: Package CLI
run: npm run dist:cli:mac
- name: Zip
run: zip -j dist-cli/bwdc-macos-$_PACKAGE_VERSION.zip dist-cli/macos/bwdc keytar/macos/build/Release/keytar.node
- name: Version Test
run: |
mkdir -p test/macos
unzip ./dist-cli/bwdc-macos-$_PACKAGE_VERSION.zip -d ./test/macos
testVersion=$(./test/macos/bwdc -v)
echo "version: $_PACKAGE_VERSION"
echo "testVersion: $testVersion"
if [ "$testVersion" != "$_PACKAGE_VERSION" ]; then
echo "Version test failed."
exit 1
fi
- name: Upload Mac Zip to GitHub
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: bwdc-macos-${{ env._PACKAGE_VERSION }}.zip
path: ./dist-cli/bwdc-macos-${{ env._PACKAGE_VERSION }}.zip
if-no-files-found: error
windows-cli:
name: Build Windows CLI
runs-on: windows-2022
needs: setup
env:
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
_WIN_PKG_FETCH_VERSION: 18.5.0
_WIN_PKG_VERSION: 3.4
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Windows builder
run: |
choco install checksum --no-progress
choco install reshack --no-progress
- name: Set up Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: '18'
- name: Update NPM
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Get pkg-fetch
shell: pwsh
run: |
cd $HOME
$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/v$env:_WIN_PKG_VERSION
Invoke-RestMethod -Uri $fetchedUrl `
-OutFile "./.pkg-cache/v$env:_WIN_PKG_VERSION/fetched-v$env:_WIN_PKG_FETCH_VERSION-win-x64"
- name: Keytar
shell: pwsh
run: |
$keytarVersion = (Get-Content -Raw -Path ./package.json | ConvertFrom-Json).dependencies.keytar
$keytarTar = "keytar-v${keytarVersion}-napi-v3-{0}-x64.tar"
$keytarTarGz = "${keytarTar}.gz"
$keytarUrl = "https://github.com/atom/node-keytar/releases/download/v${keytarVersion}/${keytarTarGz}"
New-Item -ItemType directory -Path ./keytar/windows | Out-Null
Invoke-RestMethod -Uri $($keytarUrl -f "win32") -OutFile "./keytar/windows/$($keytarTarGz -f "win32")"
7z e "./keytar/windows/$($keytarTarGz -f "win32")" -o"./keytar/windows"
7z e "./keytar/windows/$($keytarTar -f "win32")" -o"./keytar/windows"
- name: Setup Version Info
shell: pwsh
run: |
$major, $minor, $patch = $env:_PACKAGE_VERSION.split('.')
$versionInfo = @"
1 VERSIONINFO
FILEVERSION $major,$minor,$patch,0
PRODUCTVERSION $major,$minor,$patch,0
FILEOS 0x40004
FILETYPE 0x1
{
BLOCK "StringFileInfo"
{
BLOCK "040904b0"
{
VALUE "CompanyName", "Bitwarden Inc."
VALUE "ProductName", "Bitwarden"
VALUE "FileDescription", "Bitwarden Directory Connector CLI"
VALUE "FileVersion", "$env:_PACKAGE_VERSION"
VALUE "ProductVersion", "$env:_PACKAGE_VERSION"
VALUE "OriginalFilename", "bwdc.exe"
VALUE "InternalName", "bwdc"
VALUE "LegalCopyright", "Copyright Bitwarden Inc."
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 0x0409 0x04B0
}
}
"@
$versionInfo | Out-File ./version-info.rc
- name: Resource Hacker
shell: cmd
run: |
set PATH=%PATH%;C:\Program Files (x86)\Resource Hacker
set WIN_PKG=C:\Users\runneradmin\.pkg-cache\v%_WIN_PKG_VERSION%\fetched-v%_WIN_PKG_FETCH_VERSION%-win-x64
set WIN_PKG_BUILT=C:\Users\runneradmin\.pkg-cache\v%_WIN_PKG_VERSION%\built-v%_WIN_PKG_FETCH_VERSION%-win-x64
ResourceHacker -open %WIN_PKG% -save %WIN_PKG% -action delete -mask ICONGROUP,1,
ResourceHacker -open version-info.rc -save version-info.res -action compile
ResourceHacker -open %WIN_PKG% -save %WIN_PKG% -action addoverwrite -resource version-info.res
- name: Install
run: npm install
- name: Package CLI
run: npm run dist:cli:win
- name: Zip
shell: cmd
run: 7z a .\dist-cli\bwdc-windows-%_PACKAGE_VERSION%.zip .\dist-cli\windows\bwdc.exe .\keytar\windows\keytar.node
- name: Version Test
shell: pwsh
run: |
Expand-Archive -Path "dist-cli\bwdc-windows-${{ env._PACKAGE_VERSION }}.zip" -DestinationPath "test\windows"
$testVersion = Invoke-Expression '& .\test\windows\bwdc.exe -v'
echo "version: ${env:_PACKAGE_VERSION}"
echo "testVersion: $testVersion"
if ($testVersion -ne ${env:_PACKAGE_VERSION}) {
Throw "Version test failed."
}
- name: Upload Windows Zip to GitHub
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: bwdc-windows-${{ env._PACKAGE_VERSION }}.zip
path: ./dist-cli/bwdc-windows-${{ env._PACKAGE_VERSION }}.zip
if-no-files-found: error
check-failures:
name: Check for failures
runs-on: ubuntu-24.04
needs:
- cloc
- setup
- linux-cli
- macos-cli
- windows-cli
steps:
- name: Check if any job failed
if: |
(github.ref == 'refs/heads/main'
|| github.ref == 'refs/heads/rc'
|| github.ref == 'refs/heads/hotfix-rc')
&& contains(needs.*.result, 'failure')
run: exit 1
- name: Login to Azure - CI subscription
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
if: failure()
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets
id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@main
if: failure()
with:
keyvault: "bitwarden-ci"
secrets: "devops-alerts-slack-webhook-url"
- name: Notify Slack on failure
uses: act10ns/slack@44541246747a30eb3102d87f7a4cc5471b0ffb7d # v2.1.0
if: failure()
env:
SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }}
with:
status: ${{ job.status }}

View File

@@ -1,354 +0,0 @@
name: Build GUI
on:
pull_request: {}
push:
branches:
- "main"
- "rc"
- "hotfix-rc"
workflow_dispatch: {}
permissions:
contents: read
jobs:
cloc:
name: CLOC
runs-on: ubuntu-24.04
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up CLOC
run: |
sudo apt update
sudo apt -y install cloc
- name: Print lines of code
run: cloc --include-lang TypeScript,JavaScript,HTML,Sass,CSS --vcs git
setup:
name: Setup
runs-on: ubuntu-24.04
outputs:
package_version: ${{ steps.retrieve-version.outputs.package_version }}
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Get Package Version
id: retrieve-version
run: |
PKG_VERSION=$(jq -r .version package.json)
echo "package_version=$PKG_VERSION" >> $GITHUB_OUTPUT
windows-gui:
name: Build Windows GUI
runs-on: windows-2022
needs: setup
env:
NODE_OPTIONS: --max_old_space_size=4096
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
HUSKY: 0
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: '18'
- name: Update NPM
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Print environment
run: |
node --version
npm --version
- name: Install AST
run: dotnet tool install --global AzureSignTool --version 4.0.1
- name: Install Node dependencies
run: npm install
- name: Login to Azure
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets
id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@main
with:
keyvault: "bitwarden-ci"
secrets: "code-signing-vault-url,
code-signing-client-id,
code-signing-tenant-id,
code-signing-client-secret,
code-signing-cert-name"
- name: Build & Sign
run: npm run dist:win
env:
ELECTRON_BUILDER_SIGN: 1
SIGNING_VAULT_URL: ${{ steps.retrieve-secrets.outputs.code-signing-vault-url }}
SIGNING_CLIENT_ID: ${{ steps.retrieve-secrets.outputs.code-signing-client-id }}
SIGNING_TENANT_ID: ${{ steps.retrieve-secrets.outputs.code-signing-tenant-id }}
SIGNING_CLIENT_SECRET: ${{ steps.retrieve-secrets.outputs.code-signing-client-secret }}
SIGNING_CERT_NAME: ${{ steps.retrieve-secrets.outputs.code-signing-cert-name }}
- name: Upload Portable Executable to GitHub
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: Bitwarden-Connector-Portable-${{ env._PACKAGE_VERSION }}.exe
path: ./dist/Bitwarden-Connector-Portable-${{ env._PACKAGE_VERSION }}.exe
if-no-files-found: error
- name: Upload Installer Executable to GitHub
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe
path: ./dist/Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe
if-no-files-found: error
- name: Upload Installer Executable Blockmap to GitHub
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe.blockmap
path: ./dist/Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe.blockmap
if-no-files-found: error
- name: Upload latest auto-update artifact
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: latest.yml
path: ./dist/latest.yml
if-no-files-found: error
linux-gui:
name: Build Linux GUI
runs-on: ubuntu-24.04
needs: setup
env:
NODE_OPTIONS: --max_old_space_size=4096
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
HUSKY: 0
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: '18'
- name: Update NPM
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: 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: NPM Install
run: npm install
- name: NPM Rebuild
run: npm run rebuild
- name: NPM Package
run: npm run dist:lin
- name: Upload AppImage
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-x86_64.AppImage
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-x86_64.AppImage
if-no-files-found: error
- name: Upload latest auto-update artifact
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: latest-linux.yml
path: ./dist/latest-linux.yml
if-no-files-found: error
macos-gui:
name: Build MacOS GUI
runs-on: macos-13
needs: setup
env:
NODE_OPTIONS: --max_old_space_size=4096
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
HUSKY: 0
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: '18'
- name: Update NPM
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Print environment
run: |
node --version
npm --version
echo "GitHub ref: $GITHUB_REF"
echo "GitHub event: $GITHUB_EVENT"
- name: Login to Azure
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Get certificates
run: |
mkdir -p $HOME/certificates
az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/devid-app-cert |
jq -r .value | base64 -d > $HOME/certificates/devid-app-cert.p12
az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/devid-installer-cert |
jq -r .value | base64 -d > $HOME/certificates/devid-installer-cert.p12
az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/macdev-cert |
jq -r .value | base64 -d > $HOME/certificates/macdev-cert.p12
- name: Set up keychain
env:
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
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/certificates/devid-app-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/certificates/devid-installer-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/certificates/macdev-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain
- name: Load package version
run: |
$rootPath = $env:GITHUB_WORKSPACE;
$packageVersion = (Get-Content -Raw -Path $rootPath\package.json | ConvertFrom-Json).version;
Write-Output "Setting package version to $packageVersion";
Write-Output "PACKAGE_VERSION=$packageVersion" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append;
shell: pwsh
- name: Install Node dependencies
run: npm install
- name: Set up private auth key
run: |
mkdir ~/private_keys
cat << EOF > ~/private_keys/AuthKey_UFD296548T.p8
${{ secrets.APP_STORE_CONNECT_AUTH_KEY }}
EOF
- name: Build application
run: npm run dist:mac
env:
APP_STORE_CONNECT_TEAM_ISSUER: ${{ secrets.APP_STORE_CONNECT_TEAM_ISSUER }}
APP_STORE_CONNECT_AUTH_KEY: UFD296548T
APP_STORE_CONNECT_AUTH_KEY_PATH: ~/private_keys/AuthKey_UFD296548T.p8
CSC_FOR_PULL_REQUEST: true
- name: Upload .zip artifact
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-mac.zip
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-mac.zip
if-no-files-found: error
- name: Upload .dmg artifact
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg
if-no-files-found: error
- name: Upload .dmg Blockmap artifact
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg.blockmap
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg.blockmap
if-no-files-found: error
- name: Upload latest auto-update artifact
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: latest-mac.yml
path: ./dist/latest-mac.yml
if-no-files-found: error
check-failures:
name: Check for failures
runs-on: ubuntu-24.04
needs:
- cloc
- setup
- windows-gui
- linux-gui
- macos-gui
steps:
- name: Check if any job failed
if: |
(github.ref == 'refs/heads/main'
|| github.ref == 'refs/heads/rc'
|| github.ref == 'refs/heads/hotfix-rc')
&& contains(needs.*.result, 'failure')
run: exit 1
- name: Login to Azure - CI subscription
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
if: failure()
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets
id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@main
if: failure()
with:
keyvault: "bitwarden-ci"
secrets: "devops-alerts-slack-webhook-url"
- name: Notify Slack on failure
uses: act10ns/slack@44541246747a30eb3102d87f7a4cc5471b0ffb7d # v2.1.0
if: failure()
env:
SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }}
with:
status: ${{ job.status }}

661
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,661 @@
---
name: Build
on:
pull_request: {}
push:
branches:
- "main"
workflow_dispatch: {}
jobs:
cloc:
name: CLOC
runs-on: ubuntu-22.04
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Set up CLOC
run: |
sudo apt update
sudo apt -y install cloc
- name: Print lines of code
run: cloc --include-lang TypeScript,JavaScript,HTML,Sass,CSS --vcs git
setup:
name: Setup
runs-on: ubuntu-22.04
outputs:
package_version: ${{ steps.retrieve-version.outputs.package_version }}
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Get Package Version
id: retrieve-version
run: |
PKG_VERSION=$(jq -r .version package.json)
echo "package_version=$PKG_VERSION" >> $GITHUB_OUTPUT
linux-cli:
name: Build Linux CLI
runs-on: ubuntu-22.04
needs: setup
env:
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
_PKG_FETCH_NODE_VERSION: 18.5.0
_PKG_FETCH_VERSION: 3.4
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Set up Node
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: '18'
- name: Update NPM
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Get pkg-fetch
run: |
cd $HOME
fetchedUrl="https://github.com/vercel/pkg-fetch/releases/download/v$_PKG_FETCH_VERSION/node-v$_PKG_FETCH_NODE_VERSION-linux-x64"
mkdir -p .pkg-cache/v$_PKG_FETCH_VERSION
wget $fetchedUrl -O "./.pkg-cache/v$_PKG_FETCH_VERSION/fetched-v$_PKG_FETCH_NODE_VERSION-linux-x64"
- name: Keytar
run: |
keytarVersion=$(cat package.json | jq -r '.dependencies.keytar')
keytarTar="keytar-v$keytarVersion-napi-v3-linux-x64.tar"
keytarTarGz="$keytarTar.gz"
keytarUrl="https://github.com/atom/node-keytar/releases/download/v$keytarVersion/$keytarTarGz"
mkdir -p ./keytar/linux
wget $keytarUrl -O ./keytar/linux/$keytarTarGz
tar -xvf ./keytar/linux/$keytarTarGz -C ./keytar/linux
- name: Install
run: npm install
- name: Package CLI
run: npm run dist:cli:lin
- name: Zip
run: zip -j dist-cli/bwdc-linux-$_PACKAGE_VERSION.zip dist-cli/linux/bwdc keytar/linux/build/Release/keytar.node
- name: Create checksums
run: |
shasum -a 256 dist-cli/bwdc-linux-$_PACKAGE_VERSION.zip | \
cut -d " " -f 1 > dist-cli/bwdc-linux-sha256-$_PACKAGE_VERSION.txt
- name: Version Test
run: |
sudo apt-get update
sudo apt install libsecret-1-0 dbus-x11 gnome-keyring
eval $(dbus-launch --sh-syntax)
eval $(echo -n "" | /usr/bin/gnome-keyring-daemon --login)
eval $(/usr/bin/gnome-keyring-daemon --components=secrets --start)
mkdir -p test/linux
unzip ./dist-cli/bwdc-linux-$_PACKAGE_VERSION.zip -d ./test/linux
testVersion=$(./test/linux/bwdc -v)
echo "version: $_PACKAGE_VERSION"
echo "testVersion: $testVersion"
if [ "$testVersion" != "$_PACKAGE_VERSION" ]; then
echo "Version test failed."
exit 1
fi
- name: Upload Linux Zip to GitHub
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: bwdc-linux-${{ env._PACKAGE_VERSION }}.zip
path: ./dist-cli/bwdc-linux-${{ env._PACKAGE_VERSION }}.zip
if-no-files-found: error
- name: Upload Linux checksum to GitHub
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: bwdc-linux-sha256-${{ env._PACKAGE_VERSION }}.txt
path: ./dist-cli/bwdc-linux-sha256-${{ env._PACKAGE_VERSION }}.txt
if-no-files-found: error
macos-cli:
name: Build Mac CLI
runs-on: macos-13
needs: setup
env:
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
_PKG_FETCH_NODE_VERSION: 18.5.0
_PKG_FETCH_VERSION: 3.4
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Set up Node
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: '18'
- name: Update NPM
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Get pkg-fetch
run: |
cd $HOME
fetchedUrl="https://github.com/vercel/pkg-fetch/releases/download/v$_PKG_FETCH_VERSION/node-v$_PKG_FETCH_NODE_VERSION-macos-x64"
mkdir -p .pkg-cache/v$_PKG_FETCH_VERSION
wget $fetchedUrl -O "./.pkg-cache/v$_PKG_FETCH_VERSION/fetched-v$_PKG_FETCH_NODE_VERSION-macos-x64"
- name: Keytar
run: |
keytarVersion=$(cat package.json | jq -r '.dependencies.keytar')
keytarTar="keytar-v$keytarVersion-napi-v3-darwin-x64.tar"
keytarTarGz="$keytarTar.gz"
keytarUrl="https://github.com/atom/node-keytar/releases/download/v$keytarVersion/$keytarTarGz"
mkdir -p ./keytar/macos
wget $keytarUrl -O ./keytar/macos/$keytarTarGz
tar -xvf ./keytar/macos/$keytarTarGz -C ./keytar/macos
- name: Install
run: npm install
- name: Package CLI
run: npm run dist:cli:mac
- name: Zip
run: zip -j dist-cli/bwdc-macos-$_PACKAGE_VERSION.zip dist-cli/macos/bwdc keytar/macos/build/Release/keytar.node
- name: Create checksums
run: |
shasum -a 256 dist-cli/bwdc-macos-$_PACKAGE_VERSION.zip | \
cut -d " " -f 1 > dist-cli/bwdc-macos-sha256-$_PACKAGE_VERSION.txt
- name: Version Test
run: |
mkdir -p test/macos
unzip ./dist-cli/bwdc-macos-$_PACKAGE_VERSION.zip -d ./test/macos
testVersion=$(./test/macos/bwdc -v)
echo "version: $_PACKAGE_VERSION"
echo "testVersion: $testVersion"
if [ "$testVersion" != "$_PACKAGE_VERSION" ]; then
echo "Version test failed."
exit 1
fi
- name: Upload Mac Zip to GitHub
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: bwdc-macos-${{ env._PACKAGE_VERSION }}.zip
path: ./dist-cli/bwdc-macos-${{ env._PACKAGE_VERSION }}.zip
if-no-files-found: error
- name: Upload Mac checksum to GitHub
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: bwdc-macos-sha256-${{ env._PACKAGE_VERSION }}.txt
path: ./dist-cli/bwdc-macos-sha256-${{ env._PACKAGE_VERSION }}.txt
if-no-files-found: error
windows-cli:
name: Build Windows CLI
runs-on: windows-2022
needs: setup
env:
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
_WIN_PKG_FETCH_VERSION: 18.5.0
_WIN_PKG_VERSION: 3.4
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Setup Windows builder
run: |
choco install checksum --no-progress
choco install reshack --no-progress
- name: Set up Node
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: '18'
- name: Update NPM
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Get pkg-fetch
shell: pwsh
run: |
cd $HOME
$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/v$env:_WIN_PKG_VERSION
Invoke-RestMethod -Uri $fetchedUrl `
-OutFile "./.pkg-cache/v$env:_WIN_PKG_VERSION/fetched-v$env:_WIN_PKG_FETCH_VERSION-win-x64"
- name: Keytar
shell: pwsh
run: |
$keytarVersion = (Get-Content -Raw -Path ./package.json | ConvertFrom-Json).dependencies.keytar
$keytarTar = "keytar-v${keytarVersion}-napi-v3-{0}-x64.tar"
$keytarTarGz = "${keytarTar}.gz"
$keytarUrl = "https://github.com/atom/node-keytar/releases/download/v${keytarVersion}/${keytarTarGz}"
New-Item -ItemType directory -Path ./keytar/windows | Out-Null
Invoke-RestMethod -Uri $($keytarUrl -f "win32") -OutFile "./keytar/windows/$($keytarTarGz -f "win32")"
7z e "./keytar/windows/$($keytarTarGz -f "win32")" -o"./keytar/windows"
7z e "./keytar/windows/$($keytarTar -f "win32")" -o"./keytar/windows"
- name: Setup Version Info
shell: pwsh
run: |
$major, $minor, $patch = $env:_PACKAGE_VERSION.split('.')
$versionInfo = @"
1 VERSIONINFO
FILEVERSION $major,$minor,$patch,0
PRODUCTVERSION $major,$minor,$patch,0
FILEOS 0x40004
FILETYPE 0x1
{
BLOCK "StringFileInfo"
{
BLOCK "040904b0"
{
VALUE "CompanyName", "Bitwarden Inc."
VALUE "ProductName", "Bitwarden"
VALUE "FileDescription", "Bitwarden Directory Connector CLI"
VALUE "FileVersion", "$env:_PACKAGE_VERSION"
VALUE "ProductVersion", "$env:_PACKAGE_VERSION"
VALUE "OriginalFilename", "bwdc.exe"
VALUE "InternalName", "bwdc"
VALUE "LegalCopyright", "Copyright Bitwarden Inc."
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 0x0409 0x04B0
}
}
"@
$versionInfo | Out-File ./version-info.rc
- name: Resource Hacker
shell: cmd
run: |
set PATH=%PATH%;C:\Program Files (x86)\Resource Hacker
set WIN_PKG=C:\Users\runneradmin\.pkg-cache\v%_WIN_PKG_VERSION%\fetched-v%_WIN_PKG_FETCH_VERSION%-win-x64
set WIN_PKG_BUILT=C:\Users\runneradmin\.pkg-cache\v%_WIN_PKG_VERSION%\built-v%_WIN_PKG_FETCH_VERSION%-win-x64
ResourceHacker -open %WIN_PKG% -save %WIN_PKG% -action delete -mask ICONGROUP,1,
ResourceHacker -open version-info.rc -save version-info.res -action compile
ResourceHacker -open %WIN_PKG% -save %WIN_PKG% -action addoverwrite -resource version-info.res
- name: Install
run: npm install
- name: Package CLI
run: npm run dist:cli:win
- name: Zip
shell: cmd
run: 7z a .\dist-cli\bwdc-windows-%_PACKAGE_VERSION%.zip .\dist-cli\windows\bwdc.exe .\keytar\windows\keytar.node
- name: Version Test
shell: pwsh
run: |
Expand-Archive -Path "dist-cli\bwdc-windows-${{ env._PACKAGE_VERSION }}.zip" -DestinationPath "test\windows"
$testVersion = Invoke-Expression '& .\test\windows\bwdc.exe -v'
echo "version: ${env:_PACKAGE_VERSION}"
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
- name: Upload Windows Zip to GitHub
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: bwdc-windows-${{ env._PACKAGE_VERSION }}.zip
path: ./dist-cli/bwdc-windows-${{ env._PACKAGE_VERSION }}.zip
if-no-files-found: error
- name: Upload Windows checksum to GitHub
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: bwdc-windows-sha256-${{ env._PACKAGE_VERSION }}.txt
path: ./dist-cli/bwdc-windows-sha256-${{ env._PACKAGE_VERSION }}.txt
if-no-files-found: error
windows-gui:
name: Build Windows GUI
runs-on: windows-2022
needs: setup
env:
NODE_OPTIONS: --max_old_space_size=4096
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
HUSKY: 0
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Set up Node
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: '18'
- name: Update NPM
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Print environment
run: |
node --version
npm --version
- name: Install AST
run: dotnet tool install --global AzureSignTool --version 4.0.1
- name: Install Node dependencies
run: npm install
- name: Build & Sign
run: npm run dist: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 }}
- name: Upload Portable Executable to GitHub
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: Bitwarden-Connector-Portable-${{ env._PACKAGE_VERSION }}.exe
path: ./dist/Bitwarden-Connector-Portable-${{ env._PACKAGE_VERSION }}.exe
if-no-files-found: error
- name: Upload Installer Executable to GitHub
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe
path: ./dist/Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe
if-no-files-found: error
- name: Upload Installer Executable Blockmap to GitHub
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe.blockmap
path: ./dist/Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe.blockmap
if-no-files-found: error
- name: Upload latest auto-update artifact
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: latest.yml
path: ./dist/latest.yml
if-no-files-found: error
linux-gui:
name: Build Linux GUI
runs-on: ubuntu-22.04
needs: setup
env:
NODE_OPTIONS: --max_old_space_size=4096
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
HUSKY: 0
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Set up Node
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: '18'
- name: Update NPM
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: 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: NPM Install
run: npm install
- name: NPM Rebuild
run: npm run rebuild
- name: NPM Package
run: npm run dist:lin
- name: Upload AppImage
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-x86_64.AppImage
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-x86_64.AppImage
if-no-files-found: error
- name: Upload latest auto-update artifact
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: latest-linux.yml
path: ./dist/latest-linux.yml
if-no-files-found: error
macos-gui:
name: Build MacOS GUI
runs-on: macos-13
needs: setup
env:
NODE_OPTIONS: --max_old_space_size=4096
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
HUSKY: 0
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Set up Node
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: '18'
- name: Update NPM
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Print environment
run: |
node --version
npm --version
echo "GitHub ref: $GITHUB_REF"
echo "GitHub event: $GITHUB_EVENT"
- name: Login to Azure
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Get certificates
run: |
mkdir -p $HOME/certificates
az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/devid-app-cert |
jq -r .value | base64 -d > $HOME/certificates/devid-app-cert.p12
az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/devid-installer-cert |
jq -r .value | base64 -d > $HOME/certificates/devid-installer-cert.p12
az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/macdev-cert |
jq -r .value | base64 -d > $HOME/certificates/macdev-cert.p12
- name: Set up keychain
env:
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
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/certificates/devid-app-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/certificates/devid-installer-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/certificates/macdev-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain
- name: Load package version
run: |
$rootPath = $env:GITHUB_WORKSPACE;
$packageVersion = (Get-Content -Raw -Path $rootPath\package.json | ConvertFrom-Json).version;
Write-Output "Setting package version to $packageVersion";
Write-Output "PACKAGE_VERSION=$packageVersion" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append;
shell: pwsh
- name: Install Node dependencies
run: npm install
- name: Set up private auth key
run: |
mkdir ~/private_keys
cat << EOF > ~/private_keys/AuthKey_UFD296548T.p8
${{ secrets.APP_STORE_CONNECT_AUTH_KEY }}
EOF
- name: Build application
run: npm run dist:mac
env:
APP_STORE_CONNECT_TEAM_ISSUER: ${{ secrets.APP_STORE_CONNECT_TEAM_ISSUER }}
APP_STORE_CONNECT_AUTH_KEY: UFD296548T
APP_STORE_CONNECT_AUTH_KEY_PATH: ~/private_keys/AuthKey_UFD296548T.p8
CSC_FOR_PULL_REQUEST: true
- name: Upload .zip artifact
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-mac.zip
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-mac.zip
if-no-files-found: error
- name: Upload .dmg artifact
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg
if-no-files-found: error
- name: Upload .dmg Blockmap artifact
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg.blockmap
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg.blockmap
if-no-files-found: error
- name: Upload latest auto-update artifact
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: latest-mac.yml
path: ./dist/latest-mac.yml
if-no-files-found: error
check-failures:
name: Check for failures
runs-on: ubuntu-22.04
needs:
- cloc
- setup
- linux-cli
- macos-cli
- windows-cli
- windows-gui
- linux-gui
- macos-gui
steps:
- name: Check if any job failed
if: github.ref == 'refs/heads/main' && contains(needs.*.result, 'failure')
run: exit 1
- name: Login to Azure - CI subscription
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
if: failure()
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets
id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@main
if: failure()
with:
keyvault: "bitwarden-ci"
secrets: "devops-alerts-slack-webhook-url"
- name: Notify Slack on failure
uses: act10ns/slack@44541246747a30eb3102d87f7a4cc5471b0ffb7d # v2.1.0
if: failure()
env:
SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }}
with:
status: ${{ job.status }}

View File

@@ -1,15 +1,13 @@
---
name: Enforce PR labels name: Enforce PR labels
on: on:
pull_request: pull_request:
types: [labeled, unlabeled, opened, edited, synchronize] types: [labeled, unlabeled, opened, edited, synchronize]
permissions:
contents: read
pull-requests: read
jobs: jobs:
enforce-label: enforce-label:
name: EnforceLabel name: EnforceLabel
runs-on: ubuntu-24.04 runs-on: ubuntu-22.04
steps: steps:
- name: Enforce Label - name: Enforce Label
uses: yogevbd/enforce-label-action@a3c219da6b8fa73f6ba62b68ff09c469b3a1c024 # 2.2.2 uses: yogevbd/enforce-label-action@a3c219da6b8fa73f6ba62b68ff09c469b3a1c024 # 2.2.2

View File

@@ -1,76 +0,0 @@
name: Integration Testing
on:
workflow_dispatch:
push:
branches:
- "main"
paths:
- ".github/workflows/integration-test.yml" # this file
- "src/services/ldap-directory.service*" # we only have integration for LDAP testing at the moment
- "./openldap/**/*" # any change to test fixtures
- "./docker-compose.yml" # any change to Docker configuration
pull_request:
paths:
- ".github/workflows/integration-test.yml" # this file
- "src/services/ldap-directory.service*" # we only have integration for LDAP testing at the moment
- "./openldap/**/*" # any change to test fixtures
- "./docker-compose.yml" # any change to Docker configuration
jobs:
testing:
name: Run tests
if: ${{ startsWith(github.head_ref, 'version_bump_') == false }}
runs-on: ubuntu-22.04
permissions:
checks: write
contents: read
pull-requests: write
steps:
- name: Check out repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Get Node version
id: retrieve-node-version
run: |
NODE_NVMRC=$(cat .nvmrc)
NODE_VERSION=${NODE_NVMRC/v/''}
echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT
- name: Set up Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: ${{ steps.retrieve-node-version.outputs.node_version }}
- name: Install Node dependencies
run: npm ci
- name: Install mkcert
run: |
sudo apt-get update
sudo apt-get -y install mkcert
- name: Setup integration tests
run: npm run test:integration:setup
- name: Run integration tests
run: npm run test:integration --coverage
- name: Report test results
uses: dorny/test-reporter@31a54ee7ebcacc03a09ea97a7e5465a47b84aea5 # v1.9.1
if: ${{ github.event.pull_request.head.repo.full_name == github.repository && !cancelled() }}
with:
name: Test Results
path: "junit.xml"
reporter: jest-junit
fail-on-error: true
- name: Upload coverage to codecov.io
uses: codecov/codecov-action@5a605bd92782ce0810fa3b8acc235c921b497052 # v5.2.0
- name: Upload results to codecov.io
uses: codecov/test-results-action@4e79e65778be1cecd5df25e14af1eafb6df80ea9 # v1.0.2

View File

@@ -1,83 +0,0 @@
name: Release
on:
workflow_dispatch:
inputs:
release_type:
description: 'Release Options'
required: true
default: 'Initial Release'
type: choice
options:
- Initial Release
- Redeploy
- Dry Run
permissions:
contents: read
jobs:
setup:
name: Setup
runs-on: ubuntu-24.04
outputs:
release_version: ${{ steps.version.outputs.version }}
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Branch check
if: ${{ inputs.release_type != 'Dry Run' }}
run: |
if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix-rc" ]]; then
echo "==================================="
echo "[!] Can only release from the 'rc' or 'hotfix-rc' branches"
echo "==================================="
exit 1
fi
- name: Check Release Version
id: version
uses: bitwarden/gh-actions/release-version-check@main
with:
release-type: ${{ inputs.release_type }}
project-type: ts
file: package.json
release:
name: Release
runs-on: ubuntu-24.04
needs: setup
steps:
- name: Download all artifacts
if: ${{ inputs.release_type != 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
workflow: build-cli.yml
workflow_conclusion: success
branch: ${{ github.ref_name }}
- name: Dry Run - Download all artifacts
if: ${{ inputs.release_type == 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
workflow: build-cli.yml
workflow_conclusion: success
branch: main
- name: Create release
if: ${{ inputs.release_type != 'Dry Run' }}
uses: ncipollo/release-action@cdcc88a9acf3ca41c16c37bb7d21b9ad48560d87 # v1.15.0
env:
PKG_VERSION: ${{ needs.setup.outputs.release_version }}
with:
artifacts: "./bwdc-windows-${{ env.PKG_VERSION }}.zip,
./bwdc-macos-${{ env.PKG_VERSION }}.zip,
./bwdc-linux-${{ env.PKG_VERSION }}.zip"
commit: ${{ github.sha }}
tag: v${{ env.PKG_VERSION }}
name: Version ${{ env.PKG_VERSION }}
body: "<insert release notes here>"
token: ${{ secrets.GITHUB_TOKEN }}
draft: true

View File

@@ -1,4 +1,5 @@
name: Release GUI ---
name: Release
on: on:
workflow_dispatch: workflow_dispatch:
@@ -13,25 +14,22 @@ on:
- Redeploy - Redeploy
- Dry Run - Dry Run
permissions:
contents: read
jobs: jobs:
setup: setup:
name: Setup name: Setup
runs-on: ubuntu-24.04 runs-on: ubuntu-22.04
outputs: outputs:
release_version: ${{ steps.version.outputs.version }} release-version: ${{ steps.version.outputs.version }}
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Branch check - name: Branch check
if: ${{ inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
run: | run: |
if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix-rc" ]]; then if [[ "$GITHUB_REF" != "refs/heads/main" ]]; then
echo "===================================" echo "==================================="
echo "[!] Can only release from the 'rc' or 'hotfix-rc' branches" echo "[!] Can only release from the 'main' branch"
echo "===================================" echo "==================================="
exit 1 exit 1
fi fi
@@ -40,38 +38,44 @@ jobs:
id: version id: version
uses: bitwarden/gh-actions/release-version-check@main uses: bitwarden/gh-actions/release-version-check@main
with: with:
release-type: ${{ inputs.release_type }} release-type: ${{ github.event.inputs.release_type }}
project-type: ts project-type: ts
file: package.json file: package.json
release: release:
name: Release name: Release
runs-on: ubuntu-24.04 runs-on: ubuntu-22.04
needs: setup needs: setup
steps: steps:
- name: Download all artifacts - name: Download all artifacts
if: ${{ inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@main uses: bitwarden/gh-actions/download-artifacts@main
with: with:
workflow: build-gui.yml workflow: build.yml
workflow_conclusion: success workflow_conclusion: success
branch: ${{ github.ref_name }} branch: ${{ github.ref_name }}
- name: Dry Run - Download all artifacts - name: Dry Run - Download all artifacts
if: ${{ inputs.release_type == 'Dry Run' }} if: ${{ github.event.inputs.release_type == 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@main uses: bitwarden/gh-actions/download-artifacts@main
with: with:
workflow: build-gui.yml workflow: build.yml
workflow_conclusion: success workflow_conclusion: success
branch: main branch: main
- name: Create release - name: Create release
if: ${{ inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: ncipollo/release-action@cdcc88a9acf3ca41c16c37bb7d21b9ad48560d87 # v1.15.0 uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0
env: env:
PKG_VERSION: ${{ needs.setup.outputs.release_version }} PKG_VERSION: ${{ needs.setup.outputs.release-version }}
with: with:
artifacts: " ./Bitwarden-Connector-Portable-${{ env.PKG_VERSION }}.exe, artifacts: "./bwdc-windows-${{ env.PKG_VERSION }}.zip,
./bwdc-macos-${{ env.PKG_VERSION }}.zip,
./bwdc-linux-${{ env.PKG_VERSION }}.zip,
./bwdc-windows-sha256-${{ env.PKG_VERSION }}.txt,
./bwdc-macos-sha256-${{ env.PKG_VERSION }}.txt,
./bwdc-linux-sha256-${{ env.PKG_VERSION }}.txt,
./Bitwarden-Connector-Portable-${{ env.PKG_VERSION }}.exe,
./Bitwarden-Connector-Installer-${{ env.PKG_VERSION }}.exe, ./Bitwarden-Connector-Installer-${{ env.PKG_VERSION }}.exe,
./Bitwarden-Connector-Installer-${{ env.PKG_VERSION }}.exe.blockmap, ./Bitwarden-Connector-Installer-${{ env.PKG_VERSION }}.exe.blockmap,
./Bitwarden-Connector-${{ env.PKG_VERSION }}-x86_64.AppImage, ./Bitwarden-Connector-${{ env.PKG_VERSION }}-x86_64.AppImage,

View File

@@ -5,27 +5,17 @@ on:
push: push:
branches: branches:
- "main" - "main"
pull_request:
types: [opened, synchronize, reopened]
branches-ignore:
- main
pull_request_target: pull_request_target:
types: [opened, synchronize, reopened] types: [opened, synchronize]
branches:
- "main"
permissions: {}
jobs: jobs:
check-run: check-run:
name: Check PR run name: Check PR run
uses: bitwarden/gh-actions/.github/workflows/check-run.yml@main uses: bitwarden/gh-actions/.github/workflows/check-run.yml@main
permissions:
contents: read
sast: sast:
name: SAST scan name: SAST scan
runs-on: ubuntu-24.04 runs-on: ubuntu-22.04
needs: check-run needs: check-run
permissions: permissions:
contents: read contents: read
@@ -34,12 +24,12 @@ jobs:
steps: steps:
- name: Check out repo - name: Check out repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha }}
- name: Scan with Checkmarx - name: Scan with Checkmarx
uses: checkmarx/ast-github-action@184bf2f64f55d1c93fd6636d539edf274703e434 # 2.0.41 uses: checkmarx/ast-github-action@6c56658230f79c227a55120e9b24845d574d5225 # 2.0.31
env: env:
INCREMENTAL: "${{ contains(github.event_name, 'pull_request') && '--sast-incremental' || '' }}" INCREMENTAL: "${{ contains(github.event_name, 'pull_request') && '--sast-incremental' || '' }}"
with: with:
@@ -54,15 +44,13 @@ jobs:
--output-path . ${{ env.INCREMENTAL }} --output-path . ${{ env.INCREMENTAL }}
- name: Upload Checkmarx results to GitHub - name: Upload Checkmarx results to GitHub
uses: github/codeql-action/upload-sarif@dd196fa9ce80b6bacc74ca1c32bd5b0ba22efca7 # v3.28.3 uses: github/codeql-action/upload-sarif@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9
with: with:
sarif_file: cx_result.sarif sarif_file: cx_result.sarif
sha: ${{ contains(github.event_name, 'pull_request') && github.event.pull_request.head.sha || github.sha }}
ref: ${{ contains(github.event_name, 'pull_request') && format('refs/pull/{0}/head', github.event.pull_request.number) || github.ref }}
quality: quality:
name: Quality scan name: Quality scan
runs-on: ubuntu-24.04 runs-on: ubuntu-22.04
needs: check-run needs: check-run
permissions: permissions:
contents: read contents: read
@@ -70,15 +58,16 @@ jobs:
steps: steps:
- name: Check out repo - name: Check out repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with: with:
fetch-depth: 0 fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha }}
- name: Scan with SonarCloud - name: Scan with SonarCloud
uses: sonarsource/sonarqube-scan-action@2500896589ef8f7247069a56136f8dc177c27ccf # v5.2.0 uses: sonarsource/sonarcloud-github-action@eb211723266fe8e83102bac7361f0a05c3ac1d1b # v3.0.0
env: env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
args: > args: >
-Dsonar.organization=${{ github.repository_owner }} -Dsonar.organization=${{ github.repository_owner }}
@@ -87,4 +76,3 @@ jobs:
-Dsonar.sources=. -Dsonar.sources=.
-Dsonar.test.inclusions=**/*.spec.ts -Dsonar.test.inclusions=**/*.spec.ts
-Dsonar.exclusions=**/*.spec.ts -Dsonar.exclusions=**/*.spec.ts
-Dsonar.pullrequest.key=${{ github.event.pull_request.number }}

View File

@@ -5,16 +5,32 @@ on:
push: push:
branches: branches:
- "main" - "main"
- "rc"
- "hotfix-rc"
pull_request: pull_request:
jobs: jobs:
check-test-secrets:
name: Check for test secrets
runs-on: ubuntu-22.04
outputs:
available: ${{ steps.check-test-secrets.outputs.available }}
permissions:
contents: read
steps:
- name: Check
id: check-test-secrets
run: |
if [ "${{ secrets.CODECOV_TOKEN }}" != '' ]; then
echo "available=true" >> $GITHUB_OUTPUT;
else
echo "available=false" >> $GITHUB_OUTPUT;
fi
testing: testing:
name: Run tests name: Run tests
if: ${{ startsWith(github.head_ref, 'version_bump_') == false }} if: ${{ startsWith(github.head_ref, 'version_bump_') == false }}
runs-on: ubuntu-24.04 runs-on: ubuntu-22.04
needs: check-test-secrets
permissions: permissions:
checks: write checks: write
contents: read contents: read
@@ -22,7 +38,7 @@ jobs:
steps: steps:
- name: Check out repo - name: Check out repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Get Node version - name: Get Node version
id: retrieve-node-version id: retrieve-node-version
@@ -32,7 +48,7 @@ jobs:
echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT
- name: Set up Node - name: Set up Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with: with:
cache: 'npm' cache: 'npm'
cache-dependency-path: '**/package-lock.json' cache-dependency-path: '**/package-lock.json'
@@ -52,7 +68,7 @@ jobs:
- name: Report test results - name: Report test results
uses: dorny/test-reporter@31a54ee7ebcacc03a09ea97a7e5465a47b84aea5 # v1.9.1 uses: dorny/test-reporter@31a54ee7ebcacc03a09ea97a7e5465a47b84aea5 # v1.9.1
if: ${{ github.event.pull_request.head.repo.full_name == github.repository && !cancelled() }} if: ${{ needs.check-test-secrets.outputs.available == 'true' && !cancelled() }}
with: with:
name: Test Results name: Test Results
path: "junit.xml" path: "junit.xml"
@@ -60,7 +76,13 @@ jobs:
fail-on-error: true fail-on-error: true
- name: Upload coverage to codecov.io - name: Upload coverage to codecov.io
uses: codecov/codecov-action@5a605bd92782ce0810fa3b8acc235c921b497052 # v5.2.0 uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0
if: ${{ needs.check-test-secrets.outputs.available == 'true' }}
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
- name: Upload results to codecov.io - name: Upload results to codecov.io
uses: codecov/test-results-action@4e79e65778be1cecd5df25e14af1eafb6df80ea9 # v1.0.2 uses: codecov/test-results-action@1b5b448b98e58ba90d1a1a1d9fcb72ca2263be46 # v1.0.0
if: ${{ needs.check-test-secrets.outputs.available == 'true' }}
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

View File

@@ -1,3 +1,4 @@
---
name: Version Bump name: Version Bump
on: on:
@@ -7,11 +8,17 @@ on:
description: "New version override (leave blank for automatic calculation, example: '2024.1.0')" description: "New version override (leave blank for automatic calculation, example: '2024.1.0')"
required: false required: false
type: string type: string
enable_slack_notification:
description: "Enable Slack notifications for upcoming release?"
default: false
type: boolean
jobs: jobs:
bump_version: bump_version:
name: Bump Version name: Bump Version
runs-on: ubuntu-24.04 runs-on: ubuntu-22.04
outputs:
version: ${{ steps.set-final-version-output.outputs.version }}
steps: steps:
- name: Validate version input - name: Validate version input
if: ${{ inputs.version_number_override != '' }} if: ${{ inputs.version_number_override != '' }}
@@ -19,22 +26,49 @@ jobs:
with: with:
version: ${{ inputs.version_number_override }} version: ${{ inputs.version_number_override }}
- name: Generate GH App token - name: Slack Notification Check
uses: actions/create-github-app-token@c1a285145b9d317df6ced56c09f525b5c2b6f755 # v1.11.1 run: |
id: app-token if [[ "${{ inputs.enable_slack_notification }}" == true ]]; then
with: echo "Slack notifications enabled."
app-id: ${{ secrets.BW_GHAPP_ID }} else
private-key: ${{ secrets.BW_GHAPP_KEY }} echo "Slack notifications disabled."
fi
- name: Checkout Branch - name: Checkout Branch
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Login to Azure - CI Subscription
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
token: ${{ steps.app-token.outputs.token }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets
id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@main
with:
keyvault: "bitwarden-ci"
secrets: "github-gpg-private-key,
github-gpg-private-key-passphrase"
- name: Import GPG key
uses: crazy-max/ghaction-import-gpg@01dd5d3ca463c7f10f7f4f7b4f177225ac661ee4 # v6.1.0
with:
gpg_private_key: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key }}
passphrase: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key-passphrase }}
git_user_signingkey: true
git_commit_gpgsign: true
- name: Setup git - name: Setup git
run: | run: |
git config user.name github-actions git config --local user.email "106330231+bitwarden-devops-bot@users.noreply.github.com"
git config user.email github-actions@github.com git config --local user.name "bitwarden-devops-bot"
- name: Create Version Branch
id: create-branch
run: |
NAME=version_bump_${{ github.ref_name }}_$(date +"%Y-%m-%d")
git switch -c $NAME
echo "name=$NAME" >> $GITHUB_OUTPUT
- name: Get current version - name: Get current version
id: current-version id: current-version
@@ -111,4 +145,61 @@ jobs:
- name: Push changes - name: Push changes
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }} if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
run: git push env:
PR_BRANCH: ${{ steps.create-branch.outputs.name }}
run: git push -u origin $PR_BRANCH
- name: Generate GH App token
uses: actions/create-github-app-token@3378cda945da322a8db4b193e19d46352ebe2de5 # v1.10.4
id: app-token
with:
app-id: ${{ secrets.BW_GHAPP_ID }}
private-key: ${{ secrets.BW_GHAPP_KEY }}
owner: ${{ github.repository_owner }}
- name: Create Version PR
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
id: create-pr
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
PR_BRANCH: ${{ steps.create-branch.outputs.name }}
TITLE: "Bump version to ${{ steps.set-final-version-output.outputs.version }}"
run: |
PR_URL=$(gh pr create --title "$TITLE" \
--base "main" \
--head "$PR_BRANCH" \
--label "version update" \
--label "automated pr" \
--body "
## Type of change
- [ ] Bug fix
- [ ] New feature development
- [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc)
- [ ] Build/deploy pipeline (DevOps)
- [X] Other
## Objective
Automated version bump to ${{ steps.set-final-version-output.outputs.version }}")
echo "pr_number=${PR_URL##*/}" >> $GITHUB_OUTPUT
- name: Approve PR
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ steps.create-pr.outputs.pr_number }}
run: gh pr review $PR_NUMBER --approve
- name: Merge PR
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
PR_NUMBER: ${{ steps.create-pr.outputs.pr_number }}
run: gh pr merge $PR_NUMBER --squash --auto --delete-branch
- name: Report upcoming release version to Slack
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' && inputs.enable_slack_notification == true }}
uses: bitwarden/gh-actions/report-upcoming-release-version@main
with:
version: ${{ steps.set-final-version-output.outputs.version }}
project: ${{ github.repository }}
AZURE_KV_CI_SERVICE_PRINCIPAL: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}

View File

@@ -3,13 +3,13 @@
# Bitwarden Directory Connector # Bitwarden Directory Connector
The Bitwarden Directory Connector is a desktop application used to sync your Bitwarden enterprise organization to an existing directory of users and groups. The Bitwarden Directory Connector is a a desktop application used to sync your Bitwarden enterprise organization to an existing directory of users and groups.
Supported directories: Supported directories:
- Active Directory - Active Directory
- Any other LDAP-based directory - Any other LDAP-based directory
- Microsoft Entra ID - Azure Active Directory
- G Suite (Google) - G Suite (Google)
- Okta - Okta

View File

@@ -1,18 +0,0 @@
services:
open-ldap:
image: bitnami/openldap:latest
hostname: openldap
environment:
- LDAP_ADMIN_USERNAME=admin
- LDAP_ADMIN_PASSWORD=admin
- LDAP_ROOT=dc=bitwarden,dc=com
- LDAP_ENABLE_TLS=yes
- LDAP_TLS_CERT_FILE=/certs/openldap.pem
- LDAP_TLS_KEY_FILE=/certs/openldap-key.pem
- LDAP_TLS_CA_FILE=/certs/rootCA.pem
volumes:
- "./openldap/ldifs:/ldifs"
- "./openldap/certs:/certs"
ports:
- "1389:1389"
- "1636:1636"

View File

@@ -1,14 +1,679 @@
import { PolicyType } from "../enums/policyType";
import { SetKeyConnectorKeyRequest } from "../models/request/account/setKeyConnectorKeyRequest";
import { VerifyOTPRequest } from "../models/request/account/verifyOTPRequest";
import { AttachmentRequest } from "../models/request/attachmentRequest";
import { BitPayInvoiceRequest } from "../models/request/bitPayInvoiceRequest";
import { CipherBulkDeleteRequest } from "../models/request/cipherBulkDeleteRequest";
import { CipherBulkMoveRequest } from "../models/request/cipherBulkMoveRequest";
import { CipherBulkRestoreRequest } from "../models/request/cipherBulkRestoreRequest";
import { CipherBulkShareRequest } from "../models/request/cipherBulkShareRequest";
import { CipherCollectionsRequest } from "../models/request/cipherCollectionsRequest";
import { CipherCreateRequest } from "../models/request/cipherCreateRequest";
import { CipherRequest } from "../models/request/cipherRequest";
import { CipherShareRequest } from "../models/request/cipherShareRequest";
import { CollectionRequest } from "../models/request/collectionRequest";
import { DeleteRecoverRequest } from "../models/request/deleteRecoverRequest";
import { EmailRequest } from "../models/request/emailRequest";
import { EmailTokenRequest } from "../models/request/emailTokenRequest";
import { EmergencyAccessAcceptRequest } from "../models/request/emergencyAccessAcceptRequest";
import { EmergencyAccessConfirmRequest } from "../models/request/emergencyAccessConfirmRequest";
import { EmergencyAccessInviteRequest } from "../models/request/emergencyAccessInviteRequest";
import { EmergencyAccessPasswordRequest } from "../models/request/emergencyAccessPasswordRequest";
import { EmergencyAccessUpdateRequest } from "../models/request/emergencyAccessUpdateRequest";
import { EventRequest } from "../models/request/eventRequest";
import { FolderRequest } from "../models/request/folderRequest";
import { GroupRequest } from "../models/request/groupRequest";
import { IapCheckRequest } from "../models/request/iapCheckRequest";
import { ApiTokenRequest } from "../models/request/identityToken/apiTokenRequest"; import { ApiTokenRequest } from "../models/request/identityToken/apiTokenRequest";
import { PasswordTokenRequest } from "../models/request/identityToken/passwordTokenRequest"; import { PasswordTokenRequest } from "../models/request/identityToken/passwordTokenRequest";
import { SsoTokenRequest } from "../models/request/identityToken/ssoTokenRequest"; import { SsoTokenRequest } from "../models/request/identityToken/ssoTokenRequest";
import { ImportCiphersRequest } from "../models/request/importCiphersRequest";
import { ImportDirectoryRequest } from "../models/request/importDirectoryRequest";
import { ImportOrganizationCiphersRequest } from "../models/request/importOrganizationCiphersRequest";
import { KdfRequest } from "../models/request/kdfRequest";
import { KeyConnectorUserKeyRequest } from "../models/request/keyConnectorUserKeyRequest";
import { KeysRequest } from "../models/request/keysRequest";
import { OrganizationSponsorshipCreateRequest } from "../models/request/organization/organizationSponsorshipCreateRequest";
import { OrganizationSponsorshipRedeemRequest } from "../models/request/organization/organizationSponsorshipRedeemRequest";
import { OrganizationSsoRequest } from "../models/request/organization/organizationSsoRequest";
import { OrganizationCreateRequest } from "../models/request/organizationCreateRequest";
import { OrganizationImportRequest } from "../models/request/organizationImportRequest"; import { OrganizationImportRequest } from "../models/request/organizationImportRequest";
import { OrganizationKeysRequest } from "../models/request/organizationKeysRequest";
import { OrganizationSubscriptionUpdateRequest } from "../models/request/organizationSubscriptionUpdateRequest";
import { OrganizationTaxInfoUpdateRequest } from "../models/request/organizationTaxInfoUpdateRequest";
import { OrganizationUpdateRequest } from "../models/request/organizationUpdateRequest";
import { OrganizationUpgradeRequest } from "../models/request/organizationUpgradeRequest";
import { OrganizationUserAcceptRequest } from "../models/request/organizationUserAcceptRequest";
import { OrganizationUserBulkConfirmRequest } from "../models/request/organizationUserBulkConfirmRequest";
import { OrganizationUserBulkRequest } from "../models/request/organizationUserBulkRequest";
import { OrganizationUserConfirmRequest } from "../models/request/organizationUserConfirmRequest";
import { OrganizationUserInviteRequest } from "../models/request/organizationUserInviteRequest";
import { OrganizationUserResetPasswordEnrollmentRequest } from "../models/request/organizationUserResetPasswordEnrollmentRequest";
import { OrganizationUserResetPasswordRequest } from "../models/request/organizationUserResetPasswordRequest";
import { OrganizationUserUpdateGroupsRequest } from "../models/request/organizationUserUpdateGroupsRequest";
import { OrganizationUserUpdateRequest } from "../models/request/organizationUserUpdateRequest";
import { PasswordHintRequest } from "../models/request/passwordHintRequest";
import { PasswordRequest } from "../models/request/passwordRequest";
import { PaymentRequest } from "../models/request/paymentRequest";
import { PolicyRequest } from "../models/request/policyRequest";
import { PreloginRequest } from "../models/request/preloginRequest";
import { ProviderAddOrganizationRequest } from "../models/request/provider/providerAddOrganizationRequest";
import { ProviderOrganizationCreateRequest } from "../models/request/provider/providerOrganizationCreateRequest";
import { ProviderSetupRequest } from "../models/request/provider/providerSetupRequest";
import { ProviderUpdateRequest } from "../models/request/provider/providerUpdateRequest";
import { ProviderUserAcceptRequest } from "../models/request/provider/providerUserAcceptRequest";
import { ProviderUserBulkConfirmRequest } from "../models/request/provider/providerUserBulkConfirmRequest";
import { ProviderUserBulkRequest } from "../models/request/provider/providerUserBulkRequest";
import { ProviderUserConfirmRequest } from "../models/request/provider/providerUserConfirmRequest";
import { ProviderUserInviteRequest } from "../models/request/provider/providerUserInviteRequest";
import { ProviderUserUpdateRequest } from "../models/request/provider/providerUserUpdateRequest";
import { RegisterRequest } from "../models/request/registerRequest";
import { SeatRequest } from "../models/request/seatRequest";
import { SecretVerificationRequest } from "../models/request/secretVerificationRequest";
import { SelectionReadOnlyRequest } from "../models/request/selectionReadOnlyRequest";
import { SendAccessRequest } from "../models/request/sendAccessRequest";
import { SendRequest } from "../models/request/sendRequest";
import { SetPasswordRequest } from "../models/request/setPasswordRequest";
import { StorageRequest } from "../models/request/storageRequest";
import { TaxInfoUpdateRequest } from "../models/request/taxInfoUpdateRequest";
import { TwoFactorEmailRequest } from "../models/request/twoFactorEmailRequest";
import { TwoFactorProviderRequest } from "../models/request/twoFactorProviderRequest";
import { TwoFactorRecoveryRequest } from "../models/request/twoFactorRecoveryRequest";
import { UpdateDomainsRequest } from "../models/request/updateDomainsRequest";
import { UpdateKeyRequest } from "../models/request/updateKeyRequest";
import { UpdateProfileRequest } from "../models/request/updateProfileRequest";
import { UpdateTempPasswordRequest } from "../models/request/updateTempPasswordRequest";
import { UpdateTwoFactorAuthenticatorRequest } from "../models/request/updateTwoFactorAuthenticatorRequest";
import { UpdateTwoFactorDuoRequest } from "../models/request/updateTwoFactorDuoRequest";
import { UpdateTwoFactorEmailRequest } from "../models/request/updateTwoFactorEmailRequest";
import { UpdateTwoFactorWebAuthnDeleteRequest } from "../models/request/updateTwoFactorWebAuthnDeleteRequest";
import { UpdateTwoFactorWebAuthnRequest } from "../models/request/updateTwoFactorWebAuthnRequest";
import { UpdateTwoFactorYubioOtpRequest } from "../models/request/updateTwoFactorYubioOtpRequest";
import { VerifyBankRequest } from "../models/request/verifyBankRequest";
import { VerifyDeleteRecoverRequest } from "../models/request/verifyDeleteRecoverRequest";
import { VerifyEmailRequest } from "../models/request/verifyEmailRequest";
import { ApiKeyResponse } from "../models/response/apiKeyResponse";
import { AttachmentResponse } from "../models/response/attachmentResponse";
import { AttachmentUploadDataResponse } from "../models/response/attachmentUploadDataResponse";
import { BillingResponse } from "../models/response/billingResponse";
import { BreachAccountResponse } from "../models/response/breachAccountResponse";
import { CipherResponse } from "../models/response/cipherResponse";
import {
CollectionGroupDetailsResponse,
CollectionResponse,
} from "../models/response/collectionResponse";
import { DomainsResponse } from "../models/response/domainsResponse";
import {
EmergencyAccessGranteeDetailsResponse,
EmergencyAccessGrantorDetailsResponse,
EmergencyAccessTakeoverResponse,
EmergencyAccessViewResponse,
} from "../models/response/emergencyAccessResponse";
import { EventResponse } from "../models/response/eventResponse";
import { FolderResponse } from "../models/response/folderResponse";
import { GroupDetailsResponse, GroupResponse } from "../models/response/groupResponse";
import { IdentityCaptchaResponse } from "../models/response/identityCaptchaResponse"; import { IdentityCaptchaResponse } from "../models/response/identityCaptchaResponse";
import { IdentityTokenResponse } from "../models/response/identityTokenResponse"; import { IdentityTokenResponse } from "../models/response/identityTokenResponse";
import { IdentityTwoFactorResponse } from "../models/response/identityTwoFactorResponse"; import { IdentityTwoFactorResponse } from "../models/response/identityTwoFactorResponse";
import { KeyConnectorUserKeyResponse } from "../models/response/keyConnectorUserKeyResponse";
import { ListResponse } from "../models/response/listResponse";
import { OrganizationSsoResponse } from "../models/response/organization/organizationSsoResponse";
import { OrganizationAutoEnrollStatusResponse } from "../models/response/organizationAutoEnrollStatusResponse";
import { OrganizationKeysResponse } from "../models/response/organizationKeysResponse";
import { OrganizationResponse } from "../models/response/organizationResponse";
import { OrganizationSubscriptionResponse } from "../models/response/organizationSubscriptionResponse";
import { OrganizationUserBulkPublicKeyResponse } from "../models/response/organizationUserBulkPublicKeyResponse";
import { OrganizationUserBulkResponse } from "../models/response/organizationUserBulkResponse";
import {
OrganizationUserDetailsResponse,
OrganizationUserResetPasswordDetailsReponse,
OrganizationUserUserDetailsResponse,
} from "../models/response/organizationUserResponse";
import { PaymentResponse } from "../models/response/paymentResponse";
import { PlanResponse } from "../models/response/planResponse";
import { PolicyResponse } from "../models/response/policyResponse";
import { PreloginResponse } from "../models/response/preloginResponse";
import { ProfileResponse } from "../models/response/profileResponse";
import {
ProviderOrganizationOrganizationDetailsResponse,
ProviderOrganizationResponse,
} from "../models/response/provider/providerOrganizationResponse";
import { ProviderResponse } from "../models/response/provider/providerResponse";
import { ProviderUserBulkPublicKeyResponse } from "../models/response/provider/providerUserBulkPublicKeyResponse";
import { ProviderUserBulkResponse } from "../models/response/provider/providerUserBulkResponse";
import {
ProviderUserResponse,
ProviderUserUserDetailsResponse,
} from "../models/response/provider/providerUserResponse";
import { SelectionReadOnlyResponse } from "../models/response/selectionReadOnlyResponse";
import { SendAccessResponse } from "../models/response/sendAccessResponse";
import { SendFileDownloadDataResponse } from "../models/response/sendFileDownloadDataResponse";
import { SendFileUploadDataResponse } from "../models/response/sendFileUploadDataResponse";
import { SendResponse } from "../models/response/sendResponse";
import { SubscriptionResponse } from "../models/response/subscriptionResponse";
import { SyncResponse } from "../models/response/syncResponse";
import { TaxInfoResponse } from "../models/response/taxInfoResponse";
import { TaxRateResponse } from "../models/response/taxRateResponse";
import { TwoFactorAuthenticatorResponse } from "../models/response/twoFactorAuthenticatorResponse";
import { TwoFactorDuoResponse } from "../models/response/twoFactorDuoResponse";
import { TwoFactorEmailResponse } from "../models/response/twoFactorEmailResponse";
import { TwoFactorProviderResponse } from "../models/response/twoFactorProviderResponse";
import { TwoFactorRecoverResponse } from "../models/response/twoFactorRescoverResponse";
import {
ChallengeResponse,
TwoFactorWebAuthnResponse,
} from "../models/response/twoFactorWebAuthnResponse";
import { TwoFactorYubiKeyResponse } from "../models/response/twoFactorYubiKeyResponse";
import { UserKeyResponse } from "../models/response/userKeyResponse";
import { SendAccessView } from "../models/view/sendAccessView";
export abstract class ApiService { export abstract class ApiService {
postIdentityToken: ( postIdentityToken: (
request: PasswordTokenRequest | SsoTokenRequest | ApiTokenRequest, request: PasswordTokenRequest | SsoTokenRequest | ApiTokenRequest,
) => Promise<IdentityTokenResponse | IdentityTwoFactorResponse | IdentityCaptchaResponse>; ) => Promise<IdentityTokenResponse | IdentityTwoFactorResponse | IdentityCaptchaResponse>;
refreshIdentityToken: () => Promise<any>;
getProfile: () => Promise<ProfileResponse>;
getUserBilling: () => Promise<BillingResponse>;
getUserSubscription: () => Promise<SubscriptionResponse>;
getTaxInfo: () => Promise<TaxInfoResponse>;
putProfile: (request: UpdateProfileRequest) => Promise<ProfileResponse>;
putTaxInfo: (request: TaxInfoUpdateRequest) => Promise<any>;
postPrelogin: (request: PreloginRequest) => Promise<PreloginResponse>;
postEmailToken: (request: EmailTokenRequest) => Promise<any>;
postEmail: (request: EmailRequest) => Promise<any>;
postPassword: (request: PasswordRequest) => Promise<any>;
setPassword: (request: SetPasswordRequest) => Promise<any>;
postSetKeyConnectorKey: (request: SetKeyConnectorKeyRequest) => Promise<any>;
postSecurityStamp: (request: SecretVerificationRequest) => Promise<any>;
deleteAccount: (request: SecretVerificationRequest) => Promise<any>;
getAccountRevisionDate: () => Promise<number>;
postPasswordHint: (request: PasswordHintRequest) => Promise<any>;
postRegister: (request: RegisterRequest) => Promise<any>;
postPremium: (data: FormData) => Promise<PaymentResponse>;
postIapCheck: (request: IapCheckRequest) => Promise<any>;
postReinstatePremium: () => Promise<any>;
postCancelPremium: () => Promise<any>;
postAccountStorage: (request: StorageRequest) => Promise<PaymentResponse>;
postAccountPayment: (request: PaymentRequest) => Promise<any>;
postAccountLicense: (data: FormData) => Promise<any>;
postAccountKey: (request: UpdateKeyRequest) => Promise<any>;
postAccountKeys: (request: KeysRequest) => Promise<any>;
postAccountVerifyEmail: () => Promise<any>;
postAccountVerifyEmailToken: (request: VerifyEmailRequest) => Promise<any>;
postAccountVerifyPassword: (request: SecretVerificationRequest) => Promise<any>;
postAccountRecoverDelete: (request: DeleteRecoverRequest) => Promise<any>;
postAccountRecoverDeleteToken: (request: VerifyDeleteRecoverRequest) => Promise<any>;
postAccountKdf: (request: KdfRequest) => Promise<any>;
postUserApiKey: (id: string, request: SecretVerificationRequest) => Promise<ApiKeyResponse>;
postUserRotateApiKey: (id: string, request: SecretVerificationRequest) => Promise<ApiKeyResponse>;
putUpdateTempPassword: (request: UpdateTempPasswordRequest) => Promise<any>;
postAccountRequestOTP: () => Promise<void>;
postAccountVerifyOTP: (request: VerifyOTPRequest) => Promise<void>;
postConvertToKeyConnector: () => Promise<void>;
getFolder: (id: string) => Promise<FolderResponse>;
postFolder: (request: FolderRequest) => Promise<FolderResponse>;
putFolder: (id: string, request: FolderRequest) => Promise<FolderResponse>;
deleteFolder: (id: string) => Promise<any>;
getSend: (id: string) => Promise<SendResponse>;
postSendAccess: (
id: string,
request: SendAccessRequest,
apiUrl?: string,
) => Promise<SendAccessResponse>;
getSends: () => Promise<ListResponse<SendResponse>>;
postSend: (request: SendRequest) => Promise<SendResponse>;
postFileTypeSend: (request: SendRequest) => Promise<SendFileUploadDataResponse>;
postSendFile: (sendId: string, fileId: string, data: FormData) => Promise<any>;
/**
* @deprecated Mar 25 2021: This method has been deprecated in favor of direct uploads.
* This method still exists for backward compatibility with old server versions.
*/
postSendFileLegacy: (data: FormData) => Promise<SendResponse>;
putSend: (id: string, request: SendRequest) => Promise<SendResponse>;
putSendRemovePassword: (id: string) => Promise<SendResponse>;
deleteSend: (id: string) => Promise<any>;
getSendFileDownloadData: (
send: SendAccessView,
request: SendAccessRequest,
apiUrl?: string,
) => Promise<SendFileDownloadDataResponse>;
renewSendFileUploadUrl: (sendId: string, fileId: string) => Promise<SendFileUploadDataResponse>;
getCipher: (id: string) => Promise<CipherResponse>;
getCipherAdmin: (id: string) => Promise<CipherResponse>;
getAttachmentData: (
cipherId: string,
attachmentId: string,
emergencyAccessId?: string,
) => Promise<AttachmentResponse>;
getCiphersOrganization: (organizationId: string) => Promise<ListResponse<CipherResponse>>;
postCipher: (request: CipherRequest) => Promise<CipherResponse>;
postCipherCreate: (request: CipherCreateRequest) => Promise<CipherResponse>;
postCipherAdmin: (request: CipherCreateRequest) => Promise<CipherResponse>;
putCipher: (id: string, request: CipherRequest) => Promise<CipherResponse>;
putCipherAdmin: (id: string, request: CipherRequest) => Promise<CipherResponse>;
deleteCipher: (id: string) => Promise<any>;
deleteCipherAdmin: (id: string) => Promise<any>;
deleteManyCiphers: (request: CipherBulkDeleteRequest) => Promise<any>;
deleteManyCiphersAdmin: (request: CipherBulkDeleteRequest) => Promise<any>;
putMoveCiphers: (request: CipherBulkMoveRequest) => Promise<any>;
putShareCipher: (id: string, request: CipherShareRequest) => Promise<CipherResponse>;
putShareCiphers: (request: CipherBulkShareRequest) => Promise<any>;
putCipherCollections: (id: string, request: CipherCollectionsRequest) => Promise<any>;
putCipherCollectionsAdmin: (id: string, request: CipherCollectionsRequest) => Promise<any>;
postPurgeCiphers: (request: SecretVerificationRequest, organizationId?: string) => Promise<any>;
postImportCiphers: (request: ImportCiphersRequest) => Promise<any>;
postImportOrganizationCiphers: (
organizationId: string,
request: ImportOrganizationCiphersRequest,
) => Promise<any>;
putDeleteCipher: (id: string) => Promise<any>;
putDeleteCipherAdmin: (id: string) => Promise<any>;
putDeleteManyCiphers: (request: CipherBulkDeleteRequest) => Promise<any>;
putDeleteManyCiphersAdmin: (request: CipherBulkDeleteRequest) => Promise<any>;
putRestoreCipher: (id: string) => Promise<CipherResponse>;
putRestoreCipherAdmin: (id: string) => Promise<CipherResponse>;
putRestoreManyCiphers: (
request: CipherBulkRestoreRequest,
) => Promise<ListResponse<CipherResponse>>;
/**
* @deprecated Mar 25 2021: This method has been deprecated in favor of direct uploads.
* This method still exists for backward compatibility with old server versions.
*/
postCipherAttachmentLegacy: (id: string, data: FormData) => Promise<CipherResponse>;
/**
* @deprecated Mar 25 2021: This method has been deprecated in favor of direct uploads.
* This method still exists for backward compatibility with old server versions.
*/
postCipherAttachmentAdminLegacy: (id: string, data: FormData) => Promise<CipherResponse>;
postCipherAttachment: (
id: string,
request: AttachmentRequest,
) => Promise<AttachmentUploadDataResponse>;
deleteCipherAttachment: (id: string, attachmentId: string) => Promise<any>;
deleteCipherAttachmentAdmin: (id: string, attachmentId: string) => Promise<any>;
postShareCipherAttachment: (
id: string,
attachmentId: string,
data: FormData,
organizationId: string,
) => Promise<any>;
renewAttachmentUploadUrl: (
id: string,
attachmentId: string,
) => Promise<AttachmentUploadDataResponse>;
postAttachmentFile: (id: string, attachmentId: string, data: FormData) => Promise<any>;
getCollectionDetails: (
organizationId: string,
id: string,
) => Promise<CollectionGroupDetailsResponse>;
getUserCollections: () => Promise<ListResponse<CollectionResponse>>;
getCollections: (organizationId: string) => Promise<ListResponse<CollectionResponse>>;
getCollectionUsers: (organizationId: string, id: string) => Promise<SelectionReadOnlyResponse[]>;
postCollection: (
organizationId: string,
request: CollectionRequest,
) => Promise<CollectionResponse>;
putCollectionUsers: (
organizationId: string,
id: string,
request: SelectionReadOnlyRequest[],
) => Promise<any>;
putCollection: (
organizationId: string,
id: string,
request: CollectionRequest,
) => Promise<CollectionResponse>;
deleteCollection: (organizationId: string, id: string) => Promise<any>;
deleteCollectionUser: (
organizationId: string,
id: string,
organizationUserId: string,
) => Promise<any>;
getGroupDetails: (organizationId: string, id: string) => Promise<GroupDetailsResponse>;
getGroups: (organizationId: string) => Promise<ListResponse<GroupResponse>>;
getGroupUsers: (organizationId: string, id: string) => Promise<string[]>;
postGroup: (organizationId: string, request: GroupRequest) => Promise<GroupResponse>;
putGroup: (organizationId: string, id: string, request: GroupRequest) => Promise<GroupResponse>;
putGroupUsers: (organizationId: string, id: string, request: string[]) => Promise<any>;
deleteGroup: (organizationId: string, id: string) => Promise<any>;
deleteGroupUser: (organizationId: string, id: string, organizationUserId: string) => Promise<any>;
getPolicy: (organizationId: string, type: PolicyType) => Promise<PolicyResponse>;
getPolicies: (organizationId: string) => Promise<ListResponse<PolicyResponse>>;
getPoliciesByToken: (
organizationId: string,
token: string,
email: string,
organizationUserId: string,
) => Promise<ListResponse<PolicyResponse>>;
getPoliciesByInvitedUser: (
organizationId: string,
userId: string,
) => Promise<ListResponse<PolicyResponse>>;
putPolicy: (
organizationId: string,
type: PolicyType,
request: PolicyRequest,
) => Promise<PolicyResponse>;
getOrganizationUser: (
organizationId: string,
id: string,
) => Promise<OrganizationUserDetailsResponse>;
getOrganizationUserGroups: (organizationId: string, id: string) => Promise<string[]>;
getOrganizationUsers: (
organizationId: string,
) => Promise<ListResponse<OrganizationUserUserDetailsResponse>>;
getOrganizationUserResetPasswordDetails: (
organizationId: string,
id: string,
) => Promise<OrganizationUserResetPasswordDetailsReponse>;
postOrganizationUserInvite: (
organizationId: string,
request: OrganizationUserInviteRequest,
) => Promise<any>;
postOrganizationUserReinvite: (organizationId: string, id: string) => Promise<any>;
postManyOrganizationUserReinvite: (
organizationId: string,
request: OrganizationUserBulkRequest,
) => Promise<ListResponse<OrganizationUserBulkResponse>>;
postOrganizationUserAccept: (
organizationId: string,
id: string,
request: OrganizationUserAcceptRequest,
) => Promise<any>;
postOrganizationUserConfirm: (
organizationId: string,
id: string,
request: OrganizationUserConfirmRequest,
) => Promise<any>;
postOrganizationUsersPublicKey: (
organizationId: string,
request: OrganizationUserBulkRequest,
) => Promise<ListResponse<OrganizationUserBulkPublicKeyResponse>>;
postOrganizationUserBulkConfirm: (
organizationId: string,
request: OrganizationUserBulkConfirmRequest,
) => Promise<ListResponse<OrganizationUserBulkResponse>>;
putOrganizationUser: (
organizationId: string,
id: string,
request: OrganizationUserUpdateRequest,
) => Promise<any>;
putOrganizationUserGroups: (
organizationId: string,
id: string,
request: OrganizationUserUpdateGroupsRequest,
) => Promise<any>;
putOrganizationUserResetPasswordEnrollment: (
organizationId: string,
userId: string,
request: OrganizationUserResetPasswordEnrollmentRequest,
) => Promise<any>;
putOrganizationUserResetPassword: (
organizationId: string,
id: string,
request: OrganizationUserResetPasswordRequest,
) => Promise<any>;
deleteOrganizationUser: (organizationId: string, id: string) => Promise<any>;
deleteManyOrganizationUsers: (
organizationId: string,
request: OrganizationUserBulkRequest,
) => Promise<ListResponse<OrganizationUserBulkResponse>>;
getSync: () => Promise<SyncResponse>;
postImportDirectory: (organizationId: string, request: ImportDirectoryRequest) => Promise<any>;
postPublicImportDirectory: (request: OrganizationImportRequest) => Promise<any>; postPublicImportDirectory: (request: OrganizationImportRequest) => Promise<any>;
getSettingsDomains: () => Promise<DomainsResponse>;
putSettingsDomains: (request: UpdateDomainsRequest) => Promise<DomainsResponse>;
getTwoFactorProviders: () => Promise<ListResponse<TwoFactorProviderResponse>>;
getTwoFactorOrganizationProviders: (
organizationId: string,
) => Promise<ListResponse<TwoFactorProviderResponse>>;
getTwoFactorAuthenticator: (
request: SecretVerificationRequest,
) => Promise<TwoFactorAuthenticatorResponse>;
getTwoFactorEmail: (request: SecretVerificationRequest) => Promise<TwoFactorEmailResponse>;
getTwoFactorDuo: (request: SecretVerificationRequest) => Promise<TwoFactorDuoResponse>;
getTwoFactorOrganizationDuo: (
organizationId: string,
request: SecretVerificationRequest,
) => Promise<TwoFactorDuoResponse>;
getTwoFactorYubiKey: (request: SecretVerificationRequest) => Promise<TwoFactorYubiKeyResponse>;
getTwoFactorWebAuthn: (request: SecretVerificationRequest) => Promise<TwoFactorWebAuthnResponse>;
getTwoFactorWebAuthnChallenge: (request: SecretVerificationRequest) => Promise<ChallengeResponse>;
getTwoFactorRecover: (request: SecretVerificationRequest) => Promise<TwoFactorRecoverResponse>;
putTwoFactorAuthenticator: (
request: UpdateTwoFactorAuthenticatorRequest,
) => Promise<TwoFactorAuthenticatorResponse>;
putTwoFactorEmail: (request: UpdateTwoFactorEmailRequest) => Promise<TwoFactorEmailResponse>;
putTwoFactorDuo: (request: UpdateTwoFactorDuoRequest) => Promise<TwoFactorDuoResponse>;
putTwoFactorOrganizationDuo: (
organizationId: string,
request: UpdateTwoFactorDuoRequest,
) => Promise<TwoFactorDuoResponse>;
putTwoFactorYubiKey: (
request: UpdateTwoFactorYubioOtpRequest,
) => Promise<TwoFactorYubiKeyResponse>;
putTwoFactorWebAuthn: (
request: UpdateTwoFactorWebAuthnRequest,
) => Promise<TwoFactorWebAuthnResponse>;
deleteTwoFactorWebAuthn: (
request: UpdateTwoFactorWebAuthnDeleteRequest,
) => Promise<TwoFactorWebAuthnResponse>;
putTwoFactorDisable: (request: TwoFactorProviderRequest) => Promise<TwoFactorProviderResponse>;
putTwoFactorOrganizationDisable: (
organizationId: string,
request: TwoFactorProviderRequest,
) => Promise<TwoFactorProviderResponse>;
postTwoFactorRecover: (request: TwoFactorRecoveryRequest) => Promise<any>;
postTwoFactorEmailSetup: (request: TwoFactorEmailRequest) => Promise<any>;
postTwoFactorEmail: (request: TwoFactorEmailRequest) => Promise<any>;
getEmergencyAccessTrusted: () => Promise<ListResponse<EmergencyAccessGranteeDetailsResponse>>;
getEmergencyAccessGranted: () => Promise<ListResponse<EmergencyAccessGrantorDetailsResponse>>;
getEmergencyAccess: (id: string) => Promise<EmergencyAccessGranteeDetailsResponse>;
getEmergencyGrantorPolicies: (id: string) => Promise<ListResponse<PolicyResponse>>;
putEmergencyAccess: (id: string, request: EmergencyAccessUpdateRequest) => Promise<any>;
deleteEmergencyAccess: (id: string) => Promise<any>;
postEmergencyAccessInvite: (request: EmergencyAccessInviteRequest) => Promise<any>;
postEmergencyAccessReinvite: (id: string) => Promise<any>;
postEmergencyAccessAccept: (id: string, request: EmergencyAccessAcceptRequest) => Promise<any>;
postEmergencyAccessConfirm: (id: string, request: EmergencyAccessConfirmRequest) => Promise<any>;
postEmergencyAccessInitiate: (id: string) => Promise<any>;
postEmergencyAccessApprove: (id: string) => Promise<any>;
postEmergencyAccessReject: (id: string) => Promise<any>;
postEmergencyAccessTakeover: (id: string) => Promise<EmergencyAccessTakeoverResponse>;
postEmergencyAccessPassword: (
id: string,
request: EmergencyAccessPasswordRequest,
) => Promise<any>;
postEmergencyAccessView: (id: string) => Promise<EmergencyAccessViewResponse>;
getOrganization: (id: string) => Promise<OrganizationResponse>;
getOrganizationBilling: (id: string) => Promise<BillingResponse>;
getOrganizationSubscription: (id: string) => Promise<OrganizationSubscriptionResponse>;
getOrganizationLicense: (id: string, installationId: string) => Promise<any>;
getOrganizationTaxInfo: (id: string) => Promise<TaxInfoResponse>;
getOrganizationAutoEnrollStatus: (
identifier: string,
) => Promise<OrganizationAutoEnrollStatusResponse>;
getOrganizationSso: (id: string) => Promise<OrganizationSsoResponse>;
postOrganization: (request: OrganizationCreateRequest) => Promise<OrganizationResponse>;
putOrganization: (
id: string,
request: OrganizationUpdateRequest,
) => Promise<OrganizationResponse>;
putOrganizationTaxInfo: (id: string, request: OrganizationTaxInfoUpdateRequest) => Promise<any>;
postLeaveOrganization: (id: string) => Promise<any>;
postOrganizationLicense: (data: FormData) => Promise<OrganizationResponse>;
postOrganizationLicenseUpdate: (id: string, data: FormData) => Promise<any>;
postOrganizationApiKey: (
id: string,
request: SecretVerificationRequest,
) => Promise<ApiKeyResponse>;
postOrganizationRotateApiKey: (
id: string,
request: SecretVerificationRequest,
) => Promise<ApiKeyResponse>;
postOrganizationSso: (
id: string,
request: OrganizationSsoRequest,
) => Promise<OrganizationSsoResponse>;
postOrganizationUpgrade: (
id: string,
request: OrganizationUpgradeRequest,
) => Promise<PaymentResponse>;
postOrganizationUpdateSubscription: (
id: string,
request: OrganizationSubscriptionUpdateRequest,
) => Promise<void>;
postOrganizationSeat: (id: string, request: SeatRequest) => Promise<PaymentResponse>;
postOrganizationStorage: (id: string, request: StorageRequest) => Promise<any>;
postOrganizationPayment: (id: string, request: PaymentRequest) => Promise<any>;
postOrganizationVerifyBank: (id: string, request: VerifyBankRequest) => Promise<any>;
postOrganizationCancel: (id: string) => Promise<any>;
postOrganizationReinstate: (id: string) => Promise<any>;
deleteOrganization: (id: string, request: SecretVerificationRequest) => Promise<any>;
getPlans: () => Promise<ListResponse<PlanResponse>>;
getTaxRates: () => Promise<ListResponse<TaxRateResponse>>;
getOrganizationKeys: (id: string) => Promise<OrganizationKeysResponse>;
postOrganizationKeys: (
id: string,
request: OrganizationKeysRequest,
) => Promise<OrganizationKeysResponse>;
postProviderSetup: (id: string, request: ProviderSetupRequest) => Promise<ProviderResponse>;
getProvider: (id: string) => Promise<ProviderResponse>;
putProvider: (id: string, request: ProviderUpdateRequest) => Promise<ProviderResponse>;
getProviderUsers: (providerId: string) => Promise<ListResponse<ProviderUserUserDetailsResponse>>;
getProviderUser: (providerId: string, id: string) => Promise<ProviderUserResponse>;
postProviderUserInvite: (providerId: string, request: ProviderUserInviteRequest) => Promise<any>;
postProviderUserReinvite: (providerId: string, id: string) => Promise<any>;
postManyProviderUserReinvite: (
providerId: string,
request: ProviderUserBulkRequest,
) => Promise<ListResponse<ProviderUserBulkResponse>>;
postProviderUserAccept: (
providerId: string,
id: string,
request: ProviderUserAcceptRequest,
) => Promise<any>;
postProviderUserConfirm: (
providerId: string,
id: string,
request: ProviderUserConfirmRequest,
) => Promise<any>;
postProviderUsersPublicKey: (
providerId: string,
request: ProviderUserBulkRequest,
) => Promise<ListResponse<ProviderUserBulkPublicKeyResponse>>;
postProviderUserBulkConfirm: (
providerId: string,
request: ProviderUserBulkConfirmRequest,
) => Promise<ListResponse<ProviderUserBulkResponse>>;
putProviderUser: (
providerId: string,
id: string,
request: ProviderUserUpdateRequest,
) => Promise<any>;
deleteProviderUser: (organizationId: string, id: string) => Promise<any>;
deleteManyProviderUsers: (
providerId: string,
request: ProviderUserBulkRequest,
) => Promise<ListResponse<ProviderUserBulkResponse>>;
getProviderClients: (
providerId: string,
) => Promise<ListResponse<ProviderOrganizationOrganizationDetailsResponse>>;
postProviderAddOrganization: (
providerId: string,
request: ProviderAddOrganizationRequest,
) => Promise<any>;
postProviderCreateOrganization: (
providerId: string,
request: ProviderOrganizationCreateRequest,
) => Promise<ProviderOrganizationResponse>;
deleteProviderOrganization: (providerId: string, organizationId: string) => Promise<any>;
getEvents: (start: string, end: string, token: string) => Promise<ListResponse<EventResponse>>;
getEventsCipher: (
id: string,
start: string,
end: string,
token: string,
) => Promise<ListResponse<EventResponse>>;
getEventsOrganization: (
id: string,
start: string,
end: string,
token: string,
) => Promise<ListResponse<EventResponse>>;
getEventsOrganizationUser: (
organizationId: string,
id: string,
start: string,
end: string,
token: string,
) => Promise<ListResponse<EventResponse>>;
getEventsProvider: (
id: string,
start: string,
end: string,
token: string,
) => Promise<ListResponse<EventResponse>>;
getEventsProviderUser: (
providerId: string,
id: string,
start: string,
end: string,
token: string,
) => Promise<ListResponse<EventResponse>>;
postEventsCollect: (request: EventRequest[]) => Promise<any>;
deleteSsoUser: (organizationId: string) => Promise<any>;
getSsoUserIdentifier: () => Promise<string>;
getUserPublicKey: (id: string) => Promise<UserKeyResponse>;
getHibpBreach: (username: string) => Promise<BreachAccountResponse[]>;
postBitPayInvoice: (request: BitPayInvoiceRequest) => Promise<string>;
postSetupPayment: () => Promise<string>;
getActiveBearerToken: () => Promise<string>;
fetch: (request: Request) => Promise<Response>;
nativeFetch: (request: Request) => Promise<Response>;
preValidateSso: (identifier: string) => Promise<boolean>;
postCreateSponsorship: (
sponsorshipOrgId: string,
request: OrganizationSponsorshipCreateRequest,
) => Promise<void>;
deleteRevokeSponsorship: (sponsoringOrganizationId: string) => Promise<void>;
deleteRemoveSponsorship: (sponsoringOrgId: string) => Promise<void>;
postPreValidateSponsorshipToken: (sponsorshipToken: string) => Promise<boolean>;
postRedeemSponsorship: (
sponsorshipToken: string,
request: OrganizationSponsorshipRedeemRequest,
) => Promise<void>;
postResendSponsorshipOffer: (sponsoringOrgId: string) => Promise<void>;
getUserKeyFromKeyConnector: (keyConnectorUrl: string) => Promise<KeyConnectorUserKeyResponse>;
postUserKeyToKeyConnector: (
keyConnectorUrl: string,
request: KeyConnectorUserKeyRequest,
) => Promise<void>;
getKeyConnectorAlive: (keyConnectorUrl: string) => Promise<void>;
} }

View File

@@ -0,0 +1,24 @@
import { KdfType } from "../../../enums/kdfType";
import { KeysRequest } from "../keysRequest";
export class SetKeyConnectorKeyRequest {
key: string;
keys: KeysRequest;
kdf: KdfType;
kdfIterations: number;
orgIdentifier: string;
constructor(
key: string,
kdf: KdfType,
kdfIterations: number,
orgIdentifier: string,
keys: KeysRequest,
) {
this.key = key;
this.kdf = kdf;
this.kdfIterations = kdfIterations;
this.orgIdentifier = orgIdentifier;
this.keys = keys;
}
}

View File

@@ -0,0 +1,7 @@
export class VerifyOTPRequest {
OTP: string;
constructor(OTP: string) {
this.OTP = OTP;
}
}

View File

@@ -0,0 +1,6 @@
export class AttachmentRequest {
fileName: string;
key: string;
fileSize: number;
adminRequest: boolean;
}

View File

@@ -0,0 +1,9 @@
export class BitPayInvoiceRequest {
userId: string;
organizationId: string;
credit: boolean;
amount: number;
returnUrl: string;
name: string;
email: string;
}

View File

@@ -0,0 +1,9 @@
export class CipherBulkDeleteRequest {
ids: string[];
organizationId: string;
constructor(ids: string[], organizationId?: string) {
this.ids = ids == null ? [] : ids;
this.organizationId = organizationId;
}
}

View File

@@ -0,0 +1,9 @@
export class CipherBulkMoveRequest {
ids: string[];
folderId: string;
constructor(ids: string[], folderId: string) {
this.ids = ids == null ? [] : ids;
this.folderId = folderId;
}
}

View File

@@ -0,0 +1,7 @@
export class CipherBulkRestoreRequest {
ids: string[];
constructor(ids: string[]) {
this.ids = ids == null ? [] : ids;
}
}

View File

@@ -0,0 +1,18 @@
import { Cipher } from "../domain/cipher";
import { CipherWithIdRequest } from "./cipherWithIdRequest";
export class CipherBulkShareRequest {
ciphers: CipherWithIdRequest[];
collectionIds: string[];
constructor(ciphers: Cipher[], collectionIds: string[]) {
if (ciphers != null) {
this.ciphers = [];
ciphers.forEach((c) => {
this.ciphers.push(new CipherWithIdRequest(c));
});
}
this.collectionIds = collectionIds;
}
}

View File

@@ -0,0 +1,7 @@
export class CipherCollectionsRequest {
collectionIds: string[];
constructor(collectionIds: string[]) {
this.collectionIds = collectionIds == null ? [] : collectionIds;
}
}

View File

@@ -0,0 +1,13 @@
import { Cipher } from "../domain/cipher";
import { CipherRequest } from "./cipherRequest";
export class CipherCreateRequest {
cipher: CipherRequest;
collectionIds: string[];
constructor(cipher: Cipher) {
this.cipher = new CipherRequest(cipher);
this.collectionIds = cipher.collectionIds;
}
}

View File

@@ -0,0 +1,164 @@
import { CipherRepromptType } from "../../enums/cipherRepromptType";
import { CipherType } from "../../enums/cipherType";
import { CardApi } from "../api/cardApi";
import { FieldApi } from "../api/fieldApi";
import { IdentityApi } from "../api/identityApi";
import { LoginApi } from "../api/loginApi";
import { LoginUriApi } from "../api/loginUriApi";
import { SecureNoteApi } from "../api/secureNoteApi";
import { Cipher } from "../domain/cipher";
import { AttachmentRequest } from "./attachmentRequest";
import { PasswordHistoryRequest } from "./passwordHistoryRequest";
export class CipherRequest {
type: CipherType;
folderId: string;
organizationId: string;
name: string;
notes: string;
favorite: boolean;
login: LoginApi;
secureNote: SecureNoteApi;
card: CardApi;
identity: IdentityApi;
fields: FieldApi[];
passwordHistory: PasswordHistoryRequest[];
// Deprecated, remove at some point and rename attachments2 to attachments
attachments: { [id: string]: string };
attachments2: { [id: string]: AttachmentRequest };
lastKnownRevisionDate: Date;
reprompt: CipherRepromptType;
constructor(cipher: Cipher) {
this.type = cipher.type;
this.folderId = cipher.folderId;
this.organizationId = cipher.organizationId;
this.name = cipher.name ? cipher.name.encryptedString : null;
this.notes = cipher.notes ? cipher.notes.encryptedString : null;
this.favorite = cipher.favorite;
this.lastKnownRevisionDate = cipher.revisionDate;
this.reprompt = cipher.reprompt;
switch (this.type) {
case CipherType.Login:
this.login = new LoginApi();
this.login.uris = null;
this.login.username = cipher.login.username ? cipher.login.username.encryptedString : null;
this.login.password = cipher.login.password ? cipher.login.password.encryptedString : null;
this.login.passwordRevisionDate =
cipher.login.passwordRevisionDate != null
? cipher.login.passwordRevisionDate.toISOString()
: null;
this.login.totp = cipher.login.totp ? cipher.login.totp.encryptedString : null;
this.login.autofillOnPageLoad = cipher.login.autofillOnPageLoad;
if (cipher.login.uris != null) {
this.login.uris = cipher.login.uris.map((u) => {
const uri = new LoginUriApi();
uri.uri = u.uri != null ? u.uri.encryptedString : null;
uri.match = u.match != null ? u.match : null;
return uri;
});
}
break;
case CipherType.SecureNote:
this.secureNote = new SecureNoteApi();
this.secureNote.type = cipher.secureNote.type;
break;
case CipherType.Card:
this.card = new CardApi();
this.card.cardholderName =
cipher.card.cardholderName != null ? cipher.card.cardholderName.encryptedString : null;
this.card.brand = cipher.card.brand != null ? cipher.card.brand.encryptedString : null;
this.card.number = cipher.card.number != null ? cipher.card.number.encryptedString : null;
this.card.expMonth =
cipher.card.expMonth != null ? cipher.card.expMonth.encryptedString : null;
this.card.expYear =
cipher.card.expYear != null ? cipher.card.expYear.encryptedString : null;
this.card.code = cipher.card.code != null ? cipher.card.code.encryptedString : null;
break;
case CipherType.Identity:
this.identity = new IdentityApi();
this.identity.title =
cipher.identity.title != null ? cipher.identity.title.encryptedString : null;
this.identity.firstName =
cipher.identity.firstName != null ? cipher.identity.firstName.encryptedString : null;
this.identity.middleName =
cipher.identity.middleName != null ? cipher.identity.middleName.encryptedString : null;
this.identity.lastName =
cipher.identity.lastName != null ? cipher.identity.lastName.encryptedString : null;
this.identity.address1 =
cipher.identity.address1 != null ? cipher.identity.address1.encryptedString : null;
this.identity.address2 =
cipher.identity.address2 != null ? cipher.identity.address2.encryptedString : null;
this.identity.address3 =
cipher.identity.address3 != null ? cipher.identity.address3.encryptedString : null;
this.identity.city =
cipher.identity.city != null ? cipher.identity.city.encryptedString : null;
this.identity.state =
cipher.identity.state != null ? cipher.identity.state.encryptedString : null;
this.identity.postalCode =
cipher.identity.postalCode != null ? cipher.identity.postalCode.encryptedString : null;
this.identity.country =
cipher.identity.country != null ? cipher.identity.country.encryptedString : null;
this.identity.company =
cipher.identity.company != null ? cipher.identity.company.encryptedString : null;
this.identity.email =
cipher.identity.email != null ? cipher.identity.email.encryptedString : null;
this.identity.phone =
cipher.identity.phone != null ? cipher.identity.phone.encryptedString : null;
this.identity.ssn =
cipher.identity.ssn != null ? cipher.identity.ssn.encryptedString : null;
this.identity.username =
cipher.identity.username != null ? cipher.identity.username.encryptedString : null;
this.identity.passportNumber =
cipher.identity.passportNumber != null
? cipher.identity.passportNumber.encryptedString
: null;
this.identity.licenseNumber =
cipher.identity.licenseNumber != null
? cipher.identity.licenseNumber.encryptedString
: null;
break;
default:
break;
}
if (cipher.fields != null) {
this.fields = cipher.fields.map((f) => {
const field = new FieldApi();
field.type = f.type;
field.name = f.name ? f.name.encryptedString : null;
field.value = f.value ? f.value.encryptedString : null;
field.linkedId = f.linkedId;
return field;
});
}
if (cipher.passwordHistory != null) {
this.passwordHistory = [];
cipher.passwordHistory.forEach((ph) => {
this.passwordHistory.push({
lastUsedDate: ph.lastUsedDate,
password: ph.password ? ph.password.encryptedString : null,
});
});
}
if (cipher.attachments != null) {
this.attachments = {};
this.attachments2 = {};
cipher.attachments.forEach((attachment) => {
const fileName = attachment.fileName ? attachment.fileName.encryptedString : null;
this.attachments[attachment.id] = fileName;
const attachmentRequest = new AttachmentRequest();
attachmentRequest.fileName = fileName;
if (attachment.key != null) {
attachmentRequest.key = attachment.key.encryptedString;
}
this.attachments2[attachment.id] = attachmentRequest;
});
}
}
}

View File

@@ -0,0 +1,13 @@
import { Cipher } from "../domain/cipher";
import { CipherRequest } from "./cipherRequest";
export class CipherShareRequest {
cipher: CipherRequest;
collectionIds: string[];
constructor(cipher: Cipher) {
this.cipher = new CipherRequest(cipher);
this.collectionIds = cipher.collectionIds;
}
}

View File

@@ -0,0 +1,12 @@
import { Cipher } from "../domain/cipher";
import { CipherRequest } from "./cipherRequest";
export class CipherWithIdRequest extends CipherRequest {
id: string;
constructor(cipher: Cipher) {
super(cipher);
this.id = cipher.id;
}
}

View File

@@ -0,0 +1,17 @@
import { Collection } from "../domain/collection";
import { SelectionReadOnlyRequest } from "./selectionReadOnlyRequest";
export class CollectionRequest {
name: string;
externalId: string;
groups: SelectionReadOnlyRequest[] = [];
constructor(collection?: Collection) {
if (collection == null) {
return;
}
this.name = collection.name ? collection.name.encryptedString : null;
this.externalId = collection.externalId;
}
}

View File

@@ -0,0 +1,3 @@
export class DeleteRecoverRequest {
email: string;
}

View File

@@ -0,0 +1,7 @@
export class DeviceTokenRequest {
pushToken: string;
constructor() {
this.pushToken = null;
}
}

View File

@@ -0,0 +1,7 @@
import { EmailTokenRequest } from "./emailTokenRequest";
export class EmailRequest extends EmailTokenRequest {
newMasterPasswordHash: string;
token: string;
key: string;
}

View File

@@ -0,0 +1,6 @@
import { SecretVerificationRequest } from "./secretVerificationRequest";
export class EmailTokenRequest extends SecretVerificationRequest {
newEmail: string;
masterPasswordHash: string;
}

View File

@@ -0,0 +1,3 @@
export class EmergencyAccessAcceptRequest {
token: string;
}

View File

@@ -0,0 +1,3 @@
export class EmergencyAccessConfirmRequest {
key: string;
}

View File

@@ -0,0 +1,7 @@
import { EmergencyAccessType } from "../../enums/emergencyAccessType";
export class EmergencyAccessInviteRequest {
email: string;
type: EmergencyAccessType;
waitTimeDays: number;
}

View File

@@ -0,0 +1,4 @@
export class EmergencyAccessPasswordRequest {
newMasterPasswordHash: string;
key: string;
}

View File

@@ -0,0 +1,7 @@
import { EmergencyAccessType } from "../../enums/emergencyAccessType";
export class EmergencyAccessUpdateRequest {
type: EmergencyAccessType;
waitTimeDays: number;
keyEncrypted?: string;
}

View File

@@ -0,0 +1,7 @@
import { EventType } from "../../enums/eventType";
export class EventRequest {
type: EventType;
cipherId: string;
date: string;
}

View File

@@ -0,0 +1,9 @@
import { Folder } from "../domain/folder";
export class FolderRequest {
name: string;
constructor(folder: Folder) {
this.name = folder.name ? folder.name.encryptedString : null;
}
}

View File

@@ -0,0 +1,12 @@
import { Folder } from "../domain/folder";
import { FolderRequest } from "./folderRequest";
export class FolderWithIdRequest extends FolderRequest {
id: string;
constructor(folder: Folder) {
super(folder);
this.id = folder.id;
}
}

View File

@@ -0,0 +1,8 @@
import { SelectionReadOnlyRequest } from "./selectionReadOnlyRequest";
export class GroupRequest {
name: string;
accessAll: boolean;
externalId: string;
collections: SelectionReadOnlyRequest[] = [];
}

View File

@@ -0,0 +1,5 @@
import { PaymentMethodType } from "../../enums/paymentMethodType";
export class IapCheckRequest {
paymentMethodType: PaymentMethodType;
}

View File

@@ -0,0 +1,9 @@
import { CipherRequest } from "./cipherRequest";
import { FolderRequest } from "./folderRequest";
import { KvpRequest } from "./kvpRequest";
export class ImportCiphersRequest {
ciphers: CipherRequest[] = [];
folders: FolderRequest[] = [];
folderRelationships: KvpRequest<number, number>[] = [];
}

View File

@@ -0,0 +1,9 @@
import { CipherRequest } from "./cipherRequest";
import { CollectionRequest } from "./collectionRequest";
import { KvpRequest } from "./kvpRequest";
export class ImportOrganizationCiphersRequest {
ciphers: CipherRequest[] = [];
collections: CollectionRequest[] = [];
collectionRelationships: KvpRequest<number, number>[] = [];
}

View File

@@ -0,0 +1,8 @@
import { KdfType } from "../../enums/kdfType";
import { PasswordRequest } from "./passwordRequest";
export class KdfRequest extends PasswordRequest {
kdf: KdfType;
kdfIterations: number;
}

View File

@@ -0,0 +1,7 @@
export class KeyConnectorUserKeyRequest {
key: string;
constructor(key: string) {
this.key = key;
}
}

View File

@@ -0,0 +1,9 @@
export class KeysRequest {
publicKey: string;
encryptedPrivateKey: string;
constructor(publicKey: string, encryptedPrivateKey: string) {
this.publicKey = publicKey;
this.encryptedPrivateKey = encryptedPrivateKey;
}
}

View File

@@ -0,0 +1,9 @@
export class KvpRequest<TK, TV> {
key: TK;
value: TV;
constructor(key: TK, value: TV) {
this.key = key;
this.value = value;
}
}

View File

@@ -0,0 +1,7 @@
import { PlanSponsorshipType } from "../../../enums/planSponsorshipType";
export class OrganizationSponsorshipCreateRequest {
sponsoredEmail: string;
planSponsorshipType: PlanSponsorshipType;
friendlyName: string;
}

View File

@@ -0,0 +1,6 @@
import { PlanSponsorshipType } from "../../../enums/planSponsorshipType";
export class OrganizationSponsorshipRedeemRequest {
planSponsorshipType: PlanSponsorshipType;
sponsoredOrganizationId: string;
}

View File

@@ -0,0 +1,6 @@
import { SsoConfigApi } from "../../api/ssoConfigApi";
export class OrganizationSsoRequest {
enabled = false;
data: SsoConfigApi;
}

View File

@@ -0,0 +1,27 @@
import { PaymentMethodType } from "../../enums/paymentMethodType";
import { PlanType } from "../../enums/planType";
import { OrganizationKeysRequest } from "./organizationKeysRequest";
export class OrganizationCreateRequest {
name: string;
businessName: string;
billingEmail: string;
planType: PlanType;
key: string;
keys: OrganizationKeysRequest;
paymentMethodType: PaymentMethodType;
paymentToken: string;
additionalSeats: number;
maxAutoscaleSeats: number;
additionalStorageGb: number;
premiumAccessAddon: boolean;
collectionName: string;
taxIdNumber: string;
billingAddressLine1: string;
billingAddressLine2: string;
billingAddressCity: string;
billingAddressState: string;
billingAddressPostalCode: string;
billingAddressCountry: string;
}

View File

@@ -8,12 +8,16 @@ export class OrganizationImportRequest {
overwriteExisting = false; overwriteExisting = false;
largeImport = false; largeImport = false;
constructor(model: { constructor(
groups: Required<OrganizationImportGroupRequest>[]; model:
users: Required<OrganizationImportMemberRequest>[]; | {
overwriteExisting: boolean; groups: Required<OrganizationImportGroupRequest>[];
largeImport: boolean; users: Required<OrganizationImportMemberRequest>[];
}) { overwriteExisting: boolean;
largeImport: boolean;
}
| ImportDirectoryRequest,
) {
if (model instanceof ImportDirectoryRequest) { if (model instanceof ImportDirectoryRequest) {
this.groups = model.groups.map((g) => new OrganizationImportGroupRequest(g)); this.groups = model.groups.map((g) => new OrganizationImportGroupRequest(g));
this.members = model.users.map((u) => new OrganizationImportMemberRequest(u)); this.members = model.users.map((u) => new OrganizationImportMemberRequest(u));

View File

@@ -0,0 +1,7 @@
import { KeysRequest } from "./keysRequest";
export class OrganizationKeysRequest extends KeysRequest {
constructor(publicKey: string, encryptedPrivateKey: string) {
super(publicKey, encryptedPrivateKey);
}
}

View File

@@ -0,0 +1,6 @@
export class OrganizationSubscriptionUpdateRequest {
constructor(
public seatAdjustment: number,
public maxAutoscaleSeats?: number,
) {}
}

View File

@@ -0,0 +1,9 @@
import { TaxInfoUpdateRequest } from "./taxInfoUpdateRequest";
export class OrganizationTaxInfoUpdateRequest extends TaxInfoUpdateRequest {
taxId: string;
line1: string;
line2: string;
city: string;
state: string;
}

View File

@@ -0,0 +1,9 @@
import { OrganizationKeysRequest } from "./organizationKeysRequest";
export class OrganizationUpdateRequest {
name: string;
identifier: string;
businessName: string;
billingEmail: string;
keys: OrganizationKeysRequest;
}

View File

@@ -0,0 +1,14 @@
import { PlanType } from "../../enums/planType";
import { OrganizationKeysRequest } from "./organizationKeysRequest";
export class OrganizationUpgradeRequest {
businessName: string;
planType: PlanType;
additionalSeats: number;
additionalStorageGb: number;
premiumAccessAddon: boolean;
billingAddressCountry: string;
billingAddressPostalCode: string;
keys: OrganizationKeysRequest;
}

View File

@@ -0,0 +1,3 @@
export class OrganizationUserAcceptRequest {
token: string;
}

View File

@@ -0,0 +1,12 @@
type OrganizationUserBulkRequestEntry = {
id: string;
key: string;
};
export class OrganizationUserBulkConfirmRequest {
keys: OrganizationUserBulkRequestEntry[];
constructor(keys: OrganizationUserBulkRequestEntry[]) {
this.keys = keys;
}
}

View File

@@ -0,0 +1,7 @@
export class OrganizationUserBulkRequest {
ids: string[];
constructor(ids: string[]) {
this.ids = ids == null ? [] : ids;
}
}

View File

@@ -0,0 +1,3 @@
export class OrganizationUserConfirmRequest {
key: string;
}

View File

@@ -0,0 +1,12 @@
import { OrganizationUserType } from "../../enums/organizationUserType";
import { PermissionsApi } from "../api/permissionsApi";
import { SelectionReadOnlyRequest } from "./selectionReadOnlyRequest";
export class OrganizationUserInviteRequest {
emails: string[] = [];
type: OrganizationUserType;
accessAll: boolean;
collections: SelectionReadOnlyRequest[] = [];
permissions: PermissionsApi;
}

View File

@@ -0,0 +1,3 @@
export class OrganizationUserResetPasswordEnrollmentRequest {
resetPasswordKey: string;
}

View File

@@ -0,0 +1,4 @@
export class OrganizationUserResetPasswordRequest {
newMasterPasswordHash: string;
key: string;
}

View File

@@ -0,0 +1,3 @@
export class OrganizationUserUpdateGroupsRequest {
groupIds: string[] = [];
}

View File

@@ -0,0 +1,11 @@
import { OrganizationUserType } from "../../enums/organizationUserType";
import { PermissionsApi } from "../api/permissionsApi";
import { SelectionReadOnlyRequest } from "./selectionReadOnlyRequest";
export class OrganizationUserUpdateRequest {
type: OrganizationUserType;
accessAll: boolean;
collections: SelectionReadOnlyRequest[] = [];
permissions: PermissionsApi;
}

View File

@@ -0,0 +1,7 @@
export class PasswordHintRequest {
email: string;
constructor(email: string) {
this.email = email;
}
}

View File

@@ -0,0 +1,4 @@
export class PasswordHistoryRequest {
password: string;
lastUsedDate: Date;
}

View File

@@ -0,0 +1,6 @@
import { SecretVerificationRequest } from "./secretVerificationRequest";
export class PasswordRequest extends SecretVerificationRequest {
newMasterPasswordHash: string;
key: string;
}

View File

@@ -0,0 +1,7 @@
import { PaymentMethodType } from "../../enums/paymentMethodType";
import { OrganizationTaxInfoUpdateRequest } from "../request/organizationTaxInfoUpdateRequest";
export class PaymentRequest extends OrganizationTaxInfoUpdateRequest {
paymentMethodType: PaymentMethodType;
paymentToken: string;
}

View File

@@ -0,0 +1,7 @@
import { PolicyType } from "../../enums/policyType";
export class PolicyRequest {
type: PolicyType;
enabled: boolean;
data: any;
}

View File

@@ -0,0 +1,7 @@
export class PreloginRequest {
email: string;
constructor(email: string) {
this.email = email;
}
}

View File

@@ -0,0 +1,4 @@
export class ProviderAddOrganizationRequest {
organizationId: string;
key: string;
}

View File

@@ -0,0 +1,8 @@
import { OrganizationCreateRequest } from "../organizationCreateRequest";
export class ProviderOrganizationCreateRequest {
constructor(
public clientOwnerEmail: string,
public organizationCreateRequest: OrganizationCreateRequest,
) {}
}

View File

@@ -0,0 +1,7 @@
export class ProviderSetupRequest {
name: string;
businessName: string;
billingEmail: string;
token: string;
key: string;
}

View File

@@ -0,0 +1,5 @@
export class ProviderUpdateRequest {
name: string;
businessName: string;
billingEmail: string;
}

View File

@@ -0,0 +1,3 @@
export class ProviderUserAcceptRequest {
token: string;
}

View File

@@ -0,0 +1,12 @@
type ProviderUserBulkRequestEntry = {
id: string;
key: string;
};
export class ProviderUserBulkConfirmRequest {
keys: ProviderUserBulkRequestEntry[];
constructor(keys: ProviderUserBulkRequestEntry[]) {
this.keys = keys;
}
}

View File

@@ -0,0 +1,7 @@
export class ProviderUserBulkRequest {
ids: string[];
constructor(ids: string[]) {
this.ids = ids == null ? [] : ids;
}
}

View File

@@ -0,0 +1,3 @@
export class ProviderUserConfirmRequest {
key: string;
}

View File

@@ -0,0 +1,6 @@
import { ProviderUserType } from "../../../enums/providerUserType";
export class ProviderUserInviteRequest {
emails: string[] = [];
type: ProviderUserType;
}

View File

@@ -0,0 +1,5 @@
import { ProviderUserType } from "../../../enums/providerUserType";
export class ProviderUserUpdateRequest {
type: ProviderUserType;
}

View File

@@ -0,0 +1,5 @@
export class ReferenceEventRequest {
id: string;
layout: string;
flow: string;
}

View File

@@ -0,0 +1,26 @@
import { KdfType } from "../../enums/kdfType";
import { CaptchaProtectedRequest } from "./captchaProtectedRequest";
import { KeysRequest } from "./keysRequest";
import { ReferenceEventRequest } from "./referenceEventRequest";
export class RegisterRequest implements CaptchaProtectedRequest {
masterPasswordHint: string;
keys: KeysRequest;
token: string;
organizationUserId: string;
constructor(
public email: string,
public name: string,
public masterPasswordHash: string,
masterPasswordHint: string,
public key: string,
public kdf: KdfType,
public kdfIterations: number,
public referenceData: ReferenceEventRequest,
public captchaResponse: string,
) {
this.masterPasswordHint = masterPasswordHint ? masterPasswordHint : null;
}
}

View File

@@ -0,0 +1,3 @@
export class SeatRequest {
seatAdjustment: number;
}

View File

@@ -0,0 +1,4 @@
export class SecretVerificationRequest {
masterPasswordHash: string;
otp: string;
}

View File

@@ -0,0 +1,11 @@
export class SelectionReadOnlyRequest {
id: string;
readOnly: boolean;
hidePasswords: boolean;
constructor(id: string, readOnly: boolean, hidePasswords: boolean) {
this.id = id;
this.readOnly = readOnly;
this.hidePasswords = hidePasswords;
}
}

View File

@@ -0,0 +1,3 @@
export class SendAccessRequest {
password: string;
}

View File

@@ -0,0 +1,48 @@
import { SendType } from "../../enums/sendType";
import { SendFileApi } from "../api/sendFileApi";
import { SendTextApi } from "../api/sendTextApi";
import { Send } from "../domain/send";
export class SendRequest {
type: SendType;
fileLength?: number;
name: string;
notes: string;
key: string;
maxAccessCount?: number;
expirationDate: string;
deletionDate: string;
text: SendTextApi;
file: SendFileApi;
password: string;
disabled: boolean;
hideEmail: boolean;
constructor(send: Send, fileLength?: number) {
this.type = send.type;
this.fileLength = fileLength;
this.name = send.name ? send.name.encryptedString : null;
this.notes = send.notes ? send.notes.encryptedString : null;
this.maxAccessCount = send.maxAccessCount;
this.expirationDate = send.expirationDate != null ? send.expirationDate.toISOString() : null;
this.deletionDate = send.deletionDate != null ? send.deletionDate.toISOString() : null;
this.key = send.key != null ? send.key.encryptedString : null;
this.password = send.password;
this.disabled = send.disabled;
this.hideEmail = send.hideEmail;
switch (this.type) {
case SendType.Text:
this.text = new SendTextApi();
this.text.text = send.text.text != null ? send.text.text.encryptedString : null;
this.text.hidden = send.text.hidden;
break;
case SendType.File:
this.file = new SendFileApi();
this.file.fileName = send.file.fileName != null ? send.file.fileName.encryptedString : null;
break;
default:
break;
}
}
}

View File

@@ -0,0 +1,12 @@
import { Send } from "../domain/send";
import { SendRequest } from "./sendRequest";
export class SendWithIdRequest extends SendRequest {
id: string;
constructor(send: Send) {
super(send);
this.id = send.id;
}
}

View File

@@ -0,0 +1,31 @@
import { KdfType } from "../../enums/kdfType";
import { KeysRequest } from "./keysRequest";
export class SetPasswordRequest {
masterPasswordHash: string;
key: string;
masterPasswordHint: string;
keys: KeysRequest;
kdf: KdfType;
kdfIterations: number;
orgIdentifier: string;
constructor(
masterPasswordHash: string,
key: string,
masterPasswordHint: string,
kdf: KdfType,
kdfIterations: number,
orgIdentifier: string,
keys: KeysRequest,
) {
this.masterPasswordHash = masterPasswordHash;
this.key = key;
this.masterPasswordHint = masterPasswordHint;
this.kdf = kdf;
this.kdfIterations = kdfIterations;
this.orgIdentifier = orgIdentifier;
this.keys = keys;
}
}

View File

@@ -0,0 +1,3 @@
export class StorageRequest {
storageGbAdjustment: number;
}

View File

@@ -0,0 +1,4 @@
export class TaxInfoUpdateRequest {
country: string;
postalCode: string;
}

View File

@@ -0,0 +1,5 @@
import { SecretVerificationRequest } from "./secretVerificationRequest";
export class TwoFactorEmailRequest extends SecretVerificationRequest {
email: string;
}

View File

@@ -0,0 +1,7 @@
import { TwoFactorProviderType } from "../../enums/twoFactorProviderType";
import { SecretVerificationRequest } from "./secretVerificationRequest";
export class TwoFactorProviderRequest extends SecretVerificationRequest {
type: TwoFactorProviderType;
}

View File

@@ -0,0 +1,6 @@
import { SecretVerificationRequest } from "./secretVerificationRequest";
export class TwoFactorRecoveryRequest extends SecretVerificationRequest {
recoveryCode: string;
email: string;
}

View File

@@ -0,0 +1,4 @@
export class UpdateDomainsRequest {
equivalentDomains: string[][];
excludedGlobalEquivalentDomains: number[];
}

View File

@@ -0,0 +1,12 @@
import { CipherWithIdRequest } from "./cipherWithIdRequest";
import { FolderWithIdRequest } from "./folderWithIdRequest";
import { SendWithIdRequest } from "./sendWithIdRequest";
export class UpdateKeyRequest {
ciphers: CipherWithIdRequest[] = [];
folders: FolderWithIdRequest[] = [];
sends: SendWithIdRequest[] = [];
masterPasswordHash: string;
privateKey: string;
key: string;
}

View File

@@ -0,0 +1,10 @@
export class UpdateProfileRequest {
name: string;
masterPasswordHint: string;
culture = "en-US"; // deprecated
constructor(name: string, masterPasswordHint: string) {
this.name = name;
this.masterPasswordHint = masterPasswordHint ? masterPasswordHint : null;
}
}

Some files were not shown because too many files have changed in this diff Show More