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

246 lines
5.4 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/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
jwtSecret string
}
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 NewHandlers(problemsUC problems.UseCase) *Handlers {
return &Handlers{
problemsUC: problemsUC,
}
}
func (h *Handlers) ListProblems(c *fiber.Ctx, params testerv1.ListProblemsParams) 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:
problemsList, err := h.problemsUC.ListProblems(c.Context(), models.ProblemsFilter{
Page: params.Page,
PageSize: params.PageSize,
})
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
resp := testerv1.ListProblemsResponse{
Problems: make([]testerv1.ProblemsListItem, len(problemsList.Problems)),
Pagination: PaginationDTO(problemsList.Pagination),
}
for i, problem := range problemsList.Problems {
resp.Problems[i] = ProblemsListItemDTO(*problem)
}
return c.JSON(resp)
default:
return c.SendStatus(pkg.ToREST(pkg.NoPermission))
}
}
func (h *Handlers) CreateProblem(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.problemsUC.CreateProblem(c.Context(), "Название задачи")
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
return c.JSON(testerv1.CreateProblemResponse{
Id: id,
})
default:
return c.SendStatus(pkg.ToREST(pkg.NoPermission))
}
}
func (h *Handlers) DeleteProblem(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.problemsUC.DeleteProblem(c.Context(), 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) GetProblem(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:
problem, err := h.problemsUC.GetProblemById(c.Context(), id)
if err != nil {
return c.SendStatus(pkg.ToREST(err))
}
return c.JSON(
testerv1.GetProblemResponse{Problem: *ProblemDTO(problem)},
)
default:
return c.SendStatus(pkg.ToREST(pkg.NoPermission))
}
}
func (h *Handlers) UpdateProblem(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.UpdateProblemRequest
err := c.BodyParser(&req)
if err != nil {
return err
}
err = h.problemsUC.UpdateProblem(c.Context(), id, &models.ProblemUpdate{
Title: req.Title,
MemoryLimit: req.MemoryLimit,
TimeLimit: req.TimeLimit,
Legend: req.Legend,
InputFormat: req.InputFormat,
OutputFormat: req.OutputFormat,
Notes: req.Notes,
Scoring: req.Scoring,
})
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) UploadProblem(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.UploadProblemRequest
err := c.BodyParser(&req)
if err != nil {
return err
}
data, err := req.Archive.Bytes()
if err != nil {
return err
}
if err = h.problemsUC.UploadProblem(c.Context(), id, data); err != nil {
return err
}
return nil
default:
return c.SendStatus(pkg.ToREST(pkg.NoPermission))
}
}
func PaginationDTO(p models.Pagination) testerv1.Pagination {
return testerv1.Pagination{
Page: p.Page,
Total: p.Total,
}
}
func ProblemsListItemDTO(p models.ProblemsListItem) testerv1.ProblemsListItem {
return testerv1.ProblemsListItem{
Id: p.Id,
Title: p.Title,
MemoryLimit: p.MemoryLimit,
TimeLimit: p.TimeLimit,
CreatedAt: p.CreatedAt,
UpdatedAt: p.UpdatedAt,
SolvedCount: p.SolvedCount,
}
}
func ProblemDTO(p *models.Problem) *testerv1.Problem {
return &testerv1.Problem{
Id: p.Id,
Title: p.Title,
TimeLimit: p.TimeLimit,
MemoryLimit: p.MemoryLimit,
Legend: p.Legend,
InputFormat: p.InputFormat,
OutputFormat: p.OutputFormat,
Notes: p.Notes,
Scoring: p.Scoring,
LegendHtml: p.LegendHtml,
InputFormatHtml: p.InputFormatHtml,
OutputFormatHtml: p.OutputFormatHtml,
NotesHtml: p.NotesHtml,
ScoringHtml: p.ScoringHtml,
CreatedAt: p.CreatedAt,
UpdatedAt: p.UpdatedAt,
}
}