feat: quiz and rbac

This commit is contained in:
Krispire Admin
2026-10-15 19:43:17 +05:30
parent 7d7ba2a002
commit 4b38047c26
26 changed files with 3270 additions and 75 deletions
+26 -3
View File
@@ -8,6 +8,8 @@ import (
"strings"
"github.com/go-chi/chi/v5"
"github.com/prabhupadasays/spsays-bff/internal/middleware"
"github.com/prabhupadasays/spsays-bff/internal/rbac"
"github.com/prabhupadasays/spsays-bff/internal/repository"
"github.com/prabhupadasays/spsays-bff/internal/service"
"github.com/prabhupadasays/spsays-bff/pkg/response"
@@ -15,9 +17,15 @@ import (
// AdminHandler serves /api/v1/admin/* — gated by RequireAuth + RequireAdmin in
// the router, so every method here can assume an admin caller.
type AdminHandler struct{ svc *service.AdminService }
type AdminHandler struct {
svc *service.AdminService
// staff guards actions that would otherwise reach other staff members.
staff *repository.StaffRepo
}
func NewAdminHandler(svc *service.AdminService) *AdminHandler { return &AdminHandler{svc: svc} }
func NewAdminHandler(svc *service.AdminService, staff *repository.StaffRepo) *AdminHandler {
return &AdminHandler{svc: svc, staff: staff}
}
// pageParams pulls (q, limit, offset) from the query string with sane defaults.
func pageParams(r *http.Request) (q string, limit, offset int) {
@@ -316,7 +324,22 @@ func (h *AdminHandler) UnbanUser(w http.ResponseWriter, r *http.Request) {
}
func (h *AdminHandler) setUserBanned(w http.ResponseWriter, r *http.Request, banned bool) {
ok, err := h.svc.SetUserBanned(r.Context(), chi.URLParam(r, "id"), banned)
target := chi.URLParam(r, "id")
// A banned account loses panel access, so banning a staff member is a way
// to remove them — which only superadmins may do. Without this, an Admin
// holding users:ban could ban a Superadmin out of the panel.
if _, err := h.staff.Access(r.Context(), target); err == nil {
if s := middleware.Staff(r.Context()); s == nil || !s.Perms.Has(rbac.ManageStaff) {
response.Error(w, http.StatusForbidden,
"staff accounts are managed from the Staff page by a superadmin")
return
}
if target == middleware.UserID(r.Context()) {
response.Error(w, http.StatusConflict, "you can't ban yourself")
return
}
}
ok, err := h.svc.SetUserBanned(r.Context(), target, banned)
if err != nil {
response.Error(w, http.StatusInternalServerError, "could not update account")
return