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

148 lines
3.5 KiB
Go

package rest
import (
testerv1 "git.sch9.ru/new_gate/ms-tester/contracts/tester/v1"
"git.sch9.ru/new_gate/ms-tester/internal/models"
"git.sch9.ru/new_gate/ms-tester/pkg"
"github.com/gofiber/fiber/v2"
"io"
)
const (
maxSolutionSize int64 = 10 * 1024 * 1024
)
func (h *Handlers) CreateSolution(c *fiber.Ctx, params testerv1.CreateSolutionParams) 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, models.RoleStudent:
s, err := c.FormFile("solution")
if err != nil {
return err
}
if s.Size == 0 || s.Size > maxSolutionSize {
return c.SendStatus(fiber.StatusBadRequest)
}
f, err := s.Open()
if err != nil {
return err
}
defer f.Close()
b, err := io.ReadAll(f)
if err != nil {
return err
}
id, err := h.contestsUC.CreateSolution(ctx, &models.SolutionCreation{
UserId: session.UserId,
TaskId: params.TaskId,
Language: params.Language,
Solution: string(b),
})
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
return c.JSON(testerv1.CreateSolutionResponse{
Id: id,
})
default:
return c.SendStatus(pkg.ToREST(pkg.NoPermission))
}
}
func (h *Handlers) GetSolution(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:
solution, err := h.contestsUC.GetSolution(ctx, id)
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
return c.JSON(testerv1.GetSolutionResponse{Solution: SolutionDTO(*solution)})
case models.RoleStudent:
_, err := h.contestsUC.GetParticipantId3(ctx, id)
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
solution, err := h.contestsUC.GetSolution(ctx, id)
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
return c.JSON(testerv1.GetSolutionResponse{Solution: SolutionDTO(*solution)})
default:
return c.SendStatus(pkg.ToREST(pkg.NoPermission))
}
}
func (h *Handlers) ListSolutions(c *fiber.Ctx, params testerv1.ListSolutionsParams) error {
ctx := c.Context()
session, err := sessionFromCtx(ctx)
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
filter := models.SolutionsFilter{
ContestId: params.ContestId,
Page: params.Page,
PageSize: params.PageSize,
ParticipantId: params.ParticipantId,
TaskId: params.TaskId,
Language: params.Language,
Order: params.Order,
State: params.State,
}
switch session.Role {
case models.RoleAdmin, models.RoleTeacher:
solutionsList, err := h.contestsUC.ListSolutions(ctx, filter)
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
return c.JSON(ListSolutionsResponseDTO(solutionsList))
case models.RoleStudent:
if params.ContestId == nil {
return c.SendStatus(pkg.ToREST(pkg.NoPermission))
}
participantId, err := h.contestsUC.GetParticipantId(ctx, *params.ContestId, session.UserId)
if err != nil {
return c.SendStatus(pkg.ToREST(pkg.NoPermission))
}
// Student cannot view other users' solutions
if params.ParticipantId != nil && *params.ParticipantId != participantId {
return c.SendStatus(pkg.ToREST(pkg.NoPermission))
}
filter.ParticipantId = &participantId
solutionsList, err := h.contestsUC.ListSolutions(ctx, filter)
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
return c.JSON(ListSolutionsResponseDTO(solutionsList))
default:
return c.SendStatus(pkg.ToREST(pkg.NoPermission))
}
}