Skip to content

Conversation

@pierre-lehnen-rc
Copy link
Contributor

@pierre-lehnen-rc pierre-lehnen-rc commented Jan 13, 2026

Proposed changes (including videos or screenshots)

Issue(s)

CORE-1666

Steps to test or reproduce

Further comments

API tests for this endpoint will be added to #32703

Summary by CodeRabbit

  • New Features
    • Users can delete individual uploaded files (permission-checked) via the API.
    • Files support optional expiration dates; UI now recognizes parsed expiration timestamps.
    • Thumbnails and derived formats are removed when a primary file is deleted.
    • File removal produces a notification entry in conversation history.
    • File attachments now include explicit file ID tracking.
    • Added "File removed" translation for English.

✏️ Tip: You can customize this high-level summary in your review settings.

@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented Jan 13, 2026

Looks like this PR is not ready to merge, because of the following issues:

  • This PR is targeting the wrong base branch. It should target 8.2.0, but it targets 8.1.0

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link

changeset-bot bot commented Jan 13, 2026

🦋 Changeset detected

Latest commit: 0085ab5

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 41 packages
Name Type
@rocket.chat/core-services Minor
@rocket.chat/model-typings Minor
@rocket.chat/core-typings Minor
@rocket.chat/models Minor
@rocket.chat/i18n Minor
@rocket.chat/meteor Minor
@rocket.chat/account-service Patch
@rocket.chat/authorization-service Patch
@rocket.chat/ddp-streamer Patch
@rocket.chat/omnichannel-transcript Patch
@rocket.chat/presence-service Patch
@rocket.chat/queue-worker Patch
@rocket.chat/abac Patch
@rocket.chat/federation-matrix Patch
@rocket.chat/network-broker Patch
@rocket.chat/omni-core-ee Patch
@rocket.chat/omnichannel-services Patch
@rocket.chat/presence Patch
rocketchat-services Patch
@rocket.chat/apps Patch
@rocket.chat/uikit-playground Patch
@rocket.chat/api-client Patch
@rocket.chat/cron Patch
@rocket.chat/ddp-client Patch
@rocket.chat/fuselage-ui-kit Major
@rocket.chat/gazzodown Major
@rocket.chat/http-router Patch
@rocket.chat/livechat Patch
@rocket.chat/rest-typings Minor
@rocket.chat/ui-avatar Major
@rocket.chat/ui-client Major
@rocket.chat/ui-contexts Major
@rocket.chat/ui-voip Major
@rocket.chat/web-ui-registration Major
@rocket.chat/license Patch
@rocket.chat/media-calls Patch
@rocket.chat/pdf-worker Patch
@rocket.chat/instance-status Patch
@rocket.chat/omni-core Patch
@rocket.chat/mock-providers Patch
@rocket.chat/ui-video-conf Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 13, 2026

Walkthrough

Adds a new authenticated REST endpoint POST /api/v1/uploads.delete and server-side UploadService methods to authorize and delete individual uploads (including derived thumbnails), updates message attachments when files are removed, and exposes related types, model queries, and client-side expiresAt handling.

Changes

