diff --git a/middleware/fiber_middleware.go b/middleware/fiber_middleware.go index 01e4ebd..d17898f 100644 --- a/middleware/fiber_middleware.go +++ b/middleware/fiber_middleware.go @@ -17,6 +17,7 @@ func JwtPlug(c *fiber.Ctx) error { return c.Next() } +// todo оказывается то что и хттп я переписал, ну надо убрать потом думаю func Jwt(c *fiber.Ctx) error { var ( token, role string diff --git a/middleware/http_middleware.go b/middleware/http_middleware.go index 9676cc9..070fb64 100644 --- a/middleware/http_middleware.go +++ b/middleware/http_middleware.go @@ -1,14 +1,12 @@ package middleware import ( - "context" "fmt" + "github.com/gofiber/fiber/v2" "heruvym/jwt_adapter" - "net/http" "strings" "time" - errors2 "github.com/pkg/errors" "github.com/rs/xid" "github.com/themakers/hlog" ) @@ -38,23 +36,25 @@ func NewMiddleware( } } -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) +func (mw *Middleware) MiddlewareLogger(ctx *fiber.Ctx) error { + mw.logger.Emit(DebugHttpRequest{ + Url: ctx.OriginalURL(), }) + return ctx.Next() } -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 - } +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) } - next.ServeHTTP(w, r) - }) + } + return ctx.Next() } func recFn(rec interface{}) (int, string) { @@ -64,196 +64,177 @@ func recFn(rec interface{}) (int, string) { ) if err, ok := rec.(error); ok { - code = http.StatusInternalServerError + code = fiber.StatusInternalServerError message = err.Error() } else { - code = http.StatusInternalServerError + code = fiber.StatusInternalServerError message = fmt.Sprintf("%v", rec) } return code, message } -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, - }) +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}) } - }() - next.ServeHTTP(w, r) - }) + mw.logger.Emit(ErrorPanicInHttpHandler{ + Code: code, + Message: message, + Recovered: rec, + }) + } + }() + + return ctx.Next() } -func (mw *Middleware) MiddlewareJwt(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { +func (mw *Middleware) MiddlewareJwt(ctx *fiber.Ctx) error { + var ( + token, role string + adapter *jwt_adapter.JwtAdapter + err error + ) - var ( - token, role string - adapter *jwt_adapter.JwtAdapter - ) - - switch r.Header["Referer"][0] { - case "sadmin.pena": - 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 + switch ctx.Get("Referer") { + case "sadmin.pena": + role = "admin" + case "admin.pena": + role = "admin" + default: + role = "user" } - 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 - }*/ + 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 + } - 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) 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)) - }) +func (mw *Middleware) ExtractHostMiddleware(ctx *fiber.Ctx) error { + host := ctx.Get("Referer") + if host != "" { + ctx.Locals(HostKey, host) + } + return ctx.Next() } -*/ -func (mw *Middleware) ExtractHostMiddleware(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - host := r.Header["Referer"][0] - ctx := context.WithValue(r.Context(), HostKey, host) - next.ServeHTTP(w, r.WithContext(ctx)) - }) -} +// 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)) +// }) +//} +//*/ diff --git a/middleware/middleware.go b/middleware/middleware.go index 5a7cd30..9b39c66 100644 --- a/middleware/middleware.go +++ b/middleware/middleware.go @@ -1,12 +1,12 @@ package middleware import ( - "heruvym/jwt_adapter" - "net/http" - + "github.com/gofiber/fiber/v2" "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 } diff --git a/middleware/sse_middleware.go b/middleware/sse_middleware.go index 24d7d80..03a302f 100644 --- a/middleware/sse_middleware.go +++ b/middleware/sse_middleware.go @@ -1,39 +1,28 @@ package middleware import ( - "context" + "github.com/gofiber/fiber/v2" "heruvym/jwt_adapter" - "net/http" ) -func (mw *Middleware) MiddlewareGetJwt(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // Escape non-GET requests - if r.Method != http.MethodGet { - next.ServeHTTP(w, r) - return +func (mw *Middleware) MiddlewareGetJwt(c *fiber.Ctx) error { + if c.Method() != fiber.MethodGet { + return c.Next() + } + + 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() - - bearer := r.URL.Query().Get(jwt_adapter.DefaultHeaderKey) - if bearer != "" { - - 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}) + } else { + sess := c.Query("s") + if sess == "" { + return nil } + c.Locals(jwt_adapter.DefaultHeaderKey, &jwt_adapter.JwtAdapter{Id: sess}) + } - next.ServeHTTP(w, r.WithContext(ctx)) - }) + return c.Next() }