Commit Graph

2053 Commits

Author SHA1 Message Date
shum 2baa868bc0 refactor: parameterize XFTP store with FSType singleton dispatch 2026-04-14 13:30:33 +00:00
shum 7aabf24eb0 refactor: stream export instead of loading recipients into memory 2026-04-13 11:19:16 +00:00
shum 509b1c712e perf: batch expired file deletions with deleteFiles 2026-04-13 10:01:50 +00:00
shum c68859e93c refactor: use SQL-standard type names in XFTP schema 2026-04-13 09:54:16 +00:00
shum 1c559a5454 fix: move file_size check from PG schema to store log import 2026-04-13 09:50:59 +00:00
shum 50c387d376 refactor: rename XFTPTestBracket to XFTPTestServer 2026-04-11 13:33:50 +00:00
shum e53046399d refactor: close store log inside closeFileStore for STM backend
Move STM store log close responsibility into closeFileStore to
match PostgresFileStore, removing the asymmetry where only PG's
close was self-contained.

STMFileStore holds the log in a TVar populated by newXFTPServerEnv
after readWriteFileStore; stopServer no longer needs the explicit
withFileLog closeStoreLog call. Writes still go through XFTPEnv.storeLog
via withFileLog (unchanged).
2026-04-11 13:03:44 +00:00
shum 3f81291e72 refactor: rename withSTMFile back to withFile 2026-04-11 12:50:15 +00:00
shum 1f8bd6bbf6 refactor: restore getFile position to match master 2026-04-11 12:43:36 +00:00
shum b5055ad68c refactor: minimize diff in tests
Restore xftpServerTests and xftpAgentTests bodies to match master
byte-for-byte (only type signatures change for XFTPTestBracket
parameterization); inline the runTestXXX helpers that were split
on this branch.
2026-04-11 12:36:16 +00:00
shum fcbb13e23c refactor: parameterize XFTPServerConfig over store type
Embed XFTPStoreConfig s as serverStoreCfg field, matching SMP's
ServerConfig. runXFTPServer and newXFTPServerEnv now take a single
XFTPServerConfig s. Restore verifyCmd local helper structure.
2026-04-11 12:36:10 +00:00
shum 26bcc72340 refactor: extract rowToFileRec shared by getFile sender/recipient paths 2026-04-11 09:31:25 +00:00
shum 6cac469cf7 refactor: merge file_size CHECK into initial migration 2026-04-11 09:01:23 +00:00
shum aee5558e5a feat: add manual tests and guide 2026-04-11 08:04:02 +00:00
shum 8a8bda2dc1 refactor: remove dead test wrappers after parameterization
Remove old non-parameterized test wrapper functions that were
superseded by the store-backend-parameterized test suites.
All test bodies (run* and _ functions) are preserved and called
from the parameterized specs. Clean up unused imports.
2026-04-08 08:17:23 +00:00
shum e63e0be2ac test: parameterize XFTP server, agent and CLI tests over store backend
- xftpTest/xftpTest2/xftpTest4/xftpTestN now take XFTPTestBracket as
  first argument, enabling the same test to run against both memory
  and PostgreSQL backends.

- xftpFileTests (server tests), xftpAgentFileTests (agent tests), and
  xftpCLIFileTests (CLI tests) are SpecWith-parameterized suites that
  receive the bracket from HSpec's before combinator.

- Test.hs runs each parameterized suite twice: once with
  xftpMemoryBracket, once with xftpPostgresBracket (CPP-guarded).

- STM-specific tests (store log restore/replay) stay in memory-only
  xftpAgentTests. SNI/CORS tests stay in memory-only xftpServerTests.
2026-04-07 18:45:25 +00:00
shum 37b3ad027e refactor: clean up per good-code review
- Remove internal helpers from Postgres.hs export list (withDB, withDB',
  handleDuplicate, assertUpdated, withLog are not imported externally)
- Replace local isNothing_ with Data.Maybe.isNothing in Env.hs
- Consolidate duplicate/unused imports in XFTPStoreTests.hs
- Add file_path IS NULL and status guards to STM setFilePath, matching
  the Postgres implementation semantics
2026-04-07 13:51:49 +00:00
shum 5de4f78e50 refactor: merge STM store into Store.hs, parameterize server tests
- Move STMFileStore and its FileStoreClass instance from Store/STM.hs
  back into Store.hs — the separate file was unnecessary indirection
  for the always-present default implementation.

