diff --git a/internal/api/handler/list.go b/internal/api/handler/list.go index 0732f34..cf025e1 100644 --- a/internal/api/handler/list.go +++ b/internal/api/handler/list.go @@ -11,6 +11,7 @@ import ( type ListHandler struct { ListService *domain.ListService + UserService *domain.UserService } func NewListHandler(listService *domain.ListService) *ListHandler { @@ -99,6 +100,7 @@ func (h *ListHandler) GetLists(w http.ResponseWriter, r *http.Request) { // @Param payload body request.AddUserToListPayload true "Add user to list payload" // @Success 204 {object} nil // @Error 400 {object} response.ErrorResponse "failed to decode request body" +// @Error 500 {object} response.ErrorResponse "failed to find email in system" // @Error 500 {object} response.ErrorResponse "failed to add user to list" // @Router /lists/user [post] func (h *ListHandler) AddUserToList(w http.ResponseWriter, r *http.Request) { @@ -118,14 +120,21 @@ func (h *ListHandler) AddUserToList(w http.ResponseWriter, r *http.Request) { return } - err = h.ListService.AddUserToList(ctx, authContext.UserID, payload.ListID, payload.UserID) + user, err := h.UserService.GetUserByEmail(ctx, payload.Email) + if err != nil { + slog.ErrorContext(ctx, "failed to get user by email", slog.Any("error", err)) + response.Error(ctx, w, http.StatusInternalServerError, "failed to find email in system") + return + } + + err = h.ListService.AddUserToList(ctx, authContext.UserID, payload.ListID, user.ID) if err != nil { slog.ErrorContext(ctx, "failed to add user to list", slog.Any("error", err)) response.Error(ctx, w, http.StatusInternalServerError, "failed to add user to list") return } - slog.InfoContext(ctx, "added user to list successfully", slog.Any("list_id", payload.ListID), slog.Any("user_id", payload.UserID)) + slog.InfoContext(ctx, "added user to list successfully", slog.Any("list_id", payload.ListID), slog.Any("email", user.Email)) response.Status(ctx, w, http.StatusNoContent) } @@ -139,6 +148,7 @@ func (h *ListHandler) AddUserToList(w http.ResponseWriter, r *http.Request) { // @Param payload body request.RemoveUserFromListPayload true "Remove user from list payload" // @Success 204 {object} nil // @Error 400 {object} response.ErrorResponse "failed to decode request body" +// @Error 500 {object} response.ErrorResponse "failed to find email in system" // @Error 500 {object} response.ErrorResponse "failed to remove user from list" // @Router /lists/user [delete] func (h *ListHandler) RemoveUserFromList(w http.ResponseWriter, r *http.Request) { @@ -158,14 +168,21 @@ func (h *ListHandler) RemoveUserFromList(w http.ResponseWriter, r *http.Request) return } - err = h.ListService.RemoveUserFromList(ctx, authContext.UserID, payload.ListID, payload.UserID) + user, err := h.UserService.GetUserByEmail(ctx, payload.Email) + if err != nil { + slog.ErrorContext(ctx, "failed to get user by email", slog.Any("error", err)) + response.Error(ctx, w, http.StatusInternalServerError, "failed to find email in system") + return + } + + err = h.ListService.RemoveUserFromList(ctx, authContext.UserID, payload.ListID, user.ID) if err != nil { slog.ErrorContext(ctx, "failed to remove user from list", slog.Any("error", err)) response.Error(ctx, w, http.StatusInternalServerError, "failed to remove user from list") return } - slog.InfoContext(ctx, "removed user from list successfully", slog.Any("list_id", payload.ListID), slog.Any("user_id", payload.UserID)) + slog.InfoContext(ctx, "removed user from list successfully", slog.Any("list_id", payload.ListID), slog.Any("email", user.Email)) response.Status(ctx, w, http.StatusNoContent) } diff --git a/internal/api/request/list.go b/internal/api/request/list.go index d425b44..00ef7ce 100644 --- a/internal/api/request/list.go +++ b/internal/api/request/list.go @@ -7,12 +7,12 @@ type CreateListPayload struct { type AddUserToListPayload struct { ListID string `json:"list_id"` - UserID string `json:"user_id"` + Email string `json:"email"` } type RemoveUserFromListPayload struct { ListID string `json:"list_id"` - UserID string `json:"user_id"` + Email string `json:"email"` } type CreateListItemPayload struct { diff --git a/internal/domain/list.go b/internal/domain/list.go index ba4d21f..7d25f33 100644 --- a/internal/domain/list.go +++ b/internal/domain/list.go @@ -78,13 +78,9 @@ func (s *ListService) AddUserToList(ctx context.Context, authUserID string, list return ErrUserIDEmpty } - inList, err := s.repo.IsUserInList(ctx, listID, authUserID) - if err != nil { + if err := s.userAllowedToAccessList(ctx, authUserID, listID); err != nil { return err } - if !inList { - return ErrUserNotInList - } return s.repo.AddUserToList(ctx, listID, userID) } diff --git a/internal/domain/user.go b/internal/domain/user.go index f7ebad4..4f57065 100644 --- a/internal/domain/user.go +++ b/internal/domain/user.go @@ -17,6 +17,7 @@ type User struct { type UserRepository interface { CreateUser(ctx context.Context, email string, name string, passwordHash string) (*User, error) + GetUserByEmail(ctx context.Context, email string) (*User, error) } type UserService struct { @@ -45,3 +46,7 @@ func (s *UserService) CreateUser(ctx context.Context, email string, name string, return s.repo.CreateUser(ctx, email, name, string(hash)) } + +func (s *UserService) GetUserByEmail(ctx context.Context, email string) (*User, error) { + return s.repo.GetUserByEmail(ctx, email) +} diff --git a/internal/repository/user.go b/internal/repository/user.go index 4749def..177a465 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -39,3 +39,17 @@ func (r *UserRepo) CreateUser(ctx context.Context, email string, name string, pa return user, nil } + +func (r *UserRepo) GetUserByEmail(ctx context.Context, email string) (*domain.User, error) { + user := &domain.User{} + + err := r.db.QueryRowContext(ctx, + "SELECT id, email, name FROM users WHERE email = $1", + email, + ).Scan(&user.ID, &user.Email, &user.Name) + if err != nil { + return nil, fmt.Errorf("failed to get user: %w", err) + } + + return user, nil +}