-
-
-
-
-
-
-
-
- {{'ex' | i18n}} ad.company.com
-
-
-
-
- {{'ex' | i18n}} 389
-
-
-
-
- {{'ex' | i18n}} dc=company,dc=com
-
-
-
-
-
-
-
-
-
-
- {{'ex' | i18n}} company\admin
- {{'ex' | i18n}}
- cn=admin,dc=company,dc=com
-
-
-
-
-
-
-
-
-
-
-
-
- {{'ex' | i18n}} companyad.onmicrosoft.com
-
-
-
-
-
-
-
-
-
-
-
- {{'ex' | i18n}} https://mycompany.okta.com/
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ "ex" | i18n }} ad.company.com
+
+
+
+
+ {{ "ex" | i18n }} 389
+
+
+
+
+ {{ "ex" | i18n }} dc=company,dc=com
+
+
+
+
+
+
+
+
+
+
+ {{ "ex" | i18n }} company\admin
+ {{ "ex" | i18n }} cn=admin,dc=company,dc=com
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ "ex" | i18n }} companyad.onmicrosoft.com
+
+
+
+
+
+
+
+
+
+
+
+ {{ "ex" | i18n }} https://mycompany.okta.com/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ "intervalMin" | i18n }}
+
+
+
+
+
+
-
-
-
-
-
-
-
-
- {{'intervalMin' | i18n}}
-
-
-
-
-
-
-
-
-
-
-
-
- {{'ex' | i18n}}
- (&(givenName=John)(|(l=Dallas)(l=Austin)))
- {{'ex' | i18n}}
- exclude:joe@company.com
- {{'ex' | i18n}}
- exclude:joe@company.com | profile.firstName eq "John"
- {{'ex' | i18n}}
- exclude:joe@company.com | orgName=Engineering
-
-
-
-
- {{'ex' | i18n}} CN=Users
-
-
-
-
-
-
-
-
-
- {{'ex' | i18n}}
- (&!(name=Sales*)!(name=IT*))
- {{'ex' | i18n}}
- include:Sales,IT
- {{'ex' | i18n}}
- include:Sales,IT | type eq "APP_GROUP"
- {{'ex' | i18n}}
- include:Sales,IT
-
-
-
-
- {{'ex' | i18n}} CN=Groups
- {{'ex' | i18n}} CN=Users
-
-
-
-
+
+
+
+
+
+ {{ "ex" | i18n }} (&(givenName=John)(|(l=Dallas)(l=Austin)))
+ {{ "ex" | i18n }} exclude:joe@company.com
+ {{ "ex" | i18n }} exclude:joe@company.com | profile.firstName eq "John"
+ {{ "ex" | i18n }} exclude:joe@company.com | orgName=Engineering
+
+
+
+
+ {{ "ex" | i18n }} CN=Users
+
+
+
+
+
+
+
+
+
+ {{ "ex" | i18n }} (&!(name=Sales*)!(name=IT*))
+ {{ "ex" | i18n }} include:Sales,IT
+ {{ "ex" | i18n }} include:Sales,IT | type eq "APP_GROUP"
+ {{ "ex" | i18n }} include:Sales,IT
+
+
+
+
+ {{ "ex" | i18n }} CN=Groups
+ {{ "ex" | i18n }} CN=Users
+
+
+
+
+
diff --git a/src/app/tabs/settings.component.ts b/src/app/tabs/settings.component.ts
index 01a20664..2c1be5fe 100644
--- a/src/app/tabs/settings.component.ts
+++ b/src/app/tabs/settings.component.ts
@@ -1,156 +1,162 @@
-import {
- ChangeDetectorRef,
- Component,
- NgZone,
- OnDestroy,
- OnInit,
-} from '@angular/core';
+import { ChangeDetectorRef, Component, NgZone, OnDestroy, OnInit } from "@angular/core";
-import { I18nService } from 'jslib-common/abstractions/i18n.service';
-import { LogService } from 'jslib-common/abstractions/log.service';
-import { StateService } from 'jslib-common/abstractions/state.service';
+import { I18nService } from "jslib-common/abstractions/i18n.service";
+import { LogService } from "jslib-common/abstractions/log.service";
+import { StateService } from "jslib-common/abstractions/state.service";
-import { ProfileOrganizationResponse } from 'jslib-common/models/response/profileOrganizationResponse';
+import { ProfileOrganizationResponse } from "jslib-common/models/response/profileOrganizationResponse";
-import { ConfigurationService } from '../../services/configuration.service';
+import { ConfigurationService } from "../../services/configuration.service";
-import { DirectoryType } from '../../enums/directoryType';
+import { DirectoryType } from "../../enums/directoryType";
-import { AzureConfiguration } from '../../models/azureConfiguration';
-import { GSuiteConfiguration } from '../../models/gsuiteConfiguration';
-import { LdapConfiguration } from '../../models/ldapConfiguration';
-import { OktaConfiguration } from '../../models/oktaConfiguration';
-import { OneLoginConfiguration } from '../../models/oneLoginConfiguration';
-import { SyncConfiguration } from '../../models/syncConfiguration';
+import { AzureConfiguration } from "../../models/azureConfiguration";
+import { GSuiteConfiguration } from "../../models/gsuiteConfiguration";
+import { LdapConfiguration } from "../../models/ldapConfiguration";
+import { OktaConfiguration } from "../../models/oktaConfiguration";
+import { OneLoginConfiguration } from "../../models/oneLoginConfiguration";
+import { SyncConfiguration } from "../../models/syncConfiguration";
-import { ConnectorUtils } from '../../utils';
+import { ConnectorUtils } from "../../utils";
@Component({
- selector: 'app-settings',
- templateUrl: 'settings.component.html',
+ selector: "app-settings",
+ templateUrl: "settings.component.html",
})
export class SettingsComponent implements OnInit, OnDestroy {
- directory: DirectoryType;
- directoryType = DirectoryType;
- ldap = new LdapConfiguration();
- gsuite = new GSuiteConfiguration();
- azure = new AzureConfiguration();
- okta = new OktaConfiguration();
- oneLogin = new OneLoginConfiguration();
- sync = new SyncConfiguration();
- directoryOptions: any[];
- showLdapPassword: boolean = false;
- showAzureKey: boolean = false;
- showOktaKey: boolean = false;
- showOneLoginSecret: boolean = false;
+ directory: DirectoryType;
+ directoryType = DirectoryType;
+ ldap = new LdapConfiguration();
+ gsuite = new GSuiteConfiguration();
+ azure = new AzureConfiguration();
+ okta = new OktaConfiguration();
+ oneLogin = new OneLoginConfiguration();
+ sync = new SyncConfiguration();
+ directoryOptions: any[];
+ showLdapPassword: boolean = false;
+ showAzureKey: boolean = false;
+ showOktaKey: boolean = false;
+ showOneLoginSecret: boolean = false;
- constructor(private i18nService: I18nService, private configurationService: ConfigurationService,
- private changeDetectorRef: ChangeDetectorRef, private ngZone: NgZone,
- private stateService: StateService, private logService: LogService) {
- this.directoryOptions = [
- { name: i18nService.t('select'), value: null },
- { name: 'Active Directory / LDAP', value: DirectoryType.Ldap },
- { name: 'Azure Active Directory', value: DirectoryType.AzureActiveDirectory },
- { name: 'G Suite (Google)', value: DirectoryType.GSuite },
- { name: 'Okta', value: DirectoryType.Okta },
- { name: 'OneLogin', value: DirectoryType.OneLogin },
- ];
+ constructor(
+ private i18nService: I18nService,
+ private configurationService: ConfigurationService,
+ private changeDetectorRef: ChangeDetectorRef,
+ private ngZone: NgZone,
+ private stateService: StateService,
+ private logService: LogService
+ ) {
+ this.directoryOptions = [
+ { name: i18nService.t("select"), value: null },
+ { name: "Active Directory / LDAP", value: DirectoryType.Ldap },
+ { name: "Azure Active Directory", value: DirectoryType.AzureActiveDirectory },
+ { name: "G Suite (Google)", value: DirectoryType.GSuite },
+ { name: "Okta", value: DirectoryType.Okta },
+ { name: "OneLogin", value: DirectoryType.OneLogin },
+ ];
+ }
+
+ async ngOnInit() {
+ this.directory = await this.configurationService.getDirectoryType();
+ this.ldap =
+ (await this.configurationService.getDirectory
(DirectoryType.Ldap)) ||
+ this.ldap;
+ this.gsuite =
+ (await this.configurationService.getDirectory(DirectoryType.GSuite)) ||
+ this.gsuite;
+ this.azure =
+ (await this.configurationService.getDirectory(
+ DirectoryType.AzureActiveDirectory
+ )) || this.azure;
+ this.okta =
+ (await this.configurationService.getDirectory(DirectoryType.Okta)) ||
+ this.okta;
+ this.oneLogin =
+ (await this.configurationService.getDirectory(
+ DirectoryType.OneLogin
+ )) || this.oneLogin;
+ this.sync = (await this.configurationService.getSync()) || this.sync;
+ }
+
+ async ngOnDestroy() {
+ await this.submit();
+ }
+
+ async submit() {
+ ConnectorUtils.adjustConfigForSave(this.ldap, this.sync);
+ if (this.ldap != null && this.ldap.ad) {
+ this.ldap.pagedSearch = true;
+ }
+ await this.configurationService.saveDirectoryType(this.directory);
+ await this.configurationService.saveDirectory(DirectoryType.Ldap, this.ldap);
+ await this.configurationService.saveDirectory(DirectoryType.GSuite, this.gsuite);
+ await this.configurationService.saveDirectory(DirectoryType.AzureActiveDirectory, this.azure);
+ await this.configurationService.saveDirectory(DirectoryType.Okta, this.okta);
+ await this.configurationService.saveDirectory(DirectoryType.OneLogin, this.oneLogin);
+ await this.configurationService.saveSync(this.sync);
+ }
+
+ parseKeyFile() {
+ const filePicker = document.getElementById("keyFile") as HTMLInputElement;
+ if (filePicker.files == null || filePicker.files.length < 0) {
+ return;
}
- async ngOnInit() {
- this.directory = await this.configurationService.getDirectoryType();
- this.ldap = (await this.configurationService.getDirectory(DirectoryType.Ldap)) ||
- this.ldap;
- this.gsuite = (await this.configurationService.getDirectory(DirectoryType.GSuite)) ||
- this.gsuite;
- this.azure = (await this.configurationService.getDirectory(
- DirectoryType.AzureActiveDirectory)) || this.azure;
- this.okta = (await this.configurationService.getDirectory(
- DirectoryType.Okta)) || this.okta;
- this.oneLogin = (await this.configurationService.getDirectory(
- DirectoryType.OneLogin)) || this.oneLogin;
- this.sync = (await this.configurationService.getSync()) || this.sync;
- }
-
- async ngOnDestroy() {
- await this.submit();
- }
-
- async submit() {
- ConnectorUtils.adjustConfigForSave(this.ldap, this.sync);
- if (this.ldap != null && this.ldap.ad) {
- this.ldap.pagedSearch = true;
+ const reader = new FileReader();
+ reader.readAsText(filePicker.files[0], "utf-8");
+ reader.onload = (evt) => {
+ this.ngZone.run(async () => {
+ try {
+ const result = JSON.parse((evt.target as FileReader).result as string);
+ if (result.client_email != null && result.private_key != null) {
+ this.gsuite.clientEmail = result.client_email;
+ this.gsuite.privateKey = result.private_key;
+ }
+ } catch (e) {
+ this.logService.error(e);
}
- await this.configurationService.saveDirectoryType(this.directory);
- await this.configurationService.saveDirectory(DirectoryType.Ldap, this.ldap);
- await this.configurationService.saveDirectory(DirectoryType.GSuite, this.gsuite);
- await this.configurationService.saveDirectory(DirectoryType.AzureActiveDirectory, this.azure);
- await this.configurationService.saveDirectory(DirectoryType.Okta, this.okta);
- await this.configurationService.saveDirectory(DirectoryType.OneLogin, this.oneLogin);
- await this.configurationService.saveSync(this.sync);
+ this.changeDetectorRef.detectChanges();
+ });
+
+ // reset file input
+ // ref: https://stackoverflow.com/a/20552042
+ filePicker.type = "";
+ filePicker.type = "file";
+ filePicker.value = "";
+ };
+ }
+
+ setSslPath(id: string) {
+ const filePicker = document.getElementById(id + "_file") as HTMLInputElement;
+ if (filePicker.files == null || filePicker.files.length < 0) {
+ return;
}
- parseKeyFile() {
- const filePicker = (document.getElementById('keyFile') as HTMLInputElement);
- if (filePicker.files == null || filePicker.files.length < 0) {
- return;
- }
+ (this.ldap as any)[id] = filePicker.files[0].path;
+ // reset file input
+ // ref: https://stackoverflow.com/a/20552042
+ filePicker.type = "";
+ filePicker.type = "file";
+ filePicker.value = "";
+ }
- const reader = new FileReader();
- reader.readAsText(filePicker.files[0], 'utf-8');
- reader.onload = evt => {
- this.ngZone.run(async () => {
- try {
- const result = JSON.parse((evt.target as FileReader).result as string);
- if (result.client_email != null && result.private_key != null) {
- this.gsuite.clientEmail = result.client_email;
- this.gsuite.privateKey = result.private_key;
- }
- } catch (e) {
- this.logService.error(e);
- }
- this.changeDetectorRef.detectChanges();
- });
+ toggleLdapPassword() {
+ this.showLdapPassword = !this.showLdapPassword;
+ document.getElementById("password").focus();
+ }
- // reset file input
- // ref: https://stackoverflow.com/a/20552042
- filePicker.type = '';
- filePicker.type = 'file';
- filePicker.value = '';
- };
- }
+ toggleAzureKey() {
+ this.showAzureKey = !this.showAzureKey;
+ document.getElementById("secretKey").focus();
+ }
- setSslPath(id: string) {
- const filePicker = (document.getElementById(id + '_file') as HTMLInputElement);
- if (filePicker.files == null || filePicker.files.length < 0) {
- return;
- }
+ toggleOktaKey() {
+ this.showOktaKey = !this.showOktaKey;
+ document.getElementById("oktaToken").focus();
+ }
- (this.ldap as any)[id] = filePicker.files[0].path;
- // reset file input
- // ref: https://stackoverflow.com/a/20552042
- filePicker.type = '';
- filePicker.type = 'file';
- filePicker.value = '';
- }
-
- toggleLdapPassword() {
- this.showLdapPassword = !this.showLdapPassword;
- document.getElementById('password').focus();
- }
-
- toggleAzureKey() {
- this.showAzureKey = !this.showAzureKey;
- document.getElementById('secretKey').focus();
- }
-
- toggleOktaKey() {
- this.showOktaKey = !this.showOktaKey;
- document.getElementById('oktaToken').focus();
- }
-
- toggleOneLoginSecret() {
- this.showOneLoginSecret = !this.showOneLoginSecret;
- document.getElementById('oneLoginClientSecret').focus();
- }
+ toggleOneLoginSecret() {
+ this.showOneLoginSecret = !this.showOneLoginSecret;
+ document.getElementById("oneLoginClientSecret").focus();
+ }
}
diff --git a/src/app/tabs/tabs.component.html b/src/app/tabs/tabs.component.html
index f118cd8d..aef2dcc2 100644
--- a/src/app/tabs/tabs.component.html
+++ b/src/app/tabs/tabs.component.html
@@ -1,23 +1,23 @@
diff --git a/src/app/tabs/tabs.component.ts b/src/app/tabs/tabs.component.ts
index 8c5df545..ea06809e 100644
--- a/src/app/tabs/tabs.component.ts
+++ b/src/app/tabs/tabs.component.ts
@@ -1,7 +1,7 @@
-import { Component } from '@angular/core';
+import { Component } from "@angular/core";
@Component({
- selector: 'app-tabs',
- templateUrl: 'tabs.component.html',
+ selector: "app-tabs",
+ templateUrl: "tabs.component.html",
})
-export class TabsComponent { }
+export class TabsComponent {}
diff --git a/src/bwdc.ts b/src/bwdc.ts
index bff0f028..7f2a8f46 100644
--- a/src/bwdc.ts
+++ b/src/bwdc.ts
@@ -1,188 +1,286 @@
-import * as fs from 'fs';
-import * as path from 'path';
+import * as fs from "fs";
+import * as path from "path";
-import { LogLevelType } from 'jslib-common/enums/logLevelType';
+import { LogLevelType } from "jslib-common/enums/logLevelType";
-import { AuthService } from './services/auth.service';
+import { AuthService } from "./services/auth.service";
-import { ConfigurationService } from './services/configuration.service';
-import { I18nService } from './services/i18n.service';
-import { KeytarSecureStorageService } from './services/keytarSecureStorage.service';
-import { LowdbStorageService } from './services/lowdbStorage.service';
-import { NodeApiService } from './services/nodeApi.service';
-import { SyncService } from './services/sync.service';
+import { ConfigurationService } from "./services/configuration.service";
+import { I18nService } from "./services/i18n.service";
+import { KeytarSecureStorageService } from "./services/keytarSecureStorage.service";
+import { LowdbStorageService } from "./services/lowdbStorage.service";
+import { NodeApiService } from "./services/nodeApi.service";
+import { SyncService } from "./services/sync.service";
-import { CliPlatformUtilsService } from 'jslib-node/cli/services/cliPlatformUtils.service';
-import { ConsoleLogService } from 'jslib-node/cli/services/consoleLog.service';
-import { NodeCryptoFunctionService } from 'jslib-node/services/nodeCryptoFunction.service';
+import { CliPlatformUtilsService } from "jslib-node/cli/services/cliPlatformUtils.service";
+import { ConsoleLogService } from "jslib-node/cli/services/consoleLog.service";
+import { NodeCryptoFunctionService } from "jslib-node/services/nodeCryptoFunction.service";
-import { ApiKeyService } from 'jslib-common/services/apiKey.service';
-import { AppIdService } from 'jslib-common/services/appId.service';
-import { CipherService } from 'jslib-common/services/cipher.service';
-import { CollectionService } from 'jslib-common/services/collection.service';
-import { ConstantsService } from 'jslib-common/services/constants.service';
-import { ContainerService } from 'jslib-common/services/container.service';
-import { CryptoService } from 'jslib-common/services/crypto.service';
-import { EnvironmentService } from 'jslib-common/services/environment.service';
-import { FileUploadService } from 'jslib-common/services/fileUpload.service';
-import { FolderService } from 'jslib-common/services/folder.service';
-import { KeyConnectorService } from 'jslib-common/services/keyConnector.service';
-import { NoopMessagingService } from 'jslib-common/services/noopMessaging.service';
-import { PasswordGenerationService } from 'jslib-common/services/passwordGeneration.service';
-import { PolicyService } from 'jslib-common/services/policy.service';
-import { SearchService } from 'jslib-common/services/search.service';
-import { SendService } from 'jslib-common/services/send.service';
-import { SettingsService } from 'jslib-common/services/settings.service';
-import { SyncService as LoginSyncService } from 'jslib-common/services/sync.service';
-import { TokenService } from 'jslib-common/services/token.service';
-import { UserService } from 'jslib-common/services/user.service';
+import { ApiKeyService } from "jslib-common/services/apiKey.service";
+import { AppIdService } from "jslib-common/services/appId.service";
+import { CipherService } from "jslib-common/services/cipher.service";
+import { CollectionService } from "jslib-common/services/collection.service";
+import { ConstantsService } from "jslib-common/services/constants.service";
+import { ContainerService } from "jslib-common/services/container.service";
+import { CryptoService } from "jslib-common/services/crypto.service";
+import { EnvironmentService } from "jslib-common/services/environment.service";
+import { FileUploadService } from "jslib-common/services/fileUpload.service";
+import { FolderService } from "jslib-common/services/folder.service";
+import { KeyConnectorService } from "jslib-common/services/keyConnector.service";
+import { NoopMessagingService } from "jslib-common/services/noopMessaging.service";
+import { PasswordGenerationService } from "jslib-common/services/passwordGeneration.service";
+import { PolicyService } from "jslib-common/services/policy.service";
+import { SearchService } from "jslib-common/services/search.service";
+import { SendService } from "jslib-common/services/send.service";
+import { SettingsService } from "jslib-common/services/settings.service";
+import { SyncService as LoginSyncService } from "jslib-common/services/sync.service";
+import { TokenService } from "jslib-common/services/token.service";
+import { UserService } from "jslib-common/services/user.service";
-import { StorageService as StorageServiceAbstraction } from 'jslib-common/abstractions/storage.service';
+import { StorageService as StorageServiceAbstraction } from "jslib-common/abstractions/storage.service";
-import { Program } from './program';
-import { refreshToken } from './services/api.service';
+import { Program } from "./program";
+import { refreshToken } from "./services/api.service";
// tslint:disable-next-line
-const packageJson = require('./package.json');
+const packageJson = require("./package.json");
export let searchService: SearchService = null;
export class Main {
- dataFilePath: string;
- logService: ConsoleLogService;
- messagingService: NoopMessagingService;
- storageService: LowdbStorageService;
- secureStorageService: StorageServiceAbstraction;
- i18nService: I18nService;
- platformUtilsService: CliPlatformUtilsService;
- constantsService: ConstantsService;
- cryptoService: CryptoService;
- tokenService: TokenService;
- appIdService: AppIdService;
- apiService: NodeApiService;
- environmentService: EnvironmentService;
- apiKeyService: ApiKeyService;
- userService: UserService;
- containerService: ContainerService;
- cryptoFunctionService: NodeCryptoFunctionService;
- authService: AuthService;
- configurationService: ConfigurationService;
- collectionService: CollectionService;
- cipherService: CipherService;
- fileUploadService: FileUploadService;
- folderService: FolderService;
- searchService: SearchService;
- sendService: SendService;
- settingsService: SettingsService;
- syncService: SyncService;
- passwordGenerationService: PasswordGenerationService;
- policyService: PolicyService;
- loginSyncService: LoginSyncService;
- keyConnectorService: KeyConnectorService;
- program: Program;
+ dataFilePath: string;
+ logService: ConsoleLogService;
+ messagingService: NoopMessagingService;
+ storageService: LowdbStorageService;
+ secureStorageService: StorageServiceAbstraction;
+ i18nService: I18nService;
+ platformUtilsService: CliPlatformUtilsService;
+ constantsService: ConstantsService;
+ cryptoService: CryptoService;
+ tokenService: TokenService;
+ appIdService: AppIdService;
+ apiService: NodeApiService;
+ environmentService: EnvironmentService;
+ apiKeyService: ApiKeyService;
+ userService: UserService;
+ containerService: ContainerService;
+ cryptoFunctionService: NodeCryptoFunctionService;
+ authService: AuthService;
+ configurationService: ConfigurationService;
+ collectionService: CollectionService;
+ cipherService: CipherService;
+ fileUploadService: FileUploadService;
+ folderService: FolderService;
+ searchService: SearchService;
+ sendService: SendService;
+ settingsService: SettingsService;
+ syncService: SyncService;
+ passwordGenerationService: PasswordGenerationService;
+ policyService: PolicyService;
+ loginSyncService: LoginSyncService;
+ keyConnectorService: KeyConnectorService;
+ program: Program;
- constructor() {
- const applicationName = 'Bitwarden Directory Connector';
- if (process.env.BITWARDENCLI_CONNECTOR_APPDATA_DIR) {
- this.dataFilePath = path.resolve(process.env.BITWARDENCLI_CONNECTOR_APPDATA_DIR);
- } else if (process.env.BITWARDEN_CONNECTOR_APPDATA_DIR) {
- this.dataFilePath = path.resolve(process.env.BITWARDEN_CONNECTOR_APPDATA_DIR);
- } else if (fs.existsSync(path.join(__dirname, 'bitwarden-connector-appdata'))) {
- this.dataFilePath = path.join(__dirname, 'bitwarden-connector-appdata');
- } else if (process.platform === 'darwin') {
- this.dataFilePath = path.join(process.env.HOME, 'Library/Application Support/' + applicationName);
- } else if (process.platform === 'win32') {
- this.dataFilePath = path.join(process.env.APPDATA, applicationName);
- } else if (process.env.XDG_CONFIG_HOME) {
- this.dataFilePath = path.join(process.env.XDG_CONFIG_HOME, applicationName);
- } else {
- this.dataFilePath = path.join(process.env.HOME, '.config/' + applicationName);
- }
-
- const plaintextSecrets = process.env.BITWARDENCLI_CONNECTOR_PLAINTEXT_SECRETS === 'true';
- this.i18nService = new I18nService('en', './locales');
- this.platformUtilsService = new CliPlatformUtilsService('connector', packageJson);
- this.logService = new ConsoleLogService(this.platformUtilsService.isDev(),
- level => process.env.BITWARDENCLI_CONNECTOR_DEBUG !== 'true' && level <= LogLevelType.Info);
- this.cryptoFunctionService = new NodeCryptoFunctionService();
- this.storageService = new LowdbStorageService(this.logService, null, this.dataFilePath, false, true);
- this.secureStorageService = plaintextSecrets ?
- this.storageService : new KeytarSecureStorageService(applicationName);
- this.cryptoService = new CryptoService(this.storageService, this.secureStorageService,
- this.cryptoFunctionService, this.platformUtilsService, this.logService);
- this.appIdService = new AppIdService(this.storageService);
- this.tokenService = new TokenService(this.storageService);
- this.messagingService = new NoopMessagingService();
- this.environmentService = new EnvironmentService(this.storageService);
- this.apiService = new NodeApiService(this.tokenService, this.platformUtilsService, this.environmentService,
- () => refreshToken(this.apiKeyService, this.authService), async (expired: boolean) => await this.logout(),
- 'Bitwarden_DC/' + this.platformUtilsService.getApplicationVersion() +
- ' (' + this.platformUtilsService.getDeviceString().toUpperCase() + ')', (clientId, clientSecret) =>
- this.authService.logInApiKey(clientId, clientSecret));
- this.apiKeyService = new ApiKeyService(this.tokenService, this.storageService);
- this.userService = new UserService(this.tokenService, this.storageService);
- this.containerService = new ContainerService(this.cryptoService);
- this.keyConnectorService = new KeyConnectorService(this.storageService, this.userService, this.cryptoService,
- this.apiService, this.tokenService, this.logService);
- this.authService = new AuthService(this.cryptoService, this.apiService, this.userService, this.tokenService,
- this.appIdService, this.i18nService, this.platformUtilsService, this.messagingService, null,
- this.logService, this.apiKeyService, this.cryptoFunctionService, this.environmentService, this.keyConnectorService);
- this.configurationService = new ConfigurationService(this.storageService, this.secureStorageService,
- process.env.BITWARDENCLI_CONNECTOR_PLAINTEXT_SECRETS !== 'true');
- this.syncService = new SyncService(this.configurationService, this.logService, this.cryptoFunctionService,
- this.apiService, this.messagingService, this.i18nService, this.environmentService);
- this.passwordGenerationService = new PasswordGenerationService(this.cryptoService, this.storageService, null);
- this.policyService = new PolicyService(this.userService, this.storageService, this.apiService);
- this.settingsService = new SettingsService(this.userService, this.storageService);
- this.fileUploadService = new FileUploadService(this.logService, this.apiService);
- this.cipherService = new CipherService(this.cryptoService, this.userService, this.settingsService,
- this.apiService, this.fileUploadService, this.storageService, this.i18nService, () => searchService,
- this.logService);
- this.searchService = new SearchService(this.cipherService, this.logService, this.i18nService);
- this.folderService = new FolderService(this.cryptoService, this.userService, this.apiService,
- this.storageService, this.i18nService, this.cipherService);
- this.collectionService = new CollectionService(this.cryptoService, this.userService, this.storageService,
- this.i18nService);
- this.sendService = new SendService(this.cryptoService, this.userService, this.apiService, this.fileUploadService, this.storageService,
- this.i18nService, this.cryptoFunctionService);
-
- this.loginSyncService = new LoginSyncService(this.userService, this.apiService, this.settingsService,
- this.folderService, this.cipherService, this.cryptoService, this.collectionService, this.storageService,
- this.messagingService, this.policyService, this.sendService, this.logService, this.tokenService,
- this.keyConnectorService, async (expired: boolean) => this.messagingService.send('logout', { expired: expired }));
-
- this.program = new Program(this);
+ constructor() {
+ const applicationName = "Bitwarden Directory Connector";
+ if (process.env.BITWARDENCLI_CONNECTOR_APPDATA_DIR) {
+ this.dataFilePath = path.resolve(process.env.BITWARDENCLI_CONNECTOR_APPDATA_DIR);
+ } else if (process.env.BITWARDEN_CONNECTOR_APPDATA_DIR) {
+ this.dataFilePath = path.resolve(process.env.BITWARDEN_CONNECTOR_APPDATA_DIR);
+ } else if (fs.existsSync(path.join(__dirname, "bitwarden-connector-appdata"))) {
+ this.dataFilePath = path.join(__dirname, "bitwarden-connector-appdata");
+ } else if (process.platform === "darwin") {
+ this.dataFilePath = path.join(
+ process.env.HOME,
+ "Library/Application Support/" + applicationName
+ );
+ } else if (process.platform === "win32") {
+ this.dataFilePath = path.join(process.env.APPDATA, applicationName);
+ } else if (process.env.XDG_CONFIG_HOME) {
+ this.dataFilePath = path.join(process.env.XDG_CONFIG_HOME, applicationName);
+ } else {
+ this.dataFilePath = path.join(process.env.HOME, ".config/" + applicationName);
}
- async run() {
- await this.init();
- this.program.run();
- }
+ const plaintextSecrets = process.env.BITWARDENCLI_CONNECTOR_PLAINTEXT_SECRETS === "true";
+ this.i18nService = new I18nService("en", "./locales");
+ this.platformUtilsService = new CliPlatformUtilsService("connector", packageJson);
+ this.logService = new ConsoleLogService(
+ this.platformUtilsService.isDev(),
+ (level) => process.env.BITWARDENCLI_CONNECTOR_DEBUG !== "true" && level <= LogLevelType.Info
+ );
+ this.cryptoFunctionService = new NodeCryptoFunctionService();
+ this.storageService = new LowdbStorageService(
+ this.logService,
+ null,
+ this.dataFilePath,
+ false,
+ true
+ );
+ this.secureStorageService = plaintextSecrets
+ ? this.storageService
+ : new KeytarSecureStorageService(applicationName);
+ this.cryptoService = new CryptoService(
+ this.storageService,
+ this.secureStorageService,
+ this.cryptoFunctionService,
+ this.platformUtilsService,
+ this.logService
+ );
+ this.appIdService = new AppIdService(this.storageService);
+ this.tokenService = new TokenService(this.storageService);
+ this.messagingService = new NoopMessagingService();
+ this.environmentService = new EnvironmentService(this.storageService);
+ this.apiService = new NodeApiService(
+ this.tokenService,
+ this.platformUtilsService,
+ this.environmentService,
+ () => refreshToken(this.apiKeyService, this.authService),
+ async (expired: boolean) => await this.logout(),
+ "Bitwarden_DC/" +
+ this.platformUtilsService.getApplicationVersion() +
+ " (" +
+ this.platformUtilsService.getDeviceString().toUpperCase() +
+ ")",
+ (clientId, clientSecret) => this.authService.logInApiKey(clientId, clientSecret)
+ );
+ this.apiKeyService = new ApiKeyService(this.tokenService, this.storageService);
+ this.userService = new UserService(this.tokenService, this.storageService);
+ this.containerService = new ContainerService(this.cryptoService);
+ this.keyConnectorService = new KeyConnectorService(
+ this.storageService,
+ this.userService,
+ this.cryptoService,
+ this.apiService,
+ this.tokenService,
+ this.logService
+ );
+ this.authService = new AuthService(
+ this.cryptoService,
+ this.apiService,
+ this.userService,
+ this.tokenService,
+ this.appIdService,
+ this.i18nService,
+ this.platformUtilsService,
+ this.messagingService,
+ null,
+ this.logService,
+ this.apiKeyService,
+ this.cryptoFunctionService,
+ this.environmentService,
+ this.keyConnectorService
+ );
+ this.configurationService = new ConfigurationService(
+ this.storageService,
+ this.secureStorageService,
+ process.env.BITWARDENCLI_CONNECTOR_PLAINTEXT_SECRETS !== "true"
+ );
+ this.syncService = new SyncService(
+ this.configurationService,
+ this.logService,
+ this.cryptoFunctionService,
+ this.apiService,
+ this.messagingService,
+ this.i18nService,
+ this.environmentService
+ );
+ this.passwordGenerationService = new PasswordGenerationService(
+ this.cryptoService,
+ this.storageService,
+ null
+ );
+ this.policyService = new PolicyService(this.userService, this.storageService, this.apiService);
+ this.settingsService = new SettingsService(this.userService, this.storageService);
+ this.fileUploadService = new FileUploadService(this.logService, this.apiService);
+ this.cipherService = new CipherService(
+ this.cryptoService,
+ this.userService,
+ this.settingsService,
+ this.apiService,
+ this.fileUploadService,
+ this.storageService,
+ this.i18nService,
+ () => searchService,
+ this.logService
+ );
+ this.searchService = new SearchService(this.cipherService, this.logService, this.i18nService);
+ this.folderService = new FolderService(
+ this.cryptoService,
+ this.userService,
+ this.apiService,
+ this.storageService,
+ this.i18nService,
+ this.cipherService
+ );
+ this.collectionService = new CollectionService(
+ this.cryptoService,
+ this.userService,
+ this.storageService,
+ this.i18nService
+ );
+ this.sendService = new SendService(
+ this.cryptoService,
+ this.userService,
+ this.apiService,
+ this.fileUploadService,
+ this.storageService,
+ this.i18nService,
+ this.cryptoFunctionService
+ );
- async logout() {
- await this.tokenService.clearToken();
- await this.apiKeyService.clear();
- }
+ this.loginSyncService = new LoginSyncService(
+ this.userService,
+ this.apiService,
+ this.settingsService,
+ this.folderService,
+ this.cipherService,
+ this.cryptoService,
+ this.collectionService,
+ this.storageService,
+ this.messagingService,
+ this.policyService,
+ this.sendService,
+ this.logService,
+ this.tokenService,
+ this.keyConnectorService,
+ async (expired: boolean) => this.messagingService.send("logout", { expired: expired })
+ );
- private async init() {
- await this.storageService.init();
- this.containerService.attachToWindow(global);
- await this.environmentService.setUrlsFromStorage();
- // Dev Server URLs. Comment out the line above.
- // this.apiService.setUrls({
- // base: null,
- // api: 'http://localhost:4000',
- // identity: 'http://localhost:33656',
- // });
- const locale = await this.storageService.get(ConstantsService.localeKey);
- await this.i18nService.init(locale);
- this.authService.init();
+ this.program = new Program(this);
+ }
- const installedVersion = await this.storageService.get(ConstantsService.installedVersionKey);
- const currentVersion = await this.platformUtilsService.getApplicationVersion();
- if (installedVersion == null || installedVersion !== currentVersion) {
- await this.storageService.save(ConstantsService.installedVersionKey, currentVersion);
- }
+ async run() {
+ await this.init();
+ this.program.run();
+ }
+
+ async logout() {
+ await this.tokenService.clearToken();
+ await this.apiKeyService.clear();
+ }
+
+ private async init() {
+ await this.storageService.init();
+ this.containerService.attachToWindow(global);
+ await this.environmentService.setUrlsFromStorage();
+ // Dev Server URLs. Comment out the line above.
+ // this.apiService.setUrls({
+ // base: null,
+ // api: 'http://localhost:4000',
+ // identity: 'http://localhost:33656',
+ // });
+ const locale = await this.storageService.get(ConstantsService.localeKey);
+ await this.i18nService.init(locale);
+ this.authService.init();
+
+ const installedVersion = await this.storageService.get(
+ ConstantsService.installedVersionKey
+ );
+ const currentVersion = await this.platformUtilsService.getApplicationVersion();
+ if (installedVersion == null || installedVersion !== currentVersion) {
+ await this.storageService.save(ConstantsService.installedVersionKey, currentVersion);
}
+ }
}
const main = new Main();
diff --git a/src/commands/clearCache.command.ts b/src/commands/clearCache.command.ts
index 946117a7..5831baaf 100644
--- a/src/commands/clearCache.command.ts
+++ b/src/commands/clearCache.command.ts
@@ -1,22 +1,25 @@
-import * as program from 'commander';
+import * as program from "commander";
-import { I18nService } from 'jslib-common/abstractions/i18n.service';
+import { I18nService } from "jslib-common/abstractions/i18n.service";
-import { ConfigurationService } from '../services/configuration.service';
+import { ConfigurationService } from "../services/configuration.service";
-import { Response } from 'jslib-node/cli/models/response';
-import { MessageResponse } from 'jslib-node/cli/models/response/messageResponse';
+import { Response } from "jslib-node/cli/models/response";
+import { MessageResponse } from "jslib-node/cli/models/response/messageResponse";
export class ClearCacheCommand {
- constructor(private configurationService: ConfigurationService, private i18nService: I18nService) { }
+ constructor(
+ private configurationService: ConfigurationService,
+ private i18nService: I18nService
+ ) {}
- async run(cmd: program.OptionValues): Promise {
- try {
- await this.configurationService.clearStatefulSettings(true);
- const res = new MessageResponse(this.i18nService.t('syncCacheCleared'), null);
- return Response.success(res);
- } catch (e) {
- return Response.error(e);
- }
+ async run(cmd: program.OptionValues): Promise {
+ try {
+ await this.configurationService.clearStatefulSettings(true);
+ const res = new MessageResponse(this.i18nService.t("syncCacheCleared"), null);
+ return Response.success(res);
+ } catch (e) {
+ return Response.error(e);
}
+ }
}
diff --git a/src/commands/config.command.ts b/src/commands/config.command.ts
index b314020f..d50f4e29 100644
--- a/src/commands/config.command.ts
+++ b/src/commands/config.command.ts
@@ -1,150 +1,160 @@
-import * as program from 'commander';
+import * as program from "commander";
-import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
-import { I18nService } from 'jslib-common/abstractions/i18n.service';
+import { EnvironmentService } from "jslib-common/abstractions/environment.service";
+import { I18nService } from "jslib-common/abstractions/i18n.service";
-import { ConfigurationService } from '../services/configuration.service';
+import { ConfigurationService } from "../services/configuration.service";
-import { DirectoryType } from '../enums/directoryType';
+import { DirectoryType } from "../enums/directoryType";
-import { Response } from 'jslib-node/cli/models/response';
-import { MessageResponse } from 'jslib-node/cli/models/response/messageResponse';
+import { Response } from "jslib-node/cli/models/response";
+import { MessageResponse } from "jslib-node/cli/models/response/messageResponse";
-import { AzureConfiguration } from '../models/azureConfiguration';
-import { GSuiteConfiguration } from '../models/gsuiteConfiguration';
-import { LdapConfiguration } from '../models/ldapConfiguration';
-import { OktaConfiguration } from '../models/oktaConfiguration';
-import { OneLoginConfiguration } from '../models/oneLoginConfiguration';
-import { SyncConfiguration } from '../models/syncConfiguration';
+import { AzureConfiguration } from "../models/azureConfiguration";
+import { GSuiteConfiguration } from "../models/gsuiteConfiguration";
+import { LdapConfiguration } from "../models/ldapConfiguration";
+import { OktaConfiguration } from "../models/oktaConfiguration";
+import { OneLoginConfiguration } from "../models/oneLoginConfiguration";
+import { SyncConfiguration } from "../models/syncConfiguration";
-import { ConnectorUtils } from '../utils';
+import { ConnectorUtils } from "../utils";
-import { NodeUtils } from 'jslib-common/misc/nodeUtils';
+import { NodeUtils } from "jslib-common/misc/nodeUtils";
export class ConfigCommand {
- private directory: DirectoryType;
- private ldap = new LdapConfiguration();
- private gsuite = new GSuiteConfiguration();
- private azure = new AzureConfiguration();
- private okta = new OktaConfiguration();
- private oneLogin = new OneLoginConfiguration();
- private sync = new SyncConfiguration();
+ private directory: DirectoryType;
+ private ldap = new LdapConfiguration();
+ private gsuite = new GSuiteConfiguration();
+ private azure = new AzureConfiguration();
+ private okta = new OktaConfiguration();
+ private oneLogin = new OneLoginConfiguration();
+ private sync = new SyncConfiguration();
- constructor(private environmentService: EnvironmentService, private i18nService: I18nService,
- private configurationService: ConfigurationService) { }
+ constructor(
+ private environmentService: EnvironmentService,
+ private i18nService: I18nService,
+ private configurationService: ConfigurationService
+ ) {}
- async run(setting: string, value: string, options: program.OptionValues): Promise {
- setting = setting.toLowerCase();
- if (value == null || value === '') {
- if (options.secretfile) {
- value = await NodeUtils.readFirstLine(options.secretfile);
- } else if (options.secretenv && process.env[options.secretenv]) {
- value = process.env[options.secretenv];
- }
- }
- try {
- switch (setting) {
- case 'server':
- await this.setServer(value);
- break;
- case 'directory':
- await this.setDirectory(value);
- break;
- case 'ldap.password':
- await this.setLdapPassword(value);
- break;
- case 'gsuite.key':
- await this.setGSuiteKey(value);
- break;
- case 'azure.key':
- await this.setAzureKey(value);
- break;
- case 'okta.token':
- await this.setOktaToken(value);
- break;
- case 'onelogin.secret':
- await this.setOneLoginSecret(value);
- break;
- default:
- return Response.badRequest('Unknown setting.');
- }
- } catch (e) {
- return Response.error(e);
- }
- const res = new MessageResponse(this.i18nService.t('savedSetting', setting), null);
- return Response.success(res);
+ async run(setting: string, value: string, options: program.OptionValues): Promise {
+ setting = setting.toLowerCase();
+ if (value == null || value === "") {
+ if (options.secretfile) {
+ value = await NodeUtils.readFirstLine(options.secretfile);
+ } else if (options.secretenv && process.env[options.secretenv]) {
+ value = process.env[options.secretenv];
+ }
}
-
- private async setServer(url: string) {
- url = (url === 'null' || url === 'bitwarden.com' || url === 'https://bitwarden.com' ? null : url);
- await this.environmentService.setUrls({
- base: url,
- });
+ try {
+ switch (setting) {
+ case "server":
+ await this.setServer(value);
+ break;
+ case "directory":
+ await this.setDirectory(value);
+ break;
+ case "ldap.password":
+ await this.setLdapPassword(value);
+ break;
+ case "gsuite.key":
+ await this.setGSuiteKey(value);
+ break;
+ case "azure.key":
+ await this.setAzureKey(value);
+ break;
+ case "okta.token":
+ await this.setOktaToken(value);
+ break;
+ case "onelogin.secret":
+ await this.setOneLoginSecret(value);
+ break;
+ default:
+ return Response.badRequest("Unknown setting.");
+ }
+ } catch (e) {
+ return Response.error(e);
}
+ const res = new MessageResponse(this.i18nService.t("savedSetting", setting), null);
+ return Response.success(res);
+ }
- private async setDirectory(type: string) {
- const dir = parseInt(type, null);
- if (dir < DirectoryType.Ldap || dir > DirectoryType.OneLogin) {
- throw new Error('Invalid directory type value.');
- }
- await this.loadConfig();
- this.directory = dir;
- await this.saveConfig();
- }
+ private async setServer(url: string) {
+ url = url === "null" || url === "bitwarden.com" || url === "https://bitwarden.com" ? null : url;
+ await this.environmentService.setUrls({
+ base: url,
+ });
+ }
- private async setLdapPassword(password: string) {
- await this.loadConfig();
- this.ldap.password = password;
- await this.saveConfig();
+ private async setDirectory(type: string) {
+ const dir = parseInt(type, null);
+ if (dir < DirectoryType.Ldap || dir > DirectoryType.OneLogin) {
+ throw new Error("Invalid directory type value.");
}
+ await this.loadConfig();
+ this.directory = dir;
+ await this.saveConfig();
+ }
- private async setGSuiteKey(key: string) {
- await this.loadConfig();
- this.gsuite.privateKey = key != null ? key.trimLeft() : null;
- await this.saveConfig();
- }
+ private async setLdapPassword(password: string) {
+ await this.loadConfig();
+ this.ldap.password = password;
+ await this.saveConfig();
+ }
- private async setAzureKey(key: string) {
- await this.loadConfig();
- this.azure.key = key;
- await this.saveConfig();
- }
+ private async setGSuiteKey(key: string) {
+ await this.loadConfig();
+ this.gsuite.privateKey = key != null ? key.trimLeft() : null;
+ await this.saveConfig();
+ }
- private async setOktaToken(token: string) {
- await this.loadConfig();
- this.okta.token = token;
- await this.saveConfig();
- }
+ private async setAzureKey(key: string) {
+ await this.loadConfig();
+ this.azure.key = key;
+ await this.saveConfig();
+ }
- private async setOneLoginSecret(secret: string) {
- await this.loadConfig();
- this.oneLogin.clientSecret = secret;
- await this.saveConfig();
- }
+ private async setOktaToken(token: string) {
+ await this.loadConfig();
+ this.okta.token = token;
+ await this.saveConfig();
+ }
- private async loadConfig() {
- this.directory = await this.configurationService.getDirectoryType();
- this.ldap = (await this.configurationService.getDirectory(DirectoryType.Ldap)) ||
- this.ldap;
- this.gsuite = (await this.configurationService.getDirectory(DirectoryType.GSuite)) ||
- this.gsuite;
- this.azure = (await this.configurationService.getDirectory(
- DirectoryType.AzureActiveDirectory)) || this.azure;
- this.okta = (await this.configurationService.getDirectory(
- DirectoryType.Okta)) || this.okta;
- this.oneLogin = (await this.configurationService.getDirectory(
- DirectoryType.OneLogin)) || this.oneLogin;
- this.sync = (await this.configurationService.getSync()) || this.sync;
- }
+ private async setOneLoginSecret(secret: string) {
+ await this.loadConfig();
+ this.oneLogin.clientSecret = secret;
+ await this.saveConfig();
+ }
- private async saveConfig() {
- ConnectorUtils.adjustConfigForSave(this.ldap, this.sync);
- await this.configurationService.saveDirectoryType(this.directory);
- await this.configurationService.saveDirectory(DirectoryType.Ldap, this.ldap);
- await this.configurationService.saveDirectory(DirectoryType.GSuite, this.gsuite);
- await this.configurationService.saveDirectory(DirectoryType.AzureActiveDirectory, this.azure);
- await this.configurationService.saveDirectory(DirectoryType.Okta, this.okta);
- await this.configurationService.saveDirectory(DirectoryType.OneLogin, this.oneLogin);
- await this.configurationService.saveSync(this.sync);
- }
+ private async loadConfig() {
+ this.directory = await this.configurationService.getDirectoryType();
+ this.ldap =
+ (await this.configurationService.getDirectory(DirectoryType.Ldap)) ||
+ this.ldap;
+ this.gsuite =
+ (await this.configurationService.getDirectory(DirectoryType.GSuite)) ||
+ this.gsuite;
+ this.azure =
+ (await this.configurationService.getDirectory(
+ DirectoryType.AzureActiveDirectory
+ )) || this.azure;
+ this.okta =
+ (await this.configurationService.getDirectory(DirectoryType.Okta)) ||
+ this.okta;
+ this.oneLogin =
+ (await this.configurationService.getDirectory(
+ DirectoryType.OneLogin
+ )) || this.oneLogin;
+ this.sync = (await this.configurationService.getSync()) || this.sync;
+ }
+
+ private async saveConfig() {
+ ConnectorUtils.adjustConfigForSave(this.ldap, this.sync);
+ await this.configurationService.saveDirectoryType(this.directory);
+ await this.configurationService.saveDirectory(DirectoryType.Ldap, this.ldap);
+ await this.configurationService.saveDirectory(DirectoryType.GSuite, this.gsuite);
+ await this.configurationService.saveDirectory(DirectoryType.AzureActiveDirectory, this.azure);
+ await this.configurationService.saveDirectory(DirectoryType.Okta, this.okta);
+ await this.configurationService.saveDirectory(DirectoryType.OneLogin, this.oneLogin);
+ await this.configurationService.saveSync(this.sync);
+ }
}
diff --git a/src/commands/lastSync.command.ts b/src/commands/lastSync.command.ts
index eacc88e5..ccccce5f 100644
--- a/src/commands/lastSync.command.ts
+++ b/src/commands/lastSync.command.ts
@@ -1,29 +1,31 @@
-import * as program from 'commander';
+import * as program from "commander";
-import { ConfigurationService } from '../services/configuration.service';
+import { ConfigurationService } from "../services/configuration.service";
-import { Response } from 'jslib-node/cli/models/response';
-import { StringResponse } from 'jslib-node/cli/models/response/stringResponse';
+import { Response } from "jslib-node/cli/models/response";
+import { StringResponse } from "jslib-node/cli/models/response/stringResponse";
export class LastSyncCommand {
- constructor(private configurationService: ConfigurationService) { }
+ constructor(private configurationService: ConfigurationService) {}
- async run(object: string): Promise {
- try {
- switch (object.toLowerCase()) {
- case 'groups':
- const groupsDate = await this.configurationService.getLastGroupSyncDate();
- const groupsRes = new StringResponse(groupsDate == null ? null : groupsDate.toISOString());
- return Response.success(groupsRes);
- case 'users':
- const usersDate = await this.configurationService.getLastUserSyncDate();
- const usersRes = new StringResponse(usersDate == null ? null : usersDate.toISOString());
- return Response.success(usersRes);
- default:
- return Response.badRequest('Unknown object.');
- }
- } catch (e) {
- return Response.error(e);
- }
+ async run(object: string): Promise {
+ try {
+ switch (object.toLowerCase()) {
+ case "groups":
+ const groupsDate = await this.configurationService.getLastGroupSyncDate();
+ const groupsRes = new StringResponse(
+ groupsDate == null ? null : groupsDate.toISOString()
+ );
+ return Response.success(groupsRes);
+ case "users":
+ const usersDate = await this.configurationService.getLastUserSyncDate();
+ const usersRes = new StringResponse(usersDate == null ? null : usersDate.toISOString());
+ return Response.success(usersRes);
+ default:
+ return Response.badRequest("Unknown object.");
+ }
+ } catch (e) {
+ return Response.error(e);
}
+ }
}
diff --git a/src/commands/sync.command.ts b/src/commands/sync.command.ts
index c9f4300b..89c00111 100644
--- a/src/commands/sync.command.ts
+++ b/src/commands/sync.command.ts
@@ -1,23 +1,25 @@
-import { I18nService } from 'jslib-common/abstractions/i18n.service';
+import { I18nService } from "jslib-common/abstractions/i18n.service";
-import { SyncService } from '../services/sync.service';
+import { SyncService } from "../services/sync.service";
-import { Response } from 'jslib-node/cli/models/response';
-import { MessageResponse } from 'jslib-node/cli/models/response/messageResponse';
+import { Response } from "jslib-node/cli/models/response";
+import { MessageResponse } from "jslib-node/cli/models/response/messageResponse";
export class SyncCommand {
- constructor(private syncService: SyncService, private i18nService: I18nService) { }
+ constructor(private syncService: SyncService, private i18nService: I18nService) {}
- async run(): Promise {
- try {
- const result = await this.syncService.sync(false, false);
- const groupCount = result[0] != null ? result[0].length : 0;
- const userCount = result[1] != null ? result[1].length : 0;
- const res = new MessageResponse(this.i18nService.t('syncingComplete'),
- this.i18nService.t('syncCounts', groupCount.toString(), userCount.toString()));
- return Response.success(res);
- } catch (e) {
- return Response.error(e);
- }
+ async run(): Promise {
+ try {
+ const result = await this.syncService.sync(false, false);
+ const groupCount = result[0] != null ? result[0].length : 0;
+ const userCount = result[1] != null ? result[1].length : 0;
+ const res = new MessageResponse(
+ this.i18nService.t("syncingComplete"),
+ this.i18nService.t("syncCounts", groupCount.toString(), userCount.toString())
+ );
+ return Response.success(res);
+ } catch (e) {
+ return Response.error(e);
}
+ }
}
diff --git a/src/commands/test.command.ts b/src/commands/test.command.ts
index c5122f29..34addb95 100644
--- a/src/commands/test.command.ts
+++ b/src/commands/test.command.ts
@@ -1,24 +1,28 @@
-import * as program from 'commander';
+import * as program from "commander";
-import { I18nService } from 'jslib-common/abstractions/i18n.service';
+import { I18nService } from "jslib-common/abstractions/i18n.service";
-import { SyncService } from '../services/sync.service';
+import { SyncService } from "../services/sync.service";
-import { ConnectorUtils } from '../utils';
+import { ConnectorUtils } from "../utils";
-import { Response } from 'jslib-node/cli/models/response';
-import { TestResponse } from '../models/response/testResponse';
+import { Response } from "jslib-node/cli/models/response";
+import { TestResponse } from "../models/response/testResponse";
export class TestCommand {
- constructor(private syncService: SyncService, private i18nService: I18nService) { }
+ constructor(private syncService: SyncService, private i18nService: I18nService) {}
- async run(cmd: program.OptionValues): Promise {
- try {
- const result = await ConnectorUtils.simulate(this.syncService, this.i18nService, cmd.last || false);
- const res = new TestResponse(result);
- return Response.success(res);
- } catch (e) {
- return Response.error(e);
- }
+ async run(cmd: program.OptionValues): Promise {
+ try {
+ const result = await ConnectorUtils.simulate(
+ this.syncService,
+ this.i18nService,
+ cmd.last || false
+ );
+ const res = new TestResponse(result);
+ return Response.success(res);
+ } catch (e) {
+ return Response.error(e);
}
+ }
}
diff --git a/src/enums/directoryType.ts b/src/enums/directoryType.ts
index 4324fc06..cb3ad986 100644
--- a/src/enums/directoryType.ts
+++ b/src/enums/directoryType.ts
@@ -1,7 +1,7 @@
export enum DirectoryType {
- Ldap = 0,
- AzureActiveDirectory = 1,
- GSuite = 2,
- Okta = 3,
- OneLogin = 4,
+ Ldap = 0,
+ AzureActiveDirectory = 1,
+ GSuite = 2,
+ Okta = 3,
+ OneLogin = 4,
}
diff --git a/src/global.d.ts b/src/global.d.ts
index 8116ab17..74e63a31 100644
--- a/src/global.d.ts
+++ b/src/global.d.ts
@@ -1,3 +1,3 @@
declare function escape(s: string): string;
declare function unescape(s: string): string;
-declare module 'duo_web_sdk';
+declare module "duo_web_sdk";
diff --git a/src/index.html b/src/index.html
index 9c16f5d7..2ec2d77c 100644
--- a/src/index.html
+++ b/src/index.html
@@ -1,16 +1,19 @@

-
-
-
-
+
+
+
+
Bitwarden Directory Connector
-
-
-
+
+
+
-
+
-
+
diff --git a/src/main.ts b/src/main.ts
index e9f89f8f..33180008 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,109 +1,135 @@
-import { app } from 'electron';
-import * as path from 'path';
+import { app } from "electron";
+import * as path from "path";
-import { MenuMain } from './main/menu.main';
-import { MessagingMain } from './main/messaging.main';
-import { I18nService } from './services/i18n.service';
+import { MenuMain } from "./main/menu.main";
+import { MessagingMain } from "./main/messaging.main";
+import { I18nService } from "./services/i18n.service";
-import { KeytarStorageListener } from 'jslib-electron/keytarStorageListener';
-import { ElectronLogService } from 'jslib-electron/services/electronLog.service';
-import { ElectronMainMessagingService } from 'jslib-electron/services/electronMainMessaging.service';
-import { ElectronStorageService } from 'jslib-electron/services/electronStorage.service';
-import { TrayMain } from 'jslib-electron/tray.main';
-import { UpdaterMain } from 'jslib-electron/updater.main';
-import { WindowMain } from 'jslib-electron/window.main';
+import { KeytarStorageListener } from "jslib-electron/keytarStorageListener";
+import { ElectronLogService } from "jslib-electron/services/electronLog.service";
+import { ElectronMainMessagingService } from "jslib-electron/services/electronMainMessaging.service";
+import { ElectronStorageService } from "jslib-electron/services/electronStorage.service";
+import { TrayMain } from "jslib-electron/tray.main";
+import { UpdaterMain } from "jslib-electron/updater.main";
+import { WindowMain } from "jslib-electron/window.main";
export class Main {
- logService: ElectronLogService;
- i18nService: I18nService;
- storageService: ElectronStorageService;
- messagingService: ElectronMainMessagingService;
- keytarStorageListener: KeytarStorageListener;
+ logService: ElectronLogService;
+ i18nService: I18nService;
+ storageService: ElectronStorageService;
+ messagingService: ElectronMainMessagingService;
+ keytarStorageListener: KeytarStorageListener;
- windowMain: WindowMain;
- messagingMain: MessagingMain;
- menuMain: MenuMain;
- updaterMain: UpdaterMain;
- trayMain: TrayMain;
+ windowMain: WindowMain;
+ messagingMain: MessagingMain;
+ menuMain: MenuMain;
+ updaterMain: UpdaterMain;
+ trayMain: TrayMain;
- constructor() {
- // Set paths for portable builds
- let appDataPath = null;
- if (process.env.BITWARDEN_CONNECTOR_APPDATA_DIR != null) {
- appDataPath = process.env.BITWARDEN_CONNECTOR_APPDATA_DIR;
- } else if (process.platform === 'win32' && process.env.PORTABLE_EXECUTABLE_DIR != null) {
- appDataPath = path.join(process.env.PORTABLE_EXECUTABLE_DIR, 'bitwarden-connector-appdata');
- }
-
- if (appDataPath != null) {
- app.setPath('userData', appDataPath);
- }
- app.setPath('logs', path.join(app.getPath('userData'), 'logs'));
-
- const args = process.argv.slice(1);
- const watch = args.some(val => val === '--watch');
-
- if (watch) {
- // tslint:disable-next-line
- require('electron-reload')(__dirname, {});
- }
-
- this.logService = new ElectronLogService(null, app.getPath('userData'));
- this.i18nService = new I18nService('en', './locales/');
- this.storageService = new ElectronStorageService(app.getPath('userData'));
-
- this.windowMain = new WindowMain(this.storageService, this.logService, false, 800, 600, arg => this.processDeepLink(arg), null);
- this.menuMain = new MenuMain(this);
- this.updaterMain = new UpdaterMain(this.i18nService, this.windowMain, 'directory-connector', () => {
- this.messagingService.send('checkingForUpdate');
- }, () => {
- this.messagingService.send('doneCheckingForUpdate');
- }, () => {
- this.messagingService.send('doneCheckingForUpdate');
- }, 'bitwardenDirectoryConnector');
- this.trayMain = new TrayMain(this.windowMain, this.i18nService, this.storageService);
- this.messagingMain = new MessagingMain(this.windowMain, this.menuMain, this.updaterMain, this.trayMain);
- this.messagingService = new ElectronMainMessagingService(this.windowMain, message => {
- this.messagingMain.onMessage(message);
- });
-
- this.keytarStorageListener = new KeytarStorageListener('Bitwarden Directory Connector', null);
+ constructor() {
+ // Set paths for portable builds
+ let appDataPath = null;
+ if (process.env.BITWARDEN_CONNECTOR_APPDATA_DIR != null) {
+ appDataPath = process.env.BITWARDEN_CONNECTOR_APPDATA_DIR;
+ } else if (process.platform === "win32" && process.env.PORTABLE_EXECUTABLE_DIR != null) {
+ appDataPath = path.join(process.env.PORTABLE_EXECUTABLE_DIR, "bitwarden-connector-appdata");
}
- bootstrap() {
- this.keytarStorageListener.init();
- this.windowMain.init().then(async () => {
- await this.i18nService.init(app.getLocale());
- this.menuMain.init();
- this.messagingMain.init();
- await this.updaterMain.init();
- await this.trayMain.init(this.i18nService.t('bitwardenDirectoryConnector'));
+ if (appDataPath != null) {
+ app.setPath("userData", appDataPath);
+ }
+ app.setPath("logs", path.join(app.getPath("userData"), "logs"));
- if (!app.isDefaultProtocolClient('bwdc')) {
- app.setAsDefaultProtocolClient('bwdc');
- }
+ const args = process.argv.slice(1);
+ const watch = args.some((val) => val === "--watch");
- // Process protocol for macOS
- app.on('open-url', (event, url) => {
- event.preventDefault();
- this.processDeepLink([url]);
- });
- }, (e: any) => {
- // tslint:disable-next-line
- console.error(e);
- });
+ if (watch) {
+ // tslint:disable-next-line
+ require("electron-reload")(__dirname, {});
}
- private processDeepLink(argv: string[]): void {
- argv.filter(s => s.indexOf('bwdc://') === 0).forEach(s => {
- const url = new URL(s);
- const code = url.searchParams.get('code');
- const receivedState = url.searchParams.get('state');
- if (code != null && receivedState != null) {
- this.messagingService.send('ssoCallback', { code: code, state: receivedState });
- }
+ this.logService = new ElectronLogService(null, app.getPath("userData"));
+ this.i18nService = new I18nService("en", "./locales/");
+ this.storageService = new ElectronStorageService(app.getPath("userData"));
+
+ this.windowMain = new WindowMain(
+ this.storageService,
+ this.logService,
+ false,
+ 800,
+ 600,
+ (arg) => this.processDeepLink(arg),
+ null
+ );
+ this.menuMain = new MenuMain(this);
+ this.updaterMain = new UpdaterMain(
+ this.i18nService,
+ this.windowMain,
+ "directory-connector",
+ () => {
+ this.messagingService.send("checkingForUpdate");
+ },
+ () => {
+ this.messagingService.send("doneCheckingForUpdate");
+ },
+ () => {
+ this.messagingService.send("doneCheckingForUpdate");
+ },
+ "bitwardenDirectoryConnector"
+ );
+ this.trayMain = new TrayMain(this.windowMain, this.i18nService, this.storageService);
+ this.messagingMain = new MessagingMain(
+ this.windowMain,
+ this.menuMain,
+ this.updaterMain,
+ this.trayMain
+ );
+ this.messagingService = new ElectronMainMessagingService(this.windowMain, (message) => {
+ this.messagingMain.onMessage(message);
+ });
+
+ this.keytarStorageListener = new KeytarStorageListener("Bitwarden Directory Connector", null);
+ }
+
+ bootstrap() {
+ this.keytarStorageListener.init();
+ this.windowMain.init().then(
+ async () => {
+ await this.i18nService.init(app.getLocale());
+ this.menuMain.init();
+ this.messagingMain.init();
+ await this.updaterMain.init();
+ await this.trayMain.init(this.i18nService.t("bitwardenDirectoryConnector"));
+
+ if (!app.isDefaultProtocolClient("bwdc")) {
+ app.setAsDefaultProtocolClient("bwdc");
+ }
+
+ // Process protocol for macOS
+ app.on("open-url", (event, url) => {
+ event.preventDefault();
+ this.processDeepLink([url]);
});
- }
+ },
+ (e: any) => {
+ // tslint:disable-next-line
+ console.error(e);
+ }
+ );
+ }
+
+ private processDeepLink(argv: string[]): void {
+ argv
+ .filter((s) => s.indexOf("bwdc://") === 0)
+ .forEach((s) => {
+ const url = new URL(s);
+ const code = url.searchParams.get("code");
+ const receivedState = url.searchParams.get("state");
+ if (code != null && receivedState != null) {
+ this.messagingService.send("ssoCallback", { code: code, state: receivedState });
+ }
+ });
+ }
}
const main = new Main();
diff --git a/src/main/menu.main.ts b/src/main/menu.main.ts
index 7f2741c2..99467d62 100644
--- a/src/main/menu.main.ts
+++ b/src/main/menu.main.ts
@@ -1,68 +1,69 @@
-import {
- Menu,
- MenuItem,
- MenuItemConstructorOptions,
-} from 'electron';
+import { Menu, MenuItem, MenuItemConstructorOptions } from "electron";
-import { Main } from '../main';
+import { Main } from "../main";
-import { BaseMenu } from 'jslib-electron/baseMenu';
+import { BaseMenu } from "jslib-electron/baseMenu";
export class MenuMain extends BaseMenu {
- menu: Menu;
+ menu: Menu;
- constructor(private main: Main) {
- super(main.i18nService, main.windowMain);
+ constructor(private main: Main) {
+ super(main.i18nService, main.windowMain);
+ }
+
+ init() {
+ this.initProperties();
+ this.initContextMenu();
+ this.initApplicationMenu();
+ }
+
+ private initApplicationMenu() {
+ const template: MenuItemConstructorOptions[] = [
+ this.editMenuItemOptions,
+ {
+ label: this.i18nService.t("view"),
+ submenu: this.viewSubMenuItemOptions,
+ },
+ this.windowMenuItemOptions,
+ ];
+
+ if (process.platform === "darwin") {
+ const firstMenuPart: MenuItemConstructorOptions[] = [
+ {
+ label: this.i18nService.t("aboutBitwarden"),
+ role: "about",
+ },
+ ];
+
+ template.unshift({
+ label: this.main.i18nService.t("bitwardenDirectoryConnector"),
+ submenu: firstMenuPart.concat(this.macAppMenuItemOptions),
+ });
+
+ // Window menu
+ template[template.length - 1].submenu = this.macWindowSubmenuOptions;
}
- init() {
- this.initProperties();
- this.initContextMenu();
- this.initApplicationMenu();
- }
+ (template[template.length - 1].submenu as MenuItemConstructorOptions[]).splice(
+ 1,
+ 0,
+ {
+ label: this.main.i18nService.t(
+ process.platform === "darwin" ? "hideToMenuBar" : "hideToTray"
+ ),
+ click: () => this.main.messagingService.send("hideToTray"),
+ accelerator: "CmdOrCtrl+Shift+M",
+ },
+ {
+ type: "checkbox",
+ label: this.main.i18nService.t("alwaysOnTop"),
+ checked: this.windowMain.win.isAlwaysOnTop(),
+ click: () => this.main.windowMain.toggleAlwaysOnTop(),
+ accelerator: "CmdOrCtrl+Shift+T",
+ }
+ );
- private initApplicationMenu() {
- const template: MenuItemConstructorOptions[] = [
- this.editMenuItemOptions,
- {
- label: this.i18nService.t('view'),
- submenu: this.viewSubMenuItemOptions,
- },
- this.windowMenuItemOptions,
- ];
-
- if (process.platform === 'darwin') {
- const firstMenuPart: MenuItemConstructorOptions[] = [
- {
- label: this.i18nService.t('aboutBitwarden'),
- role: 'about',
- },
- ];
-
- template.unshift({
- label: this.main.i18nService.t('bitwardenDirectoryConnector'),
- submenu: firstMenuPart.concat(this.macAppMenuItemOptions),
- });
-
- // Window menu
- template[template.length - 1].submenu = this.macWindowSubmenuOptions;
- }
-
- (template[template.length - 1].submenu as MenuItemConstructorOptions[]).splice(1, 0,
- {
- label: this.main.i18nService.t(process.platform === 'darwin' ? 'hideToMenuBar' : 'hideToTray'),
- click: () => this.main.messagingService.send('hideToTray'),
- accelerator: 'CmdOrCtrl+Shift+M',
- },
- {
- type: 'checkbox',
- label: this.main.i18nService.t('alwaysOnTop'),
- checked: this.windowMain.win.isAlwaysOnTop(),
- click: () => this.main.windowMain.toggleAlwaysOnTop(),
- accelerator: 'CmdOrCtrl+Shift+T',
- });
-
- this.menu = Menu.buildFromTemplate(template);
- Menu.setApplicationMenu(this.menu);
- }
+ this.menu = Menu.buildFromTemplate(template);
+ Menu.setApplicationMenu(this.menu);
+ }
}
diff --git a/src/main/messaging.main.ts b/src/main/messaging.main.ts
index 4658445f..8bc70500 100644
--- a/src/main/messaging.main.ts
+++ b/src/main/messaging.main.ts
@@ -1,67 +1,68 @@
-import {
- app,
- ipcMain,
-} from 'electron';
+import { app, ipcMain } from "electron";
-import { TrayMain } from 'jslib-electron/tray.main';
-import { UpdaterMain } from 'jslib-electron/updater.main';
-import { WindowMain } from 'jslib-electron/window.main';
+import { TrayMain } from "jslib-electron/tray.main";
+import { UpdaterMain } from "jslib-electron/updater.main";
+import { WindowMain } from "jslib-electron/window.main";
-import { MenuMain } from './menu.main';
+import { MenuMain } from "./menu.main";
const SyncCheckInterval = 60 * 1000; // 1 minute
export class MessagingMain {
- private syncTimeout: NodeJS.Timer;
+ private syncTimeout: NodeJS.Timer;
- constructor(private windowMain: WindowMain, private menuMain: MenuMain,
- private updaterMain: UpdaterMain, private trayMain: TrayMain) { }
+ constructor(
+ private windowMain: WindowMain,
+ private menuMain: MenuMain,
+ private updaterMain: UpdaterMain,
+ private trayMain: TrayMain
+ ) {}
- init() {
- ipcMain.on('messagingService', async (event: any, message: any) => this.onMessage(message));
- }
+ init() {
+ ipcMain.on("messagingService", async (event: any, message: any) => this.onMessage(message));
+ }
- onMessage(message: any) {
- switch (message.command) {
- case 'checkForUpdate':
- this.updaterMain.checkForUpdate(true);
- break;
- case 'scheduleNextDirSync':
- this.scheduleNextSync();
- break;
- case 'cancelDirSync':
- this.windowMain.win.webContents.send('messagingService', {
- command: 'syncScheduleStopped',
- });
- if (this.syncTimeout) {
- global.clearTimeout(this.syncTimeout);
- }
- break;
- case 'hideToTray':
- this.trayMain.hideToTray();
- break;
- default:
- break;
- }
- }
-
- private scheduleNextSync() {
- this.windowMain.win.webContents.send('messagingService', {
- command: 'syncScheduleStarted',
+ onMessage(message: any) {
+ switch (message.command) {
+ case "checkForUpdate":
+ this.updaterMain.checkForUpdate(true);
+ break;
+ case "scheduleNextDirSync":
+ this.scheduleNextSync();
+ break;
+ case "cancelDirSync":
+ this.windowMain.win.webContents.send("messagingService", {
+ command: "syncScheduleStopped",
});
-
if (this.syncTimeout) {
- global.clearTimeout(this.syncTimeout);
+ global.clearTimeout(this.syncTimeout);
}
-
- this.syncTimeout = global.setTimeout(() => {
- if (this.windowMain.win == null) {
- return;
- }
-
- this.windowMain.win.webContents.send('messagingService', {
- command: 'checkDirSync',
- });
- }, SyncCheckInterval);
+ break;
+ case "hideToTray":
+ this.trayMain.hideToTray();
+ break;
+ default:
+ break;
}
+ }
+
+ private scheduleNextSync() {
+ this.windowMain.win.webContents.send("messagingService", {
+ command: "syncScheduleStarted",
+ });
+
+ if (this.syncTimeout) {
+ global.clearTimeout(this.syncTimeout);
+ }
+
+ this.syncTimeout = global.setTimeout(() => {
+ if (this.windowMain.win == null) {
+ return;
+ }
+
+ this.windowMain.win.webContents.send("messagingService", {
+ command: "checkDirSync",
+ });
+ }, SyncCheckInterval);
+ }
}
diff --git a/src/models/azureConfiguration.ts b/src/models/azureConfiguration.ts
index 904aec8c..38c61338 100644
--- a/src/models/azureConfiguration.ts
+++ b/src/models/azureConfiguration.ts
@@ -1,6 +1,6 @@
export class AzureConfiguration {
- identityAuthority: string;
- tenant: string;
- applicationId: string;
- key: string;
+ identityAuthority: string;
+ tenant: string;
+ applicationId: string;
+ key: string;
}
diff --git a/src/models/entry.ts b/src/models/entry.ts
index 4bfe120a..1cf3e383 100644
--- a/src/models/entry.ts
+++ b/src/models/entry.ts
@@ -1,8 +1,8 @@
export abstract class Entry {
- referenceId: string;
- externalId: string;
+ referenceId: string;
+ externalId: string;
- get displayName(): string {
- return this.referenceId;
- }
+ get displayName(): string {
+ return this.referenceId;
+ }
}
diff --git a/src/models/groupEntry.ts b/src/models/groupEntry.ts
index 207699a6..8d2c9d22 100644
--- a/src/models/groupEntry.ts
+++ b/src/models/groupEntry.ts
@@ -1,15 +1,15 @@
-import { Entry } from './entry';
+import { Entry } from "./entry";
export class GroupEntry extends Entry {
- name: string;
- userMemberExternalIds = new Set();
- groupMemberReferenceIds = new Set();
+ name: string;
+ userMemberExternalIds = new Set();
+ groupMemberReferenceIds = new Set();
- get displayName(): string {
- if (this.name == null) {
- return this.referenceId;
- }
-
- return this.name;
+ get displayName(): string {
+ if (this.name == null) {
+ return this.referenceId;
}
+
+ return this.name;
+ }
}
diff --git a/src/models/gsuiteConfiguration.ts b/src/models/gsuiteConfiguration.ts
index cbe18e8b..6d147993 100644
--- a/src/models/gsuiteConfiguration.ts
+++ b/src/models/gsuiteConfiguration.ts
@@ -1,7 +1,7 @@
export class GSuiteConfiguration {
- clientEmail: string;
- privateKey: string;
- domain: string;
- adminUser: string;
- customer: string;
+ clientEmail: string;
+ privateKey: string;
+ domain: string;
+ adminUser: string;
+ customer: string;
}
diff --git a/src/models/ldapConfiguration.ts b/src/models/ldapConfiguration.ts
index dd1f7556..3a1cbf40 100644
--- a/src/models/ldapConfiguration.ts
+++ b/src/models/ldapConfiguration.ts
@@ -1,18 +1,18 @@
export class LdapConfiguration {
- ssl = false;
- startTls = false;
- tlsCaPath: string;
- sslAllowUnauthorized = false;
- sslCertPath: string;
- sslKeyPath: string;
- sslCaPath: string;
- hostname: string;
- port = 389;
- domain: string;
- rootPath: string;
- currentUser = false;
- username: string;
- password: string;
- ad = true;
- pagedSearch = true;
+ ssl = false;
+ startTls = false;
+ tlsCaPath: string;
+ sslAllowUnauthorized = false;
+ sslCertPath: string;
+ sslKeyPath: string;
+ sslCaPath: string;
+ hostname: string;
+ port = 389;
+ domain: string;
+ rootPath: string;
+ currentUser = false;
+ username: string;
+ password: string;
+ ad = true;
+ pagedSearch = true;
}
diff --git a/src/models/oktaConfiguration.ts b/src/models/oktaConfiguration.ts
index 3e983026..88f77f41 100644
--- a/src/models/oktaConfiguration.ts
+++ b/src/models/oktaConfiguration.ts
@@ -1,4 +1,4 @@
export class OktaConfiguration {
- orgUrl: string;
- token: string;
+ orgUrl: string;
+ token: string;
}
diff --git a/src/models/oneLoginConfiguration.ts b/src/models/oneLoginConfiguration.ts
index b9a2402f..76d0f13a 100644
--- a/src/models/oneLoginConfiguration.ts
+++ b/src/models/oneLoginConfiguration.ts
@@ -1,5 +1,5 @@
export class OneLoginConfiguration {
- clientId: string;
- clientSecret: string;
- region = 'us';
+ clientId: string;
+ clientSecret: string;
+ region = "us";
}
diff --git a/src/models/response/groupResponse.ts b/src/models/response/groupResponse.ts
index d0f9c4e3..76348b42 100644
--- a/src/models/response/groupResponse.ts
+++ b/src/models/response/groupResponse.ts
@@ -1,13 +1,13 @@
-import { GroupEntry } from '../groupEntry';
+import { GroupEntry } from "../groupEntry";
export class GroupResponse {
- externalId: string;
- displayName: string;
- userIds: string[];
+ externalId: string;
+ displayName: string;
+ userIds: string[];
- constructor(g: GroupEntry) {
- this.externalId = g.externalId;
- this.displayName = g.displayName;
- this.userIds = Array.from(g.userMemberExternalIds);
- }
+ constructor(g: GroupEntry) {
+ this.externalId = g.externalId;
+ this.displayName = g.displayName;
+ this.userIds = Array.from(g.userMemberExternalIds);
+ }
}
diff --git a/src/models/response/testResponse.ts b/src/models/response/testResponse.ts
index b16f4294..1d14ca5a 100644
--- a/src/models/response/testResponse.ts
+++ b/src/models/response/testResponse.ts
@@ -1,22 +1,25 @@
-import { GroupResponse } from './groupResponse';
-import { UserResponse } from './userResponse';
+import { GroupResponse } from "./groupResponse";
+import { UserResponse } from "./userResponse";
-import { SimResult } from '../simResult';
+import { SimResult } from "../simResult";
-import { BaseResponse } from 'jslib-node/cli/models/response/baseResponse';
+import { BaseResponse } from "jslib-node/cli/models/response/baseResponse";
export class TestResponse implements BaseResponse {
- object: string;
- groups: GroupResponse[] = [];
- enabledUsers: UserResponse[] = [];
- disabledUsers: UserResponse[] = [];
- deletedUsers: UserResponse[] = [];
+ object: string;
+ groups: GroupResponse[] = [];
+ enabledUsers: UserResponse[] = [];
+ disabledUsers: UserResponse[] = [];
+ deletedUsers: UserResponse[] = [];
- constructor(result: SimResult) {
- this.object = 'test';
- this.groups = result.groups != null ? result.groups.map(g => new GroupResponse(g)) : [];
- this.enabledUsers = result.enabledUsers != null ? result.enabledUsers.map(u => new UserResponse(u)) : [];
- this.disabledUsers = result.disabledUsers != null ? result.disabledUsers.map(u => new UserResponse(u)) : [];
- this.deletedUsers = result.deletedUsers != null ? result.deletedUsers.map(u => new UserResponse(u)) : [];
- }
+ constructor(result: SimResult) {
+ this.object = "test";
+ this.groups = result.groups != null ? result.groups.map((g) => new GroupResponse(g)) : [];
+ this.enabledUsers =
+ result.enabledUsers != null ? result.enabledUsers.map((u) => new UserResponse(u)) : [];
+ this.disabledUsers =
+ result.disabledUsers != null ? result.disabledUsers.map((u) => new UserResponse(u)) : [];
+ this.deletedUsers =
+ result.deletedUsers != null ? result.deletedUsers.map((u) => new UserResponse(u)) : [];
+ }
}
diff --git a/src/models/response/userResponse.ts b/src/models/response/userResponse.ts
index aff5406c..ad1f51ad 100644
--- a/src/models/response/userResponse.ts
+++ b/src/models/response/userResponse.ts
@@ -1,11 +1,11 @@
-import { UserEntry } from '../userEntry';
+import { UserEntry } from "../userEntry";
export class UserResponse {
- externalId: string;
- displayName: string;
+ externalId: string;
+ displayName: string;
- constructor(u: UserEntry) {
- this.externalId = u.externalId;
- this.displayName = u.displayName;
- }
+ constructor(u: UserEntry) {
+ this.externalId = u.externalId;
+ this.displayName = u.displayName;
+ }
}
diff --git a/src/models/simResult.ts b/src/models/simResult.ts
index 4adf301f..d4cdda0b 100644
--- a/src/models/simResult.ts
+++ b/src/models/simResult.ts
@@ -1,10 +1,10 @@
-import { GroupEntry } from './groupEntry';
-import { UserEntry } from './userEntry';
+import { GroupEntry } from "./groupEntry";
+import { UserEntry } from "./userEntry";
export class SimResult {
- groups: GroupEntry[] = [];
- users: UserEntry[] = [];
- enabledUsers: UserEntry[] = [];
- disabledUsers: UserEntry[] = [];
- deletedUsers: UserEntry[] = [];
+ groups: GroupEntry[] = [];
+ users: UserEntry[] = [];
+ enabledUsers: UserEntry[] = [];
+ disabledUsers: UserEntry[] = [];
+ deletedUsers: UserEntry[] = [];
}
diff --git a/src/models/syncConfiguration.ts b/src/models/syncConfiguration.ts
index 8b7fa634..fe2fa194 100644
--- a/src/models/syncConfiguration.ts
+++ b/src/models/syncConfiguration.ts
@@ -1,23 +1,23 @@
export class SyncConfiguration {
- users = false;
- groups = false;
- interval = 5;
- userFilter: string;
- groupFilter: string;
- removeDisabled = false;
- overwriteExisting = false;
- largeImport = false;
- // Ldap properties
- groupObjectClass: string;
- userObjectClass: string;
- groupPath: string;
- userPath: string;
- groupNameAttribute: string;
- userEmailAttribute: string;
- memberAttribute: string;
- useEmailPrefixSuffix = false;
- emailPrefixAttribute: string;
- emailSuffix: string;
- creationDateAttribute: string;
- revisionDateAttribute: string;
+ users = false;
+ groups = false;
+ interval = 5;
+ userFilter: string;
+ groupFilter: string;
+ removeDisabled = false;
+ overwriteExisting = false;
+ largeImport = false;
+ // Ldap properties
+ groupObjectClass: string;
+ userObjectClass: string;
+ groupPath: string;
+ userPath: string;
+ groupNameAttribute: string;
+ userEmailAttribute: string;
+ memberAttribute: string;
+ useEmailPrefixSuffix = false;
+ emailPrefixAttribute: string;
+ emailSuffix: string;
+ creationDateAttribute: string;
+ revisionDateAttribute: string;
}
diff --git a/src/models/userEntry.ts b/src/models/userEntry.ts
index a0ca272e..be9a61cf 100644
--- a/src/models/userEntry.ts
+++ b/src/models/userEntry.ts
@@ -1,15 +1,15 @@
-import { Entry } from './entry';
+import { Entry } from "./entry";
export class UserEntry extends Entry {
- email: string;
- disabled = false;
- deleted = false;
+ email: string;
+ disabled = false;
+ deleted = false;
- get displayName(): string {
- if (this.email == null) {
- return this.referenceId;
- }
-
- return this.email;
+ get displayName(): string {
+ if (this.email == null) {
+ return this.referenceId;
}
+
+ return this.email;
+ }
}
diff --git a/src/program.ts b/src/program.ts
index b578658e..7e009360 100644
--- a/src/program.ts
+++ b/src/program.ts
@@ -1,302 +1,330 @@
-import * as chalk from 'chalk';
-import * as program from 'commander';
-import * as path from 'path';
+import * as chalk from "chalk";
+import * as program from "commander";
+import * as path from "path";
-import { Main } from './bwdc';
+import { Main } from "./bwdc";
-import { ClearCacheCommand } from './commands/clearCache.command';
-import { ConfigCommand } from './commands/config.command';
-import { LastSyncCommand } from './commands/lastSync.command';
-import { SyncCommand } from './commands/sync.command';
-import { TestCommand } from './commands/test.command';
+import { ClearCacheCommand } from "./commands/clearCache.command";
+import { ConfigCommand } from "./commands/config.command";
+import { LastSyncCommand } from "./commands/lastSync.command";
+import { SyncCommand } from "./commands/sync.command";
+import { TestCommand } from "./commands/test.command";
-import { LoginCommand } from 'jslib-node/cli/commands/login.command';
-import { LogoutCommand } from 'jslib-node/cli/commands/logout.command';
-import { UpdateCommand } from 'jslib-node/cli/commands/update.command';
+import { LoginCommand } from "jslib-node/cli/commands/login.command";
+import { LogoutCommand } from "jslib-node/cli/commands/logout.command";
+import { UpdateCommand } from "jslib-node/cli/commands/update.command";
-import { BaseProgram } from 'jslib-node/cli/baseProgram';
+import { BaseProgram } from "jslib-node/cli/baseProgram";
-import { ApiKeyService } from 'jslib-common/abstractions/apiKey.service';
-import { Response } from 'jslib-node/cli/models/response';
-import { StringResponse } from 'jslib-node/cli/models/response/stringResponse';
+import { ApiKeyService } from "jslib-common/abstractions/apiKey.service";
+import { Response } from "jslib-node/cli/models/response";
+import { StringResponse } from "jslib-node/cli/models/response/stringResponse";
-import { Utils } from 'jslib-common/misc/utils';
+import { Utils } from "jslib-common/misc/utils";
const writeLn = (s: string, finalLine: boolean = false, error: boolean = false) => {
- const stream = error ? process.stderr : process.stdout;
- if (finalLine && process.platform === 'win32') {
- stream.write(s);
- } else {
- stream.write(s + '\n');
- }
+ const stream = error ? process.stderr : process.stdout;
+ if (finalLine && process.platform === "win32") {
+ stream.write(s);
+ } else {
+ stream.write(s + "\n");
+ }
};
export class Program extends BaseProgram {
- private apiKeyService: ApiKeyService;
+ private apiKeyService: ApiKeyService;
- constructor(private main: Main) {
- super(main.userService, writeLn);
- this.apiKeyService = main.apiKeyService;
- }
+ constructor(private main: Main) {
+ super(main.userService, writeLn);
+ this.apiKeyService = main.apiKeyService;
+ }
- async run() {
- program
- .option('--pretty', 'Format output. JSON is tabbed with two spaces.')
- .option('--raw', 'Return raw output instead of a descriptive message.')
- .option('--response', 'Return a JSON formatted version of response output.')
- .option('--cleanexit', 'Exit with a success exit code (0) unless an error is thrown.')
- .option('--quiet', 'Don\'t return anything to stdout.')
- .option('--nointeraction', 'Do not prompt for interactive user input.')
- .version(await this.main.platformUtilsService.getApplicationVersion(), '-v, --version');
+ async run() {
+ program
+ .option("--pretty", "Format output. JSON is tabbed with two spaces.")
+ .option("--raw", "Return raw output instead of a descriptive message.")
+ .option("--response", "Return a JSON formatted version of response output.")
+ .option("--cleanexit", "Exit with a success exit code (0) unless an error is thrown.")
+ .option("--quiet", "Don't return anything to stdout.")
+ .option("--nointeraction", "Do not prompt for interactive user input.")
+ .version(await this.main.platformUtilsService.getApplicationVersion(), "-v, --version");
- program.on('option:pretty', () => {
- process.env.BW_PRETTY = 'true';
- });
+ program.on("option:pretty", () => {
+ process.env.BW_PRETTY = "true";
+ });
- program.on('option:raw', () => {
- process.env.BW_RAW = 'true';
- });
+ program.on("option:raw", () => {
+ process.env.BW_RAW = "true";
+ });
- program.on('option:quiet', () => {
- process.env.BW_QUIET = 'true';
- });
+ program.on("option:quiet", () => {
+ process.env.BW_QUIET = "true";
+ });
- program.on('option:response', () => {
- process.env.BW_RESPONSE = 'true';
- });
+ program.on("option:response", () => {
+ process.env.BW_RESPONSE = "true";
+ });
- program.on('option:cleanexit', () => {
- process.env.BW_CLEANEXIT = 'true';
- });
+ program.on("option:cleanexit", () => {
+ process.env.BW_CLEANEXIT = "true";
+ });
- program.on('option:nointeraction', () => {
- process.env.BW_NOINTERACTION = 'true';
- });
+ program.on("option:nointeraction", () => {
+ process.env.BW_NOINTERACTION = "true";
+ });
- program.on('command:*', () => {
- writeLn(chalk.redBright('Invalid command: ' + program.args.join(' ')), false, true);
- writeLn('See --help for a list of available commands.', true, true);
- process.exitCode = 1;
- });
+ program.on("command:*", () => {
+ writeLn(chalk.redBright("Invalid command: " + program.args.join(" ")), false, true);
+ writeLn("See --help for a list of available commands.", true, true);
+ process.exitCode = 1;
+ });
- program.on('--help', () => {
- writeLn('\n Examples:');
- writeLn('');
- writeLn(' bwdc login');
- writeLn(' bwdc test');
- writeLn(' bwdc sync');
- writeLn(' bwdc last-sync');
- writeLn(' bwdc config server https://bw.company.com');
- writeLn(' bwdc update');
- writeLn('', true);
- });
+ program.on("--help", () => {
+ writeLn("\n Examples:");
+ writeLn("");
+ writeLn(" bwdc login");
+ writeLn(" bwdc test");
+ writeLn(" bwdc sync");
+ writeLn(" bwdc last-sync");
+ writeLn(" bwdc config server https://bw.company.com");
+ writeLn(" bwdc update");
+ writeLn("", true);
+ });
- program
- .command('login [clientId] [clientSecret]')
- .description('Log into an organization account.', {
- clientId: 'Client_id part of your organization\'s API key',
- clientSecret: 'Client_secret part of your organization\'s API key',
- })
- .action(async (clientId: string, clientSecret: string, options: program.OptionValues) => {
- await this.exitIfAuthed();
- const command = new LoginCommand(this.main.authService, this.main.apiService, this.main.i18nService,
- this.main.environmentService, this.main.passwordGenerationService, this.main.cryptoFunctionService,
- this.main.platformUtilsService, this.main.userService, this.main.cryptoService,
- this.main.policyService, 'connector', this.main.loginSyncService, this.main.keyConnectorService);
+ program
+ .command("login [clientId] [clientSecret]")
+ .description("Log into an organization account.", {
+ clientId: "Client_id part of your organization's API key",
+ clientSecret: "Client_secret part of your organization's API key",
+ })
+ .action(async (clientId: string, clientSecret: string, options: program.OptionValues) => {
+ await this.exitIfAuthed();
+ const command = new LoginCommand(
+ this.main.authService,
+ this.main.apiService,
+ this.main.i18nService,
+ this.main.environmentService,
+ this.main.passwordGenerationService,
+ this.main.cryptoFunctionService,
+ this.main.platformUtilsService,
+ this.main.userService,
+ this.main.cryptoService,
+ this.main.policyService,
+ "connector",
+ this.main.loginSyncService,
+ this.main.keyConnectorService
+ );
- if (!Utils.isNullOrWhitespace(clientId)) {
- process.env.BW_CLIENTID = clientId;
- }
- if (!Utils.isNullOrWhitespace(clientSecret)) {
- process.env.BW_CLIENTSECRET = clientSecret;
- }
-
- options = Object.assign(options ?? {}, { apikey: true }); // force apikey use
- const response = await command.run(null, null, options);
- this.processResponse(response);
- });
-
- program
- .command('logout')
- .description('Log out of the current user account.')
- .on('--help', () => {
- writeLn('\n Examples:');
- writeLn('');
- writeLn(' bwdc logout');
- writeLn('', true);
- })
- .action(async () => {
- await this.exitIfNotAuthed();
- const command = new LogoutCommand(this.main.authService, this.main.i18nService,
- async () => await this.main.logout());
- const response = await command.run();
- this.processResponse(response);
- });
-
- program
- .command('test')
- .description('Test a simulated sync.')
- .option('-l, --last', 'Since the last successful sync.')
- .on('--help', () => {
- writeLn('\n Examples:');
- writeLn('');
- writeLn(' bwdc test');
- writeLn(' bwdc test --last');
- writeLn('', true);
- })
- .action(async (options: program.OptionValues) => {
- await this.exitIfNotAuthed();
- const command = new TestCommand(this.main.syncService, this.main.i18nService);
- const response = await command.run(options);
- this.processResponse(response);
- });
-
- program
- .command('sync')
- .description('Sync the directory.')
- .on('--help', () => {
- writeLn('\n Examples:');
- writeLn('');
- writeLn(' bwdc sync');
- writeLn('', true);
- })
- .action(async () => {
- await this.exitIfNotAuthed();
- const command = new SyncCommand(this.main.syncService, this.main.i18nService);
- const response = await command.run();
- this.processResponse(response);
- });
-
- program
- .command('last-sync