@pnp/cli-microsoft365 5.3.0-beta.4033f50 → 5.3.0-beta.421b58b

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/Auth.js CHANGED
@@ -540,6 +540,11 @@ class Auth {
540
540
  // we need to use https://management.azure.com/ instead
541
541
  resource = 'https://management.azure.com/';
542
542
  }
543
+ if (resource === 'https://api.powerbi.com') {
544
+ // api.powerbi.com is not a valid resource
545
+ // we need to use https://analysis.windows.net/powerbi/api instead
546
+ resource = 'https://analysis.windows.net/powerbi/api';
547
+ }
543
548
  return resource;
544
549
  }
545
550
  getServiceConnectionInfo() {
@@ -1,4 +1,13 @@
1
1
  "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
2
11
  Object.defineProperty(exports, "__esModule", { value: true });
3
12
  const fs = require("fs");
4
13
  const uuid_1 = require("uuid");
@@ -31,6 +40,9 @@ class AadAppAddCommand extends GraphCommand_1.default {
31
40
  telemetryProps.scopeName = typeof args.options.scopeName !== 'undefined';
32
41
  telemetryProps.uri = typeof args.options.uri !== 'undefined';
33
42
  telemetryProps.withSecret = args.options.withSecret;
43
+ telemetryProps.certificateFile = typeof args.options.certificateFile !== 'undefined';
44
+ telemetryProps.certificateBase64Encoded = typeof args.options.certificateBase64Encoded !== 'undefined';
45
+ telemetryProps.certificateDisplayName = typeof args.options.certificateDisplayName !== 'undefined';
34
46
  return telemetryProps;
35
47
  }
36
48
  commandAction(logger, args, cb) {
@@ -66,43 +78,55 @@ class AadAppAddCommand extends GraphCommand_1.default {
66
78
  }, (rawRes) => this.handleRejectedODataJsonPromise(rawRes, logger, cb));
67
79
  }
