generated from VLADIMIR/template
fix
This commit is contained in:
@@ -31,6 +31,9 @@ func participationError(err error) string {
|
|||||||
}
|
}
|
||||||
func (s *server) GetParticipation(ctx context.Context, req *proto.GetParticipationReq) (*proto.ParticipationRsp, error) {
|
func (s *server) GetParticipation(ctx context.Context, req *proto.GetParticipationReq) (*proto.ParticipationRsp, error) {
|
||||||
_ = grpc.SetHeader(ctx, metadata.Pairs("Cache-Control", "no-store"))
|
_ = grpc.SetHeader(ctx, metadata.Pairs("Cache-Control", "no-store"))
|
||||||
|
if req == nil {
|
||||||
|
return &proto.ParticipationRsp{Error: participationError(participation_service.ErrParticipationLink)}, nil
|
||||||
|
}
|
||||||
p, err := s.participationService.GetParticipation(ctx, req.Token)
|
p, err := s.participationService.GetParticipation(ctx, req.Token)
|
||||||
result := mapParticipationResponse(p)
|
result := mapParticipationResponse(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -40,8 +43,11 @@ func (s *server) GetParticipation(ctx context.Context, req *proto.GetParticipati
|
|||||||
}
|
}
|
||||||
func (s *server) AnswerParticipation(ctx context.Context, req *proto.AnswerParticipationReq) (*proto.ParticipationRsp, error) {
|
func (s *server) AnswerParticipation(ctx context.Context, req *proto.AnswerParticipationReq) (*proto.ParticipationRsp, error) {
|
||||||
_ = grpc.SetHeader(ctx, metadata.Pairs("Cache-Control", "no-store"))
|
_ = grpc.SetHeader(ctx, metadata.Pairs("Cache-Control", "no-store"))
|
||||||
|
if req == nil {
|
||||||
|
return &proto.ParticipationRsp{Error: participationError(participation_service.ErrParticipationLink)}, nil
|
||||||
|
}
|
||||||
if req.Answer != "confirmed" && req.Answer != "cancelled" {
|
if req.Answer != "confirmed" && req.Answer != "cancelled" {
|
||||||
return &proto.ParticipationRsp{Error: "Выберите подтверждение или отмену участия"}, nil
|
return &proto.ParticipationRsp{Error: participation_service.ErrInvalidAnswer.Error()}, nil
|
||||||
}
|
}
|
||||||
p, err := s.participationService.AnswerParticipation(ctx, req.Token, req.Answer)
|
p, err := s.participationService.AnswerParticipation(ctx, req.Token, req.Answer)
|
||||||
result := mapParticipationResponse(p)
|
result := mapParticipationResponse(p)
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"evening_detective_server/internal/services/participation_service"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParticipationError(t *testing.T) {
|
||||||
|
for _, tc := range []struct {
|
||||||
|
name string
|
||||||
|
err error
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{"invalid link", participation_service.ErrParticipationLink, "Ссылка недействительна"},
|
||||||
|
{"closed", participation_service.ErrParticipationClosed, "Приём ответов закрыт"},
|
||||||
|
{"final", participation_service.ErrParticipationFinal, "Решение уже принято и не может быть изменено"},
|
||||||
|
{"internal", errors.New("private database detail"), "Не удалось обработать ответ. Попробуйте позже."},
|
||||||
|
} {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
if got := participationError(tc.err); got != tc.want {
|
||||||
|
t.Fatalf("message=%q, want %q", got, tc.want)
|
||||||
|
}
|
||||||
|
if strings.Contains(participationError(tc.err), "private database detail") {
|
||||||
|
t.Fatal("private error exposed")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
package participation_service
|
package participation_service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"evening_detective_server/internal/repos/teams_repo"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Participation — данные участия, доступные транспортному и email-сценариям.
|
// Participation — данные участия, доступные транспортному и email-сценариям.
|
||||||
@@ -20,7 +19,8 @@ type Participation struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrParticipationLink = teams_repo.ErrParticipationLink
|
ErrParticipationLink = errors.New("Ссылка недействительна")
|
||||||
ErrParticipationClosed = teams_repo.ErrParticipationClosed
|
ErrParticipationClosed = errors.New("Приём ответов закрыт")
|
||||||
ErrParticipationFinal = teams_repo.ErrParticipationFinal
|
ErrParticipationFinal = errors.New("Решение уже принято и не может быть изменено")
|
||||||
|
ErrInvalidAnswer = errors.New("Выберите подтверждение или отмену участия")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -30,11 +30,26 @@ func NewParticipationService(teamsRepo *teams_repo.TeamsRepo, appBaseURL string)
|
|||||||
|
|
||||||
func (s *ParticipationService) GetParticipation(ctx context.Context, token string) (*Participation, error) {
|
func (s *ParticipationService) GetParticipation(ctx context.Context, token string) (*Participation, error) {
|
||||||
p, err := s.teamsRepo.GetParticipation(ctx, token)
|
p, err := s.teamsRepo.GetParticipation(ctx, token)
|
||||||
return mapParticipation(p), err
|
return mapParticipation(p), mapParticipationError(err)
|
||||||
}
|
}
|
||||||
func (s *ParticipationService) AnswerParticipation(ctx context.Context, token, answer string) (*Participation, error) {
|
func (s *ParticipationService) AnswerParticipation(ctx context.Context, token, answer string) (*Participation, error) {
|
||||||
p, err := s.teamsRepo.AnswerParticipation(ctx, token, answer)
|
p, err := s.teamsRepo.AnswerParticipation(ctx, token, answer)
|
||||||
return mapParticipation(p), err
|
return mapParticipation(p), mapParticipationError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapParticipationError(err error) error {
|
||||||
|
switch {
|
||||||
|
case errors.Is(err, teams_repo.ErrParticipationLink):
|
||||||
|
return ErrParticipationLink
|
||||||
|
case errors.Is(err, teams_repo.ErrParticipationClosed):
|
||||||
|
return ErrParticipationClosed
|
||||||
|
case errors.Is(err, teams_repo.ErrParticipationFinal):
|
||||||
|
return ErrParticipationFinal
|
||||||
|
case err != nil && err.Error() == ErrInvalidAnswer.Error():
|
||||||
|
return ErrInvalidAnswer
|
||||||
|
default:
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Стабильные токены для разных целей сохраняют работоспособность ссылок при
|
// Стабильные токены для разных целей сохраняют работоспособность ссылок при
|
||||||
|
|||||||
Reference in New Issue
Block a user