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

parameter validation

This commit is contained in:
Kyle Spearrin
2018-05-07 23:36:14 -04:00
parent 294404750d
commit 2ea71e1feb
8 changed files with 71 additions and 28 deletions

View File

@@ -72,7 +72,7 @@ const authService = new AuthService(cryptoService, apiService, userService, toke
i18nService, platformUtilsService, messagingService, false); i18nService, platformUtilsService, messagingService, false);
const configurationService = new ConfigurationService(storageService, secureStorageService); const configurationService = new ConfigurationService(storageService, secureStorageService);
const syncSevrice = new SyncService(configurationService, logService, cryptoFunctionService, apiService, const syncSevrice = new SyncService(configurationService, logService, cryptoFunctionService, apiService,
messagingService); messagingService, i18nService);
const analytics = new Analytics(window, () => true, platformUtilsService, storageService, appIdService); const analytics = new Analytics(window, () => true, platformUtilsService, storageService, appIdService);
containerService.attachToWindow(window); containerService.attachToWindow(window);

View File

@@ -97,8 +97,8 @@ export class DashboardComponent implements OnInit, OnDestroy {
} }
async simulate() { async simulate() {
this.simGroups = null; this.simGroups = [];
this.simUsers = null; this.simUsers = [];
this.simEnabledUsers = []; this.simEnabledUsers = [];
this.simDisabledUsers = []; this.simDisabledUsers = [];
this.simDeletedUsers = []; this.simDeletedUsers = [];
@@ -106,14 +106,20 @@ export class DashboardComponent implements OnInit, OnDestroy {
this.simPromise = new Promise(async (resolve, reject) => { this.simPromise = new Promise(async (resolve, reject) => {
try { try {
const result = await this.syncService.sync(!this.simSinceLast, true); const result = await this.syncService.sync(!this.simSinceLast, true);
this.simUsers = result[1]; if (result[0] != null) {
this.simGroups = result[0]; this.simGroups = result[0];
}
if (result[1] != null) {
this.simUsers = result[1];
}
} catch (e) { } catch (e) {
this.simGroups = null;
this.simUsers = null;
reject(e || this.i18nService.t('syncError')); reject(e || this.i18nService.t('syncError'));
return;
} }
const userMap = new Map<string, UserEntry>(); const userMap = new Map<string, UserEntry>();
if (this.simUsers != null) {
this.sort(this.simUsers); this.sort(this.simUsers);
for (const u of this.simUsers) { for (const u of this.simUsers) {
userMap.set(u.externalId, u); userMap.set(u.externalId, u);
@@ -125,9 +131,8 @@ export class DashboardComponent implements OnInit, OnDestroy {
this.simEnabledUsers.push(u); this.simEnabledUsers.push(u);
} }
} }
}
if (userMap.size > 0 && this.simGroups != null) { if (userMap.size > 0) {
this.sort(this.simGroups); this.sort(this.simGroups);
for (const g of this.simGroups) { for (const g of this.simGroups) {
if (g.userMemberExternalIds == null) { if (g.userMemberExternalIds == null) {

View File

@@ -534,5 +534,11 @@
}, },
"logInDesc": { "logInDesc": {
"message": "Log in as an organization admin user below." "message": "Log in as an organization admin user below."
},
"dirConfigIncomplete": {
"message": "Directory configuration incomplete."
},
"usernamePasswordNotConfigured": {
"message": "Username/password are not configured."
} }
} }

View File

@@ -14,6 +14,9 @@ import { BaseDirectoryService } from './baseDirectory.service';
import { ConfigurationService } from './configuration.service'; import { ConfigurationService } from './configuration.service';
import { DirectoryService } from './directory.service'; import { DirectoryService } from './directory.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { LogService } from 'jslib/abstractions/log.service';
const NextLink = '@odata.nextLink'; const NextLink = '@odata.nextLink';
const DeltaLink = '@odata.deltaLink'; const DeltaLink = '@odata.deltaLink';
const ObjectType = '@odata.type'; const ObjectType = '@odata.type';
@@ -25,7 +28,8 @@ export class AzureDirectoryService extends BaseDirectoryService implements Direc
private accessToken: string; private accessToken: string;
private accessTokenExpiration: Date; private accessTokenExpiration: Date;
constructor(private configurationService: ConfigurationService) { constructor(private configurationService: ConfigurationService, private logService: LogService,
private i18nService: I18nService) {
super(); super();
this.init(); this.init();
} }
@@ -238,6 +242,12 @@ export class AzureDirectoryService extends BaseDirectoryService implements Direc
private init() { private init() {
this.client = graph.Client.init({ this.client = graph.Client.init({
authProvider: (done) => { authProvider: (done) => {
if (this.dirConfig.applicationId == null || this.dirConfig.key == null ||
this.dirConfig.tenant == null) {
done(this.i18nService.t('dirConfigIncomplete'), null);
return;
}
if (!this.accessTokenIsExpired()) { if (!this.accessTokenIsExpired()) {
done(null, this.accessToken); done(null, this.accessToken);
return; return;

View File

@@ -20,6 +20,7 @@ import { BaseDirectoryService } from './baseDirectory.service';
import { ConfigurationService } from './configuration.service'; import { ConfigurationService } from './configuration.service';
import { DirectoryService } from './directory.service'; import { DirectoryService } from './directory.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { LogService } from 'jslib/abstractions/log.service'; import { LogService } from 'jslib/abstractions/log.service';
export class GSuiteDirectoryService extends BaseDirectoryService implements DirectoryService { export class GSuiteDirectoryService extends BaseDirectoryService implements DirectoryService {
@@ -29,7 +30,8 @@ export class GSuiteDirectoryService extends BaseDirectoryService implements Dire
private dirConfig: GSuiteConfiguration; private dirConfig: GSuiteConfiguration;
private syncConfig: SyncConfiguration; private syncConfig: SyncConfiguration;
constructor(private configurationService: ConfigurationService, private logService: LogService) { constructor(private configurationService: ConfigurationService, private logService: LogService,
private i18nService: I18nService) {
super(); super();
this.service = google.admin<Admin>('directory_v1'); this.service = google.admin<Admin>('directory_v1');
} }
@@ -183,6 +185,11 @@ export class GSuiteDirectoryService extends BaseDirectoryService implements Dire
} }
private async auth() { private async auth() {
if (this.dirConfig.clientEmail == null || this.dirConfig.privateKey == null ||
this.dirConfig.adminUser == null || this.dirConfig.domain == null) {
throw new Error(this.i18nService.t('dirConfigIncomplete'));
}
this.client = new google.auth.JWT({ this.client = new google.auth.JWT({
email: this.dirConfig.clientEmail, email: this.dirConfig.clientEmail,
key: this.dirConfig.privateKey, key: this.dirConfig.privateKey,

View File

@@ -10,7 +10,9 @@ import { UserEntry } from '../models/userEntry';
import { ConfigurationService } from './configuration.service'; import { ConfigurationService } from './configuration.service';
import { DirectoryService } from './directory.service'; import { DirectoryService } from './directory.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { LogService } from 'jslib/abstractions/log.service'; import { LogService } from 'jslib/abstractions/log.service';
import { Utils } from 'jslib/misc/utils'; import { Utils } from 'jslib/misc/utils';
const UserControlAccountDisabled = 2; const UserControlAccountDisabled = 2;
@@ -20,7 +22,8 @@ export class LdapDirectoryService implements DirectoryService {
private dirConfig: LdapConfiguration; private dirConfig: LdapConfiguration;
private syncConfig: SyncConfiguration; private syncConfig: SyncConfiguration;
constructor(private configurationService: ConfigurationService, private logService: LogService) { } constructor(private configurationService: ConfigurationService, private logService: LogService,
private i18nService: I18nService) { }
async getEntries(force: boolean, test: boolean): Promise<[GroupEntry[], UserEntry[]]> { async getEntries(force: boolean, test: boolean): Promise<[GroupEntry[], UserEntry[]]> {
const type = await this.configurationService.getDirectoryType(); const type = await this.configurationService.getDirectoryType();
@@ -312,6 +315,11 @@ export class LdapDirectoryService implements DirectoryService {
private async bind(): Promise<any> { private async bind(): Promise<any> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (this.dirConfig.hostname == null || this.dirConfig.port == null) {
reject(this.i18nService.t('dirConfigIncomplete'));
return;
}
const url = 'ldap' + (this.dirConfig.ssl ? 's' : '') + '://' + this.dirConfig.hostname + const url = 'ldap' + (this.dirConfig.ssl ? 's' : '') + '://' + this.dirConfig.hostname +
':' + this.dirConfig.port; ':' + this.dirConfig.port;
@@ -325,13 +333,13 @@ export class LdapDirectoryService implements DirectoryService {
this.dirConfig.password; this.dirConfig.password;
if (user == null || pass == null) { if (user == null || pass == null) {
reject('Username and/or password are not configured.'); reject(this.i18nService.t('usernamePasswordNotConfigured'));
return; return;
} }
this.client.bind(user, pass, (err) => { this.client.bind(user, pass, (err) => {
if (err != null) { if (err != null) {
reject('Error authenticating: ' + err.message); reject(err.message);
} else { } else {
resolve(); resolve();
} }

View File

@@ -9,6 +9,7 @@ import { BaseDirectoryService } from './baseDirectory.service';
import { ConfigurationService } from './configuration.service'; import { ConfigurationService } from './configuration.service';
import { DirectoryService } from './directory.service'; import { DirectoryService } from './directory.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { LogService } from 'jslib/abstractions/log.service'; import { LogService } from 'jslib/abstractions/log.service';
// tslint:disable-next-line // tslint:disable-next-line
@@ -19,7 +20,8 @@ export class OktaDirectoryService extends BaseDirectoryService implements Direct
private syncConfig: SyncConfiguration; private syncConfig: SyncConfiguration;
private client: any; private client: any;
constructor(private configurationService: ConfigurationService, private logService: LogService) { constructor(private configurationService: ConfigurationService, private logService: LogService,
private i18nService: I18nService) {
super(); super();
} }
@@ -39,6 +41,10 @@ export class OktaDirectoryService extends BaseDirectoryService implements Direct
return; return;
} }
if (this.dirConfig.orgUrl == null || this.dirConfig.token == null) {
throw new Error(this.i18nService.t('dirConfigIncomplete'));
}
this.client = new okta.Client({ this.client = new okta.Client({
orgUrl: this.dirConfig.orgUrl, orgUrl: this.dirConfig.orgUrl,
token: this.dirConfig.token, token: this.dirConfig.token,

View File

@@ -10,6 +10,7 @@ import { ImportDirectoryRequestUser } from 'jslib/models/request/importDirectory
import { ApiService } from 'jslib/abstractions/api.service'; import { ApiService } from 'jslib/abstractions/api.service';
import { CryptoFunctionService } from 'jslib/abstractions/cryptoFunction.service'; import { CryptoFunctionService } from 'jslib/abstractions/cryptoFunction.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { LogService } from 'jslib/abstractions/log.service'; import { LogService } from 'jslib/abstractions/log.service';
import { MessagingService } from 'jslib/abstractions/messaging.service'; import { MessagingService } from 'jslib/abstractions/messaging.service';
import { StorageService } from 'jslib/abstractions/storage.service'; import { StorageService } from 'jslib/abstractions/storage.service';
@@ -31,7 +32,7 @@ export class SyncService {
constructor(private configurationService: ConfigurationService, private logService: LogService, constructor(private configurationService: ConfigurationService, private logService: LogService,
private cryptoFunctionService: CryptoFunctionService, private apiService: ApiService, private cryptoFunctionService: CryptoFunctionService, private apiService: ApiService,
private messagingService: MessagingService) { } private messagingService: MessagingService, private i18nService: I18nService) { }
async sync(force: boolean, test: boolean): Promise<[GroupEntry[], UserEntry[]]> { async sync(force: boolean, test: boolean): Promise<[GroupEntry[], UserEntry[]]> {
this.dirType = await this.configurationService.getDirectoryType(); this.dirType = await this.configurationService.getDirectoryType();
@@ -119,13 +120,13 @@ export class SyncService {
private getDirectoryService(): DirectoryService { private getDirectoryService(): DirectoryService {
switch (this.dirType) { switch (this.dirType) {
case DirectoryType.GSuite: case DirectoryType.GSuite:
return new GSuiteDirectoryService(this.configurationService, this.logService); return new GSuiteDirectoryService(this.configurationService, this.logService, this.i18nService);
case DirectoryType.AzureActiveDirectory: case DirectoryType.AzureActiveDirectory:
return new AzureDirectoryService(this.configurationService); return new AzureDirectoryService(this.configurationService, this.logService, this.i18nService);
case DirectoryType.Ldap: case DirectoryType.Ldap:
return new LdapDirectoryService(this.configurationService, this.logService); return new LdapDirectoryService(this.configurationService, this.logService, this.i18nService);
case DirectoryType.Okta: case DirectoryType.Okta:
return new OktaDirectoryService(this.configurationService, this.logService); return new OktaDirectoryService(this.configurationService, this.logService, this.i18nService);
default: default:
return null; return null;
} }