Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Environment variables
.env

# Installation journal (contains infra IDs, credentials references)
journal.md

# Session files (contain authentication tokens)
*.session
*.session-journal
Expand Down
7 changes: 6 additions & 1 deletion Dockerfile.viewer
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ WORKDIR /app
# Copy requirements first for better caching
COPY requirements-viewer.txt .

# Install Python dependencies (no gcc needed - viewer has no native extensions)
# Install system libs for Pillow (JPEG + WebP thumbnail support)
RUN apt-get update && \
apt-get install -y --no-install-recommends libjpeg62-turbo-dev libwebp-dev && \
rm -rf /var/lib/apt/lists/*

# Install Python dependencies
RUN pip install --no-cache-dir -r requirements-viewer.txt

# Copy only the necessary application code for the viewer
Expand Down
56 changes: 56 additions & 0 deletions alembic/versions/20260224_007_add_viewer_accounts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""Add viewer_accounts and viewer_audit_log tables for multi-user access control.

Revision ID: 007
Revises: 006
Create Date: 2026-02-24
"""

from collections.abc import Sequence

import sqlalchemy as sa

from alembic import op

revision: str = "007"
down_revision: str | None = "006"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None


def upgrade() -> None:
op.create_table(
"viewer_accounts",
sa.Column("id", sa.Integer(), autoincrement=True, nullable=False),
sa.Column("username", sa.String(255), nullable=False),
sa.Column("password_hash", sa.String(255), nullable=False),
sa.Column("salt", sa.String(64), nullable=False),
sa.Column("allowed_chat_ids", sa.Text(), nullable=True),
sa.Column("is_active", sa.Integer(), server_default="1", nullable=False),
sa.Column("created_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
sa.Column("updated_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("username"),
)
op.create_index("idx_viewer_accounts_username", "viewer_accounts", ["username"])

op.create_table(
"viewer_audit_log",
sa.Column("id", sa.Integer(), autoincrement=True, nullable=False),
sa.Column("viewer_id", sa.Integer(), nullable=False),
sa.Column("username", sa.String(255), nullable=False),
sa.Column("endpoint", sa.String(500), nullable=False),
sa.Column("chat_id", sa.BigInteger(), nullable=True),
sa.Column("ip_address", sa.String(45), nullable=True),
sa.Column("timestamp", sa.DateTime(), server_default=sa.func.now(), nullable=False),
sa.PrimaryKeyConstraint("id"),
)
op.create_index("idx_audit_viewer_id", "viewer_audit_log", ["viewer_id"])
op.create_index("idx_audit_timestamp", "viewer_audit_log", ["timestamp"])


def downgrade() -> None:
op.drop_index("idx_audit_timestamp", table_name="viewer_audit_log")
op.drop_index("idx_audit_viewer_id", table_name="viewer_audit_log")
op.drop_table("viewer_audit_log")
op.drop_index("idx_viewer_accounts_username", table_name="viewer_accounts")
op.drop_table("viewer_accounts")
102 changes: 102 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,108 @@ For upgrade instructions, see [Upgrading](#upgrading) at the bottom.

## [Unreleased]

## [7.1.0] - 2026-02-24

### Added

- **Multi-user Viewer Authentication** — Per-user viewer accounts with PBKDF2-SHA256 password hashing (600k iterations). Each viewer assigned specific chats for fine-grained access control. Dual-mode: master account via env vars (VIEWER_USERNAME/VIEWER_PASSWORD) + database viewer accounts.
- **ViewerAccount & ViewerAuditLog Models** — New ORM models for viewer authentication and audit logging. ViewerAccount stores username, password hash, assigned chat IDs, and active status. ViewerAuditLog tracks all actions: login, logout, view, export with timestamp, IP, user agent.
- **Session Caching** — In-memory session cache with 24-hour TTL for fast auth validation without database queries on every request.
- **Per-user Chat Filtering** — All API endpoints now filter results based on viewer's assigned chats. Master user respects DISPLAY_CHAT_IDS for backward compatibility.
- **Admin API Endpoints** (NEW):
- `GET /api/admin/viewers` — List all viewer accounts
- `POST /api/admin/viewers` — Create new viewer account
- `PUT /api/admin/viewers/{viewer_id}` — Update viewer permissions and chats
- `DELETE /api/admin/viewers/{viewer_id}` — Delete viewer account
- `GET /api/admin/chats` — List all chats with message counts
- `GET /api/admin/audit` — View access audit log (paginated)
- **Admin UI** — New admin panel for viewer management, chat picker with counts, audit log viewer with filtering.
- **Alembic Migration 007** — Database schema for viewer_accounts and viewer_audit_log tables with proper indexes.
- **7 DB Adapter Methods** — `get_viewer_account_by_username`, `get_all_viewer_accounts`, `create_viewer_account`, `update_viewer_account`, `delete_viewer_account`, `get_audit_log`, `log_audit_action`.

### Changed

- **Authentication Overhaul** — Replaced SHA256 tokens with PBKDF2-SHA256 password hashing. Changed from single global auth to per-user permissions model.
- **Backward Compatibility** — Master users login via VIEWER_USERNAME env var and retain DISPLAY_CHAT_IDS filtering. Existing single-user deployments continue to work without migration.

### Technical

- Alembic migration 007: viewer_accounts, viewer_audit_log tables
- New env vars: No new required vars (VIEWER_USERNAME/VIEWER_PASSWORD already existed, now define master account)

## [7.0.0] - 2026-02-17

### Added

- **Advanced Search with Filters** — Full-text search across all messages with advanced filtering: sender (by name/ID), media type (photo/video/document/audio), and date range (from/to). Results include highlighting and context. Implements FTS index for <100ms query performance.
- **Global Cross-Chat Search** — Search across all accessible chats in a single query, enabling discovery across entire backup without navigating individual chats.
- **Message Deep Linking** — Generate copyable links to specific messages (#chat/{id}/message/{id}). Restore scroll position and highlight on page load. Enables sharing message URLs.
- **Search Result Highlighting** — Search queries highlight matching text in context. Display surrounding messages for better understanding. Result count and query timing shown.
- **Copy Message Link** — Button to copy permalink to specific message for sharing via external channels.
- **Media Gallery with Type Filters** — Grid view of all media in a chat with type filters: photo, video, document, audio. Responsive layout (1-4 columns). Lazy-loaded thumbnails. Pagination support (limit 100/page).
- **Lightbox Viewer** — Full-size image/video preview. Navigate between media with arrow keys. Fullscreen mode. Download option. Close with Esc key.
- **Keyboard Shortcuts** — Esc (close lightbox/clear search), Ctrl+K/Cmd+K (focus search), ? (show help overlay), Arrow keys (navigate media).
- **URL Hash Routing** — Hash-based navigation (#/search, #/chat/{id}, #/chat/{id}/media, etc.). Preserve filters in URL. Browser back/forward support. Shareable state links.
- **Skeleton Loading States** — Show skeleton screens during data fetch. Spinner during search. Progress indicator for media load. Better perceived performance.
- **Transaction Accounting View** — Auto-detect monetary transactions from chat messages. Spreadsheet-like interface with date, sender, debit, credit, balance, category columns.
- **Auto-Detect Transactions** — Scan message text for monetary amounts using regex patterns. Support multiple currency prefixes: PHP, $, ₱, P. Classify as credit/debit based on keywords (sent, paid, transfer, received, etc.). Confidence scoring (0.4-0.9 based on signal clarity). Range validation (1-10M).
- **Transaction Management UI** — Inline editing of category and notes. Manual override of credit/debit amounts. Toggle auto-detected vs. manually-entered. Visibility of confidence scores.
- **Transaction Summary** — Total credit/debit/balance. Count by category. Auto-generated insights. Date range filtering.
- **Transaction CSV Export** — Export to CSV with headers and running balance column. Include date range and category filters. Download as file.
- **Alembic Migration 007** — Database schema for transactions table. Adds indexes on (chat_id, date) and unique constraint on message_id.
- **Transaction Detection Module** (`src/transaction_detector.py`) — Pattern matching for amounts and keyword-based classification. Handles comma-separated numbers (1,000.00). Validates amounts. Returns confidence scores.

### Changed

- **Frontend Upgrade** — Migrated to Vue 3 Composition API. Enhanced Tailwind CSS styling. Mobile-first responsive design. Improved component organization.
- **Search Pagination** — Limited to 500 results per query (increased from 100 in v6.2). Prevents UI slowdown on very broad searches.
- **API Response Format** — Unified response structure across endpoints. Include metadata (total, took_ms) for better client-side handling.

### Technical

- **30+ New API Endpoints**:
- `/api/search` — Global search with advanced filters
- `/api/chats/{chat_id}/messages` — Chat messages with highlighting
- `/api/chats/{chat_id}/media` — Media gallery with type filters
- `/api/chats/{chat_id}/messages/{message_id}/context` — Deep link support
- `/api/chats/{chat_id}/transactions` — Paginated transaction list
- `/api/chats/{chat_id}/transactions/scan` — Auto-detect from messages
- `/api/transactions/{txn_id}` — Manual transaction update/delete
- `/api/chats/{chat_id}/transactions/summary` — Running balance
- `/api/chats/{chat_id}/transactions/export` — CSV export
- Plus 20+ supporting endpoints for media, stats, and real-time updates

- **Database Model: Transaction** — id, message_id, chat_id, sender_id, date, category, credit, debit, notes, auto_detected, confidence, created_at, updated_at. Indexes on chat_id+date and unique on message_id.

- **Backward Compatibility** — v7.0 maintains full compatibility with v6.x databases. Migration 007 is non-breaking. Existing backups continue to work without data loss.

### Performance

- Full-text search index on message text (FTS)
- Index on (chat_id, media_type, date) for gallery queries
- Index on (chat_id, date) for transaction queries
- P95 search latency: <100ms for typical queries
- P95 media gallery load: <200ms for 100 items
- P95 transaction scan: <1s for 1000 messages

### Dependencies

- **sqlalchemy** >=2.0 (for FTS support)
- **alembic** >=1.18 (migration framework)
- **vue** 3.3+ (frontend)
- **tailwindcss** >=3.0 (styling)

### Migration Path

1. Backup your database: `cp data/backups/telegram_backup.db data/backups/telegram_backup.db.backup`
2. Update container image: `docker pull drumsergio/telegram-archive:v7.0`
3. Run migration: `docker compose up` (automatic on startup)
4. Scan transactions (optional): POST `/api/chats/{chat_id}/transactions/scan` for each chat

### Contributors

- Telegram Archive Team — v7.0 feature implementation and testing

## [6.3.2] - 2026-02-17

### Fixed
Expand Down
Loading