feat: v7.2.0 — Share tokens, thumbnails, download restrictions#89
Merged
feat: v7.2.0 — Share tokens, thumbnails, download restrictions#89
Conversation
Add share token authentication for link-shareable access scoped to specific chats. Tokens use PBKDF2-SHA256 (600K iterations) with constant-time comparison. Includes on-demand WebP thumbnail generation with Pillow, server-side no_download enforcement, app_settings table, audit log action filtering, and admin UI for token management. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
🐳 Dev images published!
The dev/test instance will pick up these changes automatically (Portainer GitOps). To test locally: docker pull drumsergio/telegram-archive:dev
docker pull drumsergio/telegram-archive-viewer:dev |
Python 3.14 allows `except X, Y:` as equivalent to `except (X, Y):`, making the parentheses redundant. Align with ruff format output. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
🐳 Dev images published!
The dev/test instance will pick up these changes automatically (Portainer GitOps). To test locally: docker pull drumsergio/telegram-archive:dev
docker pull drumsergio/telegram-archive-viewer:dev |
High: - Token revocation now invalidates active sessions immediately. Sessions track source_token_id; revoke/delete/scope-change calls _invalidate_token_sessions() to purge both in-memory and DB sessions. - Migration 010 stamping checks all 3 artifacts (viewer_tokens, app_settings, viewer_accounts.no_download) before stamping complete. Medium-High: - no_download and source_token_id persisted in viewer_sessions table. save_session() stores both; _viewer_session_to_dict() returns both; _resolve_session() restores them on DB fallback/restart. Medium: - create_viewer() now reads and passes is_active and no_download from request body to create_viewer_account(). - no_download no longer breaks inline media. Only explicit downloads (download=1 query param) and exports are blocked. Frontend hides download buttons for restricted users. - Token expiry timezone fixed: frontend converts datetime-local to UTC ISO before sending. Low-Medium: - Audit log filter uses startswith() instead of exact match, so "viewer_updated" matches "viewer_updated:username". Standards: - Version bumped to 7.2.0 in pyproject.toml and src/__init__.py - SECURITY.md: added 7.x.x as supported - pyproject.toml: added viewer optional dep group for Pillow - CHANGELOG updated with all security/fix entries Tests (12 new): - Token revocation invalidates sessions (revoke, delete, scope change) - Label-only update preserves sessions - no_download blocks explicit download but allows inline - no_download blocks export - no_download persisted via save_session - source_token_id persisted and tracked - no_download restored from DB session - create_viewer passes no_download and is_active flags Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Owner
Author
Review Response — All Findings AddressedThanks for the thorough review. Every finding was valid. Here's what was fixed in commit c11329f: High: Token revocation not enforced on active sessions ✅
High: Migration 010 stamping incomplete ✅
Medium-High: no_download not persisted in DB sessions ✅
Medium: create_viewer ignores is_active and no_download ✅
Medium: no_download breaks inline media ✅
Medium: Token expiry timezone-shifted ✅
Low-Medium: Audit filter mismatch ✅
Standards ✅
Test Summary31 tests total (12 new), all passing. Covers every finding above. |
|
🐳 Dev images published!
The dev/test instance will pick up these changes automatically (Portainer GitOps). To test locally: docker pull drumsergio/telegram-archive:dev
docker pull drumsergio/telegram-archive-viewer:dev |
The test_create_viewer mock was missing the no_download field added by the review fix, causing a KeyError → 500 in CI. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
🐳 Dev images published!
The dev/test instance will pick up these changes automatically (Portainer GitOps). To test locally: docker pull drumsergio/telegram-archive:dev
docker pull drumsergio/telegram-archive-viewer:dev |
GeiserX
added a commit
that referenced
this pull request
Mar 23, 2026
High: - Token revocation now invalidates active sessions immediately. Sessions track source_token_id; revoke/delete/scope-change calls _invalidate_token_sessions() to purge both in-memory and DB sessions. - Migration 010 stamping checks all 3 artifacts (viewer_tokens, app_settings, viewer_accounts.no_download) before stamping complete. Medium-High: - no_download and source_token_id persisted in viewer_sessions table. save_session() stores both; _viewer_session_to_dict() returns both; _resolve_session() restores them on DB fallback/restart. Medium: - create_viewer() now reads and passes is_active and no_download from request body to create_viewer_account(). - no_download no longer breaks inline media. Only explicit downloads (download=1 query param) and exports are blocked. Frontend hides download buttons for restricted users. - Token expiry timezone fixed: frontend converts datetime-local to UTC ISO before sending. Low-Medium: - Audit log filter uses startswith() instead of exact match, so "viewer_updated" matches "viewer_updated:username". Standards: - Version bumped to 7.2.0 in pyproject.toml and src/__init__.py - SECURITY.md: added 7.x.x as supported - pyproject.toml: added viewer optional dep group for Pillow - CHANGELOG updated with all security/fix entries Tests (12 new): - Token revocation invalidates sessions (revoke, delete, scope change) - Label-only update preserves sessions - no_download blocks explicit download but allows inline - no_download blocks export - no_download persisted via save_session - source_token_id persisted and tracked - no_download restored from DB session - create_viewer passes no_download and is_active flags
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.
Summary
no_downloadflag on viewer accounts and share tokens blocks explicit downloads/exports while preserving inline media renderingType of Change
Database Changes
Migration 010 creates:
viewer_tokenstable (share token authentication)app_settingstable (key-value store)no_downloadcolumn onviewer_accountsno_download+source_token_idcolumns onviewer_sessionsAll operations are idempotent via
sa.inspect(). Entrypoint stamping checks all 3 table/column artifacts before marking 010 as complete.Data Consistency Checklist
chat_idvalues use marked format (via_get_marked_id())_strip_tz()before DB operationsTesting
python -m pytest tests/ -v) — 31 tests intest_v720_features.pyruff check .)ruff format --check .)Test coverage:
Security Checklist
Security specifics:
secrets.compare_digestfor constant-time comparisonsource_token_idtrackingno_downloadsurvives container restarts (stored inviewer_sessions)Image.MAX_IMAGE_PIXELSlimit,Path.resolve() + is_relative_to()traversal guardno_downloadrestrictionDeployment Notes
Dockerfile.vieweradds Pillow system dependencies)requirements-viewer.txtaddsPillow>=10.0.0; also declared inpyproject.toml[project.optional-dependencies.viewer]