Skip to content

Commit 58ae9e6

Browse files
committed
Adds 'purview retentionlabel get' command. Closes pnp#4146
1 parent 3406d28 commit 58ae9e6

File tree

5 files changed

+308
-0
lines changed

5 files changed

+308
-0
lines changed
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# purview retentionlabel get
2+
3+
Get a retention label
4+
5+
## Usage
6+
7+
```sh
8+
m365 purview retentionlabel get [options]
9+
```
10+
11+
## Options
12+
13+
`-i, --id <id>`
14+
: The Id of the retention label.
15+
16+
--8<-- "docs/cmd/_global.md"
17+
18+
## Examples
19+
20+
Get a retention label
21+
22+
```sh
23+
m365 purview retentionlabel get --id c37d695e-d581-4ae9-82a0-9364eba4291e
24+
```
25+
26+
## Remarks
27+
28+
!!! attention
29+
This command is based on a Microsoft Graph API that is currently in preview and is subject to change once the API reached general availability.
30+
31+
## Response
32+
33+
34+
=== "JSON"
35+
36+
```json
37+
{
38+
"displayName": "TEST LABEL",
39+
"descriptionForAdmins": "",
40+
"descriptionForUsers": "",
41+
"isInUse": false,
42+
"retentionTrigger": "dateCreated",
43+
"behaviorDuringRetentionPeriod": "retain",
44+
"actionAfterRetentionPeriod": "delete",
45+
"createdDateTime": "2022-12-12T15:14:53Z",
46+
"lastModifiedDateTime": "2022-12-12T15:43:06Z",
47+
"labelToBeApplied": "",
48+
"defaultRecordBehavior": "startLocked",
49+
"id": "5c8af2e2-b489-4fa0-9c16-180180245ac8",
50+
"retentionDuration": {
51+
"days": 100
52+
},
53+
"createdBy": {
54+
"user": {
55+
"id": null,
56+
"displayName": "John Doe"
57+
}
58+
},
59+
"lastModifiedBy": {
60+
"user": {
61+
"id": null,
62+
"displayName": "John Doe"
63+
}
64+
},
65+
"dispositionReviewStages": []
66+
}
67+
```
68+
69+
=== "Text"
70+
71+
```text
72+
actionAfterRetentionPeriod : delete
73+
behaviorDuringRetentionPeriod: retain
74+
createdBy : {"user":{"id":null,"displayName":"John Doe"}}
75+
createdDateTime : 2022-12-12T15:14:53Z
76+
defaultRecordBehavior : startLocked
77+
descriptionForAdmins :
78+
descriptionForUsers :
79+
displayName : TEST LABEL
80+
dispositionReviewStages : []
81+
id : 5c8af2e2-b489-4fa0-9c16-180180245ac8
82+
isInUse : false
83+
labelToBeApplied :
84+
lastModifiedBy : {"user":{"id":null,"displayName":"John Doe"}}
85+
lastModifiedDateTime : 2022-12-12T15:43:06Z
86+
retentionDuration : {"days":100}
87+
retentionTrigger : dateCreated
88+
```
89+
90+
=== "CSV"
91+
92+
```csv
93+
displayName,descriptionForAdmins,descriptionForUsers,isInUse,retentionTrigger,behaviorDuringRetentionPeriod,actionAfterRetentionPeriod,createdDateTime,lastModifiedDateTime,labelToBeApplied,defaultRecordBehavior,id,retentionDuration,createdBy,lastModifiedBy,dispositionReviewStages
94+
TEST LABEL,,,,dateCreated,retain,delete,2022-12-12T15:14:53Z,2022-12-12T15:43:06Z,,startLocked,5c8af2e2-b489-4fa0-9c16-180180245ac8,"{""days"":100}","{""user"":{""id"":null,""displayName"":""John Doe""}}","{""user"":{""id"":null,""displayName"":""John Doe""}}",[]
95+
```

