1
Fork 0
mirror of https://github.com/thegeneralist01/archivr synced 2026-07-21 18:55:36 +02:00
Commit graph

68 commits

Author SHA1 Message Date
5ce68b58f3
feat(server): require auth on list_entries and search_entries_handler
Both handlers accepted AuthUser but served guests.
auth.require_auth()? added as first line closes the gap.
Existing unauthenticated tests updated with session cookies.
2026-06-29 20:13:31 +02:00
007c5fc5fb
feat(server): enforce auth on all public read endpoints
Add auth_user: AuthUser + require_auth() to entry_detail, list_runs,
serve_artifact, serve_entry_favicon, serve_blob, list_tags,
list_entry_tags, list_collections_handler, list_entry_collections_handler.
Add require_auth() to get_collection_handler (already had extractor).

Update existing tests to pass session cookies.
2026-06-29 20:12:00 +02:00
a8e52bdf71
security: add per-IP sliding-window rate limit on POST /api/auth/login
5 attempts / 15 min per IP. Excess attempts get 429 + Retry-After.
Client IP read from X-Forwarded-For with loopback fallback.
In-memory; prune inline on each check.
Refactored app() into app_with_state() + thin wrapper.
Uses parking_lot::Mutex (no unwrap, no poisoning).
2026-06-29 20:06:41 +02:00
3b3b0d7207
feat(server): add HTTP security response headers middleware
Injects X-Content-Type-Options, X-Frame-Options, Referrer-Policy,
Content-Security-Policy, and Permissions-Policy on every response.
Registered as outermost layer so it covers setup_guard 503s too.
No new dependencies.
2026-06-29 20:03:44 +02:00
4311e85f95
ui: comprehensive UI polish pass
- LoginPage/SetupPage: centered card layout with display font, styled fields and submit button
- Topbar: fix duplicate Settings nav item; add styled user-menu with username + logout button
- RunsView: format ISO timestamps to readable dates, add colored status badges (completed/failed/running)
- AdminView: view-tabs system, styled admin-table, admin-input, status-badge (active/disabled), btn-primary
- SettingsView: replace all inline styles with form-section/form-field/field-input/btn-primary/btn-danger
- CollectionsView: restructure create form with proper field labels and btn-primary
- TagsView: add Tags section heading with separator
- ContextRail: show visibility as human-readable label not raw number; fix assign-error class
- styles.css: add auth-loading, view-tabs, form utilities, btn variants, status badges,
  run-status pills, token-banner/row, checkbox-row, coll-create-form, tag-tree-header CSS
2026-06-28 22:14:08 +02:00
ae92448fa3
build(frontend): bundle assets for collections UI 2026-06-26 17:33:50 +02:00
383cec1f81
feat(collections): routes — PATCH|DELETE /api/archives/:id/collections/:uid, visibility_bits in GET response 2026-06-26 17:33:38 +02:00
533e9d5d2e
feat(collections): db — update_collection, delete_collection helpers 2026-06-26 17:33:35 +02:00
ea0a8f80d1
test(settings): routes tests for profile update, password change, instance settings 2026-06-26 17:19:26 +02:00
44f18f4dcc
build(frontend): bundle assets for settings UI 2026-06-26 17:18:30 +02:00
dabe014e7e
feat(settings): routes — PATCH /api/auth/me, GET|PATCH /api/admin/instance-settings 2026-06-26 17:17:37 +02:00
69af2d2060
feat(settings): db — display_name column, InstanceSettings struct, profile and instance-settings helpers 2026-06-26 17:17:34 +02:00
cb390dfaab
build(frontend): bundle assets for collections UI 2026-06-26 17:05:22 +02:00
dd56fc8c70
test(collections): update tag-search test to send auth (private entries require auth) 2026-06-26 17:01:43 +02:00
24c5321f6e
feat(collections): collection CRUD + entry-visibility routes 2026-06-26 17:00:19 +02:00
02cab149fa
feat(collections): visibility-filtered entry queries + collection helpers 2026-06-26 16:51:48 +02:00
ab054f6256
feat(collections): schema — collections + collection_entries tables 2026-06-26 16:48:22 +02:00
2335776347
feat(users): admin routes — list/create users, roles, set status 2026-06-26 16:22:08 +02:00
48da356eee
feat(users): user management DB helpers (list_users, create_user, assign_role, custom roles) 2026-06-26 15:03:40 +02:00
9f7b3c912a
build(frontend): update bundled assets for async capture polling 2026-06-26 12:59:00 +02:00
da2b58ef96
feat(capture): mark stalled running jobs failed on server startup 2026-06-26 12:57:59 +02:00
cfd51778b1
feat(capture): async capture_handler (spawn_blocking) + job poll endpoint 2026-06-26 12:57:44 +02:00
27b37c3b6d
feat(capture): CaptureJobSummary type and archive::get_capture_job 2026-06-26 12:56:38 +02:00
d86a4d92a8
feat(capture): capture_jobs schema and DB helpers 2026-06-26 12:56:10 +02:00
37fd057c1f
fix(auth): use rfc3339 for session expires_at; update tag tests for auth guards 2026-06-26 12:03:13 +02:00
f9d2ac80e7
feat(auth): session cleanup background task (24h interval) 2026-06-26 11:57:14 +02:00
cb376aa986
feat(auth): apply ROLE_USER guard to WRITE routes (captures, tags) 2026-06-26 11:56:38 +02:00
36c7d575e2
feat(auth): API token endpoints (create, list, delete) 2026-06-26 11:55:05 +02:00
affb8aadc0
feat(auth): login, logout, /me, setup endpoints + setup_guard middleware 2026-06-26 11:53:58 +02:00
db28d038d9
feat(auth): AuthUser extractor, password helpers, token generation 2026-06-26 11:50:29 +02:00
a4239ba5fc
feat(auth): add auth_db_path to AppState, registry, and main.rs 2026-06-26 11:46:23 +02:00
86e8049f1b
feat(auth): session and token DB helpers 2026-06-26 11:32:32 +02:00
f482707b75
feat(auth): user and role DB helpers (create_owner, compute_role_bits) 2026-06-26 11:31:20 +02:00
696a5e1ac7
feat(auth): add initialize_auth_schema, open_auth_db, and auth record types 2026-06-26 11:30:02 +02:00
57fc48d73c
feat(auth): add argon2, rand, axum-extra dependencies 2026-06-26 11:28:51 +02:00
5fba6987a3
fix(capture): remove debug println! from hash_exists 2026-06-25 16:19:33 +02:00
351e74df09
feat(fonts): wire font extraction into capture pipeline + blob serving route
- capture.rs: add archive_id: Option<&str> to perform_capture; when Some,
  call font_extractor::extract_and_rewrite before hashing HTML, register
  each font as a deduplicated blob + 'font' artifact
