@pnp/cli-microsoft365 10.0.0-beta.7dfc31a → 10.0.0-beta.a0367997

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 (173) hide show
  1. package/allCommands.json +1 -1
  2. package/allCommandsFull.json +1 -1
  3. package/dist/Auth.js +17 -16
  4. package/dist/AuthServer.js +7 -7
  5. package/dist/Command.js +4 -1
  6. package/dist/api.js +1 -1
  7. package/dist/cli/cli.js +14 -0
  8. package/dist/config.js +61 -5
  9. package/dist/m365/base/PowerAutomateCommand.js +1 -1
  10. package/dist/m365/base/SpoCommand.js +1 -1
  11. package/dist/m365/cli/commands/cli-consent.js +2 -2
  12. package/dist/m365/cli/commands/cli-doctor.js +4 -4
  13. package/dist/m365/cli/commands/config/config-set.js +12 -4
  14. package/dist/m365/cli/commands.js +1 -2
  15. package/dist/m365/commands/login.js +28 -9
  16. package/dist/m365/commands/setup.js +256 -33
  17. package/dist/m365/commands/setupPresets.js +2 -4
  18. package/dist/m365/connection/commands/connection-list.js +4 -4
  19. package/dist/m365/entra/commands/app/app-add.js +52 -288
  20. package/dist/m365/entra/commands/m365group/m365group-set.js +24 -16
  21. package/dist/m365/entra/commands/m365group/m365group-user-add.js +5 -12
  22. package/dist/m365/entra/commands/oauth2grant/oauth2grant-list.js +3 -12
  23. package/dist/m365/external/commands/item/item-add.js +2 -5
  24. package/dist/m365/file/commands/file-move.js +135 -0
  25. package/dist/m365/file/commands.js +2 -1
  26. package/dist/m365/flow/commands/environment/environment-get.js +1 -1
  27. package/dist/m365/flow/commands/environment/environment-list.js +2 -2
  28. package/dist/m365/flow/commands/flow-disable.js +1 -1
  29. package/dist/m365/flow/commands/flow-enable.js +1 -1
  30. package/dist/m365/flow/commands/flow-export.js +17 -16
  31. package/dist/m365/flow/commands/flow-get.js +1 -1
  32. package/dist/m365/flow/commands/flow-list.js +1 -1
  33. package/dist/m365/flow/commands/flow-remove.js +1 -1
  34. package/dist/m365/flow/commands/owner/owner-ensure.js +1 -1
  35. package/dist/m365/flow/commands/owner/owner-list.js +1 -1
  36. package/dist/m365/flow/commands/owner/owner-remove.js +1 -1
  37. package/dist/m365/flow/commands/recyclebinitem/recyclebinitem-list.js +47 -0
  38. package/dist/m365/flow/commands/recyclebinitem/recyclebinitem-restore.js +48 -0
  39. package/dist/m365/flow/commands/run/run-cancel.js +1 -1
  40. package/dist/m365/flow/commands/run/run-get.js +1 -1
  41. package/dist/m365/flow/commands/run/run-list.js +1 -1
  42. package/dist/m365/flow/commands/run/run-resubmit.js +2 -2
  43. package/dist/m365/flow/commands.js +2 -0
  44. package/dist/m365/pa/commands/app/app-list.js +1 -6
  45. package/dist/m365/pa/commands/connector/connector-list.js +1 -6
  46. package/dist/m365/pa/commands/environment/environment-list.js +1 -1
  47. package/dist/m365/pp/commands/environment/environment-list.js +1 -1
  48. package/dist/m365/spfx/commands/project/project-doctor/doctor-1.20.0.js +27 -0
  49. package/dist/m365/spfx/commands/project/project-doctor/rules/FN002021_DEVDEP_rushstack_eslint_config.js +10 -0
  50. package/dist/m365/spfx/commands/project/project-doctor.js +2 -1
  51. package/dist/m365/spfx/commands/project/project-upgrade/upgrade-1.20.0.js +59 -0
  52. package/dist/m365/spfx/commands/project/project-upgrade.js +2 -1
  53. package/dist/m365/spfx/commands/spfx-doctor.js +15 -0
  54. package/dist/m365/spo/commands/app/app-instance-list.js +3 -18
  55. package/dist/m365/spo/commands/app/app-list.js +1 -8
  56. package/dist/m365/spo/commands/contenttype/contenttype-field-remove.js +8 -8
  57. package/dist/m365/spo/commands/contenttype/contenttype-field-set.js +2 -2
  58. package/dist/m365/spo/commands/feature/feature-list.js +1 -8
  59. package/dist/m365/spo/commands/file/file-copy.js +5 -1
  60. package/dist/m365/spo/commands/file/file-move.js +55 -33
  61. package/dist/m365/spo/commands/file/file-roleassignment-add.js +17 -54
  62. package/dist/m365/spo/commands/file/file-roleassignment-remove.js +13 -40
  63. package/dist/m365/spo/commands/file/file-roleinheritance-break.js +5 -13
  64. package/dist/m365/spo/commands/file/file-roleinheritance-reset.js +5 -13
  65. package/dist/m365/spo/commands/folder/folder-sharinglink-add.js +143 -0
  66. package/dist/m365/spo/commands/folder/folder-sharinglink-clear.js +111 -0
  67. package/dist/m365/spo/commands/folder/folder-sharinglink-remove.js +95 -0
  68. package/dist/m365/spo/commands/list/list-get.js +17 -4
  69. package/dist/m365/spo/commands/list/list-webhook-list.js +1 -6
  70. package/dist/m365/spo/commands/listitem/listitem-attachment-list.js +1 -8
  71. package/dist/m365/spo/commands/page/page-list.js +1 -1
  72. package/dist/m365/spo/commands/page/page-remove.js +37 -16
  73. package/dist/m365/spo/commands/page/page-section-add.js +185 -34
  74. package/dist/m365/spo/commands/page/page-template-list.js +1 -3
  75. package/dist/m365/spo/commands/site/SiteAdmin.js +2 -0
  76. package/dist/m365/spo/commands/site/site-admin-add.js +252 -0
  77. package/dist/m365/spo/commands/site/site-admin-list.js +10 -36
  78. package/dist/m365/spo/commands/site/site-admin-remove.js +194 -0
  79. package/dist/m365/spo/commands/site/site-sharingpermission-set.js +68 -0
  80. package/dist/m365/spo/commands/sitescript/sitescript-get.js +3 -2
  81. package/dist/m365/spo/commands/sitescript/sitescript-list.js +1 -3
  82. package/dist/m365/spo/commands/{site/site-rename.js → tenant/tenant-site-rename.js} +29 -32
  83. package/dist/m365/spo/commands/theme/theme-list.js +1 -1
  84. package/dist/m365/spo/commands/user/user-get.js +67 -9
  85. package/dist/m365/spo/commands/web/web-clientsidewebpart-list.js +1 -6
  86. package/dist/m365/spo/commands.js +7 -1
  87. package/dist/m365/spp/commands/contentcenter/contentcenter-list.js +56 -0
  88. package/dist/m365/spp/commands.js +5 -0
  89. package/dist/m365/teams/MeetingTranscript.js +2 -0
  90. package/dist/m365/teams/commands/meeting/meeting-transcript-get.js +152 -0
  91. package/dist/m365/teams/commands/tab/tab-list.js +5 -3
  92. package/dist/m365/teams/commands.js +1 -0
  93. package/dist/m365/viva/commands/engage/Community.js +2 -0
  94. package/dist/m365/viva/commands/engage/engage-community-list.js +28 -0
  95. package/dist/m365/viva/commands.js +1 -0
  96. package/dist/request.js +46 -61
  97. package/dist/settingsNames.js +6 -1
  98. package/dist/utils/driveUtil.js +51 -0
  99. package/dist/utils/entraApp.js +283 -0
  100. package/dist/utils/spo.js +76 -8
  101. package/dist/utils/timersUtil.js +12 -0
  102. package/dist/utils/urlUtil.js +8 -0
  103. package/dist/utils/zod.js +1 -1
  104. package/docs/docs/_clisettings.mdx +6 -1
  105. package/docs/docs/cmd/cli/cli-doctor.mdx +24 -23
  106. package/docs/docs/cmd/entra/m365group/m365group-report-activitystorage.mdx +2 -2
  107. package/docs/docs/cmd/entra/m365group/m365group-set.mdx +9 -6
  108. package/docs/docs/cmd/entra/m365group/m365group-user-add.mdx +0 -3
  109. package/docs/docs/cmd/external/item/item-add.mdx +3 -3
  110. package/docs/docs/cmd/file/file-move.mdx +79 -0
  111. package/docs/docs/cmd/flow/recyclebinitem/recyclebinitem-list.mdx +132 -0
  112. package/docs/docs/cmd/flow/recyclebinitem/recyclebinitem-restore.mdx +55 -0
  113. package/docs/docs/cmd/setup.mdx +17 -6
  114. package/docs/docs/cmd/spfx/project/project-upgrade.mdx +1 -1
  115. package/docs/docs/cmd/spo/cdn/cdn-get.mdx +1 -1
  116. package/docs/docs/cmd/spo/cdn/cdn-origin-add.mdx +1 -1
  117. package/docs/docs/cmd/spo/cdn/cdn-origin-list.mdx +1 -1
  118. package/docs/docs/cmd/spo/cdn/cdn-origin-remove.mdx +1 -1
  119. package/docs/docs/cmd/spo/cdn/cdn-policy-list.mdx +1 -1
  120. package/docs/docs/cmd/spo/cdn/cdn-policy-set.mdx +1 -1
  121. package/docs/docs/cmd/spo/contenttype/contenttype-field-remove.mdx +7 -7
  122. package/docs/docs/cmd/spo/contenttype/contenttype-field-set.mdx +2 -2
  123. package/docs/docs/cmd/spo/externaluser/externaluser-list.mdx +1 -1
  124. package/docs/docs/cmd/spo/file/file-move.mdx +116 -9
  125. package/docs/docs/cmd/spo/folder/folder-sharinglink-add.mdx +125 -0
  126. package/docs/docs/cmd/spo/folder/folder-sharinglink-clear.mdx +50 -0
  127. package/docs/docs/cmd/spo/folder/folder-sharinglink-remove.mdx +50 -0
  128. package/docs/docs/cmd/spo/hidedefaultthemes/hidedefaultthemes-get.mdx +1 -1
  129. package/docs/docs/cmd/spo/hidedefaultthemes/hidedefaultthemes-set.mdx +1 -1
  130. package/docs/docs/cmd/spo/homesite/homesite-remove.mdx +1 -1
  131. package/docs/docs/cmd/spo/knowledgehub/knowledgehub-get.mdx +1 -1
  132. package/docs/docs/cmd/spo/knowledgehub/knowledgehub-remove.mdx +1 -1
  133. package/docs/docs/cmd/spo/knowledgehub/knowledgehub-set.mdx +1 -1
  134. package/docs/docs/cmd/spo/orgassetslibrary/orgassetslibrary-add.mdx +1 -1
  135. package/docs/docs/cmd/spo/orgassetslibrary/orgassetslibrary-list.mdx +1 -1
  136. package/docs/docs/cmd/spo/orgassetslibrary/orgassetslibrary-remove.mdx +1 -1
  137. package/docs/docs/cmd/spo/orgnewssite/orgnewssite-list.mdx +1 -1
  138. package/docs/docs/cmd/spo/orgnewssite/orgnewssite-remove.mdx +1 -1
  139. package/docs/docs/cmd/spo/orgnewssite/orgnewssite-set.mdx +1 -1
  140. package/docs/docs/cmd/spo/page/page-remove.mdx +30 -12
  141. package/docs/docs/cmd/spo/page/page-section-add.mdx +57 -2
  142. package/docs/docs/cmd/spo/site/site-admin-add.mdx +67 -0
  143. package/docs/docs/cmd/spo/site/site-admin-list.mdx +64 -12
  144. package/docs/docs/cmd/spo/site/site-admin-remove.mdx +67 -0
  145. package/docs/docs/cmd/spo/site/site-appcatalog-add.mdx +1 -1
  146. package/docs/docs/cmd/spo/site/site-appcatalog-remove.mdx +1 -1
  147. package/docs/docs/cmd/spo/site/site-commsite-enable.mdx +1 -1
  148. package/docs/docs/cmd/spo/site/site-list.mdx +6 -4
  149. package/docs/docs/cmd/spo/site/site-set.mdx +1 -1
  150. package/docs/docs/cmd/spo/site/site-sharingpermission-set.mdx +58 -0
  151. package/docs/docs/cmd/spo/sitescript/sitescript-get.mdx +14 -1
  152. package/docs/docs/cmd/spo/storageentity/storageentity-remove.mdx +1 -1
  153. package/docs/docs/cmd/spo/storageentity/storageentity-set.mdx +1 -1
  154. package/docs/docs/cmd/spo/tenant/tenant-appcatalog-add.mdx +1 -1
  155. package/docs/docs/cmd/spo/tenant/tenant-appcatalogurl-get.mdx +1 -1
  156. package/docs/docs/cmd/spo/tenant/tenant-recyclebinitem-list.mdx +1 -1
  157. package/docs/docs/cmd/spo/tenant/tenant-recyclebinitem-remove.mdx +1 -1
  158. package/docs/docs/cmd/spo/tenant/tenant-settings-list.mdx +1 -1
  159. package/docs/docs/cmd/spo/{site/site-rename.mdx → tenant/tenant-site-rename.mdx} +7 -7
  160. package/docs/docs/cmd/spo/theme/theme-apply.mdx +1 -1
  161. package/docs/docs/cmd/spo/theme/theme-get.mdx +1 -1
  162. package/docs/docs/cmd/spo/theme/theme-list.mdx +1 -1
  163. package/docs/docs/cmd/spo/theme/theme-remove.mdx +1 -1
  164. package/docs/docs/cmd/spo/theme/theme-set.mdx +1 -1
  165. package/docs/docs/cmd/spo/user/user-get.mdx +35 -9
  166. package/docs/docs/cmd/spp/contentcenter/contentcenter-list.mdx +287 -0
  167. package/docs/docs/cmd/teams/meeting/meeting-transcript-get.mdx +132 -0
  168. package/docs/docs/cmd/teams/tab/tab-list.mdx +1 -2
  169. package/docs/docs/cmd/viva/engage/engage-community-list.mdx +81 -0
  170. package/npm-shrinkwrap.json +203 -375
  171. package/package.json +16 -17
  172. package/dist/m365/cli/commands/cli-reconsent.js +0 -30
  173. package/docs/docs/cmd/cli/cli-reconsent.mdx +0 -62
