dotCMS / dotCMS/core

fix(apps): DELETE /api/v1/apps/{key} returns OK but app remains visible and re-upload fails

Open
#34,981 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

OKR : Customer Support stale
Dominant language
Java
Stars
970
Forks
486
Avg merge
3d 33m
Merged PRs (30d)
170

Description

Problem Statement

DELETE /api/v1/apps/{key} has misleading behavior by default. When called without ?removeDescriptor=true, the endpoint:

  1. Deletes all per-site secrets from the keystore
  2. Returns 200 OK
  3. Leaves the YAML descriptor file on disk

This causes two user-facing bugs:

Bug 1 — App still visible after DELETE
After calling DELETE /api/v1/apps/{key}, invalidateCache() is called but the descriptor file remains on disk. On the next request to GET /api/v1/apps/, the file is re-read and the app reappears.

Bug 2 — Re-uploading the same app fails
createAppDescriptor() in AppsAPIImpl checks if the file already exists on disk before writing:

if (incomingFile.exists()) {
    throw new AlreadyExistException("Invalid attempt to override an existing file named '%s'.");
}

Since the descriptor was never removed, POST /api/v1/apps/ throws AlreadyExistException after a DELETE that returned 200 OK.

Secondary bug — misleading log in removeDescriptor()
Logger.warn() fires unconditionally before Files.delete(), not inside the catch block:

// Current (wrong):
Logger.warn(..., "Failed attempt to delete file with path `%s`", file);
Files.delete(file);

// Should be:
try {
    Files.delete(file);
} catch (IOException e) {
    Logger.warn(..., "Failed attempt to delete file with path `%s`", file);
    throw new DotDataException(e);
}

Steps to Reproduce

  1. Upload an app via POST /api/v1/apps/ with a YAML descriptor
  2. Call DELETE /api/v1/apps/{key} (without ?removeDescriptor=true)
  3. Observe 200 OK response
  4. Call GET /api/v1/apps/ — app still visible
  5. Attempt POST /api/v1/apps/ with the same YAML — receives AlreadyExistException error

Workaround: Use DELETE /api/v1/apps/{key}?removeDescriptor=true to fully remove the app.

Acceptance Criteria

  • DELETE /api/v1/apps/{key} without ?removeDescriptor=true should either remove the descriptor by default OR the API documentation/response must clearly communicate that secrets were deleted but the app descriptor remains
  • After a successful DELETE /api/v1/apps/{key}, POST /api/v1/apps/ with the same YAML must succeed
  • Logger.warn() in removeDescriptor() must only fire when Files.delete() actually fails (inside catch block)

dotCMS Version

Latest from main branch

Severity

Medium - Some functionality impacted

Affected Files

  • dotCMS/src/main/java/com/dotcms/rest/api/v1/apps/AppsResource.java
  • dotCMS/src/main/java/com/dotcms/security/apps/AppsAPIImpl.java
  • dotCMS/src/main/java/com/dotcms/rest/api/v1/apps/AppsHelper.java

Links

NA

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the DELETE handling in dotCMS/src/main/java/com/dotcms/rest/api/v1/apps/AppsResource.java and trace descriptor removal through AppsAPIImpl and AppsHelper. Verify the chosen default behavior against the listed reproduction steps, ensure the same YAML can be uploaded after a successful DELETE, and move the warning so it is emitted only when Files.delete() fails.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.