mirror of
https://github.com/bitwarden/directory-connector
synced 2025-12-14 15:23:16 +00:00
implement azure users and groups fetching for sync
This commit is contained in:
@@ -15,6 +15,7 @@ import { DirectoryService } from './directory.service';
|
|||||||
|
|
||||||
const NextLink = '@odata.nextLink';
|
const NextLink = '@odata.nextLink';
|
||||||
const DeltaLink = '@odata.deltaLink';
|
const DeltaLink = '@odata.deltaLink';
|
||||||
|
const ObjectType = '@odata.type';
|
||||||
|
|
||||||
export class AzureDirectoryService implements DirectoryService {
|
export class AzureDirectoryService implements DirectoryService {
|
||||||
private client: graph.Client;
|
private client: graph.Client;
|
||||||
@@ -49,7 +50,21 @@ export class AzureDirectoryService implements DirectoryService {
|
|||||||
|
|
||||||
let groups: GroupEntry[];
|
let groups: GroupEntry[];
|
||||||
if (this.syncConfig.groups) {
|
if (this.syncConfig.groups) {
|
||||||
groups = await this.getGroups();
|
const setFilter = this.createSet(this.syncConfig.groupFilter);
|
||||||
|
|
||||||
|
const groupForce = force ||
|
||||||
|
(users != null && users.filter((u) => !u.deleted && !u.disabled).length > 0);
|
||||||
|
|
||||||
|
groups = await this.getGroups(groupForce, setFilter);
|
||||||
|
if (setFilter != null && users != null) {
|
||||||
|
users = users.filter((u) => {
|
||||||
|
if (u.disabled || u.deleted) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return groups.filter((g) => g.userMemberExternalIds.has(u.externalId)).length > 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return [groups, users];
|
return [groups, users];
|
||||||
@@ -76,22 +91,16 @@ export class AzureDirectoryService implements DirectoryService {
|
|||||||
|
|
||||||
const filter = this.createSet(this.syncConfig.userFilter);
|
const filter = this.createSet(this.syncConfig.userFilter);
|
||||||
while (true) {
|
while (true) {
|
||||||
const users: graphType.User[] = res.val;
|
const users: graphType.User[] = res.value;
|
||||||
if (users != null) {
|
if (users != null) {
|
||||||
users.forEach((user) => {
|
users.forEach((user) => {
|
||||||
const entry = new UserEntry();
|
const entry = this.buildUser(user);
|
||||||
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)) {
|
if (this.filterOutResult(filter, entry.email)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((user as any)['@removed'] != null && (user as any)['@removed'].reason === 'changed') {
|
if (!entry.disabled && !entry.deleted &&
|
||||||
entry.deleted = true;
|
(entry.email == null || entry.email.indexOf('#') > -1)) {
|
||||||
} else if (!entry.disabled && (entry.email == null || entry.email.indexOf('#') > -1)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,22 +122,126 @@ export class AzureDirectoryService implements DirectoryService {
|
|||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getGroups(): Promise<GroupEntry[]> {
|
private buildUser(user: graphType.User): UserEntry {
|
||||||
|
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 ((user as any)['@removed'] != null && (user as any)['@removed'].reason === 'changed') {
|
||||||
|
entry.deleted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getGroups(force: boolean, setFilter: [boolean, Set<string>]): Promise<GroupEntry[]> {
|
||||||
const entries: GroupEntry[] = [];
|
const entries: GroupEntry[] = [];
|
||||||
|
const changedGroupIds: string[] = [];
|
||||||
|
const token = await this.configurationService.getGroupDeltaToken();
|
||||||
|
const getFullResults = token == null || force;
|
||||||
|
let res: any = null;
|
||||||
|
let errored = false;
|
||||||
|
|
||||||
const request = this.client.api('/groups/delta');
|
try {
|
||||||
const groups = await request.get();
|
if (!getFullResults) {
|
||||||
console.log(groups);
|
try {
|
||||||
|
const deltaReq = this.client.api(token);
|
||||||
|
res = await deltaReq.get();
|
||||||
|
} catch {
|
||||||
|
res = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
groups.value.forEach(async (g: any) => {
|
if (res == null) {
|
||||||
const membersRequest = this.client.api('/groups/' + g.id + '/members');
|
const groupReq = this.client.api('/groups/delta');
|
||||||
const members = await membersRequest.get();
|
res = await groupReq.get();
|
||||||
console.log(members);
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const groups: graphType.Group[] = res.value;
|
||||||
|
if (groups != null) {
|
||||||
|
groups.forEach(async (group) => {
|
||||||
|
if (getFullResults) {
|
||||||
|
if (this.filterOutResult(setFilter, group.displayName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const entry = await this.buildGroup(group);
|
||||||
|
entries.push(entry);
|
||||||
|
} else {
|
||||||
|
changedGroupIds.push(group.id);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res[NextLink] == null) {
|
||||||
|
if (res[DeltaLink] != null) {
|
||||||
|
await this.configurationService.saveGroupDeltaToken(res[DeltaLink]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
const nextReq = this.client.api(res[NextLink]);
|
||||||
|
res = await nextReq.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
errored = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!errored && (getFullResults || changedGroupIds.length === 0)) {
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
const allGroupsReq = this.client.api('/groups');
|
||||||
|
res = await allGroupsReq.get();
|
||||||
|
while (true) {
|
||||||
|
const allGroups: graphType.Group[] = res.value;
|
||||||
|
if (allGroups != null) {
|
||||||
|
allGroups.forEach(async (group) => {
|
||||||
|
if (this.filterOutResult(setFilter, group.displayName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const entry = await this.buildGroup(group);
|
||||||
|
entries.push(entry);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res[NextLink] == null) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
const nextReq = this.client.api(res[NextLink]);
|
||||||
|
res = await nextReq.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async buildGroup(group: graphType.Group): Promise<GroupEntry> {
|
||||||
|
const entry = new GroupEntry();
|
||||||
|
entry.referenceId = group.id;
|
||||||
|
entry.externalId = group.id;
|
||||||
|
entry.name = group.displayName;
|
||||||
|
|
||||||
|
const memReq = this.client.api('/groups/' + group.id + '/members');
|
||||||
|
const memRes = await memReq.get();
|
||||||
|
const members: any = memRes.value;
|
||||||
|
if (members != null) {
|
||||||
|
members.forEach((member: any) => {
|
||||||
|
if (member[ObjectType] === '#microsoft.graph.group') {
|
||||||
|
entry.groupMemberReferenceIds.add((member as graphType.Group).id);
|
||||||
|
} else if (member[ObjectType] === '#microsoft.graph.user') {
|
||||||
|
entry.userMemberExternalIds.add((member as graphType.User).id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
private createSet(filter: string): [boolean, Set<string>] {
|
private createSet(filter: string): [boolean, Set<string>] {
|
||||||
if (filter == null || filter === '') {
|
if (filter == null || filter === '') {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
Reference in New Issue
Block a user