From: Chris Duncan Date: Wed, 10 Sep 2025 04:44:32 +0000 (-0700) Subject: Refactor timeout config. X-Git-Tag: v0.10.5~22^2~3 X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=c26e002edcbe7f7d7dd4aa1b3fb52fafcda4cddd;p=libnemo.git Refactor timeout config. Get timeout config from data extraction. Throw if locked when calling config. Limit to 0 minutes min and 10 minutes max. Reset timer on new config. Use configured timeout for other timer resets. --- diff --git a/src/lib/vault/vault-worker.ts b/src/lib/vault/vault-worker.ts index c9ac8be..f2a2d02 100644 --- a/src/lib/vault/vault-worker.ts +++ b/src/lib/vault/vault-worker.ts @@ -32,20 +32,19 @@ export class VaultWorker { NODE: if (this.#parentPort == null) setTimeout(() => listener(event), 0) const data = this.#parseData(event.data) const action = this.#parseAction(data) - const config = this.#parseConfig(action, data) const keySalt = this.#parseKeySalt(action, data) Passkey.create(action, keySalt, data) .then((key: CryptoKey | undefined): Promise => { const type = this.#parseType(action, data) const iv = this.#parseIv(action, data) - const { seed, mnemonicPhrase, mnemonicSalt, index, encrypted, message } = this.#extractData(action, data) + const { seed, mnemonicPhrase, mnemonicSalt, index, encrypted, message, timeout } = this.#extractData(action, data) switch (action) { case 'STOP': { BROWSER: close() NODE: process.exit() } case 'config': { - return this.config(config) + return this.config(timeout) } case 'create': { return this.create(type, key, keySalt, mnemonicSalt) @@ -117,11 +116,28 @@ export class VaultWorker { * Configures vault settings. The wallet must be unlocked prior to * configuration. */ - config (config: { [key: string]: unknown }): Promise { - if (typeof config.timeout === 'number') { - this.#timeout = config.timeout + config (timeout?: number): Promise { + try { + this.#timer?.pause() + if (this.#locked) { + throw new Error('Wallet is locked') + } + if (typeof timeout === 'number') { + if (timeout < 0) { + throw new RangeError('Timeout must be non-negative') + } + if (timeout > 600) { + throw new RangeError('Maximum timeout is 10 minutes') + } + this.#timeout = timeout * 1000 + this.#timer = new VaultTimer(() => this.lock(), this.#timeout) + } + return Promise.resolve() + } catch (err) { + console.error(err) + this.#timer?.resume() + throw new Error('Failed to configure Vault', { cause: err }) } - return Promise.resolve() } /** @@ -176,7 +192,7 @@ export class VaultWorker { : Blake2b.ckd(this.#seed, index) return derive.then(prv => { const pub = NanoNaCl.convert(new Uint8Array(prv)) - this.#timer = new VaultTimer(() => this.lock(), 120000) + this.#timer = new VaultTimer(() => this.lock(), this.#timeout) return { index, publicKey: pub.buffer } }) } catch (err) { @@ -242,7 +258,7 @@ export class VaultWorker { : Blake2b.ckd(this.#seed, index) return derive.then(prv => { const sig = NanoNaCl.detached(new Uint8Array(data), new Uint8Array(prv)) - this.#timer = new VaultTimer(() => this.lock(), 120000) + this.#timer = new VaultTimer(() => this.lock(), this.#timeout) return { signature: sig.buffer } }) } catch (err) { @@ -286,7 +302,7 @@ export class VaultWorker { this.#seed = seed this.#mnemonic = mnemonic this.#locked = false - this.#timer = new VaultTimer(this.lock.bind(this), 120000) + this.#timer = new VaultTimer(this.lock.bind(this), this.#timeout) BROWSER: postMessage('unlocked') NODE: this.#parentPort?.postMessage('unlocked') }) @@ -317,7 +333,7 @@ export class VaultWorker { } return WalletAesGcm.encrypt(this.#type, key, this.#seed, this.#mnemonic) .then(({ iv, encrypted }) => { - this.#timer = new VaultTimer(() => this.lock(), 120000) + this.#timer = new VaultTimer(() => this.lock(), this.#timeout) return { iv, salt, encrypted } }) } catch (err) { @@ -450,7 +466,20 @@ export class VaultWorker { : undefined delete data.message - return { seed, mnemonicPhrase, mnemonicSalt, encrypted, index, message } + // Vault configuration + if (action === 'config') { + if (data.timeout == null) { + throw new TypeError('Configuration not found') + } + if (typeof data.timeout !== 'number') { + throw new TypeError('Invalid timeout configuration') + } + } + const timeout = typeof data.timeout === 'number' + ? data.timeout + : undefined + + return { seed, mnemonicPhrase, mnemonicSalt, encrypted, index, message, timeout } } catch (err) { console.error(err) throw new Error('Failed to extract data', { cause: err }) @@ -543,17 +572,6 @@ export class VaultWorker { return data.action } - // Action for configuring vault - #parseConfig (action: string, data: { [key: string]: unknown }) { - const config: any = {} - if (action === 'config') { - if (data.timeout != null) { - config.timeout = data.timeout - } - } - return config - } - // Worker message data itself #parseData (data: unknown) { if (data == null) {