@pnp/cli-microsoft365 9.0.0-beta.0d94b15 → 9.0.0-beta.1516729
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/allCommands.json +1 -1
- package/allCommandsFull.json +1 -1
- package/dist/Auth.js +11 -12
- package/dist/Command.js +1 -3
- package/dist/cli/cli.js +57 -8
- package/dist/config.js +60 -5
- package/dist/m365/app/commands/permission/permission-add.js +9 -9
- package/dist/m365/base/SpoCommand.js +1 -1
- package/dist/m365/cli/commands/cli-consent.js +9 -5
- package/dist/m365/cli/commands/cli-doctor.js +2 -2
- package/dist/m365/cli/commands/cli-reconsent.js +2 -3
- package/dist/m365/cli/commands/config/config-set.js +12 -3
- package/dist/m365/commands/login.js +38 -14
- package/dist/m365/commands/setup.js +256 -33
- package/dist/m365/commands/status.js +2 -2
- package/dist/m365/connection/commands/connection-list.js +4 -4
- package/dist/m365/entra/commands/app/app-add.js +52 -288
- package/dist/m365/entra/commands/enterpriseapp/enterpriseapp-add.js +13 -13
- package/dist/m365/entra/commands/enterpriseapp/enterpriseapp-get.js +18 -18
- package/dist/m365/entra/commands/enterpriseapp/enterpriseapp-list.js +1 -1
- package/dist/m365/entra/commands/group/group-user-list.js +4 -4
- package/dist/m365/entra/commands/m365group/m365group-conversation-post-list.js +4 -4
- package/dist/m365/entra/commands/m365group/m365group-recyclebinitem-list.js +3 -3
- package/dist/m365/entra/commands/m365group/m365group-user-list.js +9 -6
- package/dist/m365/onenote/commands/notebook/notebook-add.js +132 -0
- package/dist/m365/onenote/commands.js +1 -0
- package/dist/m365/outlook/commands/message/message-get.js +11 -11
- package/dist/m365/spfx/commands/project/DeployWorkflow.js +1 -1
- package/dist/m365/spfx/commands/project/project-github-workflow-add.js +10 -1
- package/dist/m365/spo/commands/applicationcustomizer/applicationcustomizer-get.js +1 -0
- package/dist/m365/spo/commands/file/file-copy.js +34 -55
- package/dist/m365/spo/commands/folder/folder-set.js +4 -0
- package/dist/m365/spo/commands/list/list-list.js +4 -1
- package/dist/m365/spo/commands/site/site-appcatalog-remove.js +24 -48
- package/dist/m365/spo/commands/site/site-get.js +12 -16
- package/dist/m365/spo/commands/site/site-remove.js +7 -1
- package/dist/m365/spo/commands/tenant/tenant-recyclebinitem-restore.js +22 -2
- package/dist/m365/spo/commands.js +1 -0
- package/dist/m365/viva/commands/engage/engage-group-list.js +5 -0
- package/dist/m365/viva/commands/engage/engage-group-user-add.js +5 -0
- package/dist/m365/viva/commands/engage/engage-group-user-remove.js +5 -0
- package/dist/m365/viva/commands/engage/engage-message-add.js +5 -0
- package/dist/m365/viva/commands/engage/engage-message-get.js +5 -0
- package/dist/m365/viva/commands/engage/engage-message-like-set.js +5 -0
- package/dist/m365/viva/commands/engage/engage-message-list.js +5 -0
- package/dist/m365/viva/commands/engage/engage-message-remove.js +5 -0
- package/dist/m365/viva/commands/engage/engage-network-list.js +5 -0
- package/dist/m365/viva/commands/engage/engage-report-activitycounts.js +8 -0
- package/dist/m365/viva/commands/engage/engage-report-activityusercounts.js +8 -0
- package/dist/m365/viva/commands/engage/engage-report-activityuserdetail.js +8 -0
- package/dist/m365/viva/commands/engage/engage-report-deviceusagedistributionusercounts.js +8 -0
- package/dist/m365/viva/commands/engage/engage-report-deviceusageusercounts.js +8 -0
- package/dist/m365/viva/commands/engage/engage-report-deviceusageuserdetail.js +8 -0
- package/dist/m365/viva/commands/engage/engage-report-groupsactivitycounts.js +8 -0
- package/dist/m365/viva/commands/engage/engage-report-groupsactivitydetail.js +8 -0
- package/dist/m365/viva/commands/engage/engage-report-groupsactivitygroupcounts.js +8 -0
- package/dist/m365/viva/commands/engage/engage-search.js +5 -0
- package/dist/m365/viva/commands/engage/engage-user-get.js +5 -0
- package/dist/m365/viva/commands/engage/engage-user-list.js +5 -0
- package/dist/m365/viva/commands/engage/yammerCommands.js +25 -0
- package/dist/settingsNames.js +7 -1
- package/dist/utils/entraApp.js +283 -0
- package/dist/utils/spo.js +0 -74
- package/docs/docs/_clisettings.mdx +6 -0
- package/docs/docs/cmd/app/permission/permission-add.mdx +5 -5
- package/docs/docs/cmd/cli/cli-consent.mdx +1 -1
- package/docs/docs/cmd/entra/enterpriseapp/enterpriseapp-add.mdx +12 -12
- package/docs/docs/cmd/entra/enterpriseapp/enterpriseapp-get.mdx +14 -14
- package/docs/docs/cmd/entra/enterpriseapp/enterpriseapp-list.mdx +5 -5
- package/docs/docs/cmd/entra/group/group-user-list.mdx +7 -7
- package/docs/docs/cmd/entra/m365group/m365group-conversation-post-list.mdx +5 -5
- package/docs/docs/cmd/entra/m365group/m365group-recyclebinitem-list.mdx +3 -3
- package/docs/docs/cmd/entra/m365group/m365group-user-list.mdx +1 -1
- package/docs/docs/cmd/onenote/notebook/notebook-add.mdx +169 -0
- package/docs/docs/cmd/outlook/message/message-get.mdx +5 -5
- package/docs/docs/cmd/setup.mdx +16 -3
- package/docs/docs/cmd/spfx/project/project-github-workflow-add.mdx +12 -11
- package/docs/docs/cmd/spo/applicationcustomizer/applicationcustomizer-get.mdx +5 -6
- package/docs/docs/cmd/spo/file/file-copy.mdx +12 -119
- package/docs/docs/cmd/spo/folder/folder-set.mdx +6 -0
- package/docs/docs/cmd/spo/list/list-list.mdx +7 -5
- package/docs/docs/cmd/spo/site/site-appcatalog-remove.mdx +2 -11
- package/docs/docs/cmd/spo/site/site-remove.mdx +3 -0
- package/docs/docs/cmd/spo/tenant/tenant-recyclebinitem-restore.mdx +49 -2
- package/package.json +1 -1
package/dist/Auth.js
CHANGED
|
@@ -4,7 +4,6 @@ import { CommandError } from './Command.js';
|
|
|
4
4
|
import { FileTokenStorage } from './auth/FileTokenStorage.js';
|
|
5
5
|
import { msalCachePlugin } from './auth/msalCachePlugin.js';
|
|
6
6
|
import { cli } from './cli/cli.js';
|
|
7
|
-
import config from './config.js';
|
|
8
7
|
import request from './request.js';
|
|
9
8
|
import { settingsNames } from './settingsNames.js';
|
|
10
9
|
import * as accessTokenUtil from './utils/accessToken.js';
|
|
@@ -22,10 +21,10 @@ export class Connection {
|
|
|
22
21
|
this.active = false;
|
|
23
22
|
this.authType = AuthType.DeviceCode;
|
|
24
23
|
this.certificateType = CertificateType.Unknown;
|
|
24
|
+
// ID of the tenant where the Microsoft Entra app is registered; common if multi-tenant
|
|
25
|
+
this.tenant = 'common';
|
|
25
26
|
this.cloudType = CloudType.Public;
|
|
26
27
|
this.accessTokens = {};
|
|
27
|
-
this.appId = config.cliEntraAppId;
|
|
28
|
-
this.tenant = config.tenant;
|
|
29
28
|
this.cloudType = CloudType.Public;
|
|
30
29
|
}
|
|
31
30
|
deactivate() {
|
|
@@ -44,18 +43,18 @@ export class Connection {
|
|
|
44
43
|
this.thumbprint = undefined;
|
|
45
44
|
this.spoUrl = undefined;
|
|
46
45
|
this.spoTenantId = undefined;
|
|
47
|
-
this.appId =
|
|
48
|
-
this.tenant =
|
|
46
|
+
this.appId = cli.getClientId();
|
|
47
|
+
this.tenant = cli.getTenant();
|
|
49
48
|
}
|
|
50
49
|
}
|
|
51
50
|
export var AuthType;
|
|
52
51
|
(function (AuthType) {
|
|
53
|
-
AuthType[
|
|
54
|
-
AuthType[
|
|
55
|
-
AuthType[
|
|
56
|
-
AuthType[
|
|
57
|
-
AuthType[
|
|
58
|
-
AuthType[
|
|
52
|
+
AuthType["DeviceCode"] = "deviceCode";
|
|
53
|
+
AuthType["Password"] = "password";
|
|
54
|
+
AuthType["Certificate"] = "certificate";
|
|
55
|
+
AuthType["Identity"] = "identity";
|
|
56
|
+
AuthType["Browser"] = "browser";
|
|
57
|
+
AuthType["Secret"] = "secret";
|
|
59
58
|
})(AuthType || (AuthType = {}));
|
|
60
59
|
export var CertificateType;
|
|
61
60
|
(function (CertificateType) {
|
|
@@ -702,7 +701,7 @@ export class Auth {
|
|
|
702
701
|
const details = {
|
|
703
702
|
connectionName: connection.name,
|
|
704
703
|
connectedAs: connection.identityName,
|
|
705
|
-
authType:
|
|
704
|
+
authType: connection.authType,
|
|
706
705
|
appId: connection.appId,
|
|
707
706
|
appTenant: connection.tenant,
|
|
708
707
|
cloudType: CloudType[connection.cloudType]
|
package/dist/Command.js
CHANGED
|
@@ -111,9 +111,7 @@ class Command {
|
|
|
111
111
|
prompted = true;
|
|
112
112
|
await cli.error('🌶️ Provide values for the following parameters:');
|
|
113
113
|
}
|
|
114
|
-
const answer = optionInfo
|
|
115
|
-
? await prompt.forSelection({ message: `${optionInfo.name}: `, choices: optionInfo.autocomplete.map((choice) => { return { name: choice, value: choice }; }) })
|
|
116
|
-
: await prompt.forInput({ message: `${optionInfo.name}: ` });
|
|
114
|
+
const answer = await cli.promptForValue(optionInfo);
|
|
117
115
|
args.options[optionInfo.name] = answer;
|
|
118
116
|
}
|
|
119
117
|
if (prompted) {
|
package/dist/cli/cli.js
CHANGED
|
@@ -59,6 +59,12 @@ function getSettingWithDefaultValue(settingName, defaultValue) {
|
|
|
59
59
|
return configuredValue;
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
+
function getClientId() {
|
|
63
|
+
return cli.getSettingWithDefaultValue(settingsNames.clientId, process.env.CLIMICROSOFT365_ENTRAAPPID || process.env.CLIMICROSOFT365_AADAPPID);
|
|
64
|
+
}
|
|
65
|
+
function getTenant() {
|
|
66
|
+
return cli.getSettingWithDefaultValue(settingsNames.tenantId, process.env.CLIMICROSOFT365_TENANT || 'common');
|
|
67
|
+
}
|
|
62
68
|
async function execute(rawArgs) {
|
|
63
69
|
const start = process.hrtime.bigint();
|
|
64
70
|
// for completion commands we also need information about commands' options
|
|
@@ -137,14 +143,38 @@ async function execute(rawArgs) {
|
|
|
137
143
|
}
|
|
138
144
|
let finalArgs = cli.optionsFromArgs.options;
|
|
139
145
|
if (cli.commandToExecute?.command.schema) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
+
while (true) {
|
|
147
|
+
const startValidation = process.hrtime.bigint();
|
|
148
|
+
const result = cli.commandToExecute.command.getSchemaToParse().safeParse(cli.optionsFromArgs.options);
|
|
149
|
+
const endValidation = process.hrtime.bigint();
|
|
150
|
+
timings.validation.push(Number(endValidation - startValidation));
|
|
151
|
+
if (result.success) {
|
|
152
|
+
finalArgs = result.data;
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
const hasNonRequiredErrors = result.error.errors.some(e => e.code !== 'invalid_type' || e.received !== 'undefined');
|
|
157
|
+
const shouldPrompt = cli.getSettingWithDefaultValue(settingsNames.prompt, true);
|
|
158
|
+
if (hasNonRequiredErrors === false &&
|
|
159
|
+
shouldPrompt) {
|
|
160
|
+
await cli.error('🌶️ Provide values for the following parameters:');
|
|
161
|
+
for (const error of result.error.errors) {
|
|
162
|
+
const optionInfo = cli.commandToExecute.options.find(o => o.name === error.path.join('.'));
|
|
163
|
+
const answer = await cli.promptForValue(optionInfo);
|
|
164
|
+
cli.optionsFromArgs.options[error.path.join('.')] = answer;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
result.error.errors.forEach(e => {
|
|
169
|
+
if (e.code === 'invalid_type' &&
|
|
170
|
+
e.received === 'undefined') {
|
|
171
|
+
e.message = `Required option not specified`;
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
return cli.closeWithError(result.error, cli.optionsFromArgs, true);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
146
177
|
}
|
|
147
|
-
finalArgs = result.data;
|
|
148
178
|
}
|
|
149
179
|
else {
|
|
150
180
|
const startValidation = process.hrtime.bigint();
|
|
@@ -753,7 +783,7 @@ async function closeWithError(error, args, showHelpIfEnabled = false) {
|
|
|
753
783
|
}
|
|
754
784
|
let errorMessage = error instanceof CommandError ? error.message : error;
|
|
755
785
|
if (error instanceof ZodError) {
|
|
756
|
-
errorMessage = error.errors.map(e => `${e.path}: ${e.message}`).join(os.EOL);
|
|
786
|
+
errorMessage = error.errors.map(e => `${e.path.join('.')}: ${e.message}`).join(os.EOL);
|
|
757
787
|
}
|
|
758
788
|
if ((!args.options.output || args.options.output === 'json') &&
|
|
759
789
|
!cli.getSettingWithDefaultValue(settingsNames.printErrorsAsPlainText, true)) {
|
|
@@ -793,6 +823,16 @@ async function error(message, ...optionalParams) {
|
|
|
793
823
|
console.error(message, ...optionalParams);
|
|
794
824
|
}
|
|
795
825
|
}
|
|
826
|
+
async function promptForValue(optionInfo) {
|
|
827
|
+
return optionInfo.autocomplete !== undefined
|
|
828
|
+
? await prompt.forSelection({
|
|
829
|
+
message: `${optionInfo.name}: `,
|
|
830
|
+
choices: optionInfo.autocomplete.map((choice) => {
|
|
831
|
+
return { name: choice, value: choice };
|
|
832
|
+
})
|
|
833
|
+
})
|
|
834
|
+
: await prompt.forInput({ message: `${optionInfo.name}: ` });
|
|
835
|
+
}
|
|
796
836
|
async function promptForSelection(config) {
|
|
797
837
|
const answer = await prompt.forSelection(config);
|
|
798
838
|
await cli.error('');
|
|
@@ -803,6 +843,11 @@ async function promptForConfirmation(config) {
|
|
|
803
843
|
await cli.error('');
|
|
804
844
|
return answer;
|
|
805
845
|
}
|
|
846
|
+
async function promptForInput(config) {
|
|
847
|
+
const answer = await prompt.forInput(config);
|
|
848
|
+
await cli.error('');
|
|
849
|
+
return answer;
|
|
850
|
+
}
|
|
806
851
|
async function handleMultipleResultsFound(message, values) {
|
|
807
852
|
const prompt = cli.getSettingWithDefaultValue(settingsNames.prompt, true);
|
|
808
853
|
if (!prompt) {
|
|
@@ -837,7 +882,9 @@ export const cli = {
|
|
|
837
882
|
closeWithError,
|
|
838
883
|
commands,
|
|
839
884
|
commandToExecute,
|
|
885
|
+
getClientId,
|
|
840
886
|
getConfig,
|
|
887
|
+
getTenant,
|
|
841
888
|
currentCommandName,
|
|
842
889
|
error,
|
|
843
890
|
execute,
|
|
@@ -856,7 +903,9 @@ export const cli = {
|
|
|
856
903
|
optionsFromArgs,
|
|
857
904
|
printAvailableCommands,
|
|
858
905
|
promptForConfirmation,
|
|
906
|
+
promptForInput,
|
|
859
907
|
promptForSelection,
|
|
908
|
+
promptForValue,
|
|
860
909
|
shouldTrimOutput,
|
|
861
910
|
yargsConfiguration
|
|
862
911
|
};
|
package/dist/config.js
CHANGED
|
@@ -1,10 +1,65 @@
|
|
|
1
|
-
import { app } from
|
|
2
|
-
const cliEntraAppId = '31359c7f-bd7e-475c-86db-fdb8c937548e';
|
|
1
|
+
import { app } from './utils/app.js';
|
|
3
2
|
export default {
|
|
3
|
+
allScopes: [
|
|
4
|
+
'https://graph.windows.net/Directory.AccessAsUser.All',
|
|
5
|
+
'https://management.azure.com/user_impersonation',
|
|
6
|
+
'https://admin.services.crm.dynamics.com/user_impersonation',
|
|
7
|
+
'https://graph.microsoft.com/AppCatalog.ReadWrite.All',
|
|
8
|
+
'https://graph.microsoft.com/AuditLog.Read.All',
|
|
9
|
+
'https://graph.microsoft.com/Bookings.Read.All',
|
|
10
|
+
'https://graph.microsoft.com/Calendars.Read',
|
|
11
|
+
'https://graph.microsoft.com/ChannelMember.ReadWrite.All',
|
|
12
|
+
'https://graph.microsoft.com/ChannelMessage.Read.All',
|
|
13
|
+
'https://graph.microsoft.com/ChannelMessage.ReadWrite',
|
|
14
|
+
'https://graph.microsoft.com/ChannelMessage.Send',
|
|
15
|
+
'https://graph.microsoft.com/ChannelSettings.ReadWrite.All',
|
|
16
|
+
'https://graph.microsoft.com/Chat.ReadWrite',
|
|
17
|
+
'https://graph.microsoft.com/Directory.AccessAsUser.All',
|
|
18
|
+
'https://graph.microsoft.com/Directory.ReadWrite.All',
|
|
19
|
+
'https://graph.microsoft.com/ExternalConnection.ReadWrite.All',
|
|
20
|
+
'https://graph.microsoft.com/ExternalItem.ReadWrite.All',
|
|
21
|
+
'https://graph.microsoft.com/Group.ReadWrite.All',
|
|
22
|
+
'https://graph.microsoft.com/IdentityProvider.ReadWrite.All',
|
|
23
|
+
'https://graph.microsoft.com/InformationProtectionPolicy.Read',
|
|
24
|
+
'https://graph.microsoft.com/Mail.Read.Shared',
|
|
25
|
+
'https://graph.microsoft.com/Mail.ReadWrite',
|
|
26
|
+
'https://graph.microsoft.com/Mail.Send',
|
|
27
|
+
'https://graph.microsoft.com/Notes.ReadWrite.All',
|
|
28
|
+
'https://graph.microsoft.com/OnlineMeetingArtifact.Read.All',
|
|
29
|
+
'https://graph.microsoft.com/OnlineMeetings.ReadWrite',
|
|
30
|
+
'https://graph.microsoft.com/OnlineMeetingTranscript.Read.All',
|
|
31
|
+
'https://graph.microsoft.com/PeopleSettings.ReadWrite.All',
|
|
32
|
+
'https://graph.microsoft.com/Place.Read.All',
|
|
33
|
+
'https://graph.microsoft.com/Policy.Read.All',
|
|
34
|
+
'https://graph.microsoft.com/RecordsManagement.ReadWrite.All',
|
|
35
|
+
'https://graph.microsoft.com/Reports.Read.All',
|
|
36
|
+
'https://graph.microsoft.com/RoleAssignmentSchedule.ReadWrite.Directory',
|
|
37
|
+
'https://graph.microsoft.com/RoleEligibilitySchedule.Read.Directory',
|
|
38
|
+
'https://graph.microsoft.com/SecurityEvents.Read.All',
|
|
39
|
+
'https://graph.microsoft.com/ServiceHealth.Read.All',
|
|
40
|
+
'https://graph.microsoft.com/ServiceMessage.Read.All',
|
|
41
|
+
'https://graph.microsoft.com/ServiceMessageViewpoint.Write',
|
|
42
|
+
'https://graph.microsoft.com/Sites.Read.All',
|
|
43
|
+
'https://graph.microsoft.com/Tasks.ReadWrite',
|
|
44
|
+
'https://graph.microsoft.com/Team.Create',
|
|
45
|
+
'https://graph.microsoft.com/TeamMember.ReadWrite.All',
|
|
46
|
+
'https://graph.microsoft.com/TeamsAppInstallation.ReadWriteForUser',
|
|
47
|
+
'https://graph.microsoft.com/TeamSettings.ReadWrite.All',
|
|
48
|
+
'https://graph.microsoft.com/TeamsTab.ReadWrite.All',
|
|
49
|
+
'https://graph.microsoft.com/User.Invite.All',
|
|
50
|
+
'https://manage.office.com/ActivityFeed.Read',
|
|
51
|
+
'https://manage.office.com/ServiceHealth.Read',
|
|
52
|
+
'https://analysis.windows.net/powerbi/api/Dataset.Read.All',
|
|
53
|
+
'https://api.powerapps.com//User',
|
|
54
|
+
'https://microsoft.sharepoint-df.com/AllSites.FullControl',
|
|
55
|
+
'https://microsoft.sharepoint-df.com/TermStore.ReadWrite.All',
|
|
56
|
+
'https://microsoft.sharepoint-df.com/User.ReadWrite.All'
|
|
57
|
+
],
|
|
4
58
|
applicationName: `CLI for Microsoft 365 v${app.packageJson().version}`,
|
|
5
59
|
delimiter: 'm365\$',
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
60
|
+
configstoreName: 'cli-m365-config',
|
|
61
|
+
minimalScopes: [
|
|
62
|
+
'https://graph.microsoft.com/User.Read'
|
|
63
|
+
]
|
|
9
64
|
};
|
|
10
65
|
//# sourceMappingURL=config.js.map
|
|
@@ -33,12 +33,12 @@ class AppPermissionAddCommand extends AppCommand {
|
|
|
33
33
|
const appObject = await this.getAppObject();
|
|
34
34
|
const servicePrincipals = await odata.getAllItems(`${this.resource}/v1.0/myorganization/servicePrincipals?$select=appId,appRoles,id,oauth2PermissionScopes,servicePrincipalNames`);
|
|
35
35
|
const appPermissions = [];
|
|
36
|
-
if (args.options.
|
|
37
|
-
const delegatedPermissions = await this.getRequiredResourceAccessForApis(servicePrincipals, args.options.
|
|
36
|
+
if (args.options.delegatedPermission) {
|
|
37
|
+
const delegatedPermissions = await this.getRequiredResourceAccessForApis(servicePrincipals, args.options.delegatedPermission, ScopeType.Scope, appPermissions, logger);
|
|
38
38
|
this.addPermissionsToResourceArray(delegatedPermissions, appObject.requiredResourceAccess);
|
|
39
39
|
}
|
|
40
|
-
if (args.options.
|
|
41
|
-
const applicationPermissions = await this.getRequiredResourceAccessForApis(servicePrincipals, args.options.
|
|
40
|
+
if (args.options.applicationPermission) {
|
|
41
|
+
const applicationPermissions = await this.getRequiredResourceAccessForApis(servicePrincipals, args.options.applicationPermission, ScopeType.Role, appPermissions, logger);
|
|
42
42
|
this.addPermissionsToResourceArray(applicationPermissions, appObject.requiredResourceAccess);
|
|
43
43
|
}
|
|
44
44
|
const addPermissionsRequestOptions = {
|
|
@@ -198,17 +198,17 @@ _AppPermissionAddCommand_instances = new WeakSet(), _AppPermissionAddCommand_ini
|
|
|
198
198
|
this.telemetry.push((args) => {
|
|
199
199
|
Object.assign(this.telemetryProperties, {
|
|
200
200
|
appId: typeof args.options.appId !== 'undefined',
|
|
201
|
-
|
|
202
|
-
|
|
201
|
+
applicationPermission: typeof args.options.applicationPermission !== 'undefined',
|
|
202
|
+
delegatedPermission: typeof args.options.delegatedPermission !== 'undefined',
|
|
203
203
|
grantAdminConsent: !!args.options.grantAdminConsent
|
|
204
204
|
});
|
|
205
205
|
});
|
|
206
206
|
}, _AppPermissionAddCommand_initOptions = function _AppPermissionAddCommand_initOptions() {
|
|
207
|
-
this.options.unshift({ option: '--appId [appId]' }, { option: '--
|
|
207
|
+
this.options.unshift({ option: '--appId [appId]' }, { option: '--applicationPermission [applicationPermission]' }, { option: '--delegatedPermission [delegatedPermission]' }, { option: '--grantAdminConsent' });
|
|
208
208
|
}, _AppPermissionAddCommand_initOptionSets = function _AppPermissionAddCommand_initOptionSets() {
|
|
209
209
|
this.optionSets.push({
|
|
210
|
-
options: ['
|
|
211
|
-
runsWhen: (args) => args.options.
|
|
210
|
+
options: ['applicationPermission', 'delegatedPermission'],
|
|
211
|
+
runsWhen: (args) => args.options.delegatedPermission === undefined && args.options.applicationPermission === undefined
|
|
212
212
|
});
|
|
213
213
|
};
|
|
214
214
|
export default new AppPermissionAddCommand();
|
|
@@ -94,7 +94,7 @@ export default class SpoCommand extends Command {
|
|
|
94
94
|
catch (error) {
|
|
95
95
|
throw new CommandError(error);
|
|
96
96
|
}
|
|
97
|
-
if (auth.connection.active &&
|
|
97
|
+
if (auth.connection.active && auth.connection.authType === AuthType.Secret) {
|
|
98
98
|
throw new CommandError(`SharePoint does not support authentication using client ID and secret. Please use a different login type to use SharePoint commands.`);
|
|
99
99
|
}
|
|
100
100
|
await super.action(logger, args);
|
|
@@ -4,7 +4,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
4
4
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
5
|
};
|
|
6
6
|
var _CliConsentCommand_instances, _CliConsentCommand_initTelemetry, _CliConsentCommand_initOptions, _CliConsentCommand_initValidators;
|
|
7
|
-
import
|
|
7
|
+
import { cli } from '../../../cli/cli.js';
|
|
8
8
|
import AnonymousCommand from '../../base/AnonymousCommand.js';
|
|
9
9
|
import commands from '../commands.js';
|
|
10
10
|
class CliConsentCommand extends AnonymousCommand {
|
|
@@ -23,10 +23,14 @@ class CliConsentCommand extends AnonymousCommand {
|
|
|
23
23
|
}
|
|
24
24
|
async commandAction(logger, args) {
|
|
25
25
|
let scope = '';
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
switch (args.options.service) {
|
|
27
|
+
case 'yammer':
|
|
28
|
+
await this.warn(logger, 'The yammer service is deprecated. Please use the VivaEngage service instead.');
|
|
29
|
+
case 'VivaEngage':
|
|
30
|
+
scope = 'https://api.yammer.com/user_impersonation';
|
|
31
|
+
break;
|
|
28
32
|
}
|
|
29
|
-
await logger.log(`To consent permissions for executing ${args.options.service} commands, navigate in your web browser to https://login.microsoftonline.com/${
|
|
33
|
+
await logger.log(`To consent permissions for executing ${args.options.service} commands, navigate in your web browser to https://login.microsoftonline.com/${cli.getTenant()}/oauth2/v2.0/authorize?client_id=${cli.getClientId()}&response_type=code&scope=${encodeURIComponent(scope)}`);
|
|
30
34
|
}
|
|
31
35
|
async action(logger, args) {
|
|
32
36
|
await this.initAction(args, logger);
|
|
@@ -46,7 +50,7 @@ _CliConsentCommand_instances = new WeakSet(), _CliConsentCommand_initTelemetry =
|
|
|
46
50
|
});
|
|
47
51
|
}, _CliConsentCommand_initValidators = function _CliConsentCommand_initValidators() {
|
|
48
52
|
this.validators.push(async (args) => {
|
|
49
|
-
if (args.options.service !== 'VivaEngage') {
|
|
53
|
+
if (args.options.service !== 'VivaEngage' && args.options.service !== 'yammer') {
|
|
50
54
|
return `${args.options.service} is not a valid value for the service option. Allowed values: VivaEngage`;
|
|
51
55
|
}
|
|
52
56
|
return true;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import os from 'os';
|
|
2
|
-
import auth
|
|
2
|
+
import auth from '../../../Auth.js';
|
|
3
3
|
import { cli } from '../../../cli/cli.js';
|
|
4
4
|
import Command from '../../../Command.js';
|
|
5
5
|
import { app } from '../../../utils/app.js';
|
|
@@ -33,7 +33,7 @@ class CliDoctorCommand extends Command {
|
|
|
33
33
|
nodeVersion: process.version,
|
|
34
34
|
cliAadAppId: auth.connection.appId,
|
|
35
35
|
cliAadAppTenant: validation.isValidGuid(auth.connection.tenant) ? 'single' : auth.connection.tenant,
|
|
36
|
-
authMode:
|
|
36
|
+
authMode: auth.connection.authType,
|
|
37
37
|
cliEnvironment: process.env.CLIMICROSOFT365_ENV ? process.env.CLIMICROSOFT365_ENV : '',
|
|
38
38
|
cliConfig: cli.getConfig().all,
|
|
39
39
|
roles: roles,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { cli } from '../../../cli/cli.js';
|
|
2
|
-
import config from '../../../config.js';
|
|
3
2
|
import { settingsNames } from '../../../settingsNames.js';
|
|
4
3
|
import { browserUtil } from '../../../utils/browserUtil.js';
|
|
5
4
|
import AnonymousCommand from '../../base/AnonymousCommand.js';
|
|
@@ -12,9 +11,9 @@ class CliReconsentCommand extends AnonymousCommand {
|
|
|
12
11
|
return 'Returns URL to open in the browser to re-consent CLI for Microsoft 365 Microsoft Entra permissions';
|
|
13
12
|
}
|
|
14
13
|
async commandAction(logger) {
|
|
15
|
-
const url = `https://login.microsoftonline.com/${
|
|
14
|
+
const url = `https://login.microsoftonline.com/${cli.getTenant()}/oauth2/authorize?client_id=${cli.getClientId()}&response_type=code&prompt=admin_consent`;
|
|
16
15
|
if (cli.getSettingWithDefaultValue(settingsNames.autoOpenLinksInBrowser, false) === false) {
|
|
17
|
-
await logger.log(`To re-consent
|
|
16
|
+
await logger.log(`To re-consent your Microsoft Entra application, navigate in your web browser to ${url}.`);
|
|
18
17
|
return;
|
|
19
18
|
}
|
|
20
19
|
await logger.log(`Opening the following page in your browser: ${url}`);
|
|
@@ -4,8 +4,10 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
4
4
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
5
|
};
|
|
6
6
|
var _CliConfigSetCommand_instances, _a, _CliConfigSetCommand_initTelemetry, _CliConfigSetCommand_initOptions, _CliConfigSetCommand_initValidators;
|
|
7
|
+
import { AuthType } from "../../../../Auth.js";
|
|
7
8
|
import { cli } from "../../../../cli/cli.js";
|
|
8
9
|
import { settingsNames } from "../../../../settingsNames.js";
|
|
10
|
+
import { validation } from "../../../../utils/validation.js";
|
|
9
11
|
import AnonymousCommand from "../../../base/AnonymousCommand.js";
|
|
10
12
|
import commands from "../../commands.js";
|
|
11
13
|
class CliConfigSetCommand extends AnonymousCommand {
|
|
@@ -82,15 +84,22 @@ _a = CliConfigSetCommand, _CliConfigSetCommand_instances = new WeakSet(), _CliCo
|
|
|
82
84
|
cli.helpModes.indexOf(args.options.value) === -1) {
|
|
83
85
|
return `${args.options.value} is not a valid value for the option ${args.options.key}. Allowed values: ${cli.helpModes.join(', ')}`;
|
|
84
86
|
}
|
|
85
|
-
const allowedAuthTypes = ['certificate', 'deviceCode', 'password', 'identity', 'browser', 'secret'];
|
|
86
87
|
if (args.options.key === settingsNames.authType &&
|
|
87
|
-
|
|
88
|
-
return `${args.options.value} is not a valid value for the option ${args.options.key}. Allowed values: ${
|
|
88
|
+
!Object.values(AuthType).map(String).includes(args.options.value)) {
|
|
89
|
+
return `${args.options.value} is not a valid value for the option ${args.options.key}. Allowed values: ${Object.values(AuthType).join(', ')}`;
|
|
89
90
|
}
|
|
90
91
|
if (args.options.key === settingsNames.helpTarget &&
|
|
91
92
|
!cli.helpTargets.includes(args.options.value)) {
|
|
92
93
|
return `${args.options.value} is not a valid value for the option ${args.options.key}. Allowed values: ${cli.helpTargets.join(', ')}`;
|
|
93
94
|
}
|
|
95
|
+
if (args.options.key === settingsNames.clientId &&
|
|
96
|
+
!validation.isValidGuid(args.options.value)) {
|
|
97
|
+
return `${args.options.value} is not a valid value for the option ${args.options.key}. The value has to be a valid GUID.`;
|
|
98
|
+
}
|
|
99
|
+
if (args.options.key === settingsNames.tenantId &&
|
|
100
|
+
!(args.options.value === 'common' || validation.isValidGuid(args.options.value))) {
|
|
101
|
+
return `${args.options.value} is not a valid value for the option ${args.options.key}. The value has to be a valid GUID or 'common'.`;
|
|
102
|
+
}
|
|
94
103
|
return true;
|
|
95
104
|
});
|
|
96
105
|
};
|
|
@@ -3,13 +3,12 @@ import { z } from 'zod';
|
|
|
3
3
|
import auth, { AuthType, CloudType } from '../../Auth.js';
|
|
4
4
|
import Command, { CommandError, globalOptionsZod } from '../../Command.js';
|
|
5
5
|
import { cli } from '../../cli/cli.js';
|
|
6
|
-
import config from '../../config.js';
|
|
7
6
|
import { settingsNames } from '../../settingsNames.js';
|
|
8
7
|
import { zod } from '../../utils/zod.js';
|
|
9
8
|
import commands from './commands.js';
|
|
10
9
|
const options = globalOptionsZod
|
|
11
10
|
.extend({
|
|
12
|
-
authType: zod.alias('t', z.
|
|
11
|
+
authType: zod.alias('t', z.nativeEnum(AuthType).optional()),
|
|
13
12
|
cloud: z.nativeEnum(CloudType).optional().default(CloudType.Public),
|
|
14
13
|
userName: zod.alias('u', z.string().optional()),
|
|
15
14
|
password: zod.alias('p', z.string().optional()),
|
|
@@ -37,20 +36,34 @@ class LoginCommand extends Command {
|
|
|
37
36
|
}
|
|
38
37
|
getRefinedSchema(schema) {
|
|
39
38
|
return schema
|
|
39
|
+
.refine(options => typeof options.appId !== 'undefined' || cli.getConfig().get(settingsNames.clientId), {
|
|
40
|
+
message: `appId is required. TIP: use the "m365 setup" command to configure the default appId`
|
|
41
|
+
})
|
|
40
42
|
.refine(options => options.authType !== 'password' || options.userName, {
|
|
41
|
-
message: 'Username is required when using password authentication'
|
|
43
|
+
message: 'Username is required when using password authentication',
|
|
44
|
+
path: ['userName']
|
|
42
45
|
})
|
|
43
46
|
.refine(options => options.authType !== 'password' || options.password, {
|
|
44
|
-
message: 'Password is required when using password authentication'
|
|
47
|
+
message: 'Password is required when using password authentication',
|
|
48
|
+
path: ['password']
|
|
45
49
|
})
|
|
46
50
|
.refine(options => options.authType !== 'certificate' || !(options.certificateFile && options.certificateBase64Encoded), {
|
|
47
|
-
message: 'Specify either certificateFile or certificateBase64Encoded, but not both.'
|
|
51
|
+
message: 'Specify either certificateFile or certificateBase64Encoded, but not both.',
|
|
52
|
+
path: ['certificateBase64Encoded']
|
|
48
53
|
})
|
|
49
|
-
.refine(options => options.authType !== 'certificate' ||
|
|
50
|
-
|
|
54
|
+
.refine(options => options.authType !== 'certificate' ||
|
|
55
|
+
options.certificateFile ||
|
|
56
|
+
options.certificateBase64Encoded ||
|
|
57
|
+
cli.getConfig().get(settingsNames.clientCertificateFile) ||
|
|
58
|
+
cli.getConfig().get(settingsNames.clientCertificateBase64Encoded), {
|
|
59
|
+
message: 'Specify either certificateFile or certificateBase64Encoded',
|
|
60
|
+
path: ['certificateFile']
|
|
51
61
|
})
|
|
52
|
-
.refine(options => options.authType !== 'secret' ||
|
|
53
|
-
|
|
62
|
+
.refine(options => options.authType !== 'secret' ||
|
|
63
|
+
options.secret ||
|
|
64
|
+
cli.getConfig().get(settingsNames.clientSecret), {
|
|
65
|
+
message: 'Secret is required when using secret authentication',
|
|
66
|
+
path: ['secret']
|
|
54
67
|
});
|
|
55
68
|
}
|
|
56
69
|
async commandAction(logger, args) {
|
|
@@ -59,13 +72,24 @@ class LoginCommand extends Command {
|
|
|
59
72
|
await logger.logToStderr(`Logging out from Microsoft 365...`);
|
|
60
73
|
}
|
|
61
74
|
const deactivate = () => auth.connection.deactivate();
|
|
75
|
+
const getCertificate = (options) => {
|
|
76
|
+
// command args take precedence over settings
|
|
77
|
+
if (options.certificateFile) {
|
|
78
|
+
return fs.readFileSync(options.certificateFile).toString('base64');
|
|
79
|
+
}
|
|
80
|
+
if (options.certificateBase64Encoded) {
|
|
81
|
+
return options.certificateBase64Encoded;
|
|
82
|
+
}
|
|
83
|
+
return cli.getConfig().get(settingsNames.clientCertificateFile) ||
|
|
84
|
+
cli.getConfig().get(settingsNames.clientCertificateBase64Encoded);
|
|
85
|
+
};
|
|
62
86
|
const login = async () => {
|
|
63
87
|
if (this.verbose) {
|
|
64
88
|
await logger.logToStderr(`Signing in to Microsoft 365...`);
|
|
65
89
|
}
|
|
66
90
|
const authType = args.options.authType || cli.getSettingWithDefaultValue(settingsNames.authType, 'deviceCode');
|
|
67
|
-
auth.connection.appId = args.options.appId ||
|
|
68
|
-
auth.connection.tenant = args.options.tenant ||
|
|
91
|
+
auth.connection.appId = args.options.appId || cli.getClientId();
|
|
92
|
+
auth.connection.tenant = args.options.tenant || cli.getTenant();
|
|
69
93
|
auth.connection.name = args.options.connectionName;
|
|
70
94
|
switch (authType) {
|
|
71
95
|
case 'password':
|
|
@@ -75,9 +99,9 @@ class LoginCommand extends Command {
|
|
|
75
99
|
break;
|
|
76
100
|
case 'certificate':
|
|
77
101
|
auth.connection.authType = AuthType.Certificate;
|
|
78
|
-
auth.connection.certificate =
|
|
102
|
+
auth.connection.certificate = getCertificate(args.options);
|
|
79
103
|
auth.connection.thumbprint = args.options.thumbprint;
|
|
80
|
-
auth.connection.password = args.options.password;
|
|
104
|
+
auth.connection.password = args.options.password || cli.getConfig().get(settingsNames.clientCertificatePassword);
|
|
81
105
|
break;
|
|
82
106
|
case 'identity':
|
|
83
107
|
auth.connection.authType = AuthType.Identity;
|
|
@@ -88,7 +112,7 @@ class LoginCommand extends Command {
|
|
|
88
112
|
break;
|
|
89
113
|
case 'secret':
|
|
90
114
|
auth.connection.authType = AuthType.Secret;
|
|
91
|
-
auth.connection.secret = args.options.secret;
|
|
115
|
+
auth.connection.secret = args.options.secret || cli.getConfig().get(settingsNames.clientSecret);
|
|
92
116
|
break;
|
|
93
117
|
}
|
|
94
118
|
auth.connection.cloudType = args.options.cloud;
|