ms-tester/internal/contests/delivery/rest/contests_handlers.go
2025-04-22 20:44:52 +05:00

202 lines
4.8 KiB
Go

package rest
import (
"context"
testerv1 "git.sch9.ru/new_gate/ms-tester/contracts/tester/v1"
"git.sch9.ru/new_gate/ms-tester/internal/contests"
"git.sch9.ru/new_gate/ms-tester/internal/models"
"git.sch9.ru/new_gate/ms-tester/internal/problems"
"git.sch9.ru/new_gate/ms-tester/pkg"
"github.com/gofiber/fiber/v2"
)
type Handlers struct {
problemsUC problems.UseCase
contestsUC contests.UseCase
jwtSecret string
}
func NewHandlers(problemsUC problems.UseCase, contestsUC contests.UseCase, jwtSecret string) *Handlers {
return &Handlers{
problemsUC: problemsUC,
contestsUC: contestsUC,
jwtSecret: jwtSecret,
}
}
const (
sessionKey = "session"
)
func sessionFromCtx(ctx context.Context) (*models.Session, error) {
const op = "sessionFromCtx"
session, ok := ctx.Value(sessionKey).(*models.Session)
if !ok {
return nil, pkg.Wrap(pkg.ErrUnauthenticated, nil, op, "")
}
return session, nil
}
func (h *Handlers) CreateContest(c *fiber.Ctx) error {
ctx := c.Context()
session, err := sessionFromCtx(ctx)
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
switch session.Role {
case models.RoleAdmin, models.RoleTeacher:
id, err := h.contestsUC.CreateContest(ctx, "Название контеста")
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
return c.JSON(&testerv1.CreateContestResponse{
Id: id,
})
default:
return c.SendStatus(pkg.ToREST(pkg.NoPermission))
}
}
func (h *Handlers) GetContest(c *fiber.Ctx, id int32) error {
ctx := c.Context()
session, err := sessionFromCtx(ctx)
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
switch session.Role {
case models.RoleAdmin, models.RoleTeacher:
contest, err := h.contestsUC.GetContest(ctx, id)
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
tasks, err := h.contestsUC.GetTasks(ctx, id)
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
solutions := make([]*models.SolutionsListItem, 0)
participantId, err := h.contestsUC.GetParticipantId(ctx, contest.Id, session.UserId)
if err == nil { // Admin or Teacher may not participate in contest
solutions, err = h.contestsUC.GetBestSolutions(ctx, id, participantId)
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
}
return c.JSON(GetContestResponseDTO(contest, tasks, solutions))
case models.RoleStudent:
contest, err := h.contestsUC.GetContest(ctx, id)
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
tasks, err := h.contestsUC.GetTasks(ctx, id)
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
participantId, err := h.contestsUC.GetParticipantId(ctx, contest.Id, session.UserId)
solutions, err := h.contestsUC.GetBestSolutions(c.Context(), id, participantId)
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
return c.JSON(GetContestResponseDTO(contest, tasks, solutions))
default:
return c.SendStatus(pkg.ToREST(pkg.NoPermission))
}
}
func (h *Handlers) UpdateContest(c *fiber.Ctx, id int32) error {
ctx := c.Context()
session, err := sessionFromCtx(ctx)
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
switch session.Role {
case models.RoleAdmin, models.RoleTeacher:
var req testerv1.UpdateContestRequest
err := c.BodyParser(&req)
if err != nil {
return err
}
err = h.contestsUC.UpdateContest(ctx, id, models.ContestUpdate{
Title: req.Title,
})
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
return c.SendStatus(fiber.StatusOK)
default:
return c.SendStatus(pkg.ToREST(pkg.NoPermission))
}
}
func (h *Handlers) DeleteContest(c *fiber.Ctx, id int32) error {
ctx := c.Context()
session, err := sessionFromCtx(ctx)
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
switch session.Role {
case models.RoleAdmin, models.RoleTeacher:
err := h.contestsUC.DeleteContest(ctx, id)
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
return c.SendStatus(fiber.StatusOK)
default:
return c.SendStatus(pkg.ToREST(pkg.NoPermission))
}
}
func (h *Handlers) ListContests(c *fiber.Ctx, params testerv1.ListContestsParams) error {
ctx := c.Context()
session, err := sessionFromCtx(ctx)
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
filter := models.ContestsFilter{
Page: params.Page,
PageSize: params.PageSize,
}
switch session.Role {
case models.RoleAdmin, models.RoleTeacher:
contestsList, err := h.contestsUC.ListContests(ctx, filter)
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
return c.JSON(ListContestsResponseDTO(contestsList))
case models.RoleStudent:
filter.UserId = &session.UserId
contestsList, err := h.contestsUC.ListContests(ctx, filter)
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
return c.JSON(ListContestsResponseDTO(contestsList))
default:
return c.SendStatus(pkg.ToREST(pkg.NoPermission))
}
}