Releases: GeiserX/Telegram-Archive
Releases · GeiserX/Telegram-Archive
v7.2.0 — Share Tokens, Download Restrictions, Thumbnails
Added
- Share tokens — Admins can create link-shareable tokens scoped to specific chats. Recipients authenticate via token without needing an account. Tokens support expiry dates, revocation, and use tracking
- Download restrictions —
no_downloadflag on both viewer accounts and share tokens. Restricted users can still view media inline but cannot explicitly download files or export chat history. Download buttons hidden in the UI for restricted users - On-demand thumbnails — WebP thumbnail generation at whitelisted sizes (200px, 400px) with disk caching under
{media_root}/.thumbs/. Includes Pillow decompression bomb protection and path traversal guards - App settings — Key-value
app_settingstable for cross-container configuration, with admin CRUD endpoints - Audit log improvements — Action-based filtering in admin panel (prefix match for suffixed events like
viewer_updated:username), token auth events tracked (token_auth_success,token_auth_failed,token_created, etc.) - Admin chat picker metadata — Chat picker now returns
username,first_name,last_namefor better display - Token management UI — New "Share Tokens" tab in admin panel with create, revoke, and delete controls. Plaintext token shown once at creation with copy button
- Token login UI — Login page has a "Share Token" tab for token-based authentication
Security
- Token revocation enforced on active sessions — Revoking, deleting, or changing scope/permissions of a share token immediately invalidates all sessions created from that token. Sessions track
source_token_idfor precise invalidation - Session persistence includes restrictions —
no_downloadandsource_token_idare now persisted inviewer_sessionstable, surviving container restarts. Previouslyno_downloadwas lost after restart, silently granting download access - Export endpoint respects no_download — The
GET /api/chats/{chat_id}/exportendpoint now returns 403 for restricted users
Fixed
- Create viewer passes all flags —
is_activeandno_downloadfrom the admin form are now correctly passed through tocreate_viewer_account(). Previously both flags were silently ignored on creation - Token expiry timezone handling — Frontend now converts local datetime to UTC ISO before sending to the backend, fixing early/late expiry for non-UTC admins
- Audit filter matches suffixed actions — Filter now uses prefix matching so "viewer_updated" catches "viewer_updated:username"
- Migration stamping checks all artifacts — Entrypoint now checks
viewer_tokens,app_settings, ANDviewer_accounts.no_downloadbefore stamping migration 010 as complete
Changed
- Migration 010 — Consolidated idempotent migration creates
viewer_tokens,app_settingstables and addsno_downloadcolumn toviewer_accounts. Also addsno_downloadandsource_token_idcolumns toviewer_sessions - Entrypoint stamping — Updated both PostgreSQL and SQLite stamping blocks to detect all migration 010 artifacts
- Dockerfile.viewer — Added Pillow system dependencies (libjpeg, libwebp) for thumbnail generation
- Version declarations —
pyproject.tomlandsrc/__init__.pyboth set to 7.2.0 - SECURITY.md — Added 7.x.x as a supported version
- pyproject.toml — Added
vieweroptional dependency group for Pillow
📋 Full changelog: docs/CHANGELOG.md
v7.1.7
Bug Fixes
- fix: add beautifulsoup4 to Docker image —
beautifulsoup4was declared inpyproject.tomlbut missing fromrequirements.txt(used by Docker builds), causingNo module named 'bs4'when running HTML imports.
Full Changelog: v7.1.6...v7.1.7
v7.1.6
Bug Fixes
- fix: make migrations 007-009 idempotent — When
create_all()runs before Alembic (fresh SQLite databases), tables and columns may already exist. Migrations now inspect the schema before altering, preventing "duplicate column name: username" crashes on upgrade. Fixes #81.
Full Changelog: v7.1.5...v7.1.6
v7.1.5
Bug Fixes
- fix: prevent duplicate messages in real-time viewer — Race condition in 3-second polling (
checkForNewMessages) allowed concurrent async calls to both add the same message. Added concurrency guard (isRefreshing) and deduplication. - fix: add
chat_idto WebSocketnew_messagebroadcast — The payload was missingchat_id, making client-side real-time message insertion a silent no-op. Messages only appeared via polling. - fix: deduplicate WebSocket new message handler — Added
messages.some()check to prevent duplicates when both WebSocket and polling deliver the same message.
Full Changelog: v7.1.4...v7.1.5
v7.1.4
Security
- Harden media file serving against path injection (CodeQL alerts #12, #13, #14)
- Early rejection of
..traversal and absolute paths before filesystem operations - Use
resolve(strict=True)to prevent TOCTOU race conditions with symlinks - Existing
is_relative_tocheck retained as defense-in-depth
- Early rejection of
What's Changed
- fix: resolve CI test failures and lint formatting by @GeiserX in #85
- fix: harden media path validation against path injection by @GeiserX in #86
Full Changelog: v7.1.3...v7.1.4
What's Changed
- fix: resolve CI test failures and lint formatting by @GeiserX in #85
- fix: harden media path validation against path injection by @GeiserX in #86
Full Changelog: v7.1.3...v7.1.4
v7.1.3
Fixed
- Alembic stamping detects all migrations — The entrypoint's pre-Alembic database stamping logic now detects migrations 008 (
push_subscriptions.usernamecolumn) and 009 (viewer_sessionstable). Previously it only checked up to 007, causingCREATE TABLEfailures whenBase.metadata.create_all()had already created newer tables (e.g. SQLite containers crash-looping onviewer_accounts already exists)
📋 Full changelog: docs/CHANGELOG.md
v7.1.2
Fixed
- Two-tier session protection — Replaces the single-backup approach from v7.1.1 with a robust two-tier system:
- Golden backup (
.session.authenticated) — only written after a successful login, guarantees a known-good recovery point that crash-loops can never corrupt - Pre-connect snapshot (
.session.bak) — taken before every connect attempt as a secondary fallback - On auth failure, restores from golden backup first, then snapshot. Prevents Telethon's silent DH key renegotiation from permanently destroying authenticated sessions during crash-loops.
- Uses raw
sqlite3to verifyauth_keypresence before deciding whether to back up or restore, avoiding false positives from empty/corrupted session files - Flushes WAL checkpoint before creating golden backup to ensure file completeness
- Golden backup (
📋 Full changelog: docs/CHANGELOG.md
v7.1.1
Added
- Non-interactive auth script —
scripts/auth_noninteractive.pyfor authenticating Telegram sessions without a TTY (useful for SSH automation, CI pipelines)
Fixed
- Session file protection — Telethon session files are now backed up before each connect attempt. If the container crash-loops (e.g. due to database permission errors), the authenticated session is preserved and restored instead of being overwritten with an empty one
- Duplicate session_path assignment in config.py removed
📋 Full changelog: docs/CHANGELOG.md
v7.1.0: Persistent Sessions
What's New
Persistent Sessions
Sessions now survive container restarts. Previously, all users were logged out whenever the Docker container restarted (regression introduced in v7.0.0 when switching from deterministic tokens to random session tokens).
How it works:
- New
viewer_sessionsdatabase table stores active sessions - In-memory write-through cache ensures zero additional latency on requests
- On startup, active sessions are restored from the database
- If the database is unavailable, falls back to in-memory only (same as v7.0.x)
Security Fix
- Sessions with corrupted
allowed_chat_idsJSON now deny access instead of silently granting access to all chats
Upgrade
Pull the new images and restart — migration is automatic for both SQLite and PostgreSQL.
Migration
- Alembic migration 009: creates
viewer_sessionstable with indexes onusernameandcreated_at
Full Changelog: v6.5.0...v7.1.0
v7.0.3
Added
- Viewer-only mode — When a reverse proxy sets
X-Viewer-Only: true, master/admin login and all admin API endpoints are blocked. Allows sharing the same backend instance across domains with different access levels.
Fixed
- Chat names in admin panel — Private chats now show
first_name last_nameinstead of numeric IDs in the chat picker and viewer list - Viewer list shows chat names — The viewer account list now displays assigned chat titles instead of just a count
📋 Full changelog: docs/CHANGELOG.md