Files
2026-10-23 00:45:30 +07:00

291 lines
8.5 KiB
Go

package app
import (
"context"
"evening_detective_server/internal/modules/processor_jwt"
"evening_detective_server/internal/modules/roles"
proto "evening_detective_server/proto"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
func nilIfEmpty(value string) *string {
if value == "" {
return nil
}
return &value
}
func (s *server) AddGame(ctx context.Context, req *proto.AddGameReq) (*proto.AddGameRsp, error) {
claims, claimsErr := claimsFromContext(ctx)
if claimsErr != nil {
return nil, claimsErr
}
if !roles.HasRole(claims, roles.Organizer) && !roles.HasRole(claims, roles.Author) {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
if req.StartAt == nil {
return nil, status.Errorf(codes.InvalidArgument, "startAt must not be nil")
}
id, err := s.gameService.AddGame(
ctx,
req.Name,
req.Description,
nilIfEmpty(req.Location),
req.StartAt.AsTime(),
req.ScenarioID,
req.Format,
)
if err != nil {
return nil, gameErrorStatus(err, "не удалось создать игру")
}
return &proto.AddGameRsp{
ID: int32(id),
}, nil
}
func (s *server) DeleteGame(ctx context.Context, req *proto.DeleteGameReq) (*proto.DeleteGameRsp, error) {
claims, claimsErr := claimsFromContext(ctx)
if claimsErr != nil {
return nil, claimsErr
}
if !roles.HasRole(claims, roles.Organizer) && !roles.HasRole(claims, roles.Author) {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
err := s.gameService.DeleteGame(
ctx,
int(req.ID),
)
if err != nil {
return nil, gameErrorStatus(err, "не удалось удалить игру")
}
return &proto.DeleteGameRsp{}, nil
}
func (s *server) GetGame(ctx context.Context, req *proto.GetGameReq) (*proto.GetGameRsp, error) {
claims, claimsErr := claimsFromContext(ctx)
if claimsErr != nil {
return nil, claimsErr
}
allowed, restricted := gameReadAccess(claims, s.uiService != nil && s.uiService.Environment == "venue")
if !allowed {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
if restricted {
game, err := s.gameService.GetGame(ctx, int(req.ID))
if err != nil {
return nil, gameErrorStatus(err, "не удалось получить игру")
}
return &proto.GetGameRsp{Game: mapGameSummary(game)}, nil
}
game, err := s.gameService.GetFullGame(ctx, int(req.ID))
if err != nil {
return nil, gameErrorStatus(err, "не удалось получить игру")
}
return &proto.GetGameRsp{
Game: mapGameSettings(game),
}, nil
}
func (s *server) GetGameAnswers(ctx context.Context, req *proto.GetGameAnswersReq) (*proto.GetGameAnswersRsp, error) {
claims, claimsErr := claimsFromContext(ctx)
if claimsErr != nil {
return nil, claimsErr
}
if !roles.HasRole(claims, roles.Organizer) && !roles.HasRole(claims, roles.Author) {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
gameAnswers, err := s.answerService.GetGameAnswers(ctx, int(req.GameID))
if err != nil {
return nil, answerErrorStatus(err, "не удалось получить ответы игры")
}
return &proto.GetGameAnswersRsp{
Questions: mapQuestions(gameAnswers.Questions),
Teams: mapTeamAnswers(gameAnswers.Teams),
}, nil
}
func (s *server) GetGameResults(ctx context.Context, req *proto.GetGameResultsReq) (*proto.GetGameResultsRsp, error) {
claims, claimsErr := claimsFromContext(ctx)
if claimsErr != nil {
return nil, claimsErr
}
if !roles.HasRole(claims, roles.Organizer) && !roles.HasRole(claims, roles.Author) {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
results, err := s.answerService.GetGameResults(ctx, int(req.GameID))
if err != nil {
return nil, answerErrorStatus(err, "не удалось получить результаты игры")
}
return &proto.GetGameResultsRsp{
Questions: mapResultsQuestions(results.Questions),
Teams: mapTeamResults(results.Teams),
}, nil
}
func (s *server) GetGames(ctx context.Context, _ *proto.GetGamesReq) (*proto.GetGamesRsp, error) {
claims, claimsErr := claimsFromContext(ctx)
if claimsErr != nil {
return nil, claimsErr
}
allowed, restricted := gameReadAccess(claims, s.uiService != nil && s.uiService.Environment == "venue")
if !allowed {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
games, err := s.gameService.GetGames(ctx)
if err != nil {
return nil, gameErrorStatus(err, "не удалось получить игры")
}
if restricted {
result := make([]*proto.Game, 0, len(games))
for _, game := range games {
result = append(result, mapGameSummary(game))
}
return &proto.GetGamesRsp{Games: result}, nil
}
return &proto.GetGamesRsp{Games: mapGames(games)}, nil
}
func (s *server) UpdateGame(ctx context.Context, req *proto.UpdateGameReq) (*proto.UpdateGameRsp, error) {
claims, claimsErr := claimsFromContext(ctx)
if claimsErr != nil {
return nil, claimsErr
}
if !roles.HasRole(claims, roles.Organizer) && !roles.HasRole(claims, roles.Author) {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
if req.StartAt == nil {
return nil, status.Errorf(codes.InvalidArgument, "startAt must not be nil")
}
err := s.gameService.UpdateGame(
ctx,
int(req.ID),
req.Name,
req.Description,
nilIfEmpty(req.Location),
req.StartAt.AsTime(),
req.ScenarioID,
req.Format,
req.WifiName,
req.WifiPassword,
)
if err != nil {
return nil, gameErrorStatus(err, "не удалось изменить игру")
}
return &proto.UpdateGameRsp{}, nil
}
func (s *server) StartGame(ctx context.Context, req *proto.StartGameReq) (*proto.StartGameRsp, error) {
claims, claimsErr := claimsFromContext(ctx)
if claimsErr != nil {
return nil, claimsErr
}
if !roles.HasRole(claims, roles.Organizer) && !roles.HasRole(claims, roles.Author) {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
err := s.gameService.StartGame(ctx, int(req.ID))
if err != nil {
return nil, gameErrorStatus(err, "не удалось запустить игру")
}
return &proto.StartGameRsp{}, nil
}
func (s *server) PauseGame(ctx context.Context, req *proto.PauseGameReq) (*proto.PauseGameRsp, error) {
claims, claimsErr := claimsFromContext(ctx)
if claimsErr != nil {
return nil, claimsErr
}
if !roles.HasRole(claims, roles.Organizer) && !roles.HasRole(claims, roles.Author) {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
err := s.gameService.PauseGame(ctx, int(req.ID))
if err != nil {
return nil, gameErrorStatus(err, "не удалось приостановить игру")
}
return &proto.PauseGameRsp{}, nil
}
func (s *server) PlayGame(ctx context.Context, req *proto.PlayGameReq) (*proto.PlayGameRsp, error) {
claims, claimsErr := claimsFromContext(ctx)
if claimsErr != nil {
return nil, claimsErr
}
if !roles.HasRole(claims, roles.Organizer) && !roles.HasRole(claims, roles.Author) {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
err := s.gameService.PlayGame(ctx, int(req.ID))
if err != nil {
return nil, gameErrorStatus(err, "не удалось продолжить игру")
}
return &proto.PlayGameRsp{}, nil
}
func (s *server) FinishGame(ctx context.Context, req *proto.FinishGameReq) (*proto.FinishGameRsp, error) {
claims, claimsErr := claimsFromContext(ctx)
if claimsErr != nil {
return nil, claimsErr
}
if !roles.HasRole(claims, roles.Organizer) && !roles.HasRole(claims, roles.Author) {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
err := s.gameService.FinishGame(ctx, int(req.ID))
if err != nil {
return nil, gameErrorStatus(err, "не удалось завершить игру")
}
return &proto.FinishGameRsp{}, nil
}
func (s *server) ResetGame(ctx context.Context, req *proto.ResetGameReq) (*proto.ResetGameRsp, error) {
claims, claimsErr := claimsFromContext(ctx)
if claimsErr != nil {
return nil, claimsErr
}
if !roles.HasRole(claims, roles.Organizer) && !roles.HasRole(claims, roles.Author) {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
err := s.gameService.ResetGame(ctx, int(req.ID))
if err != nil {
return nil, gameErrorStatus(err, "не удалось сбросить игру")
}
return &proto.ResetGameRsp{}, nil
}
func gameReadAccess(claims *processor_jwt.JWTClaims, venue bool) (allowed, restricted bool) {
if roles.HasRole(claims, roles.Organizer) || roles.HasRole(claims, roles.Author) {
return true, false
}
if venue && roles.HasRole(claims, roles.Developer) {
return true, true
}
return false, false
}