docs/mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ nav:
299299
- tenant settings list: cmd/pp/tenant/tenant-settings-list.md
300300
- Purview (purview):
301301
- retentionlabel:
302+
- retentionlabel get: cmd/purview/retentionlabel/retentionlabel-get.md
302303
- retentionlabel list: cmd/purview/retentionlabel/retentionlabel-list.md
303304
- retentionlabel remove: cmd/purview/retentionlabel/retentionlabel-remove.md
304305
- retentionlabel set: cmd/purview/retentionlabel/retentionlabel-set.md

src/m365/purview/commands.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const prefix: string = 'purview';
22

33
export default {
4+
RETENTIONLABEL_GET: `${prefix} retentionlabel get`,
45
RETENTIONLABEL_LIST: `${prefix} retentionlabel list`,
56
RETENTIONLABEL_REMOVE: `${prefix} retentionlabel remove`,
67
RETENTIONLABEL_SET: `${prefix} retentionlabel set`
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import * as assert from 'assert';
2+
import * as sinon from 'sinon';
3+
import { telemetry } from '../../../../telemetry';
4+
import auth from '../../../../Auth';
5+
import { Logger } from '../../../../cli/Logger';
6+
import Command, { CommandError } from '../../../../Command';
7+
import request from '../../../../request';
8+
import { pid } from '../../../../utils/pid';
9+
import { sinonUtil } from '../../../../utils/sinonUtil';
10+
import commands from '../../commands';
11+
import { CommandInfo } from '../../../../cli/CommandInfo';
12+
import { Cli } from '../../../../cli/Cli';
13+
const command: Command = require('./retentionlabel-get');
14+
15+
describe(commands.RETENTIONLABEL_GET, () => {
16+
17+
const retentionLabelId = '5c8af2e2-b489-4fa0-9c16-180180245ac8';
18+
const retentionLabelGetResponse = {
19+
"displayName": "TEST LABEL",
20+
"descriptionForAdmins": "",
21+
"descriptionForUsers": "",
22+
"isInUse": false,
23+
"retentionTrigger": "dateCreated",
24+
"behaviorDuringRetentionPeriod": "retain",
25+
"actionAfterRetentionPeriod": "delete",
26+
"createdDateTime": "2022-12-12T15:14:53Z",
27+
"lastModifiedDateTime": "2022-12-12T15:43:06Z",
28+
"labelToBeApplied": "",
29+
"defaultRecordBehavior": "startLocked",
30+
"id": retentionLabelId,
31+
"retentionDuration": {
32+
"days": 100
33+
},
34+
"createdBy": {
35+
"user": {
36+
"id": null,
37+
"displayName": "John Doe"
38+
}
39+
},
40+
"lastModifiedBy": {
41+
"user": {
42+
"id": null,
43+
"displayName": "John Doe"
44+
}
45+
},
46+
"dispositionReviewStages": []
47+
};
48+
49+
let log: string[];
50+
let logger: Logger;
51+
let loggerLogSpy: sinon.SinonSpy;
52+
let commandInfo: CommandInfo;
53+
54+
before(() => {
55+
sinon.stub(auth, 'restoreAuth').callsFake(() => Promise.resolve());
56+
sinon.stub(telemetry, 'trackEvent').callsFake(() => { });
57+
sinon.stub(pid, 'getProcessName').callsFake(() => '');
58+
auth.service.connected = true;
59+
commandInfo = Cli.getCommandInfo(command);
60+
});
61+
62+
beforeEach(() => {
63+
log = [];
64+
logger = {
65+
log: (msg: string) => {
66+
log.push(msg);
67+
},
68+
logRaw: (msg: string) => {
69+
log.push(msg);
70+
},
71+
logToStderr: (msg: string) => {
72+
log.push(msg);
73+
}
74+
};
75+
loggerLogSpy = sinon.spy(logger, 'log');
76+
(command as any).items = [];
77+
});
78+
79+
afterEach(() => {
80+
sinonUtil.restore([
81+
request.get
82+
]);
83+
});
84+
85+
after(() => {
86+
sinonUtil.restore([
87+
auth.restoreAuth,
88+
telemetry.trackEvent,
89+
pid.getProcessName
90+
]);
91+
auth.service.connected = false;
92+
});
93+
94+
it('has correct name', () => {
95+
assert.strictEqual(command.name, commands.RETENTIONLABEL_GET);
96+
});
97+
98+
it('has a description', () => {
99+
assert.notStrictEqual(command.description, null);
100+
});
101+
102+
it('retrieves retention label specified by id', async () => {
103+
sinon.stub(request, 'get').callsFake(async (opts) => {
104+
if (opts.url === `https://graph.microsoft.com/beta/security/labels/retentionLabels/${retentionLabelId}`) {
105+
return retentionLabelGetResponse;
106+
}
107+
108+
throw 'Invalid request';
109+
});
110+
111+
await command.action(logger, { options: { id: retentionLabelId, verbose: true } });
112+
assert(loggerLogSpy.calledWith(retentionLabelGetResponse));
113+
});
114+
115+
it('handles error when retention label by id is not found', async () => {
116+
sinon.stub(request, 'get').callsFake(async (opts) => {
117+
if (opts.url === `https://graph.microsoft.com/beta/security/labels/retentionLabels/${retentionLabelId}`) {
118+
throw `Error: The operation couldn't be performed because object '${retentionLabelId}' couldn't be found on 'FfoConfigurationSession'.`;
119+
}
120+
121+
throw 'Invalid request';
122+
});
123+
124+
await assert.rejects(command.action(logger, { options: { id: retentionLabelId } }), new CommandError(`Error: The operation couldn't be performed because object '${retentionLabelId}' couldn't be found on 'FfoConfigurationSession'.`));
125+
});
126+
127+
it('fails validation if id is not a valid GUID', async () => {
128+
const actual = await command.validate({ options: { id: 'invalid' } }, commandInfo);
129+
assert.notStrictEqual(actual, true);
130+
});
131+
132+
it('passes validation if a correct id is entered', async () => {
133+
const actual = await command.validate({ options: { id: retentionLabelId } }, commandInfo);
134+
assert.strictEqual(actual, true);
135+
});
136+
});
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { Logger } from '../../../../cli/Logger';
2+
import GraphCommand from '../../../base/GraphCommand';
3+
import GlobalOptions from '../../../../GlobalOptions';
4+
import commands from '../../commands';
5+
import request from '../../../../request';
6+
import { AxiosRequestConfig } from 'axios';
7+
import { validation } from '../../../../utils/validation';
8+
9+
interface CommandArgs {
10+
options: Options;
11+
}
12+
13+
interface Options extends GlobalOptions {
14+
id: string;
15+
}
16+
17+
class PurviewRetentionLabelGetCommand extends GraphCommand {
18+
public get name(): string {
19+
return commands.RETENTIONLABEL_GET;
20+
}
21+
22+
public get description(): string {
23+
return 'Retrieve the specified retention label';
24+
}
25+
26+
constructor() {
27+
super();
28+
29+
this.#initOptions();
30+
this.#initValidators();
31+
}
32+
33+
#initOptions(): void {
34+
this.options.unshift(
35+
{
36+
option: '-i, --id <id>'
37+
}
38+
);
39+
}
40+
41+
#initValidators(): void {
42+
this.validators.push(
43+
async (args: CommandArgs) => {
44+
if (!validation.isValidGuid(args.options.id)) {
45+
return `'${args.options.id}' is not a valid GUID.`;
46+
}
47+
48+
return true;
49+
}
50+
);
51+
}
52+
53+
public async commandAction(logger: Logger, args: CommandArgs): Promise<void> {
54+
try {
55+
if (this.verbose) {
56+
logger.logToStderr(`Retrieving retention label with id ${args.options.id}`);
57+
}
58+
59+
const requestOptions: AxiosRequestConfig = {
60+
url: `${this.resource}/beta/security/labels/retentionLabels/${args.options.id}`,
61+
headers: {
62+
accept: 'application/json;odata.metadata=none'
63+
},
64+
responseType: 'json'
65+
};
66+
const res: any = await request.get<any>(requestOptions);
67+
logger.log(res);
68+
}
69+
catch (err: any) {
70+
this.handleRejectedODataJsonPromise(err);
71+
}
72+
}
73+
}
74+
75+
module.exports = new PurviewRetentionLabelGetCommand();

0 commit comments

Comments
 (0)