From da3b2a5a6e345692962f5daac68061ed67e90a48 Mon Sep 17 00:00:00 2001 From: Robin Dittmar Date: Sat, 29 Aug 2026 17:37:52 +0200 Subject: [PATCH] feat: change password now requires old/current password --- internal/api/handler/user.go | 10 +++++++++- internal/api/request/user.go | 3 ++- internal/domain/auth.go | 4 ++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/internal/api/handler/user.go b/internal/api/handler/user.go index 6df0278..8b49bb2 100644 --- a/internal/api/handler/user.go +++ b/internal/api/handler/user.go @@ -61,6 +61,7 @@ func (h *UserHandler) CreateUser(w http.ResponseWriter, r *http.Request) { // @Param payload body request.ChangePasswordPayload true "Change password payload" // @Success 204 // @Error 400 {object} response.ErrorResponse "failed to decode request body" +// @Error 401 {object} response.ErrorResponse "could not authenticate with current password" // @Error 500 {object} response.ErrorResponse "could not get auth context" // @Error 500 {object} response.ErrorResponse "failed to change password" // @Router /users/password [post] @@ -81,7 +82,14 @@ func (h *UserHandler) ChangePassword(w http.ResponseWriter, r *http.Request) { return } - err = h.UserService.ChangePassword(ctx, authContext.UserID, payload.Password) + _, err = h.AuthService.Authenticate(ctx, authContext.Email, payload.OldPassword) + if err != nil { + slog.ErrorContext(ctx, "failed to authenticate with current password", slog.Any("error", err)) + response.Error(ctx, w, http.StatusUnauthorized, "could not authenticate with current password") + return + } + + err = h.UserService.ChangePassword(ctx, authContext.UserID, payload.NewPassword) if err != nil { slog.ErrorContext(ctx, "failed to change password", slog.Any("error", err)) response.Error(ctx, w, http.StatusInternalServerError, "failed to change password") diff --git a/internal/api/request/user.go b/internal/api/request/user.go index 90a97e9..fef44d6 100644 --- a/internal/api/request/user.go +++ b/internal/api/request/user.go @@ -7,5 +7,6 @@ type CreateUserPayload struct { } type ChangePasswordPayload struct { - Password string `json:"password"` + OldPassword string `json:"old_password"` + NewPassword string `json:"new_password"` } diff --git a/internal/domain/auth.go b/internal/domain/auth.go index eb86bc5..ba5d141 100644 --- a/internal/domain/auth.go +++ b/internal/domain/auth.go @@ -62,7 +62,7 @@ func NewAuthService(r AuthRepository, jwtSecret []byte) *AuthService { return &AuthService{repo: r, jwtSecret: jwtSecret} } -func (s *AuthService) authenticate(ctx context.Context, email string, password string) (*AuthUser, error) { +func (s *AuthService) Authenticate(ctx context.Context, email string, password string) (*AuthUser, error) { user, err := s.repo.GetUserByEmail(ctx, email) if err != nil { return user, err @@ -80,7 +80,7 @@ func (s *AuthService) authenticate(ctx context.Context, email string, password s } func (s *AuthService) Login(ctx context.Context, email string, password string) (TokenPair, error) { - user, err := s.authenticate(ctx, email, password) + user, err := s.Authenticate(ctx, email, password) if err != nil { return TokenPair{}, err }