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>
This commit is contained in:
code
2026-07-15 00:17:54 +00:00
parent cb64836901
commit b882c304b1
39 changed files with 1476 additions and 318 deletions
+8 -8
View File
@@ -15,11 +15,11 @@ return [
// 'matomo_url' => 'https://matomo.example.com/',
// 'matomo_site_id' => '1',
// Docs: /admin/docs/admin-auth — generate a hash with:
// php -r "echo password_hash('yourpassword', PASSWORD_DEFAULT), PHP_EOL;"
// or use the built-in /admin/password-hash form.
// 'admin_username' => 'admin',
// 'admin_password_hash' => '$2y$10$...',
// Docs: /admin/docs/admin-auth — session login for /admin/* against
// the SQLite-backed users table. After enabling, create the first user
// at /admin/users, or beforehand (safer) with:
// php novaconium/bin/create-admin-user.php <username>
// 'admin_auth_enabled' => true,
// Docs: /admin/docs/database — adds (or overrides) named Lib\Db
// connections. This merges into db_connections by name rather than
@@ -38,9 +38,9 @@ return [
// ],
// ],
// Docs: /admin/docs/drafts — requires admin_password_hash above to be
// set to actually gate anything; open access otherwise, same as the
// rest of /admin/*.
// Docs: /admin/docs/drafts — requires admin_auth_enabled above (and at
// least one user) to actually gate anything; open access otherwise,
// same as the rest of /admin/*.
// 'draft_routes' => ['blog/upcoming-post'],
// Docs: /admin/docs/content-index — powers /sitemap.xml, /search, and