From 0325fe101c00b0609673a1bb7f3a954e30e4a3a8 Mon Sep 17 00:00:00 2001 From: Tim Wundenberg Date: Sat, 27 Dec 2025 06:58:04 +0100 Subject: [PATCH] feat: move some service declarations to core --- internal/account/service.go | 5 +-- internal/core/default.go | 44 ------------------- internal/core/error.go | 28 ++++++++++++ internal/core/observabillity.go | 16 +++++++ .../default.go => core/validate_string.go} | 11 ++--- internal/service/transaction.go | 4 +- internal/service/transaction_recurring.go | 8 +++- internal/service/treasure_chest.go | 4 +- 8 files changed, 59 insertions(+), 61 deletions(-) delete mode 100644 internal/core/default.go create mode 100644 internal/core/observabillity.go rename internal/{service/default.go => core/validate_string.go} (73%) diff --git a/internal/account/service.go b/internal/account/service.go index ffa6050..b30a4d9 100644 --- a/internal/account/service.go +++ b/internal/account/service.go @@ -7,7 +7,6 @@ import ( "log/slog" "spend-sparrow/internal/auth_types" "spend-sparrow/internal/core" - "spend-sparrow/internal/service" "github.com/google/uuid" "github.com/jmoiron/sqlx" @@ -45,7 +44,7 @@ func (s ServiceImpl) Add(ctx context.Context, user *auth_types.User, name string return nil, core.ErrInternal } - err = service.ValidateString(name, "name") + err = core.ValidateString(name, "name") if err != nil { return nil, err } @@ -81,7 +80,7 @@ func (s ServiceImpl) UpdateName(ctx context.Context, user *auth_types.User, id s if user == nil { return nil, core.ErrUnauthorized } - err := service.ValidateString(name, "name") + err := core.ValidateString(name, "name") if err != nil { return nil, err } diff --git a/internal/core/default.go b/internal/core/default.go deleted file mode 100644 index 2830102..0000000 --- a/internal/core/default.go +++ /dev/null @@ -1,44 +0,0 @@ -package core - -import ( - "errors" - "net/http" - "spend-sparrow/internal/utils" - "strings" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" -) - -func HandleError(w http.ResponseWriter, r *http.Request, err error) { - switch { - case errors.Is(err, ErrUnauthorized): - utils.TriggerToastWithStatus(r.Context(), w, r, "error", "You are not autorized to perform this operation.", http.StatusUnauthorized) - return - case errors.Is(err, ErrBadRequest): - utils.TriggerToastWithStatus(r.Context(), w, r, "error", extractErrorMessage(err), http.StatusBadRequest) - return - case errors.Is(err, ErrNotFound): - utils.TriggerToastWithStatus(r.Context(), w, r, "error", extractErrorMessage(err), http.StatusNotFound) - return - } - - utils.TriggerToastWithStatus(r.Context(), w, r, "error", "Internal Server Error", http.StatusInternalServerError) -} - -func extractErrorMessage(err error) string { - errMsg := err.Error() - if errMsg == "" { - return "" - } - - return strings.SplitN(errMsg, ":", 2)[0] -} - -func UpdateSpan(r *http.Request) { - currentSpan := trace.SpanFromContext(r.Context()) - if currentSpan != nil { - currentSpan.SetAttributes(attribute.String("http.pattern", r.Pattern)) - currentSpan.SetAttributes(attribute.String("http.pattern.id", r.PathValue("id"))) - } -} diff --git a/internal/core/error.go b/internal/core/error.go index 247b0a8..7ca32aa 100644 --- a/internal/core/error.go +++ b/internal/core/error.go @@ -5,6 +5,9 @@ import ( "database/sql" "errors" "log/slog" + "net/http" + "spend-sparrow/internal/utils" + "strings" ) var ( @@ -41,3 +44,28 @@ func TransformAndLogDbError(ctx context.Context, module string, r sql.Result, er return nil } + +func HandleError(w http.ResponseWriter, r *http.Request, err error) { + switch { + case errors.Is(err, ErrUnauthorized): + utils.TriggerToastWithStatus(r.Context(), w, r, "error", "You are not autorized to perform this operation.", http.StatusUnauthorized) + return + case errors.Is(err, ErrBadRequest): + utils.TriggerToastWithStatus(r.Context(), w, r, "error", extractErrorMessage(err), http.StatusBadRequest) + return + case errors.Is(err, ErrNotFound): + utils.TriggerToastWithStatus(r.Context(), w, r, "error", extractErrorMessage(err), http.StatusNotFound) + return + } + + utils.TriggerToastWithStatus(r.Context(), w, r, "error", "Internal Server Error", http.StatusInternalServerError) +} + +func extractErrorMessage(err error) string { + errMsg := err.Error() + if errMsg == "" { + return "" + } + + return strings.SplitN(errMsg, ":", 2)[0] +} diff --git a/internal/core/observabillity.go b/internal/core/observabillity.go new file mode 100644 index 0000000..f80fd0d --- /dev/null +++ b/internal/core/observabillity.go @@ -0,0 +1,16 @@ +package core + +import ( + "net/http" + + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" +) + +func UpdateSpan(r *http.Request) { + currentSpan := trace.SpanFromContext(r.Context()) + if currentSpan != nil { + currentSpan.SetAttributes(attribute.String("http.pattern", r.Pattern)) + currentSpan.SetAttributes(attribute.String("http.pattern.id", r.PathValue("id"))) + } +} diff --git a/internal/service/default.go b/internal/core/validate_string.go similarity index 73% rename from internal/service/default.go rename to internal/core/validate_string.go index b92dd39..5b01196 100644 --- a/internal/service/default.go +++ b/internal/core/validate_string.go @@ -1,13 +1,8 @@ -package service +package core import ( "fmt" "regexp" - "spend-sparrow/internal/core" -) - -const ( - DECIMALS_MULTIPLIER = 100 ) var ( @@ -17,9 +12,9 @@ var ( func ValidateString(value string, fieldName string) error { switch { case value == "": - return fmt.Errorf("field \"%s\" needs to be set: %w", fieldName, core.ErrBadRequest) + return fmt.Errorf("field \"%s\" needs to be set: %w", fieldName, ErrBadRequest) case !safeInputRegex.MatchString(value): - return fmt.Errorf("use only letters, dashes and spaces for \"%s\": %w", fieldName, core.ErrBadRequest) + return fmt.Errorf("use only letters, dashes and spaces for \"%s\": %w", fieldName, ErrBadRequest) default: return nil } diff --git a/internal/service/transaction.go b/internal/service/transaction.go index 1bb14a9..bffe587 100644 --- a/internal/service/transaction.go +++ b/internal/service/transaction.go @@ -500,13 +500,13 @@ func (s TransactionImpl) validateAndEnrichTransaction(ctx context.Context, tx *s } if input.Party != "" { - err = ValidateString(input.Party, "party") + err = core.ValidateString(input.Party, "party") if err != nil { return nil, err } } if input.Description != "" { - err = ValidateString(input.Description, "description") + err = core.ValidateString(input.Description, "description") if err != nil { return nil, err } diff --git a/internal/service/transaction_recurring.go b/internal/service/transaction_recurring.go index 16dbed4..72769d2 100644 --- a/internal/service/transaction_recurring.go +++ b/internal/service/transaction_recurring.go @@ -16,6 +16,10 @@ import ( "github.com/jmoiron/sqlx" ) +const ( + DECIMALS_MULTIPLIER = 100 +) + type TransactionRecurring interface { Add(ctx context.Context, user *auth_types.User, transactionRecurring types.TransactionRecurringInput) (*types.TransactionRecurring, error) Update(ctx context.Context, user *auth_types.User, transactionRecurring types.TransactionRecurringInput) (*types.TransactionRecurring, error) @@ -472,13 +476,13 @@ func (s TransactionRecurringImpl) validateAndEnrichTransactionRecurring( value := int64(math.Round(valueFloat * DECIMALS_MULTIPLIER)) if input.Party != "" { - err = ValidateString(input.Party, "party") + err = core.ValidateString(input.Party, "party") if err != nil { return nil, err } } if input.Description != "" { - err = ValidateString(input.Description, "description") + err = core.ValidateString(input.Description, "description") if err != nil { return nil, err } diff --git a/internal/service/treasure_chest.go b/internal/service/treasure_chest.go index c9bcc00..5a1e5fa 100644 --- a/internal/service/treasure_chest.go +++ b/internal/service/treasure_chest.go @@ -46,7 +46,7 @@ func (s TreasureChestImpl) Add(ctx context.Context, user *auth_types.User, paren return nil, core.ErrInternal } - err = ValidateString(name, "name") + err = core.ValidateString(name, "name") if err != nil { return nil, err } @@ -93,7 +93,7 @@ func (s TreasureChestImpl) Update(ctx context.Context, user *auth_types.User, id if user == nil { return nil, core.ErrUnauthorized } - err := ValidateString(name, "name") + err := core.ValidateString(name, "name") if err != nil { return nil, err }