Cohort / File(s) Summary
API registration & endpoint
apps/meteor/app/api/server/index.ts, apps/meteor/app/api/server/v1/uploads.ts
Registers uploads routes and implements POST /api/v1/uploads.delete with request validation, auth, and response schema returning deletedFiles.
Upload service implementation
apps/meteor/server/services/upload/service.ts
Adds canDeleteFile(userId, file, msg) and deleteFile(user, fileId, msg) with derivative (thumbnail) discovery/removal, message update to strip attachments, and per-derivative error logging.
Service & model typings
packages/core-services/src/types/IUploadService.ts, packages/model-typings/src/models/IUploadsModel.ts
Adds canDeleteFile and deleteFile to IUploadService; adds findAllByOriginalFileId to IUploadsModel.
Models: uploads query
packages/models/src/models/Uploads.ts
Implements findAllByOriginalFileId(originalFileId, options) returning a cursor for derived-file lookup.
Attachment & upload types
packages/core-typings/src/IUpload.ts, packages/core-typings/src/IMessage/MessageAttachment/Files/FileAttachmentProps.ts
Adds optional expiresAt?: Date to IUpload; refactors file attachment types with CommonFileProps and optional fileId.
Message/file creation payloads
apps/meteor/app/file-upload/server/methods/sendFileMessage.ts
Adds fileId: file._id to all file attachment payloads (image, audio, video, generic).
Client file lists mapping
apps/meteor/client/views/room/ImageGallery/hooks/useImagesList.ts, apps/meteor/client/views/room/contextualBar/RoomFiles/hooks/useFilesList.ts
Parse expiresAt into Date when present for file list/gallery mappings.
Authorization & constants
apps/meteor/app/authorization/server/functions/canDeleteMessage.ts, apps/meteor/lib/constants.ts, apps/meteor/app/lib/server/functions/cleanRoomHistory.ts
Makes ts parameter optional in canDeleteMessageAsync; exports NOTIFICATION_ATTACHMENT_COLOR and replaces hardcoded color in cleanRoomHistory.
API context & i18n
apps/meteor/app/api/server/definition.ts, packages/i18n/src/locales/en.i18n.json
Adds readonly logger: Logger to TypedThis context; adds translation key File_removed.
Release metadata
.changeset/forty-socks-roll.md
New changeset documenting minor version bumps and the new file deletion endpoint.

Sequence Diagram

sequenceDiagram
    participant Client as Client
    participant API as "API: /api/v1/uploads.delete"
    participant UploadSvc as UploadService
    participant Auth as Authorization
    participant Model as Uploads Model / DB
    participant Message as Message Store

    Client->>API: POST { fileId }
    API->>API: validate body (isUploadsDeleteParams)
    API->>UploadSvc: canDeleteFile(userId, file, msg?)
    UploadSvc->>Auth: check message perms / room access
    Auth-->>UploadSvc: permission result
    UploadSvc-->>API: canDelete (bool)
    API->>UploadSvc: deleteFile(user, fileId, msg?)
    UploadSvc->>Model: findAllByOriginalFileId(fileId) → derived files
    UploadSvc->>Model: remove main file
    UploadSvc->>Model: remove derived files (iterate)
    UploadSvc->>Message: updateMessageRemovingFiles(message, removedFileIds)
    Message->>Model: save updated message
    UploadSvc-->>API: { deletedFiles: [...] }
    API-->>Client: 200 OK with deletedFiles
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • d-gubert
  • cardoso
  • ricardogarim
  • tassoevan

Poem

🐰 I nibble bytes and tidy the heap,
Thumbs and kin fall silent, softly sleep.
One file gone, the message grows light,
Marshalled crumbs vanish out of sight—
Hooray, clean rooms and hops of delight! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature: a new endpoint to delete uploaded files individually, which directly addresses the PR's primary objective.
Linked Issues check ✅ Passed The PR implements the core objective from CORE-1666: adding API support to remove individual files from multi-file messages, including endpoint creation, authorization checks, and message attachment updates.
Out of Scope Changes check ✅ Passed All changes are directly related to file deletion functionality: API endpoint, authorization, file management service, database queries, type definitions, UI file list transformations, and supporting utilities.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/uploads.delete

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@pierre-lehnen-rc pierre-lehnen-rc added this to the 8.1.0 milestone Jan 13, 2026
@codecov
Copy link

codecov bot commented Jan 13, 2026

Codecov Report

❌ Patch coverage is 2.70270% with 36 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.77%. Comparing base (c4eff65) to head (0085ab5).
⚠️ Report is 1 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #38173      +/-   ##
===========================================
- Coverage    70.80%   70.77%   -0.03%     
===========================================
  Files         3159     3159              
  Lines       109364   109401      +37     
  Branches     19680    19884     +204     
