b882c304b1
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>
105 lines
5.6 KiB
PHP
105 lines
5.6 KiB
PHP
<?php
|
|
|
|
// These are the framework defaults. A project overrides any subset of them
|
|
// by creating App/config.php returning an array of just the keys it wants
|
|
// to change — novaconium/bootstrap.php shallow-merges it over this file, the
|
|
// same App-over-novaconium override pattern used for pages/ and lib/. This
|
|
// file itself is not meant to be edited per-project.
|
|
return [
|
|
// Ordered override roots: App/pages is checked first so a project can
|
|
// override any page, sidecar, or layout by placing one at the same
|
|
// relative path there; novaconium/pages supplies the framework defaults.
|
|
'pages_dirs' => [
|
|
__DIR__ . '/../App/pages',
|
|
__DIR__ . '/pages',
|
|
],
|
|
'cache_dir' => __DIR__ . '/../public/cache',
|
|
'debug' => true,
|
|
|
|
// Site name used as the default page title, og:site_name, and the
|
|
// footer copyright line in novaconium/pages/_layout/layout.twig.
|
|
'site_name' => 'Novaconium Website',
|
|
|
|
// Matomo analytics. Leave both empty (the default) to disable tracking
|
|
// entirely — the layout emits no tracking script at all in that case.
|
|
// Set both via App/config.php to enable, e.g.:
|
|
// 'matomo_url' => 'https://matomo.example.com/',
|
|
// 'matomo_site_id' => '1',
|
|
'matomo_url' => '',
|
|
'matomo_site_id' => '',
|
|
|
|
// Gates every /admin/* route (clear-cache, docs, users, and any future
|
|
// admin page) behind a session login against the `users` table on
|
|
// Lib\Db's default connection — see /admin/docs/admin-auth. The first
|
|
// user created is the admin; users after that are 'registered', each
|
|
// with an optional group, and see whatever content sidecars grant via
|
|
// Lib\Access (see /admin/docs/access-control) — /admin/* itself 404s
|
|
// for them. Off by default because it depends on SQLite (same
|
|
// reasoning as content_index_enabled below): when false, /admin/* is
|
|
// wide open, /admin/login, /admin/logout, and /admin/users 404,
|
|
// Access::require() allows everything, and nothing ever touches
|
|
// Lib\Db because of this feature. After enabling it via
|
|
// App/config.php, create the first user at /admin/users (open access
|
|
// until at least one user exists) or with:
|
|
// php novaconium/bin/create-admin-user.php <username>
|
|
'admin_auth_enabled' => false,
|
|
|
|
// Lib\Db (see /admin/docs/database) — named, simultaneously-usable
|
|
// connections, keyed by name; 'default' is the only one required. A
|
|
// sidecar can use more than one at once, e.g. Db::query(...) (default)
|
|
// alongside Db::query(..., 'legacy'). Supported drivers: 'sqlite',
|
|
// 'mysql'. The default connection's path deliberately lives outside
|
|
// both public/ (must never be web-accessible) and novaconium/ (gets
|
|
// wholly replaced on a framework update — see
|
|
// /admin/docs/getting-started's "Updating the framework" section) — a
|
|
// top-level data/ directory, project-owned like App/, is the only safe
|
|
// place for it. migrations_dir is optional per connection (omit it to
|
|
// never run migrations against that connection, e.g. a read-only
|
|
// legacy database) and accepts either one path or an ordered list of
|
|
// roots — the default connection lists novaconium/migrations/ (framework
|
|
// -shipped schema, e.g. the content index — see /admin/docs/content-index)
|
|
// before App/migrations/ (project migrations), so framework migrations
|
|
// always apply first. NOTE: unlike every other key here, App/config.php
|
|
// merges into db_connections one level deeper than a normal shallow
|
|
// override — see the comment on Lib\Db::config() — so adding a second
|
|
// connection there doesn't require repeating 'default'.
|
|
'db_connections' => [
|
|
'default' => [
|
|
'driver' => 'sqlite',
|
|
'path' => __DIR__ . '/../data/novaconium.sqlite',
|
|
'migrations_dir' => [
|
|
__DIR__ . '/migrations',
|
|
__DIR__ . '/../App/migrations',
|
|
],
|
|
],
|
|
],
|
|
|
|
// Routes an admin can preview before the public can see them (see
|
|
// /admin/docs/drafts) — a list of Route::$dir-format paths, no leading
|
|
// slash, e.g. 'blog/upcoming-post'. Not authenticated as admin (per
|
|
// AdminAuth::isAuthenticated()) → 404, same as a route that doesn't
|
|
// exist at all, so a draft's existence isn't revealed to anyone
|
|
// poking at the URL. Authenticated → renders normally, and — critically
|
|
// — is never written to the static HTML cache regardless of whether
|
|
// the page has a sidecar (see Renderer::render()'s $isDraft param),
|
|
// since a world-readable cached copy would otherwise permanently leak
|
|
// the draft the first time an admin previewed it.
|
|
'draft_routes' => [],
|
|
|
|
// Content index (see /admin/docs/content-index) — backs /sitemap.xml,
|
|
// /search, and blog tag browsing. Off by default: all three depend on
|
|
// SQLite (Lib\Db), a real dependency plenty of sites built on this
|
|
// framework won't want at all, the same reasoning that keeps Matomo
|
|
// and admin auth off by default above. When false, all three routes
|
|
// 404 exactly as if they didn't exist, and nothing ever touches
|
|
// Lib\Db because of this feature — no data/novaconium.sqlite gets
|
|
// created just because the code exists. content_index_auto only
|
|
// matters once enabled: true (the default) reindexes lazily,
|
|
// on-demand, the first time a stale index is actually needed (never on
|
|
// a normal page view); false disables that and leaves indexing
|
|
// entirely to `php novaconium/bin/index-content.php`, e.g. from a
|
|
// deploy step.
|
|
'content_index_enabled' => false,
|
|
'content_index_auto' => true,
|
|
];
|