Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const dictionary = [
'activation',
'activations',
'adaptive',
'administrative',
'ai',
'app',
'application',
Expand Down Expand Up @@ -90,6 +91,7 @@ const dictionary = [
'threat',
'token',
'type',
'unit',
'user',
'web',
'webhook'
Expand Down
98 changes: 98 additions & 0 deletions docs/docs/cmd/aad/administrativeunit/administrativeunit-get.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import Global from '/docs/cmd/_global.mdx';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# aad administrativeunit get

Gets information about a specific administrative unit

## Usage

```sh
m365 aad administrativeunit get [options]
```

## Options

```md definition-list
`-i, --id [id]`
: The id of the administrative unit. Specify either `id` or `displayName` but not both.

`-n, --displayName [displayName]`
: The display name of the administrative unit. Specify either `id` or `displayName` but not both.
```

<Global />

## Examples

Get information about the administrative unit by its id

```sh
m365 aad administrativeunit get --id 03c4c9dc-6f0c-4c4f-a4e6-0c9ed80f54c7
```

Get information about the administrative unit by its display name

```sh
m365 aad administrativeunit get --displayName 'Marketing Division'
```

## Response

<Tabs>
<TabItem value="JSON">

```json
{
"id": "0a22c83d-c4ac-43e2-bb5e-87af3015d49f",
"deletedDateTime": null,
"displayName": "Marketing Division",
"description": "Marketing Department Administration",
"membershipRule": null,
"membershipType": null,
"membershipRuleProcessingState": null,
"visibility": "HiddenMembership"
}
```

</TabItem>
<TabItem value="Text">

```text
deletedDateTime : null
description : Marketing Department Administration
displayName : Marketing Division
id : 0a22c83d-c4ac-43e2-bb5e-87af3015d49f
membershipRule : null
membershipRuleProcessingState: null
membershipType : null
visibility : HiddenMembership
```

</TabItem>
<TabItem value="CSV">

```csv
id,displayName,description,visibility
0a22c83d-c4ac-43e2-bb5e-87af3015d49f,Marketing Division,Marketing Department Administration,HiddenMembership
```

</TabItem>
<TabItem value="Markdown">

```md
Date: 10/23/2023

## Marketing Division (0a22c83d-c4ac-43e2-bb5e-87af3015d49f)

Property | Value
---------|-------
id | 0a22c83d-c4ac-43e2-bb5e-87af3015d49f
displayName | Marketing Division
description | Marketing Department Administration
visibility | HiddenMembership
```

</TabItem>
</Tabs>
9 changes: 9 additions & 0 deletions docs/src/config/sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ const sidebars = {
'cmd/version',
{
'Azure Active Directory (aad)': [
{
administrativeunit: [
{
type: 'doc',
label: 'administrativeunit get',
id: 'cmd/aad/administrativeunit/administrativeunit-get'
}
]
},
{
app: [
{
Expand Down
1 change: 1 addition & 0 deletions src/m365/aad/commands.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const prefix: string = 'aad';

export default {
ADMINISTRATIVEUNIT_GET: `${prefix} administrativeunit get`,
APP_ADD: `${prefix} app add`,
APP_GET: `${prefix} app get`,
APP_LIST: `${prefix} app list`,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import assert from 'assert';
import sinon from "sinon";
import auth from '../../../../Auth.js';
import { CommandInfo } from "../../../../cli/CommandInfo.js";
import { Logger } from "../../../../cli/Logger.js";
import commands from "../../commands.js";
import { telemetry } from '../../../../telemetry.js';
import { pid } from '../../../../utils/pid.js';
import { session } from '../../../../utils/session.js';
import { Cli } from '../../../../cli/Cli.js';
import command from './administrativeunit-get.js';
import request from '../../../../request.js';
import { sinonUtil } from '../../../../utils/sinonUtil.js';
import { CommandError } from '../../../../Command.js';
import { formatting } from '../../../../utils/formatting.js';

describe(commands.ADMINISTRATIVEUNIT_GET, () => {
let log: string[];
let logger: Logger;
let loggerLogSpy: sinon.SinonSpy;
let commandInfo: CommandInfo;
const administrativeUnitsReponse = {
value: [
{
id: 'fc33aa61-cf0e-46b6-9506-f633347202ab',
displayName: 'European Division',
visibility: 'HiddenMembership'
},
{
id: 'a25b4c5e-e8b7-4f02-a23d-0965b6415098',
displayName: 'Asian Division',
visibility: null
}
]
};
const validId = 'fc33aa61-cf0e-46b6-9506-f633347202ab';
const validDisplayName = 'European Division';
const invalidDisplayName = 'European';

before(() => {
sinon.stub(auth, 'restoreAuth').resolves();
sinon.stub(telemetry, 'trackEvent').returns();
sinon.stub(pid, 'getProcessName').returns('');
sinon.stub(session, 'getId').returns('');
auth.service.connected = true;
commandInfo = Cli.getCommandInfo(command);
});

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,
Cli.handleMultipleResultsFound
]);
});

after(() => {
sinon.restore();
auth.service.connected = false;
});

it('has correct name', () => {
assert.strictEqual(command.name, commands.ADMINISTRATIVEUNIT_GET);
});

it('has a description', () => {
assert.notStrictEqual(command.description, null);
});

it('retrieves information about the specified administrative unit by id', async () => {
sinon.stub(request, 'get').callsFake(async (opts) => {
if (opts.url === `https://graph.microsoft.com/v1.0/directory/administrativeUnits/${validId}`) {
return administrativeUnitsReponse.value[0];
}

throw 'Invalid request';
});

await command.action(logger, { options: { id: validId } });
assert(loggerLogSpy.calledOnceWithExactly(administrativeUnitsReponse.value[0]));
});

it('retrieves information about the specified administrative unit by displayName', async () => {
sinon.stub(request, 'get').callsFake(async (opts) => {
if (opts.url === `https://graph.microsoft.com/v1.0/directory/administrativeUnits?$filter=displayName eq '${formatting.encodeQueryParameter(validDisplayName)}'`) {
return {
value: [
administrativeUnitsReponse.value[0]
]
};
}

throw 'Invalid Request';
});

await command.action(logger, { options: { displayName: validDisplayName } });
assert(loggerLogSpy.calledOnceWithExactly(administrativeUnitsReponse.value[0]));
});

it('throws error message when no administrative unit was found by displayName', async () => {
sinon.stub(request, 'get').callsFake(async (opts) => {
if (opts.url === `https://graph.microsoft.com/v1.0/directory/administrativeUnits?$filter=displayName eq '${formatting.encodeQueryParameter(invalidDisplayName)}'`) {
return { value: [] };
}

throw 'Invalid Request';
});

await assert.rejects(command.action(logger, { options: { displayName: invalidDisplayName } }), new CommandError(`The specified administrative unit '${invalidDisplayName}' does not exist.`));
});

it('handles selecting single result when multiple administrative units with the specified displayName found and cli is set to prompt', async () => {
sinon.stub(request, 'get').callsFake(async opts => {
if (opts.url === `https://graph.microsoft.com/v1.0/directory/administrativeUnits?$filter=displayName eq '${formatting.encodeQueryParameter(validDisplayName)}'`) {
return {
value: [
administrativeUnitsReponse.value[0],
administrativeUnitsReponse.value[0]
]
};
}

return 'Invalid Request';
});

sinon.stub(Cli, 'handleMultipleResultsFound').resolves({ id: validId, displayName: validDisplayName, visibility: 'HiddenMembership' });

await command.action(logger, { options: { displayName: validDisplayName } });
assert(loggerLogSpy.calledWith(administrativeUnitsReponse.value[0]));
});

it('handles random API error', async () => {
const errorMessage = 'Something went wrong';
sinon.stub(request, 'get').rejects(new Error(errorMessage));

await assert.rejects(command.action(logger, { options: { id: validId } }), new CommandError(errorMessage));
});

it('fails validation if the id is not a valid GUID', async () => {
const actual = await command.validate({ options: { id: '123' } }, commandInfo);
assert.notStrictEqual(actual, true);
});

it('passes validation if the id is a valid GUID', async () => {
const actual = await command.validate({ options: { id: validId } }, commandInfo);
assert.strictEqual(actual, true);
});

it('passes validation if required options specified (displayName)', async () => {
const actual = await command.validate({ options: { displayName: validDisplayName } }, commandInfo);
assert.strictEqual(actual, true);
});
});
Loading