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 /admin/games) func (a *Admin) CreateGame(ctx echo.Context) error { user := contextlib.GetUser(ctx) req := &api.GameEditRequest{} if err := ctx.Bind(req); err != nil { return err } game := a.mapCreateGameRequest(req, user) var err error game, err = a.GameService.CreateGame(ctx.Request().Context(), game) if err != nil { return err } tasks := make([]api.TaskEdit, 0, len(game.Tasks)) for _, t := range game.Tasks { codes := make([]api.CodeEdit, 0, len(t.Codes)) for _, c := range t.Codes { codes = append(codes, api.CodeEdit{ Code: c.Code, Description: c.Description, }) } tasks = append(tasks, api.TaskEdit{ 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, }) } // (POST /games/{uid}) func (a *Admin) EditGame(ctx echo.Context, uid uuid.UUID) error { user := contextlib.GetUser(ctx) req := &api.GameEditRequest{} 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 } } if err = ctx.Bind(req); err != nil { return err } game = a.mapCreateGameRequest(req, user) game, err = a.GameService.UpdateGame(ctx.Request().Context(), uid, 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) GetGameByAdmin(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) ListGamesByAdmin(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.GameEditRequest, user *models.User) *models.Game { game := &models.Game{ Model: models.Model{ ID: uuid.New(), }, 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 { if te.Id == nil { u := uuid.New() te.Id = &u } task := &models.Task{ Model: models.Model{ ID: *te.Id, }, Title: te.Title, Text: te.Text, Codes: make([]*models.Code, 0, len(te.Codes)), TaskOrder: uint(order), } for _, ce := range te.Codes { if ce.Id == nil { u := uuid.New() ce.Id = &u } task.Codes = append(task.Codes, &models.Code{ Model: models.Model{ ID: *ce.Id, }, Code: ce.Code, Description: ce.Description, }) } game.Tasks = append(game.Tasks, task) } return game }