- Parameterize xftpFileTests over store backend using HSpec SpecWith
  pattern (following SMP's serverTests approach). The same 11 tests
  now run against both memory and PostgreSQL backends via a bracket
  parameter, eliminating all *Pg test duplicates.

- Extract shared run* functions (runTestFileChunkDeliveryAddRecipients,
  runTestWrongChunkSize, runTestFileChunkExpiration, runTestFileStorageQuota)
  from inlined test bodies.
2026-04-07 12:08:41 +00:00
shum 464e083c3a fix: check deleteFile result in expireServerFiles
deleteFile result was discarded with void. If a concurrent delete
already removed the file, deleteFile returned AUTH but usedStorage
was still decremented — causing double-decrement drift. Now the
usedStorage adjustment and filesExpired stat only run on success.
2026-04-02 15:50:14 +00:00
shum 1c6f68873a fix: check storeAction result in deleteOrBlockServerFile_
The store action result (deleteFile/blockFile) was discarded with void.
If the DB row was already deleted by a concurrent operation, the
function still decremented usedStorage, causing drift. Now the error
propagates via ExceptT, skipping the usedStorage adjustment.
2026-04-02 13:21:55 +00:00
shum e659f4a64e fix: clean up disk file when setFilePath fails in receiveServerFile
When setFilePath fails (file deleted or blocked concurrently, or
duplicate upload), the uploaded file was left orphaned on disk with
no DB record pointing to it. Now the file is removed on failure,
matching the cleanup in the receiveChunk error path.
2026-04-02 13:16:58 +00:00
shum c306e9bcd3 fix: check for existing data before database import
importFileStore now checks if the target database already contains
files and aborts with an error. Previously, importing into a non-empty
database would fail mid-COPY on duplicate primary keys, leaving the
database in a partially imported state.
2026-04-02 12:45:52 +00:00
shum e831d5a022 fix: add CHECK constraint on file_size > 0
Prevents negative or zero file_size values at the database level.
Without this, corrupted data from import or direct DB access could
cause incorrect storage accounting (getUsedStorage sums file_size,
and expiredFiles casts to Word32 which wraps negative values).
2026-04-02 12:45:06 +00:00
shum c1f978a4af fix: reject upload to blocked file in Postgres setFilePath
In Postgres mode, getFile returns a snapshot TVar for fileStatus. If a
file is blocked between getFile and setFilePath, the stale status check
passes but the upload should be rejected. Added status = 'active' to
the UPDATE WHERE clause so blocked files cannot receive uploads.
2026-04-02 12:44:14 +00:00
shum e5f664815f fix: escape double quotes in COPY CSV status field
The status field (e.g. "blocked,reason=spam,notice={...}") is quoted in
CSV for COPY protocol, but embedded double quotes from BlockingInfo
notice (JSON) were not escaped. This could break CSV parsing during
import. Now double quotes are escaped as "" per CSV spec.
2026-04-02 12:43:27 +00:00
shum 0d28333919 fix: handle setFilePath error in receiveServerFile
setFilePath result was discarded with void. If it failed (file deleted
concurrently, or double-upload where file_path IS NULL guard rejected
the second write), the server still reported FROk, incremented stats,
and left usedStorage permanently inflated. Now the error is checked:
on failure, reserved storage is released and AUTH is returned.
2026-04-02 12:42:16 +00:00
shum dd395b4a06 fix: only decrement usedStorage for uploaded files on expiration
expireServerFiles unconditionally subtracted file_size from usedStorage
for every expired file, including files that were never uploaded (no
file_path). Since reserve only increments usedStorage during upload,
expiring never-uploaded files caused usedStorage to drift negative.
2026-04-02 12:41:30 +00:00
shum d101a9b764 fix: map ForeignKeyViolation to AUTH in addRecipient
When a file is concurrently deleted while addRecipient runs, the FK
constraint on recipients.sender_id raises ForeignKeyViolation. Previously
this propagated as INTERNAL; now it returns AUTH (file not found).
2026-04-02 12:40:40 +00:00
shum dea62cc349 test: add PostgreSQL backend tests 2026-04-01 15:52:01 +00:00
shum aacd873dff feat: add database import/export CLI commands 2026-04-01 14:54:40 +00:00
shum d6b6cd5c88 feat: add PostgreSQL INI config, store dispatch, startup validation 2026-04-01 14:35:22 +00:00
shum ae4888fc6e feat: implement PostgresFileStore operations 2026-04-01 14:10:53 +00:00
shum cde9f50544 feat: add PostgreSQL store skeleton with schema migration 2026-04-01 13:52:54 +00:00
shum ff254b451b refactor: make XFTPEnv and server polymorphic over FileStoreClass 2026-04-01 13:34:35 +00:00
shum 6f4bf647ed refactor: extract FileStoreClass typeclass, move STM impl to Store.STM 2026-04-01 13:22:14 +00:00
shum b0da98273b refactor: change file store operations from STM to IO 2026-04-01 13:14:31 +00:00
shum 8e449b8476 refactor: add getUsedStorage, getFileCount, expiredFiles store functions 2026-04-01 13:07:53 +00:00
shum d703cfae87 refactor: move usedStorage from FileStore to XFTPEnv 2026-04-01 12:59:48 +00:00
shum 2caf2e54e2 add implementation plan 2026-04-01 12:53:04 +00:00
shum 1bf3211d6e adjust styling 2026-04-01 11:30:36 +00:00
shum 7a76102001 update doc 2026-04-01 07:53:50 +00:00
shum 704cdac72b xftp: add PostgreSQL backend design spec 2026-03-31 12:58:42 +00:00
sh 1a12ee0a5a xftp-web: version bump to 0.3.0 (#1742) 2026-03-20 11:43:43 +00:00
sh efcef2d1fd xftp-web: add postgres schema cleanup for integration tests (#1741)
Stale postgres schema leaked pending XFTP operations between
cross-language tests, causing N-1 of N tests to fail.
2026-03-20 09:58:56 +00:00
Evgeny 963d7b2f75 fix small bugs (#1740)
* fix small bugs

* toChunks
2026-03-20 08:59:38 +00:00
Evgeny Poberezkin 4e4e0a4f42 6.5.0.11 v6.5.0-beta.6 2026-03-17 09:26:02 +00:00
sh 082a6c6f22 web: serve on-the-fly compressed gzip static files (#1735)
* web: serve pre-compressed gzip static files

* web: compress static files on the fly instead of pre-compressed
2026-03-16 09:08:43 +00:00
sh dc2921e4ce xftp-server: embed file download widget in XFTP server web page (#1733)
* xftp-server: embed file download widget in XFTP server web page

When a URL has a hash fragment (>50 chars), the server page shows the
file download UI instead of the server info page. Embeds xftp-web
assets (JS, CSS, crypto worker) and protocol overlay with matching
website content. Overlay renders below the server navbar.

* xftp-server: fix overlay scroll lock, remove extra margin, fix dark SVG

* xftp-server: move file transfer widget to standalone /file page

* web: collapse all repeated Nothing sections in render

section_ only collapsed the first occurrence of a section when content
was Nothing, leaving subsequent sections with the same label intact.
This caused SMP server pages to show raw <x-xftpConfig> tags.

* xftp-server: update bundled css/js

* xftp-server: move file.html to xftp-server, rename xftp bundle dir

* web: remove unused server-info wrapper div

* refactor

* fix

---------

Co-authored-by: Evgeny <evgeny@poberezkin.com>
2026-03-13 16:00:02 +00:00
sh 5a32e729e0 xftp-web: add "Upload your file" link after download completes (#1736)
* xftp-web: add "Upload your file" link after download completes

* xftp-web: call initUpload directly instead of hashchange dispatch
2026-03-13 15:01:15 +00:00
sh 782cacfb3c fix: using simplexmq as dependency (move embedFile to executables) (#1734)
* web: parameterize generateSite, remove Embedded from library

Move embedFile/embedDir out of the library so it works when
simplexmq is consumed as a dependency. generateSite now accepts
mediaContent, wellKnown, and linkHtml as parameters.

* smp-server, xftp-server: embed static files in executables

Add shared apps/common/Embedded.hs with TH splices, update SMPWeb
and XFTPWeb to pass embedded content to generateSite, move
file-embed dependency from library to executables and test suite.

* refactor

* add export, move common files to Web subfolder

* fix .cabal

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2026-03-12 17:05:00 +00:00