From 778cb72c8a0902bd0b8159ebd3bb7eff93f28c83 Mon Sep 17 00:00:00 2001 From: grm Date: Mon, 14 Sep 2026 23:51:55 +0300 Subject: Turn the image library into a file library, with a per-blog upload limit Bloggers want to attach PDFs, archives, audio and other files to posts, not only images. The Images tab becomes Files: any type is accepted, listed by kind with search, paging, rename and multi-file upload, and the editor's paste/drop/"Insert file" takes anything (images are shown, everything else becomes a link). The default limit goes from 5 to 10 MB and the superadmin can override it per blog from /admin/. Files stay in Postgres so one pg_dump is still the whole blog. The bytea column is STORAGE EXTERNAL and /media streams it in substring() slices, so serving never holds a whole file in memory whatever limit a blog gets. Serving any type on the root domain, which carries the session cookie, needs a policy: uploads are typed by sniffing (the extension may only refine a generic sniff to an allowlisted type) and only images, PDF, plain text, audio and video render inline; HTML, SVG, XML, scripts, archives and binaries always go out as application/octet-stream with Content-Disposition: attachment. The body cap moves out of requireAuth into guardPOST, which runs after withBlog has resolved the blog and so knows its limit. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Sd8UPWrvyYCLj97JexNw3A --- .env.example | 2 +- AGENTS.md | 80 +++++-- README.md | 20 +- cmd/blogspace/seed.go | 9 +- internal/config/config.go | 6 +- internal/db/migrations/blog/00003_files.sql | 25 ++ .../db/migrations/control/00002_upload_limit.sql | 6 + internal/i18n/el.go | 67 ++++-- internal/markdown/render_test.go | 4 +- internal/store/blogs.go | 21 +- internal/store/files.go | 174 ++++++++++++++ internal/store/files_test.go | 69 ++++++ internal/store/images.go | 57 ----- internal/store/users.go | 9 +- internal/web/filetype.go | 196 +++++++++++++++ internal/web/filetype_test.go | 192 +++++++++++++++ internal/web/handlers_admin.go | 34 ++- internal/web/handlers_design.go | 174 +------------- internal/web/handlers_files.go | 264 +++++++++++++++++++++ internal/web/handlers_media.go | 13 +- internal/web/handlers_pages.go | 6 +- internal/web/handlers_posts.go | 6 +- internal/web/handlers_sections.go | 6 +- internal/web/routes.go | 10 +- internal/web/server.go | 93 ++++++-- internal/web/static/dashboard.css | 25 +- internal/web/templates.go | 9 +- internal/web/templates/admin/delete_user.html | 2 +- internal/web/templates/admin/index.html | 9 +- internal/web/templates/dashboard/files.html | 95 ++++++++ internal/web/templates/dashboard/images.html | 24 -- internal/web/templates/dashboard/overview.html | 2 +- internal/web/templates/dashboard/page_form.html | 2 +- internal/web/templates/dashboard/post_form.html | 2 +- internal/web/templates/dashboard/section_form.html | 2 +- internal/web/templates/partials/dashnav.html | 2 +- internal/web/templates/partials/editor.html | 18 +- internal/web/templates/partials/mdhelp.html | 2 +- internal/web/web_test.go | 28 ++- 39 files changed, 1373 insertions(+), 392 deletions(-) create mode 100644 internal/db/migrations/blog/00003_files.sql create mode 100644 internal/db/migrations/control/00002_upload_limit.sql create mode 100644 internal/store/files.go create mode 100644 internal/store/files_test.go delete mode 100644 internal/store/images.go create mode 100644 internal/web/filetype.go create mode 100644 internal/web/filetype_test.go create mode 100644 internal/web/handlers_files.go create mode 100644 internal/web/templates/dashboard/files.html delete mode 100644 internal/web/templates/dashboard/images.html diff --git a/.env.example b/.env.example index bc29fa2..ee6d25f 100644 --- a/.env.example +++ b/.env.example @@ -8,6 +8,6 @@ JWT_SECRET=change-me-to-a-long-random-string SUPERADMIN_USERNAME=admin SUPERADMIN_PASSWORD=change-me POSTGRES_PASSWORD=change-me-too -MAX_UPLOAD_MB=5 +MAX_UPLOAD_MB=10 # Only when running the dashboard on a non-standard port (dev): appended to generated blog links. #PUBLIC_PORT=8080 diff --git a/AGENTS.md b/AGENTS.md index 09d9b7d..4a04077 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -22,12 +22,14 @@ table and deployment notes. needs JS, keep it small and give it a sensible fallback where cheap (e.g. the `