mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-13 17:22:15 -05:00
Fix some build errors using latest typescript version
This commit is contained in:
@@ -40,7 +40,6 @@ const extensions = [
|
||||
'extension-editing',
|
||||
'markdown',
|
||||
'merge-conflict',
|
||||
'account-provider-azure',
|
||||
'insights-default'
|
||||
];
|
||||
|
||||
|
||||
@@ -467,7 +467,7 @@ function createMessageConnection<T extends MessageConnection>(messageReader: Mes
|
||||
|
||||
eventHandlers[type.method] = handler;
|
||||
},
|
||||
sendRequest: <P, R, E>(type: RequestType<P, R, E>, params: P, token?: CancellationToken) => {
|
||||
sendRequest: <P, R, E>(type: RequestType<P, R, E>, params: P, token?: CancellationToken): any => {
|
||||
throwIfClosedOrDisposed();
|
||||
|
||||
let id = sequenceNumber++;
|
||||
|
||||
@@ -108,7 +108,7 @@ export class IPCMessageWriter extends AbstractMessageWriter implements MessageWr
|
||||
|
||||
public write(msg: Message): void {
|
||||
try {
|
||||
this.process.send(msg);
|
||||
(<any>this.process).send(<any>msg);
|
||||
this.errorCount = 0;
|
||||
} catch (error) {
|
||||
this.errorCount++;
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
{
|
||||
"name": "account-provider-azure",
|
||||
"version": "0.0.1",
|
||||
"publisher": "Microsoft",
|
||||
"engines": { "vscode": "*" },
|
||||
"main": "./out/main",
|
||||
"activationEvents": [ "*" ],
|
||||
"scripts": {
|
||||
"compile": "gulp compile-extension:account-provider-azure"
|
||||
},
|
||||
"dependencies": {
|
||||
"adal-node": "^0.1.16",
|
||||
"decompress": "^4.0.0",
|
||||
"extensions-modules": "file:../../extensions-modules",
|
||||
"fs-extra-promise": "^0.3.1",
|
||||
"opener": "1.4.2",
|
||||
"request": "2.63.0",
|
||||
"urijs": "^1.18.12",
|
||||
"vscode-extension-telemetry": "^0.0.5",
|
||||
"vscode-nls": "2.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^8.0.24"
|
||||
},
|
||||
"contributes": {
|
||||
"commands": [
|
||||
{
|
||||
"command": "extension.clearTokenCache",
|
||||
"title": "%extension.clearTokenCache%",
|
||||
"category": "Azure Accounts"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"extension.clearTokenCache": "Clear Azure Account Token Cache"
|
||||
}
|
||||
@@ -1,371 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as adal from 'adal-node';
|
||||
import * as data from 'data';
|
||||
import * as request from 'request';
|
||||
import * as nls from 'vscode-nls';
|
||||
import {
|
||||
Arguments,
|
||||
AzureAccount,
|
||||
AzureAccountProviderMetadata,
|
||||
AzureAccountSecurityTokenCollection,
|
||||
Tenant
|
||||
} from './interfaces';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
export class AzureAccountProvider implements data.AccountProvider {
|
||||
private static WorkSchoolAccountLogo: data.AccountContextualLogo = {
|
||||
light: AzureAccountProvider.loadIcon('work_school_account.svg'),
|
||||
dark: AzureAccountProvider.loadIcon('work_school_account_inverse.svg')
|
||||
};
|
||||
private static MicrosoftAccountLogo: data.AccountContextualLogo = {
|
||||
light: AzureAccountProvider.loadIcon('microsoft_account.svg'),
|
||||
dark: AzureAccountProvider.loadIcon('microsoft_account.svg')
|
||||
};
|
||||
|
||||
private _args: Arguments;
|
||||
private _isInitialized: boolean;
|
||||
private _tokenCache: adal.TokenCache;
|
||||
|
||||
public metadata: AzureAccountProviderMetadata;
|
||||
|
||||
constructor(metadata: AzureAccountProviderMetadata, tokenCache: adal.TokenCache) {
|
||||
this.metadata = metadata;
|
||||
this._args = {
|
||||
host: metadata.settings.host,
|
||||
clientId: metadata.settings.clientId
|
||||
};
|
||||
this._isInitialized = false;
|
||||
this._tokenCache = tokenCache;
|
||||
}
|
||||
|
||||
// PUBLIC METHODS //////////////////////////////////////////////////////
|
||||
public clear(accountKey: data.AccountKey): Thenable<void> {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
public clearTokenCache(): Thenable<void> {
|
||||
return this._tokenCache.clear();
|
||||
}
|
||||
|
||||
public getSecurityToken(account: AzureAccount): Thenable<AzureAccountSecurityTokenCollection> {
|
||||
let self = this;
|
||||
return this.doIfInitialized(() => self.getAccessTokens(account));
|
||||
}
|
||||
|
||||
public initialize(restoredAccounts: data.Account[]): Thenable<data.Account[]> {
|
||||
let self = this;
|
||||
|
||||
return new Promise<data.Account[]>(resolve => {
|
||||
// Rehydrate the accounts
|
||||
restoredAccounts.forEach((account) => {
|
||||
// Set the icon for the account
|
||||
account.displayInfo.contextualLogo = account.properties.isMsAccount
|
||||
? AzureAccountProvider.MicrosoftAccountLogo
|
||||
: AzureAccountProvider.WorkSchoolAccountLogo;
|
||||
|
||||
// TODO: Set stale status based on whether we can authenticate or not
|
||||
});
|
||||
|
||||
self._isInitialized = true;
|
||||
|
||||
resolve(restoredAccounts);
|
||||
});
|
||||
}
|
||||
|
||||
public prompt(): Thenable<AzureAccount> {
|
||||
let self = this;
|
||||
return this.doIfInitialized(() => self.signIn());
|
||||
}
|
||||
|
||||
public refresh(account: AzureAccount): Thenable<AzureAccount> {
|
||||
let self = this;
|
||||
return this.doIfInitialized(() => self.signIn(account.properties.isMsAccount, account.key.accountId));
|
||||
}
|
||||
|
||||
// PRIVATE METHODS /////////////////////////////////////////////////////
|
||||
private static loadIcon(iconName: string) {
|
||||
let filePath = path.join(__dirname, 'media', iconName);
|
||||
try {
|
||||
return 'image/svg+xml,' + fs.readFileSync(filePath);
|
||||
} catch(e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
private authenticate(tenantId: string, msa: boolean, userId: string, silent: boolean): Thenable<adal.TokenResponse> {
|
||||
let authorityUrl = `${this.metadata.settings.host}/${tenantId}`;
|
||||
// TODO: Rewrite using urijs
|
||||
let authorizeUrl = `${authorityUrl}/oauth2/authorize`
|
||||
+ `?client_id=${this.metadata.settings.clientId}` // Specify the client ID
|
||||
+ `&response_type=code` // Request the authorization code grant flow
|
||||
+ (userId ? (msa ? '&domain_hint=live.com' : '&msafed=0') : '') // Optimize prompt given existing MSA or org ID
|
||||
+ ((!userId && !silent) ? '&prompt=login' : '') // Require login if not silent
|
||||
+ (userId ? `&login_hint=${encodeURIComponent(userId)}` : '') // Show login hint if we have an existing user ID
|
||||
+ (this.metadata.settings.siteId ? `&site_id=${this.metadata.settings.siteId}` : '') // Site ID to use as brand on the prompt
|
||||
+ '&display=popup' // Causes a popup version of the UI to be shown
|
||||
+ `&resource=${encodeURIComponent(this.metadata.settings.signInResourceId)}` // Specify the resource for which an access token should be retrieved
|
||||
+ `&redirect_uri=${encodeURIComponent(this.metadata.settings.redirectUri)}`; // TODO: add locale parameter like in VSAccountProvider.TryAppendLocalParameter
|
||||
|
||||
// Get the authorization code. If this is the initial authentication (the user is unknown),
|
||||
// do not silently prompt. If this is a subsequent authentication for an additional tenant,
|
||||
// the browser cookie cache will be used to authenticate without prompting, so run the
|
||||
// browser silently.
|
||||
return data.accounts.performOAuthAuthorization(authorizeUrl, silent)
|
||||
.then((code: string) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let context = new adal.AuthenticationContext(authorityUrl, null, this._tokenCache);
|
||||
context.acquireTokenWithAuthorizationCode(
|
||||
code,
|
||||
this.metadata.settings.redirectUri,
|
||||
this.metadata.settings.signInResourceId,
|
||||
this.metadata.settings.clientId,
|
||||
null,
|
||||
(error, response) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(<adal.TokenResponse> response);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private doIfInitialized<T>(op: () => Thenable<T>): Thenable<T> {
|
||||
return this._isInitialized
|
||||
? op()
|
||||
: Promise.reject(localize('accountProviderNotInitialized', 'Account provider not initialized, cannot perform action'));
|
||||
}
|
||||
|
||||
private getAccessTokens(account: AzureAccount): Thenable<AzureAccountSecurityTokenCollection> {
|
||||
let self = this;
|
||||
|
||||
// TODO: Could we add some better typing here?
|
||||
let accessTokenPromises: Thenable<void>[] = [];
|
||||
let tokenCollection: AzureAccountSecurityTokenCollection = {};
|
||||
for (let tenant of account.properties.tenants) {
|
||||
let promise = new Promise<void>((resolve, reject) => {
|
||||
// TODO: use urijs to generate this URI
|
||||
let authorityUrl = `${self.metadata.settings.host}/${tenant.id}`;
|
||||
let context = new adal.AuthenticationContext(authorityUrl, null, self._tokenCache);
|
||||
|
||||
// TODO: This is where we should mark the account as stale
|
||||
context.acquireToken(
|
||||
self.metadata.settings.armResource.id,
|
||||
tenant.userId,
|
||||
self.metadata.settings.clientId,
|
||||
(error: adal.ErrorResponse, response: adal.SuccessResponse) => {
|
||||
// Handle errors first
|
||||
if (error) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate a token object and add it to the collection
|
||||
tokenCollection[tenant.id] = {
|
||||
expiresOn: response.expiresOn,
|
||||
resource: response.resource,
|
||||
token: response.accessToken,
|
||||
tokenType: response.tokenType
|
||||
};
|
||||
resolve();
|
||||
}
|
||||
);
|
||||
});
|
||||
accessTokenPromises.push(promise);
|
||||
}
|
||||
|
||||
// Wait until all the tokens have been acquired then return the collection
|
||||
return Promise.all(accessTokenPromises)
|
||||
.then(() => tokenCollection);
|
||||
}
|
||||
|
||||
private getTenantDisplayName(msa: boolean, tenantId: string, userId: string): Thenable<string> {
|
||||
let self = this;
|
||||
if(msa) {
|
||||
return Promise.resolve(localize('microsoftAccountDisplayName', 'Microsoft Account'));
|
||||
}
|
||||
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
// Get an access token to the AAD graph resource
|
||||
// TODO: Use urijs to generate this URI
|
||||
let authorityUrl = `${self.metadata.settings.host}/${tenantId}`;
|
||||
let context = new adal.AuthenticationContext(authorityUrl, null, self._tokenCache);
|
||||
context.acquireToken(self.metadata.settings.graphResource.id, userId, self.metadata.settings.clientId, (error, response) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
|
||||
request.get(
|
||||
`${self.metadata.settings.graphResource.endpoint}/${tenantId}/tenantDetails?api-version=2013-04-05`,
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${(<adal.TokenResponse>response).accessToken}`
|
||||
},
|
||||
json: true
|
||||
},
|
||||
(graphError, graphResponse, body: {error: any; value: any[];}) => {
|
||||
if (graphError || body['odata.error']) {
|
||||
reject(graphError || body['odata.error']);
|
||||
} else if (body.value.length && body.value[0].displayName) {
|
||||
resolve(body.value[0].displayName);
|
||||
} else {
|
||||
resolve(localize('azureWorkAccountDisplayName', 'Work or school account'));
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private getTenants(msa: boolean, userId: string, tenantIds: string[], homeTenant: string): Thenable<Tenant[]> {
|
||||
let self = this;
|
||||
|
||||
// Lookup each tenant ID that was provided
|
||||
let getTenantPromises: Thenable<Tenant>[] = [];
|
||||
for (let tenantId of tenantIds) {
|
||||
let promise = this.authenticate(tenantId, msa, userId, false)
|
||||
.then((response) => self.getTenantDisplayName(msa, response.tenantId, response.userId))
|
||||
.then((displayName) => {
|
||||
return <Tenant>{
|
||||
displayName: displayName,
|
||||
id: tenantId,
|
||||
userId: userId
|
||||
};
|
||||
});
|
||||
getTenantPromises.push(promise);
|
||||
}
|
||||
|
||||
return Promise.all(getTenantPromises)
|
||||
.then((tenants) => {
|
||||
// Resort the tenants to make sure that the 'home' tenant is the first in the list
|
||||
let homeTenantIndex = tenants.findIndex((tenant) => tenant.id === homeTenant);
|
||||
if (homeTenantIndex >= 0) {
|
||||
let homeTenant = tenants.splice(homeTenantIndex, 1);
|
||||
tenants.unshift(homeTenant[0]);
|
||||
}
|
||||
return tenants;
|
||||
});
|
||||
}
|
||||
|
||||
private getTenantIds(userId: string): Thenable<string[]> {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Get an access token to the ARM resource
|
||||
// TODO: Build this URL with urijs
|
||||
let authorityUrl = `${this.metadata.settings.host}/common`;
|
||||
let context = new adal.AuthenticationContext(authorityUrl, null, this._tokenCache);
|
||||
context.acquireToken(this.metadata.settings.armResource.id, userId, this.metadata.settings.clientId, (error, response) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!!this.metadata.settings.adTenants && this.metadata.settings.adTenants.length > 0) {
|
||||
resolve(this.metadata.settings.adTenants);
|
||||
} else {
|
||||
request.get(
|
||||
`${this.metadata.settings.armResource.endpoint}/tenants?api-version=2015-01-01`,
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${(<adal.TokenResponse>response).accessToken}`
|
||||
},
|
||||
json: true
|
||||
},
|
||||
(armError, armResponse, body: {error: any; value: any[];}) => {
|
||||
if (armError || body.error) {
|
||||
reject(armError || body.error);
|
||||
} else {
|
||||
resolve(body.value.map(item => <string>item.tenantId));
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private signIn(msa?: boolean, userId?: string): Thenable<AzureAccount> {
|
||||
let self = this;
|
||||
|
||||
// Initial authentication is via the common/discovery tenant
|
||||
return this.authenticate('common', msa, userId, false)
|
||||
.then((response: adal.TokenResponse) => {
|
||||
let identityProvider = response.identityProvider;
|
||||
if (identityProvider) {
|
||||
identityProvider = identityProvider.toLowerCase();
|
||||
}
|
||||
|
||||
// Determine if this is a microsoft account
|
||||
msa = identityProvider && (
|
||||
identityProvider.indexOf('live.com') !== -1 ||
|
||||
identityProvider.indexOf('live-int.com') !== -1 ||
|
||||
identityProvider.indexOf('f8cdef31-a31e-4b4a-93e4-5f571e91255a') !== -1 ||
|
||||
identityProvider.indexOf('ea8a4392-515e-481f-879e-6571ff2a8a36') !== -1);
|
||||
|
||||
// Get the user information
|
||||
userId = response.userId;
|
||||
let displayName = (response.givenName && response.familyName)
|
||||
? `${response.givenName} ${response.familyName}`
|
||||
: userId;
|
||||
|
||||
// Get all the additional tenants
|
||||
return this.getTenantIds(userId)
|
||||
.then(tenantIds => self.getTenants(msa, userId, tenantIds, response.tenantId))
|
||||
.then(tenants => {
|
||||
return <AzureAccount>{
|
||||
key: {
|
||||
providerId: self.metadata.id,
|
||||
accountId: userId
|
||||
},
|
||||
name: userId,
|
||||
displayInfo: {
|
||||
contextualLogo: msa
|
||||
? AzureAccountProvider.MicrosoftAccountLogo
|
||||
: AzureAccountProvider.WorkSchoolAccountLogo,
|
||||
contextualDisplayName: tenants[0].displayName,
|
||||
displayName: displayName
|
||||
},
|
||||
properties: {
|
||||
isMsAccount: msa,
|
||||
tenants: tenants
|
||||
},
|
||||
isStale: false
|
||||
};
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// ADAL MONKEY PATCH ///////////////////////////////////////////////////////
|
||||
// Monkey patch the ADAL TokenRequest class to fix the fact that when you request a token from an
|
||||
// authorization code, it doesn't update the cache
|
||||
import * as TokenRequest from 'adal-node/lib/token-request';
|
||||
let getTokenWithAuthorizationCodeOriginal = TokenRequest.prototype.getTokenWithAuthorizationCode;
|
||||
TokenRequest.prototype.getTokenWithAuthorizationCode = function (
|
||||
authorizationCode: string,
|
||||
clientSecret: string,
|
||||
callback: adal.AcquireTokenCallback
|
||||
) {
|
||||
this._cacheDriver = this._createCacheDriver();
|
||||
getTokenWithAuthorizationCodeOriginal.call(this, authorizationCode, clientSecret, (error: Error, response: adal.ErrorResponse|adal.TokenResponse) => {
|
||||
if (error) {
|
||||
callback(error, response);
|
||||
} else {
|
||||
this._userId = (<adal.TokenResponse> response).userId;
|
||||
this._cacheDriver.add(response, () => callback(null, response));
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -1,87 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as constants from '../constants';
|
||||
import * as data from 'data';
|
||||
import * as events from 'events';
|
||||
import * as nls from 'vscode-nls';
|
||||
import * as path from 'path';
|
||||
import * as vscode from 'vscode';
|
||||
import CredentialServiceTokenCache from './tokenCache';
|
||||
import providerSettings from './providerSettings';
|
||||
import { AzureAccountProvider } from './azureAccountProvider';
|
||||
import { AzureAccountProviderMetadata } from './interfaces';
|
||||
|
||||
let localize = nls.loadMessageBundle();
|
||||
|
||||
export class AzureAccountProviderService implements vscode.Disposable {
|
||||
// CONSTANTS ///////////////////////////////////////////////////////////////
|
||||
private static CommandClearTokenCache = 'extension.clearTokenCache';
|
||||
private static CredentialNamespace = 'azureAccountProviderCredentials';
|
||||
|
||||
// MEMBER VARIABLES ////////////////////////////////////////////////////////
|
||||
private _accountProviders: { [accountProviderId: string]: AzureAccountProvider };
|
||||
private _event: events.EventEmitter;
|
||||
|
||||
constructor(private _context: vscode.ExtensionContext, private _userStoragePath: string) {
|
||||
this._accountProviders = {};
|
||||
this._event = new events.EventEmitter();
|
||||
}
|
||||
|
||||
// PUBLIC METHODS //////////////////////////////////////////////////////
|
||||
public activate(): Thenable<boolean> {
|
||||
let self = this;
|
||||
|
||||
// Register commands
|
||||
this._context.subscriptions.push(vscode.commands.registerCommand(
|
||||
AzureAccountProviderService.CommandClearTokenCache,
|
||||
() => { self._event.emit(AzureAccountProviderService.CommandClearTokenCache); }
|
||||
));
|
||||
this._event.on(AzureAccountProviderService.CommandClearTokenCache, () => { self.onClearTokenCache(); });
|
||||
|
||||
// Create the token caches
|
||||
// 1) Get a credential provider
|
||||
// 2) Iterate over the enabled providers
|
||||
// 2a) Create a token cache for provider
|
||||
// 2b) Create the provider from the provider's settings
|
||||
// 2c) Register the provider with the account service
|
||||
return data.credentials.getProvider(AzureAccountProviderService.CredentialNamespace)
|
||||
.then(credProvider => {
|
||||
providerSettings.forEach(provider => {
|
||||
let tokenCacheKey = `azureTokenCache-${provider.metadata.id}`;
|
||||
let tokenCachePath = path.join(self._userStoragePath, tokenCacheKey);
|
||||
let tokenCache = new CredentialServiceTokenCache(credProvider, tokenCacheKey, tokenCachePath);
|
||||
let accountProvider = new AzureAccountProvider(<AzureAccountProviderMetadata>provider.metadata, tokenCache);
|
||||
self._accountProviders[provider.metadata.id] = accountProvider;
|
||||
data.accounts.registerAccountProvider(provider.metadata, accountProvider);
|
||||
});
|
||||
})
|
||||
.then(() => { return true; });
|
||||
}
|
||||
|
||||
public dispose() { }
|
||||
|
||||
// PRIVATE HELPERS /////////////////////////////////////////////////////
|
||||
private onClearTokenCache(): Thenable<void> {
|
||||
let self = this;
|
||||
|
||||
let promises: Thenable<void>[] = providerSettings.map(provider => {
|
||||
return self._accountProviders[provider.metadata.id].clearTokenCache();
|
||||
});
|
||||
|
||||
return Promise.all(promises)
|
||||
.then(
|
||||
() => {
|
||||
let message = localize('clearTokenCacheSuccess', 'Token cache successfully cleared');
|
||||
vscode.window.showInformationMessage(`${constants.extensionName}: ${message}`);
|
||||
},
|
||||
err => {
|
||||
let message = localize('clearTokenCacheFailure', 'Failed to clear token cache');
|
||||
vscode.window.showErrorMessage(`${constants.extensionName}: ${message}: ${err}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,167 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import * as data from 'data';
|
||||
|
||||
/**
|
||||
* Represents a tenant (an Azure Active Directory instance) to which a user has access
|
||||
*/
|
||||
export interface Tenant {
|
||||
/**
|
||||
* Globally unique identifier of the tenant
|
||||
*/
|
||||
id: string;
|
||||
|
||||
/**
|
||||
* Display name of the tenant
|
||||
*/
|
||||
displayName: string;
|
||||
|
||||
/**
|
||||
* Identifier of the user in the tenant
|
||||
*/
|
||||
userId: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a resource exposed by an Azure Active Directory
|
||||
*/
|
||||
export interface Resource {
|
||||
/**
|
||||
* Identifier of the resource
|
||||
*/
|
||||
id: string;
|
||||
|
||||
/**
|
||||
* Endpoint url used to access the resource
|
||||
*/
|
||||
endpoint: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the arguments that identify an instantiation of the AAD account provider
|
||||
*/
|
||||
export interface Arguments {
|
||||
/**
|
||||
* Host of the authority
|
||||
*/
|
||||
host: string;
|
||||
|
||||
/**
|
||||
* Identifier of the client application
|
||||
*/
|
||||
clientId: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents settings for an AAD account provider
|
||||
*/
|
||||
export interface Settings {
|
||||
/**
|
||||
* Host of the authority
|
||||
*/
|
||||
host?: string;
|
||||
|
||||
/**
|
||||
* Identifier of the client application
|
||||
*/
|
||||
clientId?: string;
|
||||
|
||||
/**
|
||||
* Identifier of the resource to request when signing in
|
||||
*/
|
||||
signInResourceId?: string;
|
||||
|
||||
/**
|
||||
* Information that describes the AAD graph resource
|
||||
*/
|
||||
graphResource?: Resource;
|
||||
|
||||
/**
|
||||
* Information that describes the Azure resource management resource
|
||||
*/
|
||||
armResource?: Resource;
|
||||
|
||||
/**
|
||||
* A list of tenant IDs to authenticate against. If defined, then these IDs will be used
|
||||
* instead of querying the tenants endpoint of the armResource
|
||||
*/
|
||||
adTenants?: string[];
|
||||
|
||||
// AuthorizationCodeGrantFlowSettings //////////////////////////////////
|
||||
|
||||
/**
|
||||
* An optional site ID that brands the interactive aspect of sign in
|
||||
*/
|
||||
siteId?: string;
|
||||
|
||||
/**
|
||||
* Redirect URI that is used to signify the end of the interactive aspect of sign it
|
||||
*/
|
||||
redirectUri?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export interface AzureAccountProviderMetadata extends data.AccountProviderMetadata {
|
||||
/**
|
||||
* Azure specific account provider settings.
|
||||
*/
|
||||
settings: Settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Properties specific to an Azure account
|
||||
*/
|
||||
export interface AzureAccountProperties {
|
||||
/**
|
||||
* Whether or not the account is a Microsoft account
|
||||
*/
|
||||
isMsAccount: boolean;
|
||||
|
||||
/**
|
||||
* A list of tenants (aka directories) that the account belongs to
|
||||
*/
|
||||
tenants: Tenant[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Override of the Account type to enforce properties that are AzureAccountProperties
|
||||
*/
|
||||
export interface AzureAccount extends data.Account {
|
||||
/**
|
||||
* AzureAccountProperties specifically used for Azure accounts
|
||||
*/
|
||||
properties: AzureAccountProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Token returned from a request for an access token
|
||||
*/
|
||||
export interface AzureAccountSecurityToken {
|
||||
/**
|
||||
* Access token, itself
|
||||
*/
|
||||
token: string;
|
||||
|
||||
/**
|
||||
* Date that the token expires on
|
||||
*/
|
||||
expiresOn: Date;
|
||||
|
||||
/**
|
||||
* Name of the resource the token is good for (ie, management.core.windows.net)
|
||||
*/
|
||||
resource: string;
|
||||
|
||||
/**
|
||||
* Type of the token (pretty much always 'Bearer')
|
||||
*/
|
||||
tokenType: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Azure account security token maps a tenant ID to the information returned from a request to get
|
||||
* an access token. The list of tenants correspond to the tenants in the account properties.
|
||||
*/
|
||||
export type AzureAccountSecurityTokenCollection = {[tenantId: string]: AzureAccountSecurityToken};
|
||||
@@ -1 +0,0 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#f25022;}.cls-2{fill:#7fba00;}.cls-3{fill:#00a4ef;}.cls-4{fill:#ffb900;}</style></defs><title>microsoft_account_16x16</title><rect class="cls-1" width="7.6" height="7.6"/><rect class="cls-2" x="8.4" width="7.6" height="7.6"/><rect class="cls-3" y="8.4" width="7.6" height="7.6"/><rect class="cls-4" x="8.4" y="8.4" width="7.6" height="7.6"/></svg>
|
||||
|
Before Width: | Height: | Size: 465 B |
@@ -1 +0,0 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><title>other_account_16x16</title><path d="M8,.28A7.71,7.71,0,1,0,15.72,8,7.73,7.73,0,0,0,8,.28ZM4.2,13.53a4,4,0,0,1,.13-.93,3.69,3.69,0,0,1,1-1.66A3.56,3.56,0,0,1,6,10.36a4,4,0,0,1,.9-.38,4.17,4.17,0,0,1,1-.13,3.79,3.79,0,0,1,1.48.29,3.61,3.61,0,0,1,2,2,3.74,3.74,0,0,1,.29,1.47A6.62,6.62,0,0,1,8,14.71,6.71,6.71,0,0,1,4.2,13.53Zm2-5a2.76,2.76,0,0,1-.54-.79,2.43,2.43,0,0,1-.19-1,2.4,2.4,0,0,1,.19-1A2.82,2.82,0,0,1,6.18,5,2.81,2.81,0,0,1,7,4.42a2.4,2.4,0,0,1,1-.19,2.43,2.43,0,0,1,1,.19A2.76,2.76,0,0,1,9.71,5a2.46,2.46,0,0,1,.54.8,2.4,2.4,0,0,1,.2,1,2.44,2.44,0,0,1-.2,1A2.59,2.59,0,0,1,8.92,9a2.44,2.44,0,0,1-1,.2A2.4,2.4,0,0,1,7,9,2.46,2.46,0,0,1,6.18,8.49Zm6.12,4.66a4.39,4.39,0,0,0-.18-.89,4.22,4.22,0,0,0-.57-1.19A4.24,4.24,0,0,0,9.44,9.48a3.41,3.41,0,0,0,.68-.5A3.36,3.36,0,0,0,11,7.56a3.32,3.32,0,0,0,.11-.83,3.09,3.09,0,0,0-.24-1.22,3.26,3.26,0,0,0-.67-1,3,3,0,0,0-1-.67A3,3,0,0,0,7.95,3.6a2.93,2.93,0,0,0-1.22.25A3.07,3.07,0,0,0,5.07,5.51a2.93,2.93,0,0,0-.25,1.22,3,3,0,0,0,.12.84,3,3,0,0,0,.32.76A3.3,3.3,0,0,0,5.78,9a3.06,3.06,0,0,0,.68.5,4.41,4.41,0,0,0-1.19.65,4.1,4.1,0,0,0-.91,1,4.18,4.18,0,0,0-.58,1.18,4.41,4.41,0,0,0-.18.8A6.66,6.66,0,0,1,1.28,8a6.72,6.72,0,1,1,11,5.15Z"/></svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -1 +0,0 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#fff;}</style></defs><title>other_account_inverse_16x16</title><path class="cls-1" d="M7.92.29A7.71,7.71,0,1,0,15.64,8,7.73,7.73,0,0,0,7.92.29ZM4.12,13.54a4,4,0,0,1,.13-.93,3.69,3.69,0,0,1,1-1.66A3.56,3.56,0,0,1,6,10.37a4,4,0,0,1,.9-.38,4.17,4.17,0,0,1,1-.13,3.79,3.79,0,0,1,1.48.29,3.61,3.61,0,0,1,2,2,3.74,3.74,0,0,1,.29,1.47,6.62,6.62,0,0,1-3.7,1.12A6.71,6.71,0,0,1,4.12,13.54Zm2-5a2.76,2.76,0,0,1-.54-.79,2.43,2.43,0,0,1-.19-1,2.4,2.4,0,0,1,.19-1A2.82,2.82,0,0,1,6.1,5a2.81,2.81,0,0,1,.8-.54,2.4,2.4,0,0,1,1-.19,2.43,2.43,0,0,1,1,.19A2.76,2.76,0,0,1,9.63,5a2.46,2.46,0,0,1,.54.8,2.4,2.4,0,0,1,.2,1,2.44,2.44,0,0,1-.2,1A2.59,2.59,0,0,1,8.84,9a2.44,2.44,0,0,1-1,.2,2.4,2.4,0,0,1-1-.2A2.46,2.46,0,0,1,6.1,8.49Zm6.12,4.66a4.39,4.39,0,0,0-.18-.89,4.22,4.22,0,0,0-.57-1.19A4.24,4.24,0,0,0,9.36,9.49,3.41,3.41,0,0,0,10,9a3.36,3.36,0,0,0,.84-1.42A3.32,3.32,0,0,0,11,6.74a3.09,3.09,0,0,0-.24-1.22,3.26,3.26,0,0,0-.67-1,3,3,0,0,0-1-.67,3,3,0,0,0-1.22-.25,2.93,2.93,0,0,0-1.22.25A3.07,3.07,0,0,0,5,5.51a2.93,2.93,0,0,0-.25,1.22,3,3,0,0,0,.12.84,3,3,0,0,0,.32.76A3.3,3.3,0,0,0,5.7,9a3.06,3.06,0,0,0,.68.5,4.41,4.41,0,0,0-1.19.65,4.1,4.1,0,0,0-.91,1,4.18,4.18,0,0,0-.58,1.18,4.41,4.41,0,0,0-.18.8A6.66,6.66,0,0,1,1.2,8a6.72,6.72,0,1,1,11,5.15Z"/></svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -1,102 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as data from 'data';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { Settings } from './interfaces';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
const publicAzureSettings = {
|
||||
configKey: 'accounts.azure.enablePublicCloud',
|
||||
metadata: <data.AccountProviderMetadata> {
|
||||
displayName: localize('publicCloudDisplayName', 'Azure'),
|
||||
id: 'azurePublicCloud',
|
||||
settings: <Settings>{
|
||||
host: 'https://login.microsoftonline.com',
|
||||
clientId: 'TBD',
|
||||
signInResourceId: 'https://management.core.windows.net/',
|
||||
graphResource: {
|
||||
id: 'https://graph.windows.net/',
|
||||
endpoint: 'https://graph.windows.net'
|
||||
},
|
||||
armResource: {
|
||||
id: 'https://management.core.windows.net/',
|
||||
endpoint: 'https://management.azure.com'
|
||||
},
|
||||
redirectUri: 'http://localhost/redirect'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const usGovAzureSettings = {
|
||||
configKey: 'accounts.azure.enableUsGovCloud',
|
||||
metadata: <data.AccountProviderMetadata> {
|
||||
displayName: localize('usGovCloudDisplayName', 'Azure (US Government)'),
|
||||
id: 'usGovAzureCloud',
|
||||
settings: <Settings> {
|
||||
host: 'https://login.microsoftonline.com/',
|
||||
clientId: 'TBD',
|
||||
signInResourceId: 'https://management.core.usgovcloudapi.net/',
|
||||
graphResource: {
|
||||
id: 'https://graph.usgovcloudapi.net/',
|
||||
endpoint: 'https://graph.usgovcloudapi.net'
|
||||
},
|
||||
armResource: {
|
||||
id: 'https://management.core.usgovcloudapi.net/',
|
||||
endpoint: 'https://management.usgovcloudapi.net'
|
||||
},
|
||||
redirectUri: 'http://localhost/redirect'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const chinaAzureSettings = {
|
||||
configKey: 'accounts.azure.enableChinaCloud',
|
||||
metadata: <data.AccountProviderMetadata> {
|
||||
displayName: localize('chinaCloudDisplayName', 'Azure (China)'),
|
||||
id: 'chinaAzureCloud',
|
||||
settings: <Settings> {
|
||||
host: 'https://login.chinacloudapi.cn/',
|
||||
clientId: 'TBD',
|
||||
signInResourceId: 'https://management.core.chinacloudapi.cn/',
|
||||
graphResource: {
|
||||
id: 'https://graph.chinacloudapi.cn/',
|
||||
endpoint: 'https://graph.chinacloudapi.cn'
|
||||
},
|
||||
armResource: {
|
||||
id: 'https://management.core.chinacloudapi.cn/',
|
||||
endpoint: 'https://managemement.chinacloudapi.net'
|
||||
},
|
||||
redirectUri: 'http://localhost/redirect'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const germanyAzureSettings = {
|
||||
configKey: 'accounts.azure.enableGermanyCloud',
|
||||
metadata: <data.AccountProviderMetadata> {
|
||||
displayName: localize('germanyCloud', 'Azure (Germany)'),
|
||||
id: 'germanyAzureCloud',
|
||||
settings: <Settings> {
|
||||
host: 'https://login.microsoftazure.de/',
|
||||
clientId: 'TBD',
|
||||
signInResourceId: 'https://management.core.cloudapi.de/',
|
||||
graphResource: {
|
||||
id: 'https://graph.cloudapi.de/',
|
||||
endpoint: 'https://graph.cloudapi.de'
|
||||
},
|
||||
armResource: {
|
||||
id: 'https://management.core.cloudapi.de/',
|
||||
endpoint: 'https://management.microsoftazure.de'
|
||||
},
|
||||
redirectUri: 'http://localhost/redirect'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default [publicAzureSettings/*, chinaAzureSettings, germanyAzureSettings, usGovAzureSettings*/];
|
||||
@@ -1,244 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as adal from 'adal-node';
|
||||
import * as data from 'data';
|
||||
import * as crypto from 'crypto';
|
||||
import * as fs from 'fs';
|
||||
|
||||
export default class TokenCache implements adal.TokenCache {
|
||||
private static CipherAlgorithm = 'aes256';
|
||||
private static CipherAlgorithmIvLength = 16;
|
||||
private static CipherKeyLength = 32;
|
||||
private static FsOptions = { encoding: 'ascii' };
|
||||
|
||||
private _activeOperation: Thenable<any>;
|
||||
|
||||
constructor(
|
||||
private _credentialProvider: data.CredentialProvider,
|
||||
private _credentialServiceKey: string,
|
||||
private _cacheSerializationPath: string
|
||||
) {
|
||||
}
|
||||
|
||||
// PUBLIC METHODS //////////////////////////////////////////////////////
|
||||
public add(entries: adal.TokenCacheEntry[], callback: (error?: Error) => void): void {
|
||||
let self = this;
|
||||
|
||||
this.doOperation(() => {
|
||||
return self.readCache()
|
||||
.then(cache => self.addToCache(cache, entries))
|
||||
.then(updatedCache => self.writeCache(updatedCache))
|
||||
.then(
|
||||
() => callback(null),
|
||||
(err) => callback(err)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
public clear(): Thenable<void> {
|
||||
let self = this;
|
||||
|
||||
// 1) Delete encrypted serialization file
|
||||
// If we got an 'ENOENT' response, the file doesn't exist, which is fine
|
||||
// 3) Delete the encryption key
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
fs.unlink(self._cacheSerializationPath, err => {
|
||||
if (err && err.code !== 'ENOENT') {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
})
|
||||
.then(() => { return self._credentialProvider.deleteCredential(self._credentialServiceKey); })
|
||||
.then(() => {});
|
||||
}
|
||||
|
||||
public find(query: adal.TokenCacheQuery, callback: (error: Error, results: adal.TokenCacheEntry[]) => void): void {
|
||||
let self = this;
|
||||
|
||||
this.doOperation(() => {
|
||||
return self.readCache()
|
||||
.then(cache => {
|
||||
return cache.filter(
|
||||
entry => TokenCache.findByPartial(entry, query)
|
||||
);
|
||||
})
|
||||
.then(
|
||||
results => callback(null, results),
|
||||
(err) => callback(err, null)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
public remove(entries: adal.TokenCacheEntry[], callback: (error?: Error) => void): void {
|
||||
let self = this;
|
||||
|
||||
this.doOperation(() => {
|
||||
return this.readCache()
|
||||
.then(cache => self.removeFromCache(cache, entries))
|
||||
.then(updatedCache => self.writeCache(updatedCache))
|
||||
.then(
|
||||
() => callback(null),
|
||||
(err) => callback(err)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// PRIVATE METHODS /////////////////////////////////////////////////////
|
||||
private static findByKeyHelper(entry1: adal.TokenCacheEntry, entry2: adal.TokenCacheEntry): boolean {
|
||||
return entry1._authority === entry2._authority
|
||||
&& entry1._clientId === entry2._clientId
|
||||
&& entry1.userId === entry2.userId
|
||||
&& entry1.resource === entry2.resource;
|
||||
}
|
||||
|
||||
private static findByPartial(entry: adal.TokenCacheEntry, query: object): boolean {
|
||||
for (let key in query) {
|
||||
if (entry[key] === undefined || entry[key] !== query[key]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private doOperation<T>(op: () => Thenable<T>): void {
|
||||
// Initialize the active operation to an empty promise if necessary
|
||||
let activeOperation = this._activeOperation || Promise.resolve<any>(null);
|
||||
|
||||
// Chain the operation to perform to the end of the existing promise
|
||||
activeOperation = activeOperation.then(op);
|
||||
|
||||
// Add a catch at the end to make sure we can continue after any errors
|
||||
activeOperation = activeOperation.then(null, err => {
|
||||
console.error(`Failed to perform token cache operation: ${err}`);
|
||||
});
|
||||
|
||||
// Point the current active operation to this one
|
||||
this._activeOperation = activeOperation;
|
||||
}
|
||||
|
||||
private addToCache(cache: adal.TokenCacheEntry[], entries: adal.TokenCacheEntry[]): adal.TokenCacheEntry[] {
|
||||
// First remove entries from the db that are being updated
|
||||
cache = this.removeFromCache(cache, entries);
|
||||
|
||||
// Then add the new entries to the cache
|
||||
entries.forEach((entry: adal.TokenCacheEntry) => {
|
||||
cache.push(entry);
|
||||
});
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
private getOrCreateEncryptionParams(): Thenable<EncryptionParams> {
|
||||
let self = this;
|
||||
|
||||
return this._credentialProvider.readCredential(this._credentialServiceKey)
|
||||
.then(credential => {
|
||||
if (credential.password) {
|
||||
// We already have encryption params, deserialize them
|
||||
let splitValues = credential.password.split('|');
|
||||
if (splitValues.length === 2 && splitValues[0] && splitValues[1]) {
|
||||
try {
|
||||
return <EncryptionParams>{
|
||||
key: new Buffer(splitValues[0], 'hex'),
|
||||
initializationVector: new Buffer(splitValues[1], 'hex')
|
||||
};
|
||||
} catch(e) {
|
||||
// Swallow the error and fall through to generate new params
|
||||
console.warn('Failed to deserialize encryption params, new ones will be generated.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We haven't stored encryption values, so generate them
|
||||
let encryptKey = crypto.randomBytes(TokenCache.CipherKeyLength);
|
||||
let initializationVector = crypto.randomBytes(TokenCache.CipherAlgorithmIvLength);
|
||||
|
||||
// Serialize the values
|
||||
let serializedValues = `${encryptKey.toString('hex')}|${initializationVector.toString('hex')}`;
|
||||
return self._credentialProvider.saveCredential(self._credentialServiceKey, serializedValues)
|
||||
.then(() => {
|
||||
return <EncryptionParams> {
|
||||
key: encryptKey,
|
||||
initializationVector: initializationVector
|
||||
};
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private readCache(): Thenable<adal.TokenCacheEntry[]> {
|
||||
let self = this;
|
||||
|
||||
// NOTE: File system operations are performed synchronously to avoid annoying nested callbacks
|
||||
// 1) Get the encryption key
|
||||
// 2) Read the encrypted token cache file
|
||||
// 3) Decrypt the file contents
|
||||
// 4) Deserialize and return
|
||||
return this.getOrCreateEncryptionParams()
|
||||
.then(encryptionParams => {
|
||||
try {
|
||||
let cacheCipher = fs.readFileSync(self._cacheSerializationPath, TokenCache.FsOptions);
|
||||
|
||||
let decipher = crypto.createDecipheriv(TokenCache.CipherAlgorithm, encryptionParams.key, encryptionParams.initializationVector);
|
||||
let cacheJson = decipher.update(cacheCipher, 'hex', 'binary');
|
||||
cacheJson += decipher.final('binary');
|
||||
|
||||
return JSON.parse(cacheJson);
|
||||
} catch(e) {
|
||||
throw e;
|
||||
}
|
||||
})
|
||||
.then(null, err => {
|
||||
// If reading the token cache fails, we'll just assume the tokens are garbage
|
||||
console.warn(`Failed to read token cache: ${err}`);
|
||||
return [];
|
||||
});
|
||||
}
|
||||
|
||||
private removeFromCache(cache: adal.TokenCacheEntry[], entries: adal.TokenCacheEntry[]): adal.TokenCacheEntry[] {
|
||||
entries.forEach((entry: adal.TokenCacheEntry) => {
|
||||
// Check to see if the entry exists
|
||||
let match = cache.findIndex(entry2 => TokenCache.findByKeyHelper(entry, entry2));
|
||||
if (match >= 0) {
|
||||
// Entry exists, remove it from cache
|
||||
cache.splice(match, 1);
|
||||
}
|
||||
});
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
private writeCache(cache: adal.TokenCacheEntry[]): Thenable<void> {
|
||||
let self = this;
|
||||
// NOTE: File system operations are being done synchronously to avoid annoying callback nesting
|
||||
// 1) Get (or generate) the encryption key
|
||||
// 2) Stringify the token cache entries
|
||||
// 4) Encrypt the JSON
|
||||
// 3) Write to the file
|
||||
return this.getOrCreateEncryptionParams()
|
||||
.then(encryptionParams => {
|
||||
try {
|
||||
let cacheJson = JSON.stringify(cache);
|
||||
|
||||
let cipher = crypto.createCipheriv(TokenCache.CipherAlgorithm, encryptionParams.key, encryptionParams.initializationVector);
|
||||
let cacheCipher = cipher.update(cacheJson, 'binary', 'hex');
|
||||
cacheCipher += cipher.final('hex');
|
||||
|
||||
fs.writeFileSync(self._cacheSerializationPath, cacheCipher, TokenCache.FsOptions);
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
interface EncryptionParams {
|
||||
key: Buffer;
|
||||
initializationVector: Buffer;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as nls from 'vscode-nls';
|
||||
|
||||
let localize = nls.loadMessageBundle();
|
||||
|
||||
export const extensionName = localize('extensionName', 'Azure Accounts');
|
||||
@@ -1,35 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as vscode from 'vscode';
|
||||
import { Utils } from 'extensions-modules';
|
||||
|
||||
import * as constants from './constants';
|
||||
import { AzureAccountProviderService } from './account-provider/azureAccountProviderService';
|
||||
|
||||
// EXTENSION ACTIVATION ////////////////////////////////////////////////////
|
||||
export function activate(context: vscode.ExtensionContext): void {
|
||||
// Create the folder for storing the token caches
|
||||
let storagePath = path.join(Utils.getDefaultLogLocation(), constants.extensionName);
|
||||
try {
|
||||
if (!fs.existsSync(storagePath)) {
|
||||
fs.mkdirSync(storagePath);
|
||||
console.log('Initialized Azure account extension storage.');
|
||||
}
|
||||
} catch(e) {
|
||||
console.error(`Initialization of Azure account extension storage failed: ${e}`);
|
||||
console.error('Azure accounts will not be available');
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the provider service and activate
|
||||
const accountProviderService = new AzureAccountProviderService(context, storagePath);
|
||||
context.subscriptions.push(accountProviderService);
|
||||
accountProviderService.activate();
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
/// <reference path='../../../../src/vs/vscode.d.ts'/>
|
||||
/// <reference path='../../../../src/sql/data.d.ts'/>
|
||||
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"compileOnSave": true,
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es6",
|
||||
"outDir": "./out",
|
||||
"lib": [
|
||||
"es6", "es2015.promise"
|
||||
],
|
||||
"sourceMap": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"moduleResolution": "node",
|
||||
"declaration": true,
|
||||
"types": ["node"]
|
||||
},
|
||||
"exclude": [
|
||||
"./node_modules"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user