Skip to content

Commit

Permalink
Adds the 'spo roledefinition list' command. Closes #3237
Browse files Browse the repository at this point in the history
  • Loading branch information
Adam-it authored and waldekmastykarz committed May 13, 2022
1 parent 99da27d commit b59b659
Show file tree
Hide file tree
Showing 5 changed files with 285 additions and 0 deletions.
24 changes: 24 additions & 0 deletions docs/docs/cmd/spo/roledefinition/roledefinition-list.md
@@ -0,0 +1,24 @@
# spo roledefinition list

Gets list of role definitions for the specified site

## Usage

```sh
m365 spo roledefinition list [options]
```

## Options

`-u, --webUrl <webUrl>`
: URL of the site for which to retrieve role definitions

--8<-- "docs/cmd/_global.md"

## Examples

Return list of role definitions for site _https://contoso.sharepoint.com/sites/project-x_

```sh
m365 spo roledefinition list --webUrl https://contoso.sharepoint.com/sites/project-x
```
2 changes: 2 additions & 0 deletions docs/mkdocs.yml
Expand Up @@ -442,6 +442,8 @@ nav:
- report siteusagepages: 'cmd/spo/report/report-siteusagepages.md'
- report siteusagesitecounts: 'cmd/spo/report/report-siteusagesitecounts.md'
- report siteusagestorage: 'cmd/spo/report/report-siteusagestorage.md'
- roledefinition:
- roledefinition list: 'cmd/spo/roledefinition/roledefinition-list.md'
- serviceprincipal:
- serviceprincipal grant add: 'cmd/spo/serviceprincipal/serviceprincipal-grant-add.md'
- serviceprincipal grant list: 'cmd/spo/serviceprincipal/serviceprincipal-grant-list.md'
Expand Down
1 change: 1 addition & 0 deletions src/m365/spo/commands.ts
Expand Up @@ -161,6 +161,7 @@ export default {
REPORT_SITEUSAGEPAGES: `${prefix} report siteusagepages`,
REPORT_SITEUSAGESITECOUNTS: `${prefix} report siteusagesitecounts`,
REPORT_SITEUSAGESTORAGE: `${prefix} report siteusagestorage`,
ROLEDEFINITION_LIST: `${prefix} roledefinition list`,
SEARCH: `${prefix} search`,
SERVICEPRINCIPAL_GRANT_ADD: `${prefix} serviceprincipal grant add`,
SERVICEPRINCIPAL_GRANT_LIST: `${prefix} serviceprincipal grant list`,
Expand Down
191 changes: 191 additions & 0 deletions src/m365/spo/commands/roledefinition/roledefinition-list.spec.ts
@@ -0,0 +1,191 @@
import * as assert from 'assert';
import * as sinon from 'sinon';
import appInsights from '../../../../appInsights';
import auth from '../../../../Auth';
import { Logger } from '../../../../cli';
import Command, { CommandError } from '../../../../Command';
import request from '../../../../request';
import { sinonUtil } from '../../../../utils';
import commands from '../../commands';
const command: Command = require('./roledefinition-list');

describe(commands.ROLEDEFINITION_LIST, () => {
let log: any[];
let logger: Logger;
let loggerLogSpy: sinon.SinonSpy;

before(() => {
sinon.stub(auth, 'restoreAuth').callsFake(() => Promise.resolve());
sinon.stub(appInsights, 'trackEvent').callsFake(() => { });
auth.service.connected = true;
});

beforeEach(() => {
log = [];
logger = {
log: (msg: string) => {
log.push(msg);
},
logRaw: (msg: string) => {
log.push(msg);
},
logToStderr: (msg: string) => {
log.push(msg);
}
};
loggerLogSpy = sinon.spy(logger, 'log');
});

afterEach(() => {
sinonUtil.restore([
request.get
]);
});

after(() => {
sinonUtil.restore([
auth.restoreAuth,
appInsights.trackEvent
]);
auth.service.connected = false;
});

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

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

it('supports debug mode', () => {
const options = command.options();
let containsDebugOption = false;
options.forEach(o => {
if (o.option === '--debug') {
containsDebugOption = true;
}
});
assert(containsDebugOption);
});

it('defines correct properties for the default output', () => {
assert.deepStrictEqual(command.defaultProperties(), ['Id', 'Name']);
});

it('fails validation if the webUrl option is not a valid SharePoint site URL', () => {
const actual = command.validate({ options: { webUrl: 'foo' } });
assert.notStrictEqual(actual, true);
});

it('passes validation if the webUrl option is a valid SharePoint site URL', () => {
const actual = command.validate({ options: { webUrl: 'https://contoso.sharepoint.com' } });
assert.strictEqual(actual, true);
});

it('list role definitions handles reject request correctly', (done) => {
const err = 'request rejected';
sinon.stub(request, 'get').callsFake((opts) => {
if ((opts.url as string).indexOf('/_api/web/roledefinitions') > -1) {
return Promise.reject(err);
}

return Promise.reject('Invalid request');
});

command.action(logger, {
options: {
debug: true,
webUrl: 'https://contoso.sharepoint.com'
}
}, (error?: any) => {
try {
assert.strictEqual(JSON.stringify(error), JSON.stringify(new CommandError(err)));
done();
}
catch (e) {
done(e);
}
});
});

it('lists all role definitions from web', (done) => {
sinon.stub(request, 'get').callsFake((opts) => {
if ((opts.url as string).indexOf('/_api/web/roledefinitions') > -1) {
return Promise.resolve({
value:
[
{
"BasePermissions": {
"High": "2147483647",
"Low": "4294967295"
},
"Description": "Has full control.",
"Hidden": false,
"Id": 1073741829,
"Name": "Full Control",
"Order": 1,
"RoleTypeKind": 5
},
{
"BasePermissions": {
"High": "432",
"Low": "1012866047"
},
"Description": "Can view, add, update, delete, approve, and customize.",
"Hidden": false,
"Id": 1073741828,
"Name": "Design",
"Order": 32,
"RoleTypeKind": 4
}
]
});
}
return Promise.reject('Invalid request');
});

command.action(logger, {
options: {
output: 'json',
debug: true,
webUrl: 'https://contoso.sharepoint.com'
}
}, () => {
try {
assert(loggerLogSpy.calledWith(
[
{
"BasePermissions": {
"High": "2147483647",
"Low": "4294967295"
},
"Description": "Has full control.",
"Hidden": false,
"Id": 1073741829,
"Name": "Full Control",
"Order": 1,
"RoleTypeKind": 5
},
{
"BasePermissions": {
"High": "432",
"Low": "1012866047"
},
"Description": "Can view, add, update, delete, approve, and customize.",
"Hidden": false,
"Id": 1073741828,
"Name": "Design",
"Order": 32,
"RoleTypeKind": 4
}
]
));
done();
}
catch (e) {
done(e);
}
});
});
});
67 changes: 67 additions & 0 deletions src/m365/spo/commands/roledefinition/roledefinition-list.ts
@@ -0,0 +1,67 @@
import { Logger } from '../../../../cli';
import { CommandOption } from '../../../../Command';
import GlobalOptions from '../../../../GlobalOptions';
import request from '../../../../request';
import { validation } from '../../../../utils';
import SpoCommand from '../../../base/SpoCommand';
import commands from '../../commands';

interface CommandArgs {
options: Options;
}

interface Options extends GlobalOptions {
webUrl: string;
}

class SpoRoleDefinitionListCommand extends SpoCommand {
public get name(): string {
return commands.ROLEDEFINITION_LIST;
}

public get description(): string {
return 'Gets list of role definitions for the specified site';
}

public defaultProperties(): string[] | undefined {
return ['Id', 'Name'];
}

public commandAction(logger: Logger, args: CommandArgs, cb: () => void): void {
if (this.verbose) {
logger.logToStderr(`Getting role definitions list from ${args.options.webUrl}...`);
}

const requestOptions: any = {
url: `${args.options.webUrl}/_api/web/roledefinitions`,
headers: {
'accept': 'application/json;odata=nometadata'
},
responseType: 'json'
};

request
.get<{ value: any[] }>(requestOptions)
.then((response: { value: any[] }): void => {
logger.log(response.value);
cb();
}, (err: any): void => this.handleRejectedODataJsonPromise(err, logger, cb));
}

public options(): CommandOption[] {
const options: CommandOption[] = [
{
option: '-u, --webUrl <webUrl>'
}
];

const parentOptions: CommandOption[] = super.options();
return options.concat(parentOptions);
}

public validate(args: CommandArgs): boolean | string {
return validation.isValidSharePointUrl(args.options.webUrl);
}
}

module.exports = new SpoRoleDefinitionListCommand();

0 comments on commit b59b659

Please sign in to comment.