Commit Graph
3 Commits
Author SHA1 Message Date
codeandClaude Fable 5 b882c304b1 Replace Basic Auth with multi-user login, roles, groups, and Lib\Access
Admin login & user management (novaconium/ISSUES.md): session-based
login against a SQLite users table replaces the single-user HTTP Basic
Auth stopgap (admin_username/admin_password_hash and /admin/password-hash
are gone; one admin_auth_enabled flag, off by default with zero DB
footprint). New /admin/login, /admin/logout (POST-only, real page), and
/admin/users pages plus bin/create-admin-user.php.

First user created is the admin; everyone after is registered with a
unique normalized email and an optional group. /admin/* and drafts are
admin-only; Lib\Access gates page content from sidecars
(Access::require('group:members')) with login-redirect/404 responses —
public by default, static pages always public by construction. User
management covers disable/enable, delete, promote/demote, group, email,
and password, with last-active-admin lockout guards.

Also: Session::regenerate() against fixation, friendly missing-PDO-driver
errors in Lib\Db, docs at /admin/docs/access-control and updates across
admin-auth/drafts/sidecars/config/libraries and README/AGENTS.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 00:17:54 +00:00
code 4862526fa1 Add draft pages (admin-only preview); fix admin panel cache leak
Lets a page under App/pages/ be previewed by an admin before the public
can see it: list its route in draft_routes (App/config.php), checked in
bootstrap.php alongside the existing /admin/* gate. Not authenticated ->
same plain 404 an unmatched route gets, not a login prompt, so a draft's
existence isn't revealed. Authenticated -> renders normally. No separate
login flow needed - Basic Auth credentials are scoped to the whole
origin/realm, so authenticating once at /admin covers draft URLs too.

AdminAuth::isAuthenticated() is extracted out of requireLogin() so the
draft gate can reuse the same credential check with a different failure
response (404 vs. a 401 challenge).

Renderer::render() gains an $excludeFromCache param so a draft without
its own sidecar can't get written to the static HTML cache - .htaccess
serves a cached file before PHP, and therefore any auth check, ever runs
again, so an uncached exception is required, not just the auth gate.

While testing this, found the same bug already existed for /admin itself:
novaconium/pages/admin/index.twig has no sidecar, so it was already being
cached - meaning any admin visiting /admin once caused the panel to be
served to everyone, unauthenticated, straight from
public/cache/admin/. Fixed in this change by excluding every /admin/*
route from the cache the same way, and documented as a standing rule in
AGENTS.md: any future mechanism that conditionally hides page content
from the public has to make the same check, not just gate the initial
request.

Closes the "Draft pages (admin-only preview)" backlog item in
novaconium/ISSUES.md.
2026-07-14 16:35:31 +00:00
code fbd4e92e9f Replace v1 with v2 codebase
Full rewrite: swap out the v1 framework (src/, controllers/, views/,
twig/, sass/, skeleton/) for the working v2 codebase from phpproject
(App/, novaconium/, public/).
2026-07-14 01:58:25 +00:00