heruvym/internal/utils/middleware/http_middleware.go
skeris 08e65722ce
Some checks failed
Deploy / CreateImage (push) Successful in 2m17s
Deploy / DeployService (push) Successful in 1m4s
Lint / Lint (push) Failing after 4m40s
--
2024-12-05 22:27:29 +03:00

242 lines
6.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package middleware
import (
"fmt"
"gitea.pena/PenaSide/heruvym/internal/utils/jwt_adapter"
"github.com/gofiber/fiber/v2"
"strings"
"time"
"gitea.pena/PenaSide/hlog"
"github.com/rs/xid"
)
// My MiddleWare with gorilla/mux
type Middleware struct {
logger hlog.Logger
// mongo dal.LayerMongoDb
allowedOrigins string
allowedRoles map[string]string // key - path, value - roles
}
const sessionKey = "Sess"
const HostKey = "host"
func NewMiddleware(
logger hlog.Logger,
//mongo dal.LayerMongoDb,
allowedOrigins string,
allowedRoles map[string]string,
) *Middleware {
return &Middleware{
logger: logger,
allowedOrigins: allowedOrigins,
allowedRoles: allowedRoles,
}
}
func (mw *Middleware) MiddlewareLogger(ctx *fiber.Ctx) error {
mw.logger.Emit(DebugHttpRequest{
Url: ctx.OriginalURL(),
})
return ctx.Next()
}
func (mw *Middleware) MiddlewareOriginAccess(ctx *fiber.Ctx) error {
origin := ctx.Get("Origin")
if origin == "" {
if mw.allowedOrigins != "*" && !strings.Contains(mw.allowedOrigins, origin) {
mw.logger.Emit(ErrorOriginAccess{
Origin: origin,
Url: ctx.OriginalURL(),
})
return ctx.SendStatus(fiber.StatusForbidden)
}
}
fmt.Println("MWLOGGER", ctx.Get("Origin"))
return ctx.Next()
}
func recFn(rec interface{}) (int, string) {
var (
code int
message string
)
if err, ok := rec.(error); ok {
code = fiber.StatusInternalServerError
message = err.Error()
} else {
code = fiber.StatusInternalServerError
message = fmt.Sprintf("%v", rec)
}
return code, message
}
func (mw *Middleware) MiddlewareRecovery(ctx *fiber.Ctx) error {
defer func() {
if rec := recover(); rec != nil {
code, message := recFn(rec)
ctx.Status(code)
if _, err := ctx.WriteString(message); err != nil {
mw.logger.Emit(ErrorWritingPanicResponse{Err: err})
}
mw.logger.Emit(ErrorPanicInHttpHandler{
Code: code,
Message: message,
Recovered: rec,
})
}
}()
return ctx.Next()
}
func (mw *Middleware) MiddlewareJwt(ctx *fiber.Ctx) error {
var (
token, role string
adapter *jwt_adapter.JwtAdapter
err error
)
switch ctx.Get("Referer") {
case "sadmin.pena":
role = "admin"
case "admin.pena":
role = "admin"
default:
role = "user"
}
ctx.Locals(jwt_adapter.RoleKey, role)
tokenCookie := ctx.Cookies(jwt_adapter.DefaultHeaderKey)
if tokenCookie == "" {
if ctx.Method() == "GET" {
return ctx.Next()
}
headerToken := ctx.Get(jwt_adapter.DefaultHeaderKey)
if headerToken == "" || !strings.HasPrefix(headerToken, "Bearer") {
if ctx.Get(sessionKey) == "" {
sessCookie := ctx.Cookies(sessionKey)
if sessCookie == "" {
id := xid.New().String()
adapter = &jwt_adapter.JwtAdapter{Id: id}
ctx.Cookie(&fiber.Cookie{
Name: sessionKey,
Value: id,
Expires: time.Now().Add(time.Hour * 24 * 30),
SameSite: fiber.CookieSameSiteNoneMode,
Secure: true,
})
} else {
adapter = &jwt_adapter.JwtAdapter{Id: sessCookie}
}
} else {
adapter = &jwt_adapter.JwtAdapter{Id: ctx.Get(sessionKey)}
}
} else {
token = strings.Replace(headerToken, "Bearer ", "", -1)
}
} else {
token = tokenCookie
}
if adapter == nil {
adapter, err = jwt_adapter.Decode(token)
if err != nil {
mw.logger.Emit(ErrorJwtAccess{Err: err})
return ctx.Status(fiber.StatusUnauthorized).SendString("Unauthorized")
}
}
err = setJwtHeader(adapter, ctx.Response(), mw.logger)
if err != nil {
mw.logger.Emit(ErrorJwtAccess{Err: err})
return ctx.Status(fiber.StatusUnauthorized).SendString("Unauthorized")
}
ctx.Locals(jwt_adapter.DefaultHeaderKey, adapter)
return ctx.Next()
}
func (mw *Middleware) ExtractHostMiddleware(ctx *fiber.Ctx) error {
host := ctx.Get("Referer")
if host != "" {
ctx.Locals(HostKey, host)
}
return ctx.Next()
}
// todo useless?
//func getJwtUserId(r *http.Request) (string, error) {
// if jwtAdapter, ok := r.Context().Value(jwt_adapter.DefaultHeaderKey).(*jwt_adapter.JwtAdapter); ok {
// return jwtAdapter.Id, nil
// }
//
// return "", errors2.New("no token in context")
//}
//
//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 {
//
// // Если роли не указаны
// if allowedRoles == "" {
// next.ServeHTTP(w, r)
// return
// }
// /*
// 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
// }
// */
// // Если у пользователя не задана роль - блокируем доступ
// /* 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
// }*/
// }
//
// next.ServeHTTP(w, r)
// })
//}
//
//// MiddlewareJwtPlug jwt заглушка для отладки кода, удалить в релизе
///*
//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)
//
// next.ServeHTTP(w, r.WithContext(ctx))
// })
//}
//*/