package middleware import ( "context" "net/http" "strings" "github.com/panelhosting/panel/internal/authsvc" "github.com/panelhosting/panel/internal/config" "github.com/panelhosting/panel/internal/models" ) type ctxKey int const userKey ctxKey = 1 func UserFromContext(ctx context.Context) (*models.User, bool) { u, ok := ctx.Value(userKey).(*models.User) return u, ok } type Auth struct { auth *authsvc.Service cfg *config.Config } func NewAuth(auth *authsvc.Service, cfg *config.Config) *Auth { return &Auth{auth: auth, cfg: cfg} } func (a *Auth) Require(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { token := tokenFromRequest(r, a.cfg.SessionCookieName) user, err := a.auth.UserByToken(r.Context(), token) if err != nil { writeUnauthorized(w) return } ctx := context.WithValue(r.Context(), userKey, user) next(w, r.WithContext(ctx)) } } func (a *Auth) Optional(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { token := tokenFromRequest(r, a.cfg.SessionCookieName) user, err := a.auth.UserByToken(r.Context(), token) if err == nil { ctx := context.WithValue(r.Context(), userKey, user) r = r.WithContext(ctx) } next(w, r) } } func tokenFromRequest(r *http.Request, cookieName string) string { if c, err := r.Cookie(cookieName); err == nil && c.Value != "" { return c.Value } h := r.Header.Get("Authorization") if strings.HasPrefix(h, "Bearer ") { return strings.TrimPrefix(h, "Bearer ") } return "" } func writeUnauthorized(w http.ResponseWriter) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusUnauthorized) _, _ = w.Write([]byte(`{"error":"unauthorized"}`)) } func IsAdmin(user *models.User) bool { return user.Role == models.RoleSuperAdmin || user.Role == models.RoleAdmin }