@pnp/cli-microsoft365 10.0.0-beta.48e9f7d → 10.0.0-beta.a868b81

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.
Files changed (48) hide show
  1. package/allCommands.json +1 -1
  2. package/allCommandsFull.json +1 -1
  3. package/dist/Auth.js +11 -12
  4. package/dist/cli/cli.js +14 -0
  5. package/dist/config.js +60 -5
  6. package/dist/m365/base/PowerAutomateCommand.js +1 -1
  7. package/dist/m365/base/SpoCommand.js +1 -1
  8. package/dist/m365/cli/commands/cli-consent.js +2 -2
  9. package/dist/m365/cli/commands/cli-doctor.js +2 -2
  10. package/dist/m365/cli/commands/cli-reconsent.js +2 -3
  11. package/dist/m365/cli/commands/config/config-set.js +12 -4
  12. package/dist/m365/commands/login.js +28 -9
  13. package/dist/m365/commands/setup.js +256 -33
  14. package/dist/m365/commands/setupPresets.js +2 -4
  15. package/dist/m365/connection/commands/connection-list.js +4 -4
  16. package/dist/m365/entra/commands/app/app-add.js +52 -288
  17. package/dist/m365/flow/commands/environment/environment-get.js +1 -1
  18. package/dist/m365/flow/commands/environment/environment-list.js +1 -1
  19. package/dist/m365/flow/commands/flow-disable.js +1 -1
  20. package/dist/m365/flow/commands/flow-enable.js +1 -1
  21. package/dist/m365/flow/commands/flow-export.js +17 -16
  22. package/dist/m365/flow/commands/flow-get.js +1 -1
  23. package/dist/m365/flow/commands/flow-list.js +1 -1
  24. package/dist/m365/flow/commands/flow-remove.js +1 -1
  25. package/dist/m365/flow/commands/owner/owner-ensure.js +1 -1
  26. package/dist/m365/flow/commands/owner/owner-list.js +1 -1
  27. package/dist/m365/flow/commands/owner/owner-remove.js +1 -1
  28. package/dist/m365/flow/commands/run/run-cancel.js +1 -1
  29. package/dist/m365/flow/commands/run/run-get.js +1 -1
  30. package/dist/m365/flow/commands/run/run-list.js +1 -1
  31. package/dist/m365/flow/commands/run/run-resubmit.js +2 -2
  32. package/dist/m365/spo/commands/contenttype/contenttype-field-remove.js +8 -8
  33. package/dist/m365/spo/commands/contenttype/contenttype-field-set.js +2 -2
  34. package/dist/m365/spo/commands/file/file-roleassignment-add.js +17 -54
  35. package/dist/m365/spo/commands/file/file-roleassignment-remove.js +13 -40
  36. package/dist/m365/spo/commands/file/file-roleinheritance-break.js +5 -13
  37. package/dist/m365/spo/commands/file/file-roleinheritance-reset.js +5 -13
  38. package/dist/m365/spo/commands/list/list-get.js +17 -4
  39. package/dist/m365/spo/commands/page/page-section-add.js +185 -34
  40. package/dist/settingsNames.js +6 -1
  41. package/dist/utils/entraApp.js +283 -0
  42. package/dist/utils/spo.js +30 -7
  43. package/docs/docs/_clisettings.mdx +6 -1
  44. package/docs/docs/cmd/setup.mdx +17 -6
  45. package/docs/docs/cmd/spo/contenttype/contenttype-field-remove.mdx +7 -7
  46. package/docs/docs/cmd/spo/contenttype/contenttype-field-set.mdx +2 -2
  47. package/docs/docs/cmd/spo/page/page-section-add.mdx +57 -2
  48. package/package.json +1 -1
@@ -3,13 +3,14 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
3
3
  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");
4
4
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
5
  };
6
- var _SpoPageSectionAddCommand_instances, _a, _SpoPageSectionAddCommand_initTelemetry, _SpoPageSectionAddCommand_initOptions, _SpoPageSectionAddCommand_initValidators;
6
+ var _SpoPageSectionAddCommand_instances, _SpoPageSectionAddCommand_initTelemetry, _SpoPageSectionAddCommand_initOptions, _SpoPageSectionAddCommand_initValidators, _SpoPageSectionAddCommand_initTypes;
7
+ import { v4 } from 'uuid';
7
8
  import request from '../../../../request.js';
8
9
  import { formatting } from '../../../../utils/formatting.js';
9
10
  import { validation } from '../../../../utils/validation.js';
10
11
  import SpoCommand from '../../../base/SpoCommand.js';
11
12
  import commands from '../../commands.js';
