alexei.dolgolyov
b803d004e1
refactor: comprehensive codebase review — security, performance, quality, UX
...
Security:
- Fix NUT protocol command injection (validate names against safe regex)
- Enable Jinja2 autoescape=True to prevent HTML injection via external data
- Add WebhookProviderConfig validation model
Performance:
- Shared aiohttp.ClientSession singleton (replaces 40+ per-request sessions)
- Fix 4 N+1 queries with batch IN loads (poller, scheduler, memory, broadcast)
- asyncio.gather for Gitea commands and notification dispatcher
- Add DB indexes on NotificationTrackerState.tracker_id, CommandTrackerListener
- LRU cache for compiled Jinja2 templates
- Daily EventLog cleanup job (90-day retention)
- 30s HTTP timeout on all external calls
- GROUP BY for target type counts (replaces 7 sequential queries)
Code quality:
- Extract get_owned_entity() helper (replaces 11 duplicate functions)
- Extract slot_helpers.py (load_slots, save_slots, render_template_preview)
- Extract command_utils.py (tracker lookup, last event, collection IDs)
- Extract http_session.py (shared session lifecycle)
- Provider connection validation dedup (3x → 1 helper)
- Command dispatch tables replacing if/elif chains
- Album+links fetch helper (fetch_albums_with_links)
- Provider dispatch polymorphism (list_provider_collections)
- Immutable _enrich_assets (no longer mutates in-place)
- Fix _format_assets return type + handler unpacking
Frontend:
- Fix 18+ hardcoded English strings → t() with new i18n keys (en + ru)
- Mobile "More" nav panel with provider filter and search
- Shared Button.svelte component (4 variants, 2 sizes)
- Shared ErrorBanner.svelte component (8 pages updated)
- SvelteKit goto() replacing window.location.href
- Dashboard grid fixed for 4 cards, paginator opacity consistency
Functionality:
- max_instances=1 on scheduler jobs (prevents duplicate events)
- Webhook provider in watcher (prevents error spam)
- Fix stale SQLModel reference in poller
- Gitea get_repo() direct API call
2026-03-28 13:22:26 +03:00
alexei.dolgolyov
e0bae394ee
feat: comprehensive code review fixes — security, performance, quality
...
Backend security:
- Reject Gitea webhooks when webhook_secret is empty (was silently skipping)
- Add slowapi rate limiting on login (5/min) and setup (3/min) endpoints
- Add CORS middleware with configurable origins
- Mask telegram_webhook_secret in settings API response
- Protect system-owned command template configs from regular user modification
- Increase minimum password length to 8 characters
Backend performance:
- Batch queries in _resolve_command_context (3 queries instead of 3N)
- Concurrent album fetching with asyncio.gather in immich commands
- Singleton Jinja2 SandboxedEnvironment (reuse instead of per-render creation)
- TTLCache for rate limits (bounded memory, auto-eviction)
- Optional aiohttp session reuse in send_reply/send_media_group
Backend code quality:
- Extract dispatch_helpers.py (shared link_data loading + event filtering)
- Extract database/seeds.py from main.py (490 lines → dedicated module)
- Split immich_handler.py (415 lines) into commands/immich/ subpackage
- Replace bare except blocks with logged warnings
- Add per-provider config validation (Pydantic models)
- Truncate command input to 512 chars
- Expose usage_* and desc_* slots in capabilities and variables API
Frontend security:
- CSS.escape() for user-controlled querySelector in highlight.ts
- Client-side password min 8 chars validation on setup and password change
Frontend code quality:
- Replace any types with proper interfaces across top files
- Decompose targets/+page.svelte into TargetForm + ReceiverSection
- Fix $derived.by usage, $state mutation patterns
- Add console.warn to empty catch blocks
Frontend UX:
- Auth redirect via goto() with "Redirecting..." state
- Platform-aware Ctrl/Cmd K keyboard hint
- Remove stat-card hover transform
Frontend accessibility:
- Modal: role=dialog, aria-modal, focus trap, restore focus
- EntitySelect/IconGridSelect: listbox/option roles, aria-selected/disabled
2026-03-23 01:59:51 +03:00
alexei.dolgolyov
751097b347
feat: comprehensive code review fixes + receivers-only architecture
...
Security:
- Refuse startup with default secret_key in production (was just logging)
- Settings endpoint now requires admin role
- Password validation on initial setup
- DOM-based HTML sanitizer replaces regex in template previews
- Add *.log to .gitignore
Performance & reliability:
- Token refresh deduplication prevents race condition on concurrent 401s
- Theme media query listener registered once (no leak)
- IconPicker uses $derived instead of function call per render
- Snackbar uses single-batch state update instead of while loop
- Replace 11 inline hover handlers with CSS :hover in layout
Architecture - receivers-only:
- Delivery endpoints (chat_id, email, url, room_id, topic) now stored
exclusively in TargetReceiver rows, never in target.config
- Migration extracts existing delivery fields to receiver rows
- Notifier and dispatcher remove all config fallbacks
- Frontend targets page shows receivers list per target with
add/remove/toggle/test per receiver
- Single-receiver test endpoint: POST /targets/{id}/receivers/{id}/test
Code quality:
- Extract AuthLayout.svelte from login/setup (150 lines CSS dedup)
- Split telegram-bots page (754→51 lines + 3 tab components)
- Split notification-trackers page (547→432 lines + 4 components)
- Deduplicate _send_reply into shared handler.send_reply()
- Add locale column to template models, replace name-based detection
- Fix delete_notification_tracker dead protection check
- Fix check_telegram_bot query (filter by type, remove bogus OR)
- Add graceful scheduler shutdown in lifespan
- Consistent /bots?tab=telegram URLs across all nav links
i18n:
- Error page, chat actions, target types, provider types internationalized
- All new receiver UI strings in EN + RU
2026-03-22 02:19:31 +03:00
alexei.dolgolyov
03ec9b3c86
feat: telegram commands, app settings, bot polling, webhook handling, UI improvements
...
Adds telegram bot command system with 13 commands (search, latest, random, etc.),
webhook/polling handlers, rate limiting, app settings page, and various UI/UX
improvements across all entity pages.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com >
2026-03-20 23:11:42 +03:00
alexei.dolgolyov
c9cab93d12
feat: port original frontend UI to Notify Bridge
...
Port the full polished frontend from Immich Watcher:
- Sidebar layout with collapsible nav, mobile bottom nav
- Login/setup pages with gradient mesh background, animations
- 11 reusable components: Card, Modal, ConfirmModal, Snackbar,
IconPicker, JinjaEditor, MdiIcon, PageHeader, Loading, Hint, IconButton
- Auth state with getAuth() reactive pattern, token refresh
- Theme: light/dark/system with media query listener
- i18n: EN/RU with nested JSON, auto-detect locale
- Snackbar notification store
Branding changes:
- "Immich Watcher" -> "Notify Bridge"
- /servers -> /providers in nav and routes
- Login icon: mdiEye -> mdiLan
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com >
2026-03-20 00:35:36 +03:00
alexei.dolgolyov
f9c41faf16
fix: local fonts via @fontsource, favicon, autocomplete attrs
...
- Replace Google Fonts with @fontsource/dm-sans and @fontsource/jetbrains-mono
- Add SVG favicon
- Add autocomplete attributes to login/setup form inputs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com >
2026-03-20 00:13:21 +03:00
alexei.dolgolyov
9dfd1b79cd
feat(notify-bridge): phase 7 - frontend restructuring
...
Notify Bridge frontend with SvelteKit 2 + Svelte 5 + Tailwind CSS v4:
- Auth: login page, setup page, auth state management with $state runes
- Theme: dark/light toggle with localStorage persistence
- i18n: EN/RU translations with reactive $state-based t() function
- Routes: dashboard, providers, trackers, targets, tracking-configs,
template-configs, telegram-bots, users (stubs for configs pages)
- Providers page: list with card grid, "Add Provider" button
- API client: JWT auth, auto-redirect on 401, typed request helpers
- Branding: "Notify Bridge" throughout, Observatory theme colors
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com >
2026-03-19 23:53:37 +03:00