Implement a no sync rule (#7216)

* implement a no sync rule

* fix linting disable

* fix unused imports

* exclude more testing

* clean up fs usage

* clean up more fs usage

* remove duplicate of code

* fix compile errors
This commit is contained in:
Anthony Dresser
2019-09-17 13:32:42 -07:00
committed by GitHub
parent 4d62983680
commit 28d453fced
31 changed files with 305 additions and 201 deletions

View File

@@ -6,7 +6,7 @@
import * as adal from 'adal-node';
import * as azdata from 'azdata';
import * as crypto from 'crypto';
import * as fs from 'fs';
import { promises as fs } from 'fs';
export default class TokenCache implements adal.TokenCache {
private static CipherAlgorithm = 'aes-256-cbc';
@@ -58,23 +58,19 @@ export default class TokenCache implements adal.TokenCache {
});
}
public clear(): Thenable<void> {
let self = this;
public async clear(): Promise<void> {
// 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(() => { });
try {
await fs.unlink(this._cacheSerializationPath);
} catch (err) {
if (err.code !== 'ENOENT') {
throw err;
}
}
await this._credentialProvider.deleteCredential(this._credentialServiceKey);
}
public find(query: any, callback: (error: Error, results: any[]) => void): void {
@@ -230,7 +226,7 @@ export default class TokenCache implements adal.TokenCache {
});
}
private readCache(): Thenable<adal.TokenResponse[]> {
private async readCache(): Promise<adal.TokenResponse[]> {
let self = this;
// NOTE: File system operations are performed synchronously to avoid annoying nested callbacks
@@ -239,13 +235,13 @@ export default class TokenCache implements adal.TokenCache {
// 3) Decrypt the file contents
// 4) Deserialize and return
return this.getOrCreateEncryptionParams()
.then(encryptionParams => {
.then(async encryptionParams => {
try {
return self.decryptCache('utf8', encryptionParams);
} catch (e) {
try {
// try to parse using 'binary' encoding and rewrite cache as UTF8
let response = self.decryptCache('binary', encryptionParams);
let response = await self.decryptCache('binary', encryptionParams);
self.writeCache(response);
return response;
} catch (e) {
@@ -260,17 +256,17 @@ export default class TokenCache implements adal.TokenCache {
});
}
private decryptCache(encoding: crypto.Utf8AsciiBinaryEncoding, encryptionParams: EncryptionParams): adal.TokenResponse[] {
let cacheCipher = fs.readFileSync(this._cacheSerializationPath, TokenCache.FsOptions);
private async decryptCache(encoding: crypto.Utf8AsciiBinaryEncoding, encryptionParams: EncryptionParams): Promise<adal.TokenResponse[]> {
let cacheCipher = await fs.readFile(this._cacheSerializationPath, TokenCache.FsOptions);
let decipher = crypto.createDecipheriv(TokenCache.CipherAlgorithm, encryptionParams.key, encryptionParams.initializationVector);
let cacheJson = decipher.update(cacheCipher, 'hex', encoding);
let cacheJson = decipher.update(cacheCipher.toString(), 'hex', encoding);
cacheJson += decipher.final(encoding);
// Deserialize the JSON into the array of tokens
let cacheObj = <adal.TokenResponse[]>JSON.parse(cacheJson);
for (let objIndex in cacheObj) {
for (const obj of cacheObj) {
// Rehydrate Date objects since they will always serialize as a string
cacheObj[objIndex].expiresOn = new Date(<string>cacheObj[objIndex].expiresOn);
obj.expiresOn = new Date(<string>obj.expiresOn);
}
return cacheObj;
@@ -297,7 +293,7 @@ export default class TokenCache implements adal.TokenCache {
// 4) Encrypt the JSON
// 3) Write to the file
return this.getOrCreateEncryptionParams()
.then(encryptionParams => {
.then(async encryptionParams => {
try {
let cacheJson = JSON.stringify(cache);
@@ -305,7 +301,7 @@ export default class TokenCache implements adal.TokenCache {
let cacheCipher = cipher.update(cacheJson, 'utf8', 'hex');
cacheCipher += cipher.final('hex');
fs.writeFileSync(self._cacheSerializationPath, cacheCipher, TokenCache.FsOptions);
await fs.writeFile(self._cacheSerializationPath, cacheCipher, TokenCache.FsOptions);
} catch (e) {
throw e;
}