- main.rs: pass None as archive_id (CLI keeps fonts embedded)
- routes.rs: add GET /api/archives/:id/blobs/:sha256 (serve_blob handler),
  pass Some(&archive_id) to perform_capture in capture_handler,
  add ApiError::internal constructor
2026-06-25 16:07:50 +02:00
22b0a55730
feat(fonts): hash_bytes, get_blob_by_sha256, font_extractor module
- fix(hash): hash raw bytes instead of lossy UTF-8; add hash_bytes
- feat(database): add get_blob_by_sha256 lookup
- feat(font_extractor): extract embedded font data-URIs from archived HTML
2026-06-25 16:02:57 +02:00
f6d636fce2
feat(singlefile): add UA, disable-web-security, and user-data-dir
- --user-agent: realistic Chrome UA so servers don't block headless string
- --browser-args=[--disable-web-security, --user-data-dir]: lets single-file
  inline fonts from any cross-origin CDN (e.g. fonts.gstatic.com) regardless
  of ACAO headers; user-data-dir required for --disable-web-security to take
  effect in newer Chromium builds (otherwise silently ignored)
2026-06-25 11:39:24 +02:00
ab353f9209
fix(singlefile): improve font capture and eliminate ES module viewer errors
Font fidelity:
- --browser-wait-delay=2000: Cloudflare Fonts injects @font-face CSS after
  HTML parse; the font hook needs extra time to see it after networkidle2
- --remove-unused-fonts=false: preserve @font-face rules even when fonts
  haven't rendered yet (font-display:swap, off-screen text)
- --remove-alternative-fonts=false: preserve unicode-range subsets instead
  of stripping them as 'alternatives'

ES module viewer error fix:
- Write a user script (sf-strip-scripts.js) that listens for
  single-file-on-before-capture-start and removes all <script> elements
  (except application/ld+json) from the live DOM before serialization.
  Scripts still execute during capture for CSS fidelity; none end up in
  the saved file, so no data:-URL base ES module resolution errors.
2026-06-24 21:30:14 +02:00
852cc45956
fix(singlefile): disable CSS stripping and script blocking for full render fidelity
Defaults that were destroying CSS fidelity:
- --remove-unused-styles=true: strips CSS nesting rules (site uses & selector)
  and any rule targeting JS-applied classes
- --remove-alternative-medias=true: deletes @media blocks that don't match
  the capture viewport, breaking responsive layout
- --block-scripts=true: prevents JS from applying classes before CSS snapshot

All three now set to false.
2026-06-24 21:15:36 +02:00
fbb96fbd05
build(frontend): update bundled assets after favicon+rendering changes 2026-06-24 21:05:35 +02:00
1206d7103d
feat(server): add GET /entries/:uid/favicon endpoint 2026-06-24 19:16:21 +02:00
cc2dbf4ac2
feat(archive): add has_favicon to EntrySummary 2026-06-24 19:16:21 +02:00
653efa9705
feat(capture): store favicon artifact for WebPage entries 2026-06-24 19:16:21 +02:00
ee697625fb
feat(singlefile): add SaveResult, favicon extraction, wait for networkidle2 2026-06-24 19:16:21 +02:00
fe9ff2dafe
feat(capture): add Source::WebPage, route HTML URLs to singlefile downloader 2026-06-24 18:39:02 +02:00
fd06632073
feat(singlefile): add single-file-cli downloader module 2026-06-24 18:38:57 +02:00
b7ab12898e
feat(http): add UrlKind enum and probe_url_kind HEAD probe 2026-06-24 18:38:52 +02:00
143f71bc17
feat(core): auto-title for HTTP/S URL downloads
http::download now returns (hash, extension, Option<title_hint>).
Title is derived from Content-Disposition filename header (RFC 5987
filename*= preferred over plain filename=), falling back to the last
path segment of the final URL after redirects (percent-decoded).

capture.rs Source::Url arm passes the title through to record_media_entry
instead of None, so entries like 'Facharbeit.pdf' or 'facharbeit' appear
in the Title column instead of the raw entry_uid.

Adds percent_decode(), title_from_content_disposition(), title_from_url()
helpers with 10 new unit tests (122 total, all green).
2026-06-24 14:56:48 +02:00