@pnp/cli-microsoft365 11.6.0-beta.358a4f1 → 11.6.0-beta.bc374af
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/.devproxy/api-specs/sharepoint-admin.yaml +40 -0
- package/.devproxy/api-specs/sharepoint.yaml +48 -0
- package/allCommands.json +1 -1
- package/allCommandsFull.json +1 -1
- package/dist/m365/entra/commands/user/user-recyclebinitem-list.js +5 -0
- package/dist/m365/outlook/commands/calendargroup/calendargroup-list.js +87 -0
- package/dist/m365/outlook/commands.js +1 -0
- package/dist/m365/spo/commands/agent/agent-add.js +172 -0
- package/dist/m365/spo/commands/list/list-set.js +186 -378
- package/dist/m365/spo/commands/navigation/navigation-node-get.js +18 -28
- package/dist/m365/spo/commands/navigation/navigation-node-list.js +14 -39
- package/dist/m365/spo/commands/site/site-accessrequest-setting-set.js +102 -0
- package/dist/m365/spo/commands/site/site-add.js +38 -8
- package/dist/m365/spo/commands/tenant/tenant-site-get.js +112 -0
- package/dist/m365/spo/commands.js +3 -0
- package/dist/utils/accessToken.js +21 -0
- package/dist/utils/brandCenter.js +29 -0
- package/docs/docs/cmd/entra/app/app-role-add.mdx +21 -0
- package/docs/docs/cmd/entra/app/app-role-list.mdx +20 -1
- package/docs/docs/cmd/entra/app/app-role-remove.mdx +22 -1
- package/docs/docs/cmd/entra/policy/policy-list.mdx +19 -0
- package/docs/docs/cmd/entra/resourcenamespace/resourcenamespace-list.mdx +19 -0
- package/docs/docs/cmd/outlook/calendargroup/calendargroup-list.mdx +120 -0
- package/docs/docs/cmd/spo/agent/agent-add.mdx +190 -0
- package/docs/docs/cmd/spo/list/list-set.mdx +19 -1
- package/docs/docs/cmd/spo/navigation/navigation-node-get.mdx +43 -10
- package/docs/docs/cmd/spo/navigation/navigation-node-list.mdx +36 -3
- package/docs/docs/cmd/spo/site/site-accessrequest-setting-set.mdx +77 -0
- package/docs/docs/cmd/spo/site/site-add.mdx +14 -5
- package/docs/docs/cmd/spo/tenant/tenant-site-get.mdx +479 -0
- package/package.json +1 -1
|
@@ -1,13 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
|
-
};
|
|
6
|
-
var _SpoNavigationNodeGetCommand_instances, _SpoNavigationNodeGetCommand_initOptions, _SpoNavigationNodeGetCommand_initValidators;
|
|
1
|
+
import { globalOptionsZod } from '../../../../Command.js';
|
|
2
|
+
import { z } from 'zod';
|
|
7
3
|
import request from '../../../../request.js';
|
|
8
4
|
import { validation } from '../../../../utils/validation.js';
|
|
9
5
|
import SpoCommand from '../../../base/SpoCommand.js';
|
|
10
6
|
import commands from '../../commands.js';
|
|
7
|
+
export const options = z.strictObject({
|
|
8
|
+
...globalOptionsZod.shape,
|
|
9
|
+
webUrl: z.string()
|
|
10
|
+
.refine(url => validation.isValidSharePointUrl(url) === true, {
|
|
11
|
+
error: e => `'${e.input}' is not a valid SharePoint Online site URL.`
|
|
12
|
+
})
|
|
13
|
+
.alias('u'),
|
|
14
|
+
id: z.int().positive()
|
|
15
|
+
});
|
|
11
16
|
class SpoNavigationNodeGetCommand extends SpoCommand {
|
|
12
17
|
get name() {
|
|
13
18
|
return commands.NAVIGATION_NODE_GET;
|
|
@@ -15,25 +20,25 @@ class SpoNavigationNodeGetCommand extends SpoCommand {
|
|
|
15
20
|
get description() {
|
|
16
21
|
return 'Retrieve information about a specific navigation node';
|
|
17
22
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
_SpoNavigationNodeGetCommand_instances.add(this);
|
|
21
|
-
__classPrivateFieldGet(this, _SpoNavigationNodeGetCommand_instances, "m", _SpoNavigationNodeGetCommand_initOptions).call(this);
|
|
22
|
-
__classPrivateFieldGet(this, _SpoNavigationNodeGetCommand_instances, "m", _SpoNavigationNodeGetCommand_initValidators).call(this);
|
|
23
|
+
get schema() {
|
|
24
|
+
return options;
|
|
23
25
|
}
|
|
24
26
|
async commandAction(logger, args) {
|
|
25
27
|
if (this.verbose) {
|
|
26
28
|
await logger.logToStderr(`Retrieving information about navigation node with id ${args.options.id}`);
|
|
27
29
|
}
|
|
28
30
|
const requestOptions = {
|
|
29
|
-
url: `${args.options.webUrl}/_api/web/navigation/GetNodeById(${args.options.id})`,
|
|
31
|
+
url: `${args.options.webUrl}/_api/web/navigation/GetNodeById(${args.options.id})?$expand=Children,Children/Children,Children/Children/Children`,
|
|
30
32
|
headers: {
|
|
31
|
-
|
|
33
|
+
accept: 'application/json;odata=nometadata'
|
|
32
34
|
},
|
|
33
35
|
responseType: 'json'
|
|
34
36
|
};
|
|
35
37
|
try {
|
|
36
38
|
const listInstance = await request.get(requestOptions);
|
|
39
|
+
if (listInstance['odata.null']) {
|
|
40
|
+
throw `No navigation node found with id ${args.options.id}.`;
|
|
41
|
+
}
|
|
37
42
|
await logger.log(listInstance);
|
|
38
43
|
}
|
|
39
44
|
catch (err) {
|
|
@@ -41,20 +46,5 @@ class SpoNavigationNodeGetCommand extends SpoCommand {
|
|
|
41
46
|
}
|
|
42
47
|
}
|
|
43
48
|
}
|
|
44
|
-
_SpoNavigationNodeGetCommand_instances = new WeakSet(), _SpoNavigationNodeGetCommand_initOptions = function _SpoNavigationNodeGetCommand_initOptions() {
|
|
45
|
-
this.options.unshift({
|
|
46
|
-
option: '-u, --webUrl <webUrl>'
|
|
47
|
-
}, {
|
|
48
|
-
option: '--id <id>'
|
|
49
|
-
});
|
|
50
|
-
}, _SpoNavigationNodeGetCommand_initValidators = function _SpoNavigationNodeGetCommand_initValidators() {
|
|
51
|
-
this.validators.push(async (args) => {
|
|
52
|
-
const id = parseInt(args.options.id);
|
|
53
|
-
if (isNaN(id)) {
|
|
54
|
-
return `${args.options.id} is not a valid number`;
|
|
55
|
-
}
|
|
56
|
-
return validation.isValidSharePointUrl(args.options.webUrl);
|
|
57
|
-
});
|
|
58
|
-
};
|
|
59
49
|
export default new SpoNavigationNodeGetCommand();
|
|
60
50
|
//# sourceMappingURL=navigation-node-get.js.map
|
|
@@ -1,13 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
|
-
};
|
|
6
|
-
var _SpoNavigationNodeListCommand_instances, _SpoNavigationNodeListCommand_initTelemetry, _SpoNavigationNodeListCommand_initOptions, _SpoNavigationNodeListCommand_initValidators;
|
|
1
|
+
import { globalOptionsZod } from '../../../../Command.js';
|
|
2
|
+
import { z } from 'zod';
|
|
7
3
|
import { odata } from '../../../../utils/odata.js';
|
|
8
4
|
import { validation } from '../../../../utils/validation.js';
|
|
9
5
|
import SpoCommand from '../../../base/SpoCommand.js';
|
|
10
6
|
import commands from '../../commands.js';
|
|
7
|
+
export const options = z.strictObject({
|
|
8
|
+
...globalOptionsZod.shape,
|
|
9
|
+
webUrl: z.string()
|
|
10
|
+
.refine(url => validation.isValidSharePointUrl(url) === true, {
|
|
11
|
+
error: e => `'${e.input}' is not a valid SharePoint Online site URL.`
|
|
12
|
+
})
|
|
13
|
+
.alias('u'),
|
|
14
|
+
location: z.enum(['QuickLaunch', 'TopNavigationBar']).alias('l')
|
|
15
|
+
});
|
|
11
16
|
class SpoNavigationNodeListCommand extends SpoCommand {
|
|
12
17
|
get name() {
|
|
13
18
|
return commands.NAVIGATION_NODE_LIST;
|
|
@@ -18,19 +23,15 @@ class SpoNavigationNodeListCommand extends SpoCommand {
|
|
|
18
23
|
defaultProperties() {
|
|
19
24
|
return ['Id', 'Title', 'Url'];
|
|
20
25
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
_SpoNavigationNodeListCommand_instances.add(this);
|
|
24
|
-
__classPrivateFieldGet(this, _SpoNavigationNodeListCommand_instances, "m", _SpoNavigationNodeListCommand_initTelemetry).call(this);
|
|
25
|
-
__classPrivateFieldGet(this, _SpoNavigationNodeListCommand_instances, "m", _SpoNavigationNodeListCommand_initOptions).call(this);
|
|
26
|
-
__classPrivateFieldGet(this, _SpoNavigationNodeListCommand_instances, "m", _SpoNavigationNodeListCommand_initValidators).call(this);
|
|
26
|
+
get schema() {
|
|
27
|
+
return options;
|
|
27
28
|
}
|
|
28
29
|
async commandAction(logger, args) {
|
|
29
30
|
if (this.verbose) {
|
|
30
31
|
await logger.logToStderr(`Retrieving navigation nodes...`);
|
|
31
32
|
}
|
|
32
33
|
try {
|
|
33
|
-
const res = await odata.getAllItems(`${args.options.webUrl}/_api/web/navigation/${args.options.location.toLowerCase()}`);
|
|
34
|
+
const res = await odata.getAllItems(`${args.options.webUrl}/_api/web/navigation/${args.options.location.toLowerCase()}?$expand=Children,Children/Children,Children/Children/Children`);
|
|
34
35
|
await logger.log(res);
|
|
35
36
|
}
|
|
36
37
|
catch (err) {
|
|
@@ -38,31 +39,5 @@ class SpoNavigationNodeListCommand extends SpoCommand {
|
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
41
|
}
|
|
41
|
-
_SpoNavigationNodeListCommand_instances = new WeakSet(), _SpoNavigationNodeListCommand_initTelemetry = function _SpoNavigationNodeListCommand_initTelemetry() {
|
|
42
|
-
this.telemetry.push((args) => {
|
|
43
|
-
Object.assign(this.telemetryProperties, {
|
|
44
|
-
location: args.options.location
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
}, _SpoNavigationNodeListCommand_initOptions = function _SpoNavigationNodeListCommand_initOptions() {
|
|
48
|
-
this.options.unshift({
|
|
49
|
-
option: '-u, --webUrl <webUrl>'
|
|
50
|
-
}, {
|
|
51
|
-
option: '-l, --location <location>',
|
|
52
|
-
autocomplete: ['QuickLaunch', 'TopNavigationBar']
|
|
53
|
-
});
|
|
54
|
-
}, _SpoNavigationNodeListCommand_initValidators = function _SpoNavigationNodeListCommand_initValidators() {
|
|
55
|
-
this.validators.push(async (args) => {
|
|
56
|
-
const isValidSharePointUrl = validation.isValidSharePointUrl(args.options.webUrl);
|
|
57
|
-
if (isValidSharePointUrl !== true) {
|
|
58
|
-
return isValidSharePointUrl;
|
|
59
|
-
}
|
|
60
|
-
if (args.options.location !== 'QuickLaunch' &&
|
|
61
|
-
args.options.location !== 'TopNavigationBar') {
|
|
62
|
-
return `${args.options.location} is not a valid value for the location option. Allowed values are QuickLaunch|TopNavigationBar`;
|
|
63
|
-
}
|
|
64
|
-
return true;
|
|
65
|
-
});
|
|
66
|
-
};
|
|
67
42
|
export default new SpoNavigationNodeListCommand();
|
|
68
43
|
//# sourceMappingURL=navigation-node-list.js.map
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { globalOptionsZod } from '../../../../Command.js';
|
|
3
|
+
import request from '../../../../request.js';
|
|
4
|
+
import { validation } from '../../../../utils/validation.js';
|
|
5
|
+
import SpoCommand from '../../../base/SpoCommand.js';
|
|
6
|
+
import commands from '../../commands.js';
|
|
7
|
+
export const options = z.strictObject({
|
|
8
|
+
...globalOptionsZod.shape,
|
|
9
|
+
siteUrl: z.string()
|
|
10
|
+
.refine(url => validation.isValidSharePointUrl(url) === true, {
|
|
11
|
+
error: e => `'${e.input}' is not a valid SharePoint Online site URL.`
|
|
12
|
+
})
|
|
13
|
+
.alias('u'),
|
|
14
|
+
disabled: z.boolean().optional(),
|
|
15
|
+
ownerGroup: z.boolean().optional(),
|
|
16
|
+
email: z.string()
|
|
17
|
+
.refine(email => validation.isValidUserPrincipalName(email), {
|
|
18
|
+
error: e => `'${e.input}' is not a valid email address.`
|
|
19
|
+
}).optional(),
|
|
20
|
+
message: z.string().optional()
|
|
21
|
+
});
|
|
22
|
+
class SpoSiteAccessRequestSettingSetCommand extends SpoCommand {
|
|
23
|
+
get name() {
|
|
24
|
+
return commands.SITE_ACCESSREQUEST_SETTING_SET;
|
|
25
|
+
}
|
|
26
|
+
get description() {
|
|
27
|
+
return 'Update access requests for a specific site';
|
|
28
|
+
}
|
|
29
|
+
get schema() {
|
|
30
|
+
return options;
|
|
31
|
+
}
|
|
32
|
+
getRefinedSchema(schema) {
|
|
33
|
+
return schema
|
|
34
|
+
.refine(o => [o.disabled, o.ownerGroup, o.email].filter(v => v !== undefined).length === 1, {
|
|
35
|
+
error: 'Specify exactly one of disabled, ownerGroup, or email'
|
|
36
|
+
})
|
|
37
|
+
.refine(o => !(o.disabled && typeof o.message !== 'undefined'), {
|
|
38
|
+
error: 'The message option cannot be used when disabled is specified'
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
async commandAction(logger, args) {
|
|
42
|
+
if (this.verbose) {
|
|
43
|
+
await logger.logToStderr(`Updating access requests for site '${args.options.siteUrl}'...`);
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
const { siteUrl, ownerGroup, email, message } = args.options;
|
|
47
|
+
const requestAccessEmail = email || '';
|
|
48
|
+
if (this.verbose) {
|
|
49
|
+
await logger.logToStderr(`Updating RequestAccessEmail to '${requestAccessEmail}'...`);
|
|
50
|
+
}
|
|
51
|
+
const requestPatchWeb = {
|
|
52
|
+
url: `${siteUrl}/_api/Web`,
|
|
53
|
+
headers: {
|
|
54
|
+
accept: 'application/json;odata=nometadata'
|
|
55
|
+
},
|
|
56
|
+
responseType: 'json',
|
|
57
|
+
data: {
|
|
58
|
+
RequestAccessEmail: requestAccessEmail
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
await request.patch(requestPatchWeb);
|
|
62
|
+
const useAccessRequestDefault = !!ownerGroup;
|
|
63
|
+
if (this.verbose) {
|
|
64
|
+
await logger.logToStderr(`Updating UseAccessRequestDefault to '${useAccessRequestDefault}'...`);
|
|
65
|
+
}
|
|
66
|
+
const requestUseDefault = {
|
|
67
|
+
url: `${siteUrl}/_api/Web/SetUseAccessRequestDefaultAndUpdate`,
|
|
68
|
+
headers: {
|
|
69
|
+
accept: 'application/json;odata=nometadata',
|
|
70
|
+
'content-type': 'application/json;odata=nometadata'
|
|
71
|
+
},
|
|
72
|
+
responseType: 'json',
|
|
73
|
+
data: {
|
|
74
|
+
useAccessRequestDefault: useAccessRequestDefault
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
await request.post(requestUseDefault);
|
|
78
|
+
if (message !== undefined) {
|
|
79
|
+
if (this.verbose) {
|
|
80
|
+
await logger.logToStderr(`Updating access request message to '${message}'...`);
|
|
81
|
+
}
|
|
82
|
+
const requestSetMessage = {
|
|
83
|
+
url: `${siteUrl}/_api/Web/SetAccessRequestSiteDescriptionAndUpdate`,
|
|
84
|
+
headers: {
|
|
85
|
+
accept: 'application/json;odata=nometadata',
|
|
86
|
+
'content-type': 'application/json;odata=nometadata'
|
|
87
|
+
},
|
|
88
|
+
responseType: 'json',
|
|
89
|
+
data: {
|
|
90
|
+
description: message
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
await request.post(requestSetMessage);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
this.handleRejectedODataJsonPromise(err);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
export default new SpoSiteAccessRequestSettingSetCommand();
|
|
102
|
+
//# sourceMappingURL=site-accessrequest-setting-set.js.map
|
|
@@ -5,6 +5,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
5
5
|
};
|
|
6
6
|
var _SpoSiteAddCommand_instances, _SpoSiteAddCommand_initTelemetry, _SpoSiteAddCommand_initOptions, _SpoSiteAddCommand_initValidators;
|
|
7
7
|
import { setTimeout } from 'timers/promises';
|
|
8
|
+
import { cli } from '../../../../cli/cli.js';
|
|
8
9
|
import config from '../../../../config.js';
|
|
9
10
|
import request from '../../../../request.js';
|
|
10
11
|
import { formatting } from '../../../../utils/formatting.js';
|
|
@@ -12,6 +13,7 @@ import { spo } from '../../../../utils/spo.js';
|
|
|
12
13
|
import { validation } from '../../../../utils/validation.js';
|
|
13
14
|
import SpoCommand from '../../../base/SpoCommand.js';
|
|
14
15
|
import commands from '../../commands.js';
|
|
16
|
+
import { brandCenter } from '../../../../utils/brandCenter.js';
|
|
15
17
|
class SpoSiteAddCommand extends SpoCommand {
|
|
16
18
|
get supportedLcids() {
|
|
17
19
|
// Languages supported by SharePoint
|
|
@@ -43,7 +45,7 @@ class SpoSiteAddCommand extends SpoCommand {
|
|
|
43
45
|
await logger.log(siteUrl);
|
|
44
46
|
}
|
|
45
47
|
async createModernSite(logger, args) {
|
|
46
|
-
const isTeamSite = args.options.type !== 'CommunicationSite';
|
|
48
|
+
const isTeamSite = args.options.type !== 'CommunicationSite' && args.options.type !== 'BrandCenter';
|
|
47
49
|
try {
|
|
48
50
|
const spoUrl = await spo.getSpoUrl(logger, this.debug);
|
|
49
51
|
if (this.verbose) {
|
|
@@ -128,6 +130,9 @@ class SpoSiteAddCommand extends SpoCommand {
|
|
|
128
130
|
if (args.options.owners) {
|
|
129
131
|
requestOptions.data.request.Owner = args.options.owners;
|
|
130
132
|
}
|
|
133
|
+
if (args.options.type === 'BrandCenter') {
|
|
134
|
+
await this.addBrandCenter(requestOptions.data.request, logger, args.options.force || false);
|
|
135
|
+
}
|
|
131
136
|
}
|
|
132
137
|
const response = await request.post(requestOptions);
|
|
133
138
|
if (isTeamSite) {
|
|
@@ -325,6 +330,27 @@ class SpoSiteAddCommand extends SpoCommand {
|
|
|
325
330
|
this.handleRejectedPromise(err);
|
|
326
331
|
}
|
|
327
332
|
}
|
|
333
|
+
async addBrandCenter(requestData, logger, force) {
|
|
334
|
+
const brandingCenterConfiguration = await brandCenter.getBrandCenterConfiguration(logger, this.debug);
|
|
335
|
+
if (brandingCenterConfiguration.IsBrandCenterSiteFeatureEnabled) {
|
|
336
|
+
throw Error('Brand center site is already created in the tenant.');
|
|
337
|
+
}
|
|
338
|
+
const warningMessage = `You agree to activate this site as your official brand center site and turn on the brand center app for use in your organization. Storage locations will be created for uploading files to brand center and managing them. Any uploaded files will be stored in the cloud and managed in a public content delivery network (CDN). The files will be accessible to anyone who is able to extract the URLs that point to them.
|
|
339
|
+
Don't use this feature if your files contain proprietary information, or if you don't have the necessary cloud hosting rights to use them. After creation, that site cannot be deleted.`;
|
|
340
|
+
if (force) {
|
|
341
|
+
await logger.logToStderr(warningMessage);
|
|
342
|
+
}
|
|
343
|
+
else {
|
|
344
|
+
const result = await cli.promptForConfirmation({
|
|
345
|
+
message: `${warningMessage}\n\nDo you want to proceed?`
|
|
346
|
+
});
|
|
347
|
+
if (!result) {
|
|
348
|
+
throw Error('Operation cancelled by the user.');
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
const brandCenterFeatureId = '99cd6e8b-189b-4611-ae89-f89105876e43';
|
|
352
|
+
requestData.AdditionalSiteFeatureIds = [brandCenterFeatureId];
|
|
353
|
+
}
|
|
328
354
|
}
|
|
329
355
|
_SpoSiteAddCommand_instances = new WeakSet(), _SpoSiteAddCommand_initTelemetry = function _SpoSiteAddCommand_initTelemetry() {
|
|
330
356
|
this.telemetry.push((args) => {
|
|
@@ -338,6 +364,7 @@ _SpoSiteAddCommand_instances = new WeakSet(), _SpoSiteAddCommand_initTelemetry =
|
|
|
338
364
|
telemetryProps.lcid = args.options.lcid;
|
|
339
365
|
telemetryProps.owners = typeof args.options.owners !== 'undefined';
|
|
340
366
|
telemetryProps.withAppCatalog = args.options.withAppCatalog || false;
|
|
367
|
+
telemetryProps.force = args.options.force || false;
|
|
341
368
|
if (isCommunicationSite) {
|
|
342
369
|
telemetryProps.shareByEmailEnabled = args.options.shareByEmailEnabled || false;
|
|
343
370
|
telemetryProps.siteDesign = args.options.siteDesign;
|
|
@@ -357,7 +384,7 @@ _SpoSiteAddCommand_instances = new WeakSet(), _SpoSiteAddCommand_initTelemetry =
|
|
|
357
384
|
}, _SpoSiteAddCommand_initOptions = function _SpoSiteAddCommand_initOptions() {
|
|
358
385
|
this.options.unshift({
|
|
359
386
|
option: '--type [type]',
|
|
360
|
-
autocomplete: ['TeamSite', 'CommunicationSite', 'ClassicSite']
|
|
387
|
+
autocomplete: ['TeamSite', 'CommunicationSite', 'ClassicSite', 'BrandCenter']
|
|
361
388
|
}, {
|
|
362
389
|
option: '-t, --title <title>'
|
|
363
390
|
}, {
|
|
@@ -399,24 +426,27 @@ _SpoSiteAddCommand_instances = new WeakSet(), _SpoSiteAddCommand_initTelemetry =
|
|
|
399
426
|
option: '--withAppCatalog'
|
|
400
427
|
}, {
|
|
401
428
|
option: '--wait'
|
|
429
|
+
}, {
|
|
430
|
+
option: '--force'
|
|
402
431
|
});
|
|
403
432
|
}, _SpoSiteAddCommand_initValidators = function _SpoSiteAddCommand_initValidators() {
|
|
404
433
|
this.validators.push(async (args) => {
|
|
405
434
|
const isClassicSite = args.options.type === 'ClassicSite';
|
|
406
|
-
const isCommunicationSite = args.options.type === 'CommunicationSite';
|
|
435
|
+
const isCommunicationSite = args.options.type === 'CommunicationSite' || args.options.type === 'BrandCenter';
|
|
407
436
|
const isTeamSite = isCommunicationSite === false && isClassicSite === false;
|
|
408
437
|
if (args.options.type) {
|
|
409
438
|
if (args.options.type !== 'TeamSite' &&
|
|
410
439
|
args.options.type !== 'CommunicationSite' &&
|
|
411
|
-
args.options.type !== 'ClassicSite'
|
|
412
|
-
|
|
440
|
+
args.options.type !== 'ClassicSite' &&
|
|
441
|
+
args.options.type !== 'BrandCenter') {
|
|
442
|
+
return `${args.options.type} is not a valid site type. Allowed types are TeamSite, CommunicationSite, ClassicSite, and BrandCenter`;
|
|
413
443
|
}
|
|
414
444
|
}
|
|
415
445
|
if (isTeamSite) {
|
|
416
446
|
if (!args.options.alias) {
|
|
417
447
|
return 'Required option alias missing';
|
|
418
448
|
}
|
|
419
|
-
if (args.options.url || args.options.siteDesign || args.options.removeDeletedSite || args.options.wait || args.options.shareByEmailEnabled || args.options.siteDesignId || args.options.timeZone || args.options.resourceQuota || args.options.resourceQuotaWarningLevel || args.options.storageQuota || args.options.storageQuotaWarningLevel || args.options.webTemplate) {
|
|
449
|
+
if (args.options.url || args.options.siteDesign || args.options.removeDeletedSite || args.options.wait || args.options.shareByEmailEnabled || args.options.siteDesignId || args.options.timeZone || args.options.resourceQuota || args.options.resourceQuotaWarningLevel || args.options.storageQuota || args.options.storageQuotaWarningLevel || args.options.webTemplate || args.options.force) {
|
|
420
450
|
return "Type TeamSite supports only the parameters title, lcid, alias, owners, classification, isPublic, and description";
|
|
421
451
|
}
|
|
422
452
|
}
|
|
@@ -447,7 +477,7 @@ _SpoSiteAddCommand_instances = new WeakSet(), _SpoSiteAddCommand_initTelemetry =
|
|
|
447
477
|
return 'Specify siteDesign or siteDesignId but not both';
|
|
448
478
|
}
|
|
449
479
|
if (args.options.timeZone || args.options.isPublic || args.options.removeDeletedSite || args.options.wait || args.options.alias || args.options.resourceQuota || args.options.resourceQuotaWarningLevel || args.options.storageQuota || args.options.storageQuotaWarningLevel || args.options.webTemplate) {
|
|
450
|
-
return "Type CommunicationSite supports only the parameters url, title, lcid, classification, siteDesign, shareByEmailEnabled, siteDesignId, owners, and
|
|
480
|
+
return "Type CommunicationSite supports only the parameters url, title, lcid, classification, siteDesign, shareByEmailEnabled, siteDesignId, owners, description, and force";
|
|
451
481
|
}
|
|
452
482
|
}
|
|
453
483
|
else {
|
|
@@ -500,7 +530,7 @@ _SpoSiteAddCommand_instances = new WeakSet(), _SpoSiteAddCommand_initTelemetry =
|
|
|
500
530
|
if (args.options.storageQuotaWarningLevel > args.options.storageQuota) {
|
|
501
531
|
return `storageQuotaWarningLevel cannot exceed storageQuota`;
|
|
502
532
|
}
|
|
503
|
-
if (args.options.classification || args.options.shareByEmailEnabled || args.options.siteDesignId || args.options.siteDesignId || args.options.alias || args.options.isPublic) {
|
|
533
|
+
if (args.options.classification || args.options.shareByEmailEnabled || args.options.siteDesignId || args.options.siteDesignId || args.options.alias || args.options.isPublic || args.options.force) {
|
|
504
534
|
return "Type ClassicSite supports only the parameters url, title, lcid, storageQuota, storageQuotaWarningLevel, resourceQuota, resourceQuotaWarningLevel, webTemplate, owners, and description";
|
|
505
535
|
}
|
|
506
536
|
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { globalOptionsZod } from '../../../../Command.js';
|
|
3
|
+
import request from '../../../../request.js';
|
|
4
|
+
import { formatting } from '../../../../utils/formatting.js';
|
|
5
|
+
import { spo } from '../../../../utils/spo.js';
|
|
6
|
+
import { validation } from '../../../../utils/validation.js';
|
|
7
|
+
import SpoCommand from '../../../base/SpoCommand.js';
|
|
8
|
+
import commands from '../../commands.js';
|
|
9
|
+
import { cli } from '../../../../cli/cli.js';
|
|
10
|
+
export const options = z.strictObject({
|
|
11
|
+
...globalOptionsZod.shape,
|
|
12
|
+
id: z.uuid().optional().alias('i'),
|
|
13
|
+
title: z.string().optional().alias('t'),
|
|
14
|
+
url: z.string().refine(url => validation.isValidSharePointUrl(url) === true, {
|
|
15
|
+
message: 'Specify a valid SharePoint site URL'
|
|
16
|
+
}).optional().alias('u')
|
|
17
|
+
});
|
|
18
|
+
class SpoTenantSiteGetCommand extends SpoCommand {
|
|
19
|
+
get name() {
|
|
20
|
+
return commands.TENANT_SITE_GET;
|
|
21
|
+
}
|
|
22
|
+
get description() {
|
|
23
|
+
return 'Retrieves the tenant site information';
|
|
24
|
+
}
|
|
25
|
+
get schema() {
|
|
26
|
+
return options;
|
|
27
|
+
}
|
|
28
|
+
getRefinedSchema(schema) {
|
|
29
|
+
return schema.refine(o => [o.id, o.title, o.url].filter(v => v !== undefined).length === 1, {
|
|
30
|
+
error: `Specify exactly one of the following options: 'id', 'title', or 'url'.`
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
async commandAction(logger, args) {
|
|
34
|
+
if (this.verbose) {
|
|
35
|
+
await logger.logToStderr(`Retrieving tenant site information for site '${args.options.url || args.options.id || args.options.title}'...`);
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
let siteUrl;
|
|
39
|
+
if (args.options.url) {
|
|
40
|
+
siteUrl = args.options.url;
|
|
41
|
+
}
|
|
42
|
+
else if (args.options.id) {
|
|
43
|
+
siteUrl = await this.getSiteUrlById(args.options.id, logger);
|
|
44
|
+
if (this.verbose) {
|
|
45
|
+
await logger.logToStderr(`Retrieved tenant site URL for site '${args.options.id}'...`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
siteUrl = await this.getSiteUrlByTitle(args.options.title, logger);
|
|
50
|
+
if (this.verbose) {
|
|
51
|
+
await logger.logToStderr(`Retrieved tenant site URL for site '${args.options.title}'...`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const site = await spo.getSiteAdminPropertiesByUrl(siteUrl, false, logger, this.verbose);
|
|
55
|
+
await logger.log(site);
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
this.handleRejectedODataJsonPromise(err);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
async getSiteUrlById(id, logger) {
|
|
62
|
+
if (this.verbose) {
|
|
63
|
+
await logger.logToStderr(`Retrieving tenant site URL for site '${id}'...`);
|
|
64
|
+
}
|
|
65
|
+
const adminUrl = await spo.getSpoAdminUrl(logger, this.debug);
|
|
66
|
+
const requestOptions = {
|
|
67
|
+
url: `${adminUrl}/_api/SPO.Tenant/sites('${id}')?$select=Url`,
|
|
68
|
+
headers: {
|
|
69
|
+
accept: 'application/json;odata=nometadata'
|
|
70
|
+
},
|
|
71
|
+
responseType: 'json'
|
|
72
|
+
};
|
|
73
|
+
const res = await request.get(requestOptions);
|
|
74
|
+
return res.Url;
|
|
75
|
+
}
|
|
76
|
+
async getSiteUrlByTitle(title, logger) {
|
|
77
|
+
if (this.verbose) {
|
|
78
|
+
await logger.logToStderr(`Retrieving tenant site URL for site '${title}'...`);
|
|
79
|
+
}
|
|
80
|
+
const adminUrl = await spo.getSpoAdminUrl(logger, this.debug);
|
|
81
|
+
const viewXml = `<View><Query><Where><And><IsNull><FieldRef Name="TimeDeleted"/></IsNull><Eq><FieldRef Name="Title"/><Value Type='Text'>${formatting.escapeXml(title)}</Value></Eq></And></Where></Query><ViewFields><FieldRef Name="Title"/><FieldRef Name="SiteUrl"/><FieldRef Name="SiteId"/></ViewFields></View>`;
|
|
82
|
+
const requestOptions = {
|
|
83
|
+
url: `${adminUrl}/_api/web/lists/GetByTitle('DO_NOT_DELETE_SPLIST_TENANTADMIN_AGGREGATED_SITECOLLECTIONS')/RenderListDataAsStream`,
|
|
84
|
+
headers: {
|
|
85
|
+
accept: 'application/json;odata=nometadata'
|
|
86
|
+
},
|
|
87
|
+
responseType: 'json',
|
|
88
|
+
data: {
|
|
89
|
+
parameters: {
|
|
90
|
+
ViewXml: viewXml,
|
|
91
|
+
DatesInUtc: true
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
const res = await request.post(requestOptions);
|
|
96
|
+
const rows = res.Row;
|
|
97
|
+
if (rows.length === 0) {
|
|
98
|
+
throw `The specified site '${title}' does not exist.`;
|
|
99
|
+
}
|
|
100
|
+
if (rows.length > 1) {
|
|
101
|
+
const resultAsKeyValuePair = rows.reduce((acc, cur) => {
|
|
102
|
+
acc[cur.SiteUrl] = { url: cur.SiteUrl };
|
|
103
|
+
return acc;
|
|
104
|
+
}, {});
|
|
105
|
+
const selection = await cli.handleMultipleResultsFound(`Multiple sites with title '${title}' found.`, resultAsKeyValuePair);
|
|
106
|
+
return selection.url;
|
|
107
|
+
}
|
|
108
|
+
return rows[0].SiteUrl;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
export default new SpoTenantSiteGetCommand();
|
|
112
|
+
//# sourceMappingURL=tenant-site-get.js.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const prefix = 'spo';
|
|
2
2
|
export default {
|
|
3
|
+
AGENT_ADD: `${prefix} agent add`,
|
|
3
4
|
APP_ADD: `${prefix} app add`,
|
|
4
5
|
APP_DEPLOY: `${prefix} app deploy`,
|
|
5
6
|
APP_GET: `${prefix} app get`,
|
|
@@ -255,6 +256,7 @@ export default {
|
|
|
255
256
|
SERVICEPRINCIPAL_PERMISSIONREQUEST_LIST: `${prefix} serviceprincipal permissionrequest list`,
|
|
256
257
|
SERVICEPRINCIPAL_SET: `${prefix} serviceprincipal set`,
|
|
257
258
|
SET: `${prefix} set`,
|
|
259
|
+
SITE_ACCESSREQUEST_SETTING_SET: `${prefix} site accessrequest setting set`,
|
|
258
260
|
SITE_ADD: `${prefix} site add`,
|
|
259
261
|
SITE_ADMIN_ADD: `${prefix} site admin add`,
|
|
260
262
|
SITE_ADMIN_LIST: `${prefix} site admin list`,
|
|
@@ -337,6 +339,7 @@ export default {
|
|
|
337
339
|
TENANT_RECYCLEBINITEM_RESTORE: `${prefix} tenant recyclebinitem restore`,
|
|
338
340
|
TENANT_SETTINGS_LIST: `${prefix} tenant settings list`,
|
|
339
341
|
TENANT_SETTINGS_SET: `${prefix} tenant settings set`,
|
|
342
|
+
TENANT_SITE_GET: `${prefix} tenant site get`,
|
|
340
343
|
TERM_ADD: `${prefix} term add`,
|
|
341
344
|
TERM_GET: `${prefix} term get`,
|
|
342
345
|
TERM_LIST: `${prefix} term list`,
|
|
@@ -87,6 +87,27 @@ export const accessToken = {
|
|
|
87
87
|
const payload = JSON.parse(payloadString);
|
|
88
88
|
return { header, payload };
|
|
89
89
|
},
|
|
90
|
+
getScopesFromAccessToken(accessToken) {
|
|
91
|
+
let scopes = [];
|
|
92
|
+
if (!accessToken || accessToken.length === 0) {
|
|
93
|
+
return scopes;
|
|
94
|
+
}
|
|
95
|
+
const chunks = accessToken.split('.');
|
|
96
|
+
if (chunks.length !== 3) {
|
|
97
|
+
return scopes;
|
|
98
|
+
}
|
|
99
|
+
const tokenString = Buffer.from(chunks[1], 'base64').toString();
|
|
100
|
+
try {
|
|
101
|
+
const token = JSON.parse(tokenString);
|
|
102
|
+
if (token.scp?.length > 0) {
|
|
103
|
+
scopes = token.scp.split(' ');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
// Do nothing
|
|
108
|
+
}
|
|
109
|
+
return scopes;
|
|
110
|
+
},
|
|
90
111
|
/**
|
|
91
112
|
* Asserts the presence of a delegated or application-only access token.
|
|
92
113
|
* @throws {CommandError} Will throw an error if the access token is not available.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import request from '../request.js';
|
|
2
|
+
import { spo } from './spo.js';
|
|
3
|
+
export const brandCenter = {
|
|
4
|
+
/**
|
|
5
|
+
* Gets the brand center configuration for the specified site
|
|
6
|
+
* @param logger Logger instance for verbose output
|
|
7
|
+
* @param debug Debug flag for detailed logging
|
|
8
|
+
* @returns Promise<BrandCenterConfiguration> Brand center configuration object
|
|
9
|
+
*/
|
|
10
|
+
async getBrandCenterConfiguration(logger, debug = false) {
|
|
11
|
+
if (debug) {
|
|
12
|
+
await logger.logToStderr(`Retrieving brand center configuration...`);
|
|
13
|
+
}
|
|
14
|
+
const spoAdminUrl = await spo.getSpoAdminUrl(logger, debug);
|
|
15
|
+
const brandConfigRequestOptions = {
|
|
16
|
+
url: `${spoAdminUrl}/_api/SPO.Tenant/GetBrandCenterConfiguration`,
|
|
17
|
+
headers: {
|
|
18
|
+
'accept': 'application/json;odata=nometadata'
|
|
19
|
+
},
|
|
20
|
+
responseType: 'json'
|
|
21
|
+
};
|
|
22
|
+
const brandConfig = await request.get(brandConfigRequestOptions);
|
|
23
|
+
if (debug) {
|
|
24
|
+
await logger.logToStderr(`Successfully retrieved brand center configuration`);
|
|
25
|
+
}
|
|
26
|
+
return brandConfig;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=brandCenter.js.map
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import Global from '../../_global.mdx';
|
|
2
|
+
import Tabs from '@theme/Tabs';
|
|
3
|
+
import TabItem from '@theme/TabItem';
|
|
2
4
|
|
|
3
5
|
# entra app role add
|
|
4
6
|
|
|
@@ -49,6 +51,25 @@ For best performance use the `appObjectId` option to reference the Entra applica
|
|
|
49
51
|
|
|
50
52
|
If the command finds multiple Entra application registrations with the specified app name, it will prompt you to disambiguate which app it should use, listing the discovered object IDs.
|
|
51
53
|
|
|
54
|
+
## Permissions
|
|
55
|
+
|
|
56
|
+
<Tabs>
|
|
57
|
+
<TabItem value="Delegated">
|
|
58
|
+
|
|
59
|
+
| Resource | Permissions |
|
|
60
|
+
| --------------- | ------------------------- |
|
|
61
|
+
| Microsoft Graph | Application.ReadWrite.All |
|
|
62
|
+
|
|
63
|
+
</TabItem>
|
|
64
|
+
<TabItem value="Application">
|
|
65
|
+
|
|
66
|
+
| Resource | Permissions |
|
|
67
|
+
| --------------- | ------------------------- |
|
|
68
|
+
| Microsoft Graph | Application.ReadWrite.All |
|
|
69
|
+
|
|
70
|
+
</TabItem>
|
|
71
|
+
</Tabs>
|
|
72
|
+
|
|
52
73
|
## Examples
|
|
53
74
|
|
|
54
75
|
Add role to the Entra application registration specified by its object ID
|
|
@@ -39,6 +39,25 @@ For best performance use the `appObjectId` option to reference the Entra applica
|
|
|
39
39
|
|
|
40
40
|
If the command finds multiple Entra application registrations with the specified app name, it will prompt you to disambiguate which app it should use, listing the discovered object IDs.
|
|
41
41
|
|
|
42
|
+
## Permissions
|
|
43
|
+
|
|
44
|
+
<Tabs>
|
|
45
|
+
<TabItem value="Delegated">
|
|
46
|
+
|
|
47
|
+
| Resource | Permissions |
|
|
48
|
+
| --------------- | -------------------- |
|
|
49
|
+
| Microsoft Graph | Application.Read.All |
|
|
50
|
+
|
|
51
|
+
</TabItem>
|
|
52
|
+
<TabItem value="Application">
|
|
53
|
+
|
|
54
|
+
| Resource | Permissions |
|
|
55
|
+
| --------------- | -------------------- |
|
|
56
|
+
| Microsoft Graph | Application.Read.All |
|
|
57
|
+
|
|
58
|
+
</TabItem>
|
|
59
|
+
</Tabs>
|
|
60
|
+
|
|
42
61
|
## Examples
|
|
43
62
|
|
|
44
63
|
Get roles for the Entra application registration specified by its object ID
|
|
@@ -118,4 +137,4 @@ m365 entra app role list --appName "My app"
|
|
|
118
137
|
```
|
|
119
138
|
|
|
120
139
|
</TabItem>
|
|
121
|
-
</Tabs>
|
|
140
|
+
</Tabs>
|