test(security): add comprehensive security tests
- Test password complexity requirements - Test account lockout mechanism - Test rate limiting functionality - Test JWT expiration (1 hour) - Test refresh token expiration (7 days) - Test password requirements list - Verify transaction manager and error handler types - All tests passing
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// ErrorResponse represents a standardized error response
|
||||
type ErrorResponse struct {
|
||||
Error string `json:"error"`
|
||||
Message string `json:"message,omitempty"`
|
||||
Code string `json:"code,omitempty"`
|
||||
}
|
||||
|
||||
// HTTPError represents an HTTP error with additional context
|
||||
type HTTPError struct {
|
||||
Code int
|
||||
Message string
|
||||
Err error
|
||||
}
|
||||
|
||||
// Error implements the error interface
|
||||
func (e *HTTPError) Error() string {
|
||||
if e.Err != nil {
|
||||
return fmt.Sprintf("%s: %v", e.Message, e.Err)
|
||||
}
|
||||
return e.Message
|
||||
}
|
||||
|
||||
// Common error types
|
||||
var (
|
||||
ErrBadRequest = &HTTPError{Code: http.StatusBadRequest, Message: "Bad request"}
|
||||
ErrUnauthorized = &HTTPError{Code: http.StatusUnauthorized, Message: "Unauthorized"}
|
||||
ErrForbidden = &HTTPError{Code: http.StatusForbidden, Message: "Forbidden"}
|
||||
ErrNotFound = &HTTPError{Code: http.StatusNotFound, Message: "Resource not found"}
|
||||
ErrConflict = &HTTPError{Code: http.StatusConflict, Message: "Resource conflict"}
|
||||
ErrTooManyRequest = &HTTPError{Code: http.StatusTooManyRequests, Message: "Too many requests"}
|
||||
ErrInternal = &HTTPError{Code: http.StatusInternalServerError, Message: "Internal server error"}
|
||||
)
|
||||
|
||||
// NewHTTPError creates a new HTTP error
|
||||
func NewHTTPError(code int, message string, err error) *HTTPError {
|
||||
return &HTTPError{
|
||||
Code: code,
|
||||
Message: message,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
// RespondWithError sends a standardized error response
|
||||
func RespondWithError(c echo.Context, code int, message string, err error) error {
|
||||
response := ErrorResponse{
|
||||
Error: message,
|
||||
Message: "",
|
||||
Code: "",
|
||||
}
|
||||
|
||||
// Include original error message in development mode if available
|
||||
if err != nil {
|
||||
response.Message = err.Error()
|
||||
}
|
||||
|
||||
return c.JSON(code, response)
|
||||
}
|
||||
|
||||
// RespondWithHTTPError sends an HTTPError as JSON
|
||||
func RespondWithHTTPError(c echo.Context, httpErr *HTTPError) error {
|
||||
response := ErrorResponse{
|
||||
Error: httpErr.Message,
|
||||
}
|
||||
|
||||
if httpErr.Err != nil {
|
||||
response.Message = httpErr.Err.Error()
|
||||
}
|
||||
|
||||
return c.JSON(httpErr.Code, response)
|
||||
}
|
||||
|
||||
// WrapHandler wraps an echo.HandlerFunc to return standardized errors
|
||||
func WrapHandler(fn func(c echo.Context) error) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
err := fn(c)
|
||||
if err != nil {
|
||||
if httpErr, ok := err.(*HTTPError); ok {
|
||||
return RespondWithHTTPError(c, httpErr)
|
||||
}
|
||||
return RespondWithError(c, http.StatusInternalServerError, "Internal server error", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user