Docker Image bauen und veröffentlichen / docker (push) Successful in 2m38s
- internal/library: ListBooks only scans .epub files, dropping the pdf-specific metadata branch (epub metadata reading is now unconditional) - internal/web: uploadSubmit rejects non-.epub uploads with updated error message - views: upload form/file input and empty-library hint now reference only EPUB; templ regenerated - README/copilot-instructions updated to reflect EPUB-only scope Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
3.6 KiB
3.6 KiB
eBook Library (Go + templ)
Minimalistic, no-JS eBook library web app for reading EPUB files on a Tolino e-reader browser. UI text/comments are in German.
Build & run
go mod tidy # install deps
templ generate # regenerate views/*_templ.go from views/*.templ (required after editing .templ files)
go build ./... # build check
go run ./cmd/server # run dev server on :8080
templCLI is required wheneverviews/pages.templchanges — generated Go code lives inviews/pages_templ.goand is checked into the repo, so it must be regenerated and committed together with template edits.- No test suite exists yet.
- Config via env vars:
ADDR(default:8080),BOOKS_DIR(defaultbooks),USERS_DB(defaultusers.db).
Admin CLI
go run ./cmd/admin user add <name> [--role reader|uploader|admin] # Standard: reader
go run ./cmd/admin user list
go run ./cmd/admin user delete <name>
go run ./cmd/admin user set-role <name> <reader|uploader|admin>
Architecture
cmd/server/main.go— entrypoint; wireslibrary.Service,users.Storeandweb.Handlertogether and starts the HTTP server.internal/library— core domain logic, no HTTP dependency (unchanged).internal/users/role.go—Roletype (reader,uploader,admin),roleLevelmap für Hierarchie,AtLeast(min Role),ParseRole(s). Neue Rollen: inroleLeveleintragen und ggf. Routen anpassen — kein Schema-Change nötig.internal/users/store.go— SQLite-backed user store. Migrations via_schema_version-Tabelle (geordnetemigrations [][]string); neue Migrationen am Ende anhängen.role TEXTstattcan_upload INTEGER.internal/web/middleware.go—requireRole(minRole users.Role)ist die zentrale Middleware;requireAuthist ein Spezialfall davon (implizitRoleReader).- Auth:
/loginund/static/sind die einzigen öffentlichen Routes. Upload-Routes verwendenrequireRole(RoleUploader).
Rollen-Hierarchie:
reader (0) < uploader (1) < admin (2)
cmd/admin/main.go— CLI binary for user management; readsUSERS_DBenv var.internal/web/handlers.go— HTTP handlers includingloginPage,loginSubmit,logout,uploadPage,uploadSubmit.internal/web/middleware.go—requireAuthandrequireUploadmiddleware; session resolved from"session"cookie; stored in request context viasessionKey.views/pages.templ—LoginPage(errMsg),UploadPage(errMsg)added;IndexPagenow takescanUpload bool;Layoutincludes logout button.
Conventions
- Path traversal guards matter:
downloadBookvalidates the resolved book path stays withinBooksDir()before serving;cleanEPUBPathrejects../-escaping hrefs inside EPUB zips;uploadSubmitvalidates the destination path stays withinBooksDir(). Preserve these checks in any related changes. - Cover image reads are capped (
maxCoverBytes = 10 MiB) to avoid decompression abuse — keep similar limits when reading zip entries. - Handlers return
404for missing/emptyidand500on internal errors; keep that pattern for new routes. - Auth:
/loginand/static/are the only public routes — everything else goes throughrequireAuth. Routes needing upload permission userequireUpload(which wrapsrequireAuth). - Session cookie:
HttpOnly,SameSite=Lax, 30-day expiry; noSecureflag set (intended for LAN use without TLS). modernc.org/sqliteis a pure-Go SQLite driver (no CGo).MaxOpenConns(1)is set because SQLite doesn't support concurrent writers.users.dbis gitignored; create it at runtime with the admin CLI.