]> git.codecow.com Git - libnemo.git/commitdiff
Refactor timeout config.
authorChris Duncan <chris@zoso.dev>
Wed, 10 Sep 2025 04:44:32 +0000 (21:44 -0700)
committerChris Duncan <chris@zoso.dev>
Wed, 10 Sep 2025 04:44:32 +0000 (21:44 -0700)
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.

src/lib/vault/vault-worker.ts

index c9ac8bec19c49107011f649191e38e7726ed45b2..f2a2d02393813faec67ed571503a0af89bac51b3 100644 (file)
@@ -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<NamedData | void> => {
                                        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<void> {
-               if (typeof config.timeout === 'number') {
-                       this.#timeout = config.timeout
+       config (timeout?: number): Promise<void> {
+               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) {