feat(backend): presence/typing tests and file message handling#256
Open
DeJune06 wants to merge 2 commits into
Open
feat(backend): presence/typing tests and file message handling#256DeJune06 wants to merge 2 commits into
DeJune06 wants to merge 2 commits into
Conversation
…ssage handling (codebestia#228) Issue codebestia#222 — add src/__tests__/presence.typing.test.ts covering multi-device aggregation, heartbeat timeout → offline, typing auto-expiry with zero DB writes, privacy suppression for non-members, and debounced transitions. Fake timers are used for all TTL/timeout assertions. Issue codebestia#228 — extend schema with a `files` table (pending→ready→deleted lifecycle) and `messageContentTypeEnum`; add `contentType` + `fileId` columns to `messages`; implement `send_file_message` socket handler that validates the referenced file is `ready` and belongs to the sender, then fans out via `io.to(conversationId).emit('new_message', …)` identical to text messages. `fileKey` is never stored or parsed server-side — it lives only inside the encrypted envelope ciphertext. Tests added in file.messages.test.ts.
|
@DeJune06 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
…bnail support
- apps/backend/src/db/schema.ts — extended `files` table with `size`, `mimeType`,
`sha256`, `storageKey`, and `isThumbnail` columns; all required by the upload
slot and thumbnail flows
- apps/backend/src/lib/storage.ts — `generatePresignedPut` (returns a presigned
PUT URL; swappable for S3/GCS SDK in production) and `generateStorageKey`
(deterministic per conversation+content)
- apps/backend/src/routes/uploads.ts — `POST /uploads` validates size (≤100 MB)
and MIME type against allowlist, verifies conversation membership, inserts a
`pending` file row, and returns `{ fileId, uploadUrl }`; `POST /uploads/:id/confirm`
transitions the row to `ready` after the client completes the PUT
- apps/backend/src/app.ts — registers `/uploads` router
- apps/backend/drizzle/0008_files_uploads.sql — migration for files table and
messages content_type/file_id columns
- apps/backend/src/__tests__/uploads.test.ts — 20 unit tests covering: valid slot
creation, size/MIME enforcement, membership check, pending insertion, confirm
lifecycle (200/404/403/409), thumbnail isThumbnail flag, missing thumbnail
graceful handling, and structural assertion that the route never imports any
image-processing library (server never generates previews from ciphertext)
closes codebestia#226
closes codebestia#230
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
closes #222
closes #228
closes #226
closes #230
Summary
Presence + typing tests #222 — Presence + typing tests: Added
src/__tests__/presence.typing.test.tswith 20 tests covering:File message construction (key inside the E2EE envelope) #228 — File message construction: Extended schema with a
filestable (pending → ready → deleted lifecycle) andmessageContentTypeEnum; addedcontentType+fileIdcolumns tomessages. Implementedsend_file_messagesocket handler that:ready, belongs to the conversation, and was uploaded by the senderio.to(conversationId).emit('new_message', …)— identical path to text messagesfileKeyserver-side; it remains inside the encrypted envelope ciphertext onlysrc/__tests__/file.messages.test.tsPOST /uploads— issue presigned upload + file record #226 —POST /uploadspresigned upload slot:src/routes/uploads.tsvalidates{ size, mimeType, sha256, conversationId }against size limit (100 MB) and MIME allowlist, verifies conversation membership, inserts apendingfile row, returns{ fileId, uploadUrl }.POST /uploads/:id/confirmtransitions toreadyafter the client completes the PUT. Extendedfilestable withsize,mimeType,sha256,storageKey,isThumbnailcolumns. Added migrationdrizzle/0008_files_uploads.sql. 15 unit tests.Client-encrypted thumbnails #230 — Client-encrypted thumbnails: Thumbnails upload via the same
POST /uploadsendpoint withisThumbnail: true; they are separatefilesrows. ThefileIdof the thumbnail rides inside the parent file message payload (E2EE envelope). Server never generates previews from ciphertext — structurally asserted in tests. Missing/optional thumbnail handled gracefully (isThumbnail defaults to false). 5 unit tests.Test plan
npx vitest run— all tests pass