@@ -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
package/dist/utils/spo.js CHANGED
@@ -500,10 +500,10 @@ export const spo = {
500
500
  * @param webUrl Web url
501
501
  * @param email The email of the user
502
502
  * @param logger the Logger object
503
- * @param verbose set if verbose logging should be logged
503
+ * @param verbose set for verbose logging
504
504
  */
505
505
  async getUserByEmail(webUrl, email, logger, verbose) {
506
- if (verbose) {
506
+ if (verbose && logger) {
507
507
  await logger.logToStderr(`Retrieving the spo user by email ${email}`);
508
508
  }
509
509
  const requestUrl = `${webUrl}/_api/web/siteusers/GetByEmail('${formatting.encodeQueryParameter(email)}')`;
@@ -574,10 +574,10 @@ export const spo = {
574
574
  * @param webUrl Web url
575
575
  * @param name The name of the group
576
576
  * @param logger the Logger object
577
- * @param verbose set if verbose logging should be logged
577
+ * @param verbose set for verbose logging
578
578
  */
579
579
  async getGroupByName(webUrl, name, logger, verbose) {
580
- if (verbose) {
580
+ if (verbose && logger) {
581
581
  await logger.logToStderr(`Retrieving the group by name ${name}`);
582
582
  }
583
583
  const requestUrl = `${webUrl}/_api/web/sitegroups/GetByName('${formatting.encodeQueryParameter(name)}')`;
@@ -596,10 +596,10 @@ export const spo = {
596
596
  * @param webUrl Web url
597
597
  * @param name the name of the role definition
598
598
  * @param logger the Logger object
599
- * @param debug set if debug logging should be logged
599
+ * @param verbose set for verbose logging
600
600
  */
601
- async getRoleDefinitionByName(webUrl, name, logger, debug) {
602
- if (debug) {
601
+ async getRoleDefinitionByName(webUrl, name, logger, verbose) {
602
+ if (verbose && logger) {
603
603
  await logger.logToStderr(`Retrieving the role definitions for ${name}`);
604
604
  }
605
605
  const roledefinitions = await odata.getAllItems(`${webUrl}/_api/web/roledefinitions`);
@@ -1527,6 +1527,29 @@ export const spo = {
1527
1527
  const itemsResponse = await request.get(requestOptionsItems);
1528
1528
  return (itemsResponse);
1529
1529
  },
1530
+ /**
1531
+ * Retrieves the file by id.
1532
+ * Returns a FileProperties object
1533
+ * @param webUrl Web url
1534
+ * @param id the id of the file
1535
+ * @param logger the Logger object
1536
+ * @param verbose set for verbose logging
1537
+ */
1538
+ async getFileById(webUrl, id, logger, verbose) {
1539
+ if (verbose && logger) {
1540
+ await logger.logToStderr(`Retrieving the file with id ${id}`);
1541
+ }
1542
+ const requestUrl = `${webUrl}/_api/web/GetFileById('${formatting.encodeQueryParameter(id)}')`;
1543
+ const requestOptions = {
1544
+ url: requestUrl,
1545
+ headers: {
1546
+ 'accept': 'application/json;odata=nometadata'
1547
+ },
1548
+ responseType: 'json'
1549
+ };
1550
+ const file = await request.get(requestOptions);
1551
+ return file;
1552
+ },
1530
1553
  /**
1531
1554
  * Create a SharePoint copy job to copy a file/folder to another location.
1532
1555
  * @param webUrl Absolute web URL where the source file/folder is located.
@@ -1550,8 +1573,10 @@ export const spo = {
1550
1573
  AllowSchemaMismatch: true,
1551
1574
  BypassSharedLock: !!options?.bypassSharedLock,
1552
1575
  IgnoreVersionHistory: !!options?.ignoreVersionHistory,
1576
+ IncludeItemPermissions: !!options?.includeItemPermissions,
1553
1577
  CustomizedItemName: options?.newName ? [options.newName] : undefined,
1554
- SameWebCopyMoveOptimization: true
1578
+ SameWebCopyMoveOptimization: true,
1579
+ IsMoveMode: options?.operation === 'move'
1555
1580
  }
1556
1581
  }
1557
1582
  };
@@ -1590,6 +1615,49 @@ export const spo = {
1590
1615
  // Get the destination object information
1591
1616
  const objectInfo = logs.find(l => l.Event === 'JobFinishedObjectInfo');
1592
1617
  return objectInfo;
1618
+ },
1619
+ /**
1620
+ * Gets the primary owner login from a site as admin.
1621
+ * @param adminUrl The SharePoint admin URL
1622
+ * @param siteId The site ID
1623
+ * @param logger The logger object
1624
+ * @param verbose If in verbose mode
1625
+ * @returns Owner login name
1626
+ */
1627
+ async getPrimaryAdminLoginNameAsAdmin(adminUrl, siteId, logger, verbose) {
1628
+ if (verbose) {
1629
+ await logger.logToStderr('Getting the primary admin login name...');
1630
+ }
1631
+ const requestOptions = {
1632
+ url: `${adminUrl}/_api/SPO.Tenant/sites('${siteId}')?$select=OwnerLoginName`,
1633
+ headers: {
1634
+ accept: 'application/json;odata=nometadata'
1635
+ },
1636
+ responseType: 'json'
1637
+ };
1638
+ const response = await request.get(requestOptions);
1639
+ return response.OwnerLoginName;
1640
+ },
1641
+ /**
1642
+ * Gets the primary owner login from a site.
1643
+ * @param siteUrl The site URL
1644
+ * @param logger The logger object
1645
+ * @param verbose If in verbose mode
1646
+ * @returns Owner login name
1647
+ */
1648
+ async getPrimaryOwnerLoginFromSite(siteUrl, logger, verbose) {
1649
+ if (verbose) {
1650
+ await logger.logToStderr('Getting the primary admin login name...');
1651
+ }
1652
+ const requestOptions = {
1653
+ url: `${siteUrl}/_api/site/owner`,
1654
+ headers: {
1655
+ 'accept': 'application/json;odata=nometadata'
1656
+ },
1657
+ responseType: 'json'
1658
+ };
1659
+ const responseContent = await request.get(requestOptions);
1660
+ return responseContent?.LoginName;
1593
1661
  }
1594
1662
  };
1595
1663
  //# sourceMappingURL=spo.js.map
@@ -0,0 +1,12 @@
1
+ import { setTimeout } from "timers/promises";
2
+ export const timersUtil = {
3
+ /**
4
+ * Timeout for a specific duration.
5
+ * @param duration Duration in milliseconds.
6
+ */
7
+ /* c8 ignore next 3 */
8
+ async setTimeout(duration) {
9
+ return setTimeout(duration);
10
+ }
11
+ };
12
+ //# sourceMappingURL=timersUtil.js.map
@@ -198,6 +198,14 @@ export const urlUtil = {
198
198
  return rootUrl.origin;
199
199
  }
200
200
  },
201
+ /**
202
+ * Removes leading slashes from the URL.
203
+ * @param url The URL to process.
204
+ * @returns The URL without leading slashes.
205
+ */
206
+ removeLeadingSlashes(url) {
207
+ return url.replace(/^\/+/, '');
208
+ },
201
209
  /**
202
210
  * Removes trailing slashes from the URL.
203
211
  * @param url The URL to process.
package/dist/utils/zod.js CHANGED
@@ -60,7 +60,7 @@ function parseDefault(def, _options, currentOption) {
60
60
  function parseEnum(def, _options, currentOption) {
61
61
  if (currentOption) {
62
62
  currentOption.type = 'string';
63
- currentOption.autocomplete = def.values;
63
+ currentOption.autocomplete = [...def.values];
64
64
  }
65
65
  return;
66
66
  }
@@ -2,6 +2,11 @@ Setting name|Definition|Default value
2
2
  ------------|----------|-------------
3
3
  `authType`|Default login method to use when running `m365 login` without the `--authType` option.|`deviceCode`
4
4
  `autoOpenLinksInBrowser`|Automatically open the browser for all commands which return a url and expect the user to copy paste this to the browser. For example when logging in, using `m365 login` in device code mode.|`false`
5
+ `clientId`|ID of the default Entra ID app use by the CLI to authenticate|``
6
+ `clientSecret`|Secret of the default Entra ID app use by the CLI to authenticate|``
7
+ `clientCertificateFile`|Path to the file containing the client certificate to use for authentication|``
8
+ `clientCertificateBase64Encoded`|Base64-encoded client certificate contents|``
9
+ `clientCertificatePassword`|Password to the client certificate file|``
5
10
  `copyDeviceCodeToClipboard`|Automatically copy the device code to the clipboard when running `m365 login` command in device code mode|`false`
6
11
  `csvEscape`|Single character used for escaping; only apply to characters matching the quote and the escape options|`"`
7
12
  `csvHeader`|Display the column names on the first line|`true`
@@ -17,4 +22,4 @@ Setting name|Definition|Default value
17
22
  `prompt`|Prompts for missing values in required options and enables interactive selection when multiple values are available for a command that requires a specific value to be retrieved.|`true`
18
23
  `promptListPageSize`|By default, lists of choices longer than 7 will be paginated. Use this option to control how many choices will appear on the screen at once.|7
19
24
  `showHelpOnFailure`|Automatically display help when executing a command failed|`true`
20
- `showSpinner`|Display spinner when executing commands|`true`
25
+ `tenantId`|ID of the default tenant to use when authenticating with|``
@@ -22,7 +22,7 @@ This command gets all the necessary diagnostic information needed to triage and
22
22
 
23
23
  ## Examples
24
24
 
25
- Retrieve diagnostic information
25
+ Retrieve diagnostic information.
26
26
 
27
27
  ```sh
28
28
  m365 cli doctor
@@ -42,18 +42,20 @@ m365 cli doctor
42
42
  },
43
43
  "cliVersion": "6.1.0",
44
44
  "nodeVersion": "v16.13.0",
45
- "cliAadAppId": "31359c7f-bd7e-475c-86db-fdb8c937548e",
46
- "cliAadAppTenant": "common",
47
- "authMode": "DeviceCode",
45
+ "cliEntraAppId": "31359c7f-bd7e-475c-86db-fdb8c937548e",
46
+ "cliEntraAppTenant": "common",
47
+ "authMode": "deviceCode",
48
48
  "cliEnvironment": "",
49
49
  "cliConfig": {
50
50
  "output": "json",
51
51
  "showHelpOnFailure": false
52
52
  },
53
53
  "roles": [],
54
- "scopes": [
55
- "AllSites.FullControl"
56
- ]
54
+ "scopes": {
55
+ "https://graph.microsoft.com": [
56
+ "AllSites.FullControl"
57
+ ]
58
+ }
57
59
  }
58
60
  ```
59
61
 
@@ -61,24 +63,24 @@ m365 cli doctor
61
63
  <TabItem value="Text">
62
64
 
63
65
  ```text
64
- authMode : DeviceCode
65
- cliAadAppId : 31359c7f-bd7e-475c-86db-fdb8c937548e
66
- cliAadAppTenant: common
67
- cliConfig : {"output":"json","showHelpOnFailure":false}
68
- cliEnvironment :
69
- cliVersion : 6.1.0
70
- nodeVersion : v16.13.0
71
- os : {"platform":"win32","version":"Windows 10 Pro","release":"10.0.19045"}
72
- roles : []
73
- scopes : ["AllSites.FullControl"]
66
+ authMode : deviceCode
67
+ cliConfig : {"output":"json","showHelpOnFailure":false}
68
+ cliEntraAppId : 31359c7f-bd7e-475c-86db-fdb8c937548e
69
+ cliEntraAppTenant: common
70
+ cliEnvironment :
71
+ cliVersion : 6.1.0
72
+ nodeVersion : v16.13.0
73
+ os : {"platform":"win32","version":"Windows 10 Pro","release":"10.0.19045"}
74
+ roles : []
75
+ scopes : {"https://graph.microsoft.com":["AllSites.FullControl"]}
74
76
  ```
75
77
 
76
78
  </TabItem>
77
79
  <TabItem value="CSV">
78
80
 
79
81
  ```csv
80
- os,cliVersion,nodeVersion,cliAadAppId,cliAadAppTenant,authMode,cliEnvironment,cliConfig,roles,scopes
81
- "{""platform"":""win32"",""version"":""Windows 10 Pro"",""release"":""10.0.19045""}",6.1.0,v16.13.0,31359c7f-bd7e-475c-86db-fdb8c937548e,common,DeviceCode,,"{""output"":""json"",""showHelpOnFailure"":false}",[],"[""AllSites.FullControl""]"
82
+ os,cliVersion,nodeVersion,cliEntraAppId,cliEntraAppTenant,authMode,cliEnvironment,cliConfig,roles,scopes
83
+ "{""platform"":""win32"",""version"":""Windows 10 Pro"",""release"":""10.0.19045""}",6.1.0,v16.13.0,31359c7f-bd7e-475c-86db-fdb8c937548e,common,deviceCode,,"{""output"":""json"",""showHelpOnFailure"":false}",[],"{""https://graph.microsoft.com"":[""AllSites.FullControl""]}"
82
84
  ```
83
85
 
84
86
  </TabItem>
@@ -93,12 +95,11 @@ m365 cli doctor
93
95
  ---------|-------
94
96
  cliVersion | 6.1.0
95
97
  nodeVersion | v16.13.0
96
- cliAadAppId | 31359c7f-bd7e-475c-86db-fdb8c937548e
97
- cliAadAppTenant | common
98
- authMode | DeviceCode
98
+ cliEntraAppId | 31359c7f-bd7e-475c-86db-fdb8c937548e
99
+ cliEntraAppTenant | common
100
+ authMode | deviceCode
99
101
  cliEnvironment |
100
102
  ```
101
103
 
102
104
  </TabItem>
103
105
  </Tabs>
104
-
@@ -9,13 +9,13 @@ Get the total storage used across all group mailboxes and group sites
9
9
  ## Usage
10
10
 
11
11
  ```sh
12
- m365 entra m365group report activitystorage [options]
12
+ m365 entra m365group report activitystorage [options]
13
13
  ```
14
14
 
15
15
  ## Alias
16
16
 
17
17
  ```sh
18
- m365 aad m365group report activitystorage [options]
18
+ m365 aad m365group report activitystorage [options]
19
19
  ```
20
20
 
21
21
  ## Options
@@ -19,11 +19,14 @@ m365 aad m365group set [options]
19
19
  ## Options
20
20
 
21
21
  ```md definition-list
22
- `-i, --id <id>`
22
+ `-i, --id [id]`
23
23
  : The ID of the Microsoft 365 Group to update
24
24
 
25
25
  `-n, --displayName [displayName]`
26
- : Display name for the Microsoft 365 Group
26
+ : Display name of the Microsoft 365 Group to update
27
+
28
+ `--newDisplayName [newDisplayName]`
29
+ : New display name for the Microsoft 365 Group
27
30
 
28
31
  `-d, --description [description]`
29
32
  : Description for the Microsoft 365 Group
@@ -72,7 +75,7 @@ Options `allowExternalSenders` and `autoSubscribeNewMembers` can only be set usi
72
75
  Update Microsoft 365 Group display name.
73
76
 
74
77
  ```sh
75
- m365 entra m365group set --id 28beab62-7540-4db1-a23f-29a6018a3848 --displayName Finance
78
+ m365 entra m365group set --id 28beab62-7540-4db1-a23f-29a6018a3848 --newDisplayName Finance
76
79
  ```
77
80
 
78
81
  Change Microsoft 365 Group visibility to public.
@@ -81,16 +84,16 @@ Change Microsoft 365 Group visibility to public.
81
84
  m365 entra m365group set --id 28beab62-7540-4db1-a23f-29a6018a3848 --isPrivate `false`
82
85
  ```
83
86
 
84
- Add new Microsoft 365 Group owners.
87
+ Add new Microsoft 365 Group owners of group.
85
88
 
86
89
  ```sh
87
- m365 entra m365group set --id 28beab62-7540-4db1-a23f-29a6018a3848 --owners "DebraB@contoso.onmicrosoft.com,DiegoS@contoso.onmicrosoft.com"
90
+ m365 entra m365group set --displayName 'Project Team' --owners "DebraB@contoso.onmicrosoft.com,DiegoS@contoso.onmicrosoft.com"
88
91
  ```
89
92
 
90
93
  Add new Microsoft 365 Group members.
91
94
 
92
95
  ```sh
93
- m365 entra m365group set --id 28beab62-7540-4db1-a23f-29a6018a3848 --members "DebraB@contoso.onmicrosoft.com,DiegoS@contoso.onmicrosoft.com"
96
+ m365 entra m365group set --displayName 'Project Team' --members "DebraB@contoso.onmicrosoft.com,DiegoS@contoso.onmicrosoft.com"
94
97
  ```
95
98
 
96
99
  Update Microsoft 365 Group logo.
@@ -37,9 +37,6 @@ m365 teams user add
37
37
  `--teamName [teamName]`
38
38
  : The display name of the Microsoft Teams team. Specify only one of the following: `groupId`, `groupName`, `teamId`, or `teamName`.
39
39
 
40
- `-n, --userName [userName]`
41
- : (deprecated) User's UPN (User Principal Name), e.g. johndoe@example.com.
42
-
43
40
  `--ids [ids]`
44
41
  : Microsoft Entra IDs of users. You can also pass a comma-separated list of IDs. Specify either `ids` or `userNames` but not both.
45
42
 
@@ -63,13 +63,13 @@ For more information about using these options, see the Microsoft Graph API docu
63
63
  Creates an external item with simple properties that everyone is allowed to access
64
64
 
65
65
  ```sh
66
- m365 external item add --id "pnp-ensure-siteassets-library" --connectionId "samplesolutiongallery" --content "Ensure that the Site Assets library is created." --title "Ensure the Site Assets Library is created" --description "Ensure that the Site Assets library is created." --authors "Phil Harding" --acls "grant,everyone,everyone"
66
+ m365 external item add --id "pnp-ensure-siteassets-library" --externalConnectionId "samplesolutiongallery" --content "Ensure that the Site Assets library is created." --title "Ensure the Site Assets Library is created" --description "Ensure that the Site Assets library is created." --authors "Phil Harding" --acls "grant,everyone,everyone"
67
67
  ```
68
68
 
69
69
  Creates an external item with multi-value properties accessible only to users from the specified Entra group
70
70
 
71
71
  ```sh
72
- m365 external item add --id "pnp-ensure-siteassets-library" --connectionId "samplesolutiongallery" --content "Ensure that the Site Assets library is created." --title "Ensure the Site Assets Library is created" --description "Ensure that the Site Assets library is created." --authors@odata.type "Collection(String)" --authors "Phil Harding;#Steve Smith" --acls "grant,group,Super users"
72
+ m365 external item add --id "pnp-ensure-siteassets-library" --externalConnectionId "samplesolutiongallery" --content "Ensure that the Site Assets library is created." --title "Ensure the Site Assets Library is created" --description "Ensure that the Site Assets library is created." --authors@odata.type "Collection(String)" --authors "Phil Harding;#Steve Smith" --acls "grant,group,Super users"
73
73
  ```
74
74
 
75
75
  ## Response
@@ -123,7 +123,7 @@ m365 external item add --id "pnp-ensure-siteassets-library" --connectionId "samp
123
123
  <TabItem value="Markdown">
124
124
 
125
125
  ```md
126
- # m365 external item add --id "pnp-ensure-siteassets-library" --connectionId "samplesolutiongallery" --content "Ensure that the Site Assets library is created." --title "Ensure the Site Assets Library is created" --description "Ensure that the Site Assets library is created." --authors "Phil Harding" --acls "grant,everyone,everyone"
126
+ # m365 external item add --id "pnp-ensure-siteassets-library" --externalConnectionId "samplesolutiongallery" --content "Ensure that the Site Assets library is created." --title "Ensure the Site Assets Library is created" --description "Ensure that the Site Assets library is created." --authors "Phil Harding" --acls "grant,everyone,everyone"
127
127
 
128
128
  Date: 2023-10-28
129
129