From 49776f84799241af6b0ba31f84217d4e59044a36 Mon Sep 17 00:00:00 2001 From: Phil Gore Date: Fri, 10 Sep 2021 16:18:54 -0500 Subject: [PATCH 1/6] commit client changes for searchStreaming generator Signed-off-by: Phil Gore --- .../src/ldap/client.ts | 56 +++++++++++++++++++ .../src/ldap/read.ts | 25 ++++++--- 2 files changed, 72 insertions(+), 9 deletions(-) diff --git a/plugins/catalog-backend-module-ldap/src/ldap/client.ts b/plugins/catalog-backend-module-ldap/src/ldap/client.ts index a99fc3846e..6dae1839ce 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/client.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/client.ts @@ -109,6 +109,62 @@ export class LdapClient { } } + /** + * Performs an LDAP search operation, calls a function on each entry to limit memory usage + * + * @param dn The fully qualified base DN to search within + * @param options The search options + */ + *searchStreaming(dn: string, options: SearchOptions) { + let queuesize = 25; + if (options) { + if ( + options.paged && + typeof options.paged === 'object' && + typeof options.paged.pageSize === 'number' && + options.paged.pageSize > 0 + ) { + queuesize = options.paged.pageSize; + } + } + const queue: SearchEntry[] = new Array(queuesize); + let done = false; + try { + this.client.search(dn, options, (err, res) => { + if (err) { + throw new Error(errorString(err)); + } + + res.on('searchReference', () => { + throw new Error('Unable to handle referral'); + }); + + res.on('searchEntry', entry => { + queue.push(entry); + }); + + res.on('error', e => { + throw new Error(errorString(e)); + }); + + res.on('end', r => { + if (!r) { + throw new Error('Null response'); + } else if (r.status !== 0) { + throw new Error(`Got status ${r.status}: ${r.errorMessage}`); + } else { + done = true; + } + }); + }); + } catch (e) { + throw new Error(`LDAP search at DN "${dn}" failed, ${e.message}`); + } + while (!done && queue.length > 0) { + yield queue.pop(); + } + } + /** * Get the Server Vendor. * Currently only detects Microsoft Active Directory Servers. diff --git a/plugins/catalog-backend-module-ldap/src/ldap/read.ts b/plugins/catalog-backend-module-ldap/src/ldap/read.ts index f3ee09d32d..96a9966628 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/read.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/read.ts @@ -107,16 +107,19 @@ export async function readLdapUsers( const transformer = opts?.transformer ?? defaultUserTransformer; - const entries = await client.search(dn, options); + const entries = client.searchStreaming(dn, options); + for (const entry of entries) { + if (!entry) { + continue; + } - for (const user of entries) { - const entity = await transformer(vendor, config, user); + const entity = await transformer(vendor, config, entry); if (!entity) { continue; } - mapReferencesAttr(user, vendor, map.memberOf, (myDn, vs) => { + mapReferencesAttr(entry, vendor, map.memberOf, (myDn, vs) => { ensureItems(userMemberOf, myDn, vs); }); @@ -210,19 +213,23 @@ export async function readLdapGroups( const transformer = opts?.transformer ?? defaultGroupTransformer; - const entries = await client.search(dn, options); + const entries = client.searchStreaming(dn, options); - for (const group of entries) { - const entity = await transformer(vendor, config, group); + for (const entry of entries) { + if (!entry) { + continue; + } + + const entity = await transformer(vendor, config, entry); if (!entity) { continue; } - mapReferencesAttr(group, vendor, map.memberOf, (myDn, vs) => { + mapReferencesAttr(entry, vendor, map.memberOf, (myDn, vs) => { ensureItems(groupMemberOf, myDn, vs); }); - mapReferencesAttr(group, vendor, map.members, (myDn, vs) => { + mapReferencesAttr(entry, vendor, map.members, (myDn, vs) => { ensureItems(groupMember, myDn, vs); }); From ebd2ddf4a27a990f25e1977c72cd4fbdbf403a00 Mon Sep 17 00:00:00 2001 From: Phil Gore Date: Sat, 11 Sep 2021 12:59:34 -0500 Subject: [PATCH 2/6] figuring out why the tests list this as not a function Signed-off-by: Phil Gore --- .../src/ldap/client.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/plugins/catalog-backend-module-ldap/src/ldap/client.ts b/plugins/catalog-backend-module-ldap/src/ldap/client.ts index 6dae1839ce..d859c5e08b 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/client.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/client.ts @@ -110,13 +110,16 @@ export class LdapClient { } /** - * Performs an LDAP search operation, calls a function on each entry to limit memory usage + * Performs an LDAP search operation, creates a generator to limit memory usage * * @param dn The fully qualified base DN to search within * @param options The search options */ - *searchStreaming(dn: string, options: SearchOptions) { - let queuesize = 25; + *searchStreaming( + dn: string, + options: SearchOptions, + ): IterableIterator { + let queueSize = 25; if (options) { if ( options.paged && @@ -124,10 +127,10 @@ export class LdapClient { typeof options.paged.pageSize === 'number' && options.paged.pageSize > 0 ) { - queuesize = options.paged.pageSize; + queueSize = options.paged.pageSize; } } - const queue: SearchEntry[] = new Array(queuesize); + const queue: SearchEntry[] = new Array(queueSize); let done = false; try { this.client.search(dn, options, (err, res) => { @@ -161,7 +164,11 @@ export class LdapClient { throw new Error(`LDAP search at DN "${dn}" failed, ${e.message}`); } while (!done && queue.length > 0) { - yield queue.pop(); + const res = queue.pop(); + if (!res) { + continue; + } + yield res; } } From 211698b3f10a21c70e64662b56d22ae1460b9374 Mon Sep 17 00:00:00 2001 From: Phil Gore Date: Tue, 14 Sep 2021 11:02:13 -0500 Subject: [PATCH 3/6] mock implementation for new func and passing tests Signed-off-by: Phil Gore --- .../src/ldap/client.ts | 82 +++---- .../src/ldap/read.test.ts | 209 ++++++++++-------- .../src/ldap/read.ts | 25 +-- 3 files changed, 163 insertions(+), 153 deletions(-) diff --git a/plugins/catalog-backend-module-ldap/src/ldap/client.ts b/plugins/catalog-backend-module-ldap/src/ldap/client.ts index d859c5e08b..eddd4291d1 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/client.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/client.ts @@ -24,6 +24,10 @@ import { LdapVendor, } from './vendors'; +export interface SearchCallback { + (entry: SearchEntry): void; +} + /** * Basic wrapper for the ldapjs library. * @@ -110,66 +114,50 @@ export class LdapClient { } /** - * Performs an LDAP search operation, creates a generator to limit memory usage + * Performs an LDAP search operation, calls a function on each entry to limit memory usage * * @param dn The fully qualified base DN to search within * @param options The search options + * @param f The callback to call on each search entry */ - *searchStreaming( + async searchStreaming( dn: string, options: SearchOptions, - ): IterableIterator { - let queueSize = 25; - if (options) { - if ( - options.paged && - typeof options.paged === 'object' && - typeof options.paged.pageSize === 'number' && - options.paged.pageSize > 0 - ) { - queueSize = options.paged.pageSize; - } - } - const queue: SearchEntry[] = new Array(queueSize); - let done = false; + f: SearchCallback, + ): Promise { try { - this.client.search(dn, options, (err, res) => { - if (err) { - throw new Error(errorString(err)); - } - - res.on('searchReference', () => { - throw new Error('Unable to handle referral'); - }); - - res.on('searchEntry', entry => { - queue.push(entry); - }); - - res.on('error', e => { - throw new Error(errorString(e)); - }); - - res.on('end', r => { - if (!r) { - throw new Error('Null response'); - } else if (r.status !== 0) { - throw new Error(`Got status ${r.status}: ${r.errorMessage}`); - } else { - done = true; + return await new Promise((resolve, reject) => { + this.client.search(dn, options, (err, res) => { + if (err) { + reject(new Error(errorString(err))); } + + res.on('searchReference', () => { + reject(new Error('Unable to handle referral')); + }); + + res.on('searchEntry', async entry => { + await f(entry); + }); + + res.on('error', e => { + reject(new Error(errorString(e))); + }); + + res.on('end', r => { + if (!r) { + throw new Error('Null response'); + } else if (r.status !== 0) { + throw new Error(`Got status ${r.status}: ${r.errorMessage}`); + } else { + resolve(); + } + }); }); }); } catch (e) { throw new Error(`LDAP search at DN "${dn}" failed, ${e.message}`); } - while (!done && queue.length > 0) { - const res = queue.pop(); - if (!res) { - continue; - } - yield res; - } } /** diff --git a/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts b/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts index b357b6b408..3615d8b2ad 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts @@ -67,7 +67,7 @@ function searchEntry( describe('readLdapUsers', () => { const client: jest.Mocked = { - search: jest.fn(), + searchStreaming: jest.fn(), getVendor: jest.fn(), } as any; @@ -75,18 +75,25 @@ describe('readLdapUsers', () => { it('transfers all attributes from a default ldap vendor', async () => { client.getVendor.mockResolvedValue(DefaultLdapVendor); - client.search.mockResolvedValue([ - searchEntry({ - uid: ['uid-value'], - description: ['description-value'], - cn: ['cn-value'], - mail: ['mail-value'], - avatarUrl: ['avatarUrl-value'], - memberOf: ['x', 'y', 'z'], - entryDN: ['dn-value'], - entryUUID: ['uuid-value'], - }), - ]); + client.searchStreaming.mockImplementation( + async (_dn, _opts, fn): Promise => { + return await new Promise((resolve, _reject) => { + fn( + searchEntry({ + uid: ['uid-value'], + description: ['description-value'], + cn: ['cn-value'], + mail: ['mail-value'], + avatarUrl: ['avatarUrl-value'], + memberOf: ['x', 'y', 'z'], + entryDN: ['dn-value'], + entryUUID: ['uuid-value'], + }), + ); + resolve(); + }); + }, + ); const config: UserConfig = { dn: 'ddd', options: {}, @@ -129,37 +136,45 @@ describe('readLdapUsers', () => { it('transfers all attributes from Microsoft Active Directory', async () => { client.getVendor.mockResolvedValue(ActiveDirectoryVendor); - client.search.mockResolvedValue([ - searchEntry({ - uid: ['uid-value'], - description: ['description-value'], - cn: ['cn-value'], - mail: ['mail-value'], - avatarUrl: ['avatarUrl-value'], - memberOf: ['x', 'y', 'z'], - distinguishedName: ['dn-value'], - objectGUID: [ - Buffer.from([ - 68, - 2, - 125, - 190, - 209, - 0, - 94, - 73, - 133, - 33, - 230, - 174, - 234, - 195, - 160, - 152, - ]), - ], - }), - ]); + client.searchStreaming.mockImplementation( + async (_dn, _opts, fn): Promise => { + return await new Promise((resolve, _reject) => { + fn( + searchEntry({ + uid: ['uid-value'], + description: ['description-value'], + cn: ['cn-value'], + mail: ['mail-value'], + avatarUrl: ['avatarUrl-value'], + memberOf: ['x', 'y', 'z'], + distinguishedName: ['dn-value'], + objectGUID: [ + Buffer.from([ + 68, + 2, + 125, + 190, + 209, + 0, + 94, + 73, + 133, + 33, + 230, + 174, + 234, + 195, + 160, + 152, + ]), + ], + }), + ); + resolve(); + }); + }, + ); + const config: UserConfig = { dn: 'ddd', options: {}, @@ -203,7 +218,7 @@ describe('readLdapUsers', () => { describe('readLdapGroups', () => { const client: jest.Mocked = { - search: jest.fn(), + searchStreaming: jest.fn(), getVendor: jest.fn(), } as any; @@ -211,19 +226,26 @@ describe('readLdapGroups', () => { it('transfers all attributes from a default ldap vendor', async () => { client.getVendor.mockResolvedValue(DefaultLdapVendor); - client.search.mockResolvedValue([ - searchEntry({ - cn: ['cn-value'], - description: ['description-value'], - tt: ['type-value'], - mail: ['mail-value'], - avatarUrl: ['avatarUrl-value'], - memberOf: ['x', 'y', 'z'], - member: ['e', 'f', 'g'], - entryDN: ['dn-value'], - entryUUID: ['uuid-value'], - }), - ]); + client.searchStreaming.mockImplementation( + async (_dn, _opts, fn): Promise => { + return await new Promise((resolve, _reject) => { + fn( + searchEntry({ + cn: ['cn-value'], + description: ['description-value'], + tt: ['type-value'], + mail: ['mail-value'], + avatarUrl: ['avatarUrl-value'], + memberOf: ['x', 'y', 'z'], + member: ['e', 'f', 'g'], + entryDN: ['dn-value'], + entryUUID: ['uuid-value'], + }), + ); + resolve(); + }); + }, + ); const config: GroupConfig = { dn: 'ddd', options: {}, @@ -274,38 +296,45 @@ describe('readLdapGroups', () => { }); it('transfers all attributes from Microsoft Active Directory', async () => { client.getVendor.mockResolvedValue(ActiveDirectoryVendor); - client.search.mockResolvedValue([ - searchEntry({ - cn: ['cn-value'], - description: ['description-value'], - tt: ['type-value'], - mail: ['mail-value'], - avatarUrl: ['avatarUrl-value'], - memberOf: ['x', 'y', 'z'], - member: ['e', 'f', 'g'], - distinguishedName: ['dn-value'], - objectGUID: [ - Buffer.from([ - 68, - 2, - 125, - 190, - 209, - 0, - 94, - 73, - 133, - 33, - 230, - 174, - 234, - 195, - 160, - 152, - ]), - ], - }), - ]); + client.searchStreaming.mockImplementation( + async (_dn, _opts, fn): Promise => { + return await new Promise((resolve, _reject) => { + fn( + searchEntry({ + cn: ['cn-value'], + description: ['description-value'], + tt: ['type-value'], + mail: ['mail-value'], + avatarUrl: ['avatarUrl-value'], + memberOf: ['x', 'y', 'z'], + member: ['e', 'f', 'g'], + distinguishedName: ['dn-value'], + objectGUID: [ + Buffer.from([ + 68, + 2, + 125, + 190, + 209, + 0, + 94, + 73, + 133, + 33, + 230, + 174, + 234, + 195, + 160, + 152, + ]), + ], + }), + ); + resolve(); + }); + }, + ); const config: GroupConfig = { dn: 'ddd', options: {}, diff --git a/plugins/catalog-backend-module-ldap/src/ldap/read.ts b/plugins/catalog-backend-module-ldap/src/ldap/read.ts index 96a9966628..37e69c5bcf 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/read.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/read.ts @@ -107,24 +107,19 @@ export async function readLdapUsers( const transformer = opts?.transformer ?? defaultUserTransformer; - const entries = client.searchStreaming(dn, options); - for (const entry of entries) { - if (!entry) { - continue; - } - - const entity = await transformer(vendor, config, entry); + await client.searchStreaming(dn, options, async user => { + const entity = await transformer(vendor, config, user); if (!entity) { - continue; + return; } - mapReferencesAttr(entry, vendor, map.memberOf, (myDn, vs) => { + mapReferencesAttr(user, vendor, map.memberOf, (myDn, vs) => { ensureItems(userMemberOf, myDn, vs); }); entities.push(entity); - } + }); return { users: entities, userMemberOf }; } @@ -213,17 +208,15 @@ export async function readLdapGroups( const transformer = opts?.transformer ?? defaultGroupTransformer; - const entries = client.searchStreaming(dn, options); - - for (const entry of entries) { + await client.searchStreaming(dn, options, async entry => { if (!entry) { - continue; + return; } const entity = await transformer(vendor, config, entry); if (!entity) { - continue; + return; } mapReferencesAttr(entry, vendor, map.memberOf, (myDn, vs) => { @@ -234,7 +227,7 @@ export async function readLdapGroups( }); groups.push(entity); - } + }); return { groups, From 8b016ce67bda539223847b045d0eb3b4ca8dbc6e Mon Sep 17 00:00:00 2001 From: Phil Gore Date: Tue, 14 Sep 2021 11:12:33 -0500 Subject: [PATCH 4/6] adding changeset Signed-off-by: Phil Gore --- .changeset/proud-adults-bathe.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/proud-adults-bathe.md diff --git a/.changeset/proud-adults-bathe.md b/.changeset/proud-adults-bathe.md new file mode 100644 index 0000000000..86b8cfecb3 --- /dev/null +++ b/.changeset/proud-adults-bathe.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-ldap': minor +--- + +Alters LDAP processor to handle one SearchEntry at a time From 287d055a9d9486ecbe5569b55f8b7fc000a94e94 Mon Sep 17 00:00:00 2001 From: Phil Gore Date: Tue, 14 Sep 2021 13:14:00 -0500 Subject: [PATCH 5/6] prettifying test, updating api-report and test cases Signed-off-by: Phil Gore callback without promise and adjust test cases Signed-off-by: Phil Gore prettifying test Signed-off-by: Phil Gore updating api-report Signed-off-by: Phil Gore --- .../catalog-backend-module-ldap/api-report.md | 9 + .../src/ldap/client.ts | 4 +- .../src/ldap/read.test.ts | 184 +++++++----------- 3 files changed, 79 insertions(+), 118 deletions(-) diff --git a/plugins/catalog-backend-module-ldap/api-report.md b/plugins/catalog-backend-module-ldap/api-report.md index 35f647ec70..91f70eaa21 100644 --- a/plugins/catalog-backend-module-ldap/api-report.md +++ b/plugins/catalog-backend-module-ldap/api-report.md @@ -103,6 +103,15 @@ export class LdapClient { // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen search(dn: string, options: SearchOptions): Promise; + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + // Warning: (ae-forgotten-export) The symbol "SearchCallback" needs to be exported by the entry point index.d.ts + searchStreaming( + dn: string, + options: SearchOptions, + f: SearchCallback, + ): Promise; } // Warning: (ae-missing-release-tag) "LdapOrgEntityProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) diff --git a/plugins/catalog-backend-module-ldap/src/ldap/client.ts b/plugins/catalog-backend-module-ldap/src/ldap/client.ts index a36a96b638..048aa40dc1 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/client.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/client.ts @@ -147,8 +147,8 @@ export class LdapClient { reject(new Error('Unable to handle referral')); }); - res.on('searchEntry', async entry => { - await f(entry); + res.on('searchEntry', entry => { + f(entry); }); res.on('error', e => { diff --git a/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts b/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts index 5674c041ab..c4f203c5db 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts @@ -75,25 +75,20 @@ describe('readLdapUsers', () => { it('transfers all attributes from a default ldap vendor', async () => { client.getVendor.mockResolvedValue(DefaultLdapVendor); - client.searchStreaming.mockImplementation( - async (_dn, _opts, fn): Promise => { - return await new Promise((resolve, _reject) => { - fn( - searchEntry({ - uid: ['uid-value'], - description: ['description-value'], - cn: ['cn-value'], - mail: ['mail-value'], - avatarUrl: ['avatarUrl-value'], - memberOf: ['x', 'y', 'z'], - entryDN: ['dn-value'], - entryUUID: ['uuid-value'], - }), - ); - resolve(); - }); - }, - ); + client.searchStreaming.mockImplementation(async (_dn, _opts, fn) => { + await fn( + searchEntry({ + uid: ['uid-value'], + description: ['description-value'], + cn: ['cn-value'], + mail: ['mail-value'], + avatarUrl: ['avatarUrl-value'], + memberOf: ['x', 'y', 'z'], + entryDN: ['dn-value'], + entryUUID: ['uuid-value'], + }), + ); + }); const config: UserConfig = { dn: 'ddd', options: {}, @@ -136,44 +131,25 @@ describe('readLdapUsers', () => { it('transfers all attributes from Microsoft Active Directory', async () => { client.getVendor.mockResolvedValue(ActiveDirectoryVendor); - client.searchStreaming.mockImplementation( - async (_dn, _opts, fn): Promise => { - return await new Promise((resolve, _reject) => { - fn( - searchEntry({ - uid: ['uid-value'], - description: ['description-value'], - cn: ['cn-value'], - mail: ['mail-value'], - avatarUrl: ['avatarUrl-value'], - memberOf: ['x', 'y', 'z'], - distinguishedName: ['dn-value'], - objectGUID: [ - Buffer.from([ - 68, - 2, - 125, - 190, - 209, - 0, - 94, - 73, - 133, - 33, - 230, - 174, - 234, - 195, - 160, - 152, - ]), - ], - }), - ); - resolve(); - }); - }, - ); + client.searchStreaming.mockImplementation(async (_dn, _opts, fn) => { + await fn( + searchEntry({ + uid: ['uid-value'], + description: ['description-value'], + cn: ['cn-value'], + mail: ['mail-value'], + avatarUrl: ['avatarUrl-value'], + memberOf: ['x', 'y', 'z'], + distinguishedName: ['dn-value'], + objectGUID: [ + Buffer.from([ + 68, 2, 125, 190, 209, 0, 94, 73, 133, 33, 230, 174, 234, 195, 160, + 152, + ]), + ], + }), + ); + }); const config: UserConfig = { dn: 'ddd', options: {}, @@ -225,26 +201,21 @@ describe('readLdapGroups', () => { it('transfers all attributes from a default ldap vendor', async () => { client.getVendor.mockResolvedValue(DefaultLdapVendor); - client.searchStreaming.mockImplementation( - async (_dn, _opts, fn): Promise => { - return await new Promise((resolve, _reject) => { - fn( - searchEntry({ - cn: ['cn-value'], - description: ['description-value'], - tt: ['type-value'], - mail: ['mail-value'], - avatarUrl: ['avatarUrl-value'], - memberOf: ['x', 'y', 'z'], - member: ['e', 'f', 'g'], - entryDN: ['dn-value'], - entryUUID: ['uuid-value'], - }), - ); - resolve(); - }); - }, - ); + client.searchStreaming.mockImplementation(async (_dn, _opts, fn) => { + await fn( + searchEntry({ + cn: ['cn-value'], + description: ['description-value'], + tt: ['type-value'], + mail: ['mail-value'], + avatarUrl: ['avatarUrl-value'], + memberOf: ['x', 'y', 'z'], + member: ['e', 'f', 'g'], + entryDN: ['dn-value'], + entryUUID: ['uuid-value'], + }), + ); + }); const config: GroupConfig = { dn: 'ddd', options: {}, @@ -295,45 +266,26 @@ describe('readLdapGroups', () => { }); it('transfers all attributes from Microsoft Active Directory', async () => { client.getVendor.mockResolvedValue(ActiveDirectoryVendor); - client.searchStreaming.mockImplementation( - async (_dn, _opts, fn): Promise => { - return await new Promise((resolve, _reject) => { - fn( - searchEntry({ - cn: ['cn-value'], - description: ['description-value'], - tt: ['type-value'], - mail: ['mail-value'], - avatarUrl: ['avatarUrl-value'], - memberOf: ['x', 'y', 'z'], - member: ['e', 'f', 'g'], - distinguishedName: ['dn-value'], - objectGUID: [ - Buffer.from([ - 68, - 2, - 125, - 190, - 209, - 0, - 94, - 73, - 133, - 33, - 230, - 174, - 234, - 195, - 160, - 152, - ]), - ], - }), - ); - resolve(); - }); - }, - ); + client.searchStreaming.mockImplementation(async (_dn, _opts, fn) => { + await fn( + searchEntry({ + cn: ['cn-value'], + description: ['description-value'], + tt: ['type-value'], + mail: ['mail-value'], + avatarUrl: ['avatarUrl-value'], + memberOf: ['x', 'y', 'z'], + member: ['e', 'f', 'g'], + distinguishedName: ['dn-value'], + objectGUID: [ + Buffer.from([ + 68, 2, 125, 190, 209, 0, 94, 73, 133, 33, 230, 174, 234, 195, 160, + 152, + ]), + ], + }), + ); + }); const config: GroupConfig = { dn: 'ddd', options: {}, From 65f5317914127e0f38a12a68ce7ebffd722d26ab Mon Sep 17 00:00:00 2001 From: Phil Gore Date: Wed, 15 Sep 2021 10:09:50 -0500 Subject: [PATCH 6/6] LDAP change is just a patch, not minor version Signed-off-by: Phil Gore --- .changeset/proud-adults-bathe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/proud-adults-bathe.md b/.changeset/proud-adults-bathe.md index 86b8cfecb3..a8f15b18a3 100644 --- a/.changeset/proud-adults-bathe.md +++ b/.changeset/proud-adults-bathe.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-catalog-backend-module-ldap': minor +'@backstage/plugin-catalog-backend-module-ldap': patch --- Alters LDAP processor to handle one SearchEntry at a time