===========================================
- Hits         77432    77426       -6     
- Misses       29897    29946      +49     
+ Partials      2035     2029       -6     
Flag Coverage Δ
e2e 60.34% <0.00%> (+0.02%) ⬆️
e2e-api 47.92% <2.77%> (-0.09%) ⬇️
unit 71.95% <ø> (-0.04%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 13, 2026

📦 Docker Image Size Report

➡️ Changes

Service Current Baseline Change Percent
sum of all images 0B 0B 0B
account-service 0B 0B 0B
authorization-service 0B 0B 0B
ddp-streamer-service 0B 0B 0B
omnichannel-transcript-service 0B 0B 0B
presence-service 0B 0B 0B
queue-worker-service 0B 0B 0B
rocketchat 0B 0B 0B

📊 Historical Trend

---
config:
  theme: "dark"
  xyChart:
    width: 900
    height: 400
---
xychart
  title "Image Size Evolution by Service (Last 30 Days + This PR)"
  x-axis ["11/18 22:53", "11/19 23:02", "11/21 16:49", "11/24 17:34", "11/27 22:32", "11/28 19:05", "12/01 23:01", "12/02 21:57", "12/03 21:00", "12/04 18:17", "12/05 21:56", "12/08 20:15", "12/09 22:17", "12/10 23:26", "12/11 21:56", "12/12 22:45", "12/13 01:34", "12/15 22:31", "12/16 22:18", "12/17 21:04", "12/18 23:12", "12/19 23:27", "12/20 21:03", "12/22 18:54", "12/23 16:16", "12/24 19:38", "12/25 17:51", "12/26 13:18", "12/29 19:01", "12/30 20:52", "01/27 15:50 (PR)"]
  y-axis "Size (GB)" 0 --> 0.5
  line "account-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.00]
  line "authorization-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.00]
  line "ddp-streamer-service" [0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.00]
  line "omnichannel-transcript-service" [0.14, 0.14, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.00]
  line "presence-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.00]
  line "queue-worker-service" [0.14, 0.14, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.00]
  line "rocketchat" [0.35, 0.35, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.00]
Loading

Statistics (last 30 days):

  • 📊 Average: 1.5GiB
  • ⬇️ Minimum: 1.4GiB
  • ⬆️ Maximum: 1.6GiB
  • 🎯 Current PR: 0B
ℹ️ About this report

This report compares Docker image sizes from this build against the develop baseline.

  • Tag: pr-38173
  • Baseline: develop
  • Timestamp: 2026-01-27 15:50:52 UTC
  • Historical data points: 30

Updated: Tue, 27 Jan 2026 15:50:53 GMT

@dougfabris dougfabris modified the milestones: 8.1.0, 8.2.0 Jan 19, 2026
@pierre-lehnen-rc pierre-lehnen-rc marked this pull request as ready for review January 19, 2026 20:20
@pierre-lehnen-rc pierre-lehnen-rc requested review from a team as code owners January 19, 2026 20:20
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 14 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="apps/meteor/app/api/server/v1/uploads.ts">

<violation number="1" location="apps/meteor/app/api/server/v1/uploads.ts:32">
P2: Response schema disallows the `success` field that `API.v1.success()` always adds, so response validation will fail when `additionalProperties: false` is enforced. Add `success` to the schema and required list.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@apps/meteor/app/api/server/v1/uploads.ts`:
- Around line 43-71: The endpoint definition uploadsDeleteEndpoint currently
declares its params under query and reads fileId from this.queryParams; change
the API.v1.post options to use body instead of query, update the validator
reference (isUploadsDeleteParams) to the body schema variant if one exists or
modify it to validate request body, and inside the action handler replace
this.queryParams usage with this.bodyParams (read fileId from body). Ensure the
request validation and any tests are updated accordingly so the POST accepts
fileId in the request body consistent with other v1 POST endpoints.

In `@packages/models/src/models/Uploads.ts`:
- Around line 96-99: The query in findAllByOriginalId is using the wrong field
name; update the filter in the method findAllByOriginalId to query { originalId:
originalFileId } (or rename the parameter to originalId and pass it directly) so
it matches the IUpload interface's originalId property; ensure the FindOptions
usage remains unchanged and run/adjust any related tests that expect derived
uploads to be found/deleted.
🧹 Nitpick comments (1)
apps/meteor/app/api/server/v1/uploads.ts (1)

86-88: Prefer self-documenting code over inline comments.

Consider extracting the permission check into a helper and drop inline comments to keep the implementation clean. As per coding guidelines, ...

@pierre-lehnen-rc pierre-lehnen-rc marked this pull request as draft January 20, 2026 13:13
@pierre-lehnen-rc pierre-lehnen-rc marked this pull request as ready for review January 20, 2026 16:44
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 15 files

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@packages/model-typings/src/models/IUploadsModel.ts`:
- Around line 21-22: The implementation of findAllByOriginalFileId has a
required parameter but the interface marks options as optional; update the
implementation of findAllByOriginalFileId(originalFileId: string, options?:
FindOptions<IUpload>) to make options optional (match the interface) and, if you
need a default, apply it inside the function body (e.g., const opts = options ??
{}) so the runtime behavior remains the same while the signature matches
IUploadsModel and uses the FindOptions<IUpload> type.

tassoevan
tassoevan previously approved these changes Jan 23, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@apps/meteor/server/services/upload/service.ts`:
- Around line 71-83: The code updates the message
(this.updateMessageRemovingFiles) before calling removeFileAndDerivates, which
can leave the UI inconsistent if store.deleteById fails; to fix, call await
this.removeFileAndDerivates(fileId, additionalFiles) first, capture its returned
deletedFiles, and only after successful deletion call
this.updateMessageRemovingFiles(msg, deletedFiles, user) (when msg is present),
then return the deletedFiles; ensure errors from removeFileAndDerivates
propagate so the message is not edited on failure.
🧹 Nitpick comments (3)
apps/meteor/server/services/upload/service.ts (3)

52-68: Remove inline comments in canDeleteFile.
The comments at Line 61 and Line 66 aren’t necessary given the readability of the code.

♻️ Suggested change
-		// If file is not confirmed and was sent by the same user
 		if (file.expiresAt && file.userId === userId) {
 			return canAccessRoomIdAsync(file.rid, userId);
 		}
 
-		// It's a confirmed file but it has no message, so use data from the file to run message delete permission checks
 		const msgForValidation = { u: { _id: file.userId }, ts: file.uploadedAt, rid: file.rid };
As per coding guidelines, avoid code comments in the implementation.

85-105: Remove inline comments in removeFileAndDerivates.
The comments at Line 90, Line 93, and Line 95 can be removed without losing clarity.

♻️ Suggested change
-		// Delete the main file first;
 		await store.deleteById(fileId);
 
-		// The main file is already deleted; From here forward we'll return a success response even if some sub-process fails
 		const deletedFiles: IUpload['_id'][] = [fileId];
-		// Delete them one by one as the store may include requests to external services
 		for await (const id of additionalFiles) {
As per coding guidelines, avoid code comments in the implementation.

112-121: Remove inline comment in updateMessageRemovingFiles.
The comment at Line 118 is unnecessary given the surrounding logic.

♻️ Suggested change
-			// If the attachment doesn't have a `fileId`, we assume it's an old message with only one file, in which case checking the id is not needed
 			if (attachment.fileId && !filesToRemove.includes(attachment.fileId)) {
As per coding guidelines, avoid code comments in the implementation.

@pierre-lehnen-rc pierre-lehnen-rc marked this pull request as draft January 26, 2026 22:36
@pierre-lehnen-rc
Copy link
Contributor Author

Setting it back to draft while we reconsider how encrypted files should be handled.

@pierre-lehnen-rc pierre-lehnen-rc marked this pull request as ready for review January 27, 2026 15:11
@pierre-lehnen-rc pierre-lehnen-rc added the stat: QA assured Means it has been tested and approved by a company insider label Jan 27, 2026
@dionisio-bot dionisio-bot bot added the stat: ready to merge PR tested and approved waiting for merge label Jan 27, 2026
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 17 files

@kodiakhq kodiakhq bot merged commit e57f158 into develop Jan 27, 2026
45 checks passed
@kodiakhq kodiakhq bot deleted the feat/uploads.delete branch January 27, 2026 16:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stat: QA assured Means it has been tested and approved by a company insider stat: ready to merge PR tested and approved waiting for merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants