rewrite midlleware to fiber

This commit is contained in:
Pavel 2024-09-25 13:18:19 +03:00
parent 2fb7cd5a02
commit 2746737891
4 changed files with 193 additions and 222 deletions

@ -17,6 +17,7 @@ func JwtPlug(c *fiber.Ctx) error {
return c.Next() return c.Next()
} }
// todo оказывается то что и хттп я переписал, ну надо убрать потом думаю
func Jwt(c *fiber.Ctx) error { func Jwt(c *fiber.Ctx) error {
var ( var (
token, role string token, role string

@ -1,14 +1,12 @@
package middleware package middleware
import ( import (
"context"
"fmt" "fmt"
"github.com/gofiber/fiber/v2"
"heruvym/jwt_adapter" "heruvym/jwt_adapter"
"net/http"
"strings" "strings"
"time" "time"
errors2 "github.com/pkg/errors"
"github.com/rs/xid" "github.com/rs/xid"
"github.com/themakers/hlog" "github.com/themakers/hlog"
) )
@ -38,23 +36,25 @@ func NewMiddleware(
} }
} }
func (mw *Middleware) MiddlewareLogger(next http.Handler) http.Handler { func (mw *Middleware) MiddlewareLogger(ctx *fiber.Ctx) error {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { mw.logger.Emit(DebugHttpRequest{
mw.logger.Emit(DebugHttpRequest{Url: r.URL.String()}) Url: ctx.OriginalURL(),
next.ServeHTTP(w, r)
}) })
return ctx.Next()
} }
func (mw *Middleware) MiddlewareOriginAccess(next http.Handler) http.Handler { func (mw *Middleware) MiddlewareOriginAccess(ctx *fiber.Ctx) error {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { origin := ctx.Get("Origin")
if len(r.Header["Origin"]) > 0 { if origin == "" {
if mw.allowedOrigins != "*" && !strings.Contains(mw.allowedOrigins, r.Header["Origin"][0]) { if mw.allowedOrigins != "*" && !strings.Contains(mw.allowedOrigins, origin) {
mw.logger.Emit(ErrorOriginAccess{Origin: r.Header["Origin"][0], Url: r.URL.String()}) mw.logger.Emit(ErrorOriginAccess{
return Origin: origin,
} Url: ctx.OriginalURL(),
})
return ctx.SendStatus(fiber.StatusForbidden)
} }
next.ServeHTTP(w, r) }
}) return ctx.Next()
} }
func recFn(rec interface{}) (int, string) { func recFn(rec interface{}) (int, string) {
@ -64,196 +64,177 @@ func recFn(rec interface{}) (int, string) {
) )
if err, ok := rec.(error); ok { if err, ok := rec.(error); ok {
code = http.StatusInternalServerError code = fiber.StatusInternalServerError
message = err.Error() message = err.Error()
} else { } else {
code = http.StatusInternalServerError code = fiber.StatusInternalServerError
message = fmt.Sprintf("%v", rec) message = fmt.Sprintf("%v", rec)
} }
return code, message return code, message
} }
func (mw *Middleware) MiddlewareRecovery(next http.Handler) http.Handler { func (mw *Middleware) MiddlewareRecovery(ctx *fiber.Ctx) error {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { defer func() {
defer func() { if rec := recover(); rec != nil {
if rec := recover(); rec != nil { code, message := recFn(rec)
code, message := recFn(rec) ctx.Status(code)
w.WriteHeader(code) if _, err := ctx.WriteString(message); err != nil {
if _, err := fmt.Fprint(w, message); err != nil { mw.logger.Emit(ErrorWritingPanicResponse{Err: err})
mw.logger.Emit(ErrorWritingPanicResponse{Err: err})
}
mw.logger.Emit(ErrorPanicInHttpHandler{
Code: code,
Message: message,
Recovered: rec,
})
} }
}() mw.logger.Emit(ErrorPanicInHttpHandler{
next.ServeHTTP(w, r) Code: code,
}) Message: message,
Recovered: rec,
})
}
}()
return ctx.Next()
} }
func (mw *Middleware) MiddlewareJwt(next http.Handler) http.Handler { func (mw *Middleware) MiddlewareJwt(ctx *fiber.Ctx) error {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var (
token, role string
adapter *jwt_adapter.JwtAdapter
err error
)
var ( switch ctx.Get("Referer") {
token, role string case "sadmin.pena":
adapter *jwt_adapter.JwtAdapter role = "admin"
) case "admin.pena":
role = "admin"
switch r.Header["Referer"][0] { default:
case "sadmin.pena": role = "user"
role = "admin"
case "admin.pena":
role = "admin"
default:
role = "user"
}
ctx := context.WithValue(r.Context(), jwt_adapter.RoleKey, role)
tokenCookie, err := r.Cookie(jwt_adapter.DefaultHeaderKey)
fmt.Println("MW1", err)
if err != nil {
// Escape GET requests
if r.Method == http.MethodGet {
next.ServeHTTP(w, r.WithContext(ctx))
return
}
fmt.Println("MW2", jwt_adapter.DefaultHeaderKey, r.Header[jwt_adapter.DefaultHeaderKey])
if len(r.Header[jwt_adapter.DefaultHeaderKey]) <= 0 || !func(hdrs []string) bool {
if len(hdrs) == 0 {return false}
fmt.Println("SS", hdrs[0])
if hdrs[0] == "Bearer" || hdrs[0] == "Bearer " {
return false
}
return true
}(r.Header[jwt_adapter.DefaultHeaderKey]) {
fmt.Println("MW3", r.Header[sessionKey], sessionKey, r.Header)
if len(r.Header[sessionKey]) == 0 {
if sessCookie, err := r.Cookie(sessionKey); err != nil {
id := xid.New().String()
adapter = &jwt_adapter.JwtAdapter{Id: id}
http.SetCookie(w, &http.Cookie{
Name: sessionKey,
Value: id,
Expires: time.Now().Add(time.Hour * 24 * 30),
SameSite: http.SameSiteNoneMode,
Secure: true,
})
fmt.Println("SSS", sessCookie, err)
} else {
fmt.Println("SSS1", sessCookie.Value, err)
adapter = &jwt_adapter.JwtAdapter{Id: sessCookie.Value}
}
} else {
adapter = &jwt_adapter.JwtAdapter{Id: r.Header[sessionKey][0]}
}
} else {
token = r.Header[jwt_adapter.DefaultHeaderKey][0]
token = strings.Replace(token, "Bearer ", "", -1)
}
} else {
token = tokenCookie.Value
}
if adapter == nil {
adapter, err = jwt_adapter.Decode(token)
if err != nil {
mw.logger.Emit(ErrorJwtAccess{Err: err})
w.WriteHeader(http.StatusUnauthorized)
return
}
}
err = setJwtHeader(adapter, w, mw.logger)
if err != nil {
mw.logger.Emit(ErrorJwtAccess{Err: err})
w.WriteHeader(http.StatusUnauthorized)
return
}
ctx = context.WithValue(ctx, jwt_adapter.DefaultHeaderKey, adapter)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
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") ctx.Locals(jwt_adapter.RoleKey, role)
} tokenCookie := ctx.Cookies(jwt_adapter.DefaultHeaderKey)
if tokenCookie == "" {
func (mw *Middleware) MiddlewareRoleAccess(next http.Handler) http.Handler { if ctx.Method() == "GET" {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return ctx.Next()
// Если доступ по роли задан
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
}*/
} }
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
}
next.ServeHTTP(w, r) 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()
} }
// MiddlewareJwtPlug jwt заглушка для отладки кода, удалить в релизе func (mw *Middleware) ExtractHostMiddleware(ctx *fiber.Ctx) error {
/* host := ctx.Get("Referer")
func (mw *Middleware) MiddlewareJwtPlug(next http.Handler) http.Handler { if host != "" {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ctx.Locals(HostKey, host)
adapter := jwt_adapter.JwtAdapter{ID: "604b79aced1d431b9e911f56"} }
adapter.Init() return ctx.Next()
adapter.SetUserID("604b79aced1d431b9e911f56")
ctx := context.WithValue(r.Context(), "JWT", &adapter)
next.ServeHTTP(w, r.WithContext(ctx))
})
} }
*/
func (mw *Middleware) ExtractHostMiddleware(next http.Handler) http.Handler { // todo useless?
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { //func getJwtUserId(r *http.Request) (string, error) {
host := r.Header["Referer"][0] // if jwtAdapter, ok := r.Context().Value(jwt_adapter.DefaultHeaderKey).(*jwt_adapter.JwtAdapter); ok {
ctx := context.WithValue(r.Context(), HostKey, host) // return jwtAdapter.Id, nil
next.ServeHTTP(w, r.WithContext(ctx)) // }
}) //
} // 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))
// })
//}
//*/

