Add Media manager (/admin/media), remove unused images/ scaffolding
Upload/browse/delete UI for files under public/uploads/, covered by the existing /admin/* auth gate with no separate feature flag needed (no SQLite dependency to gate). Extension allowlist and max upload size are configurable; filenames are sanitized and de-duplicated on upload, and deletes re-verify the resolved path lands inside the upload directory before touching disk. Docker gains a fourth-turned-third named volume for public/uploads/ so uploads survive a rebuild. images/ (reserved scaffolding for a future image feature) is removed — nothing ever consumed it, and public/uploads/ now covers that use case. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,7 @@ A tiny, Hugo-flavored PHP micro-framework. Routes are directories on disk, pages
|
||||
- **Admin authentication** — gate every `/admin/*` route behind a session login with multi-user management: a SQLite-backed `users` table, `/admin/login`/`/admin/logout`, and an `/admin/users` page to create, disable, delete, group, promote/demote, and change the email or password of accounts (plus a `novaconium/bin/create-admin-user.php` CLI for the first user or deploy scripts). Two roles: the first user created is the admin; everyone after is a registered user with an optional group. Every account has a unique, normalized email address — groundwork for email verification later. Enabled with a single `admin_auth_enabled` flag in `App/config.php`; off by default, and reusable for any admin page a project adds later.
|
||||
- **Access control** — assign a page (or a section, one line per page) to a user or group from its sidecar: `Access::require('group:members')` returns `null` or a ready-made `Response` (login redirect with a return path, or a 404 for the wrong account). Public is the default — a sidecar that never calls it is untouched, and static (sidecar-less, cached) pages are always public by construction. Gated pages stay out of `/search` and `/sitemap.xml` automatically.
|
||||
- **Draft pages** — list a route under `draft_routes` in `App/config.php` to make it visible only to an authenticated admin; anyone else gets a plain 404, not a login prompt. Reuses the admin auth check directly, and is excluded from static caching so a cached copy can't leak the draft to the public. See `/admin/docs/drafts`.
|
||||
- **Media manager** — `/admin/media`, an upload/browse/delete UI for files under `public/uploads/`, covered by the existing `/admin/*` auth gate with no separate flag needed. Extension allowlist and max upload size are configurable (`media_upload_extensions`/`media_upload_max_bytes` in `App/config.php`), filenames are sanitized and de-duplicated on upload, and deletes are re-verified to resolve inside the upload directory before touching disk. See `/admin/docs/media-manager`.
|
||||
- **Dark/light theme toggle** — a nav button flips a `data-theme` attribute (persisted to `localStorage`) that swaps every color via CSS custom properties; both palettes live in `App/sass/_colors.sass`, same override mechanism as everything else.
|
||||
- **Self-hosted spam prevention & form validation** — `Lib\SpamGuard`, a reusable class for any form: a CSS-hidden honeypot field plus a submission-timing check, no external CAPTCHA service, site key, or outbound API call. Pairs with `Lib\FormValidator` (accumulating required-field/email/length checks) and `Lib\Validate` (the underlying validation primitives — email, length, phone, postal/zip, spam-word checks). All three ship in `novaconium/lib/`, demonstrated on the contact form.
|
||||
- **Form security by default** — `Lib\Input`, a cleaning accessor for `$_POST`/`$_GET` (defense-in-depth against HTML/script injection, not a substitute for parameterized queries), and `Lib\Csrf`, standalone session-token CSRF protection called directly from a sidecar. Both ship in `novaconium/lib/`, wired into the contact form, `/admin/clear-cache`, `/admin/login`, and `/admin/users`.
|
||||
@@ -49,7 +50,7 @@ Point the vhost's document root at `public/`, make sure `mod_rewrite` is enabled
|
||||
docker compose up --build
|
||||
```
|
||||
|
||||
Builds an Arch Linux-based Apache/PHP image and serves the site at `http://localhost:8080/`. Three named volumes (`cache`, `data`, `images`) keep the page cache, SQLite database, and a reserved-for-later images directory out of paths the "Updating the framework" workflow below would wipe; `App/` is baked into the image but can be bind-mounted for edits without a rebuild. See [Docker](http://127.0.0.1:8000/admin/docs/docker) for details.
|
||||
Builds an Arch Linux-based Apache/PHP image and serves the site at `http://localhost:8080/`. Three named volumes (`cache`, `uploads`, `data`) keep the page cache, media manager uploads, and SQLite database out of paths the "Updating the framework" workflow below would wipe; `App/` is baked into the image but can be bind-mounted for edits without a rebuild. See [Docker](http://127.0.0.1:8000/admin/docs/docker) for details.
|
||||
|
||||
### Starting a new project
|
||||
|
||||
@@ -110,6 +111,7 @@ The full framework documentation — routing, sidecars, libraries, database, ses
|
||||
- [Admin authentication](http://127.0.0.1:8000/admin/docs/admin-auth)
|
||||
- [Access control](http://127.0.0.1:8000/admin/docs/access-control)
|
||||
- [Draft pages](http://127.0.0.1:8000/admin/docs/drafts)
|
||||
- [Media manager](http://127.0.0.1:8000/admin/docs/media-manager)
|
||||
- [Styling](http://127.0.0.1:8000/admin/docs/styling)
|
||||
- [Project layout](http://127.0.0.1:8000/admin/docs/project-layout)
|
||||
- [Third-party](http://127.0.0.1:8000/admin/docs/third-party)
|
||||
|
||||
Reference in New Issue
Block a user