mirror of
https://github.com/hazemKrimi/crimson-vault.git
synced 2026-05-01 18:20:27 +00:00
wip: custom logger and error handler
This commit is contained in:
+3
-1
@@ -5,6 +5,7 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/hazemKrimi/crimson-vault/internal/api"
|
"github.com/hazemKrimi/crimson-vault/internal/api"
|
||||||
@@ -35,7 +36,8 @@ to quickly create a Cobra application.`,
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
server := api.API{ConfigDirectory: dir}
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
||||||
|
server := api.API{ConfigDirectory: dir, Logger: logger}
|
||||||
server.Initialize()
|
server.Initialize()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
"github.com/gorilla/sessions"
|
"github.com/gorilla/sessions"
|
||||||
@@ -11,12 +12,14 @@ import (
|
|||||||
|
|
||||||
"github.com/hazemKrimi/crimson-vault/internal/lib"
|
"github.com/hazemKrimi/crimson-vault/internal/lib"
|
||||||
"github.com/hazemKrimi/crimson-vault/internal/models"
|
"github.com/hazemKrimi/crimson-vault/internal/models"
|
||||||
|
"github.com/hazemKrimi/crimson-vault/internal/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type API struct {
|
type API struct {
|
||||||
ConfigDirectory string
|
ConfigDirectory string
|
||||||
instance *echo.Echo
|
instance *echo.Echo
|
||||||
db *models.DB
|
db *models.DB
|
||||||
|
Logger *slog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) Initialize() {
|
func (api *API) Initialize() {
|
||||||
@@ -26,6 +29,19 @@ func (api *API) Initialize() {
|
|||||||
db := &models.DB{}
|
db := &models.DB{}
|
||||||
ech := echo.New()
|
ech := echo.New()
|
||||||
ech.Validator = &CustomValidator{validator: validator}
|
ech.Validator = &CustomValidator{validator: validator}
|
||||||
|
ech.HTTPErrorHandler = func(err error, context echo.Context) {
|
||||||
|
if context.Response().Committed {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
custom, ok := err.(types.Error)
|
||||||
|
|
||||||
|
if ok {
|
||||||
|
context.JSONPretty(custom.Code, map[string][]string{"errors": custom.Messages}, " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
ech.DefaultHTTPErrorHandler(err, context)
|
||||||
|
}
|
||||||
|
|
||||||
db.Connect(api.ConfigDirectory)
|
db.Connect(api.ConfigDirectory)
|
||||||
db.MigrateClients()
|
db.MigrateClients()
|
||||||
@@ -34,6 +50,7 @@ func (api *API) Initialize() {
|
|||||||
api.instance = ech
|
api.instance = ech
|
||||||
api.db = db
|
api.db = db
|
||||||
|
|
||||||
|
api.instance.Use(api.LoggerMiddleware())
|
||||||
// TODO: Update with appropriate origins when finishing v1
|
// TODO: Update with appropriate origins when finishing v1
|
||||||
api.instance.Use(middleware.CORSWithConfig(middleware.CORSConfig{
|
api.instance.Use(middleware.CORSWithConfig(middleware.CORSConfig{
|
||||||
AllowOrigins: []string{"*"},
|
AllowOrigins: []string{"*"},
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/labstack/echo-contrib/session"
|
"github.com/labstack/echo-contrib/session"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
|
"github.com/labstack/echo/v4/middleware"
|
||||||
|
|
||||||
"github.com/hazemKrimi/crimson-vault/internal/types"
|
"github.com/hazemKrimi/crimson-vault/internal/types"
|
||||||
)
|
)
|
||||||
@@ -43,3 +46,28 @@ func (api *API) AuthSessionMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
|
|||||||
return next(context)
|
return next(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (api *API) LoggerMiddleware() echo.MiddlewareFunc {
|
||||||
|
return middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
|
||||||
|
LogStatus: true,
|
||||||
|
LogURI: true,
|
||||||
|
LogError: true,
|
||||||
|
HandleError: true,
|
||||||
|
LogMethod: true,
|
||||||
|
LogValuesFunc: func(logContext echo.Context, values middleware.RequestLoggerValues) error {
|
||||||
|
if values.Error == nil {
|
||||||
|
api.Logger.LogAttrs(context.Background(), slog.LevelInfo, "REQUEST",
|
||||||
|
slog.String("uri", values.URI),
|
||||||
|
slog.Int("status", values.Status),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
api.Logger.LogAttrs(context.Background(), slog.LevelError, "REQUEST_ERROR",
|
||||||
|
slog.String("uri", values.URI),
|
||||||
|
slog.Int("status", values.Status),
|
||||||
|
slog.String("err", values.Error.Error()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,13 +15,14 @@ func (api *API) ClientRoutes() {
|
|||||||
func (api *API) UserRoutes() {
|
func (api *API) UserRoutes() {
|
||||||
users := api.instance.Group("/api/users")
|
users := api.instance.Group("/api/users")
|
||||||
|
|
||||||
|
users.GET("/", api.GetAllUsersHandler)
|
||||||
users.POST("/", api.CreateUserHandler)
|
users.POST("/", api.CreateUserHandler)
|
||||||
users.GET("/", api.GetUserHandler, api.AuthSessionMiddleware)
|
users.GET("/me/", api.GetUserHandler, api.AuthSessionMiddleware)
|
||||||
users.PUT("/", api.UpdateUserHandler, api.AuthSessionMiddleware)
|
users.PUT("/me/", api.UpdateUserHandler, api.AuthSessionMiddleware)
|
||||||
users.PUT("/security/", api.UpdateUserSecurityCredentialsHandler, api.AuthSessionMiddleware)
|
users.PUT("/me/security/", api.UpdateUserSecurityCredentialsHandler, api.AuthSessionMiddleware)
|
||||||
users.PUT("/logo/", api.UpdateUserLogoHandler, middleware.BodyLimit("2M"), api.AuthSessionMiddleware)
|
users.PUT("/me/logo/", api.UpdateUserLogoHandler, middleware.BodyLimit("2M"), api.AuthSessionMiddleware)
|
||||||
users.DELETE("/", api.DeleteUserHandler, api.AuthSessionMiddleware)
|
users.DELETE("/me/", api.DeleteUserHandler, api.AuthSessionMiddleware)
|
||||||
users.DELETE("/logo/", api.DeleteUserLogoHandler, api.AuthSessionMiddleware)
|
users.DELETE("/me/logo/", api.DeleteUserLogoHandler, api.AuthSessionMiddleware)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) AuthRoutes() {
|
func (api *API) AuthRoutes() {
|
||||||
|
|||||||
@@ -180,8 +180,7 @@ func (api *API) UpdateUserLogoHandler(context echo.Context) error {
|
|||||||
file, err := context.FormFile("logo")
|
file, err := context.FormFile("logo")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(fmt.Sprintf("Error updating logo for User: %v.", err))
|
return types.Error{Code: http.StatusBadRequest, Messages: []string{"No image has been uploaded!"}}
|
||||||
return context.String(http.StatusBadRequest, "No image has been uploaded!")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ext := strings.ToLower(filepath.Ext(file.Filename))
|
ext := strings.ToLower(filepath.Ext(file.Filename))
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
"github.com/labstack/echo/v4"
|
|
||||||
|
"github.com/hazemKrimi/crimson-vault/internal/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CustomValidator struct {
|
type CustomValidator struct {
|
||||||
@@ -16,7 +17,7 @@ type CustomValidator struct {
|
|||||||
func (v *CustomValidator) Validate(i any) error {
|
func (v *CustomValidator) Validate(i any) error {
|
||||||
if err := v.validator.Struct(i); err != nil {
|
if err := v.validator.Struct(i); err != nil {
|
||||||
if validationErrors, ok := err.(validator.ValidationErrors); ok {
|
if validationErrors, ok := err.(validator.ValidationErrors); ok {
|
||||||
errors := make(map[string]string)
|
errors := make([]string, 0, 10)
|
||||||
|
|
||||||
for _, ve := range validationErrors {
|
for _, ve := range validationErrors {
|
||||||
field := ve.Field()
|
field := ve.Field()
|
||||||
@@ -41,9 +42,9 @@ func (v *CustomValidator) Validate(i any) error {
|
|||||||
msg = fmt.Sprintf("%s is not valid!", field)
|
msg = fmt.Sprintf("%s is not valid!", field)
|
||||||
}
|
}
|
||||||
|
|
||||||
errors[field] = msg
|
errors = append(errors, msg)
|
||||||
}
|
}
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, errors)
|
return types.Error{Code: http.StatusBadRequest, Messages: errors}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type Error struct {
|
||||||
|
Messages []string
|
||||||
|
Code int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err Error) Error() string {
|
||||||
|
return fmt.Sprintf("%v",
|
||||||
|
err.Messages)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user