76 lines
1.8 KiB
Go
76 lines
1.8 KiB
Go
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
|
|
}
|