refactor: replace can_upload boolean with role-based access control
Introduces a three-tier role hierarchy: reader < uploader < admin. - internal/users/role.go: Role type, roleLevel map, AtLeast(min), ParseRole() — new roles added by inserting into roleLevel only - internal/users/store.go: versioned migrations via _schema_version table; v2 migration adds 'role' column and migrates existing can_upload data; SetRole() replaces SetUpload(); Session carries Role instead of CanUpload - internal/web/middleware.go: generic requireRole(minRole) middleware replaces the ad-hoc requireUpload - internal/web/handlers.go: upload routes use requireRole(RoleUploader); listBooks derives canUpload from sess.Role.AtLeast(RoleUploader) - cmd/admin/main.go: user add --role <reader|uploader|admin>, user set-role replaces user set-upload - README, copilot-instructions updated Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -22,10 +22,10 @@ go run ./cmd/server # run dev server on :8080
|
||||
## Admin CLI
|
||||
|
||||
```bash
|
||||
go run ./cmd/admin user add <name> [--upload] # Benutzer anlegen
|
||||
go run ./cmd/admin user list # alle Benutzer
|
||||
go run ./cmd/admin user delete <name> # löschen
|
||||
go run ./cmd/admin user set-upload <name> <true|false>
|
||||
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
|
||||
@@ -33,11 +33,23 @@ go run ./cmd/admin user set-upload <name> <true|false>
|
||||
- `cmd/server/main.go` — entrypoint; wires `library.Service`, `users.Store` and
|
||||
`web.Handler` together and starts the HTTP server.
|
||||
- `internal/library` — core domain logic, no HTTP dependency (unchanged).
|
||||
- `internal/users/store.go` — SQLite-backed user store (`modernc.org/sqlite`,
|
||||
pure Go driver). Tables: `users` (id, username, password_hash bcrypt,
|
||||
can_upload), `sessions` (token, user_id FK, expires_at unix timestamp).
|
||||
Sessions TTL = 30 days. Key methods: `Authenticate`, `CreateSession`,
|
||||
`LookupSession`, `DeleteSession`, `CreateUser`, `SetUpload`, `DeleteUser`, `ListUsers`.
|
||||
- `internal/users/role.go` — `Role` type (`reader`, `uploader`, `admin`),
|
||||
`roleLevel` map für Hierarchie, `AtLeast(min Role)`, `ParseRole(s)`.
|
||||
Neue Rollen: in `roleLevel` eintragen und ggf. Routen anpassen — kein
|
||||
Schema-Change nötig.
|
||||
- `internal/users/store.go` — SQLite-backed user store. Migrations via
|
||||
`_schema_version`-Tabelle (geordnete `migrations [][]string`); neue
|
||||
Migrationen am Ende anhängen. `role TEXT` statt `can_upload INTEGER`.
|
||||
- `internal/web/middleware.go` — `requireRole(minRole users.Role)` ist die
|
||||
zentrale Middleware; `requireAuth` ist ein Spezialfall davon (implizit
|
||||
`RoleReader`).
|
||||
- Auth: `/login` und `/static/` sind die einzigen öffentlichen Routes.
|
||||
Upload-Routes verwenden `requireRole(RoleUploader)`.
|
||||
|
||||
**Rollen-Hierarchie:**
|
||||
```
|
||||
reader (0) < uploader (1) < admin (2)
|
||||
```
|
||||
- `cmd/admin/main.go` — CLI binary for user management; reads `USERS_DB` env var.
|
||||
- `internal/web/handlers.go` — HTTP handlers including `loginPage`,
|
||||
`loginSubmit`, `logout`, `uploadPage`, `uploadSubmit`.
|
||||
|
||||
Reference in New Issue
Block a user