forked from pnp/cli-microsoft365
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds command 'tenant info get'. Closes pnp#5389
- Loading branch information
1 parent
45fb2db
commit d9f224d
Showing
5 changed files
with
410 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import Global from '/docs/cmd/_global.mdx'; | ||
import Tabs from '@theme/Tabs'; | ||
import TabItem from '@theme/TabItem'; | ||
|
||
# tenant info get | ||
|
||
Gets information about any tenant | ||
|
||
## Usage | ||
|
||
```sh | ||
m365 tenant info get [options] | ||
``` | ||
|
||
## Options | ||
|
||
```md definition-list | ||
`-d, --domainName [domainName]` | ||
: The primary domain name of a tenant. Optionally specify either `domainName` or `tenantId` but not both. If none are specified, the tenantId of the currently signed-in user is used. | ||
|
||
`-i, --tenantId [tenantId]` | ||
: The unique tenant identifier of a tenant. Optionally specify either `domainName` or `tenantId` but not both. If none are specified, the tenantId of the currently signed-in user is used. | ||
``` | ||
|
||
<Global /> | ||
|
||
## Remarks | ||
|
||
If no domain name or tenantId is specified, the command will return the tenant information of the currently signed in user. | ||
|
||
## Examples | ||
|
||
Get tenant information for the currently signed in user. | ||
|
||
```sh | ||
m365 tenant info get | ||
``` | ||
|
||
Get tenant information for the Contoso tenant. | ||
|
||
```sh | ||
m365 tenant info get --domainName contoso.com | ||
``` | ||
|
||
Get tenant information by id. | ||
|
||
```sh | ||
m365 tenant info get --tenantId e65b162c-6f87-4eb1-a24e-1b37d3504663 | ||
``` | ||
|
||
## Response | ||
|
||
<Tabs> | ||
<TabItem value="JSON"> | ||
|
||
```json | ||
{ | ||
"tenantId": "e65b162c-6f87-4eb1-a24e-1b37d3504663", | ||
"federationBrandName": null, | ||
"displayName": "Contoso", | ||
"defaultDomainName": "contoso.com" | ||
} | ||
``` | ||
|
||
</TabItem> | ||
<TabItem value="Text"> | ||
|
||
```text | ||
defaultDomainName : contoso.com | ||
displayName : Contoso | ||
federationBrandName : null | ||
tenantId : e65b162c-6f87-4eb1-a24e-1b37d3504663 | ||
``` | ||
|
||
</TabItem> | ||
<TabItem value="CSV"> | ||
|
||
```csv | ||
tenantId,displayName,defaultDomainName | ||
e65b162c-6f87-4eb1-a24e-1b37d3504663,Contoso,contoso.com | ||
``` | ||
|
||
</TabItem> | ||
<TabItem value="Markdown"> | ||
|
||
```md | ||
# tenant info get | ||
|
||
Date: 9/14/2023 | ||
|
||
## Contoso | ||
|
||
Property | Value | ||
---------|------- | ||
tenantId | e65b162c-6f87-4eb1-a24e-1b37d3504663 | ||
displayName | Contoso | ||
defaultDomainName | contoso.com | ||
``` | ||
|
||
</TabItem> | ||
</Tabs> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
import assert from 'assert'; | ||
import sinon from 'sinon'; | ||
import auth from '../../../../Auth.js'; | ||
import { Cli } from '../../../../cli/Cli.js'; | ||
import { CommandInfo } from '../../../../cli/CommandInfo.js'; | ||
import { Logger } from '../../../../cli/Logger.js'; | ||
import { CommandError } from '../../../../Command.js'; | ||
import request from '../../../../request.js'; | ||
import { telemetry } from '../../../../telemetry.js'; | ||
import { accessToken } from '../../../../utils/accessToken.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 './info-get.js'; | ||
|
||
describe(commands.INFO_GET, () => { | ||
const domainName = 'contoso.com'; | ||
const tenantId = 'e65b162c-6f87-4eb1-a24e-1b37d3504663'; | ||
const tenantInfoResponse = { | ||
tenantId: tenantId, | ||
federationBrandName: null, | ||
displayName: "Contoso", | ||
defaultDomainName: domainName | ||
}; | ||
|
||
let log: any[]; | ||
let loggerLogSpy: sinon.SinonSpy; | ||
let logger: Logger; | ||
let commandInfo: CommandInfo; | ||
|
||
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); | ||
if (!auth.service.accessTokens[auth.defaultResource]) { | ||
auth.service.accessTokens[auth.defaultResource] = { | ||
expiresOn: '123', | ||
accessToken: 'abc' | ||
}; | ||
} | ||
}); | ||
|
||
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.service.connected = false; | ||
}); | ||
|
||
it('has correct name', () => { | ||
assert.strictEqual(command.name, commands.INFO_GET); | ||
}); | ||
|
||
it('has a description', () => { | ||
assert.notStrictEqual(command.description, null); | ||
}); | ||
|
||
it('fails validation if the tenantId is not a valid guid', async () => { | ||
const actual = await command.validate({ options: { tenantId: 'abc' } }, commandInfo); | ||
assert.notStrictEqual(actual, true); | ||
}); | ||
|
||
it('passes validation when the tenantId is a valid GUID', async () => { | ||
const actual = await command.validate({ options: { tenantId: tenantId } }, commandInfo); | ||
assert.strictEqual(actual, true); | ||
}); | ||
|
||
it('fails validation if both domainName and tenantId are specified', async () => { | ||
const actual = await command.validate({ options: { domainName: domainName, tenantId: tenantId } }, commandInfo); | ||
assert.notStrictEqual(actual, true); | ||
}); | ||
|
||
it('gets tenant information for the currently signed in user if no domain name or tenantId is passed', async () => { | ||
sinon.stub(accessToken, 'getUserNameFromAccessToken').callsFake(() => { | ||
return '[email protected]'; | ||
}); | ||
|
||
sinon.stub(request, 'get').callsFake(async (opts) => { | ||
if (opts.url === `https://graph.microsoft.com/v1.0/tenantRelationships/findTenantInformationByDomainName(domainName='contoso.com')`) { | ||
return tenantInfoResponse; | ||
} | ||
|
||
throw 'Invalid Request'; | ||
}); | ||
|
||
await command.action(logger, { options: { verbose: true } }); | ||
assert(loggerLogSpy.calledOnceWithExactly(tenantInfoResponse)); | ||
sinonUtil.restore(accessToken.getUserNameFromAccessToken); | ||
}); | ||
|
||
it('gets tenant information with correct domain name', async () => { | ||
sinon.stub(request, 'get').callsFake(async (opts) => { | ||
if (opts.url === `https://graph.microsoft.com/v1.0/tenantRelationships/findTenantInformationByDomainName(domainName='contoso.com')`) { | ||
return tenantInfoResponse; | ||
} | ||
|
||
throw 'Invalid Request'; | ||
}); | ||
|
||
await command.action(logger, { options: { verbose: true, domainName: domainName } }); | ||
assert(loggerLogSpy.calledOnceWithExactly(tenantInfoResponse)); | ||
}); | ||
|
||
it('gets tenant information with correct tenant id', async () => { | ||
sinon.stub(request, 'get').callsFake(async (opts) => { | ||
if (opts.url === `https://graph.microsoft.com/v1.0/tenantRelationships/findTenantInformationByTenantId(tenantId='e65b162c-6f87-4eb1-a24e-1b37d3504663')`) { | ||
return tenantInfoResponse; | ||
} | ||
|
||
throw 'Invalid Request'; | ||
}); | ||
|
||
await command.action(logger, { options: { verbose: true, tenantId: tenantId } }); | ||
assert(loggerLogSpy.calledOnceWithExactly(tenantInfoResponse)); | ||
}); | ||
|
||
it('handles error when trying to retrieve information for a non-existant tenant by id', async () => { | ||
sinon.stub(request, 'get').callsFake(async (opts) => { | ||
if (opts.url === `https://graph.microsoft.com/v1.0/tenantRelationships/findTenantInformationByTenantId(tenantId='e65b162c-6f87-4eb1-a24e-1b37d3504663')`) { | ||
throw { | ||
"error": { | ||
"code": "Directory_ObjectNotFound", | ||
"message": "Unable to read the company information from the directory.", | ||
"innerError": { | ||
"date": "2023-09-14T14:07:47", | ||
"request-id": "3b91132c-5c79-454b-8dd4-06964e788a24", | ||
"client-request-id": "2147e6c6-8036-cc2f-f4d0-eec89dbc48d7" | ||
} | ||
} | ||
}; | ||
} | ||
|
||
throw 'Invalid Request'; | ||
}); | ||
|
||
await assert.rejects(command.action(logger, { options: { tenantId: tenantId } } as any), new CommandError("Unable to read the company information from the directory.")); | ||
}); | ||
|
||
it('handles error when trying to retrieve information for a non-existant tenant by domain name', async () => { | ||
sinon.stub(request, 'get').callsFake(async (opts) => { | ||
if (opts.url === `https://graph.microsoft.com/v1.0/tenantRelationships/findTenantInformationByDomainName(domainName='xyz.com')`) { | ||
throw { | ||
"error": { | ||
"code": "Directory_ObjectNotFound", | ||
"message": "Unable to read the company information from the directory.", | ||
"innerError": { | ||
"date": "2023-09-14T14:07:47", | ||
"request-id": "3b91132c-5c79-454b-8dd4-06964e788a24", | ||
"client-request-id": "2147e6c6-8036-cc2f-f4d0-eec89dbc48d7" | ||
} | ||
} | ||
}; | ||
} | ||
|
||
throw 'Invalid Request'; | ||
}); | ||
|
||
await assert.rejects(command.action(logger, { options: { domainName: 'xyz.com' } } as any), new CommandError("Unable to read the company information from the directory.")); | ||
}); | ||
|
||
it('correctly handles random API error', async () => { | ||
sinon.stub(request, 'get').rejects(new Error('An error has occurred')); | ||
await assert.rejects(command.action(logger, { options: { domainName: 'xyz.com' } } as any), new CommandError('An error has occurred')); | ||
}); | ||
}); |
Oops, something went wrong.