@pnp/cli-microsoft365 5.8.0-beta.5250f08 → 5.8.0-beta.57eff68

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.
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.default = {
4
4
  LOGIN: `login`,
5
5
  LOGOUT: `logout`,
6
+ REQUEST: `request`,
6
7
  STATUS: `status`,
7
8
  VERSION: 'version'
8
9
  };
@@ -0,0 +1,153 @@
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
+ };
11
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
12
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
13
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
14
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
15
+ };
16
+ var _RequestCommand_instances, _RequestCommand_initTelemetry, _RequestCommand_initOptions, _RequestCommand_initValidators;
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ const fs = require("fs");
19
+ const Command_1 = require("../../Command");
20
+ const request_1 = require("../../request");
21
+ const commands_1 = require("./commands");
22
+ const path = require("path");
23
+ class RequestCommand extends Command_1.default {
24
+ constructor() {
25
+ super();
26
+ _RequestCommand_instances.add(this);
27
+ this.allowedMethods = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options'];
28
+ __classPrivateFieldGet(this, _RequestCommand_instances, "m", _RequestCommand_initTelemetry).call(this);
29
+ __classPrivateFieldGet(this, _RequestCommand_instances, "m", _RequestCommand_initOptions).call(this);
30
+ __classPrivateFieldGet(this, _RequestCommand_instances, "m", _RequestCommand_initValidators).call(this);
31
+ }
32
+ get name() {
33
+ return commands_1.default.REQUEST;
34
+ }
35
+ get description() {
36
+ return 'Executes the specified web request using CLI for Microsoft 365';
37
+ }
38
+ allowUnknownOptions() {
39
+ return true;
40
+ }
41
+ commandAction(logger, args, cb) {
42
+ if (this.debug) {
43
+ logger.logToStderr(`Preparing request...`);
44
+ }
45
+ const method = (args.options.method || 'get').toUpperCase();
46
+ const headers = {};
47
+ const unknownOptions = this.getUnknownOptions(args.options);
48
+ const unknownOptionsNames = Object.getOwnPropertyNames(unknownOptions);
49
+ unknownOptionsNames.forEach(o => {
50
+ headers[o] = unknownOptions[o];
51
+ });
52
+ if (!headers.accept) {
53
+ headers.accept = 'application/json';
54
+ }
55
+ if (args.options.resource) {
56
+ headers['x-resource'] = args.options.resource;
57
+ }
58
+ const config = {
59
+ url: args.options.url,
60
+ headers,
61
+ method,
62
+ data: args.options.body
63
+ };
64
+ if (headers.accept.toString().startsWith('application/json')) {
65
+ config.responseType = 'json';
66
+ }
67
+ if (args.options.filePath) {
68
+ config.responseType = 'stream';
69
+ }
70
+ if (this.verbose) {
71
+ logger.logToStderr(`Executing request...`);
72
+ }
73
+ if (args.options.filePath) {
74
+ request_1.default
75
+ .execute(config)
76
+ .then((file) => {
77
+ return new Promise((resolve, reject) => {
78
+ const writer = fs.createWriteStream(args.options.filePath);
79
+ file.data.pipe(writer);
80
+ writer.on('error', err => {
81
+ reject(err);
82
+ });
83
+ writer.on('close', () => {
84
+ resolve(args.options.filePath);
85
+ });
86
+ });
87
+ })
88
+ .then((file) => {
89
+ if (this.verbose) {
90
+ logger.logToStderr(`File saved to path ${file}`);
91
+ }
92
+ cb();
93
+ }, (err) => this.handleError(err, logger, cb));
94
+ }
95
+ else {
96
+ request_1.default
97
+ .execute(config)
98
+ .then(response => {
99
+ logger.log(response);
100
+ cb();
101
+ }, (rawRes) => this.handleError(rawRes, logger, cb));
102
+ }
103
+ }
104
+ }
105
+ _RequestCommand_instances = new WeakSet(), _RequestCommand_initTelemetry = function _RequestCommand_initTelemetry() {
106
+ this.telemetry.push((args) => {
107
+ const properties = {
108
+ method: args.options.method || 'get',
109
+ resource: typeof args.options.resource !== 'undefined',
110
+ accept: args.options.accept || 'application/json',
111
+ body: typeof args.options.body !== 'undefined',
112
+ filePath: typeof args.options.filePath !== 'undefined'
113
+ };
114
+ const unknownOptions = this.getUnknownOptions(args.options);
115
+ const unknownOptionsNames = Object.getOwnPropertyNames(unknownOptions);
116
+ unknownOptionsNames.forEach(o => {
117
+ properties[o] = typeof unknownOptions[o] !== 'undefined';
118
+ });
119
+ Object.assign(this.telemetryProperties, properties);
120
+ });
121
+ }, _RequestCommand_initOptions = function _RequestCommand_initOptions() {
122
+ this.options.unshift({
123
+ option: '-u, --url <url>'
124
+ }, {
125
+ option: '-m, --method [method]',
126
+ autocomplete: this.allowedMethods
127
+ }, {
128
+ option: '-r, --resource [resource]'
129
+ }, {
130
+ option: '-b, --body [body]'
131
+ }, {
132
+ option: '-p, --filePath [filePath]'
133
+ });
134
+ }, _RequestCommand_initValidators = function _RequestCommand_initValidators() {
135
+ this.validators.push((args) => __awaiter(this, void 0, void 0, function* () {
136
+ const currentMethod = args.options.method || 'get';
137
+ if (this.allowedMethods.indexOf(currentMethod) === -1) {
138
+ return `${currentMethod} is not a valid value for method. Allowed values: ${this.allowedMethods.join(', ')}`;
139
+ }
140
+ if (args.options.body && (!args.options.method || args.options.method === 'get')) {
141
+ return 'Specify a different method when using body';
142
+ }
143
+ if (args.options.body && !args.options['content-type']) {
144
+ return 'Specify the content-type when using body';
145
+ }
146
+ if (args.options.filePath && !fs.existsSync(path.dirname(args.options.filePath))) {
147
+ return 'The location specified in the filePath does not exist';
148
+ }
149
+ return true;
150
+ }));
151
+ };
152
+ module.exports = new RequestCommand();
153
+ //# sourceMappingURL=request.js.map
@@ -0,0 +1,139 @@
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
+ };
11
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
12
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
13
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
14
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
15
+ };
16
+ var _OneNoteNotebookListCommand_instances, _OneNoteNotebookListCommand_initTelemetry, _OneNoteNotebookListCommand_initOptions, _OneNoteNotebookListCommand_initValidators;
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ const request_1 = require("../../../../request");
19
+ const utils_1 = require("../../../../utils");
20
+ const aadGroup_1 = require("../../../../utils/aadGroup");
21
+ const GraphCommand_1 = require("../../../base/GraphCommand");
22
+ const commands_1 = require("../../commands");
23
+ class OneNoteNotebookListCommand extends GraphCommand_1.default {
24
+ constructor() {
25
+ super();
26
+ _OneNoteNotebookListCommand_instances.add(this);
27
+ __classPrivateFieldGet(this, _OneNoteNotebookListCommand_instances, "m", _OneNoteNotebookListCommand_initTelemetry).call(this);
28
+ __classPrivateFieldGet(this, _OneNoteNotebookListCommand_instances, "m", _OneNoteNotebookListCommand_initOptions).call(this);
29
+ __classPrivateFieldGet(this, _OneNoteNotebookListCommand_instances, "m", _OneNoteNotebookListCommand_initValidators).call(this);
30
+ }
31
+ get name() {
32
+ return commands_1.default.NOTEBOOK_LIST;
33
+ }
34
+ get description() {
35
+ return 'Retrieve a list of notebooks';
36
+ }
37
+ getEndpointUrl(args) {
38
+ return new Promise((resolve, reject) => {
39
+ let endpoint = `${this.resource}/v1.0/me/onenote/notebooks`;
40
+ if (args.options.userId) {
41
+ endpoint = `${this.resource}/v1.0/users/${args.options.userId}/onenote/notebooks`;
42
+ return resolve(endpoint);
43
+ }
44
+ else if (args.options.userName) {
45
+ endpoint = `${this.resource}/v1.0/users/${args.options.userName}/onenote/notebooks`;
46
+ return resolve(endpoint);
47
+ }
48
+ else if (args.options.groupId) {
49
+ endpoint = `${this.resource}/v1.0/groups/${args.options.groupId}/onenote/notebooks`;
50
+ return resolve(endpoint);
51
+ }
52
+ else if (args.options.groupName) {
53
+ this
54
+ .getGroupId(args)
55
+ .then((retrievedgroupId) => {
56
+ endpoint = `${this.resource}/v1.0/groups/${retrievedgroupId}/onenote/notebooks`;
57
+ return resolve(endpoint);
58
+ })
59
+ .catch((err) => {
60
+ reject(err);
61
+ });
62
+ }
63
+ else if (args.options.webUrl) {
64
+ this
65
+ .getSpoSiteId(args)
66
+ .then((siteId) => {
67
+ endpoint = `${this.resource}/v1.0/sites/${siteId}/onenote/notebooks`;
68
+ return resolve(endpoint);
69
+ })
70
+ .catch((err) => {
71
+ reject(err);
72
+ });
73
+ }
74
+ else {
75
+ return resolve(endpoint);
76
+ }
77
+ });
78
+ }
79
+ defaultProperties() {
80
+ return ['createdDateTime', 'displayName', 'id'];
81
+ }
82
+ getGroupId(args) {
83
+ return aadGroup_1.aadGroup
84
+ .getGroupByDisplayName(args.options.groupName)
85
+ .then(group => group.id);
86
+ }
87
+ getSpoSiteId(args) {
88
+ const url = new URL(args.options.webUrl);
89
+ const requestOptions = {
90
+ url: `${this.resource}/v1.0/sites/${url.hostname}:${url.pathname}`,
91
+ headers: {
92
+ accept: 'application/json;odata.metadata=none'
93
+ },
94
+ responseType: 'json'
95
+ };
96
+ return request_1.default
97
+ .get(requestOptions)
98
+ .then((site) => site.id);
99
+ }
100
+ commandAction(logger, args, cb) {
101
+ this
102
+ .getEndpointUrl(args)
103
+ .then(endpoint => utils_1.odata.getAllItems(endpoint))
104
+ .then((items) => {
105
+ return Promise.resolve(items);
106
+ })
107
+ .then((items) => {
108
+ logger.log(items);
109
+ cb();
110
+ }, (err) => this.handleRejectedODataJsonPromise(err, logger, cb));
111
+ }
112
+ }
113
+ _OneNoteNotebookListCommand_instances = new WeakSet(), _OneNoteNotebookListCommand_initTelemetry = function _OneNoteNotebookListCommand_initTelemetry() {
114
+ this.telemetry.push((args) => {
115
+ Object.assign(this.telemetryProperties, {
116
+ joined: args.options.joined
117
+ });
118
+ });
119
+ }, _OneNoteNotebookListCommand_initOptions = function _OneNoteNotebookListCommand_initOptions() {
120
+ this.options.unshift({ option: '--userId [userId]' }, { option: '--userName [userName]' }, { option: '--groupId [groupId]' }, { option: '--groupName [groupName]' }, { option: '-u, --webUrl [webUrl]' });
121
+ }, _OneNoteNotebookListCommand_initValidators = function _OneNoteNotebookListCommand_initValidators() {
122
+ this.validators.push((args) => __awaiter(this, void 0, void 0, function* () {
123
+ if (args.options.userId && !utils_1.validation.isValidGuid(args.options.userId)) {
124
+ return `${args.options.userId} is not a valid GUID`;
125
+ }
126
+ if (args.options.groupId && !utils_1.validation.isValidGuid(args.options.groupId)) {
127
+ return `${args.options.groupId} is not a valid GUID`;
128
+ }
129
+ if (args.options.userId && args.options.userName) {
130
+ return 'Specify either userId or userName, but not both';
131
+ }
132
+ if (args.options.groupId && args.options.groupName) {
133
+ return 'Specify either groupId or groupName, but not both';
134
+ }
135
+ return true;
136
+ }));
137
+ };
138
+ module.exports = new OneNoteNotebookListCommand();
139
+ //# sourceMappingURL=notebook-list.js.map
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const prefix = 'onenote';
4
+ exports.default = {
5
+ NOTEBOOK_LIST: `${prefix} notebook list`
6
+ };
7
+ //# sourceMappingURL=commands.js.map
@@ -180,6 +180,13 @@ _PlannerTaskGetCommand_instances = new WeakSet(), _PlannerTaskGetCommand_initTel
180
180
  { option: '-i, --id [id]' }, { option: '-t, --title [title]' }, { option: '--bucketId [bucketId]' }, { option: '--bucketName [bucketName]' }, { option: '--planId [planId]' }, { option: '--planName [planName]' }, { option: '--planTitle [planTitle]' }, { option: '--ownerGroupId [ownerGroupId]' }, { option: '--ownerGroupName [ownerGroupName]' });
