generated from VLADIMIR/template
fix
This commit is contained in:
@@ -36,11 +36,11 @@ func (s *server) DownloadScenarioArchive(ctx context.Context, req *proto.Downloa
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, scenarios_service.ErrScenarioNotFound):
|
||||
return nil, status.Errorf(codes.NotFound, "%v", err)
|
||||
return nil, status.Error(codes.NotFound, err.Error())
|
||||
case errors.Is(err, scenarios_service.ErrScenarioNotOwner):
|
||||
return nil, status.Errorf(codes.PermissionDenied, "%v", err)
|
||||
return nil, status.Error(codes.PermissionDenied, err.Error())
|
||||
default:
|
||||
return nil, status.Errorf(codes.Internal, "%v", err)
|
||||
return nil, status.Error(codes.Internal, "не удалось скачать архив сценария")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ func (s *server) DownloadScenarioArchive(ctx context.Context, req *proto.Downloa
|
||||
}
|
||||
filename := transliterated + ".zip"
|
||||
if err := grpc.SetHeader(ctx, metadata.Pairs("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, filename))); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "failed to set response header: %v", err)
|
||||
return nil, status.Error(codes.Internal, "не удалось установить заголовки архива")
|
||||
}
|
||||
|
||||
return &httpbody.HttpBody{
|
||||
@@ -78,9 +78,10 @@ func (s *server) UploadScenarioArchive(ctx context.Context, req *httpbody.HttpBo
|
||||
|
||||
id, err := s.scenarioService.UploadArchive(ctx, req.Data, claims.UserID)
|
||||
if err != nil {
|
||||
return &proto.UploadScenarioArchiveRsp{
|
||||
Error: err.Error(),
|
||||
}, nil
|
||||
if errors.Is(err, scenarios_service.ErrInvalidArchive) {
|
||||
return nil, status.Error(codes.InvalidArgument, scenarios_service.ErrInvalidArchive.Error())
|
||||
}
|
||||
return nil, status.Error(codes.Internal, "не удалось загрузить архив сценария")
|
||||
}
|
||||
return &proto.UploadScenarioArchiveRsp{
|
||||
ID: int32(id),
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"evening_detective_server/internal/services/scenarios_service"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
func scenarioErrorStatus(err error, internalMessage string) error {
|
||||
switch {
|
||||
case errors.Is(err, scenarios_service.ErrScenarioNotFound):
|
||||
return status.Error(codes.NotFound, err.Error())
|
||||
case errors.Is(err, scenarios_service.ErrScenarioNotOwner):
|
||||
return status.Error(codes.PermissionDenied, err.Error())
|
||||
case errors.Is(err, scenarios_service.ErrScenarioPublished):
|
||||
return status.Error(codes.FailedPrecondition, err.Error())
|
||||
case errors.Is(err, scenarios_service.ErrInvalidScenarioData):
|
||||
return status.Error(codes.InvalidArgument, err.Error())
|
||||
default:
|
||||
return status.Error(codes.Internal, internalMessage)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"evening_detective_server/internal/services/scenarios_service"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
func TestScenarioErrorStatus(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
name, internalMessage string
|
||||
err error
|
||||
code codes.Code
|
||||
message string
|
||||
}{
|
||||
{"not found", "scenario failed", scenarios_service.ErrScenarioNotFound, codes.NotFound, "Сценарий не найден"},
|
||||
{"not owner", "scenario failed", scenarios_service.ErrScenarioNotOwner, codes.PermissionDenied, "Сценарий принадлежит другому пользователю"},
|
||||
{"published", "scenario failed", scenarios_service.ErrScenarioPublished, codes.FailedPrecondition, scenarios_service.ErrScenarioPublished.Error()},
|
||||
{"internal", "scenario failed", errors.New("private database detail"), codes.Internal, "scenario failed"},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err := scenarioErrorStatus(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")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -27,9 +27,7 @@ func (s *server) AddScenarioPlace(ctx context.Context, req *proto.AddScenarioPla
|
||||
roles.HasRole(claims, roles.Admin),
|
||||
)
|
||||
if err != nil {
|
||||
return &proto.AddScenarioPlaceRsp{
|
||||
Error: err.Error(),
|
||||
}, nil
|
||||
return nil, scenarioErrorStatus(err, "не удалось добавить место сценария")
|
||||
}
|
||||
|
||||
return &proto.AddScenarioPlaceRsp{}, nil
|
||||
@@ -53,9 +51,7 @@ func (s *server) UpdateScenarioPlace(ctx context.Context, req *proto.UpdateScena
|
||||
roles.HasRole(claims, roles.Admin),
|
||||
)
|
||||
if err != nil {
|
||||
return &proto.UpdateScenarioPlaceRsp{
|
||||
Error: err.Error(),
|
||||
}, nil
|
||||
return nil, scenarioErrorStatus(err, "не удалось изменить место сценария")
|
||||
}
|
||||
|
||||
return &proto.UpdateScenarioPlaceRsp{}, nil
|
||||
@@ -78,9 +74,7 @@ func (s *server) DeleteScenarioPlace(ctx context.Context, req *proto.DeleteScena
|
||||
roles.HasRole(claims, roles.Admin),
|
||||
)
|
||||
if err != nil {
|
||||
return &proto.DeleteScenarioPlaceRsp{
|
||||
Error: err.Error(),
|
||||
}, nil
|
||||
return nil, scenarioErrorStatus(err, "не удалось удалить место сценария")
|
||||
}
|
||||
|
||||
return &proto.DeleteScenarioPlaceRsp{}, nil
|
||||
@@ -103,9 +97,7 @@ func (s *server) AddScenarioQuestion(ctx context.Context, req *proto.AddScenario
|
||||
roles.HasRole(claims, roles.Admin),
|
||||
)
|
||||
if err != nil {
|
||||
return &proto.AddScenarioQuestionRsp{
|
||||
Error: err.Error(),
|
||||
}, nil
|
||||
return nil, scenarioErrorStatus(err, "не удалось добавить вопрос сценария")
|
||||
}
|
||||
|
||||
return &proto.AddScenarioQuestionRsp{}, nil
|
||||
@@ -129,9 +121,7 @@ func (s *server) UpdateScenarioQuestion(ctx context.Context, req *proto.UpdateSc
|
||||
roles.HasRole(claims, roles.Admin),
|
||||
)
|
||||
if err != nil {
|
||||
return &proto.UpdateScenarioQuestionRsp{
|
||||
Error: err.Error(),
|
||||
}, nil
|
||||
return nil, scenarioErrorStatus(err, "не удалось изменить вопрос сценария")
|
||||
}
|
||||
|
||||
return &proto.UpdateScenarioQuestionRsp{}, nil
|
||||
@@ -154,9 +144,7 @@ func (s *server) DeleteScenarioQuestion(ctx context.Context, req *proto.DeleteSc
|
||||
roles.HasRole(claims, roles.Admin),
|
||||
)
|
||||
if err != nil {
|
||||
return &proto.DeleteScenarioQuestionRsp{
|
||||
Error: err.Error(),
|
||||
}, nil
|
||||
return nil, scenarioErrorStatus(err, "не удалось удалить вопрос сценария")
|
||||
}
|
||||
|
||||
return &proto.DeleteScenarioQuestionRsp{}, nil
|
||||
@@ -179,9 +167,7 @@ func (s *server) UpdateScenarioBackground(ctx context.Context, req *proto.Update
|
||||
roles.HasRole(claims, roles.Admin),
|
||||
)
|
||||
if err != nil {
|
||||
return &proto.UpdateScenarioBackgroundRsp{
|
||||
Error: err.Error(),
|
||||
}, nil
|
||||
return nil, scenarioErrorStatus(err, "не удалось изменить фон сценария")
|
||||
}
|
||||
|
||||
return &proto.UpdateScenarioBackgroundRsp{}, nil
|
||||
@@ -204,9 +190,7 @@ func (s *server) UpdateScenarioIntro(ctx context.Context, req *proto.UpdateScena
|
||||
roles.HasRole(claims, roles.Admin),
|
||||
)
|
||||
if err != nil {
|
||||
return &proto.UpdateScenarioIntroRsp{
|
||||
Error: err.Error(),
|
||||
}, nil
|
||||
return nil, scenarioErrorStatus(err, "не удалось изменить введение сценария")
|
||||
}
|
||||
|
||||
return &proto.UpdateScenarioIntroRsp{}, nil
|
||||
@@ -221,7 +205,7 @@ func (s *server) UpdateScenarioConclusion(ctx context.Context, req *proto.Update
|
||||
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
|
||||
}
|
||||
if err := s.scenarioService.UpdateScenarioConclusion(ctx, int(req.ID), convertConclusion(req.Conclusion), claims.UserID, roles.HasRole(claims, roles.Admin)); err != nil {
|
||||
return &proto.UpdateScenarioConclusionRsp{Error: err.Error()}, nil
|
||||
return nil, scenarioErrorStatus(err, "не удалось изменить заключение сценария")
|
||||
}
|
||||
return &proto.UpdateScenarioConclusionRsp{}, nil
|
||||
}
|
||||
|
||||
+11
-29
@@ -22,9 +22,7 @@ func (s *server) AddScenario(ctx context.Context, req *proto.AddScenarioReq) (*p
|
||||
|
||||
id, err := s.scenarioService.AddScenario(ctx, req.Name, claims.UserID)
|
||||
if err != nil {
|
||||
return &proto.AddScenarioRsp{
|
||||
Error: err.Error(),
|
||||
}, nil
|
||||
return nil, scenarioErrorStatus(err, "не удалось создать сценарий")
|
||||
}
|
||||
return &proto.AddScenarioRsp{
|
||||
ID: int32(id),
|
||||
@@ -42,9 +40,7 @@ func (s *server) GetMyScenarios(ctx context.Context, req *proto.GetMyScenariosRe
|
||||
|
||||
scenarios, err := s.scenarioService.GetScenariosByAuthorID(ctx, claims.UserID)
|
||||
if err != nil {
|
||||
return &proto.GetMyScenariosRsp{
|
||||
Error: err.Error(),
|
||||
}, nil
|
||||
return nil, scenarioErrorStatus(err, "не удалось получить сценарии автора")
|
||||
}
|
||||
|
||||
return &proto.GetMyScenariosRsp{
|
||||
@@ -55,12 +51,10 @@ func (s *server) GetMyScenarios(ctx context.Context, req *proto.GetMyScenariosRe
|
||||
func (s *server) GetScenariosCatalog(ctx context.Context, req *proto.GetScenariosCatalogReq) (*proto.GetScenariosCatalogRsp, error) {
|
||||
scenarios, err := s.scenarioService.GetScenariosCatalog(ctx)
|
||||
if err != nil {
|
||||
return &proto.GetScenariosCatalogRsp{
|
||||
Error: err.Error(),
|
||||
}, nil
|
||||
return nil, scenarioErrorStatus(err, "не удалось получить каталог сценариев")
|
||||
}
|
||||
if err := s.addScenarioRatings(ctx, scenarios); err != nil {
|
||||
return &proto.GetScenariosCatalogRsp{Error: err.Error()}, nil
|
||||
return nil, scenarioErrorStatus(err, "не удалось получить рейтинг сценариев")
|
||||
}
|
||||
|
||||
return &proto.GetScenariosCatalogRsp{
|
||||
@@ -79,9 +73,7 @@ func (s *server) GetFullScenario(ctx context.Context, req *proto.GetScenarioReq)
|
||||
|
||||
scenario, err := s.scenarioService.GetFullScenarioByID(ctx, int(req.ID))
|
||||
if err != nil {
|
||||
return &proto.GetScenarioRsp{
|
||||
Error: err.Error(),
|
||||
}, nil
|
||||
return nil, scenarioErrorStatus(err, "не удалось получить сценарий")
|
||||
}
|
||||
|
||||
return &proto.GetScenarioRsp{
|
||||
@@ -92,12 +84,10 @@ func (s *server) GetFullScenario(ctx context.Context, req *proto.GetScenarioReq)
|
||||
func (s *server) GetScenario(ctx context.Context, req *proto.GetScenarioReq) (*proto.GetScenarioRsp, error) {
|
||||
scenario, err := s.scenarioService.GetScenarioByID(ctx, int(req.ID))
|
||||
if err != nil {
|
||||
return &proto.GetScenarioRsp{
|
||||
Error: err.Error(),
|
||||
}, nil
|
||||
return nil, scenarioErrorStatus(err, "не удалось получить сценарий")
|
||||
}
|
||||
if err := s.addScenarioRatings(ctx, []*scenarios_service.Scenario{scenario}); err != nil {
|
||||
return &proto.GetScenarioRsp{Error: err.Error()}, nil
|
||||
return nil, scenarioErrorStatus(err, "не удалось получить рейтинг сценария")
|
||||
}
|
||||
|
||||
return &proto.GetScenarioRsp{
|
||||
@@ -136,9 +126,7 @@ func (s *server) UpdateScenario(ctx context.Context, req *proto.UpdateScenarioRe
|
||||
roles.HasRole(claims, roles.Admin),
|
||||
)
|
||||
if err != nil {
|
||||
return &proto.UpdateScenarioRsp{
|
||||
Error: err.Error(),
|
||||
}, nil
|
||||
return nil, scenarioErrorStatus(err, "не удалось изменить сценарий")
|
||||
}
|
||||
|
||||
return &proto.UpdateScenarioRsp{}, nil
|
||||
@@ -161,9 +149,7 @@ func (s *server) PublicScenario(ctx context.Context, req *proto.PublicScenarioRe
|
||||
roles.HasRole(claims, roles.Admin), // публикация = момент отчуждения прав
|
||||
)
|
||||
if err != nil {
|
||||
return &proto.PublicScenarioRsp{
|
||||
Error: err.Error(),
|
||||
}, nil
|
||||
return nil, scenarioErrorStatus(err, "не удалось опубликовать сценарий")
|
||||
}
|
||||
|
||||
return &proto.PublicScenarioRsp{}, nil
|
||||
@@ -189,9 +175,7 @@ func (s *server) DraftScenario(ctx context.Context, req *proto.DraftScenarioReq)
|
||||
true,
|
||||
)
|
||||
if err != nil {
|
||||
return &proto.DraftScenarioRsp{
|
||||
Error: err.Error(),
|
||||
}, nil
|
||||
return nil, scenarioErrorStatus(err, "не удалось снять сценарий с публикации")
|
||||
}
|
||||
|
||||
return &proto.DraftScenarioRsp{}, nil
|
||||
@@ -215,9 +199,7 @@ func (s *server) DeleteScenario(ctx context.Context, req *proto.DeleteScenarioRe
|
||||
roles.HasRole(claims, roles.Admin),
|
||||
)
|
||||
if err != nil {
|
||||
return &proto.DeleteScenarioRsp{
|
||||
Error: err.Error(),
|
||||
}, nil
|
||||
return nil, scenarioErrorStatus(err, "не удалось удалить сценарий")
|
||||
}
|
||||
|
||||
return &proto.DeleteScenarioRsp{}, nil
|
||||
|
||||
@@ -91,7 +91,7 @@ func (s *ScenarioService) GetFullScenarioByID(
|
||||
) (*Scenario, error) {
|
||||
scenario, err := s.scenariosRepo.GetScenarioByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, mapScenarioError(err)
|
||||
}
|
||||
return mapScenario(scenario, s.domain)
|
||||
}
|
||||
@@ -102,7 +102,7 @@ func (s *ScenarioService) GetScenarioByID(
|
||||
) (*Scenario, error) {
|
||||
scenario, err := s.scenariosRepo.GetScenarioByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, mapScenarioError(err)
|
||||
}
|
||||
return MapScenarioLight(scenario, s.domain), nil
|
||||
}
|
||||
@@ -134,6 +134,12 @@ var ErrScenarioNotOwner = errors.New("Сценарий принадлежит д
|
||||
// ErrScenarioNotFound — сценарий не найден или уже удалён.
|
||||
var ErrScenarioNotFound = errors.New("Сценарий не найден")
|
||||
|
||||
// ErrInvalidArchive — архив не соответствует формату сценария.
|
||||
var ErrInvalidArchive = errors.New("Некорректный архив сценария")
|
||||
|
||||
// ErrInvalidScenarioData — данные истории сценария не проходят валидацию.
|
||||
var ErrInvalidScenarioData = errors.New("Некорректные данные сценария")
|
||||
|
||||
// MaxArchiveSize возвращает максимальный размер загружаемого архива.
|
||||
func MaxArchiveSize() int {
|
||||
return scenario_archive.MaxArchiveSize()
|
||||
@@ -150,10 +156,10 @@ func (s *ScenarioService) getScenarioForChange(
|
||||
) (*repos.Scenario, error) {
|
||||
scenario, err := s.scenariosRepo.GetScenarioByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, mapScenarioError(err)
|
||||
}
|
||||
if scenario.IsDeleted {
|
||||
return nil, scenarios_repo.ErrScenarioNotFound
|
||||
return nil, ErrScenarioNotFound
|
||||
}
|
||||
if isAdmin {
|
||||
return scenario, nil
|
||||
@@ -164,6 +170,13 @@ func (s *ScenarioService) getScenarioForChange(
|
||||
return scenario, nil
|
||||
}
|
||||
|
||||
func mapScenarioError(err error) error {
|
||||
if errors.Is(err, scenarios_repo.ErrScenarioNotFound) {
|
||||
return ErrScenarioNotFound
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *ScenarioService) UpdateScenarioStatusByID(
|
||||
ctx context.Context,
|
||||
id int,
|
||||
@@ -455,7 +468,7 @@ func (s *ScenarioService) UploadArchive(
|
||||
) (int, error) {
|
||||
bundle, err := s.scenarioArchive.Unpack(data)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
return 0, fmt.Errorf("%w: %v", ErrInvalidArchive, err)
|
||||
}
|
||||
scenario := bundle.Scenario
|
||||
|
||||
@@ -482,7 +495,7 @@ func (s *ScenarioService) UploadArchive(
|
||||
}
|
||||
content, exists := bundle.Files[archiveRef]
|
||||
if !exists {
|
||||
return "", fmt.Errorf("изображение %q не найдено в архиве", archiveRef)
|
||||
return "", fmt.Errorf("%w: изображение %q не найдено в архиве", ErrInvalidArchive, archiveRef)
|
||||
}
|
||||
name, err := file_storage.NewName()
|
||||
if err != nil {
|
||||
@@ -535,7 +548,7 @@ func (s *ScenarioService) UploadArchive(
|
||||
}
|
||||
storyJSON, err := normalizeStory(scenario.Story)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
return 0, fmt.Errorf("%w: %v", ErrInvalidArchive, err)
|
||||
}
|
||||
|
||||
id, err := s.scenariosRepo.AddScenario(ctx, scenario.Name, authorID)
|
||||
@@ -571,7 +584,7 @@ func (s *ScenarioService) updateStory(ctx context.Context, id int, story *storyt
|
||||
}
|
||||
storyString, err := normalizeStory(story)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("%w: %v", ErrInvalidScenarioData, err)
|
||||
}
|
||||
|
||||
return s.scenariosRepo.UpdateStoryByScenarioID(ctx, id, storyString)
|
||||
|
||||
Reference in New Issue
Block a user