@azure/msal-node-extensions 1.0.0-alpha.3 → 1.0.0-alpha.30
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/README.md +156 -5
- package/binding.gyp +11 -1
- package/dist/{dpapi-addon/Dpapi.d.ts → Dpapi.d.ts} +0 -0
- package/dist/error/PersistenceError.d.ts +28 -0
- package/dist/index.d.ts +3 -0
- package/dist/msal-node-extensions.cjs.development.js +603 -859
- package/dist/msal-node-extensions.cjs.development.js.map +1 -1
- package/dist/msal-node-extensions.cjs.production.min.js +1 -1
- package/dist/msal-node-extensions.cjs.production.min.js.map +1 -1
- package/dist/msal-node-extensions.esm.js +613 -874
- package/dist/msal-node-extensions.esm.js.map +1 -1
- package/dist/packageMetadata.d.ts +2 -0
- package/dist/persistence/BasePersistence.d.ts +5 -0
- package/dist/persistence/FilePersistence.d.ts +4 -2
- package/dist/persistence/FilePersistenceWithDataProtection.d.ts +3 -1
- package/dist/persistence/IPersistence.d.ts +3 -1
- package/dist/persistence/IPersistenceConfiguration.d.ts +10 -0
- package/dist/persistence/KeychainPersistence.d.ts +3 -1
- package/dist/persistence/LibSecretPersistence.d.ts +3 -1
- package/dist/persistence/PersistenceCachePlugin.d.ts +11 -7
- package/dist/persistence/PersistenceCreator.d.ts +5 -0
- package/dist/utils/Constants.d.ts +26 -0
- package/dist/utils/Environment.d.ts +16 -0
- package/package.json +27 -15
- package/src/{dpapi-addon/Dpapi.ts → Dpapi.ts} +12 -12
- package/src/dpapi-addon/dpapi_addon.h +2 -1
- package/src/dpapi-addon/dpapi_not_supported.cpp +4 -10
- package/src/dpapi-addon/dpapi_win.cpp +25 -33
- package/src/dpapi-addon/main.cpp +14 -16
- package/src/error/PersistenceError.ts +101 -61
- package/src/index.ts +16 -8
- package/src/lock/CrossPlatformLock.ts +89 -89
- package/src/lock/CrossPlatformLockOptions.ts +15 -15
- package/src/packageMetadata.ts +3 -0
- package/src/persistence/BasePersistence.ts +43 -0
- package/src/persistence/FilePersistence.ts +140 -134
- package/src/persistence/FilePersistenceWithDataProtection.ts +92 -84
- package/src/persistence/IPersistence.ts +4 -2
- package/src/persistence/IPersistenceConfiguration.ts +17 -0
- package/src/persistence/KeychainPersistence.ts +89 -78
- package/src/persistence/LibSecretPersistence.ts +90 -79
- package/src/persistence/PersistenceCachePlugin.ts +40 -30
- package/src/persistence/PersistenceCreator.ts +78 -0
- package/src/utils/Constants.ts +62 -30
- package/src/utils/Environment.ts +101 -0
- package/CHANGELOG.json +0 -50
- package/changelog.md +0 -28
|
@@ -1,200 +1,14 @@
|
|
|
1
1
|
import { promises } from 'fs';
|
|
2
2
|
import { pid } from 'process';
|
|
3
|
-
import { dirname } from 'path';
|
|
4
|
-
import { Logger, LogLevel } from '@azure/msal-common';
|
|
3
|
+
import path, { dirname } from 'path';
|
|
4
|
+
import { Logger, LogLevel, StringUtils } from '@azure/msal-common';
|
|
5
5
|
import { setPassword, getPassword, deletePassword } from 'keytar';
|
|
6
6
|
|
|
7
|
-
// A type of promise-like that resolves synchronously and supports only one observer
|
|
8
|
-
const _Pact = /*#__PURE__*/(function() {
|
|
9
|
-
function _Pact() {}
|
|
10
|
-
_Pact.prototype.then = function(onFulfilled, onRejected) {
|
|
11
|
-
const result = new _Pact();
|
|
12
|
-
const state = this.s;
|
|
13
|
-
if (state) {
|
|
14
|
-
const callback = state & 1 ? onFulfilled : onRejected;
|
|
15
|
-
if (callback) {
|
|
16
|
-
try {
|
|
17
|
-
_settle(result, 1, callback(this.v));
|
|
18
|
-
} catch (e) {
|
|
19
|
-
_settle(result, 2, e);
|
|
20
|
-
}
|
|
21
|
-
return result;
|
|
22
|
-
} else {
|
|
23
|
-
return this;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
this.o = function(_this) {
|
|
27
|
-
try {
|
|
28
|
-
const value = _this.v;
|
|
29
|
-
if (_this.s & 1) {
|
|
30
|
-
_settle(result, 1, onFulfilled ? onFulfilled(value) : value);
|
|
31
|
-
} else if (onRejected) {
|
|
32
|
-
_settle(result, 1, onRejected(value));
|
|
33
|
-
} else {
|
|
34
|
-
_settle(result, 2, value);
|
|
35
|
-
}
|
|
36
|
-
} catch (e) {
|
|
37
|
-
_settle(result, 2, e);
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
return result;
|
|
41
|
-
};
|
|
42
|
-
return _Pact;
|
|
43
|
-
})();
|
|
44
|
-
|
|
45
|
-
// Settles a pact synchronously
|
|
46
|
-
function _settle(pact, state, value) {
|
|
47
|
-
if (!pact.s) {
|
|
48
|
-
if (value instanceof _Pact) {
|
|
49
|
-
if (value.s) {
|
|
50
|
-
if (state & 1) {
|
|
51
|
-
state = value.s;
|
|
52
|
-
}
|
|
53
|
-
value = value.v;
|
|
54
|
-
} else {
|
|
55
|
-
value.o = _settle.bind(null, pact, state);
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
if (value && value.then) {
|
|
60
|
-
value.then(_settle.bind(null, pact, state), _settle.bind(null, pact, 2));
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
pact.s = state;
|
|
64
|
-
pact.v = value;
|
|
65
|
-
const observer = pact.o;
|
|
66
|
-
if (observer) {
|
|
67
|
-
observer(pact);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function _isSettledPact(thenable) {
|
|
73
|
-
return thenable instanceof _Pact && thenable.s & 1;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const _iteratorSymbol = /*#__PURE__*/ typeof Symbol !== "undefined" ? (Symbol.iterator || (Symbol.iterator = Symbol("Symbol.iterator"))) : "@@iterator";
|
|
77
|
-
|
|
78
|
-
const _asyncIteratorSymbol = /*#__PURE__*/ typeof Symbol !== "undefined" ? (Symbol.asyncIterator || (Symbol.asyncIterator = Symbol("Symbol.asyncIterator"))) : "@@asyncIterator";
|
|
79
|
-
|
|
80
|
-
// Asynchronously implement a generic for loop
|
|
81
|
-
function _for(test, update, body) {
|
|
82
|
-
var stage;
|
|
83
|
-
for (;;) {
|
|
84
|
-
var shouldContinue = test();
|
|
85
|
-
if (_isSettledPact(shouldContinue)) {
|
|
86
|
-
shouldContinue = shouldContinue.v;
|
|
87
|
-
}
|
|
88
|
-
if (!shouldContinue) {
|
|
89
|
-
return result;
|
|
90
|
-
}
|
|
91
|
-
if (shouldContinue.then) {
|
|
92
|
-
stage = 0;
|
|
93
|
-
break;
|
|
94
|
-
}
|
|
95
|
-
var result = body();
|
|
96
|
-
if (result && result.then) {
|
|
97
|
-
if (_isSettledPact(result)) {
|
|
98
|
-
result = result.s;
|
|
99
|
-
} else {
|
|
100
|
-
stage = 1;
|
|
101
|
-
break;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
if (update) {
|
|
105
|
-
var updateValue = update();
|
|
106
|
-
if (updateValue && updateValue.then && !_isSettledPact(updateValue)) {
|
|
107
|
-
stage = 2;
|
|
108
|
-
break;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
var pact = new _Pact();
|
|
113
|
-
var reject = _settle.bind(null, pact, 2);
|
|
114
|
-
(stage === 0 ? shouldContinue.then(_resumeAfterTest) : stage === 1 ? result.then(_resumeAfterBody) : updateValue.then(_resumeAfterUpdate)).then(void 0, reject);
|
|
115
|
-
return pact;
|
|
116
|
-
function _resumeAfterBody(value) {
|
|
117
|
-
result = value;
|
|
118
|
-
do {
|
|
119
|
-
if (update) {
|
|
120
|
-
updateValue = update();
|
|
121
|
-
if (updateValue && updateValue.then && !_isSettledPact(updateValue)) {
|
|
122
|
-
updateValue.then(_resumeAfterUpdate).then(void 0, reject);
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
shouldContinue = test();
|
|
127
|
-
if (!shouldContinue || (_isSettledPact(shouldContinue) && !shouldContinue.v)) {
|
|
128
|
-
_settle(pact, 1, result);
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
if (shouldContinue.then) {
|
|
132
|
-
shouldContinue.then(_resumeAfterTest).then(void 0, reject);
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
result = body();
|
|
136
|
-
if (_isSettledPact(result)) {
|
|
137
|
-
result = result.v;
|
|
138
|
-
}
|
|
139
|
-
} while (!result || !result.then);
|
|
140
|
-
result.then(_resumeAfterBody).then(void 0, reject);
|
|
141
|
-
}
|
|
142
|
-
function _resumeAfterTest(shouldContinue) {
|
|
143
|
-
if (shouldContinue) {
|
|
144
|
-
result = body();
|
|
145
|
-
if (result && result.then) {
|
|
146
|
-
result.then(_resumeAfterBody).then(void 0, reject);
|
|
147
|
-
} else {
|
|
148
|
-
_resumeAfterBody(result);
|
|
149
|
-
}
|
|
150
|
-
} else {
|
|
151
|
-
_settle(pact, 1, result);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
function _resumeAfterUpdate() {
|
|
155
|
-
if (shouldContinue = test()) {
|
|
156
|
-
if (shouldContinue.then) {
|
|
157
|
-
shouldContinue.then(_resumeAfterTest).then(void 0, reject);
|
|
158
|
-
} else {
|
|
159
|
-
_resumeAfterTest(shouldContinue);
|
|
160
|
-
}
|
|
161
|
-
} else {
|
|
162
|
-
_settle(pact, 1, result);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// Asynchronously call a function and send errors to recovery continuation
|
|
168
|
-
function _catch(body, recover) {
|
|
169
|
-
try {
|
|
170
|
-
var result = body();
|
|
171
|
-
} catch(e) {
|
|
172
|
-
return recover(e);
|
|
173
|
-
}
|
|
174
|
-
if (result && result.then) {
|
|
175
|
-
return result.then(void 0, recover);
|
|
176
|
-
}
|
|
177
|
-
return result;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// Asynchronously await a promise and pass the result to a finally continuation
|
|
181
|
-
function _finallyRethrows(body, finalizer) {
|
|
182
|
-
try {
|
|
183
|
-
var result = body();
|
|
184
|
-
} catch (e) {
|
|
185
|
-
return finalizer(true, e);
|
|
186
|
-
}
|
|
187
|
-
if (result && result.then) {
|
|
188
|
-
return result.then(finalizer.bind(null, false), finalizer.bind(null, true));
|
|
189
|
-
}
|
|
190
|
-
return finalizer(false, result);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
7
|
/*
|
|
194
8
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
195
9
|
* Licensed under the MIT License.
|
|
196
10
|
*/
|
|
197
|
-
|
|
11
|
+
const Constants = {
|
|
198
12
|
/**
|
|
199
13
|
* An existing file was the target of an operation that required that the target not exist
|
|
200
14
|
*/
|
|
@@ -216,106 +30,40 @@ var Constants = {
|
|
|
216
30
|
/**
|
|
217
31
|
* Default service name for using MSAL Keytar
|
|
218
32
|
*/
|
|
219
|
-
DEFAULT_SERVICE_NAME: "msal-node-extensions"
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
function _inheritsLoose(subClass, superClass) {
|
|
223
|
-
subClass.prototype = Object.create(superClass.prototype);
|
|
224
|
-
subClass.prototype.constructor = subClass;
|
|
225
|
-
subClass.__proto__ = superClass;
|
|
226
|
-
}
|
|
33
|
+
DEFAULT_SERVICE_NAME: "msal-node-extensions",
|
|
227
34
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
return _getPrototypeOf(o);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
function _setPrototypeOf(o, p) {
|
|
236
|
-
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
|
|
237
|
-
o.__proto__ = p;
|
|
238
|
-
return o;
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
return _setPrototypeOf(o, p);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
function _isNativeReflectConstruct() {
|
|
245
|
-
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
|
|
246
|
-
if (Reflect.construct.sham) return false;
|
|
247
|
-
if (typeof Proxy === "function") return true;
|
|
248
|
-
|
|
249
|
-
try {
|
|
250
|
-
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
|
|
251
|
-
return true;
|
|
252
|
-
} catch (e) {
|
|
253
|
-
return false;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
function _construct(Parent, args, Class) {
|
|
258
|
-
if (_isNativeReflectConstruct()) {
|
|
259
|
-
_construct = Reflect.construct;
|
|
260
|
-
} else {
|
|
261
|
-
_construct = function _construct(Parent, args, Class) {
|
|
262
|
-
var a = [null];
|
|
263
|
-
a.push.apply(a, args);
|
|
264
|
-
var Constructor = Function.bind.apply(Parent, a);
|
|
265
|
-
var instance = new Constructor();
|
|
266
|
-
if (Class) _setPrototypeOf(instance, Class.prototype);
|
|
267
|
-
return instance;
|
|
268
|
-
};
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
return _construct.apply(null, arguments);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
function _isNativeFunction(fn) {
|
|
275
|
-
return Function.toString.call(fn).indexOf("[native code]") !== -1;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
function _wrapNativeSuper(Class) {
|
|
279
|
-
var _cache = typeof Map === "function" ? new Map() : undefined;
|
|
280
|
-
|
|
281
|
-
_wrapNativeSuper = function _wrapNativeSuper(Class) {
|
|
282
|
-
if (Class === null || !_isNativeFunction(Class)) return Class;
|
|
283
|
-
|
|
284
|
-
if (typeof Class !== "function") {
|
|
285
|
-
throw new TypeError("Super expression must either be null or a function");
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
if (typeof _cache !== "undefined") {
|
|
289
|
-
if (_cache.has(Class)) return _cache.get(Class);
|
|
290
|
-
|
|
291
|
-
_cache.set(Class, Wrapper);
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
function Wrapper() {
|
|
295
|
-
return _construct(Class, arguments, _getPrototypeOf(this).constructor);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
Wrapper.prototype = Object.create(Class.prototype, {
|
|
299
|
-
constructor: {
|
|
300
|
-
value: Wrapper,
|
|
301
|
-
enumerable: false,
|
|
302
|
-
writable: true,
|
|
303
|
-
configurable: true
|
|
304
|
-
}
|
|
305
|
-
});
|
|
306
|
-
return _setPrototypeOf(Wrapper, Class);
|
|
307
|
-
};
|
|
35
|
+
/**
|
|
36
|
+
* Test data used to verify underlying persistence mechanism
|
|
37
|
+
*/
|
|
38
|
+
PERSISTENCE_TEST_DATA: "Dummy data to verify underlying persistence mechanism",
|
|
308
39
|
|
|
309
|
-
|
|
310
|
-
|
|
40
|
+
/**
|
|
41
|
+
* This is the value of a the guid if the process is being ran by the root user
|
|
42
|
+
*/
|
|
43
|
+
LINUX_ROOT_USER_GUID: 0,
|
|
311
44
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
45
|
+
/**
|
|
46
|
+
* List of environment variables
|
|
47
|
+
*/
|
|
48
|
+
ENVIRONMENT: {
|
|
49
|
+
HOME: "HOME",
|
|
50
|
+
LOGNAME: "LOGNAME",
|
|
51
|
+
USER: "USER",
|
|
52
|
+
LNAME: "LNAME",
|
|
53
|
+
USERNAME: "USERNAME",
|
|
54
|
+
PLATFORM: "platform",
|
|
55
|
+
LOCAL_APPLICATION_DATA: "LOCALAPPDATA"
|
|
56
|
+
},
|
|
57
|
+
// Name of the default cache file
|
|
58
|
+
DEFAULT_CACHE_FILE_NAME: "cache.json"
|
|
59
|
+
};
|
|
60
|
+
var Platform;
|
|
316
61
|
|
|
317
|
-
|
|
318
|
-
|
|
62
|
+
(function (Platform) {
|
|
63
|
+
Platform["WINDOWS"] = "win32";
|
|
64
|
+
Platform["LINUX"] = "linux";
|
|
65
|
+
Platform["MACOS"] = "darwin";
|
|
66
|
+
})(Platform || (Platform = {}));
|
|
319
67
|
|
|
320
68
|
/*
|
|
321
69
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -325,71 +73,113 @@ function _assertThisInitialized(self) {
|
|
|
325
73
|
/**
|
|
326
74
|
* Error thrown when trying to write MSAL cache to persistence.
|
|
327
75
|
*/
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
Object.setPrototypeOf(_assertThisInitialized(_this), PersistenceError.prototype);
|
|
337
|
-
_this.errorCode = errorCode;
|
|
338
|
-
_this.errorMessage = errorMessage;
|
|
339
|
-
_this.name = "PersistenceError";
|
|
340
|
-
return _this;
|
|
76
|
+
class PersistenceError extends Error {
|
|
77
|
+
constructor(errorCode, errorMessage) {
|
|
78
|
+
const errorString = errorMessage ? `${errorCode}: ${errorMessage}` : errorCode;
|
|
79
|
+
super(errorString);
|
|
80
|
+
Object.setPrototypeOf(this, PersistenceError.prototype);
|
|
81
|
+
this.errorCode = errorCode;
|
|
82
|
+
this.errorMessage = errorMessage;
|
|
83
|
+
this.name = "PersistenceError";
|
|
341
84
|
}
|
|
342
85
|
/**
|
|
343
86
|
* Error thrown when trying to access the file system.
|
|
344
87
|
*/
|
|
345
88
|
|
|
346
89
|
|
|
347
|
-
|
|
90
|
+
static createFileSystemError(errorCode, errorMessage) {
|
|
348
91
|
return new PersistenceError(errorCode, errorMessage);
|
|
349
92
|
}
|
|
350
93
|
/**
|
|
351
94
|
* Error thrown when trying to write, load, or delete data from secret service on linux.
|
|
352
95
|
* Libsecret is used to access secret service.
|
|
353
96
|
*/
|
|
354
|
-
;
|
|
355
97
|
|
|
356
|
-
|
|
98
|
+
|
|
99
|
+
static createLibSecretError(errorMessage) {
|
|
357
100
|
return new PersistenceError("GnomeKeyringError", errorMessage);
|
|
358
101
|
}
|
|
359
102
|
/**
|
|
360
103
|
* Error thrown when trying to write, load, or delete data from keychain on macOs.
|
|
361
104
|
*/
|
|
362
|
-
;
|
|
363
105
|
|
|
364
|
-
|
|
106
|
+
|
|
107
|
+
static createKeychainPersistenceError(errorMessage) {
|
|
365
108
|
return new PersistenceError("KeychainError", errorMessage);
|
|
366
109
|
}
|
|
367
110
|
/**
|
|
368
111
|
* Error thrown when trying to encrypt or decrypt data using DPAPI on Windows.
|
|
369
112
|
*/
|
|
370
|
-
;
|
|
371
113
|
|
|
372
|
-
|
|
114
|
+
|
|
115
|
+
static createFilePersistenceWithDPAPIError(errorMessage) {
|
|
373
116
|
return new PersistenceError("DPAPIEncryptedFileError", errorMessage);
|
|
374
117
|
}
|
|
375
118
|
/**
|
|
376
119
|
* Error thrown when using the cross platform lock.
|
|
377
120
|
*/
|
|
378
|
-
;
|
|
379
121
|
|
|
380
|
-
|
|
122
|
+
|
|
123
|
+
static createCrossPlatformLockError(errorMessage) {
|
|
381
124
|
return new PersistenceError("CrossPlatformLockError", errorMessage);
|
|
382
|
-
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Throw cache persistence error
|
|
128
|
+
*
|
|
129
|
+
* @param errorMessage string
|
|
130
|
+
* @returns PersistenceError
|
|
131
|
+
*/
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
static createCachePersistenceError(errorMessage) {
|
|
135
|
+
return new PersistenceError("CachePersistenceError", errorMessage);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Throw unsupported error
|
|
139
|
+
*
|
|
140
|
+
* @param errorMessage string
|
|
141
|
+
* @returns PersistenceError
|
|
142
|
+
*/
|
|
383
143
|
|
|
384
|
-
return PersistenceError;
|
|
385
|
-
}( /*#__PURE__*/_wrapNativeSuper(Error));
|
|
386
144
|
|
|
145
|
+
static createNotSupportedError(errorMessage) {
|
|
146
|
+
return new PersistenceError("NotSupportedError", errorMessage);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Throw persistence not verified error
|
|
150
|
+
*
|
|
151
|
+
* @param errorMessage string
|
|
152
|
+
* @returns PersistenceError
|
|
153
|
+
*/
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
static createPersistenceNotVerifiedError(errorMessage) {
|
|
157
|
+
return new PersistenceError("PersistenceNotVerifiedError", errorMessage);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Throw persistence creation validation error
|
|
161
|
+
*
|
|
162
|
+
* @param errorMessage string
|
|
163
|
+
* @returns PersistenceError
|
|
164
|
+
*/
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
static createPersistenceNotValidatedError(errorMessage) {
|
|
168
|
+
return new PersistenceError("PersistenceNotValidatedError", errorMessage);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/*
|
|
174
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
175
|
+
* Licensed under the MIT License.
|
|
176
|
+
*/
|
|
387
177
|
/**
|
|
388
178
|
* Cross-process lock that works on all platforms.
|
|
389
179
|
*/
|
|
390
180
|
|
|
391
|
-
|
|
392
|
-
|
|
181
|
+
class CrossPlatformLock {
|
|
182
|
+
constructor(lockFilePath, logger, lockOptions) {
|
|
393
183
|
this.lockFilePath = lockFilePath;
|
|
394
184
|
this.retryNumber = lockOptions ? lockOptions.retryNumber : 500;
|
|
395
185
|
this.retryDelay = lockOptions ? lockOptions.retryDelay : 100;
|
|
@@ -402,108 +192,65 @@ var CrossPlatformLock = /*#__PURE__*/function () {
|
|
|
402
192
|
*/
|
|
403
193
|
|
|
404
194
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
var _temp4 = _for(function () {
|
|
424
|
-
return !_exit2 && _tryCount < _this2.retryNumber;
|
|
425
|
-
}, function () {
|
|
426
|
-
return _tryCount++;
|
|
427
|
-
}, function () {
|
|
428
|
-
return _catch(function () {
|
|
429
|
-
_this2.logger.info("Pid " + pid + " trying to acquire lock");
|
|
430
|
-
|
|
431
|
-
return Promise.resolve(promises.open(_this2.lockFilePath, "wx+")).then(function (_fs$open) {
|
|
432
|
-
_this2.lockFileHandle = _fs$open;
|
|
433
|
-
|
|
434
|
-
_this2.logger.info("Pid " + pid + " acquired lock");
|
|
435
|
-
|
|
436
|
-
return Promise.resolve(_this2.lockFileHandle.write(pid.toString())).then(function () {
|
|
437
|
-
_exit2 = true;
|
|
438
|
-
});
|
|
439
|
-
});
|
|
440
|
-
}, function (err) {
|
|
441
|
-
return function () {
|
|
442
|
-
if (err.code == Constants.EEXIST_ERROR || err.code == Constants.EPERM_ERROR) {
|
|
443
|
-
_this2.logger.info(err);
|
|
444
|
-
|
|
445
|
-
return Promise.resolve(_this2.sleep(_this2.retryDelay)).then(function () {});
|
|
446
|
-
} else {
|
|
447
|
-
_this2.logger.error(pid + " was not able to acquire lock. Ran into error: " + err.message);
|
|
448
|
-
|
|
449
|
-
throw PersistenceError.createCrossPlatformLockError(err.message);
|
|
450
|
-
}
|
|
451
|
-
}();
|
|
452
|
-
});
|
|
453
|
-
});
|
|
454
|
-
|
|
455
|
-
return Promise.resolve(_temp4 && _temp4.then ? _temp4.then(_temp3) : _temp3(_temp4));
|
|
456
|
-
} catch (e) {
|
|
457
|
-
return Promise.reject(e);
|
|
195
|
+
async lock() {
|
|
196
|
+
for (let tryCount = 0; tryCount < this.retryNumber; tryCount++) {
|
|
197
|
+
try {
|
|
198
|
+
this.logger.info(`Pid ${pid} trying to acquire lock`);
|
|
199
|
+
this.lockFileHandle = await promises.open(this.lockFilePath, "wx+");
|
|
200
|
+
this.logger.info(`Pid ${pid} acquired lock`);
|
|
201
|
+
await this.lockFileHandle.write(pid.toString());
|
|
202
|
+
return;
|
|
203
|
+
} catch (err) {
|
|
204
|
+
if (err.code === Constants.EEXIST_ERROR || err.code === Constants.EPERM_ERROR) {
|
|
205
|
+
this.logger.info(err);
|
|
206
|
+
await this.sleep(this.retryDelay);
|
|
207
|
+
} else {
|
|
208
|
+
this.logger.error(`${pid} was not able to acquire lock. Ran into error: ${err.message}`);
|
|
209
|
+
throw PersistenceError.createCrossPlatformLockError(err.message);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
458
212
|
}
|
|
213
|
+
|
|
214
|
+
this.logger.error(`${pid} was not able to acquire lock. Exceeded amount of retries set in the options`);
|
|
215
|
+
throw PersistenceError.createCrossPlatformLockError("Not able to acquire lock. Exceeded amount of retries set in options");
|
|
459
216
|
}
|
|
460
217
|
/**
|
|
461
218
|
* unlocks cache file by deleting .lockfile.
|
|
462
219
|
*/
|
|
463
|
-
;
|
|
464
220
|
|
|
465
|
-
_proto.unlock = function unlock() {
|
|
466
|
-
try {
|
|
467
|
-
var _this4 = this;
|
|
468
|
-
|
|
469
|
-
return Promise.resolve(_catch(function () {
|
|
470
|
-
var _temp5 = function () {
|
|
471
|
-
if (_this4.lockFileHandle) {
|
|
472
|
-
// if we have a file handle to the .lockfile, delete lock file
|
|
473
|
-
return Promise.resolve(promises.unlink(_this4.lockFilePath)).then(function () {
|
|
474
|
-
return Promise.resolve(_this4.lockFileHandle.close()).then(function () {
|
|
475
|
-
_this4.logger.info("lockfile deleted");
|
|
476
|
-
});
|
|
477
|
-
});
|
|
478
|
-
} else {
|
|
479
|
-
_this4.logger.warning("lockfile handle does not exist, so lockfile could not be deleted");
|
|
480
|
-
}
|
|
481
|
-
}();
|
|
482
221
|
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
}
|
|
493
|
-
} catch (
|
|
494
|
-
|
|
222
|
+
async unlock() {
|
|
223
|
+
try {
|
|
224
|
+
if (this.lockFileHandle) {
|
|
225
|
+
// if we have a file handle to the .lockfile, delete lock file
|
|
226
|
+
await promises.unlink(this.lockFilePath);
|
|
227
|
+
await this.lockFileHandle.close();
|
|
228
|
+
this.logger.info("lockfile deleted");
|
|
229
|
+
} else {
|
|
230
|
+
this.logger.warning("lockfile handle does not exist, so lockfile could not be deleted");
|
|
231
|
+
}
|
|
232
|
+
} catch (err) {
|
|
233
|
+
if (err.code === Constants.ENOENT_ERROR) {
|
|
234
|
+
this.logger.info("Tried to unlock but lockfile does not exist");
|
|
235
|
+
} else {
|
|
236
|
+
this.logger.error(`${pid} was not able to release lock. Ran into error: ${err.message}`);
|
|
237
|
+
throw PersistenceError.createCrossPlatformLockError(err.message);
|
|
238
|
+
}
|
|
495
239
|
}
|
|
496
|
-
}
|
|
240
|
+
}
|
|
497
241
|
|
|
498
|
-
|
|
499
|
-
return new Promise(
|
|
242
|
+
sleep(ms) {
|
|
243
|
+
return new Promise(resolve => {
|
|
500
244
|
setTimeout(resolve, ms);
|
|
501
245
|
});
|
|
502
|
-
}
|
|
246
|
+
}
|
|
503
247
|
|
|
504
|
-
|
|
505
|
-
}();
|
|
248
|
+
}
|
|
506
249
|
|
|
250
|
+
/*
|
|
251
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
252
|
+
* Licensed under the MIT License.
|
|
253
|
+
*/
|
|
507
254
|
/**
|
|
508
255
|
* MSAL cache plugin which enables callers to write the MSAL cache to disk on Windows,
|
|
509
256
|
* macOs, and Linux.
|
|
@@ -518,125 +265,117 @@ var CrossPlatformLock = /*#__PURE__*/function () {
|
|
|
518
265
|
* libsecret be installed.
|
|
519
266
|
*/
|
|
520
267
|
|
|
521
|
-
|
|
522
|
-
|
|
268
|
+
class PersistenceCachePlugin {
|
|
269
|
+
constructor(persistence, lockOptions) {
|
|
523
270
|
this.persistence = persistence; // initialize logger
|
|
524
271
|
|
|
525
272
|
this.logger = persistence.getLogger(); // create file lock
|
|
526
273
|
|
|
527
|
-
this.lockFilePath = this.persistence.getFilePath()
|
|
274
|
+
this.lockFilePath = `${this.persistence.getFilePath()}.lockfile`;
|
|
528
275
|
this.crossPlatformLock = new CrossPlatformLock(this.lockFilePath, this.logger, lockOptions); // initialize default values
|
|
529
276
|
|
|
530
277
|
this.lastSync = 0;
|
|
531
278
|
this.currentCache = null;
|
|
532
279
|
}
|
|
533
280
|
/**
|
|
534
|
-
* Reads from storage and
|
|
281
|
+
* Reads from storage and saves an in-memory copy. If persistence has not been updated
|
|
535
282
|
* since last time data was read, in memory copy is used.
|
|
283
|
+
*
|
|
284
|
+
* If cacheContext.cacheHasChanged === true, then file lock is created and not deleted until
|
|
285
|
+
* afterCacheAccess() is called, to prevent the cache file from changing in between
|
|
286
|
+
* beforeCacheAccess() and afterCacheAccess().
|
|
536
287
|
*/
|
|
537
288
|
|
|
538
289
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
try {
|
|
543
|
-
var _this2 = this;
|
|
290
|
+
async beforeCacheAccess(cacheContext) {
|
|
291
|
+
this.logger.info("Executing before cache access");
|
|
292
|
+
const reloadNecessary = await this.persistence.reloadNecessary(this.lastSync);
|
|
544
293
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
}
|
|
294
|
+
if (!reloadNecessary && this.currentCache !== null) {
|
|
295
|
+
if (cacheContext.cacheHasChanged) {
|
|
296
|
+
this.logger.verbose("Cache context has changed");
|
|
297
|
+
await this.crossPlatformLock.lock();
|
|
298
|
+
}
|
|
551
299
|
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
var _temp4 = _finallyRethrows(function () {
|
|
555
|
-
_this2.logger.info("Reload necessary. Last sync time: " + _this2.lastSync);
|
|
556
|
-
|
|
557
|
-
return Promise.resolve(_this2.crossPlatformLock.lock()).then(function () {
|
|
558
|
-
return Promise.resolve(_this2.persistence.load()).then(function (_this$persistence$loa) {
|
|
559
|
-
_this2.currentCache = _this$persistence$loa;
|
|
560
|
-
_this2.lastSync = new Date().getTime();
|
|
561
|
-
|
|
562
|
-
_this2.logger.info("Last sync time updated to: " + _this2.lastSync);
|
|
563
|
-
});
|
|
564
|
-
});
|
|
565
|
-
}, function (_wasThrown, _result) {
|
|
566
|
-
return Promise.resolve(_this2.crossPlatformLock.unlock()).then(function () {
|
|
567
|
-
_this2.logger.info("Pid " + pid + " Released lock");
|
|
568
|
-
|
|
569
|
-
if (_wasThrown) throw _result;
|
|
570
|
-
return _result;
|
|
571
|
-
});
|
|
572
|
-
});
|
|
573
|
-
|
|
574
|
-
if (_temp4 && _temp4.then) return _temp4.then(function () {});
|
|
575
|
-
}
|
|
576
|
-
}();
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
577
302
|
|
|
578
|
-
|
|
579
|
-
});
|
|
580
|
-
|
|
581
|
-
|
|
303
|
+
try {
|
|
304
|
+
this.logger.info(`Reload necessary. Last sync time: ${this.lastSync}`);
|
|
305
|
+
await this.crossPlatformLock.lock();
|
|
306
|
+
this.currentCache = await this.persistence.load();
|
|
307
|
+
this.lastSync = new Date().getTime();
|
|
308
|
+
cacheContext.tokenCache.deserialize(this.currentCache);
|
|
309
|
+
this.logger.info(`Last sync time updated to: ${this.lastSync}`);
|
|
310
|
+
} finally {
|
|
311
|
+
if (!cacheContext.cacheHasChanged) {
|
|
312
|
+
await this.crossPlatformLock.unlock();
|
|
313
|
+
this.logger.info(`Pid ${pid} released lock`);
|
|
314
|
+
} else {
|
|
315
|
+
this.logger.info(`Pid ${pid} beforeCacheAccess did not release lock`);
|
|
316
|
+
}
|
|
582
317
|
}
|
|
583
318
|
}
|
|
584
319
|
/**
|
|
585
|
-
* Writes to storage
|
|
586
|
-
* reads and latest state from persistence, sends state via callback, and updates in memory copy.
|
|
320
|
+
* Writes to storage if MSAL in memory copy of cache has been changed.
|
|
587
321
|
*/
|
|
588
|
-
;
|
|
589
322
|
|
|
590
|
-
|
|
323
|
+
|
|
324
|
+
async afterCacheAccess(cacheContext) {
|
|
325
|
+
this.logger.info("Executing after cache access");
|
|
326
|
+
|
|
591
327
|
try {
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
var _temp5 = function () {
|
|
607
|
-
if (_this3$persistence$re) {
|
|
608
|
-
_this4.logger.info("Reload necessary. Last sync time: " + _this4.lastSync);
|
|
609
|
-
|
|
610
|
-
return Promise.resolve(_this4.persistence.load()).then(function (_this3$persistence$lo) {
|
|
611
|
-
_this4.currentCache = _this3$persistence$lo;
|
|
612
|
-
_this4.lastSync = new Date().getTime();
|
|
613
|
-
|
|
614
|
-
_this4.logger.info("Last sync time updated to: " + _this4.lastSync);
|
|
615
|
-
});
|
|
616
|
-
}
|
|
617
|
-
}();
|
|
618
|
-
|
|
619
|
-
return _temp5 && _temp5.then ? _temp5.then(_temp6) : _temp6(_temp5);
|
|
620
|
-
});
|
|
621
|
-
});
|
|
622
|
-
}, function (_wasThrown2, _result2) {
|
|
623
|
-
return Promise.resolve(_this4.crossPlatformLock.unlock()).then(function () {
|
|
624
|
-
_this4.logger.info("Pid " + pid + " Released lock");
|
|
625
|
-
|
|
626
|
-
if (_wasThrown2) throw _result2;
|
|
627
|
-
return _result2;
|
|
628
|
-
});
|
|
629
|
-
});
|
|
328
|
+
if (cacheContext.cacheHasChanged) {
|
|
329
|
+
this.logger.info("Msal in-memory cache has changed. Writing changes to persistence");
|
|
330
|
+
this.currentCache = cacheContext.tokenCache.serialize();
|
|
331
|
+
await this.persistence.save(this.currentCache);
|
|
332
|
+
} else {
|
|
333
|
+
this.logger.info("Msal in-memory cache has not changed. Did not write to persistence");
|
|
334
|
+
}
|
|
335
|
+
} finally {
|
|
336
|
+
await this.crossPlatformLock.unlock();
|
|
337
|
+
this.logger.info(`Pid ${pid} afterCacheAccess released lock`);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
}
|
|
630
342
|
|
|
631
|
-
|
|
343
|
+
/*
|
|
344
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
345
|
+
* Licensed under the MIT License.
|
|
346
|
+
*/
|
|
347
|
+
class BasePersistence {
|
|
348
|
+
async verifyPersistence() {
|
|
349
|
+
// We are using a different location for the test to avoid overriding the functional cache
|
|
350
|
+
const persistenceValidator = await this.createForPersistenceValidation();
|
|
351
|
+
|
|
352
|
+
try {
|
|
353
|
+
await persistenceValidator.save(Constants.PERSISTENCE_TEST_DATA);
|
|
354
|
+
const retrievedDummyData = await persistenceValidator.load();
|
|
355
|
+
|
|
356
|
+
if (!retrievedDummyData) {
|
|
357
|
+
throw PersistenceError.createCachePersistenceError("Persistence check failed. Data was written but it could not be read. " + "Possible cause: on Linux, LibSecret is installed but D-Bus isn't running \
|
|
358
|
+
because it cannot be started over SSH.");
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
if (retrievedDummyData !== Constants.PERSISTENCE_TEST_DATA) {
|
|
362
|
+
throw PersistenceError.createCachePersistenceError(`Persistence check failed. Data written ${Constants.PERSISTENCE_TEST_DATA} is different \
|
|
363
|
+
from data read ${retrievedDummyData}`);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
await persistenceValidator.delete();
|
|
367
|
+
return true;
|
|
632
368
|
} catch (e) {
|
|
633
|
-
|
|
369
|
+
throw PersistenceError.createCachePersistenceError(`Verifing persistence failed with the error: ${e}`);
|
|
634
370
|
}
|
|
635
|
-
}
|
|
371
|
+
}
|
|
636
372
|
|
|
637
|
-
|
|
638
|
-
}();
|
|
373
|
+
}
|
|
639
374
|
|
|
375
|
+
/*
|
|
376
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
377
|
+
* Licensed under the MIT License.
|
|
378
|
+
*/
|
|
640
379
|
/**
|
|
641
380
|
* Reads and writes data to file specified by file location. File contents are not
|
|
642
381
|
* encrypted.
|
|
@@ -645,203 +384,162 @@ var PersistenceCachePlugin = /*#__PURE__*/function () {
|
|
|
645
384
|
* file and any directories in the path recursively.
|
|
646
385
|
*/
|
|
647
386
|
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
return Promise.resolve(filePersistence.createCacheFile()).then(function () {
|
|
657
|
-
return filePersistence;
|
|
658
|
-
});
|
|
659
|
-
} catch (e) {
|
|
660
|
-
return Promise.reject(e);
|
|
661
|
-
}
|
|
662
|
-
};
|
|
663
|
-
|
|
664
|
-
var _proto = FilePersistence.prototype;
|
|
387
|
+
class FilePersistence extends BasePersistence {
|
|
388
|
+
static async create(fileLocation, loggerOptions) {
|
|
389
|
+
const filePersistence = new FilePersistence();
|
|
390
|
+
filePersistence.filePath = fileLocation;
|
|
391
|
+
filePersistence.logger = new Logger(loggerOptions || FilePersistence.createDefaultLoggerOptions());
|
|
392
|
+
await filePersistence.createCacheFile();
|
|
393
|
+
return filePersistence;
|
|
394
|
+
}
|
|
665
395
|
|
|
666
|
-
|
|
396
|
+
async save(contents) {
|
|
667
397
|
try {
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
return Promise.resolve(promises.writeFile(_this2.getFilePath(), contents, "utf-8")).then(function () {});
|
|
672
|
-
}, function (err) {
|
|
673
|
-
throw PersistenceError.createFileSystemError(err.code, err.message);
|
|
674
|
-
}));
|
|
675
|
-
} catch (e) {
|
|
676
|
-
return Promise.reject(e);
|
|
398
|
+
await promises.writeFile(this.getFilePath(), contents, "utf-8");
|
|
399
|
+
} catch (err) {
|
|
400
|
+
throw PersistenceError.createFileSystemError(err.code, err.message);
|
|
677
401
|
}
|
|
678
|
-
}
|
|
402
|
+
}
|
|
679
403
|
|
|
680
|
-
|
|
404
|
+
async saveBuffer(contents) {
|
|
681
405
|
try {
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
return Promise.resolve(promises.writeFile(_this4.getFilePath(), contents)).then(function () {});
|
|
686
|
-
}, function (err) {
|
|
687
|
-
throw PersistenceError.createFileSystemError(err.code, err.message);
|
|
688
|
-
}));
|
|
689
|
-
} catch (e) {
|
|
690
|
-
return Promise.reject(e);
|
|
406
|
+
await promises.writeFile(this.getFilePath(), contents);
|
|
407
|
+
} catch (err) {
|
|
408
|
+
throw PersistenceError.createFileSystemError(err.code, err.message);
|
|
691
409
|
}
|
|
692
|
-
}
|
|
410
|
+
}
|
|
693
411
|
|
|
694
|
-
|
|
412
|
+
async load() {
|
|
695
413
|
try {
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
return Promise.resolve(promises.readFile(_this6.getFilePath(), "utf-8"));
|
|
700
|
-
}, function (err) {
|
|
701
|
-
throw PersistenceError.createFileSystemError(err.code, err.message);
|
|
702
|
-
}));
|
|
703
|
-
} catch (e) {
|
|
704
|
-
return Promise.reject(e);
|
|
414
|
+
return await promises.readFile(this.getFilePath(), "utf-8");
|
|
415
|
+
} catch (err) {
|
|
416
|
+
throw PersistenceError.createFileSystemError(err.code, err.message);
|
|
705
417
|
}
|
|
706
|
-
}
|
|
418
|
+
}
|
|
707
419
|
|
|
708
|
-
|
|
420
|
+
async loadBuffer() {
|
|
709
421
|
try {
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
return Promise.resolve(promises.readFile(_this8.getFilePath()));
|
|
714
|
-
}, function (err) {
|
|
715
|
-
throw PersistenceError.createFileSystemError(err.code, err.message);
|
|
716
|
-
}));
|
|
717
|
-
} catch (e) {
|
|
718
|
-
return Promise.reject(e);
|
|
422
|
+
return await promises.readFile(this.getFilePath());
|
|
423
|
+
} catch (err) {
|
|
424
|
+
throw PersistenceError.createFileSystemError(err.code, err.message);
|
|
719
425
|
}
|
|
720
|
-
}
|
|
426
|
+
}
|
|
721
427
|
|
|
722
|
-
|
|
428
|
+
async delete() {
|
|
723
429
|
try {
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
// file does not exist, so it was not deleted
|
|
733
|
-
_this10.logger.warning("Cache file does not exist, so it could not be deleted");
|
|
734
|
-
|
|
735
|
-
return false;
|
|
736
|
-
}
|
|
430
|
+
await promises.unlink(this.getFilePath());
|
|
431
|
+
return true;
|
|
432
|
+
} catch (err) {
|
|
433
|
+
if (err.code === Constants.ENOENT_ERROR) {
|
|
434
|
+
// file does not exist, so it was not deleted
|
|
435
|
+
this.logger.warning("Cache file does not exist, so it could not be deleted");
|
|
436
|
+
return false;
|
|
437
|
+
}
|
|
737
438
|
|
|
738
|
-
|
|
739
|
-
}));
|
|
740
|
-
} catch (e) {
|
|
741
|
-
return Promise.reject(e);
|
|
439
|
+
throw PersistenceError.createFileSystemError(err.code, err.message);
|
|
742
440
|
}
|
|
743
|
-
}
|
|
441
|
+
}
|
|
744
442
|
|
|
745
|
-
|
|
443
|
+
getFilePath() {
|
|
746
444
|
return this.filePath;
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
_proto.reloadNecessary = function reloadNecessary(lastSync) {
|
|
750
|
-
try {
|
|
751
|
-
var _this12 = this;
|
|
445
|
+
}
|
|
752
446
|
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
} catch (e) {
|
|
757
|
-
return Promise.reject(e);
|
|
758
|
-
}
|
|
759
|
-
};
|
|
447
|
+
async reloadNecessary(lastSync) {
|
|
448
|
+
return lastSync < (await this.timeLastModified());
|
|
449
|
+
}
|
|
760
450
|
|
|
761
|
-
|
|
451
|
+
getLogger() {
|
|
762
452
|
return this.logger;
|
|
763
|
-
}
|
|
453
|
+
}
|
|
764
454
|
|
|
765
|
-
|
|
455
|
+
createForPersistenceValidation() {
|
|
456
|
+
const testCacheFileLocation = `${dirname(this.filePath)}/test.cache`;
|
|
457
|
+
return FilePersistence.create(testCacheFileLocation);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
static createDefaultLoggerOptions() {
|
|
766
461
|
return {
|
|
767
|
-
loggerCallback:
|
|
462
|
+
loggerCallback: () => {// allow users to not set loggerCallback
|
|
768
463
|
},
|
|
769
464
|
piiLoggingEnabled: false,
|
|
770
465
|
logLevel: LogLevel.Info
|
|
771
466
|
};
|
|
772
|
-
}
|
|
467
|
+
}
|
|
773
468
|
|
|
774
|
-
|
|
469
|
+
async timeLastModified() {
|
|
775
470
|
try {
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
// file does not exist, so it's never been modified
|
|
785
|
-
_this14.logger.verbose("Cache file does not exist");
|
|
786
|
-
|
|
787
|
-
return 0;
|
|
788
|
-
}
|
|
471
|
+
const stats = await promises.stat(this.filePath);
|
|
472
|
+
return stats.mtime.getTime();
|
|
473
|
+
} catch (err) {
|
|
474
|
+
if (err.code === Constants.ENOENT_ERROR) {
|
|
475
|
+
// file does not exist, so it's never been modified
|
|
476
|
+
this.logger.verbose("Cache file does not exist");
|
|
477
|
+
return 0;
|
|
478
|
+
}
|
|
789
479
|
|
|
790
|
-
|
|
791
|
-
}));
|
|
792
|
-
} catch (e) {
|
|
793
|
-
return Promise.reject(e);
|
|
480
|
+
throw PersistenceError.createFileSystemError(err.code, err.message);
|
|
794
481
|
}
|
|
795
|
-
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
async createCacheFile() {
|
|
485
|
+
await this.createFileDirectory(); // File is created only if it does not exist
|
|
796
486
|
|
|
797
|
-
|
|
487
|
+
const fileHandle = await promises.open(this.filePath, "a");
|
|
488
|
+
await fileHandle.close();
|
|
489
|
+
this.logger.info(`File created at ${this.filePath}`);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
async createFileDirectory() {
|
|
798
493
|
try {
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
return Promise.resolve(_this16.createFileDirectory()).then(function () {
|
|
802
|
-
// File is created only if it does not exist
|
|
803
|
-
return Promise.resolve(promises.open(_this16.filePath, "a")).then(function (fileHandle) {
|
|
804
|
-
return Promise.resolve(fileHandle.close()).then(function () {
|
|
805
|
-
_this16.logger.info("File created at " + _this16.filePath);
|
|
806
|
-
});
|
|
807
|
-
});
|
|
494
|
+
await promises.mkdir(dirname(this.filePath), {
|
|
495
|
+
recursive: true
|
|
808
496
|
});
|
|
809
|
-
} catch (
|
|
810
|
-
|
|
497
|
+
} catch (err) {
|
|
498
|
+
if (err.code === Constants.EEXIST_ERROR) {
|
|
499
|
+
this.logger.info(`Directory ${dirname(this.filePath)} already exists`);
|
|
500
|
+
} else {
|
|
501
|
+
throw PersistenceError.createFileSystemError(err.code, err.message);
|
|
502
|
+
}
|
|
811
503
|
}
|
|
812
|
-
}
|
|
504
|
+
}
|
|
813
505
|
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
recursive: true
|
|
821
|
-
})).then(function () {});
|
|
822
|
-
}, function (err) {
|
|
823
|
-
if (err.code == Constants.EEXIST_ERROR) {
|
|
824
|
-
_this18.logger.info("Directory " + dirname(_this18.filePath) + " already exists");
|
|
825
|
-
} else {
|
|
826
|
-
throw PersistenceError.createFileSystemError(err.code, err.message);
|
|
827
|
-
}
|
|
828
|
-
}));
|
|
829
|
-
} catch (e) {
|
|
830
|
-
return Promise.reject(e);
|
|
831
|
-
}
|
|
832
|
-
};
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/*
|
|
509
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
510
|
+
* Licensed under the MIT License.
|
|
511
|
+
*/
|
|
833
512
|
|
|
834
|
-
|
|
835
|
-
|
|
513
|
+
/* eslint-disable-next-line @typescript-eslint/no-var-requires, no-var, import/no-commonjs */
|
|
514
|
+
var Dpapi = /*#__PURE__*/require("../build/Release/dpapi.node");
|
|
836
515
|
|
|
837
516
|
/*
|
|
838
517
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
839
518
|
* Licensed under the MIT License.
|
|
840
519
|
*/
|
|
841
520
|
|
|
842
|
-
|
|
843
|
-
|
|
521
|
+
/**
|
|
522
|
+
* Specifies the scope of the data protection - either the current user or the local
|
|
523
|
+
* machine.
|
|
524
|
+
*
|
|
525
|
+
* You do not need a key to protect or unprotect the data.
|
|
526
|
+
* If you set the Scope to CurrentUser, only applications running on your credentials can
|
|
527
|
+
* unprotect the data; however, that means that any application running on your credentials
|
|
528
|
+
* can access the protected data. If you set the Scope to LocalMachine, any full-trust
|
|
529
|
+
* application on the computer can unprotect, access, and modify the data.
|
|
530
|
+
*
|
|
531
|
+
*/
|
|
532
|
+
var DataProtectionScope;
|
|
844
533
|
|
|
534
|
+
(function (DataProtectionScope) {
|
|
535
|
+
DataProtectionScope["CurrentUser"] = "CurrentUser";
|
|
536
|
+
DataProtectionScope["LocalMachine"] = "LocalMachine";
|
|
537
|
+
})(DataProtectionScope || (DataProtectionScope = {}));
|
|
538
|
+
|
|
539
|
+
/*
|
|
540
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
541
|
+
* Licensed under the MIT License.
|
|
542
|
+
*/
|
|
845
543
|
/**
|
|
846
544
|
* Uses CryptProtectData and CryptUnprotectData on Windows to encrypt and decrypt file contents.
|
|
847
545
|
*
|
|
@@ -849,117 +547,70 @@ var Dpapi = /*#__PURE__*/require("bindings")("dpapi");
|
|
|
849
547
|
* optionalEntropy: Password or other additional entropy used to encrypt the data
|
|
850
548
|
*/
|
|
851
549
|
|
|
852
|
-
|
|
853
|
-
|
|
550
|
+
class FilePersistenceWithDataProtection extends BasePersistence {
|
|
551
|
+
constructor(scope, optionalEntropy) {
|
|
552
|
+
super();
|
|
854
553
|
this.scope = scope;
|
|
855
554
|
this.optionalEntropy = optionalEntropy ? Buffer.from(optionalEntropy, "utf-8") : null;
|
|
856
555
|
}
|
|
857
556
|
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
return persistence;
|
|
864
|
-
});
|
|
865
|
-
} catch (e) {
|
|
866
|
-
return Promise.reject(e);
|
|
867
|
-
}
|
|
868
|
-
};
|
|
869
|
-
|
|
870
|
-
var _proto = FilePersistenceWithDataProtection.prototype;
|
|
557
|
+
static async create(fileLocation, scope, optionalEntropy, loggerOptions) {
|
|
558
|
+
const persistence = new FilePersistenceWithDataProtection(scope, optionalEntropy);
|
|
559
|
+
persistence.filePersistence = await FilePersistence.create(fileLocation, loggerOptions);
|
|
560
|
+
return persistence;
|
|
561
|
+
}
|
|
871
562
|
|
|
872
|
-
|
|
563
|
+
async save(contents) {
|
|
873
564
|
try {
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
return Promise.resolve(_this2.filePersistence.saveBuffer(encryptedContents)).then(function () {});
|
|
879
|
-
}, function (err) {
|
|
880
|
-
throw PersistenceError.createFilePersistenceWithDPAPIError(err.message);
|
|
881
|
-
}));
|
|
882
|
-
} catch (e) {
|
|
883
|
-
return Promise.reject(e);
|
|
565
|
+
const encryptedContents = Dpapi.protectData(Buffer.from(contents, "utf-8"), this.optionalEntropy, this.scope.toString());
|
|
566
|
+
await this.filePersistence.saveBuffer(encryptedContents);
|
|
567
|
+
} catch (err) {
|
|
568
|
+
throw PersistenceError.createFilePersistenceWithDPAPIError(err.message);
|
|
884
569
|
}
|
|
885
|
-
}
|
|
570
|
+
}
|
|
886
571
|
|
|
887
|
-
|
|
572
|
+
async load() {
|
|
888
573
|
try {
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
return Promise.resolve(_catch(function () {
|
|
892
|
-
return Promise.resolve(_this4.filePersistence.loadBuffer()).then(function (encryptedContents) {
|
|
893
|
-
if (typeof encryptedContents === "undefined" || !encryptedContents || 0 === encryptedContents.length) {
|
|
894
|
-
_this4.filePersistence.getLogger().info("Encrypted contents loaded from file were null or empty");
|
|
895
|
-
|
|
896
|
-
return null;
|
|
897
|
-
}
|
|
898
|
-
|
|
899
|
-
return Dpapi.unprotectData(encryptedContents, _this4.optionalEntropy, _this4.scope.toString()).toString();
|
|
900
|
-
});
|
|
901
|
-
}, function (err) {
|
|
902
|
-
throw PersistenceError.createFilePersistenceWithDPAPIError(err.message);
|
|
903
|
-
}));
|
|
904
|
-
} catch (e) {
|
|
905
|
-
return Promise.reject(e);
|
|
906
|
-
}
|
|
907
|
-
};
|
|
574
|
+
const encryptedContents = await this.filePersistence.loadBuffer();
|
|
908
575
|
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
576
|
+
if (typeof encryptedContents === "undefined" || !encryptedContents || 0 === encryptedContents.length) {
|
|
577
|
+
this.filePersistence.getLogger().info("Encrypted contents loaded from file were null or empty");
|
|
578
|
+
return null;
|
|
579
|
+
}
|
|
912
580
|
|
|
913
|
-
return
|
|
914
|
-
} catch (
|
|
915
|
-
|
|
581
|
+
return Dpapi.unprotectData(encryptedContents, this.optionalEntropy, this.scope.toString()).toString();
|
|
582
|
+
} catch (err) {
|
|
583
|
+
throw PersistenceError.createFilePersistenceWithDPAPIError(err.message);
|
|
916
584
|
}
|
|
917
|
-
}
|
|
585
|
+
}
|
|
918
586
|
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
587
|
+
async delete() {
|
|
588
|
+
return this.filePersistence.delete();
|
|
589
|
+
}
|
|
922
590
|
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
}
|
|
927
|
-
};
|
|
591
|
+
async reloadNecessary(lastSync) {
|
|
592
|
+
return this.filePersistence.reloadNecessary(lastSync);
|
|
593
|
+
}
|
|
928
594
|
|
|
929
|
-
|
|
595
|
+
getFilePath() {
|
|
930
596
|
return this.filePersistence.getFilePath();
|
|
931
|
-
}
|
|
597
|
+
}
|
|
932
598
|
|
|
933
|
-
|
|
599
|
+
getLogger() {
|
|
934
600
|
return this.filePersistence.getLogger();
|
|
935
|
-
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
createForPersistenceValidation() {
|
|
604
|
+
const testCacheFileLocation = `${dirname(this.filePersistence.getFilePath())}/test.cache`;
|
|
605
|
+
return FilePersistenceWithDataProtection.create(testCacheFileLocation, DataProtectionScope.CurrentUser);
|
|
606
|
+
}
|
|
936
607
|
|
|
937
|
-
|
|
938
|
-
}();
|
|
608
|
+
}
|
|
939
609
|
|
|
940
610
|
/*
|
|
941
611
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
942
612
|
* Licensed under the MIT License.
|
|
943
613
|
*/
|
|
944
|
-
|
|
945
|
-
/**
|
|
946
|
-
* Specifies the scope of the data protection - either the current user or the local
|
|
947
|
-
* machine.
|
|
948
|
-
*
|
|
949
|
-
* You do not need a key to protect or unprotect the data.
|
|
950
|
-
* If you set the Scope to CurrentUser, only applications running on your credentials can
|
|
951
|
-
* unprotect the data; however, that means that any application running on your credentials
|
|
952
|
-
* can access the protected data. If you set the Scope to LocalMachine, any full-trust
|
|
953
|
-
* application on the computer can unprotect, access, and modify the data.
|
|
954
|
-
*
|
|
955
|
-
*/
|
|
956
|
-
var DataProtectionScope;
|
|
957
|
-
|
|
958
|
-
(function (DataProtectionScope) {
|
|
959
|
-
DataProtectionScope["CurrentUser"] = "CurrentUser";
|
|
960
|
-
DataProtectionScope["LocalMachine"] = "LocalMachine";
|
|
961
|
-
})(DataProtectionScope || (DataProtectionScope = {}));
|
|
962
|
-
|
|
963
614
|
/**
|
|
964
615
|
* Uses reads and writes passwords to macOS keychain
|
|
965
616
|
*
|
|
@@ -967,99 +618,70 @@ var DataProtectionScope;
|
|
|
967
618
|
* accountName: Account under which password should be stored
|
|
968
619
|
*/
|
|
969
620
|
|
|
970
|
-
|
|
971
|
-
|
|
621
|
+
class KeychainPersistence extends BasePersistence {
|
|
622
|
+
constructor(serviceName, accountName) {
|
|
623
|
+
super();
|
|
972
624
|
this.serviceName = serviceName;
|
|
973
625
|
this.accountName = accountName;
|
|
974
626
|
}
|
|
975
627
|
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
return persistence;
|
|
982
|
-
});
|
|
983
|
-
} catch (e) {
|
|
984
|
-
return Promise.reject(e);
|
|
985
|
-
}
|
|
986
|
-
};
|
|
987
|
-
|
|
988
|
-
var _proto = KeychainPersistence.prototype;
|
|
628
|
+
static async create(fileLocation, serviceName, accountName, loggerOptions) {
|
|
629
|
+
const persistence = new KeychainPersistence(serviceName, accountName);
|
|
630
|
+
persistence.filePersistence = await FilePersistence.create(fileLocation, loggerOptions);
|
|
631
|
+
return persistence;
|
|
632
|
+
}
|
|
989
633
|
|
|
990
|
-
|
|
634
|
+
async save(contents) {
|
|
991
635
|
try {
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
var _exit2 = false;
|
|
636
|
+
await setPassword(this.serviceName, this.accountName, contents);
|
|
637
|
+
} catch (err) {
|
|
638
|
+
throw PersistenceError.createKeychainPersistenceError(err.message);
|
|
639
|
+
} // Write dummy data to update file mtime
|
|
997
640
|
|
|
998
|
-
var _this2 = this;
|
|
999
641
|
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
}, function (err) {
|
|
1003
|
-
throw PersistenceError.createKeychainPersistenceError(err.message);
|
|
1004
|
-
});
|
|
1005
|
-
|
|
1006
|
-
return Promise.resolve(_temp4 && _temp4.then ? _temp4.then(_temp3) : _temp3(_temp4)); // Write dummy data to update file mtime
|
|
1007
|
-
} catch (e) {
|
|
1008
|
-
return Promise.reject(e);
|
|
1009
|
-
}
|
|
1010
|
-
};
|
|
642
|
+
await this.filePersistence.save("{}");
|
|
643
|
+
}
|
|
1011
644
|
|
|
1012
|
-
|
|
645
|
+
async load() {
|
|
1013
646
|
try {
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
return Promise.resolve(getPassword(_this4.serviceName, _this4.accountName));
|
|
1018
|
-
}, function (err) {
|
|
1019
|
-
throw PersistenceError.createKeychainPersistenceError(err.message);
|
|
1020
|
-
}));
|
|
1021
|
-
} catch (e) {
|
|
1022
|
-
return Promise.reject(e);
|
|
647
|
+
return await getPassword(this.serviceName, this.accountName);
|
|
648
|
+
} catch (err) {
|
|
649
|
+
throw PersistenceError.createKeychainPersistenceError(err.message);
|
|
1023
650
|
}
|
|
1024
|
-
}
|
|
651
|
+
}
|
|
1025
652
|
|
|
1026
|
-
|
|
653
|
+
async delete() {
|
|
1027
654
|
try {
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
return Promise.resolve(deletePassword(_this6.serviceName, _this6.accountName));
|
|
1033
|
-
});
|
|
1034
|
-
}, function (err) {
|
|
1035
|
-
throw PersistenceError.createKeychainPersistenceError(err.message);
|
|
1036
|
-
}));
|
|
1037
|
-
} catch (e) {
|
|
1038
|
-
return Promise.reject(e);
|
|
655
|
+
await this.filePersistence.delete();
|
|
656
|
+
return await deletePassword(this.serviceName, this.accountName);
|
|
657
|
+
} catch (err) {
|
|
658
|
+
throw PersistenceError.createKeychainPersistenceError(err.message);
|
|
1039
659
|
}
|
|
1040
|
-
}
|
|
1041
|
-
|
|
1042
|
-
_proto.reloadNecessary = function reloadNecessary(lastSync) {
|
|
1043
|
-
try {
|
|
1044
|
-
var _this8 = this;
|
|
660
|
+
}
|
|
1045
661
|
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
}
|
|
1050
|
-
};
|
|
662
|
+
async reloadNecessary(lastSync) {
|
|
663
|
+
return this.filePersistence.reloadNecessary(lastSync);
|
|
664
|
+
}
|
|
1051
665
|
|
|
1052
|
-
|
|
666
|
+
getFilePath() {
|
|
1053
667
|
return this.filePersistence.getFilePath();
|
|
1054
|
-
}
|
|
668
|
+
}
|
|
1055
669
|
|
|
1056
|
-
|
|
670
|
+
getLogger() {
|
|
1057
671
|
return this.filePersistence.getLogger();
|
|
1058
|
-
}
|
|
672
|
+
}
|
|
1059
673
|
|
|
1060
|
-
|
|
1061
|
-
|
|
674
|
+
createForPersistenceValidation() {
|
|
675
|
+
const testCacheFileLocation = `${dirname(this.filePersistence.getFilePath())}/test.cache`;
|
|
676
|
+
return KeychainPersistence.create(testCacheFileLocation, "persistenceValidationServiceName", "persistencValidationAccountName");
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
}
|
|
1062
680
|
|
|
681
|
+
/*
|
|
682
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
683
|
+
* Licensed under the MIT License.
|
|
684
|
+
*/
|
|
1063
685
|
/**
|
|
1064
686
|
* Uses reads and writes passwords to Secret Service API/libsecret. Requires libsecret
|
|
1065
687
|
* to be installed.
|
|
@@ -1068,98 +690,215 @@ var KeychainPersistence = /*#__PURE__*/function () {
|
|
|
1068
690
|
* accountName: Account under which password should be stored
|
|
1069
691
|
*/
|
|
1070
692
|
|
|
1071
|
-
|
|
1072
|
-
|
|
693
|
+
class LibSecretPersistence extends BasePersistence {
|
|
694
|
+
constructor(serviceName, accountName) {
|
|
695
|
+
super();
|
|
1073
696
|
this.serviceName = serviceName;
|
|
1074
697
|
this.accountName = accountName;
|
|
1075
698
|
}
|
|
1076
699
|
|
|
1077
|
-
|
|
700
|
+
static async create(fileLocation, serviceName, accountName, loggerOptions) {
|
|
701
|
+
const persistence = new LibSecretPersistence(serviceName, accountName);
|
|
702
|
+
persistence.filePersistence = await FilePersistence.create(fileLocation, loggerOptions);
|
|
703
|
+
return persistence;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
async save(contents) {
|
|
1078
707
|
try {
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
});
|
|
1084
|
-
} catch (e) {
|
|
1085
|
-
return Promise.reject(e);
|
|
1086
|
-
}
|
|
1087
|
-
};
|
|
708
|
+
await setPassword(this.serviceName, this.accountName, contents);
|
|
709
|
+
} catch (err) {
|
|
710
|
+
throw PersistenceError.createLibSecretError(err.message);
|
|
711
|
+
} // Write dummy data to update file mtime
|
|
1088
712
|
|
|
1089
|
-
var _proto = LibSecretPersistence.prototype;
|
|
1090
713
|
|
|
1091
|
-
|
|
714
|
+
await this.filePersistence.save("{}");
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
async load() {
|
|
1092
718
|
try {
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
719
|
+
return await getPassword(this.serviceName, this.accountName);
|
|
720
|
+
} catch (err) {
|
|
721
|
+
throw PersistenceError.createLibSecretError(err.message);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
1096
724
|
|
|
1097
|
-
|
|
725
|
+
async delete() {
|
|
726
|
+
try {
|
|
727
|
+
await this.filePersistence.delete();
|
|
728
|
+
return await deletePassword(this.serviceName, this.accountName);
|
|
729
|
+
} catch (err) {
|
|
730
|
+
throw PersistenceError.createLibSecretError(err.message);
|
|
731
|
+
}
|
|
732
|
+
}
|
|
1098
733
|
|
|
1099
|
-
|
|
734
|
+
async reloadNecessary(lastSync) {
|
|
735
|
+
return this.filePersistence.reloadNecessary(lastSync);
|
|
736
|
+
}
|
|
1100
737
|
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
throw PersistenceError.createLibSecretError(err.message);
|
|
1105
|
-
});
|
|
738
|
+
getFilePath() {
|
|
739
|
+
return this.filePersistence.getFilePath();
|
|
740
|
+
}
|
|
1106
741
|
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
}
|
|
1111
|
-
};
|
|
742
|
+
getLogger() {
|
|
743
|
+
return this.filePersistence.getLogger();
|
|
744
|
+
}
|
|
1112
745
|
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
746
|
+
createForPersistenceValidation() {
|
|
747
|
+
const testCacheFileLocation = `${dirname(this.filePersistence.getFilePath())}/test.cache`;
|
|
748
|
+
return LibSecretPersistence.create(testCacheFileLocation, "persistenceValidationServiceName", "persistencValidationAccountName");
|
|
749
|
+
}
|
|
1116
750
|
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
/*
|
|
754
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
755
|
+
* Licensed under the MIT License.
|
|
756
|
+
*/
|
|
757
|
+
class Environment {
|
|
758
|
+
static get homeEnvVar() {
|
|
759
|
+
return this.getEnvironmentVariable(Constants.ENVIRONMENT.HOME);
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
static get lognameEnvVar() {
|
|
763
|
+
return this.getEnvironmentVariable(Constants.ENVIRONMENT.LOGNAME);
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
static get userEnvVar() {
|
|
767
|
+
return this.getEnvironmentVariable(Constants.ENVIRONMENT.USER);
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
static get lnameEnvVar() {
|
|
771
|
+
return this.getEnvironmentVariable(Constants.ENVIRONMENT.LNAME);
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
static get usernameEnvVar() {
|
|
775
|
+
return this.getEnvironmentVariable(Constants.ENVIRONMENT.USERNAME);
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
static getEnvironmentVariable(name) {
|
|
779
|
+
return process.env[name];
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
static getEnvironmentPlatform() {
|
|
783
|
+
return process.platform;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
static isWindowsPlatform() {
|
|
787
|
+
return this.getEnvironmentPlatform() === Platform.WINDOWS;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
static isLinuxPlatform() {
|
|
791
|
+
return this.getEnvironmentPlatform() === Platform.LINUX;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
static isMacPlatform() {
|
|
795
|
+
return this.getEnvironmentPlatform() === Platform.MACOS;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
static isLinuxRootUser() {
|
|
799
|
+
return process.getuid() === Constants.LINUX_ROOT_USER_GUID;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
static getUserRootDirectory() {
|
|
803
|
+
return !this.isWindowsPlatform ? this.getUserHomeDirOnUnix() : this.getUserHomeDirOnWindows();
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
static getUserHomeDirOnWindows() {
|
|
807
|
+
return this.getEnvironmentVariable(Constants.ENVIRONMENT.LOCAL_APPLICATION_DATA);
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
static getUserHomeDirOnUnix() {
|
|
811
|
+
if (this.isWindowsPlatform()) {
|
|
812
|
+
throw PersistenceError.createNotSupportedError("Getting the user home directory for unix is not supported in windows");
|
|
1124
813
|
}
|
|
1125
|
-
};
|
|
1126
814
|
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
var _this6 = this;
|
|
1130
|
-
|
|
1131
|
-
return Promise.resolve(_catch(function () {
|
|
1132
|
-
return Promise.resolve(_this6.filePersistence["delete"]()).then(function () {
|
|
1133
|
-
return Promise.resolve(deletePassword(_this6.serviceName, _this6.accountName));
|
|
1134
|
-
});
|
|
1135
|
-
}, function (err) {
|
|
1136
|
-
throw PersistenceError.createLibSecretError(err.message);
|
|
1137
|
-
}));
|
|
1138
|
-
} catch (e) {
|
|
1139
|
-
return Promise.reject(e);
|
|
815
|
+
if (!StringUtils.isEmpty(this.homeEnvVar)) {
|
|
816
|
+
return this.homeEnvVar;
|
|
1140
817
|
}
|
|
1141
|
-
};
|
|
1142
818
|
|
|
1143
|
-
|
|
1144
|
-
try {
|
|
1145
|
-
var _this8 = this;
|
|
819
|
+
let username = null;
|
|
1146
820
|
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
821
|
+
if (!StringUtils.isEmpty(this.lognameEnvVar)) {
|
|
822
|
+
username = this.lognameEnvVar;
|
|
823
|
+
} else if (!StringUtils.isEmpty(this.userEnvVar)) {
|
|
824
|
+
username = this.userEnvVar;
|
|
825
|
+
} else if (!StringUtils.isEmpty(this.lnameEnvVar)) {
|
|
826
|
+
username = this.lnameEnvVar;
|
|
827
|
+
} else if (!StringUtils.isEmpty(this.usernameEnvVar)) {
|
|
828
|
+
username = this.usernameEnvVar;
|
|
1150
829
|
}
|
|
1151
|
-
};
|
|
1152
830
|
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
831
|
+
if (this.isMacPlatform()) {
|
|
832
|
+
return !StringUtils.isEmpty(username) ? path.join("/Users", username) : null;
|
|
833
|
+
} else if (this.isLinuxPlatform()) {
|
|
834
|
+
if (this.isLinuxRootUser()) {
|
|
835
|
+
return "/root";
|
|
836
|
+
} else {
|
|
837
|
+
return !StringUtils.isEmpty(username) ? path.join("/home", username) : null;
|
|
838
|
+
}
|
|
839
|
+
} else {
|
|
840
|
+
throw PersistenceError.createNotSupportedError("Getting the user home directory for unix is not supported in windows");
|
|
841
|
+
}
|
|
842
|
+
}
|
|
1156
843
|
|
|
1157
|
-
|
|
1158
|
-
return this.filePersistence.getLogger();
|
|
1159
|
-
};
|
|
844
|
+
}
|
|
1160
845
|
|
|
1161
|
-
|
|
1162
|
-
|
|
846
|
+
/*
|
|
847
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
848
|
+
* Licensed under the MIT License.
|
|
849
|
+
*/
|
|
850
|
+
class PersistenceCreator {
|
|
851
|
+
static async createPersistence(config) {
|
|
852
|
+
let peristence; // On Windows, uses a DPAPI encrypted file
|
|
853
|
+
|
|
854
|
+
if (Environment.isWindowsPlatform()) {
|
|
855
|
+
if (!config.cachePath || !config.dataProtectionScope) {
|
|
856
|
+
throw PersistenceError.createPersistenceNotValidatedError("Cache path and/or data protection scope not provided for the FilePersistenceWithDataProtection cache plugin");
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
peristence = await FilePersistenceWithDataProtection.create(config.cachePath, DataProtectionScope.CurrentUser, undefined, config.loggerOptions);
|
|
860
|
+
} // On Mac, uses keychain.
|
|
861
|
+
else if (Environment.isMacPlatform()) {
|
|
862
|
+
if (!config.cachePath || !config.serviceName || !config.accountName) {
|
|
863
|
+
throw PersistenceError.createPersistenceNotValidatedError("Cache path, service name and/or account name not provided for the KeychainPersistence cache plugin");
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
peristence = await KeychainPersistence.create(config.cachePath, config.serviceName, config.accountName, config.loggerOptions);
|
|
867
|
+
} // On Linux, uses libsecret to store to secret service. Libsecret has to be installed.
|
|
868
|
+
else if (Environment.isLinuxPlatform()) {
|
|
869
|
+
if (!config.cachePath || !config.serviceName || !config.accountName) {
|
|
870
|
+
throw PersistenceError.createPersistenceNotValidatedError("Cache path, service name and/or account name not provided for the LibSecretPersistence cache plugin");
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
peristence = await LibSecretPersistence.create(config.cachePath, config.serviceName, config.accountName, config.loggerOptions);
|
|
874
|
+
} else {
|
|
875
|
+
throw PersistenceError.createNotSupportedError("The current environment is not supported by msal-node-extensions yet.");
|
|
876
|
+
} // Initially suppress the error thrown during persistence verification to allow us to fallback to plain text
|
|
877
|
+
|
|
878
|
+
|
|
879
|
+
const isPersistenceVerified = await peristence.verifyPersistence().catch(() => false);
|
|
880
|
+
|
|
881
|
+
if (!isPersistenceVerified) {
|
|
882
|
+
if (Environment.isLinuxPlatform() && config.usePlaintextFileOnLinux) {
|
|
883
|
+
if (!config.cachePath) {
|
|
884
|
+
throw PersistenceError.createPersistenceNotValidatedError("Cache path not provided for the FilePersistence cache plugin");
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
peristence = await FilePersistence.create(config.cachePath, config.loggerOptions);
|
|
888
|
+
const isFilePersistenceVerified = await peristence.verifyPersistence();
|
|
889
|
+
|
|
890
|
+
if (isFilePersistenceVerified) {
|
|
891
|
+
return peristence;
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
throw PersistenceError.createPersistenceNotVerifiedError("Persistence could not be verified");
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
return peristence;
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
}
|
|
1163
902
|
|
|
1164
|
-
export { DataProtectionScope, FilePersistence, FilePersistenceWithDataProtection, KeychainPersistence, LibSecretPersistence, PersistenceCachePlugin };
|
|
903
|
+
export { DataProtectionScope, Environment, FilePersistence, FilePersistenceWithDataProtection, KeychainPersistence, LibSecretPersistence, PersistenceCachePlugin, PersistenceCreator };
|
|
1165
904
|
//# sourceMappingURL=msal-node-extensions.esm.js.map
|