Commit Graph

4 Commits

Author SHA1 Message Date
Ganonmaster 9c5212de05 feat: add emote import from legacy source with dry-run mode
Add POST /manage/import (auth-protected) that fetches emotes from a
legacy JSON endpoint, downloads each image, uploads it to S3, and
inserts it into the DB with the original timestamps preserved.

- Skip emotes whose name already exists (best-effort duplicate detection
  across SQLite and PostgreSQL via error code + message fallback)
- Validate source_url against a configurable host allowlist
  ([import] allowed_hosts in config, default ["smutba.se"])
- dry_run: true previews the import without writing to S3 or DB;
  result statuses are "would_import" / "would_skip" instead of
  "imported" / "skipped"
- Add db.name_exists() for efficient per-name existence checks used
  by dry-run
- Add reqwest (rustls-tls + json) and url dependencies
- Integration tests: auth guard, allowlist rejection, mirror +
  skip-duplicates, dry-run no-persist
2026-05-02 02:48:24 +02:00
Ganonmaster 2c219f5565 Fix S3 collision, alias clearing, upload limit, TOCTOU; add tests
Bug fixes:
- S3 key is now emoji/{uuid}.{ext} instead of emoji/{filename},
  preventing silent overwrites when two emotes share a filename
- UpdateEmoteRequest.alias uses Option<Option<String>> with a custom
  deserializer so a JSON null clears the alias rather than being ignored;
  the manage UI now sends null when the alias field is emptied
- POST /emotes is limited to 8 MiB via DefaultBodyLimit
- update_emote replaced the fetch-then-update pair with a single
  UPDATE … RETURNING using COALESCE/CASE WHEN, eliminating the TOCTOU
  race between concurrent edits

Refactoring:
- Extracted src/lib.rs so domain logic is a library crate; src/main.rs
  is now a thin startup entry point
- auth::check decoupled from AppState — takes Option<&AuthConfig> directly
- Removed unused config field from Database struct

Tests (40 total):
- auth: 10 unit tests covering all check() branches
- models: 6 unit tests for timestamp parsing and alias deserialization
- db: 9 unit tests against in-memory SQLite covering full CRUD
- routes: 15 integration tests in tests/routes.rs covering auth
  middleware, input validation, and all mutating endpoints
2026-04-28 11:31:25 +02:00
Ganonmaster 08fd6cea70 Add HTTP Basic Auth
All write endpoints and the manage
routes are gated behind HTTP Basic Auth middleware; credentials are
configured via [auth] in config.toml or APP__AUTH__USERNAME /
APP__AUTH__PASSWORD environment variables.
2026-04-28 03:23:57 +02:00
Ganonmaster 33acab96a2 Implement Rust-based emote database and REST API 2026-03-18 13:18:40 +00:00