181
181
  }, _PlannerTaskGetCommand_initValidators = function _PlannerTaskGetCommand_initValidators() {
182
182
  this.validators.push((args) => __awaiter(this, void 0, void 0, function* () {
183
+ if (args.options.id) {
184
+ if (args.options.bucketId || args.options.bucketName ||
185
+ args.options.planId || args.options.planName || args.options.planTitle ||
186
+ args.options.ownerGroupId || args.options.ownerGroupName) {
187
+ return 'Don\'t specify bucketId, bucketName, planId, planTitle, ownerGroupId or ownerGroupName when using id';
188
+ }
189
+ }
183
190
  if (args.options.title && !args.options.bucketId && !args.options.bucketName) {
184
191
  return 'Specify either bucketId or bucketName when using title';
185
192
  }
@@ -32,7 +32,7 @@ class SpoHubSiteUnregisterCommand extends SpoCommand_1.default {
32
32
  return commands_1.default.HUBSITE_UNREGISTER;
33
33
  }
34
34
  get description() {
35
- return 'Unregisters the specifies site collection as a hub site';
35
+ return 'Unregisters the specified site collection as a hub site';
36
36
  }
37
37
  commandAction(logger, args, cb) {
38
38
  const unregisterHubSite = () => {
@@ -193,14 +193,23 @@ _SpoListRoleAssignmentAddCommand_instances = new WeakSet(), _SpoListRoleAssignme
193
193
  if (listOptions.some(item => item !== undefined) && listOptions.filter(item => item !== undefined).length > 1) {
194
194
  return `Specify either list id or title or list url`;
195
195
  }
196
+ if (listOptions.filter(item => item !== undefined).length === 0) {
197
+ return `Specify at least list id or title or list url`;
198
+ }
196
199
  const principalOptions = [args.options.principalId, args.options.upn, args.options.groupName];
197
200
  if (principalOptions.some(item => item !== undefined) && principalOptions.filter(item => item !== undefined).length > 1) {
198
201
  return `Specify either principalId id or upn or groupName`;
199
202
  }
203
+ if (principalOptions.filter(item => item !== undefined).length === 0) {
204
+ return `Specify at least principalId id or upn or groupName`;
205
+ }
200
206
  const roleDefinitionOptions = [args.options.roleDefinitionId, args.options.roleDefinitionName];
201
207
  if (roleDefinitionOptions.some(item => item !== undefined) && roleDefinitionOptions.filter(item => item !== undefined).length > 1) {
202
208
  return `Specify either roleDefinitionId id or roleDefinitionName`;
203
209
  }
210
+ if (roleDefinitionOptions.filter(item => item !== undefined).length === 0) {
211
+ return `Specify at least roleDefinitionId id or roleDefinitionName`;
212
+ }
204
213
  return true;
205
214
  }));
206
215
  };
@@ -37,36 +37,56 @@ class SpoListRoleAssignmentRemoveCommand extends SpoCommand_1.default {
37
37
  return 'Removes a role assignment from list permissions';
38
38
  }
39
39
  commandAction(logger, args, cb) {
40
- if (this.verbose) {
41
- logger.logToStderr(`Removing role assignment frm list in site at ${args.options.webUrl}...`);
42
- }
43
- let requestUrl = `${args.options.webUrl}/_api/web/`;
44
- if (args.options.listId) {
45
- requestUrl += `lists(guid'${utils_1.formatting.encodeQueryParameter(args.options.listId)}')/`;
46
- }
47
- else if (args.options.listTitle) {
48
- requestUrl += `lists/getByTitle('${utils_1.formatting.encodeQueryParameter(args.options.listTitle)}')/`;
49
- }
50
- else if (args.options.listUrl) {
51
- const listServerRelativeUrl = utils_1.urlUtil.getServerRelativePath(args.options.webUrl, args.options.listUrl);
52
- requestUrl += `GetList('${utils_1.formatting.encodeQueryParameter(listServerRelativeUrl)}')/`;
53
- }
54
- if (args.options.upn) {
55
- this.GetUserPrincipalId(args.options)
56
- .then((userPrincipalId) => {
57
- args.options.principalId = userPrincipalId;
58
- this.RemoveRoleAssignment(requestUrl, logger, args.options, cb);
59
- }, (err) => this.handleRejectedODataJsonPromise(err, logger, cb));
60
- }
61
- else if (args.options.groupName) {
62
- this.GetGroupPrincipalId(args.options)
63
- .then((groupPrincipalId) => {
64
- args.options.principalId = groupPrincipalId;
40
+ const removeRoleAssignment = () => {
41
+ if (this.verbose) {
42
+ logger.logToStderr(`Removing role assignment from list in site at ${args.options.webUrl}...`);
43
+ }
44
+ let requestUrl = `${args.options.webUrl}/_api/web/`;
45
+ if (args.options.listId) {
46
+ requestUrl += `lists(guid'${utils_1.formatting.encodeQueryParameter(args.options.listId)}')/`;
47
+ }
48
+ else if (args.options.listTitle) {
49
+ requestUrl += `lists/getByTitle('${utils_1.formatting.encodeQueryParameter(args.options.listTitle)}')/`;
50
+ }
51
+ else if (args.options.listUrl) {
52
+ const listServerRelativeUrl = utils_1.urlUtil.getServerRelativePath(args.options.webUrl, args.options.listUrl);
53
+ requestUrl += `GetList('${utils_1.formatting.encodeQueryParameter(listServerRelativeUrl)}')/`;
54
+ }
55
+ if (args.options.upn) {
56
+ this.GetUserPrincipalId(args.options)
57
+ .then((userPrincipalId) => {
58
+ args.options.principalId = userPrincipalId;
59
+ this.RemoveRoleAssignment(requestUrl, logger, args.options, cb);
60
+ }, (err) => this.handleRejectedODataJsonPromise(err, logger, cb));
61
+ }
62
+ else if (args.options.groupName) {
63
+ this.GetGroupPrincipalId(args.options)
64
+ .then((groupPrincipalId) => {
65
+ args.options.principalId = groupPrincipalId;
66
+ this.RemoveRoleAssignment(requestUrl, logger, args.options, cb);
67
+ }, (err) => this.handleRejectedODataJsonPromise(err, logger, cb));
68
+ }
69
+ else {
65
70
  this.RemoveRoleAssignment(requestUrl, logger, args.options, cb);
66
- }, (err) => this.handleRejectedODataJsonPromise(err, logger, cb));
71
+ }
72
+ };
73
+ if (args.options.confirm) {
74
+ removeRoleAssignment();
67
75
  }
68
76
  else {
69
- this.RemoveRoleAssignment(requestUrl, logger, args.options, cb);
77
+ cli_1.Cli.prompt({
78
+ type: 'confirm',
79
+ name: 'continue',
80
+ default: false,
81
+ message: `Are you sure you want to remove role assignment from list ${args.options.listId || args.options.listTitle} from site ${args.options.webUrl}?`
82
+ }, (result) => {
83
+ if (!result.continue) {
84
+ cb();
85
+ }
86
+ else {
87
+ removeRoleAssignment();
88
+ }
89
+ });
70
90
  }
71
91
  }
72
92
  RemoveRoleAssignment(requestUrl, logger, options, cb) {
@@ -125,7 +145,8 @@ _SpoListRoleAssignmentRemoveCommand_instances = new WeakSet(), _SpoListRoleAssig
125
145
  listUrl: typeof args.options.listUrl !== 'undefined',
126
146
  principalId: typeof args.options.principalId !== 'undefined',
127
147
  upn: typeof args.options.upn !== 'undefined',
128
- groupName: typeof args.options.groupName !== 'undefined'
148
+ groupName: typeof args.options.groupName !== 'undefined',
149
+ confirm: (!(!args.options.confirm)).toString()
129
150
  });
130
151
  });
