Skip to content

Commit 27ee37e

Browse files
CDeltakaiaryanjassal
authored andcommitted
feat: added helper method to CommandRename for secrets to process the new secret name and ensure its a valid base name even with the vaultName:secret syntax
1 parent 9180ec4 commit 27ee37e

File tree

1 file changed

+76
-3
lines changed

1 file changed

+76
-3
lines changed

src/secrets/CommandRename.ts

Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,25 @@ class CommandRename extends CommandPolykey {
2020
this.addOption(binOptions.nodeId);
2121
this.addOption(binOptions.clientHost);
2222
this.addOption(binOptions.clientPort);
23-
this.action(async (secretPath, newSecretName, options) => {
23+
this.action(async (secretPath, newSecretNameArg, options) => {
2424
// Ensure that a valid secret path is provided
25-
if (secretPath[1] == null) {
25+
if (
26+
secretPath[1] == null ||
27+
secretPath[1].trim() === '' ||
28+
secretPath[1].trim() === '/'
29+
) {
2630
throw new errors.ErrorPolykeyCLIRenameSecret(
2731
'EPERM: Cannot rename vault root',
2832
);
2933
}
34+
35+
// Process the newSecretNameArg using the abstracted helper method.
36+
// secretPath[0] is the original vault name.
37+
const finalNewSecretName = CommandRename._processNewSecretNameArgument(
38+
newSecretNameArg,
39+
secretPath[0],
40+
);
41+
3042
const { default: PolykeyClient } = await import(
3143
'polykey/PolykeyClient.js'
3244
);
@@ -63,7 +75,7 @@ class CommandRename extends CommandPolykey {
6375
metadata: auth,
6476
nameOrId: secretPath[0],
6577
secretName: secretPath[1],
66-
newSecretName: newSecretName,
78+
newSecretName: newSecretNameArg,
6779
}),
6880
meta,
6981
);
@@ -72,6 +84,67 @@ class CommandRename extends CommandPolykey {
7284
}
7385
});
7486
}
87+
88+
/**
89+
* Processes the newSecretName argument to ensure it's a valid base name.
90+
*/
91+
private static _processNewSecretNameArgument(
92+
newSecretNameArg: string,
93+
originalVaultName: string,
94+
): string {
95+
let finalNewBaseName = newSecretNameArg;
96+
97+
if (newSecretNameArg.includes(':')) {
98+
let parsedNewPath: Array<any>;
99+
try {
100+
parsedNewPath = binParsers.parseSecretPath(newSecretNameArg);
101+
} catch (e: any) {
102+
throw new errors.ErrorPolykeyCLIRenameSecret(
103+
`EINVALID: The new secret name '${newSecretNameArg}' appears to be a path but could not be parsed: ${e.message}`,
104+
);
105+
}
106+
const newVaultNameInArg = parsedNewPath[0];
107+
const newSecretPathPart = parsedNewPath[1];
108+
if (newVaultNameInArg !== originalVaultName) {
109+
throw new errors.ErrorPolykeyCLIRenameSecret(
110+
`ECROSSVAULT: Renaming to a different vault ('${newVaultNameInArg}') is not supported by this command. The target vault must be the same as the source vault ('${originalVaultName}').`,
111+
);
112+
}
113+
if (
114+
newSecretPathPart == null ||
115+
newSecretPathPart.trim() === '' ||
116+
newSecretPathPart.trim() === '/'
117+
) {
118+
throw new errors.ErrorPolykeyCLIRenameSecret(
119+
`EINVALID: The path component of the new secret name '${newSecretNameArg}' is empty or invalid.`,
120+
);
121+
}
122+
const parts = newSecretPathPart.split('/').filter((p) => p.length > 0);
123+
if (parts.length === 0) {
124+
throw new errors.ErrorPolykeyCLIRenameSecret(
125+
`EINVALID: Could not extract a valid base name from the path component '${newSecretPathPart}' in '${newSecretNameArg}'.`,
126+
);
127+
}
128+
finalNewBaseName = parts[parts.length - 1];
129+
} else {
130+
if (newSecretNameArg.includes('/')) {
131+
throw new errors.ErrorPolykeyCLIRenameSecret(
132+
`EINVALIDNAME: The new secret name '${newSecretNameArg}' must be a base name and cannot contain '/'. If you intended to specify a path, include the vault name (e.g., '${originalVaultName}:/path/NewName').`,
133+
);
134+
}
135+
}
136+
if (!finalNewBaseName || finalNewBaseName.trim() === '') {
137+
throw new errors.ErrorPolykeyCLIRenameSecret(
138+
`EEMPTYNAME: The new secret name derived from '${newSecretNameArg}' is empty.`,
139+
);
140+
}
141+
if (finalNewBaseName.includes('/') || finalNewBaseName.includes(':')) {
142+
throw new errors.ErrorPolykeyCLIRenameSecret(
143+
`EINVALIDCHAR: The final new secret name '${finalNewBaseName}' (derived from '${newSecretNameArg}') is invalid. It cannot contain '/' or ':' characters.`,
144+
);
145+
}
146+
return finalNewBaseName;
147+
}
75148
}
76149

77150
export default CommandRename;

0 commit comments

Comments
 (0)