favalib 0.0.14 → 0.0.15
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/build/Command/BaseCommand.d.mts +5 -5
- package/build/Command/CommandQueue.d.mts +1 -1
- package/build/Command/CommandQueue.mjs +3 -3
- package/build/Command/commands/AddEntryCommand.d.mts +2 -2
- package/build/Command/commands/AddEntryCommand.mjs +1 -1
- package/build/Command/commands/AddSyncDeviceCommand.d.mts +2 -2
- package/build/Command/commands/AddSyncDeviceCommand.mjs +2 -2
- package/build/Command/commands/ChangeDeviceInfoCommand.d.mts +3 -3
- package/build/Command/commands/ChangeDeviceInfoCommand.mjs +2 -2
- package/build/Command/commands/DeleteEntryCommand.d.mts +2 -2
- package/build/Command/commands/DeleteEntryCommand.mjs +1 -1
- package/build/Command/commands/UpdateEntryCommand.d.mts +2 -2
- package/build/Command/commands/UpdateEntryCommand.mjs +1 -1
- package/build/{TwoFaLib.d.mts → FavaLib.d.mts} +5 -5
- package/build/{TwoFaLib.mjs → FavaLib.mjs} +14 -14
- package/build/{TwoFALibError.d.mts → FavaLibError.d.mts} +9 -9
- package/build/{TwoFALibError.mjs → FavaLibError.mjs} +13 -13
- package/build/{TwoFaLibEvent.d.mts → FavaLibEvent.d.mts} +1 -1
- package/build/FavaLibEvent.mjs +9 -0
- package/build/{TwoFaLibMediator.d.mts → FavaLibMediator.d.mts} +3 -3
- package/build/{TwoFaLibMediator.mjs → FavaLibMediator.mjs} +4 -4
- package/build/interfaces/Events.d.mts +10 -10
- package/build/interfaces/PlatformProviders.d.mts +4 -0
- package/build/interfaces/Vault.d.mts +2 -2
- package/build/main.d.mts +5 -5
- package/build/main.mjs +5 -5
- package/build/platformProviders/browser/cryptoLib.mjs +1 -1
- package/build/platformProviders/browser/index.mjs +2 -0
- package/build/platformProviders/browser/qrCodeLib.mjs +5 -5
- package/build/platformProviders/node/cryptoLib.mjs +1 -1
- package/build/platformProviders/node/index.mjs +2 -0
- package/build/platformProviders/node/qrCodeLib.mjs +2 -2
- package/build/subclasses/CommandManager.d.mts +2 -2
- package/build/subclasses/CommandManager.mjs +1 -1
- package/build/subclasses/ExportImportManager.d.mts +2 -2
- package/build/subclasses/ExportImportManager.mjs +1 -1
- package/build/subclasses/LibraryLoader.mjs +1 -1
- package/build/subclasses/PersistentStorageManager.d.mts +2 -2
- package/build/subclasses/PersistentStorageManager.mjs +3 -3
- package/build/subclasses/StorageOperationsManager.d.mts +2 -2
- package/build/subclasses/SyncManager.d.mts +2 -2
- package/build/subclasses/SyncManager.mjs +11 -11
- package/build/subclasses/VaultDataManager.d.mts +2 -2
- package/build/subclasses/VaultDataManager.mjs +6 -6
- package/build/subclasses/VaultOperationsManager.d.mts +3 -2
- package/build/subclasses/VaultOperationsManager.mjs +5 -3
- package/build/utils/creationUtils.d.mts +7 -7
- package/build/utils/creationUtils.mjs +16 -17
- package/build/utils/exportImportUtils.mjs +1 -1
- package/build/utils/qrUtils.mjs +2 -2
- package/build/utils/syncUtils.mjs +1 -1
- package/package.json +2 -1
- package/build/TwoFaLibEvent.mjs +0 -9
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import BrowserCryptoLib from './cryptoLib.mjs';
|
|
2
2
|
import { BrowserQrCodeLib } from './qrCodeLib.mjs';
|
|
3
3
|
import { BrowserOpenPgpLib } from './openPgpLib.mjs';
|
|
4
|
+
import { v4 as genUuidV4 } from 'uuid';
|
|
4
5
|
/**
|
|
5
6
|
* Browser-specific platform providers
|
|
6
7
|
*/
|
|
@@ -9,5 +10,6 @@ export const browserProviders = {
|
|
|
9
10
|
WebSocketLib: () => WebSocket,
|
|
10
11
|
QrCodeLib: BrowserQrCodeLib,
|
|
11
12
|
OpenPgpLib: BrowserOpenPgpLib,
|
|
13
|
+
genUuidV4: () => genUuidV4(),
|
|
12
14
|
};
|
|
13
15
|
export default browserProviders;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FavaLibError } from '../../FavaLibError.mjs';
|
|
2
2
|
/**
|
|
3
3
|
* Gets the ImageData from an image, for browser environments.
|
|
4
4
|
* This ImageData is then further processed to get QR codes.
|
|
@@ -8,7 +8,7 @@ import { TwoFALibError } from '../../TwoFALibError.mjs';
|
|
|
8
8
|
export const getImageDataFromInput = (input) => {
|
|
9
9
|
return new Promise((resolve, reject) => {
|
|
10
10
|
if (input instanceof Uint8Array) {
|
|
11
|
-
reject(new
|
|
11
|
+
reject(new FavaLibError('Uint8Array input not supported in browser environment'));
|
|
12
12
|
return;
|
|
13
13
|
}
|
|
14
14
|
const img = new Image();
|
|
@@ -18,13 +18,13 @@ export const getImageDataFromInput = (input) => {
|
|
|
18
18
|
canvas.height = img.height;
|
|
19
19
|
const ctx = canvas.getContext('2d');
|
|
20
20
|
if (!ctx) {
|
|
21
|
-
reject(new
|
|
21
|
+
reject(new FavaLibError('Could not create canvas context'));
|
|
22
22
|
return;
|
|
23
23
|
}
|
|
24
24
|
ctx.drawImage(img, 0, 0);
|
|
25
25
|
resolve(ctx.getImageData(0, 0, img.width, img.height));
|
|
26
26
|
};
|
|
27
|
-
img.onerror = () => reject(new
|
|
27
|
+
img.onerror = () => reject(new FavaLibError('Failed to load image'));
|
|
28
28
|
if (typeof input === 'string') {
|
|
29
29
|
// URL or Data URL
|
|
30
30
|
img.src = input;
|
|
@@ -35,7 +35,7 @@ export const getImageDataFromInput = (input) => {
|
|
|
35
35
|
reader.onload = (e) => {
|
|
36
36
|
img.src = e.target?.result;
|
|
37
37
|
};
|
|
38
|
-
reader.onerror = () => reject(new
|
|
38
|
+
reader.onerror = () => reject(new FavaLibError('Failed to read file'));
|
|
39
39
|
reader.readAsDataURL(input);
|
|
40
40
|
}
|
|
41
41
|
});
|
|
@@ -3,7 +3,7 @@ import { promisify } from 'node:util';
|
|
|
3
3
|
import { generateKeyPair as generateKeyPairCb, generateKey as generateKeyCb, publicEncrypt, privateDecrypt, createPrivateKey, createPublicKey, randomBytes, createCipheriv, createDecipheriv, } from 'node:crypto';
|
|
4
4
|
import { argon2id } from 'hash-wasm';
|
|
5
5
|
import { toUint8Array } from 'uint8array-extras';
|
|
6
|
-
import { CryptoError } from '../../
|
|
6
|
+
import { CryptoError } from '../../FavaLibError.mjs';
|
|
7
7
|
import { generatePasswordHash } from '../browser/cryptoLib.mjs';
|
|
8
8
|
const generateKeyPair = promisify(generateKeyPairCb);
|
|
9
9
|
const generateKey = promisify(generateKeyCb);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import NodeCryptoLib from './cryptoLib.mjs';
|
|
2
2
|
import { NodeQrCodeLib } from './qrCodeLib.mjs';
|
|
3
3
|
import { NodeOpenPgpLib } from './openPgpLib.mjs';
|
|
4
|
+
import { v4 as genUuidV4 } from 'uuid';
|
|
4
5
|
/**
|
|
5
6
|
* Node.js-specific platform providers
|
|
6
7
|
*/
|
|
@@ -9,5 +10,6 @@ export const nodeProviders = {
|
|
|
9
10
|
WebSocketLib: () => WebSocket,
|
|
10
11
|
QrCodeLib: NodeQrCodeLib,
|
|
11
12
|
OpenPgpLib: NodeOpenPgpLib,
|
|
13
|
+
genUuidV4: () => genUuidV4(),
|
|
12
14
|
};
|
|
13
15
|
export default nodeProviders;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FavaLibError } from '../../FavaLibError.mjs';
|
|
2
2
|
import { isUint8Array } from 'uint8array-extras';
|
|
3
3
|
/**
|
|
4
4
|
* Gets the ImageData from an image, for Node.js environments.
|
|
@@ -8,7 +8,7 @@ import { isUint8Array } from 'uint8array-extras';
|
|
|
8
8
|
*/
|
|
9
9
|
export const getImageDataFromInput = async (inputImage) => {
|
|
10
10
|
if (inputImage instanceof File) {
|
|
11
|
-
throw new
|
|
11
|
+
throw new FavaLibError('Getting data from QR where image type is "File" is not supported in the node environment');
|
|
12
12
|
}
|
|
13
13
|
const canvasLib = await import('canvas');
|
|
14
14
|
const { createCanvas, loadImage } = canvasLib;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import type FavaLibMediator from '../FavaLibMediator.mjs';
|
|
2
2
|
import type Command from '../Command/BaseCommand.mjs';
|
|
3
3
|
import { type SyncCommand } from '../interfaces/CommandTypes.mjs';
|
|
4
4
|
/**
|
|
@@ -14,7 +14,7 @@ declare class CommandManager {
|
|
|
14
14
|
* Constructs a new CommandManager instance.
|
|
15
15
|
* @param mediator - The mediator for accessing other components.
|
|
16
16
|
*/
|
|
17
|
-
constructor(mediator:
|
|
17
|
+
constructor(mediator: FavaLibMediator);
|
|
18
18
|
private get syncManager();
|
|
19
19
|
private get log();
|
|
20
20
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { EntryId } from '../interfaces/Entry.mjs';
|
|
2
2
|
import type { PasswordExtraDict } from '../interfaces/PasswordExtraDict.js';
|
|
3
|
-
import type
|
|
3
|
+
import type FavaLibMediator from '../FavaLibMediator.mjs';
|
|
4
4
|
/**
|
|
5
5
|
* Manages the export and import of entries in various formats.
|
|
6
6
|
*/
|
|
@@ -12,7 +12,7 @@ declare class ExportImportManager {
|
|
|
12
12
|
* @param mediator - The mediator for accessing other components.
|
|
13
13
|
* @param passwordExtraDict - Additional words to be used for password strength evaluation.
|
|
14
14
|
*/
|
|
15
|
-
constructor(mediator:
|
|
15
|
+
constructor(mediator: FavaLibMediator, passwordExtraDict: PasswordExtraDict);
|
|
16
16
|
private get libraryLoader();
|
|
17
17
|
private get vaultDataManager();
|
|
18
18
|
private get vaultOperationsManager();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { parseOtpUri, generateHtmlExport, generateTextExport, processImportLines, encryptExport, decryptExport, } from '../utils/exportImportUtils.mjs';
|
|
2
2
|
import { getDataFromQRImage } from '../utils/qrUtils.mjs';
|
|
3
|
-
import { ExportImportError } from '../
|
|
3
|
+
import { ExportImportError } from '../FavaLibError.mjs';
|
|
4
4
|
import { validatePasswordStrength } from '../utils/creationUtils.mjs';
|
|
5
5
|
/**
|
|
6
6
|
* Manages the export and import of entries in various formats.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { InitializationError } from '../
|
|
1
|
+
import { InitializationError } from '../FavaLibError.mjs';
|
|
2
2
|
/**
|
|
3
3
|
* Class responsible for loading various external (big) libraries required by the application.
|
|
4
4
|
* All libraries (except CryptoLib) are loaded on demand. This helps to reduce the initial bundle size.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { EncryptedPrivateKey, EncryptedSymmetricKey, Password, PrivateKey, Salt, SymmetricKey } from '../interfaces/CryptoLib.mjs';
|
|
2
2
|
import { EncryptedVaultStateString, LockedRepresentationString } from '../interfaces/Vault.mjs';
|
|
3
|
-
import type
|
|
3
|
+
import type FavaLibMediator from '../FavaLibMediator.mjs';
|
|
4
4
|
import type { FavaMeta } from '../interfaces/FavaMeta.mjs';
|
|
5
5
|
import type { PasswordExtraDict } from '../interfaces/PasswordExtraDict.js';
|
|
6
6
|
import type { SaveFunction } from '../interfaces/SaveFunction.mjs';
|
|
@@ -32,7 +32,7 @@ declare class PersistentStorageManager {
|
|
|
32
32
|
* @param salt - The salt used for key derivation.
|
|
33
33
|
* @param saveFunction - The function to save the data.
|
|
34
34
|
*/
|
|
35
|
-
constructor(mediator:
|
|
35
|
+
constructor(mediator: FavaLibMediator, passwordExtraDict: PasswordExtraDict, favaMeta: FavaMeta, privateKey: PrivateKey, symmetricKey: SymmetricKey, encryptedPrivateKey: EncryptedPrivateKey, encryptedSymmetricKey: EncryptedSymmetricKey, salt: Salt, saveFunction?: SaveFunction | undefined);
|
|
36
36
|
private get cryptoLib();
|
|
37
37
|
private get vaultDataManager();
|
|
38
38
|
private get syncManager();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { AuthenticationError } from '../
|
|
2
|
-
import
|
|
1
|
+
import { AuthenticationError } from '../FavaLibError.mjs';
|
|
2
|
+
import FavaLib from '../FavaLib.mjs';
|
|
3
3
|
import { validatePasswordStrength } from '../utils/creationUtils.mjs';
|
|
4
4
|
/**
|
|
5
5
|
* Manages all storage of data that should be persistent.
|
|
@@ -75,7 +75,7 @@ class PersistentStorageManager {
|
|
|
75
75
|
async getLockedRepresentation() {
|
|
76
76
|
const encryptedVaultState = await this.getEncryptedVaultState();
|
|
77
77
|
const lockedRepresentation = {
|
|
78
|
-
libVersion:
|
|
78
|
+
libVersion: FavaLib.version,
|
|
79
79
|
storageVersion: PersistentStorageManager.storageVersion,
|
|
80
80
|
encryptedPrivateKey: this.encryptedPrivateKey,
|
|
81
81
|
encryptedSymmetricKey: this.encryptedSymmetricKey,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import type FavaLibMediator from '../FavaLibMediator.mjs';
|
|
2
2
|
import type { Password } from '../interfaces/CryptoLib.mjs';
|
|
3
3
|
import type { SaveFunction } from '../interfaces/SaveFunction.mjs';
|
|
4
4
|
/**
|
|
@@ -10,7 +10,7 @@ declare class StorageOperationsManager {
|
|
|
10
10
|
* Constructs a new instance of StorageOperationsManager.
|
|
11
11
|
* @param mediator - The mediator for accessing other components.
|
|
12
12
|
*/
|
|
13
|
-
constructor(mediator:
|
|
13
|
+
constructor(mediator: FavaLibMediator);
|
|
14
14
|
/**
|
|
15
15
|
* @returns The persistent storage manager instance which can be used to store data.
|
|
16
16
|
*/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SyncDevice, PublicSyncDevice, DeviceType } from '../interfaces/SyncTypes.mjs';
|
|
2
2
|
import type { PrivateKey, PublicKey } from '../interfaces/CryptoLib.mjs';
|
|
3
3
|
import type Command from '../Command/BaseCommand.mjs';
|
|
4
|
-
import type
|
|
4
|
+
import type FavaLibMediator from '../FavaLibMediator.mjs';
|
|
5
5
|
import { VaultSyncStateWithServerUrl } from '../interfaces/Vault.mjs';
|
|
6
6
|
import type { FavaMeta } from '../interfaces/FavaMeta.mjs';
|
|
7
7
|
import { SyncCommandFromServer } from 'favaserver/ServerMessage';
|
|
@@ -56,7 +56,7 @@ declare class SyncManager {
|
|
|
56
56
|
* @param deviceType - The identifier for this device type (e.g. 2fa-cli).
|
|
57
57
|
* @throws {InitializationError} If initialization fails (e.g., if the server URL is invalid).
|
|
58
58
|
*/
|
|
59
|
-
constructor(mediator:
|
|
59
|
+
constructor(mediator: FavaLibMediator, publicKey: PublicKey, privateKey: PrivateKey, favaMeta: FavaMeta, syncState: VaultSyncStateWithServerUrl, deviceType: DeviceType);
|
|
60
60
|
private get libraryLoader();
|
|
61
61
|
private get cryptoLib();
|
|
62
62
|
private get persistentStorageManager();
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { base64ToUint8Array, hexToUint8Array, stringToBase64, uint8ArrayToBase64, uint8ArrayToHex, } from 'uint8array-extras';
|
|
2
2
|
import { deriveSFromPassword, JPakeThreePass, } from 'jpake-ts';
|
|
3
|
-
import {
|
|
3
|
+
import { FavaLibEvent } from '../FavaLibEvent.mjs';
|
|
4
4
|
import { decodeInitiatorData, jsonToUint8Array } from '../utils/syncUtils.mjs';
|
|
5
|
-
import { InitializationError, SyncAddDeviceFlowConflictError, SyncError, SyncInWrongStateError, SyncNoServerConnectionError,
|
|
5
|
+
import { InitializationError, SyncAddDeviceFlowConflictError, SyncError, SyncInWrongStateError, SyncNoServerConnectionError, FavaLibError, } from '../FavaLibError.mjs';
|
|
6
6
|
import AddSyncDeviceCommand from '../Command/commands/AddSyncDeviceCommand.mjs';
|
|
7
7
|
const IN_TESTING = process.env.NODE_ENV === 'test';
|
|
8
8
|
const IN_DEV = process.env.NODE_ENV === 'development';
|
|
@@ -91,8 +91,8 @@ class SyncManager {
|
|
|
91
91
|
this.connectionFailedTimeout = setTimeout(() => {
|
|
92
92
|
if (!this.readyEventEmitted && !this.webSocketConnected) {
|
|
93
93
|
this.log('warning', 'Failed to connect to sync backend');
|
|
94
|
-
this.dispatchLibEvent(
|
|
95
|
-
this.dispatchLibEvent(
|
|
94
|
+
this.dispatchLibEvent(FavaLibEvent.Ready);
|
|
95
|
+
this.dispatchLibEvent(FavaLibEvent.ConnectionToSyncServerStatusChanged, {
|
|
96
96
|
newStatus: ConnectionStatus.FAILED,
|
|
97
97
|
});
|
|
98
98
|
}
|
|
@@ -168,7 +168,7 @@ class SyncManager {
|
|
|
168
168
|
ws.addEventListener('open', () => {
|
|
169
169
|
this.log('info', 'Connected to server.');
|
|
170
170
|
this.sendToServer('connect', { deviceId: syncManager.deviceId });
|
|
171
|
-
this.dispatchLibEvent(
|
|
171
|
+
this.dispatchLibEvent(FavaLibEvent.ConnectionToSyncServerStatusChanged, {
|
|
172
172
|
newStatus: ConnectionStatus.CONNECTED,
|
|
173
173
|
});
|
|
174
174
|
clearTimeout(this.connectionFailedTimeout);
|
|
@@ -181,7 +181,7 @@ class SyncManager {
|
|
|
181
181
|
}
|
|
182
182
|
handleWebSocketClose(event) {
|
|
183
183
|
if (this.shouldReconnect) {
|
|
184
|
-
this.dispatchLibEvent(
|
|
184
|
+
this.dispatchLibEvent(FavaLibEvent.ConnectionToSyncServerStatusChanged, {
|
|
185
185
|
newStatus: ConnectionStatus.CONNECTING,
|
|
186
186
|
});
|
|
187
187
|
// if we shouldn't reconnect, this closing is expected
|
|
@@ -189,7 +189,7 @@ class SyncManager {
|
|
|
189
189
|
this.attemptReconnect();
|
|
190
190
|
}
|
|
191
191
|
else {
|
|
192
|
-
this.dispatchLibEvent(
|
|
192
|
+
this.dispatchLibEvent(FavaLibEvent.ConnectionToSyncServerStatusChanged, {
|
|
193
193
|
newStatus: ConnectionStatus.NOT_CONNECTED,
|
|
194
194
|
});
|
|
195
195
|
// Connection closed, no need to force terminate
|
|
@@ -292,7 +292,7 @@ class SyncManager {
|
|
|
292
292
|
// Set a timeout for if we get no response from the server
|
|
293
293
|
const timeout = setTimeout(() => {
|
|
294
294
|
if (this.activeAddDeviceFlow?.state === 'initiator:initiated') {
|
|
295
|
-
reject(new
|
|
295
|
+
reject(new FavaLibError('Timeout of registerAddDeviceFlowRequest, no response'));
|
|
296
296
|
this.activeAddDeviceFlow = undefined;
|
|
297
297
|
}
|
|
298
298
|
}, 10000);
|
|
@@ -485,7 +485,7 @@ class SyncManager {
|
|
|
485
485
|
await this.importVaultState(encryptedVaultState, this.activeAddDeviceFlow.syncKey, this.activeAddDeviceFlow.initiatorDeviceId);
|
|
486
486
|
// Reset the active add device flow
|
|
487
487
|
this.activeAddDeviceFlow = undefined;
|
|
488
|
-
this.dispatchLibEvent(
|
|
488
|
+
this.dispatchLibEvent(FavaLibEvent.ConnectToExistingVaultFinished);
|
|
489
489
|
}
|
|
490
490
|
async importVaultState(encryptedVaultState, symmetricKey, expectedDeviceId) {
|
|
491
491
|
const vaultState = JSON.parse(await this.cryptoLib.decryptSymmetric(symmetricKey, encryptedVaultState));
|
|
@@ -521,7 +521,7 @@ class SyncManager {
|
|
|
521
521
|
});
|
|
522
522
|
// Reset the active add device flow
|
|
523
523
|
this.activeAddDeviceFlow = undefined;
|
|
524
|
-
this.dispatchLibEvent(
|
|
524
|
+
this.dispatchLibEvent(FavaLibEvent.ConnectToExistingVaultFinished);
|
|
525
525
|
}
|
|
526
526
|
/**
|
|
527
527
|
* Sends a command to the server to synchronize with other devices.
|
|
@@ -599,7 +599,7 @@ class SyncManager {
|
|
|
599
599
|
// we can signal that we're done loading after the commands where processed
|
|
600
600
|
if (!this.readyEventEmitted) {
|
|
601
601
|
this.readyEventEmitted = true;
|
|
602
|
-
this.dispatchLibEvent(
|
|
602
|
+
this.dispatchLibEvent(FavaLibEvent.Ready);
|
|
603
603
|
}
|
|
604
604
|
if (commandsExecutedIds.length > 0) {
|
|
605
605
|
this.sendToServer('syncCommandsExecuted', {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type Entry from '../interfaces/Entry.mjs';
|
|
2
2
|
import type { EntryId, Token } from '../interfaces/Entry.mjs';
|
|
3
|
-
import type
|
|
3
|
+
import type FavaLibMediator from '../FavaLibMediator.mjs';
|
|
4
4
|
import { Vault } from '../interfaces/Vault.mjs';
|
|
5
5
|
/**
|
|
6
6
|
* Manages the data within the vault. This class should only be used internally
|
|
@@ -13,7 +13,7 @@ declare class VaultDataManager {
|
|
|
13
13
|
* Constructs a new VaultDataManager instance.
|
|
14
14
|
* @param mediator - The mediator for accessing other components.
|
|
15
15
|
*/
|
|
16
|
-
constructor(mediator:
|
|
16
|
+
constructor(mediator: FavaLibMediator);
|
|
17
17
|
private get persistentStorageManager();
|
|
18
18
|
private get dispatchLibEvent();
|
|
19
19
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TOTP } from 'totp-generator';
|
|
2
|
-
import { EntryNotFoundError, TokenGenerationError } from '../
|
|
3
|
-
import {
|
|
2
|
+
import { EntryNotFoundError, TokenGenerationError } from '../FavaLibError.mjs';
|
|
3
|
+
import { FavaLibEvent } from '../FavaLibEvent.mjs';
|
|
4
4
|
import { SUPPORTED_ALGORITHMS, } from '../utils/constants.mjs';
|
|
5
5
|
/**
|
|
6
6
|
* Manages the data within the vault. This class should only be used internally
|
|
@@ -84,7 +84,7 @@ class VaultDataManager {
|
|
|
84
84
|
return;
|
|
85
85
|
}
|
|
86
86
|
this.vault.push(entry);
|
|
87
|
-
this.dispatchLibEvent(
|
|
87
|
+
this.dispatchLibEvent(FavaLibEvent.Changed);
|
|
88
88
|
if (saveAfter) {
|
|
89
89
|
await this.persistentStorageManager.save();
|
|
90
90
|
}
|
|
@@ -99,7 +99,7 @@ class VaultDataManager {
|
|
|
99
99
|
if (index === -1)
|
|
100
100
|
throw new EntryNotFoundError('Entry not found');
|
|
101
101
|
this.vault.splice(index, 1);
|
|
102
|
-
this.dispatchLibEvent(
|
|
102
|
+
this.dispatchLibEvent(FavaLibEvent.Changed);
|
|
103
103
|
await this.persistentStorageManager.save();
|
|
104
104
|
}
|
|
105
105
|
/**
|
|
@@ -114,7 +114,7 @@ class VaultDataManager {
|
|
|
114
114
|
if (index === -1)
|
|
115
115
|
throw new EntryNotFoundError('Entry not found');
|
|
116
116
|
this.vault[index] = updatedEntry;
|
|
117
|
-
this.dispatchLibEvent(
|
|
117
|
+
this.dispatchLibEvent(FavaLibEvent.Changed);
|
|
118
118
|
await this.persistentStorageManager.save();
|
|
119
119
|
}
|
|
120
120
|
/**
|
|
@@ -123,7 +123,7 @@ class VaultDataManager {
|
|
|
123
123
|
*/
|
|
124
124
|
replaceVault(newVault) {
|
|
125
125
|
this.vault = newVault;
|
|
126
|
-
this.dispatchLibEvent(
|
|
126
|
+
this.dispatchLibEvent(FavaLibEvent.Changed);
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
export default VaultDataManager;
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import type Entry from '../interfaces/Entry.mjs';
|
|
2
2
|
import type { EntryId, EntryMeta, EntryMetaWithToken, NewEntry, Token } from '../interfaces/Entry.mjs';
|
|
3
|
-
import type
|
|
3
|
+
import type FavaLibMediator from '../FavaLibMediator.mjs';
|
|
4
4
|
/**
|
|
5
5
|
* Manages the public operations related to the vault, including adding, deleting, and updating entries.
|
|
6
6
|
*/
|
|
7
7
|
declare class VaultOperationsManager {
|
|
8
8
|
private readonly mediator;
|
|
9
|
+
private get platformProviders();
|
|
9
10
|
/**
|
|
10
11
|
* Constructs a new instance of VaultManager.
|
|
11
12
|
* @param mediator - The mediator for accessing other components.
|
|
12
13
|
*/
|
|
13
|
-
constructor(mediator:
|
|
14
|
+
constructor(mediator: FavaLibMediator);
|
|
14
15
|
private get vaultDataManager();
|
|
15
16
|
private get commandManager();
|
|
16
17
|
/**
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { v4 as genUuidV4 } from 'uuid';
|
|
2
1
|
import AddEntryCommand from '../Command/commands/AddEntryCommand.mjs';
|
|
3
2
|
import DeleteEntryCommand from '../Command/commands/DeleteEntryCommand.mjs';
|
|
4
3
|
import UpdateEntryCommand from '../Command/commands/UpdateEntryCommand.mjs';
|
|
5
|
-
import { EntryNotFoundError } from '../
|
|
4
|
+
import { EntryNotFoundError } from '../FavaLibError.mjs';
|
|
6
5
|
const getMetaForEntry = (entry) => ({
|
|
7
6
|
id: entry.id,
|
|
8
7
|
name: entry.name,
|
|
@@ -15,6 +14,9 @@ const getMetaForEntry = (entry) => ({
|
|
|
15
14
|
* Manages the public operations related to the vault, including adding, deleting, and updating entries.
|
|
16
15
|
*/
|
|
17
16
|
class VaultOperationsManager {
|
|
17
|
+
get platformProviders() {
|
|
18
|
+
return this.mediator.getComponent('libraryLoader').getPlatformProviders();
|
|
19
|
+
}
|
|
18
20
|
/**
|
|
19
21
|
* Constructs a new instance of VaultManager.
|
|
20
22
|
* @param mediator - The mediator for accessing other components.
|
|
@@ -117,7 +119,7 @@ class VaultOperationsManager {
|
|
|
117
119
|
* @throws {InvalidCommandError} If the provided entry data is invalid or incomplete.
|
|
118
120
|
*/
|
|
119
121
|
async addEntry(entry) {
|
|
120
|
-
const newId = genUuidV4();
|
|
122
|
+
const newId = this.platformProviders.genUuidV4();
|
|
121
123
|
const newEntry = {
|
|
122
124
|
...entry,
|
|
123
125
|
id: newId,
|
|
@@ -2,7 +2,7 @@ import type { ZxcvbnResult } from '@zxcvbn-ts/core';
|
|
|
2
2
|
import type { PlatformProviders } from '../interfaces/PlatformProviders.mjs';
|
|
3
3
|
import type { Password } from '../interfaces/CryptoLib.mjs';
|
|
4
4
|
import type { DeviceType } from '../interfaces/SyncTypes.mjs';
|
|
5
|
-
import
|
|
5
|
+
import FavaLib from '../FavaLib.mjs';
|
|
6
6
|
import LibraryLoader from '../subclasses/LibraryLoader.mjs';
|
|
7
7
|
import type { LockedRepresentationString } from '../interfaces/Vault.mjs';
|
|
8
8
|
import type { PasswordExtraDict } from '../interfaces/PasswordExtraDict.js';
|
|
@@ -24,22 +24,22 @@ export declare const getPasswordStrength: (libraryLoader: LibraryLoader, passwor
|
|
|
24
24
|
*/
|
|
25
25
|
export declare const validatePasswordStrength: (libraryLoader: LibraryLoader, passwordExtraDict: PasswordExtraDict, password: Password) => Promise<void>;
|
|
26
26
|
/**
|
|
27
|
-
* Returns utility functions useful in creating a new
|
|
27
|
+
* Returns utility functions useful in creating a new favaLib vault
|
|
28
28
|
* @param platformProviders - The platform-specific providers containing CryptoLib and other providers.
|
|
29
29
|
* @param deviceType - A unique identifier for this device type (e.g. 2fa-cli).
|
|
30
30
|
* @param passwordExtraDict - Additional words to be used for password strength evaluation.
|
|
31
31
|
* @param saveFunction - The function to save the data.
|
|
32
32
|
* @param serverUrl - The server URL for syncing.
|
|
33
|
-
* @returns An object with methods to evaluate password strength and create a new
|
|
33
|
+
* @returns An object with methods to evaluate password strength and create a new FavaLib vault.
|
|
34
34
|
*/
|
|
35
|
-
export declare const
|
|
35
|
+
export declare const getFavaLibVaultCreationUtils: (platformProviders: PlatformProviders, deviceType: DeviceType, passwordExtraDict: PasswordExtraDict, saveFunction?: SaveFunction, serverUrl?: string) => {
|
|
36
36
|
getPasswordStrength: (password: Password) => Promise<ZxcvbnResult>;
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
createNewFavaLibVault: (password: Password) => Promise<{
|
|
38
|
+
favaLib: FavaLib;
|
|
39
39
|
publicKey: import("../interfaces/CryptoLib.mjs").PublicKey;
|
|
40
40
|
encryptedPrivateKey: import("../interfaces/CryptoLib.mjs").EncryptedPrivateKey;
|
|
41
41
|
encryptedSymmetricKey: import("../interfaces/CryptoLib.mjs").EncryptedSymmetricKey;
|
|
42
42
|
salt: import("../interfaces/CryptoLib.mjs").Salt;
|
|
43
43
|
}>;
|
|
44
|
-
|
|
44
|
+
loadFavaLibFromLockedRepesentation: (lockedRepresentationString: LockedRepresentationString, password: Password) => Promise<FavaLib>;
|
|
45
45
|
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import { InitializationError, TwoFALibError } from '../TwoFALibError.mjs';
|
|
1
|
+
import FavaLib from '../FavaLib.mjs';
|
|
2
|
+
import { InitializationError, FavaLibError } from '../FavaLibError.mjs';
|
|
4
3
|
import LibraryLoader from '../subclasses/LibraryLoader.mjs';
|
|
5
4
|
/**
|
|
6
5
|
* Evaluates the strength of a password.
|
|
@@ -47,26 +46,26 @@ export const getPasswordStrength = async (libraryLoader, passwordExtraDict, pass
|
|
|
47
46
|
export const validatePasswordStrength = async (libraryLoader, passwordExtraDict, password) => {
|
|
48
47
|
const passwordStrength = await getPasswordStrength(libraryLoader, passwordExtraDict, password);
|
|
49
48
|
if (passwordStrength.score < 3) {
|
|
50
|
-
throw new
|
|
49
|
+
throw new FavaLibError('Password is too weak');
|
|
51
50
|
}
|
|
52
51
|
};
|
|
53
52
|
/**
|
|
54
|
-
* Creates a new
|
|
53
|
+
* Creates a new FavaLib vault.
|
|
55
54
|
* @param libraryLoader - An instance of LibraryLoader.
|
|
56
55
|
* @param deviceType - A unique identifier for the device type e.g. 2fa-cli.
|
|
57
56
|
* @param serverUrl - The server URL for syncing.
|
|
58
57
|
* @param passwordExtraDict - Additional words to be used for password strength evaluation.
|
|
59
58
|
* @param saveFunction - The function to save the data.
|
|
60
59
|
* @param password - The password to be used to encrypt the private key.
|
|
61
|
-
* @returns Promise resolving to an object containing the newly created
|
|
60
|
+
* @returns Promise resolving to an object containing the newly created FavaLib instance and related data.
|
|
62
61
|
*/
|
|
63
|
-
const
|
|
62
|
+
const createNewFavaLibVault = async (libraryLoader, deviceType, serverUrl, passwordExtraDict, saveFunction, password) => {
|
|
64
63
|
const cryptoLib = libraryLoader.getCryptoLib();
|
|
65
64
|
const platformProviders = libraryLoader.getPlatformProviders();
|
|
66
65
|
const { publicKey, privateKey, symmetricKey, encryptedPrivateKey, encryptedSymmetricKey, salt, } = await cryptoLib.createKeys(password);
|
|
67
66
|
await validatePasswordStrength(libraryLoader, passwordExtraDict, password);
|
|
68
|
-
const deviceId = genUuidV4();
|
|
69
|
-
const
|
|
67
|
+
const deviceId = platformProviders.genUuidV4();
|
|
68
|
+
const favaLib = new FavaLib(deviceType, platformProviders, passwordExtraDict, privateKey, symmetricKey, encryptedPrivateKey, encryptedSymmetricKey, salt, publicKey, {
|
|
70
69
|
deviceId,
|
|
71
70
|
}, [], saveFunction, {
|
|
72
71
|
serverUrl,
|
|
@@ -74,7 +73,7 @@ const createNewTwoFaLibVault = async (libraryLoader, deviceType, serverUrl, pass
|
|
|
74
73
|
commandSendQueue: [],
|
|
75
74
|
});
|
|
76
75
|
return {
|
|
77
|
-
|
|
76
|
+
favaLib,
|
|
78
77
|
publicKey,
|
|
79
78
|
encryptedPrivateKey,
|
|
80
79
|
encryptedSymmetricKey,
|
|
@@ -92,7 +91,7 @@ const createNewTwoFaLibVault = async (libraryLoader, deviceType, serverUrl, pass
|
|
|
92
91
|
* @returns A promise that resolves when loading is complete.
|
|
93
92
|
* @throws {InitializationError} If loading fails due to invalid or corrupted data.
|
|
94
93
|
*/
|
|
95
|
-
const
|
|
94
|
+
const loadFavaLibFromLockedRepesentation = async (libraryLoader, deviceType, passwordExtraDict, saveFunction, lockedRepresentationString, password) => {
|
|
96
95
|
const cryptoLib = libraryLoader.getCryptoLib();
|
|
97
96
|
const platformProviders = libraryLoader.getPlatformProviders();
|
|
98
97
|
const lockedRepresentation = JSON.parse(lockedRepresentationString);
|
|
@@ -111,25 +110,25 @@ const loadTwoFaLibFromLockedRepesentation = async (libraryLoader, deviceType, pa
|
|
|
111
110
|
!vaultState.sync?.devices) {
|
|
112
111
|
throw new InitializationError('encryptedVaultState is incomplete or corrupted');
|
|
113
112
|
}
|
|
114
|
-
return new
|
|
113
|
+
return new FavaLib(deviceType, platformProviders, passwordExtraDict, privateKey, symmetricKey, lockedRepresentation.encryptedPrivateKey, lockedRepresentation.encryptedSymmetricKey, lockedRepresentation.salt, publicKey, {
|
|
115
114
|
deviceId: vaultState.deviceId,
|
|
116
115
|
deviceFriendlyName: vaultState.deviceFriendlyName,
|
|
117
116
|
}, vaultState.vault, saveFunction, vaultState.sync);
|
|
118
117
|
};
|
|
119
118
|
/**
|
|
120
|
-
* Returns utility functions useful in creating a new
|
|
119
|
+
* Returns utility functions useful in creating a new favaLib vault
|
|
121
120
|
* @param platformProviders - The platform-specific providers containing CryptoLib and other providers.
|
|
122
121
|
* @param deviceType - A unique identifier for this device type (e.g. 2fa-cli).
|
|
123
122
|
* @param passwordExtraDict - Additional words to be used for password strength evaluation.
|
|
124
123
|
* @param saveFunction - The function to save the data.
|
|
125
124
|
* @param serverUrl - The server URL for syncing.
|
|
126
|
-
* @returns An object with methods to evaluate password strength and create a new
|
|
125
|
+
* @returns An object with methods to evaluate password strength and create a new FavaLib vault.
|
|
127
126
|
*/
|
|
128
|
-
export const
|
|
127
|
+
export const getFavaLibVaultCreationUtils = (platformProviders, deviceType, passwordExtraDict, saveFunction, serverUrl) => {
|
|
129
128
|
const libraryLoader = new LibraryLoader(platformProviders);
|
|
130
129
|
return {
|
|
131
130
|
getPasswordStrength: getPasswordStrength.bind(null, libraryLoader, passwordExtraDict),
|
|
132
|
-
|
|
133
|
-
|
|
131
|
+
createNewFavaLibVault: createNewFavaLibVault.bind(null, libraryLoader, deviceType, serverUrl, passwordExtraDict, saveFunction),
|
|
132
|
+
loadFavaLibFromLockedRepesentation: loadFavaLibFromLockedRepesentation.bind(null, libraryLoader, deviceType, passwordExtraDict, saveFunction),
|
|
134
133
|
};
|
|
135
134
|
};
|
package/build/utils/qrUtils.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FavaLibError } from '../FavaLibError.mjs';
|
|
2
2
|
/**
|
|
3
3
|
* Import an entry from a QR code image.
|
|
4
4
|
* @param libraryLoader - An instance of LibraryLoader.
|
|
@@ -12,7 +12,7 @@ export const getDataFromQRImage = async (libraryLoader, imageInput) => {
|
|
|
12
12
|
const imageData = await qrLib.getImageDataFromInput(imageInput);
|
|
13
13
|
const qrCodeResult = jsQr(imageData.data, imageData.width, imageData.height);
|
|
14
14
|
if (!qrCodeResult) {
|
|
15
|
-
throw new
|
|
15
|
+
throw new FavaLibError("Couldn't read QR code data from image");
|
|
16
16
|
}
|
|
17
17
|
return qrCodeResult.data;
|
|
18
18
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { base64ToString } from 'uint8array-extras';
|
|
2
|
-
import { SyncError } from '../
|
|
2
|
+
import { SyncError } from '../FavaLibError.mjs';
|
|
3
3
|
/**
|
|
4
4
|
* Decodes the initiator data from a string or QR code.
|
|
5
5
|
* @param initiatorData - The initiator data to decode.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "favalib",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.15",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"@vitest/coverage-v8": "^3.1.4",
|
|
32
32
|
"eslint": "^9.27.0",
|
|
33
33
|
"type-fest": "^4.41.0",
|
|
34
|
+
"typedoc": "^0.27.8",
|
|
34
35
|
"vitest": "^3.1.4",
|
|
35
36
|
"vitest-websocket-mock": "^0.5.0"
|
|
36
37
|
},
|
package/build/TwoFaLibEvent.mjs
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export var TwoFaLibEvent;
|
|
2
|
-
(function (TwoFaLibEvent) {
|
|
3
|
-
TwoFaLibEvent["Changed"] = "changed";
|
|
4
|
-
TwoFaLibEvent["LoadedFromLockedRepresentation"] = "loadedFromLockedRepresentation";
|
|
5
|
-
TwoFaLibEvent["ConnectToExistingVaultFinished"] = "connectToExistingVaultFinished";
|
|
6
|
-
TwoFaLibEvent["ConnectionToSyncServerStatusChanged"] = "connectionToSyncServerStatusChanged";
|
|
7
|
-
TwoFaLibEvent["Log"] = "log";
|
|
8
|
-
TwoFaLibEvent["Ready"] = "ready";
|
|
9
|
-
})(TwoFaLibEvent || (TwoFaLibEvent = {}));
|