diff --git a/docs/docs/cmd/viva/engage/engage-role-list.mdx b/docs/docs/cmd/viva/engage/engage-role-list.mdx new file mode 100644 index 00000000000..4dd6fc0632c --- /dev/null +++ b/docs/docs/cmd/viva/engage/engage-role-list.mdx @@ -0,0 +1,102 @@ +import Global from '/docs/cmd/_global.mdx'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# viva engage role list + +Lists all Viva Engage roles + +## Usage + +```sh +m365 viva engage role list [options] +``` + +## Options + + + +## Remarks + +:::warning + +This command is based on an API that is currently in preview and is subject to change once the API reaches general availability. + +::: + +## Permissions + + + + + | Resource | Permissions | + |-----------------|-------------------------| + | Microsoft Graph | EngagementRole.Read.All | + + + + + | Resource | Permissions | + |-----------------|-------------------------| + | Microsoft Graph | EngagementRole.Read.All | + + + + +## Examples + +List all Viva Engage roles + +```sh +m365 viva engage role list +``` + +## Response + + + + + ```json + [ + { + "id": "ec759127-089f-4f91-8dfc-03a30b51cb38", + "displayName": "Network Admin" + } + ] + ``` + + + + + ```text + id displayName + ------------------------------------ ------------- + ec759127-089f-4f91-8dfc-03a30b51cb38 Network Admin + ``` + + + + + ```csv + id,displayName + ec759127-089f-4f91-8dfc-03a30b51cb38,Network Admin + ``` + + + + + ```md + # viva engage role list + + Date: 7/11/2025 + + ## Network Admin (ec759127-089f-4f91-8dfc-03a30b51cb38) + + Property | Value + ---------|------- + id | ec759127-089f-4f91-8dfc-03a30b51cb38 + displayName | Network Admin + ``` + + + diff --git a/docs/src/config/sidebars.ts b/docs/src/config/sidebars.ts index 1d71537c551..39c83d28353 100644 --- a/docs/src/config/sidebars.ts +++ b/docs/src/config/sidebars.ts @@ -4907,6 +4907,11 @@ const sidebars: SidebarsConfig = { label: 'engage report groupsactivitygroupcounts', id: 'cmd/viva/engage/engage-report-groupsactivitygroupcounts' }, + { + type: 'doc', + label: 'engage role list', + id: 'cmd/viva/engage/engage-role-list' + }, { type: 'doc', label: 'engage user get', diff --git a/src/config.ts b/src/config.ts index 0128cb1abb5..6436c64c241 100644 --- a/src/config.ts +++ b/src/config.ts @@ -17,6 +17,7 @@ export default { 'https://graph.microsoft.com/Community.ReadWrite.All', 'https://graph.microsoft.com/Directory.AccessAsUser.All', 'https://graph.microsoft.com/Directory.ReadWrite.All', + 'https://graph.microsoft.com/EngagementRole.ReadWrite.All', 'https://graph.microsoft.com/ExternalConnection.ReadWrite.All', 'https://graph.microsoft.com/ExternalItem.ReadWrite.All', 'https://graph.microsoft.com/FileStorageContainer.Selected', diff --git a/src/m365/viva/commands.ts b/src/m365/viva/commands.ts index aafe65d892b..b099b1e004e 100644 --- a/src/m365/viva/commands.ts +++ b/src/m365/viva/commands.ts @@ -28,6 +28,7 @@ export default { ENGAGE_REPORT_GROUPSACTIVITYCOUNTS: `${prefix} engage report groupsactivitycounts`, ENGAGE_REPORT_GROUPSACTIVITYDETAIL: `${prefix} engage report groupsactivitydetail`, ENGAGE_REPORT_GROUPSACTIVITYGROUPCOUNTS: `${prefix} engage report groupsactivitygroupcounts`, + ENGAGE_ROLE_LIST: `${prefix} engage role list`, ENGAGE_SEARCH: `${prefix} engage search`, ENGAGE_USER_GET: `${prefix} engage user get`, ENGAGE_USER_LIST: `${prefix} engage user list` diff --git a/src/m365/viva/commands/engage/EngageRole.ts b/src/m365/viva/commands/engage/EngageRole.ts new file mode 100644 index 00000000000..4986dd5ca03 --- /dev/null +++ b/src/m365/viva/commands/engage/EngageRole.ts @@ -0,0 +1,4 @@ +export interface EngageRole { + id?: string; + displayName?: string; +} diff --git a/src/m365/viva/commands/engage/engage-role-list.spec.ts b/src/m365/viva/commands/engage/engage-role-list.spec.ts new file mode 100644 index 00000000000..6a10a272c54 --- /dev/null +++ b/src/m365/viva/commands/engage/engage-role-list.spec.ts @@ -0,0 +1,125 @@ +import assert from 'assert'; +import sinon from 'sinon'; +import auth from '../../../../Auth.js'; +import { Logger } from '../../../../cli/Logger.js'; +import { CommandError } from '../../../../Command.js'; +import request from '../../../../request.js'; +import { telemetry } from '../../../../telemetry.js'; +import { pid } from '../../../../utils/pid.js'; +import { session } from '../../../../utils/session.js'; +import { sinonUtil } from '../../../../utils/sinonUtil.js'; +import commands from '../../commands.js'; +import command from './engage-role-list.js'; + +describe(commands.ENGAGE_ROLE_LIST, () => { + let log: string[]; + let logger: Logger; + let loggerLogSpy: sinon.SinonSpy; + + before(() => { + sinon.stub(auth, 'restoreAuth').resolves(); + sinon.stub(telemetry, 'trackEvent').resolves(); + sinon.stub(pid, 'getProcessName').returns(''); + sinon.stub(session, 'getId').returns(''); + auth.connection.active = true; + }); + + beforeEach(() => { + log = []; + logger = { + log: async (msg: string) => { + log.push(msg); + }, + logRaw: async (msg: string) => { + log.push(msg); + }, + logToStderr: async (msg: string) => { + log.push(msg); + } + }; + loggerLogSpy = sinon.spy(logger, 'log'); + }); + + afterEach(() => { + sinonUtil.restore([ + request.get + ]); + }); + + after(() => { + sinon.restore(); + auth.connection.active = false; + }); + + it('has correct name', () => { + assert.strictEqual(command.name, commands.ENGAGE_ROLE_LIST); + }); + + it('has a description', () => { + assert.notStrictEqual(command.description, null); + }); + + it('defines correct properties for the default output', () => { + assert.deepStrictEqual(command.defaultProperties(), ['id', 'displayName']); + }); + + it(`should get a list of Viva Engage roles`, async () => { + sinon.stub(request, 'get').callsFake(async (opts) => { + if (opts.url === `https://graph.microsoft.com/beta/employeeExperience/roles`) { + return { + "value": [ + { + "id": "ec759127-089f-4f91-8dfc-03a30b51cb38", + "displayName": "Network Admin" + }, + { + "id": "966b8ec4-6457-4f22-bd3c-5a2520e98f4a", + "displayName": "Verified Admin" + }, + { + "id": "77aa47ad-96fe-4ecc-8024-fd1ac5e28f17", + "displayName": "Corporate Communicator" + } + ] + }; + } + + throw 'Invalid request'; + }); + + await command.action(logger, { + options: { verbose: true } + }); + + assert( + loggerLogSpy.calledOnceWith([ + { + "id": "ec759127-089f-4f91-8dfc-03a30b51cb38", + "displayName": "Network Admin" + }, + { + "id": "966b8ec4-6457-4f22-bd3c-5a2520e98f4a", + "displayName": "Verified Admin" + }, + { + "id": "77aa47ad-96fe-4ecc-8024-fd1ac5e28f17", + "displayName": "Corporate Communicator" + } + ]) + ); + }); + + it('handles error when retrieving Viva Engage roles failed', async () => { + sinon.stub(request, 'get').callsFake(async (opts) => { + if (opts.url === `https://graph.microsoft.com/beta/employeeExperience/roles`) { + throw { error: { message: 'An error has occurred' } }; + } + throw `Invalid request`; + }); + + await assert.rejects( + command.action(logger, { options: {} }), + new CommandError('An error has occurred') + ); + }); +}); \ No newline at end of file diff --git a/src/m365/viva/commands/engage/engage-role-list.ts b/src/m365/viva/commands/engage/engage-role-list.ts new file mode 100644 index 00000000000..af056f01da7 --- /dev/null +++ b/src/m365/viva/commands/engage/engage-role-list.ts @@ -0,0 +1,35 @@ +import { Logger } from '../../../../cli/Logger.js'; +import { odata } from '../../../../utils/odata.js'; +import GraphCommand from '../../../base/GraphCommand.js'; +import commands from '../../commands.js'; +import { EngageRole } from './EngageRole.js'; + +class VivaEngageRoleListCommand extends GraphCommand { + public get name(): string { + return commands.ENGAGE_ROLE_LIST; + } + + public get description(): string { + return 'Lists all Viva Engage roles'; + } + + public defaultProperties(): string[] | undefined { + return ['id', 'displayName']; + } + + public async commandAction(logger: Logger): Promise { + if (this.verbose) { + await logger.logToStderr('Getting all Viva Engage roles...'); + } + + try { + const results = await odata.getAllItems(`${this.resource}/beta/employeeExperience/roles`); + await logger.log(results); + } + catch (err: any) { + this.handleRejectedODataJsonPromise(err); + } + } +} + +export default new VivaEngageRoleListCommand(); \ No newline at end of file