26 Commits
Author SHA1 Message Date
LeoVasanko 7a0e473fb4 Drop watch websockets on session loss, purge SSO cache on logout
- Successful SSO /auth/api/validate responses are cached per credential
  and perm/renew URL for 10s, so watch websocket re-checks do not hammer
  the auth backend. A POST to the logout endpoint purges all cached
  entries for the request's credentials immediately, so logout/login
  flows are not served stale successes.
- The watch websocket now re-validates auth before each forwarded
  message and every 10s when idle (SSO and built-in sessions alike).
  When the session is gone the client gets an auth error message and
  the socket is closed, instead of streaming updates forever.
- Token-authenticated (API/share token) sockets are exempt from
  re-validation; they are checked once at handshake.
2026-08-12 21:20:12 +00:00
LeoVasanko 0c3c3615ce Restructured preview functionality into a separate mediapreview package. 2026-08-12 00:06:56 +00:00
LeoVasanko 7b1c6f6772 Fix preview pool permanently wedging after worker stderr pipe fills
Production symptom: previews of all types (pdf/pyvips/onlyoffice) start
hitting the 10s timeout and never recover until server restart, while the
rest of the server stays healthy.

Root cause (reproduced on Python 3.12): workers were spawned with
stderr=PIPE that nothing drained after startup. Once the OS pipe buffer
filled from accumulated worker tracebacks and library warnings, asyncio
flow control stopped the parent reading it and the worker blocked forever
mid-request on a stderr write. The 10s timeout then fired, but
_replace_worker hung forever in proc.wait() even after kill() — the
flow-control-paused pipe transport never sees EOF — permanently wedging
one dispatcher per stuck worker. Once all dispatchers were stuck, every
preview request timed out. Restart cleared it.

Fixes:
- Spawn workers with inherited stderr (stderr=None) so worker diagnostics
  go straight to the server log and no undrained pipe can exist.
- Bound proc.wait() in worker kill() with a 5s grace timeout so a wedged
  transport can never hang a dispatcher; log the worker pid instead.
- Guard the dispatch loop with an outer exception handler so a dispatcher
  can never die silently and shrink pool capacity.
- Retry failed worker replacement spawns with 1s-30s backoff instead of
  silently shrinking the pool.
- Fix latent crash: except-tuple referenced msgspec.json.DecodeError,
  which does not exist in the installed msgspec; any protocol failure
  would itself raise AttributeError. Use msgspec.DecodeError.
- Worker: redirect Python-level sys.stdout to stderr in persistent mode
  and keep the raw buffer solely for the binary protocol, so a library
  print() can never corrupt the command channel again (cf. the pymupdf
  deprecation warning that crashed workers at startup).
- Worker: close the pymupdf document explicitly in process_pdf.
- Log worker pid on timeout/protocol/checksum failures, and log failed
  kills and replacement retries, for future production diagnostics.

Add tests/test_preview_pool.py with an end-to-end regression recreating
the wedged-worker setup (piped, undrained stderr) plus kill-grace,
respawn-retry and dispatcher-survival tests.
2026-08-11 04:57:20 +00:00
LeoVasanko d5b77932ea Allow anonymous share links in public mode 2026-05-05 02:47:18 +00:00
LeoVasanko d4be755d46 Enforce 128 MiB minimum free space on uploads
- Add cista/util/diskspace.py with MIN_FREE_BYTES limit and cached
  check_free_space() helper.
- Check available space in File.write() before ftruncate/write.
- Catch ENOSPC in File.write and re-raise as InsufficientStorageError.
- upload_file_chunk catches both proactive and ENOSPC errors and
  returns HTTP 507 Insufficient Storage.
