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

131 commits

Author SHA1 Message Date
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
f9de282b0e
feat(nix): add NixOS module for archivr-server
modules/nixos/archivr-server.nix — services.archivr-server NixOS module:
- enable/bind/archives/user/group/openFirewall options
- generates archivr-server.toml from options via pkgs.writeText
- pins auth DB to /var/lib/archivr-server/ (StateDirectory)
- dedicated archivr system user + group
- hardened systemd unit: ProtectSystem=strict, NoNewPrivileges,
  PrivateTmp, RestrictNamespaces, etc.; archive paths whitelisted
- openFirewall parses the port from the bind string automatically

flake.nix:
- add self to outputs args
- add aarch64-linux to systems (Raspberry Pi / ARM servers)
- expose nixosModules.archivr-server + nixosModules.default

.gitignore: whitelist modules/ directory

docs/README.md: add 'Hosting on NixOS' section with full example
2026-06-29 16:51:20 +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
3ccfcce87b
feat(ui): add Storybook design system refinements 2026-06-28 21:01:50 +02:00
46ad816c4c
fix(flake): add openssl to buildInputs for Rust packages (#10)
Garnix CI was failing because openssl-sys couldn't find the OpenSSL
library. Added pkgs.openssl to buildInputs for both archivr_cli_unwrapped
and archivr_server_unwrapped to provide the necessary system dependency
and allow pkg-config to locate openssl.pc.
2026-06-27 11:54:31 +02:00
91e73d85e7
feat(collections): Track 8 — collection rename, delete, add/remove entries, per-entry visibility UI 2026-06-26 17:33:58 +02:00
ae92448fa3
build(frontend): bundle assets for collections UI 2026-06-26 17:33:50 +02:00
80dce80033
feat(collections): frontend — CollectionsView rename, delete, add/remove entries, per-entry visibility 2026-06-26 17:33:46 +02:00
c4ce2129bb
feat(collections): frontend — api.js updateCollection and deleteCollection helpers 2026-06-26 17:33:42 +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
96eaf50609
docs(settings): mark Track 7 done in NEXT.md 2026-06-26 17:20:06 +02:00
d558ce2a3f
feat(settings): Track 7 — account profile, password change, API tokens UI, instance settings
- db: display_name column migration, InstanceSettings struct, 6 new pub helpers
  (get/update_instance_settings, update_user_display_name, update_user_password,
  get_user_password_hash, get_user_display_name)
- routes: PATCH /api/auth/me (display name + password change, current-password verify);
  GET|PATCH /api/admin/instance-settings (ROLE_ADMIN); auth/me now returns display_name
- frontend/api.js: updateProfile, changePassword, listTokens, createToken,
  deleteToken, getInstanceSettings, updateInstanceSettings helpers
- frontend: SettingsView (Profile / API Tokens / Instance tabs), settings nav in
  Topbar, App routing for view === 'settings'
- 7 new routes tests; 176 tests green
2026-06-26 17:19:43 +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
78e763c377
feat(settings): frontend — SettingsView component, settings nav, App routing 2026-06-26 17:17:45 +02:00
677e5c439b
feat(settings): frontend — api.js helpers for profile, tokens, and instance settings 2026-06-26 17:17:40 +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
4d0daf2dc0
chore: update Cargo.lock after collections feature 2026-06-26 17:07:48 +02:00
915878ff10
feat(collections): Track 6 permissions & visibility — collection model, role-bitmask visibility, collection UI 2026-06-26 17:06:18 +02:00
1b91e7ef5e
docs(collections): mark Track 6 done in NEXT.md 2026-06-26 17:05:57 +02:00
cb390dfaab
build(frontend): bundle assets for collections UI 2026-06-26 17:05:22 +02:00
763cb8e17f
feat(collections): frontend — CollectionsView, nav, visibility in ContextRail 2026-06-26 17:04:49 +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
2c3d3eb86e
feat(users): Track 5 user management — admin panel, custom roles, banning
Adds admin-only user management API and UI:

- DB: UserSummary, RoleRecord structs; 10 new auth-DB helpers (list_users, create_user,
  get_user_by_uid, set_user_status, assign_role, remove_role, list_roles, create_custom_role,
  invalidate_user_sessions, get_user_id_by_uid) with 4 tests
- Server: 5 admin routes (/api/admin/users, /api/admin/users/:uid/status,
  /api/admin/users/:uid/roles, /api/admin/roles) with 7 handlers + 2 tests
- Frontend: 7 admin API helpers in api.js; AdminView two-tab panel (Users/Roles)
  with ban/unban, create user, create custom role forms
- Role bitmask: guest=1, user=2, admin=4, owner=8; custom roles bit>=4
- Ban invalidates all active sessions; only-owner guard prevents last owner removal

169 tests green, frontend builds clean.
2026-06-26 16:24:15 +02:00
b3b0c8ec8d
docs(users): mark Track 5 done in NEXT.md 2026-06-26 16:24:04 +02:00
dcbced3590
Merge branch 'task/user-mgmt-backend' 2026-06-26 16:22:56 +02:00
2335776347
feat(users): admin routes — list/create users, roles, set status 2026-06-26 16:22:08 +02:00
6357cc518e
Merge branch 'task/user-mgmt-frontend' 2026-06-26 16:18:40 +02:00
ffecb72230
Merge branch 'task/user-mgmt-db' 2026-06-26 16:16:50 +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
2042752177
feat(users): admin user management UI + api helpers 2026-06-26 15:02:50 +02:00
ff3d20ae04
feat(capture): Track 3 async capture jobs — spawn_blocking job queue
POST /api/archives/:id/captures now returns 202 Accepted immediately with
{ job_uid, status: "pending" }. The capture runs in a tokio::task::spawn_blocking
thread and updates the job status to running → completed/failed in the archive DB.

Core DB (database.rs):
- capture_jobs table: id, job_uid, archive_id, run_uid, status, error_text, created_at, updated_at
- create_capture_job, update_capture_job_status, get_capture_job, fail_stalled_capture_jobs

Core archive (archive.rs):
- CaptureJobSummary type + get_capture_job query

Server (routes.rs):
- capture_handler: creates job, spawns background capture, returns 202 immediately
- GET /api/archives/:id/capture_jobs/:job_uid: poll job status
- main.rs: on startup, marks any 'running' jobs from previous session as 'failed'

Frontend:
- api.js: submitCapture returns job object; pollCaptureJob added
- CaptureDialog.jsx: polls every 500ms after submit, shows 'Running…' state,
  handles completed (close + refresh) and failed (show error), cleans up interval

163 tests green. Frontend builds cleanly.
2026-06-26 12:59:00 +02:00
9f7b3c912a
build(frontend): update bundled assets for async capture polling 2026-06-26 12:59:00 +02:00
116b30e0e9
Merge branch 'task/async-capture-frontend' 2026-06-26 12:58:31 +02:00
5e31a4188c
Merge branch 'task/async-capture-backend' 2026-06-26 12:58:31 +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
9ac28459ed
feat(capture): async polling in CaptureDialog + pollCaptureJob api helper 2026-06-26 12:54:31 +02:00
f76f5438f2
feat(auth): Track 4 auth foundation — sessions, roles, login, setup wizard
Implements the full auth foundation layer across 13 atomic task commits:

Core DB (archivr-core/database.rs):
- initialize_auth_schema: roles, user_roles, sessions, api_tokens, instance_settings
- open_auth_db: dedicated server-level auth SQLite (separate from archive DBs)
- create_owner, compute_role_bits: cumulative role assignment (guest=1 user=2 admin=4 owner=8)
- create_session, get_session, delete_session, touch_session, delete_expired_sessions
- create_api_token, get_user_for_token, list_user_tokens, delete_api_token

Server (archivr-server):
- auth.rs: AuthUser Axum extractor (cookie→session or Bearer→token), Argon2id
  password hashing, random token generation, role bit constants
- AppState gains auth_db_path; ServerRegistry gains optional auth_db_path field
- main.rs: auth DB path computed from config dir, session cleanup background task (24h)
- setup_guard middleware: 503 SERVICE_UNAVAILABLE for all non-/api/auth/ routes until
  first owner account is created via POST /api/auth/setup
- Auth endpoints: GET|POST /api/auth/setup, POST /api/auth/login, POST /api/auth/logout,
  GET /api/auth/me, GET|POST|DELETE /api/auth/tokens
- WRITE routes guarded with ROLE_USER: captures, tag create/assign/remove

Frontend:
- LoginPage.jsx, SetupPage.jsx (new)
- App.jsx: AuthContext, auth state machine (loading→setup→login→authenticated),
  setup check on mount, auth:expired event listener
- api.js: checkSetup, doSetup, login, logout, fetchMe, 401 interceptor
- Topbar.jsx: user menu with username and logout button

Docs:
- NEXT.md: Track 4 marked done, Tracks 5-8 stubs added, old tracks renumbered

159 tests green. Frontend builds cleanly.
2026-06-26 12:04:08 +02:00
7cebf06124
chore: update Cargo.lock after frontend build 2026-06-26 12:03:30 +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
7671049f55
Merge branch 'task/auth-docs' 2026-06-26 11:59:31 +02:00
8edd17d694
Merge branch 'task/auth-topbar' 2026-06-26 11:59:31 +02:00