heruvym/middleware/http_middleware.go

213 lines
5.6 KiB
Go
Raw Normal View History

2021-05-15 14:03:10 +00:00
package middleware
2021-04-11 09:48:15 +00:00
import (
"context"
"fmt"
2021-09-05 15:24:13 +00:00
"heruvym/jwt_adapter"
2021-04-11 09:48:15 +00:00
"net/http"
"strings"
2023-03-01 17:38:03 +00:00
errors2 "github.com/pkg/errors"
"github.com/themakers/hlog"
2021-04-11 09:48:15 +00:00
)
2021-05-15 14:03:10 +00:00
// My MiddleWare with gorilla/mux
type Middleware struct {
2023-03-01 17:38:03 +00:00
logger hlog.Logger
// mongo dal.LayerMongoDb
2021-05-15 14:03:10 +00:00
allowedOrigins string
allowedRoles map[string]string // key - path, value - roles
2021-04-11 09:48:15 +00:00
}
2021-05-15 14:03:10 +00:00
func NewMiddleware(
logger hlog.Logger,
2023-03-01 17:38:03 +00:00
//mongo dal.LayerMongoDb,
2021-05-15 14:03:10 +00:00
allowedOrigins string,
allowedRoles map[string]string,
) *Middleware {
return &Middleware{
2023-03-01 17:38:03 +00:00
logger: logger,
// mongo: mongo,
2021-05-15 14:03:10 +00:00
allowedOrigins: allowedOrigins,
allowedRoles: allowedRoles,
}
}
2021-04-11 09:48:15 +00:00
2021-05-15 14:03:10 +00:00
func (mw *Middleware) MiddlewareLogger(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
mw.logger.Emit(DebugHttpRequest{Url: r.URL.String()})
next.ServeHTTP(w, r)
})
}
2021-04-11 09:48:15 +00:00
2021-05-15 14:03:10 +00:00
func (mw *Middleware) MiddlewareOriginAccess(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if len(r.Header["Origin"]) > 0 {
if mw.allowedOrigins != "*" && !strings.Contains(mw.allowedOrigins, r.Header["Origin"][0]) {
mw.logger.Emit(ErrorOriginAccess{Origin: r.Header["Origin"][0], Url: r.URL.String()})
return
}
}
next.ServeHTTP(w, r)
})
}
2021-05-01 10:05:45 +00:00
2021-05-15 14:03:10 +00:00
func recFn(rec interface{}) (int, string) {
var (
code int
message string
)
if err, ok := rec.(error); ok {
2023-03-01 17:38:03 +00:00
code = http.StatusInternalServerError
message = err.Error()
2021-05-15 14:03:10 +00:00
} else {
code = http.StatusInternalServerError
message = fmt.Sprintf("%v", rec)
}
2021-04-11 09:48:15 +00:00
2021-05-15 14:03:10 +00:00
return code, message
}
2021-04-11 09:48:15 +00:00
2021-05-15 14:03:10 +00:00
func (mw *Middleware) MiddlewareRecovery(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if rec := recover(); rec != nil {
code, message := recFn(rec)
w.WriteHeader(code)
if _, err := fmt.Fprint(w, message); err != nil {
mw.logger.Emit(ErrorWritingPanicResponse{Err: err})
}
mw.logger.Emit(ErrorPanicInHttpHandler{
Code: code,
Message: message,
Recovered: rec,
})
2021-04-11 09:48:15 +00:00
}
2021-05-15 14:03:10 +00:00
}()
next.ServeHTTP(w, r)
})
}
2021-04-11 09:48:15 +00:00
2021-05-15 14:03:10 +00:00
func (mw *Middleware) MiddlewareJwt(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
2021-04-11 09:48:15 +00:00
2023-03-01 17:38:03 +00:00
var token, role string
fmt.Println("HOOOOOST", r.Host)
2023-03-01 17:38:03 +00:00
switch r.Host {
case "admin.pena.digital":
role = "admin"
default:
role = "user"
}
ctx := context.WithValue(r.Context(), jwt_adapter.RoleKey, role)
2023-03-01 17:38:03 +00:00
2021-09-05 15:24:13 +00:00
tokenCookie, err := r.Cookie(jwt_adapter.DefaultHeaderKey)
if err != nil {
// Escape GET requests
if r.Method == http.MethodGet {
next.ServeHTTP(w, r.WithContext(ctx))
2021-09-05 15:24:13 +00:00
return
}
if len(r.Header[jwt_adapter.DefaultHeaderKey]) <= 0 {
2023-03-01 17:38:03 +00:00
mw.logger.Emit(ErrorJwtAccess{Err: errors2.New(jwt_adapter.DefaultHeaderKey + "header missing")})
w.WriteHeader(http.StatusUnauthorized)
return
2021-09-05 15:24:13 +00:00
}
token = r.Header[jwt_adapter.DefaultHeaderKey][0]
token = strings.Replace(token, "Bearer ", "", -1)
} else {
token = tokenCookie.Value
2021-04-11 09:48:15 +00:00
}
2021-05-15 14:03:10 +00:00
adapter, err := jwt_adapter.Decode(token)
2021-04-11 09:48:15 +00:00
2021-05-15 14:03:10 +00:00
if err != nil {
mw.logger.Emit(ErrorJwtAccess{Err: err})
w.WriteHeader(http.StatusUnauthorized)
return
2021-04-11 09:48:15 +00:00
}
2021-05-15 14:03:10 +00:00
err = setJwtHeader(adapter, w, mw.logger)
if err != nil {
mw.logger.Emit(ErrorJwtAccess{Err: err})
w.WriteHeader(http.StatusUnauthorized)
return
}
2021-04-11 09:48:15 +00:00
ctx = context.WithValue(ctx, jwt_adapter.DefaultHeaderKey, adapter)
2021-05-15 14:03:10 +00:00
next.ServeHTTP(w, r.WithContext(ctx))
})
2021-04-11 09:48:15 +00:00
}
2021-05-15 14:03:10 +00:00
func getJwtUserId(r *http.Request) (string, error) {
2021-09-05 15:24:13 +00:00
if jwtAdapter, ok := r.Context().Value(jwt_adapter.DefaultHeaderKey).(*jwt_adapter.JwtAdapter); ok {
2023-03-01 17:38:03 +00:00
return jwtAdapter.Id, nil
2021-04-11 09:48:15 +00:00
}
2021-05-15 14:03:10 +00:00
return "", errors2.New("no token in context")
2021-04-11 09:48:15 +00:00
}
2021-05-15 14:03:10 +00:00
func (mw *Middleware) MiddlewareRoleAccess(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Если доступ по роли задан
if allowedRoles, ok := mw.allowedRoles[r.URL.Path]; ok {
2021-04-11 09:48:15 +00:00
2021-05-15 14:03:10 +00:00
// Если роли не указаны
if allowedRoles == "" {
next.ServeHTTP(w, r)
return
2021-04-11 09:48:15 +00:00
}
2023-03-01 17:38:03 +00:00
/*
id, err := getJwtUserId(r)
if err != nil {
mw.logger.Emit(ErrorRoleAccess{Err: err})
http.Error(w, "internal server error", http.StatusInternalServerError)
return
}*/
/*
role, err := mw.mongo.GetProfileRole(r.Context(), id)
if err != nil {
mw.logger.Emit(ErrorRoleAccess{Err: err})
http.Error(w, "internal server error", http.StatusInternalServerError)
return
}
*/
2021-05-15 14:03:10 +00:00
// Если у пользователя не задана роль - блокируем доступ
2023-03-01 17:38:03 +00:00
/* if role == "" {
err = errors.UserHaveNoRole("User have no role")
mw.logger.Emit(ErrorRoleAccess{err})
http.Error(w, err.Error(), http.StatusForbidden)
return
}
// Если указан астериск - доступ имеет любая роль
if !(allowedRoles == "*" || strings.Contains(allowedRoles, role)) {
err = errors.UserHaveNoRole("User role not allowed")
mw.logger.Emit(ErrorRoleAccess{err})
http.Error(w, err.Error(), http.StatusForbidden)
return
}*/
2021-05-15 14:03:10 +00:00
}
2021-04-11 09:48:15 +00:00
2021-05-15 14:03:10 +00:00
next.ServeHTTP(w, r)
})
}
2021-04-11 09:48:15 +00:00
2021-05-15 14:03:10 +00:00
// MiddlewareJwtPlug jwt заглушка для отладки кода, удалить в релизе
2023-03-01 17:38:03 +00:00
/*
2021-05-15 14:03:10 +00:00
func (mw *Middleware) MiddlewareJwtPlug(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
adapter := jwt_adapter.JwtAdapter{ID: "604b79aced1d431b9e911f56"}
adapter.Init()
adapter.SetUserID("604b79aced1d431b9e911f56")
ctx := context.WithValue(r.Context(), "JWT", &adapter)
2021-04-11 09:48:15 +00:00
2021-05-15 14:03:10 +00:00
next.ServeHTTP(w, r.WithContext(ctx))
})
2021-04-11 09:48:15 +00:00
}
2023-03-01 17:38:03 +00:00
*/