Skip to content

Commit

Permalink
Merge pull request #803 from MatrixAI/feature-unix-rm
Browse files Browse the repository at this point in the history
Implementing `secrets rm` RPC handler
  • Loading branch information
aryanjassal committed Sep 16, 2024
2 parents 8490111 + f0ae66b commit 3dd7f22
Show file tree
Hide file tree
Showing 10 changed files with 350 additions and 110 deletions.
6 changes: 3 additions & 3 deletions src/client/callers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ import vaultsPermissionUnset from './vaultsPermissionUnset';
import vaultsPull from './vaultsPull';
import vaultsRename from './vaultsRename';
import vaultsScan from './vaultsScan';
import vaultsSecretsDelete from './vaultsSecretsDelete';
import vaultsSecretsEdit from './vaultsSecretsEdit';
import vaultsSecretsEnv from './vaultsSecretsEnv';
import vaultsSecretsGet from './vaultsSecretsGet';
Expand All @@ -72,6 +71,7 @@ import vaultsSecretsMkdir from './vaultsSecretsMkdir';
import vaultsSecretsNew from './vaultsSecretsNew';
import vaultsSecretsNewDir from './vaultsSecretsNewDir';
import vaultsSecretsRename from './vaultsSecretsRename';
import vaultsSecretsRemove from './vaultsSecretsRemove';
import vaultsSecretsStat from './vaultsSecretsStat';
import vaultsVersion from './vaultsVersion';

