-
Notifications
You must be signed in to change notification settings - Fork 329
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
446 additions
and
0 deletions.
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,89 @@ | ||
import Global from '/docs/cmd/_global.mdx'; | ||
import Tabs from '@theme/Tabs'; | ||
import TabItem from '@theme/TabItem'; | ||
|
||
# spo tenant site membership list | ||
|
||
Retrieve information about default site groups' membership | ||
|
||
## Usage | ||
|
||
```sh | ||
m365 spo tenant site membership list [options] | ||
``` | ||
|
||
## Options | ||
|
||
```md definition-list | ||
`-u, --siteUrl <siteUrl>` | ||
: The URL of the site. | ||
|
||
`-r, --role [role]` | ||
: Filter the results to include only users with the specified roles: 'Owner', 'Member', or 'Visitor'.. | ||
|
||
``` | ||
|
||
<Global /> | ||
|
||
## Remarks | ||
|
||
To execute this command successfully, ensure you are logged in to the CLI for M365 with an account that has SharePoint admin permissions. For other scenarios, refer to the `spo web get --withGroups` and `spo group member list` commands. | ||
|
||
## Examples | ||
|
||
Retrieves information about default site groups' owners, members, and visitors of the site. | ||
|
||
```sh | ||
m365 spo tenant site membership list --siteUrl https://contoso.sharepoint.com | ||
``` | ||
|
||
Retrieves information about site owners. | ||
|
||
```sh | ||
m365 spo tenant site membership list --siteUrl https://contoso.sharepoint.com --role Owner | ||
``` | ||
|
||
## Response | ||
|
||
<Tabs> | ||
<TabItem value="JSON"> | ||
|
||
```json | ||
{ | ||
"AssociatedOwnerGroup": [ | ||
{ | ||
"email": "[email protected]", | ||
"loginName": "i:0#.f|membership|[email protected]", | ||
"name": "UserName", | ||
"userPrincipalName": "[email protected]" | ||
} | ||
], | ||
"AssociatedMemberGroup": [ | ||
{ | ||
"email": "[email protected]", | ||
"loginName": "i:0#.f|membership|[email protected]", | ||
"name": "internal", | ||
"userPrincipalName": "[email protected]" | ||
} | ||
], | ||
"AssociatedVisitorGroup": [ | ||
{ | ||
"email": "", | ||
"loginName": "c:0-.f|rolemanager|spo-grid-all-users/dc109ffd-4298-487e-9cbc-6b9b1a2cd3e2", | ||
"name": "Everyone except external users", | ||
"userPrincipalName": null | ||
} | ||
] | ||
} | ||
``` | ||
</TabItem> | ||
<TabItem value="Text"> | ||
|
||
```text | ||
AssociatedMemberGroup : [{"email":"[email protected]","loginName":"i:0#.f|membership|[email protected]","name":"internal","userPrincipalName":"[email protected]"}] | ||
AssociatedOwnerGroup : [{"email":"[email protected]","loginName":"i:0#.f|membership|[email protected]","name":"UserName","userPrincipalName":"[email protected]"}] | ||
AssociatedVisitorGroup: [{"email":"","loginName":"c:0-.f|rolemanager|spo-grid-all-users/dc109ffd-4298-487e-9cbc-6b9b1a2cd3e2","name":"Everyone except external users","userPrincipalName":null}] | ||
``` | ||
|
||
</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
196 changes: 196 additions & 0 deletions
196
src/m365/spo/commands/tenant/tenant-site-membership-list.spec.ts
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,196 @@ | ||
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 { spo } from '../../../../utils/spo.js'; | ||
import commands from '../../commands.js'; | ||
import command from './tenant-site-membership-list.js'; | ||
import { CommandInfo } from '../../../../cli/CommandInfo.js'; | ||
import { cli } from '../../../../cli/cli.js'; | ||
|
||
describe(commands.TENANT_SITE_MEMBERSHIP_LIST, () => { | ||
let log: any[]; | ||
let logger: Logger; | ||
let loggerLogSpy: sinon.SinonSpy; | ||
let commandInfo: CommandInfo; | ||
const membershipList = [ | ||
{ | ||
email: '[email protected]', | ||
loginName: 'i:0#.f|membership|[email protected]', | ||
name: 'user1DisplayName', | ||
userPrincipalName: 'user1loginName' | ||
}, | ||
{ | ||
email: '[email protected]', | ||
loginName: 'i:0#.f|membership|[email protected]', | ||
name: 'user2DisplayName', | ||
userPrincipalName: 'user2loginName' | ||
} | ||
]; | ||
const adminUrl = 'https://contoso-admin.sharepoint.com'; | ||
const siteUrl = 'https://contoso.sharepoint.com/sites/site'; | ||
const siteId = '00000000-0000-0000-0000-000000000010'; | ||
|
||
before(() => { | ||
sinon.stub(auth, 'restoreAuth').resolves(); | ||
sinon.stub(telemetry, 'trackEvent').returns(); | ||
sinon.stub(pid, 'getProcessName').returns(''); | ||
sinon.stub(session, 'getId').returns(''); | ||
sinon.stub(spo, 'getRequestDigest').resolves({ | ||
FormDigestValue: 'ABC', | ||
FormDigestTimeoutSeconds: 1800, | ||
FormDigestExpiresAt: new Date(), | ||
WebFullUrl: 'https://contoso.sharepoint.com' | ||
}); | ||
auth.connection.active = true; | ||
auth.connection.spoUrl = 'https://contoso.sharepoint.com'; | ||
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, | ||
request.post | ||
]); | ||
}); | ||
|
||
after(() => { | ||
sinon.restore(); | ||
auth.connection.active = false; | ||
auth.connection.spoUrl = undefined; | ||
}); | ||
|
||
it('has correct name', () => { | ||
assert.strictEqual(command.name, commands.TENANT_SITE_MEMBERSHIP_LIST); | ||
}); | ||
|
||
it('has a description', () => { | ||
assert.notStrictEqual(command.description, null); | ||
}); | ||
|
||
it('fails validation if the siteUrl option is not a valid SharePoint URL', () => { | ||
const actual = command.validate({ options: { siteUrl: 'foo' } }, commandInfo); | ||
assert.notStrictEqual(actual, true); | ||
}); | ||
|
||
it('fails validation if the role option is not a valid role', () => { | ||
const actual = command.validate({ options: { siteUrl: 'https://contoso.sharepoint.com', role: 'foo' } }, commandInfo); | ||
assert.notStrictEqual(actual, true); | ||
}); | ||
|
||
it('lists all site membership groups', async () => { | ||
sinon.stub(request, 'get').callsFake(async (opts) => { | ||
if (opts.url === `${adminUrl}/_api/SPO.Tenant/sites/GetSiteUserGroups?siteId=%27${siteId}%27&userGroupIds=[0,1,2]`) { | ||
return { value: [{ userGroup: membershipList }, { userGroup: membershipList }, { userGroup: membershipList }] }; | ||
}; | ||
|
||
if (opts.url === `https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/site?$select=id`) { | ||
return { id: `contoso.sharepoint.com,${siteId},fb0a066f-c10f-4734-94d1-f896de4aa484` }; | ||
} | ||
|
||
throw 'Invalid request'; | ||
}); | ||
|
||
await command.action(logger, { options: { siteUrl: siteUrl } }); | ||
assert(loggerLogSpy.calledWith({ | ||
AssociatedOwnerGroup: membershipList, | ||
AssociatedMemberGroup: membershipList, | ||
AssociatedVisitorGroup: membershipList | ||
})); | ||
}); | ||
|
||
it('lists all site membership groups - just Owners group', async () => { | ||
sinon.stub(request, 'get').callsFake(async (opts) => { | ||
if (opts.url === `${adminUrl}/_api/SPO.Tenant/sites/GetSiteUserGroups?siteId=%27${siteId}%27&userGroupIds=[0]`) { | ||
return { value: [{ userGroup: membershipList }] }; | ||
}; | ||
|
||
if (opts.url === `https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/site?$select=id`) { | ||
return { id: `contoso.sharepoint.com,${siteId},fb0a066f-c10f-4734-94d1-f896de4aa484` }; | ||
} | ||
|
||
throw 'Invalid request'; | ||
}); | ||
|
||
await command.action(logger, { options: { siteUrl: siteUrl, role: "Owner" } }); | ||
assert(loggerLogSpy.calledWith({ | ||
AssociatedOwnerGroup: membershipList | ||
})); | ||
}); | ||
|
||
it('lists all site membership groups - just Members group', async () => { | ||
sinon.stub(request, 'get').callsFake(async (opts) => { | ||
if (opts.url === `${adminUrl}/_api/SPO.Tenant/sites/GetSiteUserGroups?siteId=%27${siteId}%27&userGroupIds=[1]`) { | ||
return { value: [{ userGroup: membershipList }] }; | ||
}; | ||
|
||
if (opts.url === `https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/site?$select=id`) { | ||
return { id: `contoso.sharepoint.com,${siteId},fb0a066f-c10f-4734-94d1-f896de4aa484` }; | ||
} | ||
|
||
throw 'Invalid request'; | ||
}); | ||
|
||
await command.action(logger, { options: { siteUrl: siteUrl, role: "Member" } }); | ||
assert(loggerLogSpy.calledWith({ | ||
AssociatedMemberGroup: membershipList | ||
})); | ||
}); | ||
|
||
it('lists all site membership groups - just Visitors group', async () => { | ||
sinon.stub(request, 'get').callsFake(async (opts) => { | ||
if (opts.url === `${adminUrl}/_api/SPO.Tenant/sites/GetSiteUserGroups?siteId=%27${siteId}%27&userGroupIds=[2]`) { | ||
return { value: [{ userGroup: membershipList }] }; | ||
}; | ||
|
||
if (opts.url === `https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/site?$select=id`) { | ||
return { id: `contoso.sharepoint.com,${siteId},fb0a066f-c10f-4734-94d1-f896de4aa484` }; | ||
} | ||
|
||
throw 'Invalid request'; | ||
}); | ||
|
||
await command.action(logger, { options: { siteUrl: siteUrl, role: "Visitor" } }); | ||
assert(loggerLogSpy.calledWith({ | ||
AssociatedVisitorGroup: membershipList | ||
})); | ||
}); | ||
|
||
it('correctly handles error when site is not found for specified site URL', async () => { | ||
sinon.stub(request, 'get').callsFake(async (opts) => { | ||
if (opts.url === `${adminUrl}/_api/SPO.Tenant/sites/GetSiteUserGroups?siteId=%27${siteId}%27&userGroupIds=[2]`) { | ||
return { value: [{ userGroup: membershipList }] }; | ||
}; | ||
|
||
if (opts.url === `https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/site?$select=id`) { | ||
return { id: 'Incorrect ID' }; | ||
} | ||
|
||
throw 'Invalid request'; | ||
}); | ||
|
||
await assert.rejects(command.action(logger, { options: { siteUrl: siteUrl } }), new CommandError(`Site with URL ${siteUrl} not found`)); | ||
}); | ||
}); |
Oops, something went wrong.