131
152
  }, _SpoListRoleAssignmentRemoveCommand_initOptions = function _SpoListRoleAssignmentRemoveCommand_initOptions() {
@@ -143,6 +164,8 @@ _SpoListRoleAssignmentRemoveCommand_instances = new WeakSet(), _SpoListRoleAssig
143
164
  option: '--upn [upn]'
144
165
  }, {
145
166
  option: '--groupName [groupName]'
167
+ }, {
168
+ option: '--confirm'
146
169
  });
147
170
  }, _SpoListRoleAssignmentRemoveCommand_initValidators = function _SpoListRoleAssignmentRemoveCommand_initValidators() {
148
171
  this.validators.push((args) => __awaiter(this, void 0, void 0, function* () {
@@ -160,10 +183,16 @@ _SpoListRoleAssignmentRemoveCommand_instances = new WeakSet(), _SpoListRoleAssig
160
183
  if (listOptions.some(item => item !== undefined) && listOptions.filter(item => item !== undefined).length > 1) {
161
184
  return `Specify either list id or title or list url`;
162
185
  }
186
+ if (listOptions.filter(item => item !== undefined).length === 0) {
187
+ return `Specify at least list id or title or list url`;
188
+ }
163
189
  const principalOptions = [args.options.principalId, args.options.upn, args.options.groupName];
164
190
  if (principalOptions.some(item => item !== undefined) && principalOptions.filter(item => item !== undefined).length > 1) {
165
191
  return `Specify either principalId id or upn or groupName`;
166
192
  }
193
+ if (principalOptions.filter(item => item !== undefined).length === 0) {
194
+ return `Specify at least principalId id or upn or groupName`;
195
+ }
167
196
  return true;
168
197
  }));
169
198
  };