This commit is contained in:
2026-10-03 00:44:03 +07:00
parent f6b799ff39
commit bd1120d10f
5 changed files with 75 additions and 12 deletions
+6
View File
@@ -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())
}
+16 -9
View File
@@ -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 {
+35
View File
@@ -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")
}
})
}
}
@@ -11,6 +11,10 @@ import (
)
var (
// ErrInvalidCaptainEmail — почта капитана команды некорректна.
ErrInvalidCaptainEmail = errors.New("Укажите корректную почту капитана")
// ErrTeamNotFound — команда не найдена.
ErrTeamNotFound = errors.New("Команда не найдена")
// ErrInvalidRegistration — входные данные регистрации команды некорректны.
ErrInvalidRegistration = errors.New("Укажите название команды (до 255 символов), почту капитана и положительное количество участников")
// ErrRegistrationClosed — игра не найдена или регистрация в неё закрыта.
+14 -3
View File
@@ -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) {