Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing secrets rm RPC handler #803

Merged
merged 1 commit into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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