@ -1,12 +1,12 @@
package middleware package middleware
import ( import (
"heruvym/jwt_adapter" "github.com/gofiber/fiber/v2"
"net/http"
"github.com/themakers/hlog" "github.com/themakers/hlog"
"heruvym/jwt_adapter"
) )
func setJwtHeader(adapter *jwt_adapter.JwtAdapter, w http.ResponseWriter, logger hlog.Logger) error { // todo useless?
func setJwtHeader(adapter *jwt_adapter.JwtAdapter, w *fiber.Response, logger hlog.Logger) error {
return nil return nil
} }

@ -1,39 +1,28 @@
package middleware package middleware
import ( import (
"context" "github.com/gofiber/fiber/v2"
"heruvym/jwt_adapter" "heruvym/jwt_adapter"
"net/http"
) )
func (mw *Middleware) MiddlewareGetJwt(next http.Handler) http.Handler { func (mw *Middleware) MiddlewareGetJwt(c *fiber.Ctx) error {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if c.Method() != fiber.MethodGet {
// Escape non-GET requests return c.Next()
if r.Method != http.MethodGet { }
next.ServeHTTP(w, r)
return bearer := c.Query(jwt_adapter.DefaultHeaderKey)
if bearer != "" {
adapter, err := jwt_adapter.Decode(bearer)
if err == nil {
c.Locals(jwt_adapter.DefaultHeaderKey, adapter)
} }
ctx := r.Context() } else {
sess := c.Query("s")
bearer := r.URL.Query().Get(jwt_adapter.DefaultHeaderKey) if sess == "" {
if bearer != "" { return nil
adapter, err := jwt_adapter.Decode(bearer)
if err == nil {
//mw.logger.Emit(ErrorJwtAccess{Err: err})
//w.WriteHeader(http.StatusUnauthorized)
//return
ctx = context.WithValue(r.Context(), jwt_adapter.DefaultHeaderKey, adapter)
//
}
} else {
sess := r.URL.Query().Get("s")
if sess == "" {
return
}
ctx = context.WithValue(r.Context(), jwt_adapter.DefaultHeaderKey, &jwt_adapter.JwtAdapter{Id: sess})
} }
c.Locals(jwt_adapter.DefaultHeaderKey, &jwt_adapter.JwtAdapter{Id: sess})
}
next.ServeHTTP(w, r.WithContext(ctx)) return c.Next()
})
} }