fix(observabillity): propagate ctx to every log call and add resource to logging
This commit was merged in pull request #187.
This commit is contained in:
@@ -53,7 +53,7 @@ func (db AuthSqlite) InsertUser(ctx context.Context, user *types.User) error {
|
||||
return ErrAlreadyExists
|
||||
}
|
||||
|
||||
slog.Error("SQL error InsertUser", "err", err)
|
||||
slog.ErrorContext(ctx, "SQL error InsertUser", "err", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ func (db AuthSqlite) UpdateUser(ctx context.Context, user *types.User) error {
|
||||
user.EmailVerified, user.EmailVerifiedAt, user.Password, user.Id)
|
||||
|
||||
if err != nil {
|
||||
slog.Error("SQL error UpdateUser", "err", err)
|
||||
slog.ErrorContext(ctx, "SQL error UpdateUser", "err", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ func (db AuthSqlite) GetUserByEmail(ctx context.Context, email string) (*types.U
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, ErrNotFound
|
||||
} else {
|
||||
slog.Error("SQL error GetUser", "err", err)
|
||||
slog.ErrorContext(ctx, "SQL error GetUser", "err", err)
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
}
|
||||
@@ -121,7 +121,7 @@ func (db AuthSqlite) GetUser(ctx context.Context, userId uuid.UUID) (*types.User
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, ErrNotFound
|
||||
} else {
|
||||
slog.Error("SQL error GetUser", "err", err)
|
||||
slog.ErrorContext(ctx, "SQL error GetUser", "err", err)
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
}
|
||||
@@ -132,55 +132,55 @@ func (db AuthSqlite) GetUser(ctx context.Context, userId uuid.UUID) (*types.User
|
||||
func (db AuthSqlite) DeleteUser(ctx context.Context, userId uuid.UUID) error {
|
||||
tx, err := db.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
slog.Error("Could not start transaction", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not start transaction", "err", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
|
||||
_, err = tx.ExecContext(ctx, "DELETE FROM account WHERE user_id = ?", userId)
|
||||
if err != nil {
|
||||
_ = tx.Rollback()
|
||||
slog.Error("Could not delete accounts", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not delete accounts", "err", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
|
||||
_, err = tx.ExecContext(ctx, "DELETE FROM token WHERE user_id = ?", userId)
|
||||
if err != nil {
|
||||
_ = tx.Rollback()
|
||||
slog.Error("Could not delete user tokens", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not delete user tokens", "err", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
|
||||
_, err = tx.ExecContext(ctx, "DELETE FROM session WHERE user_id = ?", userId)
|
||||
if err != nil {
|
||||
_ = tx.Rollback()
|
||||
slog.Error("Could not delete sessions", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not delete sessions", "err", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
|
||||
_, err = tx.ExecContext(ctx, "DELETE FROM user WHERE user_id = ?", userId)
|
||||
if err != nil {
|
||||
_ = tx.Rollback()
|
||||
slog.Error("Could not delete user", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not delete user", "err", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
|
||||
_, err = tx.ExecContext(ctx, "DELETE FROM treasure_chest WHERE user_id = ?", userId)
|
||||
if err != nil {
|
||||
_ = tx.Rollback()
|
||||
slog.Error("Could not delete user", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not delete user", "err", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
|
||||
_, err = tx.ExecContext(ctx, "DELETE FROM \"transaction\" WHERE user_id = ?", userId)
|
||||
if err != nil {
|
||||
_ = tx.Rollback()
|
||||
slog.Error("Could not delete user", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not delete user", "err", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
slog.Error("Could not commit transaction", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not commit transaction", "err", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ func (db AuthSqlite) InsertToken(ctx context.Context, token *types.Token) error
|
||||
VALUES (?, ?, ?, ?, ?, ?)`, token.UserId, token.SessionId, token.Type, token.Token, token.CreatedAt, token.ExpiresAt)
|
||||
|
||||
if err != nil {
|
||||
slog.Error("Could not insert token", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not insert token", "err", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
|
||||
@@ -218,23 +218,23 @@ func (db AuthSqlite) GetToken(ctx context.Context, token string) (*types.Token,
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
slog.Info("Token not found", "token", token)
|
||||
slog.InfoContext(ctx, "Token not found", "token", token)
|
||||
return nil, ErrNotFound
|
||||
} else {
|
||||
slog.Error("Could not get token", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not get token", "err", err)
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
}
|
||||
|
||||
createdAt, err = time.Parse(time.RFC3339, createdAtStr)
|
||||
if err != nil {
|
||||
slog.Error("Could not parse token.created_at", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not parse token.created_at", "err", err)
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
|
||||
expiresAt, err = time.Parse(time.RFC3339, expiresAtStr)
|
||||
if err != nil {
|
||||
slog.Error("Could not parse token.expires_at", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not parse token.expires_at", "err", err)
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
|
||||
@@ -249,11 +249,11 @@ func (db AuthSqlite) GetTokensByUserIdAndType(ctx context.Context, userId uuid.U
|
||||
AND type = ?`, userId, tokenType)
|
||||
|
||||
if err != nil {
|
||||
slog.Error("Could not get token", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not get token", "err", err)
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
|
||||
return getTokensFromQuery(query, userId, "", tokenType)
|
||||
return getTokensFromQuery(ctx, query, userId, "", tokenType)
|
||||
}
|
||||
|
||||
func (db AuthSqlite) GetTokensBySessionIdAndType(ctx context.Context, sessionId string, tokenType types.TokenType) ([]*types.Token, error) {
|
||||
@@ -264,14 +264,14 @@ func (db AuthSqlite) GetTokensBySessionIdAndType(ctx context.Context, sessionId
|
||||
AND type = ?`, sessionId, tokenType)
|
||||
|
||||
if err != nil {
|
||||
slog.Error("Could not get token", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not get token", "err", err)
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
|
||||
return getTokensFromQuery(query, uuid.Nil, sessionId, tokenType)
|
||||
return getTokensFromQuery(ctx, query, uuid.Nil, sessionId, tokenType)
|
||||
}
|
||||
|
||||
func getTokensFromQuery(query *sql.Rows, userId uuid.UUID, sessionId string, tokenType types.TokenType) ([]*types.Token, error) {
|
||||
func getTokensFromQuery(ctx context.Context, query *sql.Rows, userId uuid.UUID, sessionId string, tokenType types.TokenType) ([]*types.Token, error) {
|
||||
var tokens []*types.Token
|
||||
|
||||
hasRows := false
|
||||
@@ -288,19 +288,19 @@ func getTokensFromQuery(query *sql.Rows, userId uuid.UUID, sessionId string, tok
|
||||
|
||||
err := query.Scan(&token, &createdAtStr, &expiresAtStr)
|
||||
if err != nil {
|
||||
slog.Error("Could not scan token", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not scan token", "err", err)
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
|
||||
createdAt, err = time.Parse(time.RFC3339, createdAtStr)
|
||||
if err != nil {
|
||||
slog.Error("Could not parse token.created_at", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not parse token.created_at", "err", err)
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
|
||||
expiresAt, err = time.Parse(time.RFC3339, expiresAtStr)
|
||||
if err != nil {
|
||||
slog.Error("Could not parse token.expires_at", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not parse token.expires_at", "err", err)
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
|
||||
@@ -317,7 +317,7 @@ func getTokensFromQuery(query *sql.Rows, userId uuid.UUID, sessionId string, tok
|
||||
func (db AuthSqlite) DeleteToken(ctx context.Context, token string) error {
|
||||
_, err := db.db.ExecContext(ctx, "DELETE FROM token WHERE token = ?", token)
|
||||
if err != nil {
|
||||
slog.Error("Could not delete token", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not delete token", "err", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
return nil
|
||||
@@ -329,7 +329,7 @@ func (db AuthSqlite) InsertSession(ctx context.Context, session *types.Session)
|
||||
VALUES (?, ?, ?, ?)`, session.Id, session.UserId, session.CreatedAt, session.ExpiresAt)
|
||||
|
||||
if err != nil {
|
||||
slog.Error("Could not insert new session", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not insert new session", "err", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
|
||||
@@ -349,7 +349,7 @@ func (db AuthSqlite) GetSession(ctx context.Context, sessionId string) (*types.S
|
||||
WHERE session_id = ?`, sessionId).Scan(&userId, &createdAt, &expiresAt)
|
||||
|
||||
if err != nil {
|
||||
slog.Warn("Session not found", "session-id", sessionId, "err", err)
|
||||
slog.WarnContext(ctx, "Session not found", "session-id", sessionId, "err", err)
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
@@ -363,7 +363,7 @@ func (db AuthSqlite) GetSessions(ctx context.Context, userId uuid.UUID) ([]*type
|
||||
FROM session
|
||||
WHERE user_id = ?`, userId)
|
||||
if err != nil {
|
||||
slog.Error("Could not get sessions", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not get sessions", "err", err)
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
|
||||
@@ -374,7 +374,7 @@ func (db AuthSqlite) DeleteSession(ctx context.Context, sessionId string) error
|
||||
if sessionId != "" {
|
||||
_, err := db.db.ExecContext(ctx, "DELETE FROM session WHERE session_id = ?", sessionId)
|
||||
if err != nil {
|
||||
slog.Error("Could not delete session", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not delete session", "err", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
}
|
||||
@@ -387,7 +387,7 @@ func (db AuthSqlite) DeleteOldSessions(ctx context.Context) error {
|
||||
DELETE FROM session
|
||||
WHERE expires_at < datetime('now')`)
|
||||
if err != nil {
|
||||
slog.Error("Could not delete old sessions", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not delete old sessions", "err", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
return nil
|
||||
@@ -398,7 +398,7 @@ func (db AuthSqlite) DeleteOldTokens(ctx context.Context) error {
|
||||
DELETE FROM token
|
||||
WHERE expires_at < datetime('now')`)
|
||||
if err != nil {
|
||||
slog.Error("Could not delete old tokens", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not delete old tokens", "err", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"log/slog"
|
||||
@@ -12,24 +13,24 @@ var (
|
||||
ErrAlreadyExists = errors.New("row already exists")
|
||||
)
|
||||
|
||||
func TransformAndLogDbError(module string, r sql.Result, err error) error {
|
||||
func TransformAndLogDbError(ctx context.Context, module string, r sql.Result, err error) error {
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return ErrNotFound
|
||||
}
|
||||
slog.Error("database sql", "module", module, "err", err)
|
||||
slog.ErrorContext(ctx, "database sql", "module", module, "err", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
|
||||
if r != nil {
|
||||
rows, err := r.RowsAffected()
|
||||
if err != nil {
|
||||
slog.Error("database rows affected", "module", module, "err", err)
|
||||
slog.ErrorContext(ctx, "database rows affected", "module", module, "err", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
|
||||
if rows == 0 {
|
||||
slog.Info("row not found", "module", module)
|
||||
slog.InfoContext(ctx, "row not found", "module", module)
|
||||
return ErrNotFound
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ func (l migrationLogger) Verbose() bool {
|
||||
func RunMigrations(ctx context.Context, db *sqlx.DB, pathPrefix string) error {
|
||||
driver, err := sqlite3.WithInstance(db.DB, &sqlite3.Config{})
|
||||
if err != nil {
|
||||
slog.Error("Could not create Migration instance", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not create Migration instance", "err", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
|
||||
@@ -33,14 +33,14 @@ func RunMigrations(ctx context.Context, db *sqlx.DB, pathPrefix string) error {
|
||||
"",
|
||||
driver)
|
||||
if err != nil {
|
||||
slog.Error("Could not create migrations instance", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not create migrations instance", "err", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
|
||||
m.Log = migrationLogger{}
|
||||
|
||||
if err = m.Up(); err != nil && !errors.Is(err, migrate.ErrNoChange) {
|
||||
slog.Error("Could not run migrations", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not run migrations", "err", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ func Run(ctx context.Context, database *sqlx.DB, migrationsPrefix string, env fu
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
err = otelShutdown(ctx)
|
||||
if err != nil {
|
||||
slog.Error("error shutting down OpenTelemetry SDK", "err", err)
|
||||
slog.ErrorContext(ctx, "error shutting down OpenTelemetry SDK", "err", err)
|
||||
}
|
||||
cancel()
|
||||
}()
|
||||
@@ -47,10 +47,10 @@ func Run(ctx context.Context, database *sqlx.DB, migrationsPrefix string, env fu
|
||||
slog.SetDefault(log.NewLogPropagator())
|
||||
}
|
||||
|
||||
slog.Info("Starting server...")
|
||||
slog.InfoContext(ctx, "Starting server...")
|
||||
|
||||
// init server settings
|
||||
serverSettings, err := types.NewSettingsFromEnv(env)
|
||||
serverSettings, err := types.NewSettingsFromEnv(ctx, env)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -67,26 +67,26 @@ func Run(ctx context.Context, database *sqlx.DB, migrationsPrefix string, env fu
|
||||
Handler: createHandlerWithServices(ctx, database, serverSettings),
|
||||
ReadHeaderTimeout: 2 * time.Second,
|
||||
}
|
||||
go startServer(httpServer)
|
||||
go startServer(ctx, httpServer)
|
||||
|
||||
// graceful shutdown
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go shutdownServer(httpServer, ctx, &wg)
|
||||
go shutdownServer(ctx, httpServer, &wg)
|
||||
|
||||
wg.Wait()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func startServer(s *http.Server) {
|
||||
slog.Info("Starting server", "addr", s.Addr)
|
||||
func startServer(ctx context.Context, s *http.Server) {
|
||||
slog.InfoContext(ctx, "Starting server", "addr", s.Addr)
|
||||
if err := s.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
slog.Error("error listening and serving", "err", err)
|
||||
slog.ErrorContext(ctx, "error listening and serving", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
func shutdownServer(s *http.Server, ctx context.Context, wg *sync.WaitGroup) {
|
||||
func shutdownServer(ctx context.Context, s *http.Server, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
if s == nil {
|
||||
return
|
||||
@@ -97,9 +97,9 @@ func shutdownServer(s *http.Server, ctx context.Context, wg *sync.WaitGroup) {
|
||||
shutdownCtx, cancel := context.WithTimeout(shutdownCtx, 10*time.Second)
|
||||
defer cancel()
|
||||
if err := s.Shutdown(shutdownCtx); err != nil {
|
||||
slog.Error("error shutting down http server", "err", err)
|
||||
slog.ErrorContext(ctx, "error shutting down http server", "err", err)
|
||||
} else {
|
||||
slog.Info("Gracefully stopped http server", "addr", s.Addr)
|
||||
slog.InfoContext(ctx, "Gracefully stopped http server", "addr", s.Addr)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ func dailyTaskTimer(ctx context.Context, transactionRecurring service.Transactio
|
||||
}
|
||||
|
||||
func runDailyTasks(ctx context.Context, transactionRecurring service.TransactionRecurring, auth service.Auth) {
|
||||
slog.Info("Running daily tasks")
|
||||
slog.InfoContext(ctx, "Running daily tasks")
|
||||
_ = transactionRecurring.GenerateTransactions(ctx)
|
||||
_ = auth.CleanupSessionsAndTokens(ctx)
|
||||
}
|
||||
|
||||
@@ -98,9 +98,9 @@ func (handler AuthImpl) handleSignIn() http.HandlerFunc {
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, service.ErrInvalidCredentials) {
|
||||
utils.TriggerToastWithStatus(w, r, "error", "Invalid email or password", http.StatusUnauthorized)
|
||||
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "Invalid email or password", http.StatusUnauthorized)
|
||||
} else {
|
||||
utils.TriggerToastWithStatus(w, r, "error", "An error occurred", http.StatusInternalServerError)
|
||||
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "An error occurred", http.StatusInternalServerError)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -167,7 +167,7 @@ func (handler AuthImpl) handleVerifyResendComp() http.HandlerFunc {
|
||||
|
||||
_, err := w.Write([]byte("<p class=\"mt-8\">Verification email sent</p>"))
|
||||
if err != nil {
|
||||
slog.Error("Could not write response", "err", err)
|
||||
slog.ErrorContext(r.Context(), "Could not write response", "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -202,13 +202,13 @@ func (handler AuthImpl) handleSignUp() http.HandlerFunc {
|
||||
var password = r.FormValue("password")
|
||||
|
||||
_, err := utils.WaitMinimumTime(securityWaitDuration, func() (any, error) {
|
||||
slog.Info("signing up", "email", email)
|
||||
slog.InfoContext(r.Context(), "signing up", "email", email)
|
||||
user, err := handler.service.SignUp(r.Context(), email, password)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
slog.Info("Sending verification email", "to", user.Email)
|
||||
slog.InfoContext(r.Context(), "Sending verification email", "to", user.Email)
|
||||
go handler.service.SendVerificationMail(r.Context(), user.Id, user.Email)
|
||||
return nil, nil
|
||||
})
|
||||
@@ -216,19 +216,19 @@ func (handler AuthImpl) handleSignUp() http.HandlerFunc {
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, types.ErrInternal):
|
||||
utils.TriggerToastWithStatus(w, r, "error", "An error occurred", http.StatusInternalServerError)
|
||||
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "An error occurred", http.StatusInternalServerError)
|
||||
return
|
||||
case errors.Is(err, service.ErrInvalidEmail):
|
||||
utils.TriggerToastWithStatus(w, r, "error", "The email provided is invalid", http.StatusBadRequest)
|
||||
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "The email provided is invalid", http.StatusBadRequest)
|
||||
return
|
||||
case errors.Is(err, service.ErrInvalidPassword):
|
||||
utils.TriggerToastWithStatus(w, r, "error", service.ErrInvalidPassword.Error(), http.StatusBadRequest)
|
||||
utils.TriggerToastWithStatus(r.Context(), w, r, "error", service.ErrInvalidPassword.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
// If err is "service.ErrAccountExists", then just continue
|
||||
}
|
||||
|
||||
utils.TriggerToastWithStatus(w, r, "success", "An activation link has been send to your email", http.StatusOK)
|
||||
utils.TriggerToastWithStatus(r.Context(), w, r, "success", "An activation link has been send to your email", http.StatusOK)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,9 +291,9 @@ func (handler AuthImpl) handleDeleteAccountComp() http.HandlerFunc {
|
||||
err := handler.service.DeleteAccount(r.Context(), user, password)
|
||||
if err != nil {
|
||||
if errors.Is(err, service.ErrInvalidCredentials) {
|
||||
utils.TriggerToastWithStatus(w, r, "error", "Password not correct", http.StatusBadRequest)
|
||||
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "Password not correct", http.StatusBadRequest)
|
||||
} else {
|
||||
utils.TriggerToastWithStatus(w, r, "error", "Internal Server Error", http.StatusInternalServerError)
|
||||
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "Internal Server Error", http.StatusInternalServerError)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -327,7 +327,7 @@ func (handler AuthImpl) handleChangePasswordComp() http.HandlerFunc {
|
||||
session := middleware.GetSession(r)
|
||||
user := middleware.GetUser(r)
|
||||
if session == nil || user == nil {
|
||||
utils.TriggerToastWithStatus(w, r, "error", "Unathorized", http.StatusUnauthorized)
|
||||
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "Unathorized", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -336,11 +336,11 @@ func (handler AuthImpl) handleChangePasswordComp() http.HandlerFunc {
|
||||
|
||||
err := handler.service.ChangePassword(r.Context(), user, session.Id, currPass, newPass)
|
||||
if err != nil {
|
||||
utils.TriggerToastWithStatus(w, r, "error", err.Error(), http.StatusBadRequest)
|
||||
utils.TriggerToastWithStatus(r.Context(), w, r, "error", err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
utils.TriggerToastWithStatus(w, r, "success", "Password changed", http.StatusOK)
|
||||
utils.TriggerToastWithStatus(r.Context(), w, r, "success", "Password changed", http.StatusOK)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,7 +365,7 @@ func (handler AuthImpl) handleForgotPasswordComp() http.HandlerFunc {
|
||||
|
||||
email := r.FormValue("email")
|
||||
if email == "" {
|
||||
utils.TriggerToastWithStatus(w, r, "error", "Please enter an email", http.StatusBadRequest)
|
||||
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "Please enter an email", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -375,9 +375,9 @@ func (handler AuthImpl) handleForgotPasswordComp() http.HandlerFunc {
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
utils.TriggerToastWithStatus(w, r, "error", "Internal Server Error", http.StatusInternalServerError)
|
||||
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "Internal Server Error", http.StatusInternalServerError)
|
||||
} else {
|
||||
utils.TriggerToastWithStatus(w, r, "info", "If the address exists, an email has been sent.", http.StatusOK)
|
||||
utils.TriggerToastWithStatus(r.Context(), w, r, "info", "If the address exists, an email has been sent.", http.StatusOK)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -388,8 +388,8 @@ func (handler AuthImpl) handleForgotPasswordResponseComp() http.HandlerFunc {
|
||||
|
||||
pageUrl, err := url.Parse(r.Header.Get("Hx-Current-Url"))
|
||||
if err != nil {
|
||||
slog.Error("Could not get current URL", "err", err)
|
||||
utils.TriggerToastWithStatus(w, r, "error", "Internal Server Error", http.StatusInternalServerError)
|
||||
slog.ErrorContext(r.Context(), "Could not get current URL", "err", err)
|
||||
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -398,9 +398,9 @@ func (handler AuthImpl) handleForgotPasswordResponseComp() http.HandlerFunc {
|
||||
|
||||
err = handler.service.ForgotPassword(r.Context(), token, newPass)
|
||||
if err != nil {
|
||||
utils.TriggerToastWithStatus(w, r, "error", err.Error(), http.StatusBadRequest)
|
||||
utils.TriggerToastWithStatus(r.Context(), w, r, "error", err.Error(), http.StatusBadRequest)
|
||||
} else {
|
||||
utils.TriggerToastWithStatus(w, r, "success", "Password changed", http.StatusOK)
|
||||
utils.TriggerToastWithStatus(r.Context(), w, r, "success", "Password changed", http.StatusOK)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,17 +15,17 @@ import (
|
||||
func handleError(w http.ResponseWriter, r *http.Request, err error) {
|
||||
switch {
|
||||
case errors.Is(err, service.ErrUnauthorized):
|
||||
utils.TriggerToastWithStatus(w, r, "error", "You are not autorized to perform this operation.", http.StatusUnauthorized)
|
||||
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(w, r, "error", extractErrorMessage(err), http.StatusBadRequest)
|
||||
utils.TriggerToastWithStatus(r.Context(), w, r, "error", extractErrorMessage(err), http.StatusBadRequest)
|
||||
return
|
||||
case errors.Is(err, db.ErrNotFound):
|
||||
utils.TriggerToastWithStatus(w, r, "error", extractErrorMessage(err), http.StatusNotFound)
|
||||
utils.TriggerToastWithStatus(r.Context(), w, r, "error", extractErrorMessage(err), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
utils.TriggerToastWithStatus(w, r, "error", "Internal Server Error", http.StatusInternalServerError)
|
||||
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "Internal Server Error", http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
func extractErrorMessage(err error) string {
|
||||
|
||||
@@ -42,9 +42,9 @@ func CrossSiteRequestForgery(auth service.Auth) func(http.Handler) http.Handler
|
||||
csrfToken := r.Header.Get("Csrf-Token")
|
||||
|
||||
if session == nil || csrfToken == "" || !auth.IsCsrfTokenValid(ctx, csrfToken, session.Id) {
|
||||
slog.Info("CSRF-Token not correct", "token", csrfToken)
|
||||
slog.InfoContext(ctx, "CSRF-Token not correct", "token", csrfToken)
|
||||
if r.Header.Get("Hx-Request") == "true" {
|
||||
utils.TriggerToastWithStatus(w, r, "error", "CSRF-Token not correct", http.StatusBadRequest)
|
||||
utils.TriggerToastWithStatus(ctx, w, r, "error", "CSRF-Token not correct", http.StatusBadRequest)
|
||||
} else {
|
||||
http.Error(w, "CSRF-Token not correct", http.StatusBadRequest)
|
||||
}
|
||||
@@ -55,7 +55,7 @@ func CrossSiteRequestForgery(auth service.Auth) func(http.Handler) http.Handler
|
||||
token, err := auth.GetCsrfToken(ctx, session)
|
||||
if err != nil {
|
||||
if r.Header.Get("Hx-Request") == "true" {
|
||||
utils.TriggerToastWithStatus(w, r, "error", "Could not generate CSRF Token", http.StatusBadRequest)
|
||||
utils.TriggerToastWithStatus(ctx, w, r, "error", "Could not generate CSRF Token", http.StatusBadRequest)
|
||||
} else {
|
||||
http.Error(w, "Could not generate CSRF Token", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ func Gzip(next http.Handler) http.Handler {
|
||||
|
||||
err := gz.Close()
|
||||
if err != nil && !errors.Is(err, http.ErrBodyNotAllowed) {
|
||||
slog.Error("Gzip: could not close Writer", "err", err)
|
||||
slog.ErrorContext(r.Context(), "Gzip: could not close Writer", "err", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ func Log(next http.Handler) http.Handler {
|
||||
}
|
||||
next.ServeHTTP(wrapped, r)
|
||||
|
||||
slog.Info("request",
|
||||
slog.InfoContext(r.Context(), "request",
|
||||
"remoteAddr", r.RemoteAddr,
|
||||
"status", wrapped.StatusCode,
|
||||
"method", r.Method,
|
||||
|
||||
@@ -22,7 +22,7 @@ func (render *Render) RenderWithStatus(r *http.Request, w http.ResponseWriter, c
|
||||
w.WriteHeader(status)
|
||||
err := comp.Render(r.Context(), w)
|
||||
if err != nil {
|
||||
slog.Error("Failed to render layout", "err", err)
|
||||
slog.ErrorContext(r.Context(), "Failed to render layout", "err", err)
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ func (handler IndexImpl) handleRootAnd404() http.HandlerFunc {
|
||||
var err error
|
||||
comp, err = handler.dashboard(user, htmx, r)
|
||||
if err != nil {
|
||||
slog.Error("Failed to get dashboard summary", "err", err)
|
||||
slog.ErrorContext(r.Context(), "Failed to get dashboard summary", "err", err)
|
||||
}
|
||||
} else {
|
||||
comp = template.Index()
|
||||
|
||||
@@ -254,7 +254,7 @@ func (h TransactionImpl) handleRecalculate() http.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
utils.TriggerToastWithStatus(w, r, "success", "Balances recalculated, please refresh", http.StatusOK)
|
||||
utils.TriggerToastWithStatus(r.Context(), w, r, "success", "Balances recalculated, please refresh", http.StatusOK)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ func (h TransactionRecurringImpl) renderItems(w http.ResponseWriter, r *http.Req
|
||||
var transactionsRecurring []*types.TransactionRecurring
|
||||
var err error
|
||||
if accountId == "" && treasureChestId == "" {
|
||||
utils.TriggerToastWithStatus(w, r, "error", "Please select an account or treasure chest", http.StatusBadRequest)
|
||||
utils.TriggerToastWithStatus(r.Context(), w, r, "error", "Please select an account or treasure chest", http.StatusBadRequest)
|
||||
}
|
||||
if accountId != "" {
|
||||
transactionsRecurring, err = h.s.GetAllByAccount(r.Context(), user, accountId)
|
||||
|
||||
@@ -27,8 +27,6 @@ func (l *logHandler) Enabled(ctx context.Context, level slog.Level) bool {
|
||||
|
||||
// Handle implements slog.Handler.
|
||||
func (l *logHandler) Handle(ctx context.Context, rec slog.Record) error {
|
||||
rec.AddAttrs(slog.String("service_name", "spend-sparrow"))
|
||||
|
||||
if err := l.console.Handle(ctx, rec); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package internal
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
@@ -13,7 +14,9 @@ import (
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
"go.opentelemetry.io/otel/sdk/log"
|
||||
"go.opentelemetry.io/otel/sdk/metric"
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
"go.opentelemetry.io/otel/sdk/trace"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -47,6 +50,14 @@ func setupOTelSDK(ctx context.Context) (func(context.Context) error, error) {
|
||||
prop := newPropagator()
|
||||
otel.SetTextMapPropagator(prop)
|
||||
|
||||
resources, err := resource.New(
|
||||
ctx,
|
||||
resource.WithAttributes(semconv.ServiceName("spend-sparrow")),
|
||||
)
|
||||
if err != nil {
|
||||
slog.ErrorContext(ctx, "failed to create resource", "error", err)
|
||||
}
|
||||
|
||||
// Set up trace provider.
|
||||
tracerProvider, err := newTracerProvider(ctx)
|
||||
if err != nil {
|
||||
@@ -66,7 +77,7 @@ func setupOTelSDK(ctx context.Context) (func(context.Context) error, error) {
|
||||
otel.SetMeterProvider(meterProvider)
|
||||
|
||||
// Set up logger provider.
|
||||
loggerProvider, err := newLoggerProvider(ctx)
|
||||
loggerProvider, err := newLoggerProvider(ctx, resources)
|
||||
if err != nil {
|
||||
handleErr(ctx, err)
|
||||
return nil, err
|
||||
@@ -85,7 +96,8 @@ func newPropagator() propagation.TextMapPropagator {
|
||||
}
|
||||
|
||||
func newTracerProvider(ctx context.Context) (*trace.TracerProvider, error) {
|
||||
exp, err := otlptracegrpc.New(ctx,
|
||||
exp, err := otlptracegrpc.New(
|
||||
ctx,
|
||||
otlptracegrpc.WithEndpoint(otelEndpoint),
|
||||
otlptracegrpc.WithInsecure(),
|
||||
)
|
||||
@@ -97,7 +109,8 @@ func newTracerProvider(ctx context.Context) (*trace.TracerProvider, error) {
|
||||
}
|
||||
|
||||
func newMeterProvider(ctx context.Context) (*metric.MeterProvider, error) {
|
||||
exp, err := otlpmetricgrpc.New(ctx,
|
||||
exp, err := otlpmetricgrpc.New(
|
||||
ctx,
|
||||
otlpmetricgrpc.WithInsecure(),
|
||||
otlpmetricgrpc.WithEndpoint(otelEndpoint))
|
||||
if err != nil {
|
||||
@@ -110,7 +123,7 @@ func newMeterProvider(ctx context.Context) (*metric.MeterProvider, error) {
|
||||
exp, metric.WithInterval(15*time.Second)))), nil
|
||||
}
|
||||
|
||||
func newLoggerProvider(ctx context.Context) (*log.LoggerProvider, error) {
|
||||
func newLoggerProvider(ctx context.Context, resource *resource.Resource) (*log.LoggerProvider, error) {
|
||||
logExporter, err := otlploggrpc.New(
|
||||
ctx,
|
||||
otlploggrpc.WithInsecure(),
|
||||
@@ -121,6 +134,7 @@ func newLoggerProvider(ctx context.Context) (*log.LoggerProvider, error) {
|
||||
|
||||
loggerProvider := log.NewLoggerProvider(
|
||||
log.WithProcessor(log.NewBatchProcessor(logExporter)),
|
||||
log.WithResource(resource),
|
||||
)
|
||||
return loggerProvider, nil
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ func (s AccountImpl) Add(ctx context.Context, user *types.User, name string) (*t
|
||||
return nil, ErrUnauthorized
|
||||
}
|
||||
|
||||
newId, err := s.random.UUID()
|
||||
newId, err := s.random.UUID(ctx)
|
||||
if err != nil {
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
@@ -68,7 +68,7 @@ func (s AccountImpl) Add(ctx context.Context, user *types.User, name string) (*t
|
||||
r, err := s.db.NamedExecContext(ctx, `
|
||||
INSERT INTO account (id, user_id, name, current_balance, oink_balance, created_at, created_by)
|
||||
VALUES (:id, :user_id, :name, :current_balance, :oink_balance, :created_at, :created_by)`, account)
|
||||
err = db.TransformAndLogDbError("account Insert", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "account Insert", r, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -86,12 +86,12 @@ func (s AccountImpl) UpdateName(ctx context.Context, user *types.User, id string
|
||||
}
|
||||
uuid, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
slog.Error("account update", "err", err)
|
||||
slog.ErrorContext(ctx, "account update", "err", err)
|
||||
return nil, fmt.Errorf("could not parse Id: %w", ErrBadRequest)
|
||||
}
|
||||
|
||||
tx, err := s.db.BeginTxx(ctx, nil)
|
||||
err = db.TransformAndLogDbError("account Update", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "account Update", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -101,7 +101,7 @@ func (s AccountImpl) UpdateName(ctx context.Context, user *types.User, id string
|
||||
|
||||
var account types.Account
|
||||
err = tx.GetContext(ctx, &account, `SELECT * FROM account WHERE user_id = ? AND id = ?`, user.Id, uuid)
|
||||
err = db.TransformAndLogDbError("account Update", nil, err)
|
||||
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)
|
||||
@@ -122,13 +122,13 @@ func (s AccountImpl) UpdateName(ctx context.Context, user *types.User, id string
|
||||
updated_by = :updated_by
|
||||
WHERE id = :id
|
||||
AND user_id = :user_id`, account)
|
||||
err = db.TransformAndLogDbError("account Update", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "account Update", r, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
err = db.TransformAndLogDbError("account Update", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "account Update", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -142,16 +142,16 @@ func (s AccountImpl) Get(ctx context.Context, user *types.User, id string) (*typ
|
||||
}
|
||||
uuid, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
slog.Error("account get", "err", err)
|
||||
slog.ErrorContext(ctx, "account get", "err", err)
|
||||
return nil, fmt.Errorf("could not parse Id: %w", ErrBadRequest)
|
||||
}
|
||||
|
||||
var account types.Account
|
||||
err = s.db.GetContext(ctx, &account, `
|
||||
SELECT * FROM account WHERE user_id = ? AND id = ?`, user.Id, uuid)
|
||||
err = db.TransformAndLogDbError("account Get", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "account Get", nil, err)
|
||||
if err != nil {
|
||||
slog.Error("account get", "err", err)
|
||||
slog.ErrorContext(ctx, "account get", "err", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ func (s AccountImpl) GetAll(ctx context.Context, user *types.User) ([]*types.Acc
|
||||
accounts := make([]*types.Account, 0)
|
||||
err := s.db.SelectContext(ctx, &accounts, `
|
||||
SELECT * FROM account WHERE user_id = ? ORDER BY name`, user.Id)
|
||||
err = db.TransformAndLogDbError("account GetAll", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "account GetAll", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -180,12 +180,12 @@ func (s AccountImpl) Delete(ctx context.Context, user *types.User, id string) er
|
||||
}
|
||||
uuid, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
slog.Error("account delete", "err", err)
|
||||
slog.ErrorContext(ctx, "account delete", "err", err)
|
||||
return fmt.Errorf("could not parse Id: %w", ErrBadRequest)
|
||||
}
|
||||
|
||||
tx, err := s.db.BeginTxx(ctx, nil)
|
||||
err = db.TransformAndLogDbError("account Delete", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "account Delete", nil, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -195,7 +195,7 @@ func (s AccountImpl) Delete(ctx context.Context, user *types.User, id string) er
|
||||
|
||||
transactionsCount := 0
|
||||
err = tx.GetContext(ctx, &transactionsCount, `SELECT COUNT(*) FROM "transaction" WHERE user_id = ? AND account_id = ?`, user.Id, uuid)
|
||||
err = db.TransformAndLogDbError("account Delete", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "account Delete", nil, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -204,13 +204,13 @@ func (s AccountImpl) Delete(ctx context.Context, user *types.User, id string) er
|
||||
}
|
||||
|
||||
res, err := tx.ExecContext(ctx, "DELETE FROM account WHERE id = ? and user_id = ?", uuid, user.Id)
|
||||
err = db.TransformAndLogDbError("account Delete", res, err)
|
||||
err = db.TransformAndLogDbError(ctx, "account Delete", res, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
err = db.TransformAndLogDbError("account Delete", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "account Delete", nil, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ func (service AuthImpl) SignInAnonymous(ctx context.Context) (*types.Session, er
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
|
||||
slog.Info("anonymous session created", "session-id", session.Id)
|
||||
slog.InfoContext(ctx, "anonymous session created", "session-id", session.Id)
|
||||
|
||||
return session, nil
|
||||
}
|
||||
@@ -153,12 +153,12 @@ func (service AuthImpl) SignUp(ctx context.Context, email string, password strin
|
||||
return nil, ErrInvalidPassword
|
||||
}
|
||||
|
||||
userId, err := service.random.UUID()
|
||||
userId, err := service.random.UUID(ctx)
|
||||
if err != nil {
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
|
||||
salt, err := service.random.Bytes(16)
|
||||
salt, err := service.random.Bytes(ctx, 16)
|
||||
if err != nil {
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
@@ -192,7 +192,7 @@ func (service AuthImpl) SendVerificationMail(ctx context.Context, userId uuid.UU
|
||||
}
|
||||
|
||||
if token == nil {
|
||||
newTokenStr, err := service.random.String(32)
|
||||
newTokenStr, err := service.random.String(ctx, 32)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -214,11 +214,11 @@ func (service AuthImpl) SendVerificationMail(ctx context.Context, userId uuid.UU
|
||||
var w strings.Builder
|
||||
err = mailTemplate.Register(service.serverSettings.BaseUrl, token.Token).Render(context.Background(), &w)
|
||||
if err != nil {
|
||||
slog.Error("Could not render welcome email", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not render welcome email", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
service.mail.SendMail(email, "Welcome to spend-sparrow", w.String())
|
||||
service.mail.SendMail(ctx, email, "Welcome to spend-sparrow", w.String())
|
||||
}
|
||||
|
||||
func (service AuthImpl) VerifyUserEmail(ctx context.Context, tokenStr string) error {
|
||||
@@ -278,7 +278,7 @@ func (service AuthImpl) DeleteAccount(ctx context.Context, user *types.User, cur
|
||||
return err
|
||||
}
|
||||
|
||||
service.mail.SendMail(user.Email, "Account deleted", "Your account has been deleted")
|
||||
service.mail.SendMail(ctx, user.Email, "Account deleted", "Your account has been deleted")
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -323,7 +323,7 @@ func (service AuthImpl) ChangePassword(ctx context.Context, user *types.User, se
|
||||
}
|
||||
|
||||
func (service AuthImpl) SendForgotPasswordMail(ctx context.Context, email string) error {
|
||||
tokenStr, err := service.random.String(32)
|
||||
tokenStr, err := service.random.String(ctx, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -353,10 +353,10 @@ func (service AuthImpl) SendForgotPasswordMail(ctx context.Context, email string
|
||||
var mail strings.Builder
|
||||
err = mailTemplate.ResetPassword(service.serverSettings.BaseUrl, token.Token).Render(context.Background(), &mail)
|
||||
if err != nil {
|
||||
slog.Error("Could not render reset password email", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not render reset password email", "err", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
service.mail.SendMail(email, "Reset Password", mail.String())
|
||||
service.mail.SendMail(ctx, email, "Reset Password", mail.String())
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -383,7 +383,7 @@ func (service AuthImpl) ForgotPassword(ctx context.Context, tokenStr string, new
|
||||
|
||||
user, err := service.db.GetUser(ctx, token.UserId)
|
||||
if err != nil {
|
||||
slog.Error("Could not get user from token", "err", err)
|
||||
slog.ErrorContext(ctx, "Could not get user from token", "err", err)
|
||||
return types.ErrInternal
|
||||
}
|
||||
|
||||
@@ -436,7 +436,7 @@ func (service AuthImpl) GetCsrfToken(ctx context.Context, session *types.Session
|
||||
return tokens[0].Token, nil
|
||||
}
|
||||
|
||||
tokenStr, err := service.random.String(32)
|
||||
tokenStr, err := service.random.String(ctx, 32)
|
||||
if err != nil {
|
||||
return "", types.ErrInternal
|
||||
}
|
||||
@@ -453,7 +453,7 @@ func (service AuthImpl) GetCsrfToken(ctx context.Context, session *types.Session
|
||||
return "", types.ErrInternal
|
||||
}
|
||||
|
||||
slog.Info("CSRF-Token created", "token", tokenStr)
|
||||
slog.InfoContext(ctx, "CSRF-Token created", "token", tokenStr)
|
||||
|
||||
return tokenStr, nil
|
||||
}
|
||||
@@ -473,7 +473,7 @@ func (service AuthImpl) CleanupSessionsAndTokens(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (service AuthImpl) createSession(ctx context.Context, userId uuid.UUID) (*types.Session, error) {
|
||||
sessionId, err := service.random.String(32)
|
||||
sessionId, err := service.random.String(ctx, 32)
|
||||
if err != nil {
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ func (s Dashboard) Summary(ctx context.Context, user *types.User, month time.Tim
|
||||
AND error IS NULL
|
||||
AND date(timestamp, 'start of month') = date($2, 'start of month')`,
|
||||
user.Id, month)
|
||||
err = db.TransformAndLogDbError("dashboard", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "dashboard", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -53,7 +53,7 @@ func (s Dashboard) Summary(ctx context.Context, user *types.User, month time.Tim
|
||||
AND error IS NULL
|
||||
AND date(timestamp, 'start of month') = date($2, 'start of month')`,
|
||||
user.Id, month)
|
||||
err = db.TransformAndLogDbError("dashboard", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "dashboard", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -70,7 +70,7 @@ func (s Dashboard) Summary(ctx context.Context, user *types.User, month time.Tim
|
||||
AND error IS NULL
|
||||
AND date(timestamp, 'start of month') = date($2, 'start of month')`,
|
||||
user.Id, month)
|
||||
err = db.TransformAndLogDbError("dashboard", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "dashboard", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -86,7 +86,7 @@ func (s Dashboard) Summary(ctx context.Context, user *types.User, month time.Tim
|
||||
FROM treasure_chest
|
||||
WHERE user_id = $1`,
|
||||
user.Id)
|
||||
err = db.TransformAndLogDbError("dashboard", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "dashboard", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -99,7 +99,7 @@ func (s Dashboard) Summary(ctx context.Context, user *types.User, month time.Tim
|
||||
FROM account
|
||||
WHERE user_id = $1`,
|
||||
user.Id)
|
||||
err = db.TransformAndLogDbError("dashboard", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "dashboard", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/smtp"
|
||||
@@ -9,7 +10,7 @@ import (
|
||||
|
||||
type Mail interface {
|
||||
// Sending an email is a fire and forget operation. Thus no error handling
|
||||
SendMail(to string, subject string, message string)
|
||||
SendMail(ctx context.Context, to string, subject string, message string)
|
||||
}
|
||||
|
||||
type MailImpl struct {
|
||||
@@ -20,11 +21,11 @@ func NewMail(server *types.Settings) MailImpl {
|
||||
return MailImpl{server: server}
|
||||
}
|
||||
|
||||
func (m MailImpl) SendMail(to string, subject string, message string) {
|
||||
go m.internalSendMail(to, subject, message)
|
||||
func (m MailImpl) SendMail(ctx context.Context, to string, subject string, message string) {
|
||||
go m.internalSendMail(ctx, to, subject, message)
|
||||
}
|
||||
|
||||
func (m MailImpl) internalSendMail(to string, subject string, message string) {
|
||||
func (m MailImpl) internalSendMail(ctx context.Context, to string, subject string, message string) {
|
||||
if m.server.Smtp == nil {
|
||||
return
|
||||
}
|
||||
@@ -47,9 +48,9 @@ func (m MailImpl) internalSendMail(to string, subject string, message string) {
|
||||
subject,
|
||||
message)
|
||||
|
||||
slog.Info("sending mail", "to", to)
|
||||
slog.InfoContext(ctx, "sending mail", "to", to)
|
||||
err := smtp.SendMail(s.Host+":"+s.Port, auth, s.FromMail, []string{to}, []byte(msg))
|
||||
if err != nil {
|
||||
slog.Error("Error sending mail", "err", err)
|
||||
slog.ErrorContext(ctx, "Error sending mail", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"log/slog"
|
||||
@@ -10,9 +11,9 @@ import (
|
||||
)
|
||||
|
||||
type Random interface {
|
||||
Bytes(size int) ([]byte, error)
|
||||
String(size int) (string, error)
|
||||
UUID() (uuid.UUID, error)
|
||||
Bytes(ctx context.Context, size int) ([]byte, error)
|
||||
String(ctx context.Context, size int) (string, error)
|
||||
UUID(ctx context.Context) (uuid.UUID, error)
|
||||
}
|
||||
|
||||
type RandomImpl struct {
|
||||
@@ -22,31 +23,31 @@ func NewRandom() *RandomImpl {
|
||||
return &RandomImpl{}
|
||||
}
|
||||
|
||||
func (r *RandomImpl) Bytes(size int) ([]byte, error) {
|
||||
func (r *RandomImpl) Bytes(ctx context.Context, tsize int) ([]byte, error) {
|
||||
b := make([]byte, 32)
|
||||
_, err := rand.Read(b)
|
||||
if err != nil {
|
||||
slog.Error("Error generating random bytes", "err", err)
|
||||
slog.ErrorContext(ctx, "Error generating random bytes", "err", err)
|
||||
return []byte{}, types.ErrInternal
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (r *RandomImpl) String(size int) (string, error) {
|
||||
bytes, err := r.Bytes(size)
|
||||
func (r *RandomImpl) String(ctx context.Context, size int) (string, error) {
|
||||
bytes, err := r.Bytes(ctx, size)
|
||||
if err != nil {
|
||||
slog.Error("Error generating random string", "err", err)
|
||||
slog.ErrorContext(ctx, "Error generating random string", "err", err)
|
||||
return "", types.ErrInternal
|
||||
}
|
||||
|
||||
return base64.StdEncoding.EncodeToString(bytes), nil
|
||||
}
|
||||
|
||||
func (r *RandomImpl) UUID() (uuid.UUID, error) {
|
||||
func (r *RandomImpl) UUID(ctx context.Context) (uuid.UUID, error) {
|
||||
id, err := uuid.NewRandom()
|
||||
if err != nil {
|
||||
slog.Error("Error generating random UUID", "err", err)
|
||||
slog.ErrorContext(ctx, "Error generating random UUID", "err", err)
|
||||
return uuid.Nil, types.ErrInternal
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ func (s TransactionImpl) Add(ctx context.Context, tx *sqlx.Tx, user *types.User,
|
||||
if tx == nil {
|
||||
ownsTransaction = true
|
||||
tx, err = s.db.BeginTxx(ctx, nil)
|
||||
err = db.TransformAndLogDbError("transaction Add", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction Add", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -66,7 +66,7 @@ func (s TransactionImpl) Add(ctx context.Context, tx *sqlx.Tx, user *types.User,
|
||||
party, description, error, created_at, created_by)
|
||||
VALUES (:id, :user_id, :account_id, :treasure_chest_id, :value, :timestamp,
|
||||
:party, :description, :error, :created_at, :created_by)`, transaction)
|
||||
err = db.TransformAndLogDbError("transaction Insert", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction Insert", r, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -76,7 +76,7 @@ func (s TransactionImpl) Add(ctx context.Context, tx *sqlx.Tx, user *types.User,
|
||||
UPDATE account
|
||||
SET current_balance = current_balance + ?
|
||||
WHERE id = ? AND user_id = ?`, transaction.Value, transaction.AccountId, user.Id)
|
||||
err = db.TransformAndLogDbError("transaction Add", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction Add", r, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -87,7 +87,7 @@ func (s TransactionImpl) Add(ctx context.Context, tx *sqlx.Tx, user *types.User,
|
||||
UPDATE treasure_chest
|
||||
SET current_balance = current_balance + ?
|
||||
WHERE id = ? AND user_id = ?`, transaction.Value, transaction.TreasureChestId, user.Id)
|
||||
err = db.TransformAndLogDbError("transaction Add", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction Add", r, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -95,7 +95,7 @@ func (s TransactionImpl) Add(ctx context.Context, tx *sqlx.Tx, user *types.User,
|
||||
|
||||
if ownsTransaction {
|
||||
err = tx.Commit()
|
||||
err = db.TransformAndLogDbError("transaction Add", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction Add", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -110,7 +110,7 @@ func (s TransactionImpl) Update(ctx context.Context, user *types.User, input typ
|
||||
}
|
||||
|
||||
tx, err := s.db.BeginTxx(ctx, nil)
|
||||
err = db.TransformAndLogDbError("transaction Update", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction Update", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -120,7 +120,7 @@ func (s TransactionImpl) Update(ctx context.Context, user *types.User, input typ
|
||||
|
||||
transaction := &types.Transaction{}
|
||||
err = tx.GetContext(ctx, transaction, `SELECT * FROM "transaction" WHERE user_id = ? AND id = ?`, user.Id, input.Id)
|
||||
err = db.TransformAndLogDbError("transaction Update", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction Update", nil, err)
|
||||
if err != nil {
|
||||
if errors.Is(err, db.ErrNotFound) {
|
||||
return nil, fmt.Errorf("transaction %v not found: %w", input.Id, ErrBadRequest)
|
||||
@@ -133,7 +133,7 @@ func (s TransactionImpl) Update(ctx context.Context, user *types.User, input typ
|
||||
UPDATE account
|
||||
SET current_balance = current_balance - ?
|
||||
WHERE id = ? AND user_id = ?`, transaction.Value, transaction.AccountId, user.Id)
|
||||
err = db.TransformAndLogDbError("transaction Update", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction Update", r, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -143,7 +143,7 @@ func (s TransactionImpl) Update(ctx context.Context, user *types.User, input typ
|
||||
UPDATE treasure_chest
|
||||
SET current_balance = current_balance - ?
|
||||
WHERE id = ? AND user_id = ?`, transaction.Value, transaction.TreasureChestId, user.Id)
|
||||
err = db.TransformAndLogDbError("transaction Update", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction Update", r, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -159,7 +159,7 @@ func (s TransactionImpl) Update(ctx context.Context, user *types.User, input typ
|
||||
UPDATE account
|
||||
SET current_balance = current_balance + ?
|
||||
WHERE id = ? AND user_id = ?`, transaction.Value, transaction.AccountId, user.Id)
|
||||
err = db.TransformAndLogDbError("transaction Update", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction Update", r, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -169,7 +169,7 @@ func (s TransactionImpl) Update(ctx context.Context, user *types.User, input typ
|
||||
UPDATE treasure_chest
|
||||
SET current_balance = current_balance + ?
|
||||
WHERE id = ? AND user_id = ?`, transaction.Value, transaction.TreasureChestId, user.Id)
|
||||
err = db.TransformAndLogDbError("transaction Update", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction Update", r, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -189,13 +189,13 @@ func (s TransactionImpl) Update(ctx context.Context, user *types.User, input typ
|
||||
updated_by = :updated_by
|
||||
WHERE id = :id
|
||||
AND user_id = :user_id`, transaction)
|
||||
err = db.TransformAndLogDbError("transaction Update", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction Update", r, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
err = db.TransformAndLogDbError("transaction Update", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction Update", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -209,13 +209,13 @@ func (s TransactionImpl) Get(ctx context.Context, user *types.User, id string) (
|
||||
}
|
||||
uuid, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
slog.Error("transaction get", "err", err)
|
||||
slog.ErrorContext(ctx, "transaction get", "err", err)
|
||||
return nil, fmt.Errorf("could not parse Id: %w", ErrBadRequest)
|
||||
}
|
||||
|
||||
var transaction types.Transaction
|
||||
err = s.db.GetContext(ctx, &transaction, `SELECT * FROM "transaction" WHERE user_id = ? AND id = ?`, user.Id, uuid)
|
||||
err = db.TransformAndLogDbError("transaction Get", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction Get", nil, err)
|
||||
if err != nil {
|
||||
if errors.Is(err, db.ErrNotFound) {
|
||||
return nil, fmt.Errorf("transaction %v not found: %w", id, ErrBadRequest)
|
||||
@@ -247,7 +247,7 @@ func (s TransactionImpl) GetAll(ctx context.Context, user *types.User, filter ty
|
||||
filter.AccountId, filter.AccountId,
|
||||
filter.TreasureChestId, filter.TreasureChestId,
|
||||
filter.Error, filter.Error, filter.Error)
|
||||
err = db.TransformAndLogDbError("transaction GetAll", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction GetAll", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -261,12 +261,12 @@ func (s TransactionImpl) Delete(ctx context.Context, user *types.User, id string
|
||||
}
|
||||
uuid, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
slog.Error("transaction delete", "err", err)
|
||||
slog.ErrorContext(ctx, "transaction delete", "err", err)
|
||||
return fmt.Errorf("could not parse Id: %w", ErrBadRequest)
|
||||
}
|
||||
|
||||
tx, err := s.db.BeginTxx(ctx, nil)
|
||||
err = db.TransformAndLogDbError("transaction Delete", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction Delete", nil, err)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
@@ -276,7 +276,7 @@ func (s TransactionImpl) Delete(ctx context.Context, user *types.User, id string
|
||||
|
||||
var transaction types.Transaction
|
||||
err = tx.GetContext(ctx, &transaction, `SELECT * FROM "transaction" WHERE user_id = ? AND id = ?`, user.Id, uuid)
|
||||
err = db.TransformAndLogDbError("transaction Delete", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction Delete", nil, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -287,7 +287,7 @@ func (s TransactionImpl) Delete(ctx context.Context, user *types.User, id string
|
||||
SET current_balance = current_balance - ?
|
||||
WHERE id = ?
|
||||
AND user_id = ?`, transaction.Value, transaction.AccountId, user.Id)
|
||||
err = db.TransformAndLogDbError("transaction Delete", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction Delete", r, err)
|
||||
if err != nil && !errors.Is(err, db.ErrNotFound) {
|
||||
return err
|
||||
}
|
||||
@@ -299,20 +299,20 @@ func (s TransactionImpl) Delete(ctx context.Context, user *types.User, id string
|
||||
SET current_balance = current_balance - ?
|
||||
WHERE id = ?
|
||||
AND user_id = ?`, transaction.Value, transaction.TreasureChestId, user.Id)
|
||||
err = db.TransformAndLogDbError("transaction Delete", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction Delete", r, err)
|
||||
if err != nil && !errors.Is(err, db.ErrNotFound) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
r, err := tx.ExecContext(ctx, "DELETE FROM \"transaction\" WHERE id = ? AND user_id = ?", uuid, user.Id)
|
||||
err = db.TransformAndLogDbError("transaction Delete", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction Delete", r, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
err = db.TransformAndLogDbError("transaction Delete", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction Delete", nil, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -326,7 +326,7 @@ func (s TransactionImpl) RecalculateBalances(ctx context.Context, user *types.Us
|
||||
}
|
||||
|
||||
tx, err := s.db.BeginTxx(ctx, nil)
|
||||
err = db.TransformAndLogDbError("transaction RecalculateBalances", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction RecalculateBalances", nil, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -338,7 +338,7 @@ func (s TransactionImpl) RecalculateBalances(ctx context.Context, user *types.Us
|
||||
UPDATE account
|
||||
SET current_balance = 0
|
||||
WHERE user_id = ?`, user.Id)
|
||||
err = db.TransformAndLogDbError("transaction RecalculateBalances", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction RecalculateBalances", r, err)
|
||||
if err != nil && !errors.Is(err, db.ErrNotFound) {
|
||||
return err
|
||||
}
|
||||
@@ -347,7 +347,7 @@ func (s TransactionImpl) RecalculateBalances(ctx context.Context, user *types.Us
|
||||
UPDATE treasure_chest
|
||||
SET current_balance = 0
|
||||
WHERE user_id = ?`, user.Id)
|
||||
err = db.TransformAndLogDbError("transaction RecalculateBalances", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction RecalculateBalances", r, err)
|
||||
if err != nil && !errors.Is(err, db.ErrNotFound) {
|
||||
return err
|
||||
}
|
||||
@@ -356,21 +356,21 @@ func (s TransactionImpl) RecalculateBalances(ctx context.Context, user *types.Us
|
||||
SELECT *
|
||||
FROM "transaction"
|
||||
WHERE user_id = ?`, user.Id)
|
||||
err = db.TransformAndLogDbError("transaction RecalculateBalances", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction RecalculateBalances", nil, err)
|
||||
if err != nil && !errors.Is(err, db.ErrNotFound) {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
err := rows.Close()
|
||||
if err != nil {
|
||||
slog.Error("transaction RecalculateBalances", "err", err)
|
||||
slog.ErrorContext(ctx, "transaction RecalculateBalances", "err", err)
|
||||
}
|
||||
}()
|
||||
|
||||
var transaction types.Transaction
|
||||
for rows.Next() {
|
||||
err = rows.StructScan(&transaction)
|
||||
err = db.TransformAndLogDbError("transaction RecalculateBalances", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction RecalculateBalances", nil, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -381,7 +381,7 @@ func (s TransactionImpl) RecalculateBalances(ctx context.Context, user *types.Us
|
||||
SET error = ?
|
||||
WHERE user_id = ?
|
||||
AND id = ?`, transaction.Error, user.Id, transaction.Id)
|
||||
err = db.TransformAndLogDbError("transaction RecalculateBalances", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction RecalculateBalances", r, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -395,7 +395,7 @@ func (s TransactionImpl) RecalculateBalances(ctx context.Context, user *types.Us
|
||||
UPDATE account
|
||||
SET current_balance = current_balance + ?
|
||||
WHERE id = ? AND user_id = ?`, transaction.Value, transaction.AccountId, user.Id)
|
||||
err = db.TransformAndLogDbError("transaction RecalculateBalances", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction RecalculateBalances", r, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -405,7 +405,7 @@ func (s TransactionImpl) RecalculateBalances(ctx context.Context, user *types.Us
|
||||
UPDATE treasure_chest
|
||||
SET current_balance = current_balance + ?
|
||||
WHERE id = ? AND user_id = ?`, transaction.Value, transaction.TreasureChestId, user.Id)
|
||||
err = db.TransformAndLogDbError("transaction RecalculateBalances", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction RecalculateBalances", r, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -413,7 +413,7 @@ func (s TransactionImpl) RecalculateBalances(ctx context.Context, user *types.Us
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
err = db.TransformAndLogDbError("transaction RecalculateBalances", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction RecalculateBalances", nil, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -434,7 +434,7 @@ func (s TransactionImpl) validateAndEnrichTransaction(ctx context.Context, tx *s
|
||||
)
|
||||
|
||||
if oldTransaction == nil {
|
||||
id, err = s.random.UUID()
|
||||
id, err = s.random.UUID(ctx)
|
||||
if err != nil {
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
@@ -451,12 +451,12 @@ func (s TransactionImpl) validateAndEnrichTransaction(ctx context.Context, tx *s
|
||||
|
||||
if input.AccountId != nil {
|
||||
err = tx.GetContext(ctx, &rowCount, `SELECT COUNT(*) FROM account WHERE id = ? AND user_id = ?`, input.AccountId, userId)
|
||||
err = db.TransformAndLogDbError("transaction validate", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction validate", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if rowCount == 0 {
|
||||
slog.Error("transaction validate", "err", err)
|
||||
slog.ErrorContext(ctx, "transaction validate", "err", err)
|
||||
return nil, fmt.Errorf("account not found: %w", ErrBadRequest)
|
||||
}
|
||||
}
|
||||
@@ -464,7 +464,7 @@ func (s TransactionImpl) validateAndEnrichTransaction(ctx context.Context, tx *s
|
||||
if input.TreasureChestId != nil {
|
||||
var treasureChest types.TreasureChest
|
||||
err = tx.GetContext(ctx, &treasureChest, `SELECT * FROM treasure_chest WHERE id = ? AND user_id = ?`, input.TreasureChestId, userId)
|
||||
err = db.TransformAndLogDbError("transaction validate", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transaction validate", nil, err)
|
||||
if err != nil {
|
||||
if errors.Is(err, db.ErrNotFound) {
|
||||
return nil, fmt.Errorf("treasure chest not found: %w", ErrBadRequest)
|
||||
|
||||
@@ -51,7 +51,7 @@ func (s TransactionRecurringImpl) Add(ctx context.Context,
|
||||
}
|
||||
|
||||
tx, err := s.db.BeginTxx(ctx, nil)
|
||||
err = db.TransformAndLogDbError("transactionRecurring Add", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring Add", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -70,13 +70,13 @@ func (s TransactionRecurringImpl) Add(ctx context.Context,
|
||||
VALUES (:id, :user_id, :interval_months,
|
||||
:next_execution, :party, :description, :account_id, :treasure_chest_id, :value, :created_at, :created_by)`,
|
||||
transactionRecurring)
|
||||
err = db.TransformAndLogDbError("transactionRecurring Insert", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring Insert", r, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
err = db.TransformAndLogDbError("transactionRecurring Add", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring Add", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -93,12 +93,12 @@ func (s TransactionRecurringImpl) Update(ctx context.Context,
|
||||
}
|
||||
uuid, err := uuid.Parse(input.Id)
|
||||
if err != nil {
|
||||
slog.Error("transactionRecurring update", "err", err)
|
||||
slog.ErrorContext(ctx, "transactionRecurring update", "err", err)
|
||||
return nil, fmt.Errorf("could not parse Id: %w", ErrBadRequest)
|
||||
}
|
||||
|
||||
tx, err := s.db.BeginTxx(ctx, nil)
|
||||
err = db.TransformAndLogDbError("transactionRecurring Update", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring Update", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -108,7 +108,7 @@ func (s TransactionRecurringImpl) Update(ctx context.Context,
|
||||
|
||||
transactionRecurring := &types.TransactionRecurring{}
|
||||
err = tx.GetContext(ctx, transactionRecurring, `SELECT * FROM transaction_recurring WHERE user_id = ? AND id = ?`, user.Id, uuid)
|
||||
err = db.TransformAndLogDbError("transactionRecurring Update", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring Update", nil, err)
|
||||
if err != nil {
|
||||
if errors.Is(err, db.ErrNotFound) {
|
||||
return nil, fmt.Errorf("transactionRecurring %v not found: %w", input.Id, ErrBadRequest)
|
||||
@@ -135,13 +135,13 @@ func (s TransactionRecurringImpl) Update(ctx context.Context,
|
||||
updated_by = :updated_by
|
||||
WHERE id = :id
|
||||
AND user_id = :user_id`, transactionRecurring)
|
||||
err = db.TransformAndLogDbError("transactionRecurring Update", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring Update", r, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
err = db.TransformAndLogDbError("transactionRecurring Update", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring Update", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -161,7 +161,7 @@ func (s TransactionRecurringImpl) GetAll(ctx context.Context, user *types.User)
|
||||
WHERE user_id = ?
|
||||
ORDER BY created_at DESC`,
|
||||
user.Id)
|
||||
err = db.TransformAndLogDbError("transactionRecurring GetAll", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring GetAll", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -176,12 +176,12 @@ func (s TransactionRecurringImpl) GetAllByAccount(ctx context.Context, user *typ
|
||||
|
||||
accountUuid, err := uuid.Parse(accountId)
|
||||
if err != nil {
|
||||
slog.Error("transactionRecurring GetAllByAccount", "err", err)
|
||||
slog.ErrorContext(ctx, "transactionRecurring GetAllByAccount", "err", err)
|
||||
return nil, fmt.Errorf("could not parse accountId: %w", ErrBadRequest)
|
||||
}
|
||||
|
||||
tx, err := s.db.BeginTxx(ctx, nil)
|
||||
err = db.TransformAndLogDbError("transactionRecurring GetAllByAccount", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring GetAllByAccount", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -191,7 +191,7 @@ func (s TransactionRecurringImpl) GetAllByAccount(ctx context.Context, user *typ
|
||||
|
||||
var rowCount int
|
||||
err = tx.GetContext(ctx, &rowCount, `SELECT COUNT(*) FROM account WHERE id = ? AND user_id = ?`, accountUuid, user.Id)
|
||||
err = db.TransformAndLogDbError("transactionRecurring GetAllByAccount", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring GetAllByAccount", nil, err)
|
||||
if err != nil {
|
||||
if errors.Is(err, db.ErrNotFound) {
|
||||
return nil, fmt.Errorf("account %v not found: %w", accountId, ErrBadRequest)
|
||||
@@ -207,13 +207,13 @@ func (s TransactionRecurringImpl) GetAllByAccount(ctx context.Context, user *typ
|
||||
AND account_id = ?
|
||||
ORDER BY created_at DESC`,
|
||||
user.Id, accountUuid)
|
||||
err = db.TransformAndLogDbError("transactionRecurring GetAll", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring GetAll", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
err = db.TransformAndLogDbError("transactionRecurring GetAllByAccount", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring GetAllByAccount", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -231,12 +231,12 @@ func (s TransactionRecurringImpl) GetAllByTreasureChest(ctx context.Context,
|
||||
|
||||
treasureChestUuid, err := uuid.Parse(treasureChestId)
|
||||
if err != nil {
|
||||
slog.Error("transactionRecurring GetAllByTreasureChest", "err", err)
|
||||
slog.ErrorContext(ctx, "transactionRecurring GetAllByTreasureChest", "err", err)
|
||||
return nil, fmt.Errorf("could not parse treasureChestId: %w", ErrBadRequest)
|
||||
}
|
||||
|
||||
tx, err := s.db.BeginTxx(ctx, nil)
|
||||
err = db.TransformAndLogDbError("transactionRecurring GetAllByTreasureChest", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring GetAllByTreasureChest", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -246,7 +246,7 @@ func (s TransactionRecurringImpl) GetAllByTreasureChest(ctx context.Context,
|
||||
|
||||
var rowCount int
|
||||
err = tx.GetContext(ctx, &rowCount, `SELECT COUNT(*) FROM treasure_chest WHERE id = ? AND user_id = ?`, treasureChestId, user.Id)
|
||||
err = db.TransformAndLogDbError("transactionRecurring GetAllByTreasureChest", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring GetAllByTreasureChest", nil, err)
|
||||
if err != nil {
|
||||
if errors.Is(err, db.ErrNotFound) {
|
||||
return nil, fmt.Errorf("treasurechest %v not found: %w", treasureChestId, ErrBadRequest)
|
||||
@@ -262,13 +262,13 @@ func (s TransactionRecurringImpl) GetAllByTreasureChest(ctx context.Context,
|
||||
AND treasure_chest_id = ?
|
||||
ORDER BY created_at DESC`,
|
||||
user.Id, treasureChestUuid)
|
||||
err = db.TransformAndLogDbError("transactionRecurring GetAll", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring GetAll", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
err = db.TransformAndLogDbError("transactionRecurring GetAllByTreasureChest", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring GetAllByTreasureChest", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -282,12 +282,12 @@ func (s TransactionRecurringImpl) Delete(ctx context.Context, user *types.User,
|
||||
}
|
||||
uuid, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
slog.Error("transactionRecurring delete", "err", err)
|
||||
slog.ErrorContext(ctx, "transactionRecurring delete", "err", err)
|
||||
return fmt.Errorf("could not parse Id: %w", ErrBadRequest)
|
||||
}
|
||||
|
||||
tx, err := s.db.BeginTxx(ctx, nil)
|
||||
err = db.TransformAndLogDbError("transactionRecurring Delete", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring Delete", nil, err)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
@@ -297,19 +297,19 @@ func (s TransactionRecurringImpl) Delete(ctx context.Context, user *types.User,
|
||||
|
||||
var transactionRecurring types.TransactionRecurring
|
||||
err = tx.GetContext(ctx, &transactionRecurring, `SELECT * FROM transaction_recurring WHERE user_id = ? AND id = ?`, user.Id, uuid)
|
||||
err = db.TransformAndLogDbError("transactionRecurring Delete", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring Delete", nil, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r, err := tx.ExecContext(ctx, "DELETE FROM transaction_recurring WHERE id = ? AND user_id = ?", uuid, user.Id)
|
||||
err = db.TransformAndLogDbError("transactionRecurring Delete", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring Delete", r, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
err = db.TransformAndLogDbError("transactionRecurring Delete", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring Delete", nil, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -321,7 +321,7 @@ func (s TransactionRecurringImpl) GenerateTransactions(ctx context.Context) erro
|
||||
now := s.clock.Now()
|
||||
|
||||
tx, err := s.db.BeginTxx(ctx, nil)
|
||||
err = db.TransformAndLogDbError("transactionRecurring GenerateTransactions", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring GenerateTransactions", nil, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -333,7 +333,7 @@ func (s TransactionRecurringImpl) GenerateTransactions(ctx context.Context) erro
|
||||
err = tx.SelectContext(ctx, &recurringTransactions, `
|
||||
SELECT * FROM transaction_recurring WHERE next_execution <= ?`,
|
||||
now)
|
||||
err = db.TransformAndLogDbError("transactionRecurring GenerateTransactions", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring GenerateTransactions", nil, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -359,14 +359,14 @@ func (s TransactionRecurringImpl) GenerateTransactions(ctx context.Context) erro
|
||||
nextExecution := transactionRecurring.NextExecution.AddDate(0, int(transactionRecurring.IntervalMonths), 0)
|
||||
r, err := tx.ExecContext(ctx, `UPDATE transaction_recurring SET next_execution = ? WHERE id = ? AND user_id = ?`,
|
||||
nextExecution, transactionRecurring.Id, user.Id)
|
||||
err = db.TransformAndLogDbError("transactionRecurring GenerateTransactions", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring GenerateTransactions", r, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
err = db.TransformAndLogDbError("transactionRecurring GenerateTransactions", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring GenerateTransactions", nil, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -395,7 +395,7 @@ func (s TransactionRecurringImpl) validateAndEnrichTransactionRecurring(
|
||||
)
|
||||
|
||||
if oldTransactionRecurring == nil {
|
||||
id, err = s.random.UUID()
|
||||
id, err = s.random.UUID(ctx)
|
||||
if err != nil {
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
@@ -415,17 +415,17 @@ func (s TransactionRecurringImpl) validateAndEnrichTransactionRecurring(
|
||||
if input.AccountId != "" {
|
||||
temp, err := uuid.Parse(input.AccountId)
|
||||
if err != nil {
|
||||
slog.Error("transactionRecurring validate", "err", err)
|
||||
slog.ErrorContext(ctx, "transactionRecurring validate", "err", err)
|
||||
return nil, fmt.Errorf("could not parse accountId: %w", ErrBadRequest)
|
||||
}
|
||||
accountUuid = &temp
|
||||
err = tx.GetContext(ctx, &rowCount, `SELECT COUNT(*) FROM account WHERE id = ? AND user_id = ?`, accountUuid, userId)
|
||||
err = db.TransformAndLogDbError("transactionRecurring validate", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring validate", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if rowCount == 0 {
|
||||
slog.Error("transactionRecurring validate", "err", err)
|
||||
slog.ErrorContext(ctx, "transactionRecurring validate", "err", err)
|
||||
return nil, fmt.Errorf("account not found: %w", ErrBadRequest)
|
||||
}
|
||||
|
||||
@@ -435,13 +435,13 @@ func (s TransactionRecurringImpl) validateAndEnrichTransactionRecurring(
|
||||
if input.TreasureChestId != "" {
|
||||
temp, err := uuid.Parse(input.TreasureChestId)
|
||||
if err != nil {
|
||||
slog.Error("transactionRecurring validate", "err", err)
|
||||
slog.ErrorContext(ctx, "transactionRecurring validate", "err", err)
|
||||
return nil, fmt.Errorf("could not parse treasureChestId: %w", ErrBadRequest)
|
||||
}
|
||||
treasureChestUuid = &temp
|
||||
var treasureChest types.TreasureChest
|
||||
err = tx.GetContext(ctx, &treasureChest, `SELECT * FROM treasure_chest WHERE id = ? AND user_id = ?`, treasureChestUuid, userId)
|
||||
err = db.TransformAndLogDbError("transactionRecurring validate", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "transactionRecurring validate", nil, err)
|
||||
if err != nil {
|
||||
if errors.Is(err, db.ErrNotFound) {
|
||||
return nil, fmt.Errorf("treasure chest not found: %w", ErrBadRequest)
|
||||
@@ -455,17 +455,17 @@ func (s TransactionRecurringImpl) validateAndEnrichTransactionRecurring(
|
||||
}
|
||||
|
||||
if !hasAccount && !hasTreasureChest {
|
||||
slog.Error("transactionRecurring validate", "err", err)
|
||||
slog.ErrorContext(ctx, "transactionRecurring validate", "err", err)
|
||||
return nil, fmt.Errorf("either account or treasure chest is required: %w", ErrBadRequest)
|
||||
}
|
||||
if hasAccount && hasTreasureChest {
|
||||
slog.Error("transactionRecurring validate", "err", err)
|
||||
slog.ErrorContext(ctx, "transactionRecurring validate", "err", err)
|
||||
return nil, fmt.Errorf("either account or treasure chest is required, not both: %w", ErrBadRequest)
|
||||
}
|
||||
|
||||
valueFloat, err := strconv.ParseFloat(input.Value, 64)
|
||||
if err != nil {
|
||||
slog.Error("transactionRecurring validate", "err", err)
|
||||
slog.ErrorContext(ctx, "transactionRecurring validate", "err", err)
|
||||
return nil, fmt.Errorf("could not parse value: %w", ErrBadRequest)
|
||||
}
|
||||
value := int64(math.Round(valueFloat * DECIMALS_MULTIPLIER))
|
||||
@@ -484,18 +484,18 @@ func (s TransactionRecurringImpl) validateAndEnrichTransactionRecurring(
|
||||
}
|
||||
intervalMonths, err = strconv.ParseInt(input.IntervalMonths, 10, 0)
|
||||
if err != nil {
|
||||
slog.Error("transactionRecurring validate", "err", err)
|
||||
slog.ErrorContext(ctx, "transactionRecurring validate", "err", err)
|
||||
return nil, fmt.Errorf("could not parse intervalMonths: %w", ErrBadRequest)
|
||||
}
|
||||
if intervalMonths < 1 {
|
||||
slog.Error("transactionRecurring validate", "err", err)
|
||||
slog.ErrorContext(ctx, "transactionRecurring validate", "err", err)
|
||||
return nil, fmt.Errorf("intervalMonths needs to be greater than 0: %w", ErrBadRequest)
|
||||
}
|
||||
var nextExecution *time.Time = nil
|
||||
if input.NextExecution != "" {
|
||||
t, err := time.Parse("2006-01-02", input.NextExecution)
|
||||
if err != nil {
|
||||
slog.Error("transaction validate", "err", err)
|
||||
slog.ErrorContext(ctx, "transaction validate", "err", err)
|
||||
return nil, fmt.Errorf("could not parse timestamp: %w", ErrBadRequest)
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ func (s TreasureChestImpl) Add(ctx context.Context, user *types.User, parentId,
|
||||
return nil, ErrUnauthorized
|
||||
}
|
||||
|
||||
newId, err := s.random.UUID()
|
||||
newId, err := s.random.UUID(ctx)
|
||||
if err != nil {
|
||||
return nil, types.ErrInternal
|
||||
}
|
||||
@@ -80,7 +80,7 @@ func (s TreasureChestImpl) Add(ctx context.Context, user *types.User, parentId,
|
||||
r, err := s.db.NamedExecContext(ctx, `
|
||||
INSERT INTO treasure_chest (id, parent_id, user_id, name, current_balance, created_at, created_by)
|
||||
VALUES (:id, :parent_id, :user_id, :name, :current_balance, :created_at, :created_by)`, treasureChest)
|
||||
err = db.TransformAndLogDbError("treasureChest Insert", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "treasureChest Insert", r, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -98,12 +98,12 @@ func (s TreasureChestImpl) Update(ctx context.Context, user *types.User, idStr,
|
||||
}
|
||||
id, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
slog.Error("treasureChest update", "err", err)
|
||||
slog.ErrorContext(ctx, "treasureChest update", "err", err)
|
||||
return nil, fmt.Errorf("could not parse Id: %w", ErrBadRequest)
|
||||
}
|
||||
|
||||
tx, err := s.db.BeginTxx(ctx, nil)
|
||||
err = db.TransformAndLogDbError("treasureChest Update", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "treasureChest Update", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -113,7 +113,7 @@ func (s TreasureChestImpl) Update(ctx context.Context, user *types.User, idStr,
|
||||
|
||||
treasureChest := &types.TreasureChest{}
|
||||
err = tx.GetContext(ctx, treasureChest, `SELECT * FROM treasure_chest WHERE user_id = ? AND id = ?`, user.Id, id)
|
||||
err = db.TransformAndLogDbError("treasureChest Update", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "treasureChest Update", nil, err)
|
||||
if err != nil {
|
||||
if errors.Is(err, db.ErrNotFound) {
|
||||
return nil, fmt.Errorf("treasureChest %v not found: %w", idStr, err)
|
||||
@@ -129,7 +129,7 @@ func (s TreasureChestImpl) Update(ctx context.Context, user *types.User, idStr,
|
||||
}
|
||||
var childCount int
|
||||
err = tx.GetContext(ctx, &childCount, `SELECT COUNT(*) FROM treasure_chest WHERE user_id = ? AND parent_id = ?`, user.Id, id)
|
||||
err = db.TransformAndLogDbError("treasureChest Update", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "treasureChest Update", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -156,13 +156,13 @@ func (s TreasureChestImpl) Update(ctx context.Context, user *types.User, idStr,
|
||||
updated_by = :updated_by
|
||||
WHERE id = :id
|
||||
AND user_id = :user_id`, treasureChest)
|
||||
err = db.TransformAndLogDbError("treasureChest Update", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "treasureChest Update", r, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
err = db.TransformAndLogDbError("treasureChest Update", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "treasureChest Update", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -176,13 +176,13 @@ func (s TreasureChestImpl) Get(ctx context.Context, user *types.User, id string)
|
||||
}
|
||||
uuid, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
slog.Error("treasureChest get", "err", err)
|
||||
slog.ErrorContext(ctx, "treasureChest get", "err", err)
|
||||
return nil, fmt.Errorf("could not parse Id: %w", ErrBadRequest)
|
||||
}
|
||||
|
||||
var treasureChest types.TreasureChest
|
||||
err = s.db.GetContext(ctx, &treasureChest, `SELECT * FROM treasure_chest WHERE user_id = ? AND id = ?`, user.Id, uuid)
|
||||
err = db.TransformAndLogDbError("treasureChest Get", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "treasureChest Get", nil, err)
|
||||
if err != nil {
|
||||
if errors.Is(err, db.ErrNotFound) {
|
||||
return nil, fmt.Errorf("treasureChest %v not found: %w", id, err)
|
||||
@@ -200,7 +200,7 @@ func (s TreasureChestImpl) GetAll(ctx context.Context, user *types.User) ([]*typ
|
||||
|
||||
treasureChests := make([]*types.TreasureChest, 0)
|
||||
err := s.db.SelectContext(ctx, &treasureChests, `SELECT * FROM treasure_chest WHERE user_id = ?`, user.Id)
|
||||
err = db.TransformAndLogDbError("treasureChest GetAll", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "treasureChest GetAll", nil, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -214,12 +214,12 @@ func (s TreasureChestImpl) Delete(ctx context.Context, user *types.User, idStr s
|
||||
}
|
||||
id, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
slog.Error("treasureChest delete", "err", err)
|
||||
slog.ErrorContext(ctx, "treasureChest delete", "err", err)
|
||||
return fmt.Errorf("could not parse Id: %w", ErrBadRequest)
|
||||
}
|
||||
|
||||
tx, err := s.db.BeginTxx(ctx, nil)
|
||||
err = db.TransformAndLogDbError("treasureChest Delete", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "treasureChest Delete", nil, err)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
@@ -229,7 +229,7 @@ func (s TreasureChestImpl) Delete(ctx context.Context, user *types.User, idStr s
|
||||
|
||||
childCount := 0
|
||||
err = tx.GetContext(ctx, &childCount, `SELECT COUNT(*) FROM treasure_chest WHERE user_id = ? AND parent_id = ?`, user.Id, id)
|
||||
err = db.TransformAndLogDbError("treasureChest Delete", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "treasureChest Delete", nil, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -242,7 +242,7 @@ func (s TreasureChestImpl) Delete(ctx context.Context, user *types.User, idStr s
|
||||
err = tx.GetContext(ctx, &transactionsCount,
|
||||
`SELECT COUNT(*) FROM "transaction" WHERE user_id = ? AND treasure_chest_id = ?`,
|
||||
user.Id, id)
|
||||
err = db.TransformAndLogDbError("treasureChest Delete", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "treasureChest Delete", nil, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -254,7 +254,7 @@ func (s TreasureChestImpl) Delete(ctx context.Context, user *types.User, idStr s
|
||||
err = tx.GetContext(ctx, &recurringCount, `
|
||||
SELECT COUNT(*) FROM transaction_recurring WHERE user_id = ? AND treasure_chest_id = ?`,
|
||||
user.Id, id)
|
||||
err = db.TransformAndLogDbError("treasureChest Delete", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "treasureChest Delete", nil, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -263,13 +263,13 @@ func (s TreasureChestImpl) Delete(ctx context.Context, user *types.User, idStr s
|
||||
}
|
||||
|
||||
r, err := tx.ExecContext(ctx, `DELETE FROM treasure_chest WHERE id = ? AND user_id = ?`, id, user.Id)
|
||||
err = db.TransformAndLogDbError("treasureChest Delete", r, err)
|
||||
err = db.TransformAndLogDbError(ctx, "treasureChest Delete", r, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
err = db.TransformAndLogDbError("treasureChest Delete", nil, err)
|
||||
err = db.TransformAndLogDbError(ctx, "treasureChest Delete", nil, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"log/slog"
|
||||
)
|
||||
@@ -26,13 +27,13 @@ type SmtpSettings struct {
|
||||
FromName string
|
||||
}
|
||||
|
||||
func NewSettingsFromEnv(env func(string) string) (*Settings, error) {
|
||||
func NewSettingsFromEnv(ctx context.Context, env func(string) string) (*Settings, error) {
|
||||
var (
|
||||
smtp *SmtpSettings
|
||||
err error
|
||||
)
|
||||
if env("SMTP_ENABLED") == "true" {
|
||||
smtp, err = getSmtpSettings(env)
|
||||
smtp, err = getSmtpSettings(ctx, env)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -46,26 +47,26 @@ func NewSettingsFromEnv(env func(string) string) (*Settings, error) {
|
||||
}
|
||||
|
||||
if settings.BaseUrl == "" {
|
||||
slog.Error("BASE_URL must be set")
|
||||
slog.ErrorContext(ctx, "BASE_URL must be set")
|
||||
return nil, ErrMissingConfig
|
||||
}
|
||||
if settings.Port == "" {
|
||||
slog.Error("PORT must be set")
|
||||
slog.ErrorContext(ctx, "PORT must be set")
|
||||
return nil, ErrMissingConfig
|
||||
}
|
||||
if settings.Environment == "" {
|
||||
slog.Error("ENVIRONMENT must be set")
|
||||
slog.ErrorContext(ctx, "ENVIRONMENT must be set")
|
||||
return nil, ErrMissingConfig
|
||||
}
|
||||
|
||||
slog.Info("settings read", "BASE_URL", settings.BaseUrl)
|
||||
slog.Info("settings read", "ENVIRONMENT", settings.Environment)
|
||||
slog.Info("settings read", "ENVIRONMENT", settings.Environment)
|
||||
slog.InfoContext(ctx, "settings read", "BASE_URL", settings.BaseUrl)
|
||||
slog.InfoContext(ctx, "settings read", "ENVIRONMENT", settings.Environment)
|
||||
slog.InfoContext(ctx, "settings read", "ENVIRONMENT", settings.Environment)
|
||||
|
||||
return settings, nil
|
||||
}
|
||||
|
||||
func getSmtpSettings(env func(string) string) (*SmtpSettings, error) {
|
||||
func getSmtpSettings(ctx context.Context, env func(string) string) (*SmtpSettings, error) {
|
||||
smtp := SmtpSettings{
|
||||
Host: env("SMTP_HOST"),
|
||||
Port: env("SMTP_PORT"),
|
||||
@@ -76,27 +77,27 @@ func getSmtpSettings(env func(string) string) (*SmtpSettings, error) {
|
||||
}
|
||||
|
||||
if smtp.Host == "" {
|
||||
slog.Error("SMTP_HOST must be set")
|
||||
slog.ErrorContext(ctx, "SMTP_HOST must be set")
|
||||
return nil, ErrMissingConfig
|
||||
}
|
||||
if smtp.Port == "" {
|
||||
slog.Error("SMTP_PORT must be set")
|
||||
slog.ErrorContext(ctx, "SMTP_PORT must be set")
|
||||
return nil, ErrMissingConfig
|
||||
}
|
||||
if smtp.User == "" {
|
||||
slog.Error("SMTP_USER must be set")
|
||||
slog.ErrorContext(ctx, "SMTP_USER must be set")
|
||||
return nil, ErrMissingConfig
|
||||
}
|
||||
if smtp.Pass == "" {
|
||||
slog.Error("SMTP_PASS must be set")
|
||||
slog.ErrorContext(ctx, "SMTP_PASS must be set")
|
||||
return nil, ErrMissingConfig
|
||||
}
|
||||
if smtp.FromMail == "" {
|
||||
slog.Error("SMTP_FROM_MAIL must be set")
|
||||
slog.ErrorContext(ctx, "SMTP_FROM_MAIL must be set")
|
||||
return nil, ErrMissingConfig
|
||||
}
|
||||
if smtp.FromName == "" {
|
||||
slog.Error("SMTP_FROM_NAME must be set")
|
||||
slog.ErrorContext(ctx, "SMTP_FROM_NAME must be set")
|
||||
return nil, ErrMissingConfig
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
@@ -8,16 +9,16 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func TriggerToast(w http.ResponseWriter, r *http.Request, class string, message string) {
|
||||
func TriggerToast(ctx context.Context, w http.ResponseWriter, r *http.Request, class string, message string) {
|
||||
if IsHtmx(r) {
|
||||
w.Header().Set("Hx-Trigger", fmt.Sprintf(`{"toast": "%v|%v"}`, class, strings.ReplaceAll(message, `"`, `\"`)))
|
||||
} else {
|
||||
slog.Error("Trying to trigger toast in non-HTMX request")
|
||||
slog.ErrorContext(ctx, "Trying to trigger toast in non-HTMX request")
|
||||
}
|
||||
}
|
||||
|
||||
func TriggerToastWithStatus(w http.ResponseWriter, r *http.Request, class string, message string, statusCode int) {
|
||||
TriggerToast(w, r, class, message)
|
||||
func TriggerToastWithStatus(ctx context.Context, w http.ResponseWriter, r *http.Request, class string, message string, statusCode int) {
|
||||
TriggerToast(ctx, w, r, class, message)
|
||||
w.WriteHeader(statusCode)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user