Skip to content
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
5 changes: 3 additions & 2 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,11 @@ Each non-empty line must use:
```env
Key1=new:val
Key2=update:val
Key3=delete:val
Key3=delete
```

The action must be `new`, `update`, or `delete`. Keys must be unique within the file; duplicate keys fail the request before any write is attempted.
The action must be `new`, `update`, or `delete`. `new` and `update` require a value after `:`;
`delete` only needs the key name and action. Keys must be unique within the file; duplicate keys fail the request before any write is attempted.

Supported request formats:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,13 @@ private EnvSecretOperation parseOperationLine(String line, int lineNumber) {

String actionAndValue = line.substring(equalsIndex + 1);
int colonIndex = actionAndValue.indexOf(':');
if (colonIndex < 0) {
if (colonIndex < 0 && actionAndValue.isBlank()) {
throw invalidLine(lineNumber);
}

String actionText = actionAndValue.substring(0, colonIndex).trim().toLowerCase(Locale.ROOT);
String actionText = colonIndex < 0
? actionAndValue.trim().toLowerCase(Locale.ROOT)
: actionAndValue.substring(0, colonIndex).trim().toLowerCase(Locale.ROOT);
EnvAction action = switch (actionText) {
case "new" -> EnvAction.NEW;
case "update" -> EnvAction.UPDATE;
Expand All @@ -129,13 +131,17 @@ private EnvSecretOperation parseOperationLine(String line, int lineNumber) {
+ ": expected new, update, or delete");
};

String value = actionAndValue.substring(colonIndex + 1);
if (colonIndex < 0 && action != EnvAction.DELETE) {
throw invalidLine(lineNumber);
}

String value = colonIndex < 0 ? "" : actionAndValue.substring(colonIndex + 1);
return new EnvSecretOperation(key, action, value);
}

private IllegalArgumentException invalidLine(int lineNumber) {
return new IllegalArgumentException("Invalid .env entry on line " + lineNumber
+ ": expected KEY=action:value");
+ ": expected KEY=new:value, KEY=update:value, or KEY=delete");
}

private void validateOperationPreconditions(String user, List<EnvSecretOperation> operations) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public void testPostSecret() throws Exception {

@Test
public void testPostEnvFileAsPlainText() throws Exception {
String envFile = "Key1=new:val\nKey2=update:other\nKey3=delete:ignored\n";
String envFile = "Key1=new:val\nKey2=update:other\nKey3=delete\n";
when(envFileService.execute(eq("user1"), eq(envFile)))
.thenReturn(ResponseEntity.ok("processed"));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ void testExecuteProcessesEnvFileOperations() {
ResponseEntity<String> response = envFileService.execute("user1", """
Key1=new:val
Key2=update:next:with:colons
Key3=delete:ignored
Key3=delete
""");

assertEquals(HttpStatus.OK, response.getStatusCode());
Expand Down Expand Up @@ -96,6 +96,16 @@ void testExecuteRejectsInvalidAction() {
verifyNoInteractions(secretPartRepository, postSecretService, putSecretService, deleteSecretService);
}

@Test
void testExecuteRejectsNewWithoutValueDelimiter() {
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
() -> envFileService.execute("user1", "Key1=new"));

assertEquals("Invalid .env entry on line 1: expected KEY=new:value, KEY=update:value, or KEY=delete",
exception.getMessage());
verifyNoInteractions(secretPartRepository, postSecretService, putSecretService, deleteSecretService);
}

@Test
void testExecuteRejectsExistingSecretForNewOperation() {
when(secretPartRepository.exists(new SecretKey("user1", "Key1"))).thenReturn(true);
Expand Down
Loading