@pnp/cli-microsoft365 7.5.0-beta.d4d820f → 7.6.0-beta.443bfd8
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/.devcontainer/Dockerfile +2 -2
- package/.eslintrc.cjs +9 -2
- package/.mocharc.json +3 -5
- package/Dockerfile +2 -5
- package/README.md +2 -2
- package/allCommands.json +1 -1
- package/allCommandsFull.json +1 -1
- package/dist/Auth.js +181 -77
- package/dist/AuthServer.js +3 -3
- package/dist/Command.js +8 -5
- package/dist/auth/FileTokenStorage.js +4 -1
- package/dist/cli/cli.js +1 -1
- package/dist/m365/base/AppCommand.js +2 -2
- package/dist/m365/base/PowerAppsCommand.js +2 -2
- package/dist/m365/base/PowerAutomateCommand.js +2 -2
- package/dist/m365/base/PowerPlatformCommand.js +2 -2
- package/dist/m365/base/SpoCommand.js +3 -3
- package/dist/m365/base/{YammerCommand.js → VivaEngageCommand.js} +2 -2
- package/dist/m365/cli/commands/cli-consent.js +5 -3
- package/dist/m365/cli/commands/cli-doctor.js +5 -5
- package/dist/m365/commands/ConnectionDetails.js +2 -0
- package/dist/m365/commands/login.js +26 -48
- package/dist/m365/commands/logout.js +2 -2
- package/dist/m365/commands/request.js +2 -2
- package/dist/m365/commands/status.js +15 -23
- package/dist/m365/connection/commands/connection-list.js +47 -0
- package/dist/m365/connection/commands/connection-remove.js +67 -0
- package/dist/m365/connection/commands/connection-set.js +56 -0
- package/dist/m365/connection/commands/connection-use.js +51 -0
- package/dist/m365/connection/commands.js +8 -0
- package/dist/m365/entra/aadCommands.js +3 -0
- package/dist/m365/entra/commands/administrativeunit/administrativeunit-member-remove.js +153 -0
- package/dist/m365/entra/commands/app/app-add.js +2 -2
- package/dist/m365/entra/commands/app/app-get.js +1 -1
- package/dist/m365/entra/commands/app/app-list.js +1 -1
- package/dist/m365/entra/commands/app/app-permission-add.js +1 -1
- package/dist/m365/entra/commands/app/app-permission-list.js +182 -0
- package/dist/m365/entra/commands/app/app-remove.js +1 -1
- package/dist/m365/entra/commands/app/app-role-add.js +1 -1
- package/dist/m365/entra/commands/app/app-role-list.js +1 -1
- package/dist/m365/entra/commands/app/app-role-remove.js +1 -1
- package/dist/m365/entra/commands/app/app-set.js +1 -1
- package/dist/m365/entra/commands/{sp/sp-add.js → enterpriseapp/enterpriseapp-add.js} +18 -18
- package/dist/m365/entra/commands/{sp/sp-get.js → enterpriseapp/enterpriseapp-get.js} +19 -19
- package/dist/m365/entra/commands/{sp/sp-list.js → enterpriseapp/enterpriseapp-list.js} +13 -13
- package/dist/m365/entra/commands/group/group-add.js +224 -0
- package/dist/m365/entra/commands/group/group-user-add.js +145 -0
- package/dist/m365/entra/commands/m365group/m365group-report-activitygroupcounts.js +1 -1
- package/dist/m365/entra/commands/user/user-get.js +38 -38
- package/dist/m365/entra/commands/user/user-license-list.js +1 -1
- package/dist/m365/entra/commands/user/user-registrationdetails-list.js +224 -0
- package/dist/m365/entra/commands/user/user-set.js +2 -2
- package/dist/m365/entra/commands.js +17 -0
- package/dist/m365/external/commands/connection/connection-doctor.js +2 -1
- package/dist/m365/file/commands/convert/convert-pdf.js +1 -1
- package/dist/m365/file/commands/file-copy.js +151 -0
- package/dist/m365/file/commands.js +1 -0
- package/dist/m365/outlook/commands/mail/mail-send.js +1 -1
- package/dist/m365/outlook/commands/message/message-get.js +1 -1
- package/dist/m365/pa/commands/app/app-permission-ensure.js +1 -1
- package/dist/m365/pa/commands/app/app-permission-remove.js +1 -1
- package/dist/m365/planner/commands/roster/roster-plan-list.js +1 -1
- package/dist/m365/purview/commands/auditlog/auditlog-list.js +1 -1
- package/dist/m365/purview/commands/sensitivitylabel/sensitivitylabel-get.js +1 -1
- package/dist/m365/purview/commands/sensitivitylabel/sensitivitylabel-list.js +1 -1
- package/dist/m365/purview/commands/sensitivitylabel/sensitivitylabel-policysettings-list.js +1 -1
- package/dist/m365/purview/commands/threatassessment/threatassessment-add.js +123 -0
- package/dist/m365/purview/commands/threatassessment/threatassessment-list.js +104 -0
- package/dist/m365/purview/commands.js +3 -1
- package/dist/m365/spfx/commands/project/DeployWorkflow.js +115 -3
- package/dist/m365/spfx/commands/project/project-azuredevops-pipeline-add.js +183 -0
- package/dist/m365/spfx/commands/project/project-azuredevops-pipeline-model.js +2 -0
- package/dist/m365/spfx/commands/project/project-github-workflow-add.js +3 -4
- package/dist/m365/spfx/commands.js +1 -0
- package/dist/m365/spo/commands/spo-get.js +1 -1
- package/dist/m365/spo/commands/spo-search.js +52 -22
- package/dist/m365/spo/commands/spo-set.js +1 -1
- package/dist/m365/spo/commands/user/user-remove.js +93 -16
- package/dist/m365/teams/commands/chat/chat-get.js +1 -1
- package/dist/m365/teams/commands/chat/chat-list.js +1 -1
- package/dist/m365/teams/commands/chat/chat-message-send.js +1 -1
- package/dist/m365/teams/commands/meeting/meeting-add.js +1 -1
- package/dist/m365/teams/commands/meeting/meeting-attendancereport-list.js +1 -1
- package/dist/m365/teams/commands/meeting/meeting-get.js +1 -1
- package/dist/m365/teams/commands/meeting/meeting-list.js +2 -2
- package/dist/m365/teams/commands/meeting/meeting-transcript-list.js +1 -1
- package/dist/m365/tenant/commands/id/id-get.js +1 -1
- package/dist/m365/tenant/commands/info/info-get.js +1 -1
- package/dist/m365/util/commands/accesstoken/accesstoken-get.js +3 -3
- package/dist/m365/{yammer/commands/group/group-list.js → viva/commands/engage/engage-group-list.js} +19 -14
- package/dist/m365/{yammer/commands/group/group-user-add.js → viva/commands/engage/engage-group-user-add.js} +19 -14
- package/dist/m365/{yammer/commands/group/group-user-remove.js → viva/commands/engage/engage-group-user-remove.js} +19 -14
- package/dist/m365/{yammer/commands/message/message-add.js → viva/commands/engage/engage-message-add.js} +19 -14
- package/dist/m365/{yammer/commands/message/message-get.js → viva/commands/engage/engage-message-get.js} +17 -12
- package/dist/m365/{yammer/commands/message/message-like-set.js → viva/commands/engage/engage-message-like-set.js} +21 -16
- package/dist/m365/{yammer/commands/message/message-list.js → viva/commands/engage/engage-message-list.js} +21 -16
- package/dist/m365/{yammer/commands/message/message-remove.js → viva/commands/engage/engage-message-remove.js} +20 -15
- package/dist/m365/{yammer/commands/network/network-list.js → viva/commands/engage/engage-network-list.js} +16 -11
- package/dist/m365/viva/commands/engage/engage-report-activitycounts.js +23 -0
- package/dist/m365/viva/commands/engage/engage-report-activityusercounts.js +23 -0
- package/dist/m365/viva/commands/engage/engage-report-activityuserdetail.js +23 -0
- package/dist/m365/viva/commands/engage/engage-report-deviceusagedistributionusercounts.js +23 -0
- package/dist/m365/viva/commands/engage/engage-report-deviceusageusercounts.js +23 -0
- package/dist/m365/viva/commands/engage/engage-report-deviceusageuserdetail.js +23 -0
- package/dist/m365/viva/commands/engage/engage-report-groupsactivitycounts.js +23 -0
- package/dist/m365/viva/commands/engage/engage-report-groupsactivitydetail.js +23 -0
- package/dist/m365/viva/commands/engage/engage-report-groupsactivitygroupcounts.js +23 -0
- package/dist/m365/{yammer/commands/yammer-search.js → viva/commands/engage/engage-search.js} +23 -18
- package/dist/m365/{yammer/commands/user/user-get.js → viva/commands/engage/engage-user-get.js} +18 -13
- package/dist/m365/{yammer/commands/user/user-list.js → viva/commands/engage/engage-user-list.js} +18 -13
- package/dist/m365/{yammer/commands.js → viva/commands/engage/yammerCommands.js} +1 -1
- package/dist/m365/viva/commands.js +22 -1
- package/dist/request.js +1 -1
- package/dist/utils/entraUser.js +36 -0
- package/dist/utils/spo.js +36 -14
- package/dist/utils/urlUtil.js +31 -0
- package/dist/utils/validation.js +8 -0
- package/docs/docs/cmd/cli/cli-consent.mdx +9 -9
- package/docs/docs/cmd/connection/connection-list.mdx +100 -0
- package/docs/docs/cmd/connection/connection-remove.mdx +45 -0
- package/docs/docs/cmd/connection/connection-set.mdx +39 -0
- package/docs/docs/cmd/connection/connection-use.mdx +98 -0
- package/docs/docs/cmd/entra/administrativeunit/administrativeunit-member-add.mdx +5 -3
- package/docs/docs/cmd/entra/administrativeunit/administrativeunit-member-remove.mdx +107 -0
- package/docs/docs/cmd/entra/app/app-add.mdx +2 -1
- package/docs/docs/cmd/entra/app/app-get.mdx +1 -0
- package/docs/docs/cmd/entra/app/app-list.mdx +1 -0
- package/docs/docs/cmd/entra/app/app-permission-add.mdx +1 -0
- package/docs/docs/cmd/entra/app/app-permission-list.mdx +105 -0
- package/docs/docs/cmd/entra/app/app-remove.mdx +1 -0
- package/docs/docs/cmd/entra/app/app-role-add.mdx +1 -0
- package/docs/docs/cmd/entra/app/app-role-list.mdx +1 -0
- package/docs/docs/cmd/entra/app/app-role-remove.mdx +1 -0
- package/docs/docs/cmd/entra/app/app-set.mdx +1 -0
- package/docs/docs/cmd/entra/{sp/sp-add.mdx → enterpriseapp/enterpriseapp-add.mdx} +16 -15
- package/docs/docs/cmd/entra/{sp/sp-get.mdx → enterpriseapp/enterpriseapp-get.mdx} +15 -14
- package/docs/docs/cmd/entra/{sp/sp-list.mdx → enterpriseapp/enterpriseapp-list.mdx} +22 -21
- package/docs/docs/cmd/entra/group/group-add.mdx +231 -0
- package/docs/docs/cmd/entra/group/group-user-add.mdx +62 -0
- package/docs/docs/cmd/entra/m365group/m365group-report-activitygroupcounts.mdx +1 -1
- package/docs/docs/cmd/entra/oauth2grant/oauth2grant-add.mdx +3 -3
- package/docs/docs/cmd/entra/oauth2grant/oauth2grant-list.mdx +1 -1
- package/docs/docs/cmd/entra/user/user-registrationdetails-list.mdx +246 -0
- package/docs/docs/cmd/external/item/item-add.mdx +1 -1
- package/docs/docs/cmd/file/convert/convert-pdf.mdx +4 -0
- package/docs/docs/cmd/file/file-add.mdx +4 -0
- package/docs/docs/cmd/file/file-copy.mdx +68 -0
- package/docs/docs/cmd/file/file-list.mdx +100 -0
- package/docs/docs/cmd/login.mdx +15 -0
- package/docs/docs/cmd/purview/threatassessment/threatassessment-add.mdx +131 -0
- package/docs/docs/cmd/purview/threatassessment/threatassessment-list.mdx +110 -0
- package/docs/docs/cmd/setup.mdx +4 -0
- package/docs/docs/cmd/spfx/project/project-azuredevops-pipeline-add.mdx +87 -0
- package/docs/docs/cmd/spo/list/list-webhook-set.mdx +1 -1
- package/docs/docs/cmd/spo/spo-search.mdx +6 -2
- package/docs/docs/cmd/spo/theme/theme-set.mdx +14 -2
- package/docs/docs/cmd/spo/user/user-remove.mdx +40 -9
- package/docs/docs/cmd/{yammer/group/group-list.mdx → viva/engage/engage-group-list.mdx} +13 -13
- package/docs/docs/cmd/{yammer/group/group-user-add.mdx → viva/engage/engage-group-user-add.mdx} +7 -7
- package/docs/docs/cmd/{yammer/group/group-user-remove.mdx → viva/engage/engage-group-user-remove.mdx} +10 -10
- package/docs/docs/cmd/{yammer/message/message-add.mdx → viva/engage/engage-message-add.mdx} +12 -13
- package/docs/docs/cmd/{yammer/message/message-get.mdx → viva/engage/engage-message-get.mdx} +10 -10
- package/docs/docs/cmd/{yammer/message/message-like-set.mdx → viva/engage/engage-message-like-set.mdx} +10 -10
- package/docs/docs/cmd/{yammer/message/message-list.mdx → viva/engage/engage-message-list.mdx} +21 -21
- package/docs/docs/cmd/{yammer/message/message-remove.mdx → viva/engage/engage-message-remove.mdx} +10 -10
- package/docs/docs/cmd/{yammer/network/network-list.mdx → viva/engage/engage-network-list.mdx} +6 -6
- package/docs/docs/cmd/{yammer/report/report-activitycounts.mdx → viva/engage/engage-report-activitycounts.mdx} +9 -9
- package/docs/docs/cmd/{yammer/report/report-activityusercounts.mdx → viva/engage/engage-report-activityusercounts.mdx} +9 -9
- package/docs/docs/cmd/{yammer/report/report-activityuserdetail.mdx → viva/engage/engage-report-activityuserdetail.mdx} +11 -12
- package/docs/docs/cmd/{yammer/report/report-deviceusagedistributionusercounts.mdx → viva/engage/engage-report-deviceusagedistributionusercounts.mdx} +5 -5
- package/docs/docs/cmd/{yammer/report/report-deviceusageusercounts.mdx → viva/engage/engage-report-deviceusageusercounts.mdx} +5 -5
- package/docs/docs/cmd/{yammer/report/report-deviceusageuserdetail.mdx → viva/engage/engage-report-deviceusageuserdetail.mdx} +11 -11
- package/docs/docs/cmd/{yammer/report/report-groupsactivitycounts.mdx → viva/engage/engage-report-groupsactivitycounts.mdx} +9 -9
- package/docs/docs/cmd/{yammer/report/report-groupsactivitydetail.mdx → viva/engage/engage-report-groupsactivitydetail.mdx} +11 -11
- package/docs/docs/cmd/{yammer/report/report-groupsactivitygroupcounts.mdx → viva/engage/engage-report-groupsactivitygroupcounts.mdx} +5 -5
- package/docs/docs/cmd/{yammer/yammer-search.mdx → viva/engage/engage-search.mdx} +10 -10
- package/docs/docs/cmd/{yammer/user/user-get.mdx → viva/engage/engage-user-get.mdx} +8 -8
- package/docs/docs/cmd/{yammer/user/user-list.mdx → viva/engage/engage-user-list.mdx} +11 -11
- package/npm-shrinkwrap.json +230 -168
- package/package.json +20 -19
- package/dist/m365/base/AzmgmtCommand.js +0 -18
- package/dist/m365/base/AzmgmtItemsListCommand.js +0 -41
- package/dist/m365/yammer/commands/report/report-activitycounts.js +0 -15
- package/dist/m365/yammer/commands/report/report-activityusercounts.js +0 -15
- package/dist/m365/yammer/commands/report/report-activityuserdetail.js +0 -15
- package/dist/m365/yammer/commands/report/report-deviceusagedistributionusercounts.js +0 -15
- package/dist/m365/yammer/commands/report/report-deviceusageusercounts.js +0 -15
- package/dist/m365/yammer/commands/report/report-deviceusageuserdetail.js +0 -15
- package/dist/m365/yammer/commands/report/report-groupsactivitycounts.js +0 -15
- package/dist/m365/yammer/commands/report/report-groupsactivitydetail.js +0 -15
- package/dist/m365/yammer/commands/report/report-groupsactivitygroupcounts.js +0 -15
package/dist/Auth.js
CHANGED
|
@@ -7,6 +7,8 @@ import config from './config.js';
|
|
|
7
7
|
import request from './request.js';
|
|
8
8
|
import { settingsNames } from './settingsNames.js';
|
|
9
9
|
import { browserUtil } from './utils/browserUtil.js';
|
|
10
|
+
import * as accessTokenUtil from './utils/accessToken.js';
|
|
11
|
+
import assert from 'assert';
|
|
10
12
|
export var CloudType;
|
|
11
13
|
(function (CloudType) {
|
|
12
14
|
CloudType[CloudType["Public"] = 0] = "Public";
|
|
@@ -15,9 +17,9 @@ export var CloudType;
|
|
|
15
17
|
CloudType[CloudType["USGovDoD"] = 3] = "USGovDoD";
|
|
16
18
|
CloudType[CloudType["China"] = 4] = "China";
|
|
17
19
|
})(CloudType || (CloudType = {}));
|
|
18
|
-
export class
|
|
20
|
+
export class Connection {
|
|
19
21
|
constructor() {
|
|
20
|
-
this.
|
|
22
|
+
this.active = false;
|
|
21
23
|
this.authType = AuthType.DeviceCode;
|
|
22
24
|
this.certificateType = CertificateType.Unknown;
|
|
23
25
|
this.cloudType = CloudType.Public;
|
|
@@ -26,17 +28,22 @@ export class Service {
|
|
|
26
28
|
this.tenant = config.tenant;
|
|
27
29
|
this.cloudType = CloudType.Public;
|
|
28
30
|
}
|
|
29
|
-
|
|
30
|
-
this.
|
|
31
|
+
deactivate() {
|
|
32
|
+
this.active = false;
|
|
33
|
+
this.name = undefined;
|
|
34
|
+
this.identityName = undefined;
|
|
35
|
+
this.identityId = undefined;
|
|
36
|
+
this.identityTenantId = undefined;
|
|
31
37
|
this.accessTokens = {};
|
|
32
38
|
this.authType = AuthType.DeviceCode;
|
|
33
39
|
this.userName = undefined;
|
|
34
40
|
this.password = undefined;
|
|
35
41
|
this.certificateType = CertificateType.Unknown;
|
|
42
|
+
this.cloudType = CloudType.Public;
|
|
36
43
|
this.certificate = undefined;
|
|
37
44
|
this.thumbprint = undefined;
|
|
38
45
|
this.spoUrl = undefined;
|
|
39
|
-
this.
|
|
46
|
+
this.spoTenantId = undefined;
|
|
40
47
|
this.appId = config.cliAadAppId;
|
|
41
48
|
this.tenant = config.tenant;
|
|
42
49
|
}
|
|
@@ -57,14 +64,26 @@ export var CertificateType;
|
|
|
57
64
|
CertificateType[CertificateType["Binary"] = 2] = "Binary";
|
|
58
65
|
})(CertificateType || (CertificateType = {}));
|
|
59
66
|
export class Auth {
|
|
60
|
-
|
|
61
|
-
|
|
67
|
+
// Retrieves the connections from the file store if it's not already loaded
|
|
68
|
+
async getAllConnections() {
|
|
69
|
+
if (this._allConnections === undefined) {
|
|
70
|
+
try {
|
|
71
|
+
this._allConnections = await this.getAllConnectionsFromStorage();
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
this._allConnections = [];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return this._allConnections;
|
|
78
|
+
}
|
|
79
|
+
get connection() {
|
|
80
|
+
return this._connection;
|
|
62
81
|
}
|
|
63
82
|
get defaultResource() {
|
|
64
|
-
return Auth.getEndpointForResource('https://graph.microsoft.com', this.
|
|
83
|
+
return Auth.getEndpointForResource('https://graph.microsoft.com', this._connection.cloudType);
|
|
65
84
|
}
|
|
66
85
|
constructor() {
|
|
67
|
-
this.
|
|
86
|
+
this._connection = new Connection();
|
|
68
87
|
}
|
|
69
88
|
// we need to init cloud endpoints here, because we're using CloudType enum
|
|
70
89
|
// as indexers, which we can't do in the static initializer
|
|
@@ -98,19 +117,19 @@ export class Auth {
|
|
|
98
117
|
}
|
|
99
118
|
async restoreAuth() {
|
|
100
119
|
// check if auth has been restored previously
|
|
101
|
-
if (this.
|
|
120
|
+
if (this._connection.active) {
|
|
102
121
|
return Promise.resolve();
|
|
103
122
|
}
|
|
104
123
|
try {
|
|
105
|
-
const
|
|
106
|
-
this.
|
|
124
|
+
const connection = await this.getConnectionInfoFromStorage();
|
|
125
|
+
this._connection = Object.assign(this._connection, connection);
|
|
107
126
|
}
|
|
108
127
|
catch {
|
|
109
128
|
}
|
|
110
129
|
}
|
|
111
130
|
async ensureAccessToken(resource, logger, debug = false, fetchNew = false) {
|
|
112
131
|
const now = new Date();
|
|
113
|
-
const accessToken = this.
|
|
132
|
+
const accessToken = this.connection.accessTokens[resource];
|
|
114
133
|
const expiresOn = accessToken && accessToken.expiresOn ?
|
|
115
134
|
// if expiresOn is serialized from the service file, it's set as a string
|
|
116
135
|
// if it's coming from MSAL, it's a Date
|
|
@@ -125,7 +144,7 @@ export class Auth {
|
|
|
125
144
|
else {
|
|
126
145
|
if (debug) {
|
|
127
146
|
if (!accessToken) {
|
|
128
|
-
await logger.logToStderr(`No token found for resource ${resource}
|
|
147
|
+
await logger.logToStderr(`No token found for resource ${resource}.`);
|
|
129
148
|
}
|
|
130
149
|
else {
|
|
131
150
|
await logger.logToStderr(`Access token expired. Token: ${accessToken.accessToken}, ExpiresAt: ${accessToken.expiresOn}`);
|
|
@@ -133,21 +152,24 @@ export class Auth {
|
|
|
133
152
|
}
|
|
134
153
|
}
|
|
135
154
|
let getTokenPromise;
|
|
136
|
-
//
|
|
137
|
-
// no account. Also cert auth
|
|
155
|
+
// When using an application identity, you can't retrieve the access token silently, because there is
|
|
156
|
+
// no account. Also (for cert auth) clientApplication is instantiated later
|
|
138
157
|
// after inspecting the specified cert and calculating thumbprint if one
|
|
139
158
|
// wasn't specified
|
|
140
|
-
if (this.
|
|
141
|
-
this.
|
|
159
|
+
if (this.connection.authType !== AuthType.Certificate &&
|
|
160
|
+
this.connection.authType !== AuthType.Secret &&
|
|
161
|
+
this.connection.authType !== AuthType.Identity) {
|
|
162
|
+
this.clientApplication = await this.getPublicClient(logger, debug);
|
|
142
163
|
if (this.clientApplication) {
|
|
143
164
|
const accounts = await this.clientApplication.getTokenCache().getAllAccounts();
|
|
144
|
-
if
|
|
165
|
+
// if there is an account in the cache and it's active, we can try to get the token silently
|
|
166
|
+
if (accounts.filter(a => a.localAccountId === this.connection.identityId).length > 0 && this.connection.active === true) {
|
|
145
167
|
getTokenPromise = this.ensureAccessTokenSilent.bind(this);
|
|
146
168
|
}
|
|
147
169
|
}
|
|
148
170
|
}
|
|
149
171
|
if (!getTokenPromise) {
|
|
150
|
-
switch (this.
|
|
172
|
+
switch (this.connection.authType) {
|
|
151
173
|
case AuthType.DeviceCode:
|
|
152
174
|
getTokenPromise = this.ensureAccessTokenWithDeviceCode.bind(this);
|
|
153
175
|
break;
|
|
@@ -171,9 +193,9 @@ export class Auth {
|
|
|
171
193
|
const response = await getTokenPromise(resource, logger, debug, fetchNew);
|
|
172
194
|
if (!response) {
|
|
173
195
|
if (debug) {
|
|
174
|
-
await logger.logToStderr(
|
|
196
|
+
await logger.logToStderr('getTokenPromise authentication result is null.');
|
|
175
197
|
}
|
|
176
|
-
throw
|
|
198
|
+
throw 'Failed to retrieve an access token. Please try again.';
|
|
177
199
|
}
|
|
178
200
|
else {
|
|
179
201
|
if (debug) {
|
|
@@ -182,11 +204,15 @@ export class Auth {
|
|
|
182
204
|
await logger.logToStderr('');
|
|
183
205
|
}
|
|
184
206
|
}
|
|
185
|
-
this.
|
|
207
|
+
this.connection.accessTokens[resource] = {
|
|
186
208
|
expiresOn: response.expiresOn,
|
|
187
209
|
accessToken: response.accessToken
|
|
188
210
|
};
|
|
189
|
-
this.
|
|
211
|
+
this.connection.active = true;
|
|
212
|
+
this.connection.identityName = accessTokenUtil.accessToken.getUserNameFromAccessToken(response.accessToken);
|
|
213
|
+
this.connection.identityId = accessTokenUtil.accessToken.getUserIdFromAccessToken(response.accessToken);
|
|
214
|
+
this.connection.identityTenantId = accessTokenUtil.accessToken.getTenantIdFromAccessToken(response.accessToken);
|
|
215
|
+
this.connection.name = this.connection.name || this.connection.identityId;
|
|
190
216
|
try {
|
|
191
217
|
await this.storeConnectionInfo();
|
|
192
218
|
}
|
|
@@ -199,21 +225,6 @@ export class Auth {
|
|
|
199
225
|
}
|
|
200
226
|
return response.accessToken;
|
|
201
227
|
}
|
|
202
|
-
async getClientApplication(logger, debug) {
|
|
203
|
-
switch (this.service.authType) {
|
|
204
|
-
case AuthType.DeviceCode:
|
|
205
|
-
case AuthType.Password:
|
|
206
|
-
case AuthType.Browser:
|
|
207
|
-
return await this.getPublicClient(logger, debug);
|
|
208
|
-
case AuthType.Certificate:
|
|
209
|
-
return await this.getConfidentialClient(logger, debug, this.service.thumbprint, this.service.password, undefined);
|
|
210
|
-
case AuthType.Identity:
|
|
211
|
-
// msal-node doesn't support managed identity so we need to do it manually
|
|
212
|
-
return undefined;
|
|
213
|
-
case AuthType.Secret:
|
|
214
|
-
return await this.getConfidentialClient(logger, debug, undefined, undefined, this.service.secret);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
228
|
async getAuthClientConfiguration(logger, debug, certificateThumbprint, certificatePrivateKey, clientSecret) {
|
|
218
229
|
const msal = await import('@azure/msal-node');
|
|
219
230
|
const { LogLevel } = msal;
|
|
@@ -222,7 +233,7 @@ export class Auth {
|
|
|
222
233
|
privateKey: certificatePrivateKey
|
|
223
234
|
};
|
|
224
235
|
let azureCloudInstance = AzureCloudInstance.None;
|
|
225
|
-
switch (this.
|
|
236
|
+
switch (this.connection.cloudType) {
|
|
226
237
|
case CloudType.Public:
|
|
227
238
|
azureCloudInstance = AzureCloudInstance.AzurePublic;
|
|
228
239
|
break;
|
|
@@ -236,11 +247,11 @@ export class Auth {
|
|
|
236
247
|
break;
|
|
237
248
|
}
|
|
238
249
|
const config = {
|
|
239
|
-
clientId: this.
|
|
240
|
-
authority: `${Auth.getEndpointForResource('https://login.microsoftonline.com', this.
|
|
250
|
+
clientId: this.connection.appId,
|
|
251
|
+
authority: `${Auth.getEndpointForResource('https://login.microsoftonline.com', this.connection.cloudType)}/${this.connection.tenant}`,
|
|
241
252
|
azureCloudOptions: {
|
|
242
253
|
azureCloudInstance,
|
|
243
|
-
tenant: this.
|
|
254
|
+
tenant: this.connection.tenant
|
|
244
255
|
}
|
|
245
256
|
};
|
|
246
257
|
const authConfig = cert
|
|
@@ -270,11 +281,11 @@ export class Auth {
|
|
|
270
281
|
async getPublicClient(logger, debug) {
|
|
271
282
|
const msal = await import('@azure/msal-node');
|
|
272
283
|
const { PublicClientApplication } = msal;
|
|
273
|
-
if (this.
|
|
274
|
-
this.
|
|
284
|
+
if (this.connection.authType === AuthType.Password &&
|
|
285
|
+
this.connection.tenant === 'common') {
|
|
275
286
|
// common is not supported for the password flow and must be changed to
|
|
276
287
|
// organizations
|
|
277
|
-
this.
|
|
288
|
+
this.connection.tenant = 'organizations';
|
|
278
289
|
}
|
|
279
290
|
return new PublicClientApplication(await this.getAuthClientConfiguration(logger, debug));
|
|
280
291
|
}
|
|
@@ -292,7 +303,7 @@ export class Auth {
|
|
|
292
303
|
if (!this._authServer) {
|
|
293
304
|
this._authServer = (await import('./AuthServer.js')).default;
|
|
294
305
|
}
|
|
295
|
-
this._authServer.initializeServer(this.
|
|
306
|
+
this._authServer.initializeServer(this.connection, resource, resolve, reject, logger, debug);
|
|
296
307
|
});
|
|
297
308
|
}
|
|
298
309
|
async ensureAccessTokenWithBrowser(resource, logger, debug) {
|
|
@@ -313,10 +324,14 @@ export class Auth {
|
|
|
313
324
|
if (debug) {
|
|
314
325
|
await logger.logToStderr(`Retrieving new access token silently`);
|
|
315
326
|
}
|
|
316
|
-
|
|
317
|
-
|
|
327
|
+
// Asserting identityId because it is expected to be available at this point.
|
|
328
|
+
assert(this.connection.identityId !== undefined);
|
|
329
|
+
const account = await this.clientApplication
|
|
330
|
+
.getTokenCache().getAccountByLocalId(this.connection.identityId);
|
|
331
|
+
// Asserting account because it is expected to be available at this point.
|
|
332
|
+
assert(account !== null);
|
|
318
333
|
return this.clientApplication.acquireTokenSilent({
|
|
319
|
-
account:
|
|
334
|
+
account: account,
|
|
320
335
|
scopes: [`${resource}/.default`],
|
|
321
336
|
forceRefresh: fetchNew
|
|
322
337
|
});
|
|
@@ -367,40 +382,40 @@ export class Auth {
|
|
|
367
382
|
await logger.logToStderr(`Retrieving new access token using credentials...`);
|
|
368
383
|
}
|
|
369
384
|
return this.clientApplication.acquireTokenByUsernamePassword({
|
|
370
|
-
username: this.
|
|
371
|
-
password: this.
|
|
385
|
+
username: this.connection.userName,
|
|
386
|
+
password: this.connection.password,
|
|
372
387
|
scopes: [`${resource}/.default`]
|
|
373
388
|
});
|
|
374
389
|
}
|
|
375
|
-
async ensureAccessTokenWithCertificate(resource, logger, debug) {
|
|
390
|
+
async ensureAccessTokenWithCertificate(resource, logger, debug, fetchNew) {
|
|
376
391
|
const nodeForge = (await import('node-forge')).default;
|
|
377
392
|
const { pem, pki, asn1, pkcs12 } = nodeForge;
|
|
378
393
|
if (debug) {
|
|
379
394
|
await logger.logToStderr(`Retrieving new access token using certificate...`);
|
|
380
395
|
}
|
|
381
396
|
let cert = '';
|
|
382
|
-
const buf = Buffer.from(this.
|
|
383
|
-
if (this.
|
|
397
|
+
const buf = Buffer.from(this.connection.certificate, 'base64');
|
|
398
|
+
if (this.connection.certificateType === CertificateType.Unknown || this.connection.certificateType === CertificateType.Base64) {
|
|
384
399
|
// First time this method is called, we don't know if certificate is PEM or PFX (type is Unknown)
|
|
385
400
|
// We assume it is PEM but when parsing of PEM fails, we assume it could be PFX
|
|
386
401
|
// Type is persisted on service so subsequent calls only run through the correct parsing flow
|
|
387
402
|
try {
|
|
388
403
|
cert = buf.toString('utf8');
|
|
389
404
|
const pemObjs = pem.decode(cert);
|
|
390
|
-
if (this.
|
|
405
|
+
if (this.connection.thumbprint === undefined) {
|
|
391
406
|
const pemCertObj = pemObjs.find(pem => pem.type === "CERTIFICATE");
|
|
392
407
|
const pemCertStr = pem.encode(pemCertObj);
|
|
393
408
|
const pemCert = pki.certificateFromPem(pemCertStr);
|
|
394
|
-
this.
|
|
409
|
+
this.connection.thumbprint = await this.calculateThumbprint(pemCert);
|
|
395
410
|
}
|
|
396
411
|
}
|
|
397
412
|
catch (e) {
|
|
398
|
-
this.
|
|
413
|
+
this.connection.certificateType = CertificateType.Binary;
|
|
399
414
|
}
|
|
400
415
|
}
|
|
401
|
-
if (this.
|
|
416
|
+
if (this.connection.certificateType === CertificateType.Binary) {
|
|
402
417
|
const p12Asn1 = asn1.fromDer(buf.toString('binary'), false);
|
|
403
|
-
const p12Parsed = pkcs12.pkcs12FromAsn1(p12Asn1, false, this.
|
|
418
|
+
const p12Parsed = pkcs12.pkcs12FromAsn1(p12Asn1, false, this.connection.password);
|
|
404
419
|
let keyBags = p12Parsed.getBags({ bagType: pki.oids.pkcs8ShroudedKeyBag });
|
|
405
420
|
const pkcs8ShroudedKeyBag = keyBags[pki.oids.pkcs8ShroudedKeyBag][0];
|
|
406
421
|
if (debug) {
|
|
@@ -419,19 +434,20 @@ export class Auth {
|
|
|
419
434
|
const privateKeyInfo = pki.wrapRsaPrivateKey(rsaPrivateKey);
|
|
420
435
|
// convert a PKCS#8 ASN.1 PrivateKeyInfo to PEM
|
|
421
436
|
cert = pki.privateKeyInfoToPem(privateKeyInfo);
|
|
422
|
-
if (this.
|
|
437
|
+
if (this.connection.thumbprint === undefined) {
|
|
423
438
|
const certBags = p12Parsed.getBags({ bagType: pki.oids.certBag });
|
|
424
439
|
const certBag = (certBags[pki.oids.certBag])[0];
|
|
425
|
-
this.
|
|
440
|
+
this.connection.thumbprint = await this.calculateThumbprint(certBag.cert);
|
|
426
441
|
}
|
|
427
442
|
}
|
|
428
|
-
this.clientApplication = await this.getConfidentialClient(logger, debug, this.
|
|
443
|
+
this.clientApplication = await this.getConfidentialClient(logger, debug, this.connection.thumbprint, cert);
|
|
429
444
|
return this.clientApplication.acquireTokenByClientCredential({
|
|
430
|
-
scopes: [`${resource}/.default`]
|
|
445
|
+
scopes: [`${resource}/.default`],
|
|
446
|
+
skipCache: fetchNew
|
|
431
447
|
});
|
|
432
448
|
}
|
|
433
449
|
async ensureAccessTokenWithIdentity(resource, logger, debug) {
|
|
434
|
-
const userName = this.
|
|
450
|
+
const userName = this.connection.userName;
|
|
435
451
|
if (debug) {
|
|
436
452
|
await logger.logToStderr('Will try to retrieve access token using identity...');
|
|
437
453
|
}
|
|
@@ -547,10 +563,11 @@ export class Auth {
|
|
|
547
563
|
}
|
|
548
564
|
}
|
|
549
565
|
}
|
|
550
|
-
async ensureAccessTokenWithSecret(resource, logger, debug) {
|
|
551
|
-
this.clientApplication = await this.getConfidentialClient(logger, debug, undefined, undefined, this.
|
|
566
|
+
async ensureAccessTokenWithSecret(resource, logger, debug, fetchNew) {
|
|
567
|
+
this.clientApplication = await this.getConfidentialClient(logger, debug, undefined, undefined, this.connection.secret);
|
|
552
568
|
return this.clientApplication.acquireTokenByClientCredential({
|
|
553
|
-
scopes: [`${resource}/.default`]
|
|
569
|
+
scopes: [`${resource}/.default`],
|
|
570
|
+
skipCache: fetchNew
|
|
554
571
|
});
|
|
555
572
|
}
|
|
556
573
|
async calculateThumbprint(certificate) {
|
|
@@ -564,7 +581,7 @@ export class Auth {
|
|
|
564
581
|
let resource = url;
|
|
565
582
|
const pos = resource.indexOf('/', 8);
|
|
566
583
|
if (pos > -1) {
|
|
567
|
-
resource = resource.
|
|
584
|
+
resource = resource.substring(0, pos);
|
|
568
585
|
}
|
|
569
586
|
if (resource === 'https://api.bap.microsoft.com' ||
|
|
570
587
|
resource === 'https://api.powerapps.com' ||
|
|
@@ -581,29 +598,70 @@ export class Auth {
|
|
|
581
598
|
}
|
|
582
599
|
return resource;
|
|
583
600
|
}
|
|
584
|
-
async
|
|
585
|
-
const tokenStorage = this.
|
|
601
|
+
async getConnectionInfoFromStorage() {
|
|
602
|
+
const tokenStorage = this.getConnectionStorage();
|
|
586
603
|
const json = await tokenStorage.get();
|
|
587
604
|
return JSON.parse(json);
|
|
588
605
|
}
|
|
589
|
-
storeConnectionInfo() {
|
|
590
|
-
const
|
|
591
|
-
|
|
606
|
+
async storeConnectionInfo() {
|
|
607
|
+
const connectionStorage = this.getConnectionStorage();
|
|
608
|
+
await connectionStorage.set(JSON.stringify(this.connection));
|
|
609
|
+
let allConnections = await this.getAllConnections();
|
|
610
|
+
if (this.connection.active) {
|
|
611
|
+
allConnections = allConnections.filter(c => c.identityId !== this.connection.identityId);
|
|
612
|
+
allConnections.forEach(c => c.active = false);
|
|
613
|
+
allConnections = [{ ...this.connection }, ...allConnections];
|
|
614
|
+
}
|
|
615
|
+
this._allConnections = allConnections;
|
|
616
|
+
const allConnectionsStorage = this.getAllConnectionsStorage();
|
|
617
|
+
await allConnectionsStorage.set(JSON.stringify(allConnections));
|
|
592
618
|
}
|
|
593
619
|
async clearConnectionInfo() {
|
|
594
|
-
const
|
|
595
|
-
|
|
620
|
+
const connectionStorage = this.getConnectionStorage();
|
|
621
|
+
const allConnectionsStorage = this.getAllConnectionsStorage();
|
|
622
|
+
await connectionStorage.remove();
|
|
623
|
+
await allConnectionsStorage.remove();
|
|
596
624
|
// we need to manually clear MSAL cache, because MSAL doesn't have support
|
|
597
625
|
// for logging out when using cert-based auth
|
|
598
626
|
const msalCache = this.getMsalCacheStorage();
|
|
599
627
|
await msalCache.remove();
|
|
600
628
|
}
|
|
601
|
-
|
|
629
|
+
async removeConnectionInfo(connection, logger, debug) {
|
|
630
|
+
const allConnections = await this.getAllConnections();
|
|
631
|
+
const isCurrentConnection = this.connection.name === connection.name;
|
|
632
|
+
this._allConnections = allConnections.filter(c => c.name !== connection.name);
|
|
633
|
+
// Asserting identityId because it is optional, but required at this point.
|
|
634
|
+
assert(connection.identityId !== undefined);
|
|
635
|
+
// When using an application identity, there is no account in the MSAL TokenCache
|
|
636
|
+
if (this.connection.authType !== AuthType.Certificate &&
|
|
637
|
+
this.connection.authType !== AuthType.Secret &&
|
|
638
|
+
this.connection.authType !== AuthType.Identity) {
|
|
639
|
+
this.clientApplication = await this.getPublicClient(logger, debug);
|
|
640
|
+
if (this.clientApplication) {
|
|
641
|
+
const tokenCache = this.clientApplication.getTokenCache();
|
|
642
|
+
const account = await tokenCache.getAccountByLocalId(connection.identityId);
|
|
643
|
+
if (account !== null) {
|
|
644
|
+
await tokenCache.removeAccount(account);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
const connectionStorage = this.getConnectionStorage();
|
|
649
|
+
const allConnectionsStorage = this.getAllConnectionsStorage();
|
|
650
|
+
await allConnectionsStorage.set(JSON.stringify(this._allConnections));
|
|
651
|
+
if (isCurrentConnection) {
|
|
652
|
+
await connectionStorage.remove();
|
|
653
|
+
this.connection.deactivate();
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
getConnectionStorage() {
|
|
602
657
|
return new FileTokenStorage(FileTokenStorage.connectionInfoFilePath());
|
|
603
658
|
}
|
|
604
659
|
getMsalCacheStorage() {
|
|
605
660
|
return new FileTokenStorage(FileTokenStorage.msalCacheFilePath());
|
|
606
661
|
}
|
|
662
|
+
getAllConnectionsStorage() {
|
|
663
|
+
return new FileTokenStorage(FileTokenStorage.allConnectionsFilePath());
|
|
664
|
+
}
|
|
607
665
|
static getEndpointForResource(resource, cloudType) {
|
|
608
666
|
if (Auth.cloudEndpoints[cloudType] &&
|
|
609
667
|
Auth.cloudEndpoints[cloudType][resource]) {
|
|
@@ -613,6 +671,52 @@ export class Auth {
|
|
|
613
671
|
return resource;
|
|
614
672
|
}
|
|
615
673
|
}
|
|
674
|
+
async getAllConnectionsFromStorage() {
|
|
675
|
+
const connectionStorage = this.getAllConnectionsStorage();
|
|
676
|
+
const json = await connectionStorage.get();
|
|
677
|
+
return JSON.parse(json);
|
|
678
|
+
}
|
|
679
|
+
async switchToConnection(connection) {
|
|
680
|
+
this.connection.deactivate();
|
|
681
|
+
this._connection = Object.assign(this._connection, connection);
|
|
682
|
+
this._connection.active = true;
|
|
683
|
+
await this.storeConnectionInfo();
|
|
684
|
+
}
|
|
685
|
+
async updateConnection(connection, newName) {
|
|
686
|
+
const allConnections = await this.getAllConnections();
|
|
687
|
+
const existingConnection = allConnections.find(c => c.name === newName);
|
|
688
|
+
const oldName = connection.name;
|
|
689
|
+
if (existingConnection) {
|
|
690
|
+
throw new CommandError(`The connection name '${newName}' is already in use`);
|
|
691
|
+
}
|
|
692
|
+
connection.name = newName;
|
|
693
|
+
if (this.connection.name === oldName) {
|
|
694
|
+
this._connection.name = newName;
|
|
695
|
+
}
|
|
696
|
+
await this.storeConnectionInfo();
|
|
697
|
+
}
|
|
698
|
+
async getConnection(name) {
|
|
699
|
+
const allConnections = await this.getAllConnections();
|
|
700
|
+
const connection = allConnections.find(i => i.name === name);
|
|
701
|
+
if (!connection) {
|
|
702
|
+
throw new CommandError(`The connection '${name}' cannot be found`);
|
|
703
|
+
}
|
|
704
|
+
return connection;
|
|
705
|
+
}
|
|
706
|
+
getConnectionDetails(connection) {
|
|
707
|
+
// Asserting name and identityId because they are optional, but required at this point.
|
|
708
|
+
assert(connection.identityName !== undefined);
|
|
709
|
+
assert(connection.name !== undefined);
|
|
710
|
+
const details = {
|
|
711
|
+
connectionName: connection.name,
|
|
712
|
+
connectedAs: connection.identityName,
|
|
713
|
+
authType: AuthType[connection.authType],
|
|
714
|
+
appId: connection.appId,
|
|
715
|
+
appTenant: connection.tenant,
|
|
716
|
+
cloudType: CloudType[connection.cloudType]
|
|
717
|
+
};
|
|
718
|
+
return details;
|
|
719
|
+
}
|
|
616
720
|
}
|
|
617
721
|
Auth.cloudEndpoints = [];
|
|
618
722
|
Auth.initialize();
|
package/dist/AuthServer.js
CHANGED
|
@@ -7,8 +7,8 @@ export class AuthServer {
|
|
|
7
7
|
this.debug = false;
|
|
8
8
|
this.resource = "";
|
|
9
9
|
this.generatedServerUrl = "";
|
|
10
|
-
this.initializeServer = (
|
|
11
|
-
this.
|
|
10
|
+
this.initializeServer = (connection, resource, resolve, reject, logger, debug = false) => {
|
|
11
|
+
this.connection = connection;
|
|
12
12
|
this.resolve = resolve;
|
|
13
13
|
this.reject = reject;
|
|
14
14
|
this.logger = logger;
|
|
@@ -20,7 +20,7 @@ export class AuthServer {
|
|
|
20
20
|
const requestState = Math.random().toString(16).substr(2, 20);
|
|
21
21
|
const address = this.httpServer.address();
|
|
22
22
|
this.generatedServerUrl = `http://localhost:${address.port}`;
|
|
23
|
-
const url = `${Auth.getEndpointForResource('https://login.microsoftonline.com', this.
|
|
23
|
+
const url = `${Auth.getEndpointForResource('https://login.microsoftonline.com', this.connection.cloudType)}/${this.connection.tenant}/oauth2/authorize?response_type=code&client_id=${this.connection.appId}&redirect_uri=${this.generatedServerUrl}&state=${requestState}&resource=${this.resource}&prompt=select_account`;
|
|
24
24
|
if (this.debug) {
|
|
25
25
|
this.logger.logToStderr('Redirect URL:');
|
|
26
26
|
this.logger.logToStderr(url);
|
package/dist/Command.js
CHANGED
|
@@ -180,7 +180,7 @@ class Command {
|
|
|
180
180
|
throw new CommandError(error);
|
|
181
181
|
}
|
|
182
182
|
this.initAction(args, logger);
|
|
183
|
-
if (!auth.
|
|
183
|
+
if (!auth.connection.active) {
|
|
184
184
|
throw new CommandError('Log in to Microsoft 365 first');
|
|
185
185
|
}
|
|
186
186
|
try {
|
|
@@ -313,6 +313,9 @@ class Command {
|
|
|
313
313
|
this.verbose = this.debug || args.options.verbose || process.env.CLIMICROSOFT365_VERBOSE === '1';
|
|
314
314
|
request.debug = this.debug;
|
|
315
315
|
request.logger = logger;
|
|
316
|
+
if (this.debug && auth.connection.identityName !== undefined) {
|
|
317
|
+
logger.logToStderr(`Executing command as '${auth.connection.identityName}', appId: ${auth.connection.appId}, tenantId: ${auth.connection.identityTenantId}`);
|
|
318
|
+
}
|
|
316
319
|
telemetry.trackEvent(this.getUsedCommandName(), this.getTelemetryProperties(args));
|
|
317
320
|
}
|
|
318
321
|
getUnknownOptions(options) {
|
|
@@ -350,10 +353,10 @@ class Command {
|
|
|
350
353
|
});
|
|
351
354
|
}
|
|
352
355
|
loadValuesFromAccessToken(args) {
|
|
353
|
-
if (!auth.
|
|
356
|
+
if (!auth.connection.accessTokens[auth.defaultResource]) {
|
|
354
357
|
return;
|
|
355
358
|
}
|
|
356
|
-
const token = auth.
|
|
359
|
+
const token = auth.connection.accessTokens[auth.defaultResource].accessToken;
|
|
357
360
|
const optionNames = Object.getOwnPropertyNames(args.options);
|
|
358
361
|
optionNames.forEach(option => {
|
|
359
362
|
const value = args.options[option];
|
|
@@ -362,7 +365,7 @@ class Command {
|
|
|
362
365
|
}
|
|
363
366
|
const lowerCaseValue = value.toLowerCase().trim();
|
|
364
367
|
if (lowerCaseValue === '@meid' || lowerCaseValue === '@meusername') {
|
|
365
|
-
const isAppOnlyAccessToken = accessToken.isAppOnlyAccessToken(auth.
|
|
368
|
+
const isAppOnlyAccessToken = accessToken.isAppOnlyAccessToken(auth.connection.accessTokens[auth.defaultResource].accessToken);
|
|
366
369
|
if (isAppOnlyAccessToken) {
|
|
367
370
|
throw `It's not possible to use ${value} with application permissions`;
|
|
368
371
|
}
|
|
@@ -379,7 +382,7 @@ class Command {
|
|
|
379
382
|
if (cli.currentCommandName &&
|
|
380
383
|
cli.currentCommandName.indexOf(deprecated) === 0) {
|
|
381
384
|
const chalk = (await import('chalk')).default;
|
|
382
|
-
await logger.logToStderr(chalk.yellow(`Command '${deprecated}' is deprecated. Please use '${recommended}' instead
|
|
385
|
+
await logger.logToStderr(chalk.yellow(`Command '${deprecated}' is deprecated. Please use '${recommended}' instead.`));
|
|
383
386
|
}
|
|
384
387
|
}
|
|
385
388
|
async warn(logger, warning) {
|
|
@@ -6,7 +6,10 @@ export class FileTokenStorage {
|
|
|
6
6
|
return path.join(os.homedir(), '.cli-m365-msal.json');
|
|
7
7
|
}
|
|
8
8
|
static connectionInfoFilePath() {
|
|
9
|
-
return path.join(os.homedir(), '.cli-m365-
|
|
9
|
+
return path.join(os.homedir(), '.cli-m365-connection.json');
|
|
10
|
+
}
|
|
11
|
+
static allConnectionsFilePath() {
|
|
12
|
+
return path.join(os.homedir(), '.cli-m365-all-connections.json');
|
|
10
13
|
}
|
|
11
14
|
constructor(filePath) {
|
|
12
15
|
this.filePath = filePath;
|
package/dist/cli/cli.js
CHANGED
|
@@ -98,7 +98,7 @@ async function execute(rawArgs) {
|
|
|
98
98
|
if (parsedArgs.output !== 'none') {
|
|
99
99
|
printHelp(await getHelpMode(parsedArgs));
|
|
100
100
|
}
|
|
101
|
-
return
|
|
101
|
+
return;
|
|
102
102
|
}
|
|
103
103
|
delete cli.optionsFromArgs.options._;
|
|
104
104
|
delete cli.optionsFromArgs.options['--'];
|
|
@@ -39,7 +39,7 @@ class AppCommand extends Command {
|
|
|
39
39
|
}
|
|
40
40
|
if (!this.m365rcJson.apps ||
|
|
41
41
|
this.m365rcJson.apps.length === 0) {
|
|
42
|
-
throw new CommandError(`No
|
|
42
|
+
throw new CommandError(`No Entra apps found in ${m365rcJsonPath}`);
|
|
43
43
|
}
|
|
44
44
|
if (args.options.appId) {
|
|
45
45
|
if (!this.m365rcJson.apps.some(app => app.appId === args.options.appId)) {
|
|
@@ -54,7 +54,7 @@ class AppCommand extends Command {
|
|
|
54
54
|
}
|
|
55
55
|
if (this.m365rcJson.apps.length > 1) {
|
|
56
56
|
const resultAsKeyValuePair = formatting.convertArrayToHashTable('appIdIndex', this.m365rcJson.apps);
|
|
57
|
-
const result = await cli.handleMultipleResultsFound(`Multiple
|
|
57
|
+
const result = await cli.handleMultipleResultsFound(`Multiple Entra apps found in ${m365rcJsonPath}.`, resultAsKeyValuePair);
|
|
58
58
|
this.appId = this.m365rcJson.apps[result.appIdIndex].appId;
|
|
59
59
|
await super.action(logger, args);
|
|
60
60
|
}
|
|
@@ -6,11 +6,11 @@ export default class PowerAppsCommand extends Command {
|
|
|
6
6
|
}
|
|
7
7
|
initAction(args, logger) {
|
|
8
8
|
super.initAction(args, logger);
|
|
9
|
-
if (!auth.
|
|
9
|
+
if (!auth.connection.active) {
|
|
10
10
|
// we fail no login in the base command command class
|
|
11
11
|
return;
|
|
12
12
|
}
|
|
13
|
-
if (auth.
|
|
13
|
+
if (auth.connection.cloudType !== CloudType.Public) {
|
|
14
14
|
throw new CommandError(`Power Apps commands only support the public cloud at the moment. We'll add support for other clouds in the future. Sorry for the inconvenience.`);
|
|
15
15
|
}
|
|
16
16
|
}
|
|
@@ -6,11 +6,11 @@ export default class PowerAutomateCommand extends Command {
|
|
|
6
6
|
}
|
|
7
7
|
initAction(args, logger) {
|
|
8
8
|
super.initAction(args, logger);
|
|
9
|
-
if (!auth.
|
|
9
|
+
if (!auth.connection.active) {
|
|
10
10
|
// we fail no login in the base command command class
|
|
11
11
|
return;
|
|
12
12
|
}
|
|
13
|
-
if (auth.
|
|
13
|
+
if (auth.connection.cloudType !== CloudType.Public) {
|
|
14
14
|
throw new CommandError(`Power Automate commands only support the public cloud at the moment. We'll add support for other clouds in the future. Sorry for the inconvenience.`);
|
|
15
15
|
}
|
|
16
16
|
}
|
|
@@ -6,11 +6,11 @@ export default class PowerPlatformCommand extends Command {
|
|
|
6
6
|
}
|
|
7
7
|
initAction(args, logger) {
|
|
8
8
|
super.initAction(args, logger);
|
|
9
|
-
if (!auth.
|
|
9
|
+
if (!auth.connection.active) {
|
|
10
10
|
// we fail no login in the base command command class
|
|
11
11
|
return;
|
|
12
12
|
}
|
|
13
|
-
if (auth.
|
|
13
|
+
if (auth.connection.cloudType !== CloudType.Public) {
|
|
14
14
|
throw new CommandError(`Power Platform commands only support the public cloud at the moment. We'll add support for other clouds in the future. Sorry for the inconvenience.`);
|
|
15
15
|
}
|
|
16
16
|
}
|