From bd1120d10f3f8f9861b9c61dd4ad805795882d26 Mon Sep 17 00:00:00 2001 From: Fedorov Vladimir Date: Sat, 3 Oct 2026 00:44:03 +0700 Subject: [PATCH] fix --- internal/app/team_registration_test.go | 6 ++++ internal/app/teams.go | 25 ++++++++----- internal/app/teams_test.go | 35 +++++++++++++++++++ .../services/team_service/registration.go | 4 +++ internal/services/team_service/service.go | 17 +++++++-- 5 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 internal/app/teams_test.go diff --git a/internal/app/team_registration_test.go b/internal/app/team_registration_test.go index 8b683cc..9d838e5 100644 --- a/internal/app/team_registration_test.go +++ b/internal/app/team_registration_test.go @@ -62,6 +62,12 @@ func TestTeamRegistrationHandler(t *testing.T) { if strings.Contains(res.Body.String(), "private database detail") { t.Fatal("private error exposed") } + if tc.name == "invalid fields" && !strings.Contains(res.Body.String(), team_service.ErrInvalidRegistration.Error()) { + t.Fatalf("public validation error missing: %s", res.Body.String()) + } + if tc.name == "closed" && !strings.Contains(res.Body.String(), team_service.ErrRegistrationClosed.Error()) { + t.Fatalf("public registration error missing: %s", res.Body.String()) + } if tc.name == "malformed" && !strings.Contains(res.Body.String(), "unexpected EOF") { t.Fatalf("malformed JSON reason missing: %s", res.Body.String()) } diff --git a/internal/app/teams.go b/internal/app/teams.go index 2423daf..093b5c3 100644 --- a/internal/app/teams.go +++ b/internal/app/teams.go @@ -2,8 +2,10 @@ package app import ( "context" + "errors" "evening_detective_server/internal/modules/roles" + "evening_detective_server/internal/services/team_service" proto "evening_detective_server/proto" "google.golang.org/grpc/codes" @@ -27,9 +29,7 @@ func (s *server) AddTeam(ctx context.Context, req *proto.AddTeamReq) (*proto.Add req.CaptainEmail, ) if err != nil { - return &proto.AddTeamRsp{ - Error: err.Error(), - }, nil + return nil, teamErrorStatus(err, "не удалось добавить команду") } return &proto.AddTeamRsp{ @@ -53,9 +53,7 @@ func (s *server) UpdateTeam(ctx context.Context, req *proto.UpdateTeamReq) (*pro req.Name, ) if err != nil { - return &proto.UpdateTeamRsp{ - Error: err.Error(), - }, nil + return nil, teamErrorStatus(err, "не удалось изменить команду") } return &proto.UpdateTeamRsp{}, nil @@ -75,14 +73,23 @@ func (s *server) DeleteTeam(ctx context.Context, req *proto.DeleteTeamReq) (*pro int(req.ID), ) if err != nil { - return &proto.DeleteTeamRsp{ - Error: err.Error(), - }, nil + return nil, teamErrorStatus(err, "не удалось удалить команду") } return &proto.DeleteTeamRsp{}, nil } +func teamErrorStatus(err error, internalMessage string) error { + switch { + case errors.Is(err, team_service.ErrGameNotFound), errors.Is(err, team_service.ErrTeamNotFound): + return status.Error(codes.NotFound, err.Error()) + case errors.Is(err, team_service.ErrInvalidCaptainEmail): + return status.Error(codes.InvalidArgument, err.Error()) + default: + return status.Error(codes.Internal, internalMessage) + } +} + func (s *server) GiveTeamApplications(ctx context.Context, req *proto.GiveTeamApplicationsReq) (*proto.GiveTeamApplicationsRsp, error) { claims, claimsErr := claimsFromContext(ctx) if claimsErr != nil { diff --git a/internal/app/teams_test.go b/internal/app/teams_test.go new file mode 100644 index 0000000..32dff1c --- /dev/null +++ b/internal/app/teams_test.go @@ -0,0 +1,35 @@ +package app + +import ( + "errors" + "testing" + + "evening_detective_server/internal/services/team_service" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func TestTeamErrorStatus(t *testing.T) { + for _, tc := range []struct { + name, internalMessage string + err error + code codes.Code + message string + }{ + {"game not found", "add failed", team_service.ErrGameNotFound, codes.NotFound, "Игра не найдена"}, + {"team not found", "delete failed", team_service.ErrTeamNotFound, codes.NotFound, "Команда не найдена"}, + {"invalid captain email", "add failed", team_service.ErrInvalidCaptainEmail, codes.InvalidArgument, "Укажите корректную почту капитана"}, + {"internal", "add failed", errors.New("private database detail"), codes.Internal, "add failed"}, + } { + t.Run(tc.name, func(t *testing.T) { + err := teamErrorStatus(tc.err, tc.internalMessage) + if status.Code(err) != tc.code || status.Convert(err).Message() != tc.message { + t.Fatalf("status=%v, want %v %q", err, tc.code, tc.message) + } + if status.Convert(err).Message() == "private database detail" { + t.Fatal("private error exposed") + } + }) + } +} diff --git a/internal/services/team_service/registration.go b/internal/services/team_service/registration.go index 15d274b..90a9c80 100644 --- a/internal/services/team_service/registration.go +++ b/internal/services/team_service/registration.go @@ -11,6 +11,10 @@ import ( ) var ( + // ErrInvalidCaptainEmail — почта капитана команды некорректна. + ErrInvalidCaptainEmail = errors.New("Укажите корректную почту капитана") + // ErrTeamNotFound — команда не найдена. + ErrTeamNotFound = errors.New("Команда не найдена") // ErrInvalidRegistration — входные данные регистрации команды некорректны. ErrInvalidRegistration = errors.New("Укажите название команды (до 255 символов), почту капитана и положительное количество участников") // ErrRegistrationClosed — игра не найдена или регистрация в неё закрыта. diff --git a/internal/services/team_service/service.go b/internal/services/team_service/service.go index f3e6575..00afb3b 100644 --- a/internal/services/team_service/service.go +++ b/internal/services/team_service/service.go @@ -50,7 +50,7 @@ func (s *TeamService) AddTeam( ) (*game_model.Team, error) { captainEmail = strings.TrimSpace(captainEmail) if captainEmail != "" && !validCaptainEmail(captainEmail) { - return nil, errors.New("Укажите корректную почту капитана") + return nil, ErrInvalidCaptainEmail } password, err := s.passwordGenerator.Generate() if err != nil { @@ -58,6 +58,9 @@ func (s *TeamService) AddTeam( } game, err := s.gamesRepo.GetGameByID(ctx, gameID) if err != nil { + if errors.Is(err, games_repo.ErrGameNotFound) { + return nil, ErrGameNotFound + } return nil, err } id, err := s.teamsRepo.AddTeamWithParticipation(ctx, creatorID, gameID, name, password, captainEmail, !time.Now().Before(game.StartAt.Add(-24*time.Hour))) @@ -71,11 +74,19 @@ func (s *TeamService) AddTeam( } func (s *TeamService) UpdateTeam(ctx context.Context, teamID int, name string) error { - return s.teamsRepo.UpdateTeam(ctx, teamID, name) + err := s.teamsRepo.UpdateTeam(ctx, teamID, name) + if errors.Is(err, teams_repo.ErrTeamNotFound) { + return ErrTeamNotFound + } + return err } func (s *TeamService) DeleteTeam(ctx context.Context, teamID int) error { - return s.teamsRepo.DeleteTeam(ctx, teamID) + err := s.teamsRepo.DeleteTeam(ctx, teamID) + if errors.Is(err, teams_repo.ErrTeamNotFound) { + return ErrTeamNotFound + } + return err } func (s *TeamService) RegisterTeam(ctx context.Context, gameID int, deliveryID string, registration Registration) (int, error) {