-
Notifications
You must be signed in to change notification settings - Fork 2.7k
[msal-extensions] Extensions #2 #1831
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 3 commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
c76184b
Add cross process lock
4d76e66
Add constants file
c6aed94
Add error and index.ts
32dbf1e
Add persistence
c20c3b8
Add extensions sample
fad64e0
Update sample
1613a1c
Add comments
d21dd3b
Add logger. Updated README and .gitignore
57b828a
Merge branch 'extensions-1' into extensions-2
f235394
PR feedback
3c7e079
Merge branch 'extensions-2' into extensions-3
8ea2716
PR Feedback
cc5e014
Merge branch 'extensions-3' into extensions-4
1677c32
Merge branch 'extensions-4' into extensions-5
2a88748
Add tests
94c62db
Add performance tests
6805e75
Merge pull request #1849 from AzureAD/extensions-6
sangonzal a5aab6f
Merge pull request #1835 from AzureAD/extensions-5
sangonzal 2724b79
Merge pull request #1833 from AzureAD/extensions-4
sangonzal 2a50811
Merge pull request #1832 from AzureAD/extensions-3
sangonzal File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/* | ||
* Copyright (c) Microsoft Corporation. All rights reserved. | ||
* Licensed under the MIT License. | ||
*/ | ||
|
||
/** | ||
* Error thrown when trying to write MSAL cache to persistence. | ||
*/ | ||
export class PersistenceError extends Error { | ||
|
||
// Short string denoting error | ||
errorCode: string; | ||
// Detailed description of error | ||
errorMessage: string; | ||
|
||
constructor(errorCode: string, errorMessage: string) { | ||
const errorString = errorMessage ? `${errorCode}: ${errorMessage}` : errorCode; | ||
super(errorString); | ||
Object.setPrototypeOf(this, PersistenceError.prototype); | ||
|
||
this.errorCode = errorCode; | ||
this.errorMessage = errorMessage; | ||
this.name = "PersistenceError"; | ||
} | ||
|
||
static createFileSystemError(errorCode: string, errorMessage: string): PersistenceError { | ||
sangonzal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return new PersistenceError(errorCode, errorMessage); | ||
} | ||
|
||
static createLibSecretError(errorCode: string, errorMessage: string): PersistenceError { | ||
const updatedErrorMessage = `Error accessing Gnome Keyring: ${errorCode}- ${errorMessage}`; | ||
return new PersistenceError("GnomeKeyringError", updatedErrorMessage); | ||
} | ||
|
||
static createKeychainPersistenceError(errorCode: string, errorMessage: string): PersistenceError { | ||
const updatedErrorMessage = `Error accessing Keychain: ${errorCode}- ${errorMessage}`; | ||
return new PersistenceError("KeychainError", updatedErrorMessage); | ||
} | ||
|
||
static createFilePersistenceWithDPAPIError(errorCode: string,errorMessage: string): PersistenceError { | ||
const updatedErrorMessage = `Error accessing DPAPI encrypted file: ${errorCode}- ${errorMessage}`; | ||
return new PersistenceError("DPAPIEncryptedFileError", updatedErrorMessage); | ||
} | ||
|
||
static createCrossPlatformLockError(errorCode: string, errorMessage: string): PersistenceError { | ||
const updatedErrorMessage = `Error acquiring lock: ${errorCode}- ${errorMessage}`; | ||
return new PersistenceError("CrossPlatformLockError", updatedErrorMessage); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export { PersistenceCachePlugin } from "./persistence/PersistenceCachePlugin" | ||
export { FilePersistence } from "./persistence/FilePersistence"; | ||
export { FilePersistenceWithDataProtection } from "./persistence/FilePersistenceWithDataProtection"; | ||
export { DataProtectionScope } from "./persistence/DataProtectionScope"; | ||
export { KeychainPersistence } from "./persistence/KeychainPersistence"; | ||
export { LibSecretPersistence } from "./persistence/LibSecretPersistence"; | ||
export { IPersistence } from "./persistence/IPersistence"; | ||
export { CrossPlatformLockOptions } from "./lock/CrossPlatformLockOptions"; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/* | ||
* Copyright (c) Microsoft Corporation. All rights reserved. | ||
* Licensed under the MIT License. | ||
*/ | ||
|
||
import { open, close, write, unlink } from "fs"; | ||
import { promisify } from "util"; | ||
import { pid } from "process"; | ||
import { CrossPlatformLockOptions } from "./CrossPlatformLockOptions"; | ||
import { Constants } from "../utils/Constants"; | ||
import { PersistenceError } from "../error/PersistenceError"; | ||
|
||
/** | ||
* Cross-process lock that works on all platforms. | ||
*/ | ||
export class CrossPlatformLock { | ||
|
||
private readonly lockFilePath: string; | ||
private lockFileDescriptor: number; | ||
private readonly retryNumber: number; | ||
private readonly retryDelay: number; | ||
|
||
constructor(lockFilePath:string, lockOptions?: CrossPlatformLockOptions) { | ||
this.lockFilePath = lockFilePath; | ||
this.retryNumber = lockOptions ? lockOptions.retryNumber : 500; | ||
this.retryDelay = lockOptions ? lockOptions.retryDelay : 100; | ||
} | ||
|
||
/** | ||
* Locks cache from read or writes by creating file with same path and name as | ||
* cache file but with .lockfile extension. If another process has already created | ||
* the lockfile, will retry again based on configuration settings set by CrossPlatformLockOptions | ||
*/ | ||
public async lock(): Promise<void> { | ||
const processId = pid.toString(); | ||
for (let tryCount = 0; tryCount < this.retryNumber; tryCount++) | ||
try { | ||
console.log("Pid " + pid + " trying to acquire lock"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Every console.log statement will be switched over to using the msal-common logger in upcoming PR |
||
const openPromise = promisify(open); | ||
sangonzal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
this.lockFileDescriptor = await openPromise(this.lockFilePath, "wx+"); | ||
|
||
console.log("Pid " + pid + " acquired lock"); | ||
const writePromise = promisify(write); | ||
await writePromise(this.lockFileDescriptor, processId); | ||
break; | ||
} catch (err) { | ||
if (err.code == Constants.EEXIST_ERROR) { | ||
console.log(err); | ||
await this.sleep(this.retryDelay); | ||
} else { | ||
throw PersistenceError.createCrossPlatformLockError(err.code, err.message); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* unlocks cache file by deleting .lockfile. | ||
*/ | ||
public async unlock(): Promise<void> { | ||
try { | ||
// delete lock file | ||
const unlinkPromise = promisify(unlink); | ||
await unlinkPromise(this.lockFilePath); | ||
const closePromise = promisify(close); | ||
await closePromise(this.lockFileDescriptor); | ||
} catch(err){ | ||
if(err.code == Constants.ENOENT_ERROR){ | ||
console.log("Lockfile does not exist"); | ||
} else { | ||
throw PersistenceError.createCrossPlatformLockError(err.code, err.message); | ||
} | ||
} | ||
} | ||
|
||
private sleep(ms): Promise<void> { | ||
return new Promise((resolve) => { | ||
setTimeout(resolve, ms); | ||
}); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/* | ||
* Copyright (c) Microsoft Corporation. All rights reserved. | ||
* Licensed under the MIT License. | ||
*/ | ||
|
||
/** | ||
* Options for CrossPlatform lock. | ||
* | ||
* retryNumber: Numbers of times we should try to acquire a lock. Defaults to 500. | ||
* retryDelay: Time to wait before trying to retry a lock acquisition. Defaults to 100 ms. | ||
*/ | ||
export type CrossPlatformLockOptions = { | ||
retryNumber: number; | ||
retryDelay: number; | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/* | ||
* Copyright (c) Microsoft Corporation. All rights reserved. | ||
* Licensed under the MIT License. | ||
*/ | ||
|
||
export const Constants = { | ||
|
||
/** | ||
* An existing file was the target of an operation that required that the target not exist | ||
*/ | ||
EEXIST_ERROR: "EEXIST", | ||
|
||
/** | ||
* No such file or directory: Commonly raised by fs operations to indicate that a component | ||
* of the specified pathname does not exist. No entity (file or directory) could be found | ||
* by the given path | ||
*/ | ||
ENOENT_ERROR: "ENOENT", | ||
|
||
/** | ||
* Default service name for using MSAL Keytar | ||
*/ | ||
DEFAULT_SERVICE_NAME: "msal-node-extensions", | ||
}; |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.