From 033c346042156afd82efc3b329d7221bb209568d Mon Sep 17 00:00:00 2001 From: Thomas Rittson <31796059+eliykat@users.noreply.github.com> Date: Tue, 14 Sep 2021 07:00:37 +1000 Subject: [PATCH] Ignore duplicate users with same externalId (#152) * Ignore duplicate users with same externalId * Add null check * Exclude deleted users from disabled users (Azure) * Fix order of null check * Stringify and compare duplicate before discarding --- src/services/azure-directory.service.ts | 2 +- src/services/sync.service.ts | 41 +++++++++++++++---------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/services/azure-directory.service.ts b/src/services/azure-directory.service.ts index a7164638..369120a7 100644 --- a/src/services/azure-directory.service.ts +++ b/src/services/azure-directory.service.ts @@ -144,7 +144,7 @@ export class AzureDirectoryService extends BaseDirectoryService implements IDire continue; } const entry = this.buildUser(user); - if (!entry.disabled && !entry.deleted) { + if (!entry.deleted) { continue; } if (await this.filterOutUserResult(setFilter, entry, false)) { diff --git a/src/services/sync.service.ts b/src/services/sync.service.ts index 7675ceb9..196b3e04 100644 --- a/src/services/sync.service.ts +++ b/src/services/sync.service.ts @@ -57,13 +57,7 @@ export class SyncService { this.flattenUsersToGroups(groups, groups); } - const duplicateEmails = this.findDuplicateUserEmails(users); - if (duplicateEmails.length > 0) { - const emailsMessage = duplicateEmails.length < 4 ? - duplicateEmails.join('\n') : - duplicateEmails.slice(0, 3).join('\n') + '\n' + this.i18nService.t('andMore', `${duplicateEmails.length - 3}`); - throw new Error(this.i18nService.t('duplicateEmails') + '\n' + emailsMessage); - } + users = this.removeDuplicateUsers(users); if (test || (!syncConfig.overwriteExisting && (groups == null || groups.length === 0) && (users == null || users.length === 0))) { @@ -118,17 +112,32 @@ export class SyncService { } } - private findDuplicateUserEmails(users: UserEntry[]) { - const duplicatedEmails = new Array(); - users.reduce((agg, user) => { - if (agg.includes(user.email) && !duplicatedEmails.includes(user.email)) { - duplicatedEmails.push(user.email); + private removeDuplicateUsers(users: UserEntry[]) { + const uniqueUsers = new Array(); + const processedUsers = new Map(); + const duplicateEmails = new Array(); + + // UserEntrys with the same email are ignored if their properties are the same + // UserEntrys with the same email but different properties will throw an error + users.forEach(u => { + if (processedUsers.has(u.email)) { + if (processedUsers.get(u.email) != JSON.stringify(u)) { + duplicateEmails.push(u.email); + } } else { - agg.push(user.email); + uniqueUsers.push(u); + processedUsers.set(u.email, JSON.stringify(u)); } - return agg; - }, new Array()); - return duplicatedEmails; + }); + + if (duplicateEmails.length > 0) { + const emailsMessage = duplicateEmails.length < 4 ? + duplicateEmails.join('\n') : + duplicateEmails.slice(0, 3).join('\n') + '\n' + this.i18nService.t('andMore', `${duplicateEmails.length - 3}`); + throw new Error(this.i18nService.t('duplicateEmails') + '\n' + emailsMessage); + } + + return uniqueUsers; } private filterUnsupportedUsers(users: UserEntry[]): UserEntry[] {