diff --git a/internal/handler/account.go b/internal/account/handler.go similarity index 59% rename from internal/handler/account.go rename to internal/account/handler.go index 09ecd88..a00e048 100644 --- a/internal/handler/account.go +++ b/internal/account/handler.go @@ -1,44 +1,36 @@ -package handler +package account import ( - "net/http" - "spend-sparrow/internal/handler/middleware" - "spend-sparrow/internal/service" - t "spend-sparrow/internal/template/account" - "spend-sparrow/internal/types" - "spend-sparrow/internal/utils" - "github.com/a-h/templ" + "net/http" + "spend-sparrow/internal/core" + "spend-sparrow/internal/utils" ) -type Account interface { - Handle(router *http.ServeMux) +type Handler struct { + s Service + r *core.Render } -type AccountImpl struct { - s service.Account - r *Render -} - -func NewAccount(s service.Account, r *Render) Account { - return AccountImpl{ +func NewHandler(s Service, r *core.Render) Handler { + return Handler{ s: s, r: r, } } -func (h AccountImpl) Handle(r *http.ServeMux) { +func (h Handler) Handle(r *http.ServeMux) { r.Handle("GET /account", h.handleAccountPage()) r.Handle("GET /account/{id}", h.handleAccountItemComp()) r.Handle("POST /account/{id}", h.handleUpdateAccount()) r.Handle("DELETE /account/{id}", h.handleDeleteAccount()) } -func (h AccountImpl) handleAccountPage() http.HandlerFunc { +func (h Handler) handleAccountPage() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return @@ -46,20 +38,20 @@ func (h AccountImpl) handleAccountPage() http.HandlerFunc { accounts, err := h.s.GetAll(r.Context(), user) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } - comp := t.Account(accounts) + comp := template(accounts) h.r.RenderLayout(r, w, comp, user) } } -func (h AccountImpl) handleAccountItemComp() http.HandlerFunc { +func (h Handler) handleAccountItemComp() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return @@ -67,39 +59,39 @@ func (h AccountImpl) handleAccountItemComp() http.HandlerFunc { id := r.PathValue("id") if id == "new" { - comp := t.EditAccount(nil) + comp := editAccount(nil) h.r.Render(r, w, comp) return } account, err := h.s.Get(r.Context(), user, id) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } var comp templ.Component if r.URL.Query().Get("edit") == "true" { - comp = t.EditAccount(account) + comp = editAccount(account) } else { - comp = t.AccountItem(account) + comp = accountItem(account) } h.r.Render(r, w, comp) } } -func (h AccountImpl) handleUpdateAccount() http.HandlerFunc { +func (h Handler) handleUpdateAccount() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return } var ( - account *types.Account + account *Account err error ) id := r.PathValue("id") @@ -107,27 +99,27 @@ func (h AccountImpl) handleUpdateAccount() http.HandlerFunc { if id == "new" { account, err = h.s.Add(r.Context(), user, name) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } } else { account, err = h.s.UpdateName(r.Context(), user, id, name) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } } - comp := t.AccountItem(account) + comp := accountItem(account) h.r.Render(r, w, comp) } } -func (h AccountImpl) handleDeleteAccount() http.HandlerFunc { +func (h Handler) handleDeleteAccount() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return @@ -137,7 +129,7 @@ func (h AccountImpl) handleDeleteAccount() http.HandlerFunc { err := h.s.Delete(r.Context(), user, id) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } } diff --git a/internal/service/account.go b/internal/account/service.go similarity index 70% rename from internal/service/account.go rename to internal/account/service.go index e89ca96..30feb26 100644 --- a/internal/service/account.go +++ b/internal/account/service.go @@ -1,42 +1,42 @@ -package service +package account import ( "context" "errors" "fmt" - "log/slog" - "spend-sparrow/internal/db" - "spend-sparrow/internal/types" - "github.com/google/uuid" "github.com/jmoiron/sqlx" + "log/slog" + "spend-sparrow/internal/db" + "spend-sparrow/internal/service" + "spend-sparrow/internal/types" ) -type Account interface { - Add(ctx context.Context, user *types.User, name string) (*types.Account, error) - UpdateName(ctx context.Context, user *types.User, id string, name string) (*types.Account, error) - Get(ctx context.Context, user *types.User, id string) (*types.Account, error) - GetAll(ctx context.Context, user *types.User) ([]*types.Account, error) +type Service interface { + Add(ctx context.Context, user *types.User, name string) (*Account, error) + UpdateName(ctx context.Context, user *types.User, id string, name string) (*Account, error) + Get(ctx context.Context, user *types.User, id string) (*Account, error) + GetAll(ctx context.Context, user *types.User) ([]*Account, error) Delete(ctx context.Context, user *types.User, id string) error } -type AccountImpl struct { +type ServiceImpl struct { db *sqlx.DB - clock Clock - random Random + clock service.Clock + random service.Random } -func NewAccount(db *sqlx.DB, random Random, clock Clock) Account { - return AccountImpl{ +func NewServiceImpl(db *sqlx.DB, random service.Random, clock service.Clock) Service { + return ServiceImpl{ db: db, clock: clock, random: random, } } -func (s AccountImpl) Add(ctx context.Context, user *types.User, name string) (*types.Account, error) { +func (s ServiceImpl) Add(ctx context.Context, user *types.User, name string) (*Account, error) { if user == nil { - return nil, ErrUnauthorized + return nil, types.ErrUnauthorized } newId, err := s.random.UUID(ctx) @@ -44,12 +44,12 @@ func (s AccountImpl) Add(ctx context.Context, user *types.User, name string) (*t return nil, types.ErrInternal } - err = validateString(name, "name") + err = service.ValidateString(name, "name") if err != nil { return nil, err } - account := &types.Account{ + account := &Account{ Id: newId, UserId: user.Id, @@ -76,18 +76,18 @@ func (s AccountImpl) Add(ctx context.Context, user *types.User, name string) (*t return account, nil } -func (s AccountImpl) UpdateName(ctx context.Context, user *types.User, id string, name string) (*types.Account, error) { +func (s ServiceImpl) UpdateName(ctx context.Context, user *types.User, id string, name string) (*Account, error) { if user == nil { - return nil, ErrUnauthorized + return nil, types.ErrUnauthorized } - err := validateString(name, "name") + err := service.ValidateString(name, "name") if err != nil { return nil, err } uuid, err := uuid.Parse(id) if err != nil { slog.ErrorContext(ctx, "account update", "err", err) - return nil, fmt.Errorf("could not parse Id: %w", ErrBadRequest) + return nil, fmt.Errorf("could not parse Id: %w", service.ErrBadRequest) } tx, err := s.db.BeginTxx(ctx, nil) @@ -99,12 +99,12 @@ func (s AccountImpl) UpdateName(ctx context.Context, user *types.User, id string _ = tx.Rollback() }() - var account types.Account + var account Account err = tx.GetContext(ctx, &account, `SELECT * FROM account WHERE user_id = ? AND id = ?`, user.Id, uuid) err = db.TransformAndLogDbError(ctx, "account Update", nil, err) if err != nil { if errors.Is(err, db.ErrNotFound) { - return nil, fmt.Errorf("account %v not found: %w", id, ErrBadRequest) + return nil, fmt.Errorf("account %v not found: %w", id, service.ErrBadRequest) } return nil, types.ErrInternal } @@ -136,17 +136,17 @@ func (s AccountImpl) UpdateName(ctx context.Context, user *types.User, id string return &account, nil } -func (s AccountImpl) Get(ctx context.Context, user *types.User, id string) (*types.Account, error) { +func (s ServiceImpl) Get(ctx context.Context, user *types.User, id string) (*Account, error) { if user == nil { - return nil, ErrUnauthorized + return nil, service.ErrUnauthorized } uuid, err := uuid.Parse(id) if err != nil { slog.ErrorContext(ctx, "account get", "err", err) - return nil, fmt.Errorf("could not parse Id: %w", ErrBadRequest) + return nil, fmt.Errorf("could not parse Id: %w", service.ErrBadRequest) } - var account types.Account + var account Account err = s.db.GetContext(ctx, &account, ` SELECT * FROM account WHERE user_id = ? AND id = ?`, user.Id, uuid) err = db.TransformAndLogDbError(ctx, "account Get", nil, err) @@ -158,12 +158,12 @@ func (s AccountImpl) Get(ctx context.Context, user *types.User, id string) (*typ return &account, nil } -func (s AccountImpl) GetAll(ctx context.Context, user *types.User) ([]*types.Account, error) { +func (s ServiceImpl) GetAll(ctx context.Context, user *types.User) ([]*Account, error) { if user == nil { - return nil, ErrUnauthorized + return nil, service.ErrUnauthorized } - accounts := make([]*types.Account, 0) + accounts := make([]*Account, 0) err := s.db.SelectContext(ctx, &accounts, ` SELECT * FROM account WHERE user_id = ? ORDER BY name`, user.Id) err = db.TransformAndLogDbError(ctx, "account GetAll", nil, err) @@ -174,14 +174,14 @@ func (s AccountImpl) GetAll(ctx context.Context, user *types.User) ([]*types.Acc return accounts, nil } -func (s AccountImpl) Delete(ctx context.Context, user *types.User, id string) error { +func (s ServiceImpl) Delete(ctx context.Context, user *types.User, id string) error { if user == nil { - return ErrUnauthorized + return service.ErrUnauthorized } uuid, err := uuid.Parse(id) if err != nil { slog.ErrorContext(ctx, "account delete", "err", err) - return fmt.Errorf("could not parse Id: %w", ErrBadRequest) + return fmt.Errorf("could not parse Id: %w", service.ErrBadRequest) } tx, err := s.db.BeginTxx(ctx, nil) @@ -200,7 +200,7 @@ func (s AccountImpl) Delete(ctx context.Context, user *types.User, id string) er return err } if transactionsCount > 0 { - return fmt.Errorf("account has transactions, cannot delete: %w", ErrBadRequest) + return fmt.Errorf("account has transactions, cannot delete: %w", service.ErrBadRequest) } res, err := tx.ExecContext(ctx, "DELETE FROM account WHERE id = ? and user_id = ?", uuid, user.Id) diff --git a/internal/template/account/account.templ b/internal/account/template.templ similarity index 86% rename from internal/template/account/account.templ rename to internal/account/template.templ index cfdb2fa..b9267d1 100644 --- a/internal/template/account/account.templ +++ b/internal/account/template.templ @@ -3,7 +3,7 @@ package account import "spend-sparrow/internal/template/svg" import "spend-sparrow/internal/types" -templ Account(accounts []*types.Account) { +templ template(accounts []*Account) {
} -templ EditAccount(account *types.Account) { +templ editAccount(account *Account) { {{ - var ( - name string - id string - cancelUrl string - ) - if account == nil { - name = "" - id = "new" - cancelUrl = "/empty" - } else { - name = account.Name - id = account.Id.String() - cancelUrl = "/account/" + id - } + var ( + name string + id string + cancelUrl string + ) + if account == nil { + name = "" + id = "new" + cancelUrl = "/empty" + } else { + name = account.Name + id = account.Id.String() + cancelUrl = "/account/" + id + } }}
} -templ AccountItem(account *types.Account) { +templ accountItem(account *Account) {

{ account.Name }

diff --git a/internal/types/account.go b/internal/account/type.go similarity index 97% rename from internal/types/account.go rename to internal/account/type.go index 75d949d..d5b3cff 100644 --- a/internal/types/account.go +++ b/internal/account/type.go @@ -1,9 +1,8 @@ -package types +package account import ( - "time" - "github.com/google/uuid" + "time" ) // The Account holds money. diff --git a/internal/core/auth.go b/internal/core/auth.go new file mode 100644 index 0000000..f51574d --- /dev/null +++ b/internal/core/auth.go @@ -0,0 +1,39 @@ +package core + +import ( + "net/http" + "spend-sparrow/internal/types" +) + +type ContextKey string + +var SessionKey ContextKey = "session" +var UserKey ContextKey = "user" + +func GetUser(r *http.Request) *types.User { + obj := r.Context().Value(UserKey) + if obj == nil { + return nil + } + + user, ok := obj.(*types.User) + if !ok { + return nil + } + + return user +} + +func GetSession(r *http.Request) *types.Session { + obj := r.Context().Value(SessionKey) + if obj == nil { + return nil + } + + session, ok := obj.(*types.Session) + if !ok { + return nil + } + + return session +} diff --git a/internal/handler/default.go b/internal/core/default.go similarity index 91% rename from internal/handler/default.go rename to internal/core/default.go index c1b5f8b..5b8a1ab 100644 --- a/internal/handler/default.go +++ b/internal/core/default.go @@ -1,4 +1,4 @@ -package handler +package core import ( "errors" @@ -12,7 +12,7 @@ import ( "go.opentelemetry.io/otel/trace" ) -func handleError(w http.ResponseWriter, r *http.Request, err error) { +func HandleError(w http.ResponseWriter, r *http.Request, err error) { switch { case errors.Is(err, service.ErrUnauthorized): utils.TriggerToastWithStatus(r.Context(), w, r, "error", "You are not autorized to perform this operation.", http.StatusUnauthorized) @@ -37,7 +37,7 @@ func extractErrorMessage(err error) string { return strings.SplitN(errMsg, ":", 2)[0] } -func updateSpan(r *http.Request) { +func UpdateSpan(r *http.Request) { currentSpan := trace.SpanFromContext(r.Context()) if currentSpan != nil { currentSpan.SetAttributes(attribute.String("http.pattern", r.Pattern)) diff --git a/internal/template/layout.templ b/internal/core/layout.templ similarity index 99% rename from internal/template/layout.templ rename to internal/core/layout.templ index 499e380..a0f53c5 100644 --- a/internal/template/layout.templ +++ b/internal/core/layout.templ @@ -1,4 +1,4 @@ -package template +package core import "spend-sparrow/internal/template/svg" diff --git a/internal/handler/render.go b/internal/core/render.go similarity index 84% rename from internal/handler/render.go rename to internal/core/render.go index 4e78403..a380a49 100644 --- a/internal/handler/render.go +++ b/internal/core/render.go @@ -1,13 +1,10 @@ -package handler +package core import ( + "github.com/a-h/templ" "log/slog" "net/http" - "spend-sparrow/internal/template" - "spend-sparrow/internal/template/auth" "spend-sparrow/internal/types" - - "github.com/a-h/templ" ) type Render struct { @@ -37,15 +34,15 @@ func (render *Render) RenderLayout(r *http.Request, w http.ResponseWriter, slot func (render *Render) RenderLayoutWithStatus(r *http.Request, w http.ResponseWriter, slot templ.Component, user *types.User, status int) { userComp := render.getUserComp(user) - layout := template.Layout(slot, userComp, user != nil, r.URL.Path) + layout := Layout(slot, userComp, user != nil, r.URL.Path) render.RenderWithStatus(r, w, layout, status) } func (render *Render) getUserComp(user *types.User) templ.Component { if user != nil { - return auth.UserComp(user.Email) + return UserComp(user.Email) } else { - return auth.UserComp("") + return UserComp("") } } diff --git a/internal/template/auth/user.templ b/internal/core/user.templ similarity index 99% rename from internal/template/auth/user.templ rename to internal/core/user.templ index 364dda7..38e3f3c 100644 --- a/internal/template/auth/user.templ +++ b/internal/core/user.templ @@ -1,4 +1,4 @@ -package auth +package core templ UserComp(user string) {
diff --git a/internal/default.go b/internal/default.go index 6134e82..277c75d 100644 --- a/internal/default.go +++ b/internal/default.go @@ -1,19 +1,20 @@ package internal import ( + "context" "errors" "fmt" "log/slog" + "net/http" + "os/signal" + "spend-sparrow/internal/account" + "spend-sparrow/internal/core" "spend-sparrow/internal/db" "spend-sparrow/internal/handler" "spend-sparrow/internal/handler/middleware" "spend-sparrow/internal/log" "spend-sparrow/internal/service" "spend-sparrow/internal/types" - - "context" - "net/http" - "os/signal" "sync" "syscall" "time" @@ -113,17 +114,17 @@ func createHandlerWithServices(ctx context.Context, d *sqlx.DB, serverSettings * mailService := service.NewMail(serverSettings) authService := service.NewAuth(authDb, randomService, clockService, mailService, serverSettings) - accountService := service.NewAccount(d, randomService, clockService) + accountService := account.NewServiceImpl(d, randomService, clockService) treasureChestService := service.NewTreasureChest(d, randomService, clockService) transactionService := service.NewTransaction(d, randomService, clockService) transactionRecurringService := service.NewTransactionRecurring(d, randomService, clockService, transactionService) dashboardService := service.NewDashboard(d) - render := handler.NewRender() + render := core.NewRender() indexHandler := handler.NewIndex(render, clockService) dashboardHandler := handler.NewDashboard(render, dashboardService, treasureChestService) authHandler := handler.NewAuth(authService, render) - accountHandler := handler.NewAccount(accountService, render) + accountHandler := account.NewHandler(accountService, render) treasureChestHandler := handler.NewTreasureChest(treasureChestService, transactionRecurringService, render) transactionHandler := handler.NewTransaction(transactionService, accountService, treasureChestService, render) transactionRecurringHandler := handler.NewTransactionRecurring(transactionRecurringService, render) diff --git a/internal/handler/auth.go b/internal/handler/auth.go index 95558f9..7370b98 100644 --- a/internal/handler/auth.go +++ b/internal/handler/auth.go @@ -5,6 +5,7 @@ import ( "log/slog" "net/http" "net/url" + "spend-sparrow/internal/core" "spend-sparrow/internal/handler/middleware" "spend-sparrow/internal/service" "spend-sparrow/internal/template/auth" @@ -19,10 +20,10 @@ type Auth interface { type AuthImpl struct { service service.Auth - render *Render + render *core.Render } -func NewAuth(service service.Auth, render *Render) Auth { +func NewAuth(service service.Auth, render *core.Render) Auth { return AuthImpl{ service: service, render: render, @@ -58,9 +59,9 @@ var ( func (handler AuthImpl) handleSignInPage() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) if user != nil { if !user.EmailVerified { utils.DoRedirect(w, r, "/auth/verify") @@ -78,10 +79,10 @@ func (handler AuthImpl) handleSignInPage() http.HandlerFunc { func (handler AuthImpl) handleSignIn() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) user, err := utils.WaitMinimumTime(securityWaitDuration, func() (*types.User, error) { - session := middleware.GetSession(r) + session := core.GetSession(r) email := r.FormValue("email") password := r.FormValue("password") @@ -115,9 +116,9 @@ func (handler AuthImpl) handleSignIn() http.HandlerFunc { func (handler AuthImpl) handleSignUpPage() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) if user != nil { if !user.EmailVerified { @@ -135,9 +136,9 @@ func (handler AuthImpl) handleSignUpPage() http.HandlerFunc { func (handler AuthImpl) handleSignUpVerifyPage() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return @@ -155,9 +156,9 @@ func (handler AuthImpl) handleSignUpVerifyPage() http.HandlerFunc { func (handler AuthImpl) handleVerifyResendComp() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return @@ -174,7 +175,7 @@ func (handler AuthImpl) handleVerifyResendComp() http.HandlerFunc { func (handler AuthImpl) handleSignUpVerifyResponsePage() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) token := r.URL.Query().Get("token") @@ -196,7 +197,7 @@ func (handler AuthImpl) handleSignUpVerifyResponsePage() http.HandlerFunc { func (handler AuthImpl) handleSignUp() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) var email = r.FormValue("email") var password = r.FormValue("password") @@ -234,9 +235,9 @@ func (handler AuthImpl) handleSignUp() http.HandlerFunc { func (handler AuthImpl) handleSignOut() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - session := middleware.GetSession(r) + session := core.GetSession(r) if session != nil { err := handler.service.SignOut(r.Context(), session.Id) @@ -263,9 +264,9 @@ func (handler AuthImpl) handleSignOut() http.HandlerFunc { func (handler AuthImpl) handleDeleteAccountPage() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return @@ -278,9 +279,9 @@ func (handler AuthImpl) handleDeleteAccountPage() http.HandlerFunc { func (handler AuthImpl) handleDeleteAccountComp() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return @@ -304,11 +305,11 @@ func (handler AuthImpl) handleDeleteAccountComp() http.HandlerFunc { func (handler AuthImpl) handleChangePasswordPage() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) isPasswordReset := r.URL.Query().Has("token") - user := middleware.GetUser(r) + user := core.GetUser(r) if user == nil && !isPasswordReset { utils.DoRedirect(w, r, "/auth/signin") @@ -322,10 +323,10 @@ func (handler AuthImpl) handleChangePasswordPage() http.HandlerFunc { func (handler AuthImpl) handleChangePasswordComp() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - session := middleware.GetSession(r) - user := middleware.GetUser(r) + session := core.GetSession(r) + user := core.GetUser(r) if session == nil || user == nil { utils.TriggerToastWithStatus(r.Context(), w, r, "error", "Unathorized", http.StatusUnauthorized) return @@ -346,9 +347,9 @@ func (handler AuthImpl) handleChangePasswordComp() http.HandlerFunc { func (handler AuthImpl) handleForgotPasswordPage() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) if user != nil { utils.DoRedirect(w, r, "/") return @@ -361,7 +362,7 @@ func (handler AuthImpl) handleForgotPasswordPage() http.HandlerFunc { func (handler AuthImpl) handleForgotPasswordComp() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) email := r.FormValue("email") if email == "" { @@ -384,7 +385,7 @@ func (handler AuthImpl) handleForgotPasswordComp() http.HandlerFunc { func (handler AuthImpl) handleForgotPasswordResponseComp() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) pageUrl, err := url.Parse(r.Header.Get("Hx-Current-Url")) if err != nil { diff --git a/internal/handler/dashboard.go b/internal/handler/dashboard.go index f38cdd8..8bc4525 100644 --- a/internal/handler/dashboard.go +++ b/internal/handler/dashboard.go @@ -4,7 +4,7 @@ import ( "fmt" "log/slog" "net/http" - "spend-sparrow/internal/handler/middleware" + "spend-sparrow/internal/core" "spend-sparrow/internal/service" "spend-sparrow/internal/template/dashboard" "spend-sparrow/internal/utils" @@ -19,12 +19,12 @@ type Dashboard interface { } type DashboardImpl struct { - r *Render + r *core.Render d *service.Dashboard treasureChest service.TreasureChest } -func NewDashboard(r *Render, d *service.Dashboard, treasureChest service.TreasureChest) Dashboard { +func NewDashboard(r *core.Render, d *service.Dashboard, treasureChest service.TreasureChest) Dashboard { return DashboardImpl{ r: r, d: d, @@ -41,9 +41,9 @@ func (handler DashboardImpl) Handle(router *http.ServeMux) { func (handler DashboardImpl) handleDashboard() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return @@ -51,7 +51,7 @@ func (handler DashboardImpl) handleDashboard() http.HandlerFunc { treasureChests, err := handler.treasureChest.GetAll(r.Context(), user) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } @@ -62,13 +62,13 @@ func (handler DashboardImpl) handleDashboard() http.HandlerFunc { func (handler DashboardImpl) handleDashboardMainChart() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) series, err := handler.d.MainChart(r.Context(), user) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } @@ -128,13 +128,13 @@ func (handler DashboardImpl) handleDashboardMainChart() http.HandlerFunc { func (handler DashboardImpl) handleDashboardTreasureChests() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) treeList, err := handler.d.TreasureChests(r.Context(), user) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } @@ -183,9 +183,9 @@ func (handler DashboardImpl) handleDashboardTreasureChests() http.HandlerFunc { func (handler DashboardImpl) handleDashboardTreasureChest() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) var treasureChestId *uuid.UUID @@ -193,7 +193,7 @@ func (handler DashboardImpl) handleDashboardTreasureChest() http.HandlerFunc { if treasureChestStr != "" { id, err := uuid.Parse(treasureChestStr) if err != nil { - handleError(w, r, fmt.Errorf("could not parse treasure chest: %w", service.ErrBadRequest)) + core.HandleError(w, r, fmt.Errorf("could not parse treasure chest: %w", service.ErrBadRequest)) return } @@ -202,7 +202,7 @@ func (handler DashboardImpl) handleDashboardTreasureChest() http.HandlerFunc { series, err := handler.d.TreasureChest(r.Context(), user, treasureChestId) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } diff --git a/internal/handler/middleware/authenticate.go b/internal/handler/middleware/authenticate.go index 226d840..d20a0b7 100644 --- a/internal/handler/middleware/authenticate.go +++ b/internal/handler/middleware/authenticate.go @@ -3,17 +3,11 @@ package middleware import ( "context" "net/http" - "strings" - + "spend-sparrow/internal/core" "spend-sparrow/internal/service" - "spend-sparrow/internal/types" + "strings" ) -type ContextKey string - -var SessionKey ContextKey = "session" -var UserKey ContextKey = "user" - func Authenticate(service service.Auth) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -41,42 +35,14 @@ func Authenticate(service service.Auth) func(http.Handler) http.Handler { http.SetCookie(w, &cookie) } - ctx = context.WithValue(ctx, UserKey, user) - ctx = context.WithValue(ctx, SessionKey, session) + ctx = context.WithValue(ctx, core.UserKey, user) + ctx = context.WithValue(ctx, core.SessionKey, session) next.ServeHTTP(w, r.WithContext(ctx)) }) } } -func GetUser(r *http.Request) *types.User { - obj := r.Context().Value(UserKey) - if obj == nil { - return nil - } - - user, ok := obj.(*types.User) - if !ok { - return nil - } - - return user -} - -func GetSession(r *http.Request) *types.Session { - obj := r.Context().Value(SessionKey) - if obj == nil { - return nil - } - - session, ok := obj.(*types.Session) - if !ok { - return nil - } - - return session -} - func getSessionID(r *http.Request) string { cookie, err := r.Cookie("id") if err != nil { diff --git a/internal/handler/middleware/cross_site_request_forgery.go b/internal/handler/middleware/cross_site_request_forgery.go index 2e70ddc..4601b56 100644 --- a/internal/handler/middleware/cross_site_request_forgery.go +++ b/internal/handler/middleware/cross_site_request_forgery.go @@ -3,6 +3,7 @@ package middleware import ( "log/slog" "net/http" + "spend-sparrow/internal/core" "spend-sparrow/internal/service" "spend-sparrow/internal/utils" "strings" @@ -40,7 +41,7 @@ func CrossSiteRequestForgery(auth service.Auth) func(http.Handler) http.Handler return } - session := GetSession(r) + session := core.GetSession(r) if r.Method == http.MethodPost || r.Method == http.MethodPut || diff --git a/internal/handler/root_and_404.go b/internal/handler/root_and_404.go index 291ee0f..19ad051 100644 --- a/internal/handler/root_and_404.go +++ b/internal/handler/root_and_404.go @@ -2,7 +2,7 @@ package handler import ( "net/http" - "spend-sparrow/internal/handler/middleware" + "spend-sparrow/internal/core" "spend-sparrow/internal/service" "spend-sparrow/internal/template" "spend-sparrow/internal/utils" @@ -15,11 +15,11 @@ type Index interface { } type IndexImpl struct { - r *Render + r *core.Render c service.Clock } -func NewIndex(r *Render, c service.Clock) Index { +func NewIndex(r *core.Render, c service.Clock) Index { return IndexImpl{ r: r, c: c, @@ -33,9 +33,9 @@ func (handler IndexImpl) Handle(router *http.ServeMux) { func (handler IndexImpl) handleRootAnd404() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) htmx := utils.IsHtmx(r) @@ -65,7 +65,7 @@ func (handler IndexImpl) handleRootAnd404() http.HandlerFunc { func (handler IndexImpl) handleEmpty() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) // Return nothing } diff --git a/internal/handler/transaction.go b/internal/handler/transaction.go index 45f3d54..bae53ca 100644 --- a/internal/handler/transaction.go +++ b/internal/handler/transaction.go @@ -4,7 +4,8 @@ import ( "fmt" "math" "net/http" - "spend-sparrow/internal/handler/middleware" + "spend-sparrow/internal/account" + "spend-sparrow/internal/core" "spend-sparrow/internal/service" t "spend-sparrow/internal/template/transaction" "spend-sparrow/internal/types" @@ -22,12 +23,12 @@ type Transaction interface { type TransactionImpl struct { s service.Transaction - account service.Account + account account.Service treasureChest service.TreasureChest - r *Render + r *core.Render } -func NewTransaction(s service.Transaction, account service.Account, treasureChest service.TreasureChest, r *Render) Transaction { +func NewTransaction(s service.Transaction, account account.Service, treasureChest service.TreasureChest, r *core.Render) Transaction { return TransactionImpl{ s: s, account: account, @@ -46,9 +47,9 @@ func (h TransactionImpl) Handle(r *http.ServeMux) { func (h TransactionImpl) handleTransactionPage() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return @@ -63,19 +64,19 @@ func (h TransactionImpl) handleTransactionPage() http.HandlerFunc { transactions, err := h.s.GetAll(r.Context(), user, filter) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } accounts, err := h.account.GetAll(r.Context(), user) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } treasureChests, err := h.treasureChest.GetAll(r.Context(), user) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } @@ -93,9 +94,9 @@ func (h TransactionImpl) handleTransactionPage() http.HandlerFunc { func (h TransactionImpl) handleTransactionItemComp() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return @@ -103,13 +104,13 @@ func (h TransactionImpl) handleTransactionItemComp() http.HandlerFunc { accounts, err := h.account.GetAll(r.Context(), user) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } treasureChests, err := h.treasureChest.GetAll(r.Context(), user) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } @@ -122,7 +123,7 @@ func (h TransactionImpl) handleTransactionItemComp() http.HandlerFunc { transaction, err := h.s.Get(r.Context(), user, id) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } @@ -139,9 +140,9 @@ func (h TransactionImpl) handleTransactionItemComp() http.HandlerFunc { func (h TransactionImpl) handleUpdateTransaction() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return @@ -156,7 +157,7 @@ func (h TransactionImpl) handleUpdateTransaction() http.HandlerFunc { if idStr != "new" { id, err = uuid.Parse(idStr) if err != nil { - handleError(w, r, fmt.Errorf("could not parse Id: %w", service.ErrBadRequest)) + core.HandleError(w, r, fmt.Errorf("could not parse Id: %w", service.ErrBadRequest)) return } } @@ -166,7 +167,7 @@ func (h TransactionImpl) handleUpdateTransaction() http.HandlerFunc { if accountIdStr != "" { i, err := uuid.Parse(accountIdStr) if err != nil { - handleError(w, r, fmt.Errorf("could not parse account id: %w", service.ErrBadRequest)) + core.HandleError(w, r, fmt.Errorf("could not parse account id: %w", service.ErrBadRequest)) return } accountId = &i @@ -177,7 +178,7 @@ func (h TransactionImpl) handleUpdateTransaction() http.HandlerFunc { if treasureChestIdStr != "" { i, err := uuid.Parse(treasureChestIdStr) if err != nil { - handleError(w, r, fmt.Errorf("could not parse treasure chest id: %w", service.ErrBadRequest)) + core.HandleError(w, r, fmt.Errorf("could not parse treasure chest id: %w", service.ErrBadRequest)) return } treasureChestId = &i @@ -185,14 +186,14 @@ func (h TransactionImpl) handleUpdateTransaction() http.HandlerFunc { valueF, err := strconv.ParseFloat(r.FormValue("value"), 64) if err != nil { - handleError(w, r, fmt.Errorf("could not parse value: %w", service.ErrBadRequest)) + core.HandleError(w, r, fmt.Errorf("could not parse value: %w", service.ErrBadRequest)) return } value := int64(math.Round(valueF * service.DECIMALS_MULTIPLIER)) timestamp, err := time.Parse("2006-01-02", r.FormValue("timestamp")) if err != nil { - handleError(w, r, fmt.Errorf("could not parse timestamp: %w", service.ErrBadRequest)) + core.HandleError(w, r, fmt.Errorf("could not parse timestamp: %w", service.ErrBadRequest)) return } @@ -210,26 +211,26 @@ func (h TransactionImpl) handleUpdateTransaction() http.HandlerFunc { if idStr == "new" { transaction, err = h.s.Add(r.Context(), nil, user, input) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } } else { transaction, err = h.s.Update(r.Context(), user, input) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } } accounts, err := h.account.GetAll(r.Context(), user) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } treasureChests, err := h.treasureChest.GetAll(r.Context(), user) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } @@ -241,9 +242,9 @@ func (h TransactionImpl) handleUpdateTransaction() http.HandlerFunc { func (h TransactionImpl) handleRecalculate() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return @@ -251,7 +252,7 @@ func (h TransactionImpl) handleRecalculate() http.HandlerFunc { err := h.s.RecalculateBalances(r.Context(), user) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } @@ -261,9 +262,9 @@ func (h TransactionImpl) handleRecalculate() http.HandlerFunc { func (h TransactionImpl) handleDeleteTransaction() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return @@ -273,13 +274,13 @@ func (h TransactionImpl) handleDeleteTransaction() http.HandlerFunc { err := h.s.Delete(r.Context(), user, id) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } } } -func (h TransactionImpl) getTransactionData(accounts []*types.Account, treasureChests []*types.TreasureChest) (map[uuid.UUID]string, map[uuid.UUID]string) { +func (h TransactionImpl) getTransactionData(accounts []*account.Account, treasureChests []*types.TreasureChest) (map[uuid.UUID]string, map[uuid.UUID]string) { accountMap := make(map[uuid.UUID]string, 0) for _, account := range accounts { accountMap[account.Id] = account.Name diff --git a/internal/handler/transaction_recurring.go b/internal/handler/transaction_recurring.go index 5d1582f..33f8a39 100644 --- a/internal/handler/transaction_recurring.go +++ b/internal/handler/transaction_recurring.go @@ -2,7 +2,7 @@ package handler import ( "net/http" - "spend-sparrow/internal/handler/middleware" + "spend-sparrow/internal/core" "spend-sparrow/internal/service" t "spend-sparrow/internal/template/transaction_recurring" "spend-sparrow/internal/types" @@ -15,10 +15,10 @@ type TransactionRecurring interface { type TransactionRecurringImpl struct { s service.TransactionRecurring - r *Render + r *core.Render } -func NewTransactionRecurring(s service.TransactionRecurring, r *Render) TransactionRecurring { +func NewTransactionRecurring(s service.TransactionRecurring, r *core.Render) TransactionRecurring { return TransactionRecurringImpl{ s: s, r: r, @@ -33,9 +33,9 @@ func (h TransactionRecurringImpl) Handle(r *http.ServeMux) { func (h TransactionRecurringImpl) handleTransactionRecurringItemComp() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return @@ -50,9 +50,9 @@ func (h TransactionRecurringImpl) handleTransactionRecurringItemComp() http.Hand func (h TransactionRecurringImpl) handleUpdateTransactionRecurring() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return @@ -72,13 +72,13 @@ func (h TransactionRecurringImpl) handleUpdateTransactionRecurring() http.Handle if input.Id == "new" { _, err := h.s.Add(r.Context(), user, input) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } } else { _, err := h.s.Update(r.Context(), user, input) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } } @@ -89,9 +89,9 @@ func (h TransactionRecurringImpl) handleUpdateTransactionRecurring() http.Handle func (h TransactionRecurringImpl) handleDeleteTransactionRecurring() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return @@ -103,7 +103,7 @@ func (h TransactionRecurringImpl) handleDeleteTransactionRecurring() http.Handle err := h.s.Delete(r.Context(), user, id) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } @@ -120,13 +120,13 @@ func (h TransactionRecurringImpl) renderItems(w http.ResponseWriter, r *http.Req if accountId != "" { transactionsRecurring, err = h.s.GetAllByAccount(r.Context(), user, accountId) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } } else { transactionsRecurring, err = h.s.GetAllByTreasureChest(r.Context(), user, treasureChestId) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } } diff --git a/internal/handler/treasure_chest.go b/internal/handler/treasure_chest.go index a044610..9cff221 100644 --- a/internal/handler/treasure_chest.go +++ b/internal/handler/treasure_chest.go @@ -2,7 +2,7 @@ package handler import ( "net/http" - "spend-sparrow/internal/handler/middleware" + "spend-sparrow/internal/core" "spend-sparrow/internal/service" tr "spend-sparrow/internal/template/transaction_recurring" t "spend-sparrow/internal/template/treasurechest" @@ -20,10 +20,10 @@ type TreasureChest interface { type TreasureChestImpl struct { s service.TreasureChest transactionRecurring service.TransactionRecurring - r *Render + r *core.Render } -func NewTreasureChest(s service.TreasureChest, transactionRecurring service.TransactionRecurring, r *Render) TreasureChest { +func NewTreasureChest(s service.TreasureChest, transactionRecurring service.TransactionRecurring, r *core.Render) TreasureChest { return TreasureChestImpl{ s: s, transactionRecurring: transactionRecurring, @@ -40,9 +40,9 @@ func (h TreasureChestImpl) Handle(r *http.ServeMux) { func (h TreasureChestImpl) handleTreasureChestPage() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return @@ -50,13 +50,13 @@ func (h TreasureChestImpl) handleTreasureChestPage() http.HandlerFunc { treasureChests, err := h.s.GetAll(r.Context(), user) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } transactionsRecurring, err := h.transactionRecurring.GetAll(r.Context(), user) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } @@ -69,9 +69,9 @@ func (h TreasureChestImpl) handleTreasureChestPage() http.HandlerFunc { func (h TreasureChestImpl) handleTreasureChestItemComp() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return @@ -79,7 +79,7 @@ func (h TreasureChestImpl) handleTreasureChestItemComp() http.HandlerFunc { treasureChests, err := h.s.GetAll(r.Context(), user) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } @@ -92,13 +92,13 @@ func (h TreasureChestImpl) handleTreasureChestItemComp() http.HandlerFunc { treasureChest, err := h.s.Get(r.Context(), user, id) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } transactionsRecurring, err := h.transactionRecurring.GetAllByTreasureChest(r.Context(), user, treasureChest.Id.String()) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } transactionsRec := tr.TransactionRecurringItems(transactionsRecurring, "", "", treasureChest.Id.String()) @@ -116,9 +116,9 @@ func (h TreasureChestImpl) handleTreasureChestItemComp() http.HandlerFunc { func (h TreasureChestImpl) handleUpdateTreasureChest() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return @@ -134,20 +134,20 @@ func (h TreasureChestImpl) handleUpdateTreasureChest() http.HandlerFunc { if id == "new" { treasureChest, err = h.s.Add(r.Context(), user, parentId, name) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } } else { treasureChest, err = h.s.Update(r.Context(), user, id, parentId, name) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } } transactionsRecurring, err := h.transactionRecurring.GetAllByTreasureChest(r.Context(), user, treasureChest.Id.String()) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } @@ -161,9 +161,9 @@ func (h TreasureChestImpl) handleUpdateTreasureChest() http.HandlerFunc { func (h TreasureChestImpl) handleDeleteTreasureChest() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - updateSpan(r) + core.UpdateSpan(r) - user := middleware.GetUser(r) + user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return @@ -173,7 +173,7 @@ func (h TreasureChestImpl) handleDeleteTreasureChest() http.HandlerFunc { err := h.s.Delete(r.Context(), user, id) if err != nil { - handleError(w, r, err) + core.HandleError(w, r, err) return } } diff --git a/internal/service/default.go b/internal/service/default.go index b1ada14..72d8261 100644 --- a/internal/service/default.go +++ b/internal/service/default.go @@ -13,7 +13,7 @@ var ( safeInputRegex = regexp.MustCompile(`^[a-zA-Z0-9ÄÖÜäöüß,&'". \-\?]+$`) ) -func validateString(value string, fieldName string) error { +func ValidateString(value string, fieldName string) error { switch { case value == "": return fmt.Errorf("field \"%s\" needs to be set: %w", fieldName, ErrBadRequest) diff --git a/internal/service/transaction.go b/internal/service/transaction.go index 8278182..f950447 100644 --- a/internal/service/transaction.go +++ b/internal/service/transaction.go @@ -499,13 +499,13 @@ func (s TransactionImpl) validateAndEnrichTransaction(ctx context.Context, tx *s } if input.Party != "" { - err = validateString(input.Party, "party") + err = ValidateString(input.Party, "party") if err != nil { return nil, err } } if input.Description != "" { - err = validateString(input.Description, "description") + err = 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 c377840..6982ebc 100644 --- a/internal/service/transaction_recurring.go +++ b/internal/service/transaction_recurring.go @@ -471,13 +471,13 @@ func (s TransactionRecurringImpl) validateAndEnrichTransactionRecurring( value := int64(math.Round(valueFloat * DECIMALS_MULTIPLIER)) if input.Party != "" { - err = validateString(input.Party, "party") + err = ValidateString(input.Party, "party") if err != nil { return nil, err } } if input.Description != "" { - err = validateString(input.Description, "description") + err = 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 54e0ed5..cdc60b5 100644 --- a/internal/service/treasure_chest.go +++ b/internal/service/treasure_chest.go @@ -45,7 +45,7 @@ func (s TreasureChestImpl) Add(ctx context.Context, user *types.User, parentId, return nil, types.ErrInternal } - err = validateString(name, "name") + err = ValidateString(name, "name") if err != nil { return nil, err } @@ -92,7 +92,7 @@ func (s TreasureChestImpl) Update(ctx context.Context, user *types.User, idStr, if user == nil { return nil, ErrUnauthorized } - err := validateString(name, "name") + err := ValidateString(name, "name") if err != nil { return nil, err } diff --git a/internal/template/account/default.go b/internal/template/account/default.go deleted file mode 100644 index 0bc7635..0000000 --- a/internal/template/account/default.go +++ /dev/null @@ -1 +0,0 @@ -package account diff --git a/internal/template/transaction/transaction.templ b/internal/template/transaction/transaction.templ index 97a446b..e55b208 100644 --- a/internal/template/transaction/transaction.templ +++ b/internal/template/transaction/transaction.templ @@ -4,9 +4,10 @@ import "fmt" import "time" import "spend-sparrow/internal/template/svg" import "spend-sparrow/internal/types" +import "spend-sparrow/internal/account" import "github.com/google/uuid" -templ Transaction(items templ.Component, filter types.TransactionItemsFilter, accounts []*types.Account, treasureChests []*types.TreasureChest) { +templ Transaction(items templ.Component, filter types.TransactionItemsFilter, accounts []*account.Account, treasureChests []*types.TreasureChest) {
} -templ EditTransaction(transaction *types.Transaction, accounts []*types.Account, treasureChests []*types.TreasureChest) { +templ EditTransaction(transaction *types.Transaction, accounts []*account.Account, treasureChests []*types.TreasureChest) { {{ var ( timestamp time.Time