feat: extract account to domain package
All checks were successful
Build and Push Docker Image / Build-And-Push-Docker-Image (push) Successful in 1m17s

This commit is contained in:
2025-12-24 07:45:44 +01:00
parent 1e61b765ae
commit f9a5a9e5f9
24 changed files with 281 additions and 284 deletions

View File

@@ -1,144 +0,0 @@
package handler
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"
)
type Account interface {
Handle(router *http.ServeMux)
}
type AccountImpl struct {
s service.Account
r *Render
}
func NewAccount(s service.Account, r *Render) Account {
return AccountImpl{
s: s,
r: r,
}
}
func (h AccountImpl) 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 {
return func(w http.ResponseWriter, r *http.Request) {
updateSpan(r)
user := middleware.GetUser(r)
if user == nil {
utils.DoRedirect(w, r, "/auth/signin")
return
}
accounts, err := h.s.GetAll(r.Context(), user)
if err != nil {
handleError(w, r, err)
return
}
comp := t.Account(accounts)
h.r.RenderLayout(r, w, comp, user)
}
}
func (h AccountImpl) handleAccountItemComp() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
updateSpan(r)
user := middleware.GetUser(r)
if user == nil {
utils.DoRedirect(w, r, "/auth/signin")
return
}
id := r.PathValue("id")
if id == "new" {
comp := t.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)
return
}
var comp templ.Component
if r.URL.Query().Get("edit") == "true" {
comp = t.EditAccount(account)
} else {
comp = t.AccountItem(account)
}
h.r.Render(r, w, comp)
}
}
func (h AccountImpl) handleUpdateAccount() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
updateSpan(r)
user := middleware.GetUser(r)
if user == nil {
utils.DoRedirect(w, r, "/auth/signin")
return
}
var (
account *types.Account
err error
)
id := r.PathValue("id")
name := r.FormValue("name")
if id == "new" {
account, err = h.s.Add(r.Context(), user, name)
if err != nil {
handleError(w, r, err)
return
}
} else {
account, err = h.s.UpdateName(r.Context(), user, id, name)
if err != nil {
handleError(w, r, err)
return
}
}
comp := t.AccountItem(account)
h.r.Render(r, w, comp)
}
}
func (h AccountImpl) handleDeleteAccount() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
updateSpan(r)
user := middleware.GetUser(r)
if user == nil {
utils.DoRedirect(w, r, "/auth/signin")
return
}
id := r.PathValue("id")
err := h.s.Delete(r.Context(), user, id)
if err != nil {
handleError(w, r, err)
return
}
}
}

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -1,46 +0,0 @@
package handler
import (
"errors"
"net/http"
"spend-sparrow/internal/db"
"spend-sparrow/internal/service"
"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, service.ErrUnauthorized):
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "You are not autorized to perform this operation.", http.StatusUnauthorized)
return
case errors.Is(err, service.ErrBadRequest):
utils.TriggerToastWithStatus(r.Context(), w, r, "error", extractErrorMessage(err), http.StatusBadRequest)
return
case errors.Is(err, db.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")))
}
}

View File

@@ -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 {

View File

@@ -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 ||

View File

@@ -1,51 +0,0 @@
package handler
import (
"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 {
}
func NewRender() *Render {
return &Render{}
}
func (render *Render) RenderWithStatus(r *http.Request, w http.ResponseWriter, comp templ.Component, status int) {
w.Header().Set("Content-Type", "text/html")
w.WriteHeader(status)
err := comp.Render(r.Context(), w)
if err != nil {
slog.ErrorContext(r.Context(), "Failed to render layout", "err", err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}
}
func (render *Render) Render(r *http.Request, w http.ResponseWriter, comp templ.Component) {
render.RenderWithStatus(r, w, comp, http.StatusOK)
}
func (render *Render) RenderLayout(r *http.Request, w http.ResponseWriter, slot templ.Component, user *types.User) {
render.RenderLayoutWithStatus(r, w, slot, user, http.StatusOK)
}
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)
render.RenderWithStatus(r, w, layout, status)
}
func (render *Render) getUserComp(user *types.User) templ.Component {
if user != nil {
return auth.UserComp(user.Email)
} else {
return auth.UserComp("")
}
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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
}
}

View File

@@ -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
}
}