Expand Down Expand Up @@ -144,7 +144,6 @@ const clientManifest = {
vaultsPull,
vaultsRename,
vaultsScan,
vaultsSecretsDelete,
vaultsSecretsEdit,
vaultsSecretsEnv,
vaultsSecretsGet,
Expand All @@ -153,6 +152,7 @@ const clientManifest = {
vaultsSecretsNew,
vaultsSecretsNewDir,
vaultsSecretsRename,
vaultsSecretsRemove,
vaultsSecretsStat,
vaultsVersion,
};
Expand Down Expand Up @@ -224,7 +224,6 @@ export {
vaultsPull,
vaultsRename,
vaultsScan,
vaultsSecretsDelete,
vaultsSecretsEdit,
vaultsSecretsEnv,
vaultsSecretsGet,
Expand All @@ -233,6 +232,7 @@ export {
vaultsSecretsNew,
vaultsSecretsNewDir,
vaultsSecretsRename,
vaultsSecretsRemove,
vaultsSecretsStat,
vaultsVersion,
};
12 changes: 0 additions & 12 deletions src/client/callers/vaultsSecretsDelete.ts

This file was deleted.

12 changes: 12 additions & 0 deletions src/client/callers/vaultsSecretsRemove.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { HandlerTypes } from '@matrixai/rpc';
import type VaultsSecretsRemove from '../handlers/VaultsSecretsRemove';
import { UnaryCaller } from '@matrixai/rpc';

type CallerTypes = HandlerTypes<VaultsSecretsRemove>;

const vaultsSecretsRemove = new UnaryCaller<
CallerTypes['input'],
CallerTypes['output']
>();

export default vaultsSecretsRemove;
50 changes: 0 additions & 50 deletions src/client/handlers/VaultsSecretsDelete.ts

This file was deleted.

55 changes: 55 additions & 0 deletions src/client/handlers/VaultsSecretsRemove.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import type { DB } from '@matrixai/db';
import type {
ClientRPCRequestParams,
ClientRPCResponseResult,
SuccessMessage,
SecretRemoveMessage,
} from '../types';
import type VaultManager from '../../vaults/VaultManager';
import { UnaryHandler } from '@matrixai/rpc';
import * as vaultsUtils from '../../vaults/utils';
import * as vaultsErrors from '../../vaults/errors';
import * as vaultOps from '../../vaults/VaultOps';

class VaultsSecretsRemove extends UnaryHandler<
{
vaultManager: VaultManager;
db: DB;
},
ClientRPCRequestParams<SecretRemoveMessage>,
ClientRPCResponseResult<SuccessMessage>
> {
public handle = async (
input: ClientRPCRequestParams<SecretRemoveMessage>,
): Promise<ClientRPCResponseResult<SuccessMessage>> => {
const { vaultManager, db } = this.container;
// Create a record of secrets to be removed, grouped by vault names
const vaultGroups: Record<string, string[]> = {};
input.secretNames.forEach(([vaultName, secretName]) => {
if (vaultGroups[vaultName] == null) {
vaultGroups[vaultName] = [];
}
vaultGroups[vaultName].push(secretName);
});
await db.withTransactionF(async (tran) => {
for (const [vaultName, secretNames] of Object.entries(vaultGroups)) {
const vaultIdFromName = await vaultManager.getVaultId(vaultName, tran);
const vaultId = vaultIdFromName ?? vaultsUtils.decodeVaultId(vaultName);
if (vaultId == null) throw new vaultsErrors.ErrorVaultsVaultUndefined();
await vaultManager.withVaults(
[vaultId],
async (vault) => {
await vaultOps.deleteSecret(vault, secretNames, {
recursive: input.options?.recursive,
});
},
tran,
);
}
});

return { success: true };
};
}

export default VaultsSecretsRemove;
6 changes: 3 additions & 3 deletions src/client/handlers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ import VaultsPermissionUnset from './VaultsPermissionUnset';
import VaultsPull from './VaultsPull';
import VaultsRename from './VaultsRename';
import VaultsScan from './VaultsScan';
import VaultsSecretsDelete from './VaultsSecretsDelete';
import VaultsSecretsEdit from './VaultsSecretsEdit';
import VaultsSecretsEnv from './VaultsSecretsEnv';
import VaultsSecretsGet from './VaultsSecretsGet';
Expand All @@ -89,6 +88,7 @@ import VaultsSecretsMkdir from './VaultsSecretsMkdir';
import VaultsSecretsNew from './VaultsSecretsNew';
import VaultsSecretsNewDir from './VaultsSecretsNewDir';
import VaultsSecretsRename from './VaultsSecretsRename';
import VaultsSecretsRemove from './VaultsSecretsRemove';
import VaultsSecretsStat from './VaultsSecretsStat';
import VaultsVersion from './VaultsVersion';

Expand Down Expand Up @@ -184,7 +184,6 @@ const serverManifest = (container: {
vaultsPull: new VaultsPull(container),
vaultsRename: new VaultsRename(container),
vaultsScan: new VaultsScan(container),
vaultsSecretsDelete: new VaultsSecretsDelete(container),
vaultsSecretsEdit: new VaultsSecretsEdit(container),
vaultsSecretsEnv: new VaultsSecretsEnv(container),
vaultsSecretsGet: new VaultsSecretsGet(container),
Expand All @@ -193,6 +192,7 @@ const serverManifest = (container: {
vaultsSecretsNew: new VaultsSecretsNew(container),
vaultsSecretsNewDir: new VaultsSecretsNewDir(container),
vaultsSecretsRename: new VaultsSecretsRename(container),
vaultsSecretsRemove: new VaultsSecretsRemove(container),
vaultsSecretsStat: new VaultsSecretsStat(container),
vaultsVersion: new VaultsVersion(container),
};
Expand Down Expand Up @@ -266,7 +266,6 @@ export {
VaultsPull,
VaultsRename,
VaultsScan,
VaultsSecretsDelete,
VaultsSecretsEdit,
VaultsSecretsEnv,
VaultsSecretsGet,
Expand All @@ -275,6 +274,7 @@ export {
VaultsSecretsNew,
VaultsSecretsNewDir,
VaultsSecretsRename,
VaultsSecretsRemove,
VaultsSecretsStat,
VaultsVersion,
};
8 changes: 8 additions & 0 deletions src/client/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,13 @@ type SecretPathMessage = {

type SecretIdentifierMessage = VaultIdentifierMessage & SecretPathMessage;

type SecretRemoveMessage = {
secretNames: Array<Array<string>>;
options?: {
recursive?: boolean;
};
};

// Contains binary content as a binary string 'toString('binary')'
type ContentMessage = {
secretContent: string;
Expand Down Expand Up @@ -416,6 +423,7 @@ export type {
VaultsLatestVersionMessage,
SecretPathMessage,
SecretIdentifierMessage,
SecretRemoveMessage,
ContentMessage,
SecretContentMessage,
SecretMkdirMessage,
Expand Down
54 changes: 28 additions & 26 deletions src/vaults/VaultOps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,37 +129,39 @@ async function statSecret(vault: Vault, secretName: string): Promise<Stat> {
*/
async function deleteSecret(
vault: Vault,
secretName: string,
secretNames: Array<string>,
fileOptions?: FileOptions,
logger?: Logger,
): Promise<void> {
try {
await vault.writeF(async (efs) => {
const stat = await efs.stat(secretName);
if (stat.isDirectory()) {
await efs.rmdir(secretName, fileOptions);
logger?.info(`Deleted directory at '${secretName}'`);
} else {
// Remove the specified file
await efs.unlink(secretName);
logger?.info(`Deleted secret at '${secretName}'`);
await vault.writeF(async (efs) => {
for (const secretName of secretNames) {
try {
const stat = await efs.stat(secretName);
if (stat.isDirectory()) {
await efs.rmdir(secretName, fileOptions);
logger?.info(`Deleted directory at '${secretName}'`);
} else {
// Remove the specified file
await efs.unlink(secretName);
logger?.info(`Deleted secret at '${secretName}'`);
}
} catch (e) {
if (e.code === 'ENOENT') {
throw new vaultsErrors.ErrorSecretsSecretUndefined(
`Secret with name: ${secretName} does not exist`,
{ cause: e },
);
}
if (e.code === 'ENOTEMPTY') {
throw new vaultsErrors.ErrorVaultsRecursive(
`Could not delete directory '${secretName}' without recursive option`,
{ cause: e },
);
}
throw e;
}
});
} catch (e) {
if (e.code === 'ENOENT') {
throw new vaultsErrors.ErrorSecretsSecretUndefined(
`Secret with name: ${secretName} does not exist`,
{ cause: e },
);
}
if (e.code === 'ENOTEMPTY') {
throw new vaultsErrors.ErrorVaultsRecursive(
`Could not delete directory '${secretName}' without recursive option`,
{ cause: e },
);
}
throw e;
}
});
}

/**
Expand Down
Loading

0 comments on commit 3dd7f22

Please sign in to comment.