68
80
  createAppRegistration(args, apis, logger) {
69
- const applicationInfo = {
70
- displayName: args.options.name,
71
- signInAudience: args.options.multitenant ? 'AzureADMultipleOrgs' : 'AzureADMyOrg'
72
- };
73
- if (!applicationInfo.displayName && this.manifest) {
74
- applicationInfo.displayName = this.manifest.name;
75
- }
76
- this.appName = applicationInfo.displayName;
77
- if (apis.length > 0) {
78
- applicationInfo.requiredResourceAccess = apis;
79
- }
80
- if (args.options.redirectUris) {
81
- applicationInfo[args.options.platform] = {
82
- redirectUris: args.options.redirectUris.split(',').map(u => u.trim())
81
+ return __awaiter(this, void 0, void 0, function* () {
82
+ const applicationInfo = {
83
+ displayName: args.options.name,
84
+ signInAudience: args.options.multitenant ? 'AzureADMultipleOrgs' : 'AzureADMyOrg'
83
85
  };
84
- }
85
- if (args.options.implicitFlow) {
86
- if (!applicationInfo.web) {
87
- applicationInfo.web = {};
86
+ if (!applicationInfo.displayName && this.manifest) {
87
+ applicationInfo.displayName = this.manifest.name;
88
+ }
89
+ this.appName = applicationInfo.displayName;
90
+ if (apis.length > 0) {
91
+ applicationInfo.requiredResourceAccess = apis;
92
+ }
93
+ if (args.options.redirectUris) {
94
+ applicationInfo[args.options.platform] = {
95
+ redirectUris: args.options.redirectUris.split(',').map(u => u.trim())
96
+ };
97
+ }
98
+ if (args.options.implicitFlow) {
99
+ if (!applicationInfo.web) {
100
+ applicationInfo.web = {};
101
+ }
102
+ applicationInfo.web.implicitGrantSettings = {
103
+ enableAccessTokenIssuance: true,
104
+ enableIdTokenIssuance: true
105
+ };
88
106
  }
89
- applicationInfo.web.implicitGrantSettings = {
90
- enableAccessTokenIssuance: true,
91
- enableIdTokenIssuance: true
107
+ if (args.options.certificateFile || args.options.certificateBase64Encoded) {
108
+ const certificateBase64Encoded = this.getCertificateBase64Encoded(args, logger);
109
+ const newKeyCredential = {
110
+ type: "AsymmetricX509Cert",
111
+ usage: "Verify",
112
+ displayName: args.options.certificateDisplayName,
113
+ key: certificateBase64Encoded
114
+ };
115
+ applicationInfo.keyCredentials = [newKeyCredential];
116
+ }
117
+ if (this.verbose) {
118
+ logger.logToStderr(`Creating Azure AD app registration...`);
119
+ }
120
+ const createApplicationRequestOptions = {
121
+ url: `${this.resource}/v1.0/myorganization/applications`,
122
+ headers: {
123
+ accept: 'application/json;odata.metadata=none'
124
+ },
125
+ responseType: 'json',
126
+ data: applicationInfo
92
127
  };
93
- }
94
- if (this.verbose) {
95
- logger.logToStderr(`Creating Azure AD app registration...`);
96
- }
97
- const createApplicationRequestOptions = {
98
- url: `${this.resource}/v1.0/myorganization/applications`,
99
- headers: {
100
- accept: 'application/json;odata.metadata=none'
101
- },
102
- responseType: 'json',
103
- data: applicationInfo
104
- };
105
- return request_1.default.post(createApplicationRequestOptions);
128
+ return request_1.default.post(createApplicationRequestOptions);
129
+ });
106
130
  }
107
131
  updateAppFromManifest(args, appInfo) {
108
132
  if (!args.options.manifest) {
@@ -437,6 +461,20 @@ class AadAppAddCommand extends GraphCommand_1.default {
437
461
  value: password.secretText
438
462
  }));
439
463
  }
464
+ getCertificateBase64Encoded(args, logger) {
465
+ if (args.options.certificateBase64Encoded) {
466
+ return args.options.certificateBase64Encoded;
467
+ }
468
+ if (this.debug) {
469
+ logger.logToStderr(`Reading existing ${args.options.certificateFile}...`);
470
+ }
471
+ try {
472
+ return fs.readFileSync(args.options.certificateFile, { encoding: 'base64' });
473
+ }
474
+ catch (e) {
475
+ throw new Error(`Error reading certificate file: ${e}. Please add the certificate using base64 option '--certificateBase64Encoded'.`);
476
+ }
477
+ }
440
478
  saveAppInfo(args, appInfo, logger) {
441
479
  if (!args.options.save) {
442
480
  return Promise.resolve(appInfo);
@@ -519,6 +557,15 @@ class AadAppAddCommand extends GraphCommand_1.default {
519
557
  {
520
558
  option: '--scopeAdminConsentDescription [scopeAdminConsentDescription]'
521
559
  },
560
+ {
561
+ option: '--certificateFile [certificateFile]'
562
+ },
563
+ {
564
+ option: '--certificateBase64Encoded [certificateBase64Encoded]'
565
+ },
566
+ {
567
+ option: '--certificateDisplayName [certificateDisplayName]'
568
+ },
522
569
  {
523
570
  option: '--manifest [manifest]'
524
571
  },
@@ -540,6 +587,15 @@ class AadAppAddCommand extends GraphCommand_1.default {
540
587
  if (args.options.redirectUris && !args.options.platform) {
541
588
  return `When you specify redirectUris you also need to specify platform`;
542
589
  }
590
+ if (args.options.certificateFile && args.options.certificateBase64Encoded) {
591
+ return 'Specify either certificateFile or certificateBase64Encoded but not both';
592
+ }
593
+ if (args.options.certificateDisplayName && !args.options.certificateFile && !args.options.certificateBase64Encoded) {
594
+ return 'When you specify certificateDisplayName you also need to specify certificateFile or certificateBase64Encoded';
595
+ }
596
+ if (args.options.certificateFile && !fs.existsSync(args.options.certificateFile)) {
597
+ return 'Certificate file not found';
598
+ }
543
599
  if (args.options.scopeName) {
544
600
  if (!args.options.uri) {
545
601
  return `When you specify scopeName you also need to specify uri`;
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ const fs = require("fs");
3
4
  const request_1 = require("../../../../request");
4
5
  const GraphCommand_1 = require("../../../base/GraphCommand");
5
6
  const commands_1 = require("../../commands");
@@ -19,6 +20,9 @@ class AadAppSetCommand extends GraphCommand_1.default {
19
20
  telemetryProps.redirectUris = typeof args.options.redirectUris !== 'undefined';
20
21
  telemetryProps.redirectUrisToRemove = typeof args.options.redirectUrisToRemove !== 'undefined';
21
22
  telemetryProps.uri = typeof args.options.uri !== 'undefined';
23
+ telemetryProps.certificateFile = typeof args.options.certificateFile !== 'undefined';
24
+ telemetryProps.certificateBase64Encoded = typeof args.options.certificateBase64Encoded !== 'undefined';
25
+ telemetryProps.certificateDisplayName = typeof args.options.certificateDisplayName !== 'undefined';
22
26
  return telemetryProps;
23
27
  }
24
28
  commandAction(logger, args, cb) {
@@ -26,6 +30,7 @@ class AadAppSetCommand extends GraphCommand_1.default {
26
30
  .getAppObjectId(args, logger)
27
31
  .then(objectId => this.configureUri(args, objectId, logger))
28
32
  .then(objectId => this.configureRedirectUris(args, objectId, logger))
33
+ .then(objectId => this.configureCertificate(args, objectId, logger))
29
34
  .then(_ => cb(), (rawRes) => this.handleRejectedODataJsonPromise(rawRes, logger, cb));
30
35
  }
31
36
  getAppObjectId(args, logger) {
@@ -156,6 +161,80 @@ class AadAppSetCommand extends GraphCommand_1.default {
156
161
  })
157
162
  .then(_ => Promise.resolve(objectId));
158
163
  }
164
+ configureCertificate(args, objectId, logger) {
165
+ if (!args.options.certificateFile && !args.options.certificateBase64Encoded) {
166
+ return Promise.resolve();
167
+ }
168
+ if (this.verbose) {
169
+ logger.logToStderr(`Setting certificate for Azure AD app...`);
170
+ }
171
+ const certificateBase64Encoded = this.getCertificateBase64Encoded(args, logger);
172
+ return this
173
+ .getCurrentKeyCredentialsList(args, objectId, certificateBase64Encoded, logger)
174
+ .then(currentKeyCredentials => {
175
+ if (this.verbose) {
176
+ logger.logToStderr(`Adding new keyCredential to list`);
177
+ }
178
+ // The KeyCredential graph type defines the 'key' property as 'NullableOption<number>'
179
+ // while it is a base64 encoded string. This is why a cast to any is used here.
180
+ const keyCredentials = currentKeyCredentials.filter(existingCredential => existingCredential.key !== certificateBase64Encoded);
181
+ const newKeyCredential = {
182
+ type: "AsymmetricX509Cert",
183
+ usage: "Verify",
184
+ displayName: args.options.certificateDisplayName,
185
+ key: certificateBase64Encoded
186
+ };
187
+ keyCredentials.push(newKeyCredential);
188
+ return Promise.resolve(keyCredentials);
189
+ })
190
+ .then(keyCredentials => this.updateKeyCredentials(objectId, keyCredentials, logger));
191
+ }
192
+ getCertificateBase64Encoded(args, logger) {
193
+ if (args.options.certificateBase64Encoded) {
194
+ return args.options.certificateBase64Encoded;
195
+ }
196
+ if (this.debug) {
197
+ logger.logToStderr(`Reading existing ${args.options.certificateFile}...`);
198
+ }
199
+ try {
200
+ return fs.readFileSync(args.options.certificateFile, { encoding: 'base64' });
201
+ }
202
+ catch (e) {
203
+ throw new Error(`Error reading certificate file: ${e}. Please add the certificate using base64 option '--certificateBase64Encoded'.`);
204
+ }
205
+ }
206
+ // We first retrieve existing certificates because we need to specify the full list of certificates when updating the app.
207
+ getCurrentKeyCredentialsList(args, objectId, certificateBase64Encoded, logger) {
208
+ if (this.verbose) {
209
+ logger.logToStderr(`Retrieving current keyCredentials list for app`);
210
+ }
211
+ const getAppRequestOptions = {
212
+ url: `${this.resource}/v1.0/myorganization/applications/${objectId}?$select=keyCredentials`,
213
+ headers: {
214
+ 'content-type': 'application/json;odata.metadata=none'
215
+ },
216
+ responseType: 'json'
217
+ };
218
+ return request_1.default.get(getAppRequestOptions).then((application) => {
219
+ return Promise.resolve(application.keyCredentials || []);
220
+ });
221
+ }
222
+ updateKeyCredentials(objectId, keyCredentials, logger) {
223
+ if (this.verbose) {
224
+ logger.logToStderr(`Updating keyCredentials in AAD app`);
225
+ }
226
+ const requestOptions = {
227
+ url: `${this.resource}/v1.0/myorganization/applications/${objectId}`,
228
+ headers: {
229
+ 'content-type': 'application/json;odata.metadata=none'
230
+ },
231
+ responseType: 'json',
232
+ data: {
233
+ keyCredentials: keyCredentials
234
+ }
235
+ };
236
+ return request_1.default.patch(requestOptions);
237
+ }
159
238
  options() {
160
239
  const options = [
161
240
  { option: '--appId [appId]' },
@@ -163,6 +242,9 @@ class AadAppSetCommand extends GraphCommand_1.default {
163
242
  { option: '-n, --name [name]' },
164
243
  { option: '-u, --uri [uri]' },
165
244
  { option: '-r, --redirectUris [redirectUris]' },
245
+ { option: '--certificateFile [certificateFile]' },
246
+ { option: '--certificateBase64Encoded [certificateBase64Encoded]' },
247
+ { option: '--certificateDisplayName [certificateDisplayName]' },
166
248
  {
167
249
  option: '--platform [platform]',
168
250
  autocomplete: AadAppSetCommand.aadApplicationPlatform
@@ -183,6 +265,15 @@ class AadAppSetCommand extends GraphCommand_1.default {
183
265
  (args.options.objectId && args.options.name)) {
184
266
  return 'Specify either appId, objectId or name but not both';
185
267
  }
268
+ if (args.options.certificateFile && args.options.certificateBase64Encoded) {
269
+ return 'Specify either certificateFile or certificateBase64Encoded but not both';
270
+ }
271
+ if (args.options.certificateDisplayName && !args.options.certificateFile && !args.options.certificateBase64Encoded) {
272
+ return 'When you specify certificateDisplayName you also need to specify certificateFile or certificateBase64Encoded';
273
+ }
274
+ if (args.options.certificateFile && !fs.existsSync(args.options.certificateFile)) {
275
+ return 'Certificate file not found';
276
+ }
186
277
  if (args.options.redirectUris && !args.options.platform) {
187
278
  return `When you specify redirectUris you also need to specify platform`;
188
279
  }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const Command_1 = require("../../Command");
4
+ class PowerBICommand extends Command_1.default {
5
+ get resource() {
6
+ return 'https://api.powerbi.com';
7
+ }
8
+ }
9
+ exports.default = PowerBICommand;
10
+ //# sourceMappingURL=PowerBICommand.js.map
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const request_1 = require("../../../../request");
4
+ const utils_1 = require("../../../../utils");
5
+ const GraphCommand_1 = require("../../../base/GraphCommand");
6
+ const commands_1 = require("../../commands");
7
+ class PlannerTaskReferenceAddCommand extends GraphCommand_1.default {
8
+ get name() {
9
+ return commands_1.default.TASK_REFERENCE_ADD;
10
+ }
11
+ get description() {
12
+ return 'Adds a new reference to a Planner task';
13
+ }
14
+ commandAction(logger, args, cb) {
15
+ this
16
+ .getTaskDetailsEtag(args.options.taskId)
17
+ .then(etag => {
18
+ const requestOptionsTaskDetails = {
19
+ url: `${this.resource}/v1.0/planner/tasks/${encodeURIComponent(args.options.taskId)}/details`,
20
+ headers: {
21
+ 'accept': 'application/json;odata.metadata=none',
22
+ 'If-Match': etag,
23
+ 'Prefer': 'return=representation'
24
+ },
25
+ responseType: 'json',
26
+ data: {
27
+ references: {
28
+ [utils_1.formatting.openTypesEncoder(args.options.url)]: Object.assign(Object.assign({ '@odata.type': 'microsoft.graph.plannerExternalReference', previewPriority: ' !' }, (args.options.alias && { alias: args.options.alias })), (args.options.type && { type: args.options.type }))
29
+ }
30
+ }
31
+ };
32
+ return request_1.default.patch(requestOptionsTaskDetails);
33
+ })
34
+ .then((res) => {
35
+ logger.log(res.references);
36
+ cb();
37
+ }, (err) => this.handleRejectedODataJsonPromise(err, logger, cb));
38
+ }
39
+ getTaskDetailsEtag(taskId) {
40
+ const requestOptions = {
41
+ url: `${this.resource}/v1.0/planner/tasks/${encodeURIComponent(taskId)}/details`,
42
+ headers: {
43
+ accept: 'application/json'
44
+ },
45
+ responseType: 'json'
46
+ };
47
+ return request_1.default
48
+ .get(requestOptions)
49
+ .then((response) => {
50
+ const etag = response ? response['@odata.etag'] : undefined;
51
+ if (!etag) {
52
+ return Promise.reject(`Error fetching task details`);
53
+ }
54
+ return Promise.resolve(etag);
55
+ });
56
+ }
57
+ options() {
58
+ const options = [
59
+ { option: '-i, --taskId <taskId>' },
60
+ { option: '-u, --url <url>' },
61
+ { option: '--alias [alias]' },
62
+ { option: '--type [type]' }
63
+ ];
64
+ const parentOptions = super.options();
65
+ return options.concat(parentOptions);
66
+ }
67
+ validate(args) {
68
+ if (args.options.type && ['powerpoint', 'word', 'excel', 'other'].indexOf(args.options.type.toLocaleLowerCase()) === -1) {
69
+ return `${args.options.type} is not a valid type value. Allowed values PowerPoint|Word|Excel|Other`;
70
+ }
71
+ return true;
72
+ }
73
+ }
74
+ module.exports = new PlannerTaskReferenceAddCommand();
75
+ //# sourceMappingURL=task-reference-add.js.map
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const request_1 = require("../../../../request");
4
+ const GraphCommand_1 = require("../../../base/GraphCommand");
5
+ const commands_1 = require("../../commands");
6
+ const utils_1 = require("../../../../utils");
7
+ const Auth_1 = require("../../../../Auth");
8
+ class PlannerTaskReferenceListCommand extends GraphCommand_1.default {
9
+ get name() {
10
+ return commands_1.default.TASK_REFERENCE_LIST;
11
+ }
12
+ get description() {
13
+ return 'Retrieve the references of the specified planner task';
14
+ }
15
+ commandAction(logger, args, cb) {
16
+ if (utils_1.accessToken.isAppOnlyAccessToken(Auth_1.default.service.accessTokens[this.resource].accessToken)) {
17
+ this.handleError('This command does not support application permissions.', logger, cb);
18
+ return;
19
+ }
20
+ const requestOptions = {
21
+ url: `${this.resource}/v1.0/planner/tasks/${encodeURIComponent(args.options.taskId)}/details?$select=references`,
22
+ headers: {
23
+ accept: 'application/json;odata.metadata=none'
24
+ },
25
+ responseType: 'json'
26
+ };
27
+ request_1.default
28
+ .get(requestOptions)
29
+ .then((res) => {
30
+ logger.log(res.references);
31
+ cb();
32
+ }, (err) => this.handleRejectedODataJsonPromise(err, logger, cb));
33
+ }
34
+ options() {
35
+ const options = [
36
+ {
37
+ option: '-i, --taskId <taskId>'
38
+ }
39
+ ];
40
+ const parentOptions = super.options();
41
+ return options.concat(parentOptions);
42
+ }
43
+ }
44
+ module.exports = new PlannerTaskReferenceListCommand();
45
+ //# sourceMappingURL=task-reference-list.js.map
@@ -8,13 +8,15 @@ exports.default = {
8
8
  BUCKET_REMOVE: `${prefix} bucket remove`,
9
9
  BUCKET_GET: `${prefix} bucket get`,
10
10
  PLAN_ADD: `${prefix} plan add`,
11
- PLAN_GET: `${prefix} plan get`,
12
11
  PLAN_DETAILS_GET: `${prefix} plan details get`,
12
+ PLAN_GET: `${prefix} plan get`,
13
13
  PLAN_LIST: `${prefix} plan list`,
14
14
  TASK_ADD: `${prefix} task add`,
15
15
  TASK_DETAILS_GET: `${prefix} task details get`,
16
16
  TASK_GET: `${prefix} task get`,
17
17
  TASK_LIST: `${prefix} task list`,
18
+ TASK_REFERENCE_ADD: `${prefix} task reference add`,
19
+ TASK_REFERENCE_LIST: `${prefix} task reference list`,
18
20
  TASK_SET: `${prefix} task set`
19
21
  };
20
22
  //# sourceMappingURL=commands.js.map
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const request_1 = require("../../../../request");
4
+ const PowerBICommand_1 = require("../../../base/PowerBICommand");
5
+ const commands_1 = require("../../commands");
6
+ class PpGatewayListCommand extends PowerBICommand_1.default {
7
+ get name() {
8
+ return commands_1.default.GATEWAY_LIST;
9
+ }
10
+ get description() {
11
+ return 'Returns a list of gateways for which the user is an admin';
12
+ }
13
+ defaultProperties() {
14
+ return ['id', 'name'];
15
+ }
16
+ commandAction(logger, args, cb) {
17
+ if (this.verbose) {
18
+ logger.logToStderr(`Retrieving list of gateways for which the user is an admin...`);
19
+ }
20
+ const requestOptions = {
21
+ url: `${this.resource}/v1.0/myorg/gateways`,
22
+ headers: {
23
+ accept: 'application/json;odata.metadata=none'
24
+ },
25
+ responseType: 'json'
26
+ };
27
+ request_1.default
28
+ .get(requestOptions)
29
+ .then((res) => {
30
+ logger.log(res.value);
31
+ cb();
32
+ }, (rawRes) => this.handleRejectedODataJsonPromise(rawRes, logger, cb));
33
+ }
34
+ }
35
+ module.exports = new PpGatewayListCommand();
36
+ //# sourceMappingURL=gateway-list.js.map
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const prefix = 'pp';
4
4
  exports.default = {
5
5
  ENVIRONMENT_LIST: `${prefix} environment list`,
6
+ GATEWAY_LIST: `${prefix} gateway list`,
6
7
  MANAGEMENTAPP_ADD: `${prefix} managementapp add`,
7
8
  MANAGEMENTAPP_LIST: `${prefix} managementapp list`
8
9
  };
@@ -153,8 +153,11 @@ class TeamsChannelMemberAddCommand extends GraphCommand_1.default {
153
153
  if (!channelItem) {
154
154
  return Promise.reject(`The specified channel '${args.options.channelName}' does not exist in the Microsoft Teams team with ID '${teamId}'`);
155
155
  }
156
+ if (channelItem.membershipType !== "private") {
157
+ return Promise.reject(`The specified channel is not a private channel`);
158
+ }
156
159
  return Promise.resolve(channelItem.id);
157
- }, err => { return Promise.reject(err); });
160
+ });
158
161
  }
159
162
  getUserId(args) {
160
163
  if (args.options.userId) {
@@ -135,6 +135,9 @@ class TeamsChannelMemberRemoveCommand extends GraphCommand_1.default {
135
135
  if (!channelItem) {
136
136
  return Promise.reject(`The specified channel does not exist in the Microsoft Teams team`);
137
137
  }
138
+ if (channelItem.membershipType !== "private") {
139
+ return Promise.reject(`The specified channel is not a private channel`);
140
+ }
138
141
  return Promise.resolve(channelItem.id);
139
142
  });
140
143
  }
@@ -103,6 +103,9 @@ class TeamsChannelMemberSetCommand extends GraphCommand_1.default {
103
103
  if (!channelItem) {
104
104
  return Promise.reject(`The specified channel does not exist in the Microsoft Teams team`);
105
105
  }
106
+ if (channelItem.membershipType !== "private") {
107
+ return Promise.reject(`The specified channel is not a private channel`);
108
+ }
106
109
  return Promise.resolve(channelItem.id);
107
110
  });
108
111
  }
@@ -30,8 +30,9 @@ exports.formatting = {
30
30
  return JSON.parse(s.replace(/^\uFEFF/, ''));
31
31
  },
32
32
  filterObject(obj, propertiesToInclude) {
33
- return Object.keys(obj)
34
- .filter(key => propertiesToInclude.includes(key))
33
+ const objKeys = Object.keys(obj);
34
+ return propertiesToInclude
35
+ .filter(prop => objKeys.includes(prop))
35
36
  .reduce((filtered, key) => {
36
37
  filtered[key] = obj[key];
37
38
  return filtered;
@@ -64,6 +65,14 @@ exports.formatting = {
64
65
  },
65
66
  splitAndTrim(s) {
66
67
  return s.split(',').map(c => c.trim());
68
+ },
69
+ openTypesEncoder(value) {
70
+ return value
71
+ .replace(/\%/g, '%25')
72
+ .replace(/\./g, '%2E')
73
+ .replace(/:/g, '%3A')
74
+ .replace(/@/g, '%40')
75
+ .replace(/#/g, '%23');
67
76
  }
68
77
  };
69
78
  //# sourceMappingURL=formatting.js.map
@@ -49,6 +49,15 @@ m365 aad app add [options]
49
49
  `--scopeAdminConsentDescription [scopeAdminConsentDescription]`
50
50
  : Scope admin consent description
51
51
 
52
+ `--certificateFile [certificateFile]`
53
+ : Path to the file with certificate public key. Specify either `certificateFile` or `certificateBase64Encoded`
54
+
55
+ `--certificateBase64Encoded [certificateBase64Encoded]`
56
+ : Base64-encoded string with certificate public key. Specify either `certificateFile` or `certificateBase64Encoded`
57
+
58
+ `--certificateDisplayName [certificateDisplayName]`
59
+ : Display name for the certificate. If not given, the displayName will be set to the certificate subject. When specified, also specify either `certificateFile` or `certificateBase64Encoded`
60
+
52
61
  `--manifest [manifest]`
53
62
  : Azure AD app manifest as retrieved from the Azure Portal to create the app registration from
54
63
 
@@ -152,3 +161,9 @@ Create new Azure AD app registration with the specified name. Store information
152
161
  ```sh
153
162
  m365 aad app add --name 'My AAD app' --save
154
163
  ```
164
+
165
+ Create new Azure AD app registration with a certificate
166
+
167
+ ```sh
168
+ m365 aad app add --name 'My AAD app' --certificateDisplayName "Some certificate name" --certificateFile c:\temp\some-certificate.cer
169
+ ```
@@ -31,6 +31,15 @@ m365 aad app set [options]
31
31
  `--redirectUrisToRemove [redirectUrisToRemove]`
32
32
  : Comma-separated list of existing redirect URIs to remove. Specify, when you want to replace existing redirect URIs with another
33
33
 
34
+ `--certificateFile [certificateFile]`
35
+ : Path to the file with certificate public key. Specify either `certificateFile` or `certificateBase64Encoded`
36
+
37
+ `--certificateBase64Encoded [certificateBase64Encoded]`
38
+ : Base64-encoded string with certificate public key. Specify either `certificateFile` or `certificateBase64Encoded`
39
+
40
+ `--certificateDisplayName [certificateDisplayName]`
41
+ : Display name for the certificate. If not given, the displayName will be set to the certificate subject. When specified, also specify either `certificateFile` or `certificateBase64Encoded`
42
+
34
43
  --8<-- "docs/cmd/_global.md"
35
44
 
36
45
  ## Remarks
@@ -39,6 +48,8 @@ For best performance use the `objectId` option to reference the Azure AD applica
39
48
 
40
49
  If the command finds multiple Azure AD application registrations with the specified app name, it will prompt you to disambiguate which app it should use, listing the discovered object IDs.
41
50
 
51
+ When a certificate is specified it will be added to the list of certificates of the app without changing existing certificates.
52
+
42
53
  ## Examples
43
54
 
44
55
  Update the app URI of the Azure AD application registration specified by its object ID
@@ -70,3 +81,9 @@ Replace one redirect URI with another for SPA authentication
70
81
  ```sh
71
82
  m365 aad app set --objectId 95cfe30d-ed44-4f9d-b73d-c66560f72e83 --redirectUris https://contoso.com/auth --platform spa --redirectUrisToRemove https://contoso.com/old-auth
72
83
  ```
84
+
85
+ Add a certificate to the app
86
+
87
+ ```sh
88
+ m365 aad app set --certificateDisplayName "Some certificate name" --certificateFile c:\temp\some-certificate.cer
89
+ ```
@@ -1,4 +1,4 @@
1
- # aad approleassignment add
1
+ # aad approleassignment remove
2
2
 
3
3
  Deletes an app role assignment for the specified Azure AD Application Registration
4
4
 
@@ -0,0 +1,45 @@
1
+ # planner task reference add
2
+
3
+ Adds a new reference to a Planner task.
4
+
5
+ ## Usage
6
+
7
+ ```sh
8
+ m365 planner task reference add [options]
9
+ ```
10
+
11
+ ## Options
12
+
13
+ `-i, --taskId <taskId>`
14
+ : ID of the task.
15
+
16
+ `-u, --url <url>`
17
+ : URL location of the reference.
18
+
19
+ `--alias [alias]`
20
+ : A name alias to describe the reference.
21
+
22
+ `--type [type]`
23
+ : Used to describe the type of the reference. Types include: `PowerPoint`, `Word`, `Excel`, `Other`.
24
+
25
+ --8<-- "docs/cmd/_global.md"
26
+
27
+ ## Examples
28
+
29
+ Add a new reference with the url _https://www.microsoft.com_ to a Planner task with the id _2Vf8JHgsBUiIf-nuvBtv-ZgAAYw2_
30
+
31
+ ```sh
32
+ m365 planner task reference add --taskId "2Vf8JHgsBUiIf-nuvBtv-ZgAAYw2" --url "https://www.microsoft.com"
33
+ ```
34
+
35
+ Add a new reference with the url _https://www.microsoft.com_ and with the alias _Parker_ to a Planner task with the id _2Vf8JHgsBUiIf-nuvBtv-ZgAAYw2_
36
+
37
+ ```sh
38
+ m365 planner task reference add --taskId "2Vf8JHgsBUiIf-nuvBtv-ZgAAYw2" --url "https://www.microsoft.com" --alias "Parker"
39
+ ```
40
+
41
+ Add a new reference with the url _https://www.microsoft.com_ and with the type Excel to a Planner task with the id _2Vf8JHgsBUiIf-nuvBtv-ZgAAYw2_
42
+
43
+ ```sh
44
+ m365 planner task reference add --taskId "2Vf8JHgsBUiIf-nuvBtv-ZgAAYw2" --url "https://www.microsoft.com" --type "Excel"
45
+ ```
@@ -0,0 +1,24 @@
1
+ # planner task reference list
2
+
3
+ Retrieve the references associated to a Planner task.
4
+
5
+ ## Usage
6
+
7
+ ```sh
8
+ m365 planner task reference list [options]
9
+ ```
10
+
11
+ ## Options
12
+
13
+ `-i, --taskId <taskId>`
14
+ : ID of the task to retrieve references from
15
+
16
+ --8<-- "docs/cmd/_global.md"
17
+
18
+ ## Examples
19
+
20
+ Retrieve the references of the specified planner task
21
+
22
+ ```sh
23
+ m365 planner task reference list --taskId uBk5fK_MHkeyuPYlCo4OFpcAM
24
+ ```
@@ -0,0 +1,21 @@
1
+ # pp gateway list
2
+
3
+ Returns a list of gateways for which the user is an admin
4
+
5
+ ## Usage
6
+
7
+ ```sh
8
+ m365 pp gateway list [options]
9
+ ```
10
+
11
+ ## Options
12
+
13
+ --8<-- "docs/cmd/_global.md"
14
+
15
+ ## Examples
16
+
17
+ List gateways for which the user is an admin
18
+
19
+ ```sh
20
+ m365 pp gateway list
21
+ ```
@@ -1,4 +1,4 @@
1
- # spo userprofile set
1
+ # spo userprofile get
2
2
 
3
3
  Get SharePoint user profile properties for the specified user
4
4
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pnp/cli-microsoft365",
3
- "version": "5.3.0-beta.4033f50",
3
+ "version": "5.3.0-beta.421b58b",
4
4
  "description": "Manage Microsoft 365 and SharePoint Framework projects on any platform",
5
5
  "license": "MIT",
6
6
  "main": "./dist/api.js",
@@ -131,6 +131,7 @@
131
131
  "Lingstuyl, Martin <martin@i4-you.com>",
132
132
  "Maillot, Michaël <battosaimykle@gmail.com>",
133
133
  "Mastykarz, Waldek <waldek@mastykarz.nl>",
134
+ "Mathijs Verbeeck <mathijs.verbeeck@vanroey.be",
134
135
  "McDonnell, Kevin <kevin@mcd79.com>",
135
136
  "Menon, Arjun <arjun.umenon@gmail.com>",
136
137
  "Moujahid, Abderahman <rags_place@hotmail.com>",