canape/backend/auth/middleware.go

103 lines
2.3 KiB
Go

package auth
import (
"context"
"net/http"
"github.com/sirupsen/logrus"
)
// Middleware get User from session and put it in context
type Middleware struct {
authorizer *Authorizer
log *logrus.Entry
}
type authContextKey string
// NewMiddleware returns a new authentication middleware
func NewMiddleware(authorizer *Authorizer, log *logrus.Entry) *Middleware {
return &Middleware{
authorizer: authorizer,
log: log.WithField("middleware", "auth"),
}
}
func (m *Middleware) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
user, err := m.authorizer.CurrentUser(w, r)
if err != nil {
http.Error(w, err.Error(), http.StatusUnauthorized)
return
}
if user != nil {
m.log.Debugf("setting user %s in the context", user.GetName())
} else {
m.log.Debugf("got a nil user in the context")
}
ctxKey := authContextKey("auth.user")
ctx := context.WithValue(r.Context(), ctxKey, user)
r = r.WithContext(ctx)
next(w, r)
}
// MiddlewareRole handles the role checking for the current user
type MiddlewareRole struct {
authorizer *Authorizer
log *logrus.Entry
role string
}
// NewMiddlewareRole returns a new MiddlewareRole
func NewMiddlewareRole(authorizer *Authorizer, log *logrus.Entry, role string) *MiddlewareRole {
return &MiddlewareRole{
authorizer: authorizer,
log: log.WithField("middleware", "role"),
role: role,
}
}
func (m *MiddlewareRole) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
user := GetCurrentUser(r, m.log)
if user == nil || !user.HasRole(m.role) {
if user == nil {
m.log.Debug("user is nil in the context")
} else {
m.log.Debug("user doesn't have the role")
}
// return unauthorized
http.Error(w, "Invalid user role", http.StatusUnauthorized)
return
}
if !user.IsActivated() {
// return unauthorized
http.Error(w, "User is not activated", http.StatusUnauthorized)
return
}
m.log.Debug("user has the role and is activated, continuing")
next(w, r)
}
// GetCurrentUser gets the current user from the request context
func GetCurrentUser(r *http.Request, log *logrus.Entry) User {
log.Debug("getting user from context")
ctxKey := authContextKey("auth.user")
u := r.Context().Value(ctxKey)
if u == nil {
return nil
}
user, ok := u.(User)
if !ok {
panic("invalid user type")
}
return user
}