b5e155fb72
Categories can now be marked "Private" in the admin panel's Category priority list. Private categories (and every article tagged with one, even if it's also tagged with a public category) are hidden from /api/categories, /api/feed, and /api/article/:id for anyone without a valid login — a plain visitor's browser, not the admin API key, since that's a header-based credential for the admin SPA only. Login is a single shared password set via PRIVATE_ACCESS_PASSWORD in the backend's .env (unset by default, which disables the feature entirely). On success the backend sets a stateless httpOnly cookie — its value is a deterministic hash of the password, checked with a timing-safe comparison on every request, so there's no session table to maintain. The cookie is requested at the ~400-day cap browsers enforce on persistent cookies, the closest a cookie can get to "retained indefinitely." On the frontend, an always-visible lock icon in the masthead (shown whenever the feature is configured, independent of the admin panel's own enabled/disabled toggle) opens a password prompt and reflects locked/unlocked state. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014c1L8ghNBFjfiH64UMViP8
19 lines
885 B
Bash
19 lines
885 B
Bash
PORT=4000
|
|
FRONTEND_ORIGIN=http://localhost:5173
|
|
DB_PATH=./data/homefeed.db
|
|
MEDIA_DIR=./data/media
|
|
|
|
# There's no admin username/password to configure here — the backend generates a
|
|
# random API key on every startup and prints it to the console. Copy that key into
|
|
# the admin login page (every /api/admin/* request requires it as an X-Api-Key
|
|
# header). It changes on every restart, so check the console output each time.
|
|
|
|
NODE_ENV=development
|
|
|
|
# Optional — unlocks "private" categories (marked in the admin panel's Category
|
|
# priority list) for visitors who log in with this password on the public site's
|
|
# lock icon. Leave unset to disable private categories entirely (they stay hidden
|
|
# from everyone, with no way to unlock them). Unlike the admin API key above, this
|
|
# is a fixed password you choose, and the resulting login persists across restarts.
|
|
# PRIVATE_ACCESS_PASSWORD=
|