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:
@@ -34,15 +34,15 @@ func (h *Handler) RegisterRoutes(mux *http.ServeMux) {
|
||||
mux.HandleFunc("POST /logout", h.logout)
|
||||
mux.Handle("GET /static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
|
||||
|
||||
// Authenticated
|
||||
// Authenticated (any role)
|
||||
mux.HandleFunc("GET /", h.requireAuth(h.listBooks))
|
||||
mux.HandleFunc("GET /book/{id}", h.requireAuth(h.bookDetails))
|
||||
mux.HandleFunc("GET /download/{id}", h.requireAuth(h.downloadBook))
|
||||
mux.HandleFunc("GET /cover/{id}", h.requireAuth(h.bookCover))
|
||||
|
||||
// Upload (authenticated + can_upload)
|
||||
mux.HandleFunc("GET /upload", h.requireUpload(h.uploadPage))
|
||||
mux.HandleFunc("POST /upload", h.requireUpload(h.uploadSubmit))
|
||||
// Uploader and above
|
||||
mux.HandleFunc("GET /upload", h.requireRole(users.RoleUploader, h.uploadPage))
|
||||
mux.HandleFunc("POST /upload", h.requireRole(users.RoleUploader, h.uploadSubmit))
|
||||
}
|
||||
|
||||
func (h *Handler) listBooks(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -52,7 +52,7 @@ func (h *Handler) listBooks(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
sess := sessionFrom(r)
|
||||
canUpload := sess != nil && sess.CanUpload
|
||||
canUpload := sess != nil && sess.Role.AtLeast(users.RoleUploader)
|
||||
render(w, r.Context(), views.IndexPage(books, canUpload))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user