mirror of
https://github.com/bitwarden/directory-connector
synced 2025-12-23 03:33:28 +00:00
get users for azure service
This commit is contained in:
@@ -15,7 +15,7 @@ export class DashboardComponent {
|
|||||||
constructor(private i18nService: I18nService, private syncService: SyncService) { }
|
constructor(private i18nService: I18nService, private syncService: SyncService) { }
|
||||||
|
|
||||||
async sync() {
|
async sync() {
|
||||||
await this.syncService.sync(true, true);
|
await this.syncService.sync(false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
async simulate() {
|
async simulate() {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import * as graph from '@microsoft/microsoft-graph-client';
|
import * as graph from '@microsoft/microsoft-graph-client';
|
||||||
|
import * as graphType from '@microsoft/microsoft-graph-types';
|
||||||
import * as https from 'https';
|
import * as https from 'https';
|
||||||
import * as querystring from 'querystring';
|
import * as querystring from 'querystring';
|
||||||
|
|
||||||
@@ -12,12 +13,168 @@ 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';
|
||||||
|
|
||||||
|
const NextLink = '@odata.nextLink';
|
||||||
|
const DeltaLink = '@odata.deltaLink';
|
||||||
|
|
||||||
export class AzureDirectoryService implements DirectoryService {
|
export class AzureDirectoryService implements DirectoryService {
|
||||||
private client: graph.Client;
|
private client: graph.Client;
|
||||||
private dirConfig: AzureConfiguration;
|
private dirConfig: AzureConfiguration;
|
||||||
private syncConfig: SyncConfiguration;
|
private syncConfig: SyncConfiguration;
|
||||||
|
|
||||||
constructor(private configurationService: ConfigurationService) {
|
constructor(private configurationService: ConfigurationService) {
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getEntries(force = false): Promise<[GroupEntry[], UserEntry[]]> {
|
||||||
|
const type = await this.configurationService.getDirectoryType();
|
||||||
|
if (type !== DirectoryType.AzureActiveDirectory) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dirConfig = await this.configurationService.getDirectory<AzureConfiguration>(
|
||||||
|
DirectoryType.AzureActiveDirectory);
|
||||||
|
if (this.dirConfig == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.syncConfig = await this.configurationService.getSync();
|
||||||
|
if (this.syncConfig == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let users: UserEntry[];
|
||||||
|
if (this.syncConfig.users) {
|
||||||
|
users = await this.getUsers(force);
|
||||||
|
}
|
||||||
|
|
||||||
|
let groups: GroupEntry[];
|
||||||
|
if (this.syncConfig.groups) {
|
||||||
|
groups = await this.getGroups();
|
||||||
|
}
|
||||||
|
|
||||||
|
return [groups, users];
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getUsers(force: boolean): Promise<UserEntry[]> {
|
||||||
|
const entries: UserEntry[] = [];
|
||||||
|
|
||||||
|
let res: any = null;
|
||||||
|
const token = await this.configurationService.getUserDeltaToken();
|
||||||
|
if (!force && token != null) {
|
||||||
|
try {
|
||||||
|
const deltaReq = this.client.api(token);
|
||||||
|
res = await deltaReq.get();
|
||||||
|
} catch {
|
||||||
|
res = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res == null) {
|
||||||
|
const userReq = this.client.api('/users/delta');
|
||||||
|
res = await userReq.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
const filter = this.createSet(this.syncConfig.userFilter);
|
||||||
|
while (true) {
|
||||||
|
const users: graphType.User[] = res.val;
|
||||||
|
if (users != null) {
|
||||||
|
users.forEach((user) => {
|
||||||
|
const entry = new UserEntry();
|
||||||
|
entry.referenceId = user.id;
|
||||||
|
entry.externalId = user.id;
|
||||||
|
entry.email = user.mail || user.userPrincipalName;
|
||||||
|
entry.disabled = user.accountEnabled == null ? false : !user.accountEnabled;
|
||||||
|
|
||||||
|
if (this.filterOutResult(filter, entry.email)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((user as any)['@removed'] != null && (user as any)['@removed'].reason === 'changed') {
|
||||||
|
entry.deleted = true;
|
||||||
|
} else if (!entry.disabled && (entry.email == null || entry.email.indexOf('#') > -1)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
entries.push(entry);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res[NextLink] == null) {
|
||||||
|
if (res[DeltaLink] != null) {
|
||||||
|
await this.configurationService.saveUserDeltaToken(res[DeltaLink]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
const nextReq = this.client.api(res[NextLink]);
|
||||||
|
res = await nextReq.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getGroups(): Promise<GroupEntry[]> {
|
||||||
|
const entries: GroupEntry[] = [];
|
||||||
|
|
||||||
|
const request = this.client.api('/groups/delta');
|
||||||
|
const groups = await request.get();
|
||||||
|
console.log(groups);
|
||||||
|
|
||||||
|
groups.value.forEach(async (g: any) => {
|
||||||
|
const membersRequest = this.client.api('/groups/' + g.id + '/members');
|
||||||
|
const members = await membersRequest.get();
|
||||||
|
console.log(members);
|
||||||
|
});
|
||||||
|
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
private createSet(filter: string): [boolean, Set<string>] {
|
||||||
|
if (filter == null || filter === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const parts = filter.split(':');
|
||||||
|
if (parts.length !== 2) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const keyword = parts[0].trim().toLowerCase();
|
||||||
|
let exclude = true;
|
||||||
|
if (keyword === 'include') {
|
||||||
|
exclude = false;
|
||||||
|
} else if (keyword === 'exclude') {
|
||||||
|
exclude = true;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const set = new Set<string>();
|
||||||
|
const pieces = parts[1].split(',');
|
||||||
|
pieces.forEach((p) => {
|
||||||
|
set.add(p.trim().toLowerCase());
|
||||||
|
});
|
||||||
|
|
||||||
|
return [exclude, set];
|
||||||
|
}
|
||||||
|
|
||||||
|
private filterOutResult(filter: [boolean, Set<string>], result: string) {
|
||||||
|
if (filter != null) {
|
||||||
|
result = result.trim().toLowerCase();
|
||||||
|
const excluded = filter[0];
|
||||||
|
const set = filter[1];
|
||||||
|
|
||||||
|
if (excluded && set.has(result)) {
|
||||||
|
return true;
|
||||||
|
} else if (!excluded && !set.has(result)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private init() {
|
||||||
this.client = graph.Client.init({
|
this.client = graph.Client.init({
|
||||||
authProvider: (done) => {
|
authProvider: (done) => {
|
||||||
const data = querystring.stringify({
|
const data = querystring.stringify({
|
||||||
@@ -56,45 +213,4 @@ export class AzureDirectoryService implements DirectoryService {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getEntries(force = false): Promise<[GroupEntry[], UserEntry[]]> {
|
|
||||||
const type = await this.configurationService.getDirectoryType();
|
|
||||||
if (type !== DirectoryType.AzureActiveDirectory) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.dirConfig = await this.configurationService.getDirectory<AzureConfiguration>(
|
|
||||||
DirectoryType.AzureActiveDirectory);
|
|
||||||
if (this.dirConfig == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.syncConfig = await this.configurationService.getSync();
|
|
||||||
if (this.syncConfig == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.getUsers();
|
|
||||||
await this.getGroups();
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async getUsers() {
|
|
||||||
const request = this.client.api('/users/delta');
|
|
||||||
const users = await request.get();
|
|
||||||
console.log(users);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async getGroups() {
|
|
||||||
const request = this.client.api('/groups/delta');
|
|
||||||
const groups = await request.get();
|
|
||||||
console.log(groups);
|
|
||||||
|
|
||||||
groups.value.forEach(async (g: any) => {
|
|
||||||
const membersRequest = this.client.api('/groups/' + g.id + '/members');
|
|
||||||
const members = await membersRequest.get();
|
|
||||||
console.log(members);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ const Keys = {
|
|||||||
directoryConfigPrefix: 'directoryConfig_',
|
directoryConfigPrefix: 'directoryConfig_',
|
||||||
sync: 'syncConfig',
|
sync: 'syncConfig',
|
||||||
directoryType: 'directoryType',
|
directoryType: 'directoryType',
|
||||||
|
userDelta: 'userDeltaToken',
|
||||||
|
groupDelta: 'groupDeltaToken',
|
||||||
};
|
};
|
||||||
|
|
||||||
export class ConfigurationService {
|
export class ConfigurationService {
|
||||||
@@ -73,19 +75,48 @@ export class ConfigurationService {
|
|||||||
await this.storageService.save(Keys.directoryConfigPrefix + type, savedConfig);
|
await this.storageService.save(Keys.directoryConfigPrefix + type, savedConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getSync(): Promise<SyncConfiguration> {
|
getSync(): Promise<SyncConfiguration> {
|
||||||
return this.storageService.get<SyncConfiguration>(Keys.sync);
|
return this.storageService.get<SyncConfiguration>(Keys.sync);
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveSync(config: SyncConfiguration) {
|
saveSync(config: SyncConfiguration) {
|
||||||
return this.storageService.save(Keys.sync, config);
|
return this.storageService.save(Keys.sync, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDirectoryType(): Promise<DirectoryType> {
|
getDirectoryType(): Promise<DirectoryType> {
|
||||||
return this.storageService.get<DirectoryType>(Keys.directoryType);
|
return this.storageService.get<DirectoryType>(Keys.directoryType);
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveDirectoryType(type: DirectoryType) {
|
async saveDirectoryType(type: DirectoryType) {
|
||||||
|
const currentType = await this.getDirectoryType();
|
||||||
|
if (type !== currentType) {
|
||||||
|
await this.saveUserDeltaToken(null);
|
||||||
|
await this.saveGroupDeltaToken(null);
|
||||||
|
}
|
||||||
return this.storageService.save(Keys.directoryType, type);
|
return this.storageService.save(Keys.directoryType, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getUserDeltaToken(): Promise<string> {
|
||||||
|
return this.storageService.get<string>(Keys.userDelta);
|
||||||
|
}
|
||||||
|
|
||||||
|
saveUserDeltaToken(token: string) {
|
||||||
|
if (token == null) {
|
||||||
|
return this.storageService.remove(Keys.userDelta);
|
||||||
|
} else {
|
||||||
|
return this.storageService.save(Keys.userDelta, token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getGroupDeltaToken(): Promise<string> {
|
||||||
|
return this.storageService.get<string>(Keys.groupDelta);
|
||||||
|
}
|
||||||
|
|
||||||
|
saveGroupDeltaToken(token: string) {
|
||||||
|
if (token == null) {
|
||||||
|
return this.storageService.remove(Keys.groupDelta);
|
||||||
|
} else {
|
||||||
|
return this.storageService.save(Keys.groupDelta, token);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user