12
- import { CanvasSectionTemplate, ZoneEmphasis } from './clientsidepages.js';
13
+ import { CanvasSectionTemplate } from './clientsidepages.js';
13
14
  class SpoPageSectionAddCommand extends SpoCommand {
14
15
  get name() {
15
16
  return commands.PAGE_SECTION_ADD;
@@ -20,13 +21,18 @@ class SpoPageSectionAddCommand extends SpoCommand {
20
21
  constructor() {
21
22
  super();
22
23
  _SpoPageSectionAddCommand_instances.add(this);
24
+ this.sectionTemplate = ['OneColumn', 'OneColumnFullWidth', 'TwoColumn', 'ThreeColumn', 'TwoColumnLeft', 'TwoColumnRight', 'Vertical'];
25
+ this.zoneEmphasis = ['None', 'Neutral', 'Soft', 'Strong', 'Image', 'Gradient'];
26
+ this.iconAlignment = ['Left', 'Right'];
27
+ this.fillMode = ['ScaleToFill', 'ScaleToFit', 'Tile', 'OriginalSize'];
23
28
  __classPrivateFieldGet(this, _SpoPageSectionAddCommand_instances, "m", _SpoPageSectionAddCommand_initTelemetry).call(this);
24
29
  __classPrivateFieldGet(this, _SpoPageSectionAddCommand_instances, "m", _SpoPageSectionAddCommand_initOptions).call(this);
25
30
  __classPrivateFieldGet(this, _SpoPageSectionAddCommand_instances, "m", _SpoPageSectionAddCommand_initValidators).call(this);
31
+ __classPrivateFieldGet(this, _SpoPageSectionAddCommand_instances, "m", _SpoPageSectionAddCommand_initTypes).call(this);
26
32
  }
27
33
  async commandAction(logger, args) {
28
34
  let pageFullName = args.options.pageName.toLowerCase();
29
- if (pageFullName.indexOf('.aspx') < 0) {
35
+ if (!pageFullName.endsWith('.aspx')) {
30
36
  pageFullName += '.aspx';
31
37
  }
32
38
  let canvasContent;
@@ -66,11 +72,22 @@ class SpoPageSectionAddCommand extends SpoCommand {
66
72
  .sort();
67
73
  // zoneIndex for the new section to add
68
74
  const zoneIndex = this.getSectionIndex(zoneIndices, args.options.order);
75
+ let zoneId;
76
+ let backgroundControlToAdd = undefined;
77
+ if (args.options.zoneEmphasis && ['image', 'gradient'].includes(args.options.zoneEmphasis.toLowerCase())) {
78
+ zoneId = v4();
79
+ // get background control based on control type 14
80
+ const backgroundControl = canvasContent.find(c => c.controlType === 14);
81
+ backgroundControlToAdd = this.setBackgroundControl(zoneId, backgroundControl, args);
82
+ if (!backgroundControl) {
83
+ canvasContent.push(backgroundControlToAdd);
84
+ }
85
+ }
69
86
  // get the list of columns to insert based on the selected template
70
- const columnsToAdd = this.getColumns(zoneIndex, args.options.sectionTemplate, args.options.zoneEmphasis, args.options.isLayoutReflowOnTop);
87
+ const columnsToAdd = this.getColumns(zoneIndex, args, zoneId);
71
88
  // insert the column in the right place in the array so that
72
89
  // it stays sorted ascending by zoneIndex
73
- let pos = canvasContent.findIndex(c => typeof c.controlType === 'undefined' && c.position.zoneIndex > zoneIndex);
90
+ let pos = canvasContent.findIndex(c => typeof c.controlType === 'undefined' && c.position && c.position.zoneIndex > zoneIndex);
74
91
  if (pos === -1) {
75
92
  pos = canvasContent.length - 1;
76
93
  }
@@ -107,71 +124,146 @@ class SpoPageSectionAddCommand extends SpoCommand {
107
124
  }
108
125
  return zoneIndices[order - 2] + ((zoneIndices[order - 1] - zoneIndices[order - 2]) / 2);
109
126
  }
110
- getColumns(zoneIndex, sectionTemplate, zoneEmphasis, isLayoutReflowOnTop) {
127
+ getColumns(zoneIndex, args, zoneId) {
111
128
  const columns = [];
112
129
  let sectionIndex = 1;
113
- switch (sectionTemplate) {
130
+ switch (args.options.sectionTemplate) {
114
131
  case 'OneColumnFullWidth':
115
- columns.push(this.getColumn(zoneIndex, sectionIndex++, 0, zoneEmphasis));
132
+ columns.push(this.getColumn(zoneIndex, sectionIndex++, 0, args, zoneId));
116
133
  break;
117
134
  case 'TwoColumn':
118
- columns.push(this.getColumn(zoneIndex, sectionIndex++, 6, zoneEmphasis));
119
- columns.push(this.getColumn(zoneIndex, sectionIndex++, 6, zoneEmphasis));
135
+ columns.push(this.getColumn(zoneIndex, sectionIndex++, 6, args, zoneId));
136
+ columns.push(this.getColumn(zoneIndex, sectionIndex++, 6, args, zoneId));
120
137
  break;
121
138
  case 'ThreeColumn':
122
- columns.push(this.getColumn(zoneIndex, sectionIndex++, 4, zoneEmphasis));
123
- columns.push(this.getColumn(zoneIndex, sectionIndex++, 4, zoneEmphasis));
124
- columns.push(this.getColumn(zoneIndex, sectionIndex++, 4, zoneEmphasis));
139
+ columns.push(this.getColumn(zoneIndex, sectionIndex++, 4, args, zoneId));
140
+ columns.push(this.getColumn(zoneIndex, sectionIndex++, 4, args, zoneId));
141
+ columns.push(this.getColumn(zoneIndex, sectionIndex++, 4, args, zoneId));
125
142
  break;
126
143
  case 'TwoColumnLeft':
127
- columns.push(this.getColumn(zoneIndex, sectionIndex++, 8, zoneEmphasis));
128
- columns.push(this.getColumn(zoneIndex, sectionIndex++, 4, zoneEmphasis));
144
+ columns.push(this.getColumn(zoneIndex, sectionIndex++, 8, args, zoneId));
145
+ columns.push(this.getColumn(zoneIndex, sectionIndex++, 4, args, zoneId));
129
146
  break;
130
147
  case 'TwoColumnRight':
131
- columns.push(this.getColumn(zoneIndex, sectionIndex++, 4, zoneEmphasis));
132
- columns.push(this.getColumn(zoneIndex, sectionIndex++, 8, zoneEmphasis));
148
+ columns.push(this.getColumn(zoneIndex, sectionIndex++, 4, args, zoneId));
149
+ columns.push(this.getColumn(zoneIndex, sectionIndex++, 8, args, zoneId));
133
150
  break;
134
151
  case 'Vertical':
135
- columns.push(this.getVerticalColumn(zoneEmphasis, isLayoutReflowOnTop));
152
+ columns.push(this.getVerticalColumn(args, zoneId));
136
153
  break;
137
154
  case 'OneColumn':
138
155
  default:
139
- columns.push(this.getColumn(zoneIndex, sectionIndex++, 12, zoneEmphasis));
156
+ columns.push(this.getColumn(zoneIndex, sectionIndex++, 12, args, zoneId));
140
157
  break;
141
158
  }
142
159
  return columns;
143
160
  }
144
- getColumn(zoneIndex, sectionIndex, sectionFactor, zoneEmphasis) {
161
+ getColumn(zoneIndex, sectionIndex, sectionFactor, args, zoneId) {
162
+ const { zoneEmphasis, isCollapsibleSection, isExpanded, showDivider, iconAlignment } = args.options;
145
163
  const columnValue = {
146
164
  displayMode: 2,
147
165
  position: {
148
166
  zoneIndex: zoneIndex,
149
167
  sectionIndex: sectionIndex,
150
168
  sectionFactor: sectionFactor,
151
- layoutIndex: 1
169
+ layoutIndex: 1,
170
+ zoneId: zoneId
152
171
  },
153
172
  emphasis: {}
154
173
  };
155
- if (zoneEmphasis) {
156
- const zoneEmphasisValue = ZoneEmphasis[zoneEmphasis];
174
+ if (zoneEmphasis && ['none', 'neutral', 'soft', 'strong'].includes(zoneEmphasis?.toLocaleLowerCase())) {
175
+ // Just these zoneEmphasis values should be added to column emphasis
176
+ const zoneEmphasisValue = ['none', 'neutral', 'soft', 'strong'].indexOf(zoneEmphasis.toLocaleLowerCase());
157
177
  columnValue.emphasis = { zoneEmphasis: zoneEmphasisValue };
158
178
  }
179
+ if (isCollapsibleSection) {
180
+ columnValue.zoneGroupMetadata = {
181
+ type: 1,
182
+ isExpanded: !!isExpanded,
183
+ showDividerLine: !!showDivider,
184
+ iconAlignment: iconAlignment && iconAlignment.toLocaleLowerCase() === "right" ? "right" : "left"
185
+ };
186
+ }
159
187
  return columnValue;
160
188
  }
161
- getVerticalColumn(zoneEmphasis, isLayoutReflowOnTop) {
162
- const columnValue = this.getColumn(1, 1, 12, zoneEmphasis);
163
- columnValue.position.isLayoutReflowOnTop = isLayoutReflowOnTop !== undefined ? true : false;
189
+ getVerticalColumn(args, zoneId) {
190
+ const columnValue = this.getColumn(1, 1, 12, args, zoneId);
191
+ columnValue.position.isLayoutReflowOnTop = args.options.isLayoutReflowOnTop !== undefined;
164
192
  columnValue.position.layoutIndex = 2;
165
193
  columnValue.position.controlIndex = 1;
166
194
  return columnValue;
167
195
  }
196
+ setBackgroundControl(zoneId, backgroundControl, args) {
197
+ const { overlayColor, overlayOpacity, useLightText, imageUrl } = args.options;
198
+ const backgroundDetails = this.getBackgroundDetails(args);
199
+ if (!backgroundControl) {
200
+ backgroundControl = {
201
+ controlType: 14,
202
+ webPartData: {
203
+ properties: {
204
+ zoneBackground: {}
205
+ },
206
+ serverProcessedContent: {
207
+ htmlStrings: {},
208
+ searchablePlainTexts: {},
209
+ imageSources: {},
210
+ links: {}
211
+ },
212
+ dataVersion: "1.0"
213
+ }
214
+ };
215
+ }
216
+ backgroundControl.webPartData.properties.zoneBackground[zoneId] = {
217
+ ...backgroundDetails,
218
+ useLightText: !!useLightText,
219
+ overlay: {
220
+ color: overlayColor ? overlayColor : "#FFFFFF",
221
+ opacity: overlayOpacity ? overlayOpacity : 60
222
+ }
223
+ };
224
+ if (imageUrl && backgroundControl.webPartData.serverProcessedContent.imageSources) {
225
+ backgroundControl.webPartData.serverProcessedContent.imageSources[`zoneBackground.${zoneId}.imageData.url`] = imageUrl;
226
+ }
227
+ return backgroundControl;
228
+ }
229
+ getBackgroundDetails(args) {
230
+ const { gradientText, imageUrl, imageHeight, imageWidth, fillMode } = args.options;
231
+ const backgroundDetails = {};
232
+ if (gradientText) {
233
+ backgroundDetails.type = "gradient";
234
+ backgroundDetails.gradient = gradientText;
235
+ }
236
+ if (imageUrl) {
237
+ backgroundDetails.type = "image";
238
+ backgroundDetails.imageData = {
239
+ source: 2,
240
+ fileName: "sectionbackground.jpg",
241
+ height: imageHeight ? imageHeight : 955,
242
+ width: imageWidth ? imageWidth : 555
243
+ };
244
+ backgroundDetails.fillMode = fillMode ? this.fillMode.indexOf(fillMode) : 0;
245
+ }
246
+ return backgroundDetails;
247
+ }
168
248
  }
169
- _a = SpoPageSectionAddCommand, _SpoPageSectionAddCommand_instances = new WeakSet(), _SpoPageSectionAddCommand_initTelemetry = function _SpoPageSectionAddCommand_initTelemetry() {
249
+ _SpoPageSectionAddCommand_instances = new WeakSet(), _SpoPageSectionAddCommand_initTelemetry = function _SpoPageSectionAddCommand_initTelemetry() {
170
250
  this.telemetry.push((args) => {
171
251
  Object.assign(this.telemetryProperties, {
172
252
  order: typeof args.options.order !== 'undefined',
173
253
  zoneEmphasis: typeof args.options.zoneEmphasis !== 'undefined',
174
- isLayoutReflowOnTop: !!args.options.isLayoutReflowOnTop
254
+ isLayoutReflowOnTop: !!args.options.isLayoutReflowOnTop,
255
+ isCollapsibleSection: !!args.options.isCollapsibleSection,
256
+ showDivider: !!typeof args.options.showDivider,
257
+ iconAlignment: typeof args.options.iconAlignment !== 'undefined',
258
+ isExpanded: !!args.options.isExpanded,
259
+ gradientText: typeof args.options.gradientText !== 'undefined',
260
+ imageUrl: typeof args.options.imageUrl !== 'undefined',
261
+ imageHeight: typeof args.options.imageHeight !== 'undefined',
262
+ imageWidth: typeof args.options.imageWidth !== 'undefined',
263
+ fillMode: typeof args.options.fillMode !== 'undefined',
264
+ useLightText: !!args.options.useLightText,
265
+ overlayColor: typeof args.options.overlayColor !== 'undefined',
266
+ overlayOpacity: typeof args.options.overlayOpacity !== 'undefined'
175
267
  });
176
268
  });
177
269
  }, _SpoPageSectionAddCommand_initOptions = function _SpoPageSectionAddCommand_initOptions() {
@@ -181,14 +273,40 @@ _a = SpoPageSectionAddCommand, _SpoPageSectionAddCommand_instances = new WeakSet
181
273
  option: '-u, --webUrl <webUrl>'
182
274
  }, {
183
275
  option: '-t, --sectionTemplate <sectionTemplate>',
184
- autocomplete: _a.SectionTemplate
276
+ autocomplete: this.sectionTemplate
185
277
  }, {
186
278
  option: '--order [order]'
187
279
  }, {
188
280
  option: '--zoneEmphasis [zoneEmphasis]',
189
- autocomplete: _a.ZoneEmphasis
281
+ autocomplete: this.zoneEmphasis
190
282
  }, {
191
283
  option: '--isLayoutReflowOnTop'
284
+ }, {
285
+ option: '--isCollapsibleSection'
286
+ }, {
287
+ option: '--showDivider'
288
+ }, {
289
+ option: '--iconAlignment [iconAlignment]',
290
+ autocomplete: this.iconAlignment
291
+ }, {
292
+ option: '--isExpanded'
293
+ }, {
294
+ option: '--gradientText [gradientText]'
295
+ }, {
296
+ option: '--imageUrl [imageUrl]'
297
+ }, {
298
+ option: '--imageHeight [imageHeight]'
299
+ }, {
300
+ option: '--imageWidth [imageWidth]'
301
+ }, {
302
+ option: '--fillMode [fillMode]',
303
+ autocomplete: this.fillMode
304
+ }, {
305
+ option: '--useLightText'
306
+ }, {
307
+ option: '--overlayColor [overlayColor]'
308
+ }, {
309
+ option: '--overlayOpacity [overlayOpacity]'
192
310
  });
193
311
  }, _SpoPageSectionAddCommand_initValidators = function _SpoPageSectionAddCommand_initValidators() {
194
312
  this.validators.push(async (args) => {
@@ -201,8 +319,8 @@ _a = SpoPageSectionAddCommand, _SpoPageSectionAddCommand_instances = new WeakSet
201
319
  }
202
320
  }
203
321
  if (typeof args.options.zoneEmphasis !== 'undefined') {
204
- if (!(args.options.zoneEmphasis in ZoneEmphasis)) {
205
- return 'The value of parameter zoneEmphasis must be None|Neutral|Soft|Strong';
322
+ if (!this.zoneEmphasis.some(zoneEmphasisValue => zoneEmphasisValue.toLocaleLowerCase() === args.options.zoneEmphasis?.toLowerCase())) {
323
+ return `The value of parameter zoneEmphasis must be ${this.zoneEmphasis.join(', ')}`;
206
324
  }
207
325
  }
208
326
  if (typeof args.options.isLayoutReflowOnTop !== 'undefined') {
@@ -210,10 +328,43 @@ _a = SpoPageSectionAddCommand, _SpoPageSectionAddCommand_instances = new WeakSet
210
328
  return 'Specify isLayoutReflowOnTop when the sectionTemplate is set to Vertical.';
211
329
  }
212
330
  }
331
+ if (typeof args.options.iconAlignment !== 'undefined') {
332
+ if (!this.iconAlignment.some(iconAlignmentValue => iconAlignmentValue.toLocaleLowerCase() === args.options.iconAlignment?.toLowerCase())) {
333
+ return `The value of parameter iconAlignment must be ${this.iconAlignment.join(', ')}`;
334
+ }
335
+ }
336
+ if (typeof args.options.fillMode !== 'undefined') {
337
+ if (!this.fillMode.some(fillModeValue => fillModeValue.toLocaleLowerCase() === args.options.fillMode?.toLowerCase())) {
338
+ return `The value of parameter fillMode must be ${this.fillMode.join(', ')}`;
339
+ }
340
+ }
341
+ if (args.options.zoneEmphasis?.toLocaleLowerCase() !== 'image' && (args.options.imageUrl || args.options.imageWidth ||
342
+ args.options.imageHeight || args.options.fillMode)) {
343
+ return 'Specify imageUrl, imageWidth, imageHeight or fillMode only when zoneEmphasis is set to Image';
344
+ }
345
+ if (args.options.zoneEmphasis?.toLocaleLowerCase() === 'image' && !args.options.imageUrl) {
346
+ return 'Specify imageUrl when zoneEmphasis is set to Image';
347
+ }
348
+ if (args.options.zoneEmphasis?.toLowerCase() !== 'gradient' && args.options.gradientText) {
349
+ return 'Specify gradientText only when zoneEmphasis is set to Gradient';
350
+ }
351
+ if (args.options.zoneEmphasis?.toLowerCase() === 'gradient' && !args.options.gradientText) {
352
+ return 'Specify gradientText when zoneEmphasis is set to Gradient';
353
+ }
354
+ if (args.options.overlayOpacity && (args.options.overlayOpacity < 0 || args.options.overlayOpacity > 100)) {
355
+ return 'The value of parameter overlayOpacity must be between 0 and 100';
356
+ }
357
+ if (args.options.overlayColor && !/^#[0-9a-f]{6}$/i.test(args.options.overlayColor)) {
358
+ return 'The value of parameter overlayColor must be a valid hex color';
359
+ }
360
+ if (!(args.options.zoneEmphasis && ['image', 'gradient'].includes(args.options.zoneEmphasis.toLowerCase())) && (args.options.overlayColor || args.options.overlayOpacity || args.options.useLightText)) {
361
+ return 'Specify overlayColor or overlayOpacity only when zoneEmphasis is set to Image or Gradient';
362
+ }
213
363
  return validation.isValidSharePointUrl(args.options.webUrl);
214
364
  });
365
+ }, _SpoPageSectionAddCommand_initTypes = function _SpoPageSectionAddCommand_initTypes() {
366
+ this.types.string = ['pageName', 'webUrl', 'sectionTemplate', 'zoneEmphasis', 'iconAlignment', 'gradientText', 'imageUrl', 'fillMode', 'overlayColor'];
367
+ this.types.boolean = ['isLayoutReflowOnTop', 'isCollapsibleSection', 'showDivider', 'isExpanded', 'useLightText'];
215
368
  };
216
- SpoPageSectionAddCommand.SectionTemplate = ['OneColumn', 'OneColumnFullWidth', 'TwoColumn', 'ThreeColumn', 'TwoColumnLeft', 'TwoColumnRight', 'Vertical'];
217
- SpoPageSectionAddCommand.ZoneEmphasis = ['None', 'Neutral', 'Soft', 'Strong'];
218
369
  export default new SpoPageSectionAddCommand();
219
370
  //# sourceMappingURL=page-section-add.js.map
@@ -1,6 +1,11 @@
1
1
  const settingsNames = {
2
2
  authType: 'authType',
3
3
  autoOpenLinksInBrowser: 'autoOpenLinksInBrowser',
4
+ clientId: 'clientId',
5
+ clientSecret: 'clientSecret',
6
+ clientCertificateFile: 'clientCertificateFile',
7
+ clientCertificateBase64Encoded: 'clientCertificateBase64Encoded',
8
+ clientCertificatePassword: 'clientCertificatePassword',
4
9
  copyDeviceCodeToClipboard: 'copyDeviceCodeToClipboard',
5
10
  csvEscape: 'csvEscape',
6
11
  csvHeader: 'csvHeader',
@@ -16,7 +21,7 @@ const settingsNames = {
16
21
  prompt: 'prompt',
17
22
  promptListPageSize: 'promptListPageSize',
18
23
  showHelpOnFailure: 'showHelpOnFailure',
19
- showSpinner: 'showSpinner'
24
+ tenantId: 'tenantId'
20
25
  };
21
26
  export { settingsNames };
22
27
  //# sourceMappingURL=settingsNames.js.map
@@ -0,0 +1,283 @@
1
+ import fs from 'fs';
2
+ import request from '../request.js';
3
+ import { odata } from './odata.js';
4
+ async function getCertificateBase64Encoded({ options, logger, debug }) {
5
+ if (options.certificateBase64Encoded) {
6
+ return options.certificateBase64Encoded;
7
+ }
8
+ if (debug) {
9
+ await logger.logToStderr(`Reading existing ${options.certificateFile}...`);
10
+ }
11
+ try {
12
+ return fs.readFileSync(options.certificateFile, { encoding: 'base64' });
13
+ }
14
+ catch (e) {
15
+ throw new Error(`Error reading certificate file: ${e}. Please add the certificate using base64 option '--certificateBase64Encoded'.`);
16
+ }
17
+ }
18
+ async function createServicePrincipal(appId) {
19
+ const requestOptions = {
20
+ url: `https://graph.microsoft.com/v1.0/myorganization/servicePrincipals`,
21
+ headers: {
22
+ 'content-type': 'application/json'
23
+ },
24
+ data: {
25
+ appId: appId
26
+ },
27
+ responseType: 'json'
28
+ };
29
+ return request.post(requestOptions);
30
+ }
31
+ async function grantOAuth2Permission({ appId, resourceId, scopeName }) {
32
+ const grantAdminConsentApplicationRequestOptions = {
33
+ url: `https://graph.microsoft.com/v1.0/myorganization/oauth2PermissionGrants`,
34
+ headers: {
35
+ accept: 'application/json;odata.metadata=none'
36
+ },
37
+ responseType: 'json',
38
+ data: {
39
+ clientId: appId,
40
+ consentType: "AllPrincipals",
41
+ principalId: null,
42
+ resourceId: resourceId,
43
+ scope: scopeName
44
+ }
45
+ };
46
+ return request.post(grantAdminConsentApplicationRequestOptions);
47
+ }
48
+ async function addRoleToServicePrincipal({ objectId, resourceId, appRoleId }) {
49
+ const requestOptions = {
50
+ url: `https://graph.microsoft.com/v1.0/myorganization/servicePrincipals/${objectId}/appRoleAssignments`,
51
+ headers: {
52
+ 'Content-Type': 'application/json'
53
+ },
54
+ responseType: 'json',
55
+ data: {
56
+ appRoleId: appRoleId,
57
+ principalId: objectId,
58
+ resourceId: resourceId
59
+ }
60
+ };
61
+ return request.post(requestOptions);
62
+ }
63
+ async function getRequiredResourceAccessForApis({ servicePrincipals, apis, scopeType, logger, debug }) {
64
+ if (!apis) {
65
+ return [];
66
+ }
67
+ const resolvedApis = [];
68
+ const requestedApis = apis.split(',').map(a => a.trim());
69
+ for (const api of requestedApis) {
70
+ const pos = api.lastIndexOf('/');
71
+ const permissionName = api.substring(pos + 1);
72
+ const servicePrincipalName = api.substring(0, pos);
73
+ if (debug) {
74
+ await logger.logToStderr(`Resolving ${api}...`);
75
+ await logger.logToStderr(`Permission name: ${permissionName}`);
76
+ await logger.logToStderr(`Service principal name: ${servicePrincipalName}`);
77
+ }
78
+ const servicePrincipal = servicePrincipals.find(sp => (sp.servicePrincipalNames.indexOf(servicePrincipalName) > -1 ||
79
+ sp.servicePrincipalNames.indexOf(`${servicePrincipalName}/`) > -1));
80
+ if (!servicePrincipal) {
81
+ throw `Service principal ${servicePrincipalName} not found`;
82
+ }
83
+ const scopesOfType = scopeType === 'Scope' ? servicePrincipal.oauth2PermissionScopes : servicePrincipal.appRoles;
84
+ const permission = scopesOfType.find(scope => scope.value === permissionName);
85
+ if (!permission) {
86
+ throw `Permission ${permissionName} for service principal ${servicePrincipalName} not found`;
87
+ }
88
+ let resolvedApi = resolvedApis.find(a => a.resourceAppId === servicePrincipal.appId);
89
+ if (!resolvedApi) {
90
+ resolvedApi = {
91
+ resourceAppId: servicePrincipal.appId,
92
+ resourceAccess: []
93
+ };
94
+ resolvedApis.push(resolvedApi);
95
+ }
96
+ const resourceAccessPermission = {
97
+ id: permission.id,
98
+ type: scopeType
99
+ };
100
+ resolvedApi.resourceAccess.push(resourceAccessPermission);
101
+ updateAppPermissions({
102
+ spId: servicePrincipal.id,
103
+ resourceAccessPermission,
104
+ oAuth2PermissionValue: permission.value
105
+ });
106
+ }
107
+ return resolvedApis;
108
+ }
109
+ function updateAppPermissions({ spId, resourceAccessPermission, oAuth2PermissionValue }) {
110
+ // During API resolution, we store globally both app role assignments and oauth2permissions
111
+ // So that we'll be able to parse them during the admin consent process
112
+ let existingPermission = entraApp.appPermissions.find(oauth => oauth.resourceId === spId);
113
+ if (!existingPermission) {
114
+ existingPermission = {
115
+ resourceId: spId,
116
+ resourceAccess: [],
117
+ scope: []
118
+ };
119
+ entraApp.appPermissions.push(existingPermission);
120
+ }
121
+ if (resourceAccessPermission.type === 'Scope' && oAuth2PermissionValue && !existingPermission.scope.find(scp => scp === oAuth2PermissionValue)) {
122
+ existingPermission.scope.push(oAuth2PermissionValue);
123
+ }
124
+ if (!existingPermission.resourceAccess.find(res => res.id === resourceAccessPermission.id)) {
125
+ existingPermission.resourceAccess.push(resourceAccessPermission);
126
+ }
127
+ }
128
+ export const entraApp = {
129
+ appPermissions: [],
130
+ createAppRegistration: async ({ options, apis, logger, verbose, debug }) => {
131
+ const applicationInfo = {
132
+ displayName: options.name,
133
+ signInAudience: options.multitenant ? 'AzureADMultipleOrgs' : 'AzureADMyOrg'
134
+ };
135
+ if (apis.length > 0) {
136
+ applicationInfo.requiredResourceAccess = apis;
137
+ }
138
+ if (options.redirectUris) {
139
+ applicationInfo[options.platform] = {
140
+ redirectUris: options.redirectUris.split(',').map(u => u.trim())
141
+ };
142
+ }
143
+ if (options.implicitFlow) {
144
+ if (!applicationInfo.web) {
145
+ applicationInfo.web = {};
146
+ }
147
+ applicationInfo.web.implicitGrantSettings = {
148
+ enableAccessTokenIssuance: true,
149
+ enableIdTokenIssuance: true
150
+ };
151
+ }
152
+ if (options.certificateFile || options.certificateBase64Encoded) {
153
+ const certificateBase64Encoded = await getCertificateBase64Encoded({ options, logger, debug });
154
+ const newKeyCredential = {
155
+ type: 'AsymmetricX509Cert',
156
+ usage: 'Verify',
157
+ displayName: options.certificateDisplayName,
158
+ key: certificateBase64Encoded
159
+ };
160
+ applicationInfo.keyCredentials = [newKeyCredential];
161
+ }
162
+ if (options.allowPublicClientFlows) {
163
+ applicationInfo.isFallbackPublicClient = true;
164
+ }
165
+ if (verbose) {
166
+ await logger.logToStderr(`Creating Microsoft Entra app registration...`);
167
+ }
168
+ const createApplicationRequestOptions = {
169
+ url: `https://graph.microsoft.com/v1.0/myorganization/applications`,
170
+ headers: {
171
+ accept: 'application/json;odata.metadata=none'
172
+ },
173
+ responseType: 'json',
174
+ data: applicationInfo
175
+ };
176
+ return request.post(createApplicationRequestOptions);
177
+ },
178
+ grantAdminConsent: async ({ appInfo, appPermissions, adminConsent, logger, debug }) => {
179
+ if (!adminConsent || appPermissions.length === 0) {
180
+ return appInfo;
181
+ }
182
+ const sp = await createServicePrincipal(appInfo.appId);
183
+ if (debug) {
184
+ await logger.logToStderr("Service principal created, returned object id: " + sp.id);
185
+ }
186
+ const tasks = [];
187
+ appPermissions.forEach(async (permission) => {
188
+ if (permission.scope.length > 0) {
189
+ tasks.push(grantOAuth2Permission({
190
+ appId: sp.id,
191
+ resourceId: permission.resourceId,
192
+ scopeName: permission.scope.join(' ')
193
+ }));
194
+ if (debug) {
195
+ await logger.logToStderr(`Admin consent granted for following resource ${permission.resourceId}, with delegated permissions: ${permission.scope.join(',')}`);
196
+ }
197
+ }
198
+ permission.resourceAccess.filter(access => access.type === "Role").forEach(async (access) => {
199
+ tasks.push(addRoleToServicePrincipal({
200
+ objectId: sp.id,
201
+ resourceId: permission.resourceId,
202
+ appRoleId: access.id
203
+ }));
204
+ if (debug) {
205
+ await logger.logToStderr(`Admin consent granted for following resource ${permission.resourceId}, with application permission: ${access.id}`);
206
+ }
207
+ });
208
+ });
209
+ await Promise.all(tasks);
210
+ return appInfo;
211
+ },
212
+ resolveApis: async ({ options, manifest, logger, verbose, debug }) => {
213
+ if (!options.apisDelegated && !options.apisApplication
214
+ && (typeof manifest?.requiredResourceAccess === 'undefined' || manifest.requiredResourceAccess.length === 0)) {
215
+ return [];
216
+ }
217
+ if (verbose) {
218
+ await logger.logToStderr('Resolving requested APIs...');
219
+ }
220
+ const servicePrincipals = await odata.getAllItems(`https://graph.microsoft.com/v1.0/myorganization/servicePrincipals?$select=appId,appRoles,id,oauth2PermissionScopes,servicePrincipalNames`);
221
+ let resolvedApis = [];
222
+ if (options.apisDelegated || options.apisApplication) {
223
+ resolvedApis = await getRequiredResourceAccessForApis({
224
+ servicePrincipals,
225
+ apis: options.apisDelegated,
226
+ scopeType: 'Scope',
227
+ logger,
228
+ debug
229
+ });
230
+ if (verbose) {
231
+ await logger.logToStderr(`Resolved delegated permissions: ${JSON.stringify(resolvedApis, null, 2)}`);
232
+ }
233
+ const resolvedApplicationApis = await getRequiredResourceAccessForApis({
234
+ servicePrincipals,
235
+ apis: options.apisApplication,
236
+ scopeType: 'Role',
237
+ logger,
238
+ debug
239
+ });
240
+ if (verbose) {
241
+ await logger.logToStderr(`Resolved application permissions: ${JSON.stringify(resolvedApplicationApis, null, 2)}`);
242
+ }
243
+ // merge resolved application APIs onto resolved delegated APIs
244
+ resolvedApplicationApis.forEach(resolvedRequiredResource => {
245
+ const requiredResource = resolvedApis.find(api => api.resourceAppId === resolvedRequiredResource.resourceAppId);
246
+ if (requiredResource) {
247
+ requiredResource.resourceAccess.push(...resolvedRequiredResource.resourceAccess);
248
+ }
249
+ else {
250
+ resolvedApis.push(resolvedRequiredResource);
251
+ }
252
+ });
253
+ }
254
+ else {
255
+ const manifestApis = manifest.requiredResourceAccess;
256
+ manifestApis.forEach(manifestApi => {
257
+ resolvedApis.push(manifestApi);
258
+ const app = servicePrincipals.find(servicePrincipals => servicePrincipals.appId === manifestApi.resourceAppId);
259
+ if (app) {
260
+ manifestApi.resourceAccess.forEach((res => {
261
+ const resourceAccessPermission = {
262
+ id: res.id,
263
+ type: res.type
264
+ };
265
+ const oAuthValue = app.oauth2PermissionScopes.find(scp => scp.id === res.id)?.value;
266
+ updateAppPermissions({
267
+ spId: app.id,
268
+ resourceAccessPermission,
269
+ oAuth2PermissionValue: oAuthValue
270
+ });
271
+ }));
272
+ }
273
+ });
274
+ }
275
+ if (verbose) {
276
+ await logger.logToStderr(`Merged delegated and application permissions: ${JSON.stringify(resolvedApis, null, 2)}`);
277
+ await logger.logToStderr(`App role assignments: ${JSON.stringify(entraApp.appPermissions.flatMap(permission => permission.resourceAccess.filter(access => access.type === "Role")), null, 2)}`);
278
+ await logger.logToStderr(`OAuth2 permissions: ${JSON.stringify(entraApp.appPermissions.flatMap(permission => permission.scope), null, 2)}`);
279
+ }
280
+ return resolvedApis;
281
+ }
282
+ };
283
+ //# sourceMappingURL=entraApp.js.map