From c72eeb7f97be7c9f67cde886c1d8663d1f766acd Mon Sep 17 00:00:00 2001 From: Jwaegebaert <38426621+Jwaegebaert@users.noreply.github.com> Date: Fri, 18 Oct 2024 14:26:22 +0200 Subject: [PATCH] Suggestions & util improvement --- src/m365/viva/commands/engage/Community.ts | 8 +- .../engage/engage-community-user-list.spec.ts | 56 ++-------- .../engage/engage-community-user-list.ts | 6 +- src/utils/vivaEngage.spec.ts | 105 +++++++++--------- src/utils/vivaEngage.ts | 86 +++++++------- 5 files changed, 115 insertions(+), 146 deletions(-) diff --git a/src/m365/viva/commands/engage/Community.ts b/src/m365/viva/commands/engage/Community.ts index 75f5405227..bde8d4838f 100644 --- a/src/m365/viva/commands/engage/Community.ts +++ b/src/m365/viva/commands/engage/Community.ts @@ -1,7 +1,7 @@ export interface Community { - id: string; - displayName: string; + id?: string; + displayName?: string; description?: string; - privacy: string; - groupId: string; + privacy?: string; + groupId?: string; } \ No newline at end of file diff --git a/src/m365/viva/commands/engage/engage-community-user-list.spec.ts b/src/m365/viva/commands/engage/engage-community-user-list.spec.ts index a422217a36..2d768c2c09 100644 --- a/src/m365/viva/commands/engage/engage-community-user-list.spec.ts +++ b/src/m365/viva/commands/engage/engage-community-user-list.spec.ts @@ -37,26 +37,7 @@ describe(commands.ENGAGE_COMMUNITY_USER_LIST, () => { "userPrincipalName": "Samu.Tolonen@contoso.onmicrosoft.com" } ]; - const membersResult = [ - { - "id": "1deb8814-8130-451d-8fcb-849dc7ed47e5", - "businessPhones": [ - "123-555-1215" - ], - "displayName": "Samu Tolonen", - "givenName": "Samu", - "jobTitle": "IT Manager", - "mail": null, - "mobilePhone": "123-555-6645", - "officeLocation": "123455", - "preferredLanguage": null, - "surname": "Tolonen", - "userPrincipalName": "Samu.Tolonen@contoso.onmicrosoft.com", - "roles": [ - "Member" - ] - } - ]; + const membersResult = [{ ...membersAPIResult[0], roles: ["Member"] }]; const adminsAPIResult = [ { "id": "da634de7-d23c-4419-ab83-fcd395b4ebd0", @@ -74,26 +55,13 @@ describe(commands.ENGAGE_COMMUNITY_USER_LIST, () => { "userPrincipalName": "Anton.Johansen@contoso.onmicrosoft.com" } ]; - const adminsResult = [ - { - "id": "da634de7-d23c-4419-ab83-fcd395b4ebd0", - "businessPhones": [ - "123-555-1215" - ], - "displayName": "Anton Johansen", - "givenName": "Anton", - "jobTitle": "IT Manager", - "mail": null, - "mobilePhone": "123-555-6645", - "officeLocation": "123455", - "preferredLanguage": null, - "surname": "Johansen", - "userPrincipalName": "Anton.Johansen@contoso.onmicrosoft.com", - "roles": [ - "Admin" - ] - } - ]; + const adminsResult = [{ ...adminsAPIResult[0], roles: ["Admin"] }]; + const community = { + id: communityId, + displayName: communityDisplayName, + privacy: 'Public', + groupId: entraGroupId + }; let log: string[]; let logger: Logger; @@ -130,7 +98,7 @@ describe(commands.ENGAGE_COMMUNITY_USER_LIST, () => { afterEach(() => { sinonUtil.restore([ request.get, - vivaEngage.getEntraGroupIdByCommunityId + vivaEngage.getCommunityById ]); }); @@ -235,7 +203,7 @@ describe(commands.ENGAGE_COMMUNITY_USER_LIST, () => { throw 'Invalid request'; }); - sinon.stub(vivaEngage, 'getEntraGroupIdByCommunityId').resolves(entraGroupId); + sinon.stub(vivaEngage, 'getCommunityById').resolves(community); await command.action(logger, { options: { communityId: communityId, verbose: true } }); assert(loggerLogSpy.calledWith([...adminsResult, ...membersResult])); @@ -254,7 +222,7 @@ describe(commands.ENGAGE_COMMUNITY_USER_LIST, () => { throw 'Invalid request'; }); - sinon.stub(vivaEngage, 'getEntraGroupIdByCommunityDisplayName').resolves(entraGroupId); + sinon.stub(vivaEngage, 'getCommunityByDisplayName').resolves(community); await command.action(logger, { options: { communityDisplayName: communityDisplayName, verbose: true } }); assert(loggerLogSpy.calledWith([...adminsResult, ...membersResult])); @@ -290,7 +258,7 @@ describe(commands.ENGAGE_COMMUNITY_USER_LIST, () => { throw 'Invalid request'; }); - sinon.stub(vivaEngage, 'getEntraGroupIdByCommunityId').resolves(entraGroupId); + sinon.stub(vivaEngage, 'getCommunityById').resolves(community); await command.action(logger, { options: { communityId: communityId, role: 'Admin' } }); assert(loggerLogSpy.calledWith(adminsResult)); diff --git a/src/m365/viva/commands/engage/engage-community-user-list.ts b/src/m365/viva/commands/engage/engage-community-user-list.ts index af559b7c99..4c7e3dfb8a 100644 --- a/src/m365/viva/commands/engage/engage-community-user-list.ts +++ b/src/m365/viva/commands/engage/engage-community-user-list.ts @@ -68,11 +68,13 @@ class VivaEngageCommunityUserListCommand extends GraphCommand { let entraGroupId = args.options.entraGroupId; if (args.options.communityDisplayName) { - entraGroupId = await vivaEngage.getEntraGroupIdByCommunityDisplayName(args.options.communityDisplayName); + const community = await vivaEngage.getCommunityByDisplayName(args.options.communityDisplayName, ['groupId']); + entraGroupId = community.groupId; } if (args.options.communityId) { - entraGroupId = await vivaEngage.getEntraGroupIdByCommunityId(args.options.communityId); + const community = await vivaEngage.getCommunityById(args.options.communityId, ['groupId']); + entraGroupId = community.groupId; } const requestOptions: CliRequestOptions = { diff --git a/src/utils/vivaEngage.spec.ts b/src/utils/vivaEngage.spec.ts index baf42f2aed..8df9f11a0d 100644 --- a/src/utils/vivaEngage.spec.ts +++ b/src/utils/vivaEngage.spec.ts @@ -35,12 +35,14 @@ describe('utils/vivaEngage', () => { ]); }); - it('correctly get single community id by name using getCommunityIdByDisplayName', async () => { + it('correctly get single community id by name using getCommunityByDisplayName', async () => { sinon.stub(request, 'get').callsFake(async opts => { - if (opts.url === `https://graph.microsoft.com/v1.0/employeeExperience/communities?$filter=displayName eq '${formatting.encodeQueryParameter(displayName)}'`) { + if (opts.url === `https://graph.microsoft.com/v1.0/employeeExperience/communities?$filter=displayName eq '${formatting.encodeQueryParameter(displayName)}'&$select=id`) { return { value: [ - communityResponse + { + id: communityId + } ] }; } @@ -48,17 +50,17 @@ describe('utils/vivaEngage', () => { return 'Invalid Request'; }); - const actual = await vivaEngage.getCommunityIdByDisplayName(displayName); - assert.deepStrictEqual(actual, 'eyJfdHlwZSI6Ikdyb3VwIiwiaWQiOiI0NzY5MTM1ODIwOSJ9'); + const actual = await vivaEngage.getCommunityByDisplayName(displayName, ['id']); + assert.deepStrictEqual(actual, { id: communityId }); }); - it('handles selecting single community when multiple communities with the specified name found using getCommunityIdByDisplayName and cli is set to prompt', async () => { + it('handles selecting single community when multiple communities with the specified name found using getCommunityByDisplayName and cli is set to prompt', async () => { sinon.stub(request, 'get').callsFake(async opts => { - if (opts.url === `https://graph.microsoft.com/v1.0/employeeExperience/communities?$filter=displayName eq '${formatting.encodeQueryParameter(displayName)}'`) { + if (opts.url === `https://graph.microsoft.com/v1.0/employeeExperience/communities?$filter=displayName eq '${formatting.encodeQueryParameter(displayName)}'&$select=id`) { return { value: [ - communityResponse, - anotherCommunityResponse + { id: communityId }, + { id: "eyJfdHlwZ0NzY5SIwiIiSJ9IwO6IaWQiOIMTM1ODikdyb3Vw" } ] }; } @@ -66,25 +68,25 @@ describe('utils/vivaEngage', () => { return 'Invalid Request'; }); - sinon.stub(cli, 'handleMultipleResultsFound').resolves(communityResponse); + sinon.stub(cli, 'handleMultipleResultsFound').resolves({ id: communityId }); - const actual = await vivaEngage.getCommunityIdByDisplayName(displayName); - assert.deepStrictEqual(actual, 'eyJfdHlwZSI6Ikdyb3VwIiwiaWQiOiI0NzY5MTM1ODIwOSJ9'); + const actual = await vivaEngage.getCommunityByDisplayName(displayName, ['id']); + assert.deepStrictEqual(actual, { id: 'eyJfdHlwZSI6Ikdyb3VwIiwiaWQiOiI0NzY5MTM1ODIwOSJ9' }); }); - it('throws error message when no community was found using getCommunityIdByDisplayName', async () => { + it('throws error message when no community was found using getCommunityByDisplayName', async () => { sinon.stub(request, 'get').callsFake(async (opts) => { - if (opts.url === `https://graph.microsoft.com/v1.0/employeeExperience/communities?$filter=displayName eq '${formatting.encodeQueryParameter(invalidDisplayName)}'`) { + if (opts.url === `https://graph.microsoft.com/v1.0/employeeExperience/communities?$filter=displayName eq '${formatting.encodeQueryParameter(invalidDisplayName)}'&$select=id`) { return { value: [] }; } throw 'Invalid Request'; }); - await assert.rejects(vivaEngage.getCommunityIdByDisplayName(invalidDisplayName)), Error(`The specified Viva Engage community '${invalidDisplayName}' does not exist.`); + await assert.rejects(vivaEngage.getCommunityByDisplayName(invalidDisplayName, ['id'])), Error(`The specified Viva Engage community '${invalidDisplayName}' does not exist.`); }); - it('throws error message when multiple communities were found using getCommunityIdByDisplayName', async () => { + it('throws error message when multiple communities were found using getCommunityByDisplayName', async () => { sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName, defaultValue) => { if (settingName === settingsNames.prompt) { return false; @@ -94,11 +96,11 @@ describe('utils/vivaEngage', () => { }); sinon.stub(request, 'get').callsFake(async opts => { - if (opts.url === `https://graph.microsoft.com/v1.0/employeeExperience/communities?$filter=displayName eq '${formatting.encodeQueryParameter(displayName)}'`) { + if (opts.url === `https://graph.microsoft.com/v1.0/employeeExperience/communities?$filter=displayName eq '${formatting.encodeQueryParameter(displayName)}'&$select=id`) { return { value: [ - communityResponse, - anotherCommunityResponse + { id: communityId }, + { id: "eyJfdHlwZ0NzY5SIwiIiSJ9IwO6IaWQiOIMTM1ODikdyb3Vw" } ] }; } @@ -106,16 +108,19 @@ describe('utils/vivaEngage', () => { return 'Invalid Request'; }); - await assert.rejects(vivaEngage.getCommunityIdByDisplayName(displayName), + await assert.rejects(vivaEngage.getCommunityByDisplayName(displayName, ['id']), Error(`Multiple Viva Engage communities with name '${displayName}' found. Found: ${communityResponse.id}, ${anotherCommunityResponse.id}.`)); }); - it('correctly get single community id by group id using getCommunityIdByEntraGroupId', async () => { + it('correctly get single community by group id using getCommunityByEntraGroupId', async () => { sinon.stub(request, 'get').callsFake(async opts => { if (opts.url === 'https://graph.microsoft.com/v1.0/employeeExperience/communities?$select=id,groupId') { return { value: [ - communityResponse + { + id: communityId, + groupId: entraGroupId + } ] }; } @@ -123,65 +128,65 @@ describe('utils/vivaEngage', () => { return 'Invalid Request'; }); - const actual = await vivaEngage.getCommunityIdByEntraGroupId(entraGroupId); - assert.deepStrictEqual(actual, 'eyJfdHlwZSI6Ikdyb3VwIiwiaWQiOiI0NzY5MTM1ODIwOSJ9'); + const actual = await vivaEngage.getCommunityByEntraGroupId(entraGroupId, ['id']); + assert.deepStrictEqual(actual, { id: communityId, groupId: entraGroupId }); }); - it('throws error message when no community was found using getCommunityIdByEntraGroupId', async () => { - sinon.stub(request, 'get').callsFake(async (opts) => { - if (opts.url === 'https://graph.microsoft.com/v1.0/employeeExperience/communities?$select=id,groupId') { - return { value: [] }; + it('correctly get single community by group id using getCommunityByEntraGroupId and multiple properties', async () => { + sinon.stub(request, 'get').callsFake(async opts => { + if (opts.url === 'https://graph.microsoft.com/v1.0/employeeExperience/communities?$select=id,groupId,displayName') { + return { + value: [ + { + id: communityId, + groupId: entraGroupId, + displayName: displayName + } + ] + }; } - throw 'Invalid Request'; + return 'Invalid Request'; }); - await assert.rejects(vivaEngage.getCommunityIdByEntraGroupId(entraGroupId)), Error(`The Microsoft Entra group with id '${entraGroupId}' is not associated with any Viva Engage community.`); + const actual = await vivaEngage.getCommunityByEntraGroupId(entraGroupId, ['id', 'groupId', 'displayName']); + assert.deepStrictEqual(actual, { id: communityId, groupId: entraGroupId, displayName: displayName }); }); - it('correctly gets Entra group ID by community ID using getEntraGroupIdByCommunityId', async () => { + it('throws error message when no community was found using getCommunityByEntraGroupId', async () => { sinon.stub(request, 'get').callsFake(async (opts) => { - if (opts.url === `https://graph.microsoft.com/v1.0/employeeExperience/communities/${communityId}?$select=groupId`) { - return communityResponse; + if (opts.url === 'https://graph.microsoft.com/v1.0/employeeExperience/communities?$select=id,groupId') { + return { value: [] }; } throw 'Invalid Request'; }); - const actual = await vivaEngage.getEntraGroupIdByCommunityId(communityId); - assert.deepStrictEqual(actual, '0bed8b86-5026-4a93-ac7d-56750cc099f1'); + await assert.rejects(vivaEngage.getCommunityByEntraGroupId(entraGroupId, ['id'])), Error(`The Microsoft Entra group with id '${entraGroupId}' is not associated with any Viva Engage community.`); }); - it('throws error message when no Entra group ID was found using getEntraGroupIdByCommunityId', async () => { + it('correctly gets Entra group ID by community ID using getEntraGroupIdByCommunityId', async () => { sinon.stub(request, 'get').callsFake(async (opts) => { if (opts.url === `https://graph.microsoft.com/v1.0/employeeExperience/communities/${communityId}?$select=groupId`) { - return null; + return { groupId: entraGroupId }; } throw 'Invalid Request'; }); - await assert.rejects(vivaEngage.getEntraGroupIdByCommunityId(communityId)), Error(`The specified Viva Engage community with ID '${communityId}' does not exist.`); + const actual = await vivaEngage.getCommunityById(communityId, ['groupId']); + assert.deepStrictEqual(actual, { groupId: '0bed8b86-5026-4a93-ac7d-56750cc099f1' }); }); - it('correctly gets Entra group ID by community display name using getEntraGroupIdByCommunityDisplayName', async () => { + it('throws error message when no Entra group ID was found using getCommunityById', async () => { sinon.stub(request, 'get').callsFake(async (opts) => { if (opts.url === `https://graph.microsoft.com/v1.0/employeeExperience/communities/${communityId}?$select=groupId`) { - return communityResponse; - } - - if (opts.url === `https://graph.microsoft.com/v1.0/employeeExperience/communities?$filter=displayName eq '${formatting.encodeQueryParameter(displayName)}'`) { - return { - value: [ - communityResponse - ] - }; + return null; } throw 'Invalid Request'; }); - const actual = await vivaEngage.getEntraGroupIdByCommunityDisplayName(displayName); - assert.deepStrictEqual(actual, entraGroupId); + await assert.rejects(vivaEngage.getCommunityById(communityId, ['groupId'])), Error(`The specified Viva Engage community with ID '${communityId}' does not exist.`); }); }); \ No newline at end of file diff --git a/src/utils/vivaEngage.ts b/src/utils/vivaEngage.ts index 9fc4403a01..40ba84ddc2 100644 --- a/src/utils/vivaEngage.ts +++ b/src/utils/vivaEngage.ts @@ -6,12 +6,37 @@ import { odata } from './odata.js'; export const vivaEngage = { /** - * Get Viva Engage community ID by display name. + * Get Viva Engage group ID by community ID. + * @param communityId The ID of the Viva Engage community. + * @returns The ID of the Viva Engage group. + * @returns The Viva Engage community. + */ + async getCommunityById(communityId: string, selectProperties: string[]): Promise { + const requestOptions: CliRequestOptions = { + url: `https://graph.microsoft.com/v1.0/employeeExperience/communities/${communityId}?$select=${selectProperties.join(',')}`, + headers: { + accept: 'application/json;odata.metadata=none' + }, + responseType: 'json' + }; + + const community = await request.get(requestOptions); + + if (!community) { + throw `The specified Viva Engage community with ID '${communityId}' does not exist.`; + } + + return community; + }, + + /** + * Get Viva Engage community by display name. * @param displayName Community display name. - * @returns The ID of the Viva Engage community. + * @param selectProperties Properties to select. + * @returns The Viva Engage community. */ - async getCommunityIdByDisplayName(displayName: string): Promise { - const communities = await odata.getAllItems(`https://graph.microsoft.com/v1.0/employeeExperience/communities?$filter=displayName eq '${formatting.encodeQueryParameter(displayName)}'`); + async getCommunityByDisplayName(displayName: string, selectProperties: string[]): Promise { + const communities = await odata.getAllItems(`https://graph.microsoft.com/v1.0/employeeExperience/communities?$filter=displayName eq '${formatting.encodeQueryParameter(displayName)}'&$select=${selectProperties.join(',')}`); if (communities.length === 0) { throw `The specified Viva Engage community '${displayName}' does not exist.`; @@ -20,60 +45,29 @@ export const vivaEngage = { if (communities.length > 1) { const resultAsKeyValuePair = formatting.convertArrayToHashTable('id', communities); const selectedCommunity = await cli.handleMultipleResultsFound(`Multiple Viva Engage communities with name '${displayName}' found.`, resultAsKeyValuePair); - return selectedCommunity.id; + return selectedCommunity; } - return communities[0].id; + return communities[0]; }, /** - * Get Viva Engage community ID by Microsoft Entra group ID. + * Get Viva Engage community by Microsoft Entra group ID. * Note: The Graph API doesn't support filtering by groupId, so we need to retrieve all communities and filter them in memory. * @param entraGroupId The ID of the Microsoft Entra group. - * @returns The ID of the Viva Engage community. + * @param selectProperties Properties to select. + * @returns The Viva Engage community. */ - async getCommunityIdByEntraGroupId(entraGroupId: string): Promise { - const communities = await odata.getAllItems('https://graph.microsoft.com/v1.0/employeeExperience/communities?$select=id,groupId'); + async getCommunityByEntraGroupId(entraGroupId: string, selectProperties: string[]): Promise { + const properties = selectProperties.includes('groupId') ? selectProperties : [...selectProperties, 'groupId']; + const communities = await odata.getAllItems(`https://graph.microsoft.com/v1.0/employeeExperience/communities?$select=${properties.join(',')}`); - const filtereCommunities = communities.filter(c => c.groupId === entraGroupId); + const filteredCommunity = communities.find(c => c.groupId === entraGroupId); - if (filtereCommunities.length === 0) { + if (!filteredCommunity) { throw `The Microsoft Entra group with id '${entraGroupId}' is not associated with any Viva Engage community.`; } - return filtereCommunities[0].id; - }, - - /** - * Get Viva Engage group ID by community ID. - * @param communityId The ID of the Viva Engage community. - * @returns The ID of the Viva Engage group. - */ - async getEntraGroupIdByCommunityId(communityId: string): Promise { - const requestOptions: CliRequestOptions = { - url: `https://graph.microsoft.com/v1.0/employeeExperience/communities/${communityId}?$select=groupId`, - headers: { - accept: 'application/json;odata.metadata=none' - }, - responseType: 'json' - }; - - const community = await request.get(requestOptions); - - if (!community) { - throw `The specified Viva Engage community with ID '${communityId}' does not exist.`; - } - - return community.groupId; - }, - - /** - * Get Viva Engage group ID by community display name. - * @param displayName Community display name. - * @returns The ID of the Viva Engage group. - */ - async getEntraGroupIdByCommunityDisplayName(displayName: string): Promise { - const communityId = await this.getCommunityIdByDisplayName(displayName); - return await this.getEntraGroupIdByCommunityId(communityId); + return filteredCommunity; } }; \ No newline at end of file