package api import ( "net/http" "strings" "github.com/gin-gonic/gin" "booklib/internal/auth" "booklib/internal/config" "booklib/internal/redispkg" "booklib/internal/scanner" "booklib/internal/store" ) type api struct { cfg *config.Config st *store.Store rdb *redispkg.R sc *scanner.Scanner } func err(c *gin.Context, status int, code, msg string) { c.AbortWithStatusJSON(status, gin.H{"error": gin.H{"code": code, "message": msg}}) } func (a *api) authMw() gin.HandlerFunc { return func(c *gin.Context) { h := c.GetHeader("Authorization") tok, ok := strings.CutPrefix(h, "Bearer ") if !ok { err(c, http.StatusUnauthorized, "unauthorized", "missing bearer token") return } cl, perr := auth.Parse(a.cfg.JWTSecret, tok) if perr != nil { err(c, http.StatusUnauthorized, "unauthorized", "invalid token") return } c.Set("uid", cl.UID) c.Set("role", cl.Role) c.Next() } } func (a *api) adminOnly() gin.HandlerFunc { return func(c *gin.Context) { if c.GetString("role") != "admin" { err(c, http.StatusForbidden, "forbidden", "admin only") return } c.Next() } } func uid(c *gin.Context) int64 { return c.GetInt64("uid") } func isAdmin(c *gin.Context) bool { return c.GetString("role") == "admin" }