- Add tests for low-disk rejection and ENOSPC handling.
2026-05-05 01:46:30 +00:00
LeoVasanko 5d566d6deb Restore CISTA_HOME internal environment passing of config dir removed in commit 31e0197, that was not being passed across processes. 2026-05-02 05:47:24 +00:00
LeoVasanko 2fa52229cc Exception nazi and other suppression removals. Added tests on auth flows that were simplified to linter requirements. 2026-05-02 05:22:56 +00:00
LeoVasanko 922069c603 Imports to top of file (ruff rule now). Refactor a couple of import cycles by implementing clear hierarchy of modules. 2026-05-02 04:46:34 +00:00
LeoVasanko 20d8d317fa Ruff linting. 2026-05-02 03:31:51 +00:00
LeoVasanko 1bec73f4cd onlyoffice previews much faster and more robust, added --oosetup helper, improved error/log handling 2026-05-02 03:10:17 +00:00
LeoVasanko 575df1214b session: rename cookie to 'cista', add __Host- prefix on HTTPS 2026-04-27 03:56:07 +00:00
LeoVasanko 6242c76be8 Add share token support with virtual filesystem and selection toolbar button 2026-04-26 07:46:14 +00:00
LeoVasanko 8c93a4f2b5 Add OnlyOffice-based preview for office documents
Replace Aspose.Words with OnlyOffice Document Server for generating
bitmap previews of office documents (Word, Excel, PowerPoint, etc.).

Backend:
- Add cista/onlyoffice.py conversion client
- Convert office docs directly to PNG via OnlyOffice, then AVIF via pyvips
- Make office previews optional based on OnlyOffice availability
- Remove Aspose.Words dependency and all related code
- Add spreadsheet and presentation format support

Frontend:
- Mark office files as previewable in Document.ts
- Add office extensions to MediaPreview.vue preview list
- Fix pre-existing @ts-ignore in HeaderMain.vue

Tests:
- Fix test_lrucache.py parameter name (open -> opener)

Also run ruff format across the codebase to satisfy linter checks.
2026-04-26 06:59:01 +00:00
LeoVasanko 942b54d795 lint: apply manual ruff cleanup (non-preview files) 2026-04-26 06:16:42 +00:00
LeoVasanko f8b2c9494a WebDAV sync support, access tokens, REST control endpoints (#10)
Implement complete WebDAV file serving compatible with various clients from Windows File Explorer to more specialized sync tools. The old control WebSocket has been updated to part-DAV, part REST API instead. Implemented user:pass BASIC auth. Added UI and backend for creating tokens that avoid the need to use actual username and password for requests from CLI or DAV.
2026-04-26 04:22:52 +00:00
LeoVasanko 62b44ddb43 Fix free/used disk space handling. Implement file disk usage tracking. Display indicators on FileExplorer for incomplete files (sparse allocation, upload in progress). 2026-02-04 18:54:54 +00:00
LeoVasanko 58579b50c4 Rewritten inotify watching and faster full tree traversal (also for polling worker). Bugs in inotify watcher fixed. 2023-11-20 18:49:24 +00:00
LeoVasanko 55007b4b8b More efficient flat file list format and various UX improvements (#3)
This is a major upgrade with assorted things included.

- Navigation flows improved, search appears in URL history, cleared when navigating to another folder
- More efficient file list format for faster loads
- Efficient updates, never re-send full root another time (except at connection)
- Large number of watching and filelist updates (inotify issues remain)
- File size coloring
- Fixed ZIP generation random glitches (thread race condition)
- Code refactoring, cleanup, typing fixes
- More tests
2023-11-12 23:20:40 +00:00
LeoVasanko 9762d7c1ad Linting, removed extra line from pyproject.toml. 2023-11-09 05:08:46 +00:00
LeoVasanko bc67ef5fd1 Frontend created and rewritten a few times, with some backend fixes (#1)
The software is fully operational.
2023-11-08 20:38:40 +00:00
LeoVasanko ab6b19e538 Formatting and fix Internal Server Error on upload 2023-10-26 11:18:59 +00:00
LeoVasanko b5a1fe6c4d Cleanup, bugfixes. Added access control on files and API. 2023-10-22 22:51:39 +00:00
LeoVasanko bfc04b3831 Refactoring and cleanup 2023-10-21 13:17:09 +00:00
LeoVasanko 447081e5d0 Implemented control commands and tests. Rewritten error and session/flash handling. 2023-10-20 22:44:43 +00:00
LeoVasanko d269442d7f Refactor with its own entry point and startup script cista, instead of running via sanic. Config file handling and Droppy updates. HTTP redirection/acme server added. 2023-10-18 20:06:14 +00:00
LeoVasanko 9dce1e843f Cleanup LRUCache, fix bug, add unit tests (pytest). 2023-10-15 02:56:50 +00:00