Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 32 additions & 66 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,31 +62,25 @@ jobs:
cache-dependency-path: '**/package-lock.json'
node-version: ${{ env._NODE_VERSION }}

- name: Update NPM
run: |
npm install -g node-gyp
node-gyp install "$(node -v)"
- name: Set up Rust
uses: dtolnay/rust-toolchain@stable

- name: Keytar
- name: Set up system dependencies
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
sudo apt-get update
sudo apt-get -y install libdbus-1-dev libsecret-1-dev pkg-config

- name: Install
run: npm install

- name: Build native module
run: npm run build:native:release

- 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"
run: zip -j "dist-cli/bwdc-linux-$_PACKAGE_VERSION.zip" "dist-cli/linux/bwdc" "node_modules/dc-native/dc_native.linux-x64-gnu.node"

- name: Version Test
run: |
Expand Down Expand Up @@ -140,31 +134,20 @@ jobs:
cache-dependency-path: '**/package-lock.json'
node-version: ${{ env._NODE_VERSION }}

- name: Update NPM
run: |
npm install -g node-gyp
node-gyp install "$(node -v)"

- 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: Set up Rust
uses: dtolnay/rust-toolchain@stable

- name: Install
run: npm install

- name: Build native module
run: npm run build:native:release

- 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"
run: zip -j "dist-cli/bwdc-macos-$_PACKAGE_VERSION.zip" "dist-cli/macos/bwdc" "node_modules/dc-native/dc_native.darwin-x64.node"

- name: Version Test
run: |
Expand Down Expand Up @@ -215,36 +198,23 @@ jobs:
cache-dependency-path: '**/package-lock.json'
node-version: ${{ env._NODE_VERSION }}

- name: Update NPM
run: |
npm install -g node-gyp
node-gyp install $(node -v)

- 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: Set up Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: x86_64-pc-windows-msvc

- name: Install
run: npm install

- name: Build native module
run: npm run build:native:release

- 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
run: 7z a .\dist-cli\bwdc-windows-%_PACKAGE_VERSION%.zip .\dist-cli\windows\bwdc.exe .\node_modules\dc-native\dc_native.win32-x64-msvc.node

- name: Version Test
shell: pwsh
Expand Down Expand Up @@ -290,10 +260,10 @@ jobs:
cache-dependency-path: '**/package-lock.json'
node-version: ${{ env._NODE_VERSION }}

- name: Update NPM
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Set up Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: x86_64-pc-windows-msvc

- name: Print environment
run: |
Expand Down Expand Up @@ -390,15 +360,13 @@ jobs:
cache-dependency-path: '**/package-lock.json'
node-version: ${{ env._NODE_VERSION }}

- name: Update NPM
run: |
npm install -g node-gyp
node-gyp install "$(node -v)"
- name: Set up Rust
uses: dtolnay/rust-toolchain@stable

- name: Set up environment
run: |
sudo apt-get update
sudo apt-get -y install pkg-config libxss-dev libsecret-1-dev
sudo apt-get -y install pkg-config libxss-dev libsecret-1-dev libdbus-1-dev
sudo apt-get -y install rpm

- name: NPM Install
Expand Down Expand Up @@ -450,10 +418,8 @@ jobs:
cache-dependency-path: '**/package-lock.json'
node-version: ${{ env._NODE_VERSION }}

- name: Update NPM
run: |
npm install -g node-gyp
node-gyp install "$(node -v)"
- name: Set up Rust
uses: dtolnay/rust-toolchain@stable

- name: Print environment
run: |
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ build
build-cli
.angular/cache

# Rust build artifacts
native/target
native/*.node

# Testing
coverage*
junit.xml*
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v20
v22
1 change: 1 addition & 0 deletions electron-builder.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"app": "build"
},
"afterSign": "scripts/notarize.js",
"asarUnpack": ["node_modules/dc-native/*.node"],
"mac": {
"artifactName": "Bitwarden-Connector-${version}-mac.${ext}",
"category": "public.app-category.productivity",
Expand Down
1 change: 1 addition & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export default [
"eslint.config.mjs",
"scripts/**/*.js",
"**/node_modules/**",
"native/**",
],
},

Expand Down
3 changes: 2 additions & 1 deletion jslib/common/src/enums/stateVersion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ export enum StateVersion {
Two = 2, // Move to a typed State object
Three = 3, // Fix migration of users' premium status
Four = 4, // Fix 'Never Lock' option by removing stale data
Latest = Four,
Five = 5, // Migrate Windows keychain credentials from keytar (UTF-8) to desktop_core (UTF-16)
Latest = Five,
}
Original file line number Diff line number Diff line change
@@ -1,43 +1,53 @@
import { ipcRenderer } from "electron";

import { StorageService } from "@/jslib/common/src/abstractions/storage.service";
import { StorageOptions } from "@/jslib/common/src/models/domain/storageOptions";

import { passwords } from "dc-native";

const APPLICATION_NAME = "Bitwarden Directory Connector";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎨 SUGGESTED: This service name is now hardcoded in three separate locations:

  1. Here in ElectronRendererSecureStorageService
  2. In stateMigration.service.ts line 190 (const serviceName = "Bitwarden Directory Connector")
  3. In bwdc.ts line 63 (const applicationName = "Bitwarden Directory Connector")

If any of these drift out of sync, credentials written by one path would be invisible to another. Consider extracting this to a shared constant (e.g., in a constants file) to make the coupling explicit and prevent future inconsistencies.


export class ElectronRendererSecureStorageService implements StorageService {
async get<T>(key: string, options?: StorageOptions): Promise<T> {
const val = ipcRenderer.sendSync("keytar", {
action: "getPassword",
key: key,
keySuffix: options?.keySuffix ?? "",
});
return Promise.resolve(val != null ? (JSON.parse(val) as T) : null);
return passwords
.getPassword(this.buildServiceName(options), key)
.then((val: string) => JSON.parse(val) as T)
.catch((e: Error): T => {
if (e.message === passwords.PASSWORD_NOT_FOUND) {
return null;
}
throw e;
});
}

async has(key: string, options?: StorageOptions): Promise<boolean> {
const val = ipcRenderer.sendSync("keytar", {
action: "hasPassword",
key: key,
keySuffix: options?.keySuffix ?? "",
});
return Promise.resolve(!!val);
return (await this.get(key, options)) != null;
}

async save(key: string, obj: any, options?: StorageOptions): Promise<any> {
ipcRenderer.sendSync("keytar", {
action: "setPassword",
key: key,
keySuffix: options?.keySuffix ?? "",
value: JSON.stringify(obj),
});
return Promise.resolve();
if (!obj) {
return this.remove(key, options);
}
return passwords.setPassword(
this.buildServiceName(options),
key,
JSON.stringify(obj),
);
}

async remove(key: string, options?: StorageOptions): Promise<any> {
ipcRenderer.sendSync("keytar", {
action: "deletePassword",
key: key,
keySuffix: options?.keySuffix ?? "",
return passwords.deletePassword(this.buildServiceName(options), key).catch((e: Error) => {
if (e.message === passwords.PASSWORD_NOT_FOUND) {
return;
}
throw e;
});
return Promise.resolve();
}

private buildServiceName(options?: StorageOptions): string {
const suffix = options?.keySuffix;
if (suffix) {
return `${APPLICATION_NAME}_${suffix}`;
}
return APPLICATION_NAME;
}
}
Loading
Loading