From e0f062d833323e5cf96dd2dbcb1568425717bf53 Mon Sep 17 00:00:00 2001 From: Aryan Jassal Date: Tue, 20 Aug 2024 15:04:15 +1000 Subject: [PATCH] chore: added error handling for invalid patterns --- src/client/errors.ts | 6 +++ .../handlers/VaultsSecretsGetFileTree.ts | 37 +++++++++++++------ tests/client/handlers/vaults.test.ts | 15 ++++++++ 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/src/client/errors.ts b/src/client/errors.ts index 804a351d9..12a8093bd 100644 --- a/src/client/errors.ts +++ b/src/client/errors.ts @@ -18,6 +18,11 @@ class ErrorClientAuthDenied extends ErrorClient { exitCode = sysexits.NOPERM; } +class ErrorClientFileReadFailed extends ErrorClient { + static description = 'Failed to read file or directory'; + exitCode = sysexits.IOERR; +} + class ErrorClientService extends ErrorClient {} class ErrorClientServiceRunning extends ErrorClientService { @@ -45,6 +50,7 @@ export { ErrorClientAuthMissing, ErrorClientAuthFormat, ErrorClientAuthDenied, + ErrorClientFileReadFailed, ErrorClientService, ErrorClientServiceRunning, ErrorClientServiceNotRunning, diff --git a/src/client/handlers/VaultsSecretsGetFileTree.ts b/src/client/handlers/VaultsSecretsGetFileTree.ts index 438638ed0..9492f65ac 100644 --- a/src/client/handlers/VaultsSecretsGetFileTree.ts +++ b/src/client/handlers/VaultsSecretsGetFileTree.ts @@ -7,6 +7,7 @@ import { ServerHandler } from '@matrixai/rpc'; import { generateStats } from '../../vaults/fileTree'; import * as vaultsUtils from '../../vaults/utils'; import * as vaultsErrors from '../../vaults/errors'; +import * as clientErrors from '../errors'; class VaultsSecretsGetFileTree extends ServerHandler< { @@ -38,18 +39,32 @@ class VaultsSecretsGetFileTree extends ServerHandler< void, void > { - // @ts-ignore: While the types don't fully match, it matches enough for our usage. - let files: Array = await fs.promises.readdir(input.pattern); - files = files.map((file) => path.join(input.pattern, file)); + try { + // @ts-ignore: While the types don't fully match, it matches enough for our usage. + let files: Array = await fs.promises.readdir(input.pattern); + files = files.map((file) => path.join(input.pattern, file)); - for await (const file of files) { - const stat = await fs.promises.stat(file); - const type = stat.isFile() ? 'FILE' : 'DIRECTORY'; - yield { - path: file, - type: type, - stat: input.yieldStats ? generateStats(stat) : undefined, - }; + for await (const file of files) { + try { + const stat = await fs.promises.stat(file); + const type = stat.isFile() ? 'FILE' : 'DIRECTORY'; + yield { + path: file, + type: type, + stat: input.yieldStats ? generateStats(stat) : undefined, + }; + } catch (e) { + throw new clientErrors.ErrorClientFileReadFailed( + `Failed to read file: ${file}`, + { cause: e }, + ); + } + } + } catch (e) { + throw new clientErrors.ErrorClientFileReadFailed( + `Failed to read directory: ${input.pattern}`, + { cause: e }, + ); } }); }); diff --git a/tests/client/handlers/vaults.test.ts b/tests/client/handlers/vaults.test.ts index 71a190f8a..17e44dd50 100644 --- a/tests/client/handlers/vaults.test.ts +++ b/tests/client/handlers/vaults.test.ts @@ -69,6 +69,7 @@ import * as nodesUtils from '@/nodes/utils'; import * as vaultsUtils from '@/vaults/utils'; import * as vaultsErrors from '@/vaults/errors'; import * as networkUtils from '@/network/utils'; +import * as clientErrors from '@/client/errors'; import * as testsUtils from '../../utils'; describe('vaultsClone', () => { @@ -1588,6 +1589,20 @@ describe('vaultsSecretsNewDir and vaultsSecretsList', () => { }); expect(addResponse.success).toBeTruthy(); + expect(async () => { + const files = await rpcClient.methods.vaultsSecretsGetFileTree({ + nameOrId: vaultsIdEncoded, + pattern: 'doesntExist', + yieldStats: false, + }); + try { + for await (const _ of files); // Consume values + } + catch (e) { + throw e.cause; + } + }).rejects.toThrow(clientErrors.ErrorClientFileReadFailed); + // List secrets with names of directories const secrets = await rpcClient.methods.vaultsSecretsGetFileTree({ nameOrId: vaultsIdEncoded,