@microsoft/vscode-azext-azureauth 3.0.0 → 3.1.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Change Log
2
2
 
3
+ ## 3.1.0 - 2024-11-26
4
+
5
+ * [#1827](https://github.com/microsoft/vscode-azuretools/pull/1827) Add more comprehensive support for multi-account scenarios
6
+ * [#1815](https://github.com/microsoft/vscode-azuretools/issues/1815) Fix `VSCodeAzureSubscriptionProvider.getSubscriptions()` returning empty
7
+
8
+ ## 3.0.1 - 2024-11-19
9
+ * [#1819](https://github.com/microsoft/vscode-azuretools/pull/1819) Add account parameter to `AzureSubscriptionProvider.isSignedIn()` function to fix a multi-account issue [#1809](https://github.com/microsoft/vscode-azuretools/issues/1809)
10
+ * [#1822](https://github.com/microsoft/vscode-azuretools/pull/1822) Add check in `VSCodeAzureSubscriptionProvider.getTenants()` to fix a multi-account issue [#1809](https://github.com/microsoft/vscode-azuretools/issues/1809)
11
+
3
12
  ## 3.0.0 - 2024-09-19
4
13
  * [#1789](https://github.com/microsoft/vscode-azuretools/pull/1789) Change `getTenants` to be compatible with the new Azure Resources tenants view. This also includes a possible breaking change where an optional parameter `account` which when passed in `getTenants` will return the tenants associated with that single account. Otherwise `getTenants` will return the tenants for all authenticated accounts.
5
14
 
@@ -34,15 +34,16 @@ export interface AzureSubscriptionProvider {
34
34
  *
35
35
  * @returns True if the user is signed in, false otherwise.
36
36
  */
37
- isSignedIn(tenantId?: string): Promise<boolean>;
37
+ isSignedIn(tenantId?: string, account?: vscode.AuthenticationSessionAccountInformation): Promise<boolean>;
38
38
  /**
39
39
  * Asks the user to sign in or pick an account to use.
40
40
  *
41
41
  * @param tenantId (Optional) Provide to sign in to a specific tenant.
42
+ * @param account (Optional) Provide to sign in to a specific account.
42
43
  *
43
44
  * @returns True if the user is signed in, false otherwise.
44
45
  */
45
- signIn(tenantId?: string): Promise<boolean>;
46
+ signIn(tenantId?: string, account?: vscode.AuthenticationSessionAccountInformation): Promise<boolean>;
46
47
  /**
47
48
  * An event that is fired when the user signs in. Debounced to fire at most once every 5 seconds.
48
49
  */
@@ -28,7 +28,8 @@ export declare class VSCodeAzureSubscriptionProvider extends vscode.Disposable i
28
28
  * @param filter - Whether to filter the list returned, according to the list returned
29
29
  * by `getTenantFilters()` and `getSubscriptionFilters()`. Optional, default true.
30
30
  *
31
- * @returns A list of Azure subscriptions.
31
+ * @returns A list of Azure subscriptions. The list is sorted by subscription name.
32
+ * The list can contain duplicate subscriptions if they come from different accounts.
32
33
  *
33
34
  * @throws A {@link NotSignedInError} If the user is not signed in to Azure.
34
35
  * Use {@link isSignedIn} and/or {@link signIn} before this method to ensure
@@ -39,18 +40,23 @@ export declare class VSCodeAzureSubscriptionProvider extends vscode.Disposable i
39
40
  * Checks to see if a user is signed in.
40
41
  *
41
42
  * @param tenantId (Optional) Provide to check if a user is signed in to a specific tenant.
43
+ * @param account (Optional) Provide to check if a user is signed in to a specific account.
42
44
  *
43
45
  * @returns True if the user is signed in, false otherwise.
46
+ *
47
+ * If no tenant or account is provided, then
48
+ * checks all accounts for a session.
44
49
  */
45
- isSignedIn(tenantId?: string): Promise<boolean>;
50
+ isSignedIn(tenantId?: string, account?: vscode.AuthenticationSessionAccountInformation): Promise<boolean>;
46
51
  /**
47
52
  * Asks the user to sign in or pick an account to use.
48
53
  *
49
54
  * @param tenantId (Optional) Provide to sign in to a specific tenant.
55
+ * @param account (Optional) Provide to sign in to a specific account.
50
56
  *
51
57
  * @returns True if the user is signed in, false otherwise.
52
58
  */
53
- signIn(tenantId?: string): Promise<boolean>;
59
+ signIn(tenantId?: string, account?: vscode.AuthenticationSessionAccountInformation): Promise<boolean>;
54
60
  /**
55
61
  * An event that is fired when the user signs in. Debounced to fire at most once every 5 seconds.
56
62
  */
@@ -85,26 +85,29 @@ class VSCodeAzureSubscriptionProvider extends vscode.Disposable {
85
85
  _g = false;
86
86
  try {
87
87
  account = _c;
88
- const { client } = yield this.getSubscriptionClient(account, undefined, undefined);
89
- try {
90
- for (var _k = true, _l = (e_2 = void 0, __asyncValues(client.tenants.list())), _m; _m = yield _l.next(), _d = _m.done, !_d;) {
91
- _f = _m.value;
92
- _k = false;
93
- try {
94
- const tenant = _f;
95
- results.push(tenant);
96
- }
97
- finally {
98
- _k = true;
88
+ // Added check. Without this the getSubscriptionClient function throws the NotSignedInError
89
+ if (yield this.isSignedIn(undefined, account)) {
90
+ const { client } = yield this.getSubscriptionClient(account, undefined, undefined);
91
+ try {
92
+ for (var _k = true, _l = (e_2 = void 0, __asyncValues(client.tenants.list())), _m; _m = yield _l.next(), _d = _m.done, !_d;) {
93
+ _f = _m.value;
94
+ _k = false;
95
+ try {
96
+ const tenant = _f;
97
+ results.push(tenant);
98
+ }
99
+ finally {
100
+ _k = true;
101
+ }
99
102
  }
100
103
  }
101
- }
102
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
103
- finally {
104
- try {
105
- if (!_k && !_d && (_e = _l.return)) yield _e.call(_l);
104
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
105
+ finally {
106
+ try {
107
+ if (!_k && !_d && (_e = _l.return)) yield _e.call(_l);
108
+ }
109
+ finally { if (e_2) throw e_2.error; }
106
110
  }
107
- finally { if (e_2) throw e_2.error; }
108
111
  }
109
112
  }
110
113
  finally {
@@ -128,7 +131,8 @@ class VSCodeAzureSubscriptionProvider extends vscode.Disposable {
128
131
  * @param filter - Whether to filter the list returned, according to the list returned
129
132
  * by `getTenantFilters()` and `getSubscriptionFilters()`. Optional, default true.
130
133
  *
131
- * @returns A list of Azure subscriptions.
134
+ * @returns A list of Azure subscriptions. The list is sorted by subscription name.
135
+ * The list can contain duplicate subscriptions if they come from different accounts.
132
136
  *
133
137
  * @throws A {@link NotSignedInError} If the user is not signed in to Azure.
134
138
  * Use {@link isSignedIn} and/or {@link signIn} before this method to ensure
@@ -138,7 +142,7 @@ class VSCodeAzureSubscriptionProvider extends vscode.Disposable {
138
142
  return __awaiter(this, void 0, void 0, function* () {
139
143
  const tenantIds = yield this.getTenantFilters();
140
144
  const shouldFilterTenants = filter && !!tenantIds.length; // If the list is empty it is treated as "no filter"
141
- const results = [];
145
+ const allSubscriptions = [];
142
146
  try {
143
147
  this.suppressSignInEvents = true;
144
148
  // Get the list of tenants from each account
@@ -151,36 +155,55 @@ class VSCodeAzureSubscriptionProvider extends vscode.Disposable {
151
155
  if (shouldFilterTenants && !tenantIds.includes(tenantId)) {
152
156
  continue;
153
157
  }
154
- // If the user is not signed in to this tenant, then skip it
155
- if (!(yield this.isSignedIn(tenantId))) {
156
- continue;
157
- }
158
158
  // For each tenant, get the list of subscriptions
159
- results.push(...yield this.getSubscriptionsForTenant(tenantId, account));
159
+ allSubscriptions.push(...yield this.getSubscriptionsForTenant(account, tenantId));
160
160
  }
161
+ // list subscriptions for the home tenant
162
+ allSubscriptions.push(...yield this.getSubscriptionsForTenant(account));
161
163
  }
162
164
  }
163
165
  finally {
164
166
  this.suppressSignInEvents = false;
165
167
  }
168
+ // It's possible that by listing subscriptions in all tenants and the "home" tenant there could be duplicate subscriptions
169
+ // Thus, we remove duplicate subscriptions. However, if multiple accounts have the same subscription, we keep them.
170
+ const subscriptionMap = new Map();
171
+ allSubscriptions.forEach(sub => subscriptionMap.set(`${sub.account.id}/${sub.subscriptionId}`, sub));
172
+ const uniqueSubscriptions = Array.from(subscriptionMap.values());
166
173
  const sortSubscriptions = (subscriptions) => subscriptions.sort((a, b) => a.name.localeCompare(b.name));
167
174
  const subscriptionIds = yield this.getSubscriptionFilters();
168
175
  if (filter && !!subscriptionIds.length) { // If the list is empty it is treated as "no filter"
169
- return sortSubscriptions(results.filter(sub => subscriptionIds.includes(sub.subscriptionId)));
176
+ return sortSubscriptions(uniqueSubscriptions.filter(sub => subscriptionIds.includes(sub.subscriptionId)));
170
177
  }
171
- return sortSubscriptions(results);
178
+ return sortSubscriptions(uniqueSubscriptions);
172
179
  });
173
180
  }
174
181
  /**
175
182
  * Checks to see if a user is signed in.
176
183
  *
177
184
  * @param tenantId (Optional) Provide to check if a user is signed in to a specific tenant.
185
+ * @param account (Optional) Provide to check if a user is signed in to a specific account.
178
186
  *
179
187
  * @returns True if the user is signed in, false otherwise.
188
+ *
189
+ * If no tenant or account is provided, then
190
+ * checks all accounts for a session.
180
191
  */
181
- isSignedIn(tenantId) {
192
+ isSignedIn(tenantId, account) {
182
193
  return __awaiter(this, void 0, void 0, function* () {
183
- const session = yield (0, getSessionFromVSCode_1.getSessionFromVSCode)([], tenantId, { createIfNone: false, silent: true });
194
+ // If no tenant or account is provided, then check all accounts for a session
195
+ if (!account && !tenantId) {
196
+ const accounts = yield vscode.authentication.getAccounts((0, configuredAzureEnv_1.getConfiguredAuthProviderId)());
197
+ if (accounts.length === 0) {
198
+ return false;
199
+ }
200
+ for (const account of accounts) {
201
+ if (yield this.isSignedIn(undefined, account)) {
202
+ return true;
203
+ }
204
+ }
205
+ }
206
+ const session = yield (0, getSessionFromVSCode_1.getSessionFromVSCode)([], tenantId, { createIfNone: false, silent: true, account });
184
207
  return !!session;
185
208
  });
186
209
  }
@@ -188,12 +211,18 @@ class VSCodeAzureSubscriptionProvider extends vscode.Disposable {
188
211
  * Asks the user to sign in or pick an account to use.
189
212
  *
190
213
  * @param tenantId (Optional) Provide to sign in to a specific tenant.
214
+ * @param account (Optional) Provide to sign in to a specific account.
191
215
  *
192
216
  * @returns True if the user is signed in, false otherwise.
193
217
  */
194
- signIn(tenantId) {
218
+ signIn(tenantId, account) {
195
219
  return __awaiter(this, void 0, void 0, function* () {
196
- const session = yield (0, getSessionFromVSCode_1.getSessionFromVSCode)([], tenantId, { createIfNone: true, clearSessionPreference: true });
220
+ const session = yield (0, getSessionFromVSCode_1.getSessionFromVSCode)([], tenantId, {
221
+ createIfNone: true,
222
+ // If no account is provided, then clear the session preference which tells VS Code to show the account picker
223
+ clearSessionPreference: !account,
224
+ account,
225
+ });
197
226
  return !!session;
198
227
  });
199
228
  }
@@ -245,9 +274,14 @@ class VSCodeAzureSubscriptionProvider extends vscode.Disposable {
245
274
  *
246
275
  * @returns The list of subscriptions for the tenant.
247
276
  */
248
- getSubscriptionsForTenant(tenantId, account) {
277
+ getSubscriptionsForTenant(account, tenantId) {
249
278
  var _a, e_3, _b, _c;
250
279
  return __awaiter(this, void 0, void 0, function* () {
280
+ // If the user is not signed in to this tenant or account, then return an empty list
281
+ // This is to prevent the NotSignedInError from being thrown in getSubscriptionClient
282
+ if (!(yield this.isSignedIn(tenantId, account))) {
283
+ return [];
284
+ }
251
285
  const { client, credential, authentication } = yield this.getSubscriptionClient(account, tenantId, undefined);
252
286
  const environment = (0, configuredAzureEnv_1.getConfiguredAzureEnv)();
253
287
  const subscriptions = [];
@@ -265,8 +299,8 @@ class VSCodeAzureSubscriptionProvider extends vscode.Disposable {
265
299
  /* eslint-disable @typescript-eslint/no-non-null-assertion */
266
300
  name: subscription.displayName,
267
301
  subscriptionId: subscription.subscriptionId,
302
+ tenantId: tenantId !== null && tenantId !== void 0 ? tenantId : subscription.tenantId,
268
303
  /* eslint-enable @typescript-eslint/no-non-null-assertion */
269
- tenantId: tenantId,
270
304
  account: account
271
305
  });
272
306
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@microsoft/vscode-azext-azureauth",
3
3
  "author": "Microsoft Corporation",
4
- "version": "3.0.0",
4
+ "version": "3.1.0",
5
5
  "description": "Azure authentication helpers for Visual Studio Code",
6
6
  "tags": [
7
7
  "azure",