package controller import ( "net/http" "time" "github.com/google/uuid" "github.com/labstack/echo/v4" "gitrepo.ru/neonxp/nquest/api" "gitrepo.ru/neonxp/nquest/pkg/contextlib" "gitrepo.ru/neonxp/nquest/pkg/models" "gitrepo.ru/neonxp/nquest/pkg/service" ) type Admin struct { GameService *service.Game } // (POST /games/{uid}) func (a *Admin) AdminEditGame(ctx echo.Context) error { user := contextlib.GetUser(ctx) req := &api.AdminEditGameJSONRequestBody{} if err := ctx.Bind(req); err != nil { return err } game := a.mapCreateGameRequest(req, user) game, err := a.GameService.UpsertGame(ctx.Request().Context(), game) if err != nil { return err } tasks := make([]api.TaskEdit, 0, len(game.Tasks)) for _, t := range game.Tasks { t := t codes := make([]api.CodeEdit, 0, len(t.Codes)) for _, c := range t.Codes { codes = append(codes, api.CodeEdit{ Id: &c.ID, Code: c.Code, Description: c.Description, }) } tasks = append(tasks, api.TaskEdit{ Id: &t.ID, Codes: codes, Text: t.Text, Title: t.Title, }) } return ctx.JSON(http.StatusOK, api.GameAdminResponse{ Description: game.Description, Icon: game.IconID, Id: &game.ID, Points: game.Points, Tasks: tasks, Title: game.Title, Type: api.MapGameTypeReverse(game.Type), Visible: game.Visible, }) } // (GET /games/{uid}) func (a *Admin) AdminGetGame(ctx echo.Context, uid uuid.UUID) error { user := contextlib.GetUser(ctx) game, err := a.GameService.GetByID(ctx.Request().Context(), uid) if err != nil { return echo.ErrNotFound } if user.Role != models.RoleAdmin { isAuthor := false for _, u := range game.Authors { if u.ID == user.ID { isAuthor = true break } } if !isAuthor { return echo.ErrForbidden } } tasks := make([]api.TaskEdit, 0, len(game.Tasks)) for _, t := range game.Tasks { t := t codes := make([]api.CodeEdit, 0, len(t.Codes)) for _, c := range t.Codes { codes = append(codes, api.CodeEdit{ Id: &c.ID, Code: c.Code, Description: c.Description, }) } tasks = append(tasks, api.TaskEdit{ Id: &t.ID, Codes: codes, Text: t.Text, Title: t.Title, }) } return ctx.JSON(http.StatusOK, api.GameAdminResponse{ Description: game.Description, Icon: game.IconID, Id: &game.ID, Points: game.Points, Tasks: tasks, Title: game.Title, Type: api.MapGameTypeReverse(game.Type), Visible: game.Visible, }) } func (a *Admin) AdminListGames(ctx echo.Context) error { user := contextlib.GetUser(ctx) games, err := a.GameService.ListByAuthor(ctx.Request().Context(), user) if err != nil { return echo.ErrNotFound } resp := make(api.GameListResponse, 0, len(games)) for _, game := range games { gv := api.GameView{ Id: game.ID, Title: game.Title, Type: api.MapGameTypeReverse(game.Type), Points: game.Points, TaskCount: len(game.Tasks), CreatedAt: game.CreatedAt.Format(time.RFC3339), Icon: game.IconID, } resp = append(resp, gv) } return ctx.JSON(http.StatusOK, resp) } func (*Admin) mapCreateGameRequest(req *api.GameEdit, user *models.User) *models.Game { id := uuid.New() if req.Id != nil { id = *req.Id } game := &models.Game{ ID: id, Visible: req.Visible, Title: req.Title, Description: req.Description, Authors: []*models.User{ user, }, Type: api.MapGameType(req.Type), Tasks: make([]*models.Task, 0, len(req.Tasks)), Points: req.Points, IconID: req.Icon, } for order, te := range req.Tasks { id := uuid.New() if te.Id != nil { id = *te.Id } task := &models.Task{ ID: id, Title: te.Title, Text: te.Text, Codes: make([]*models.Code, 0, len(te.Codes)), TaskOrder: uint(order), } for _, ce := range te.Codes { id := uuid.New() if ce.Id != nil { id = *ce.Id } task.Codes = append(task.Codes, &models.Code{ ID: id, Code: ce.Code, Description: ce.Description, }) } game.Tasks = append(game.Tasks, task) } return game }