mirror of
https://github.com/bitwarden/directory-connector
synced 2025-12-05 23:53:21 +00:00
test command for cli
This commit is contained in:
@@ -12,18 +12,16 @@ import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||
import { MessagingService } from 'jslib/abstractions/messaging.service';
|
||||
import { StateService } from 'jslib/abstractions/state.service';
|
||||
|
||||
import { AzureDirectoryService } from '../../services/azure-directory.service';
|
||||
import { GSuiteDirectoryService } from '../../services/gsuite-directory.service';
|
||||
import { LdapDirectoryService } from '../../services/ldap-directory.service';
|
||||
import { SyncService } from '../../services/sync.service';
|
||||
|
||||
import { Entry } from '../../models/entry';
|
||||
import { GroupEntry } from '../../models/groupEntry';
|
||||
import { UserEntry } from '../../models/userEntry';
|
||||
import { ConfigurationService } from '../../services/configuration.service';
|
||||
|
||||
import { BroadcasterService } from 'jslib/angular/services/broadcaster.service';
|
||||
|
||||
import { ConnectorUtils } from '../../utils';
|
||||
|
||||
const BroadcasterSubscriptionId = 'DashboardComponent';
|
||||
|
||||
@Component({
|
||||
@@ -105,63 +103,22 @@ export class DashboardComponent implements OnInit, OnDestroy {
|
||||
|
||||
this.simPromise = new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
const result = await this.syncService.sync(!this.simSinceLast, true);
|
||||
if (result[0] != null) {
|
||||
this.simGroups = result[0];
|
||||
}
|
||||
if (result[1] != null) {
|
||||
this.simUsers = result[1];
|
||||
}
|
||||
const result = await ConnectorUtils.simulate(this.syncService, this.i18nService, this.simSinceLast);
|
||||
this.simGroups = result.groups;
|
||||
this.simUsers = result.users;
|
||||
this.simEnabledUsers = result.enabledUsers;
|
||||
this.simDisabledUsers = result.disabledUsers;
|
||||
this.simDeletedUsers = result.deletedUsers;
|
||||
} catch (e) {
|
||||
this.simGroups = null;
|
||||
this.simUsers = null;
|
||||
reject(e || this.i18nService.t('syncError'));
|
||||
reject(e);
|
||||
return;
|
||||
}
|
||||
|
||||
const userMap = new Map<string, UserEntry>();
|
||||
this.sort(this.simUsers);
|
||||
for (const u of this.simUsers) {
|
||||
userMap.set(u.externalId, u);
|
||||
if (u.deleted) {
|
||||
this.simDeletedUsers.push(u);
|
||||
} else if (u.disabled) {
|
||||
this.simDisabledUsers.push(u);
|
||||
} else {
|
||||
this.simEnabledUsers.push(u);
|
||||
}
|
||||
}
|
||||
|
||||
this.sort(this.simGroups);
|
||||
for (const g of this.simGroups) {
|
||||
if (g.userMemberExternalIds == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const anyG = (g as any);
|
||||
anyG.users = [];
|
||||
for (const uid of g.userMemberExternalIds) {
|
||||
if (userMap.has(uid)) {
|
||||
anyG.users.push(userMap.get(uid));
|
||||
} else {
|
||||
anyG.users.push({ displayName: uid });
|
||||
}
|
||||
}
|
||||
|
||||
this.sort(anyG.users);
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
private sort(arr: Entry[]) {
|
||||
arr.sort((a, b) => {
|
||||
return this.i18nService.collator ? this.i18nService.collator.compare(a.displayName, b.displayName) :
|
||||
a.displayName.localeCompare(b.displayName);
|
||||
});
|
||||
}
|
||||
|
||||
private async updateLastSync() {
|
||||
this.lastGroupSync = await this.configurationService.getLastGroupSyncDate();
|
||||
this.lastUserSync = await this.configurationService.getLastUserSyncDate();
|
||||
|
||||
24
src/commands/test.command.ts
Normal file
24
src/commands/test.command.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import * as program from 'commander';
|
||||
|
||||
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||
|
||||
import { SyncService } from '../services/sync.service';
|
||||
|
||||
import { ConnectorUtils } from '../utils';
|
||||
|
||||
import { Response } from 'jslib/cli/models/response';
|
||||
import { TestResponse } from '../models/response/testResponse';
|
||||
|
||||
export class TestCommand {
|
||||
constructor(private syncService: SyncService, private i18nService: I18nService) { }
|
||||
|
||||
async run(cmd: program.Command): Promise<Response> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
13
src/models/response/groupResponse.ts
Normal file
13
src/models/response/groupResponse.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { GroupEntry } from '../groupEntry';
|
||||
|
||||
export class GroupResponse {
|
||||
externalId: string;
|
||||
displayName: string;
|
||||
userIds: string[];
|
||||
|
||||
constructor(g: GroupEntry) {
|
||||
this.externalId = g.externalId;
|
||||
this.displayName = g.displayName;
|
||||
this.userIds = Array.from(g.userMemberExternalIds);
|
||||
}
|
||||
}
|
||||
22
src/models/response/testResponse.ts
Normal file
22
src/models/response/testResponse.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { GroupResponse } from './groupResponse';
|
||||
import { UserResponse } from './userResponse';
|
||||
|
||||
import { SimResult } from '../simResult';
|
||||
|
||||
import { BaseResponse } from 'jslib/cli/models/response/baseResponse';
|
||||
|
||||
export class TestResponse implements BaseResponse {
|
||||
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)) : [];
|
||||
}
|
||||
}
|
||||
11
src/models/response/userResponse.ts
Normal file
11
src/models/response/userResponse.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { UserEntry } from '../userEntry';
|
||||
|
||||
export class UserResponse {
|
||||
externalId: string;
|
||||
displayName: string;
|
||||
|
||||
constructor(u: UserEntry) {
|
||||
this.externalId = u.externalId;
|
||||
this.displayName = u.displayName;
|
||||
}
|
||||
}
|
||||
10
src/models/simResult.ts
Normal file
10
src/models/simResult.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { GroupEntry } from './groupEntry';
|
||||
import { UserEntry } from './userEntry';
|
||||
|
||||
export class SimResult {
|
||||
groups: GroupEntry[] = [];
|
||||
users: UserEntry[] = [];
|
||||
enabledUsers: UserEntry[] = [];
|
||||
disabledUsers: UserEntry[] = [];
|
||||
deletedUsers: UserEntry[] = [];
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import * as program from 'commander';
|
||||
import { Main } from './bwdc';
|
||||
|
||||
import { ConfigCommand } from './commands/config.command';
|
||||
import { TestCommand } from './commands/test.command';
|
||||
|
||||
import { UpdateCommand } from 'jslib/cli/commands/update.command';
|
||||
|
||||
@@ -57,10 +58,30 @@ export class Program {
|
||||
program.on('--help', () => {
|
||||
writeLn('\n Examples:');
|
||||
writeLn('');
|
||||
writeLn(' bwdc login');
|
||||
writeLn(' bwdc test');
|
||||
writeLn(' bwdc config server bitwarden.com');
|
||||
writeLn(' bwdc update');
|
||||
writeLn('', true);
|
||||
});
|
||||
|
||||
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 (cmd) => {
|
||||
await this.exitIfNotAuthed();
|
||||
const command = new TestCommand(this.main.syncService, this.main.i18nService);
|
||||
const response = await command.run(cmd);
|
||||
this.processResponse(response);
|
||||
});
|
||||
|
||||
program
|
||||
.command('config <setting> <value>')
|
||||
.description('Configure CLI settings.')
|
||||
@@ -187,14 +208,6 @@ export class Program {
|
||||
return out.trim() === '' ? null : out;
|
||||
}
|
||||
|
||||
private async exitIfLocked() {
|
||||
await this.exitIfNotAuthed();
|
||||
const hasKey = await this.main.cryptoService.hasKey();
|
||||
if (!hasKey) {
|
||||
this.processResponse(Response.error('Vault is locked.'), true);
|
||||
}
|
||||
}
|
||||
|
||||
private async exitIfAuthed() {
|
||||
const authed = await this.main.userService.isAuthenticated();
|
||||
if (authed) {
|
||||
|
||||
70
src/utils.ts
Normal file
70
src/utils.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||
|
||||
import { SyncService } from './services/sync.service';
|
||||
|
||||
import { Entry } from './models/entry';
|
||||
import { SimResult } from './models/simResult';
|
||||
import { UserEntry } from './models/userEntry';
|
||||
|
||||
export class ConnectorUtils {
|
||||
static async simulate(syncService: SyncService, i18nService: I18nService, sinceLast: boolean): Promise<SimResult> {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
const simResult = new SimResult();
|
||||
try {
|
||||
const result = await syncService.sync(!sinceLast, true);
|
||||
if (result[0] != null) {
|
||||
simResult.groups = result[0];
|
||||
}
|
||||
if (result[1] != null) {
|
||||
simResult.users = result[1];
|
||||
}
|
||||
} catch (e) {
|
||||
simResult.groups = null;
|
||||
simResult.users = null;
|
||||
reject(e || i18nService.t('syncError'));
|
||||
return;
|
||||
}
|
||||
|
||||
const userMap = new Map<string, UserEntry>();
|
||||
this.sortEntries(simResult.users, i18nService);
|
||||
for (const u of simResult.users) {
|
||||
userMap.set(u.externalId, u);
|
||||
if (u.deleted) {
|
||||
simResult.deletedUsers.push(u);
|
||||
} else if (u.disabled) {
|
||||
simResult.disabledUsers.push(u);
|
||||
} else {
|
||||
simResult.enabledUsers.push(u);
|
||||
}
|
||||
}
|
||||
|
||||
this.sortEntries(simResult.groups, i18nService);
|
||||
for (const g of simResult.groups) {
|
||||
if (g.userMemberExternalIds == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const anyG = (g as any);
|
||||
anyG.users = [];
|
||||
for (const uid of g.userMemberExternalIds) {
|
||||
if (userMap.has(uid)) {
|
||||
anyG.users.push(userMap.get(uid));
|
||||
} else {
|
||||
anyG.users.push({ displayName: uid });
|
||||
}
|
||||
}
|
||||
|
||||
this.sortEntries(anyG.users, i18nService);
|
||||
}
|
||||
|
||||
resolve(simResult);
|
||||
});
|
||||
}
|
||||
|
||||
private static sortEntries(arr: Entry[], i18nService: I18nService) {
|
||||
arr.sort((a, b) => {
|
||||
return i18nService.collator ? i18nService.collator.compare(a.displayName, b.displayName) :
|
||||
a.displayName.localeCompare(b.displayName);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user