feat: merge auth&tester
This commit is contained in:
parent
0a2dea6c23
commit
441af4c6a2
72 changed files with 4910 additions and 2378 deletions
202
internal/contests/delivery/rest/contests_handlers.go
Normal file
202
internal/contests/delivery/rest/contests_handlers.go
Normal file
|
@ -0,0 +1,202 @@
|
|||
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))
|
||||
}
|
||||
}
|
202
internal/contests/delivery/rest/dto.go
Normal file
202
internal/contests/delivery/rest/dto.go
Normal file
|
@ -0,0 +1,202 @@
|
|||
package rest
|
||||
|
||||
import (
|
||||
testerv1 "git.sch9.ru/new_gate/ms-tester/contracts/tester/v1"
|
||||
"git.sch9.ru/new_gate/ms-tester/internal/models"
|
||||
)
|
||||
|
||||
func GetContestResponseDTO(contest *models.Contest,
|
||||
tasks []*models.TasksListItem,
|
||||
solutions []*models.SolutionsListItem) *testerv1.GetContestResponse {
|
||||
|
||||
m := make(map[int32]*models.SolutionsListItem)
|
||||
|
||||
for i := 0; i < len(solutions); i++ {
|
||||
m[solutions[i].TaskPosition] = solutions[i]
|
||||
}
|
||||
|
||||
resp := testerv1.GetContestResponse{
|
||||
Contest: ContestDTO(*contest),
|
||||
Tasks: make([]struct {
|
||||
Solution testerv1.SolutionsListItem `json:"solution"`
|
||||
Task testerv1.TasksListItem `json:"task"`
|
||||
}, len(tasks)),
|
||||
}
|
||||
|
||||
for i, task := range tasks {
|
||||
solution := testerv1.SolutionsListItem{}
|
||||
if sol, ok := m[task.Position]; ok {
|
||||
solution = SolutionsListItemDTO(*sol)
|
||||
}
|
||||
resp.Tasks[i] = struct {
|
||||
Solution testerv1.SolutionsListItem `json:"solution"`
|
||||
Task testerv1.TasksListItem `json:"task"`
|
||||
}{
|
||||
Solution: solution,
|
||||
Task: TasksListItemDTO(*task),
|
||||
}
|
||||
}
|
||||
|
||||
return &resp
|
||||
}
|
||||
|
||||
func ListContestsResponseDTO(contestsList *models.ContestsList) *testerv1.ListContestsResponse {
|
||||
resp := testerv1.ListContestsResponse{
|
||||
Contests: make([]testerv1.ContestsListItem, len(contestsList.Contests)),
|
||||
Pagination: PaginationDTO(contestsList.Pagination),
|
||||
}
|
||||
|
||||
for i, contest := range contestsList.Contests {
|
||||
resp.Contests[i] = ContestsListItemDTO(*contest)
|
||||
}
|
||||
|
||||
return &resp
|
||||
}
|
||||
|
||||
func ListSolutionsResponseDTO(solutionsList *models.SolutionsList) *testerv1.ListSolutionsResponse {
|
||||
resp := testerv1.ListSolutionsResponse{
|
||||
Solutions: make([]testerv1.SolutionsListItem, len(solutionsList.Solutions)),
|
||||
Pagination: PaginationDTO(solutionsList.Pagination),
|
||||
}
|
||||
|
||||
for i, solution := range solutionsList.Solutions {
|
||||
resp.Solutions[i] = SolutionsListItemDTO(*solution)
|
||||
}
|
||||
|
||||
return &resp
|
||||
}
|
||||
|
||||
func GetTaskResponseDTO(contest *models.Contest, tasks []*models.TasksListItem, task *models.Task) *testerv1.GetTaskResponse {
|
||||
resp := testerv1.GetTaskResponse{
|
||||
Contest: ContestDTO(*contest),
|
||||
Tasks: make([]testerv1.TasksListItem, len(tasks)),
|
||||
Task: *TaskDTO(task),
|
||||
}
|
||||
|
||||
for i, t := range tasks {
|
||||
resp.Tasks[i] = TasksListItemDTO(*t)
|
||||
}
|
||||
|
||||
return &resp
|
||||
}
|
||||
|
||||
func PaginationDTO(p models.Pagination) testerv1.Pagination {
|
||||
return testerv1.Pagination{
|
||||
Page: p.Page,
|
||||
Total: p.Total,
|
||||
}
|
||||
}
|
||||
|
||||
func ContestDTO(c models.Contest) testerv1.Contest {
|
||||
return testerv1.Contest{
|
||||
Id: c.Id,
|
||||
Title: c.Title,
|
||||
CreatedAt: c.CreatedAt,
|
||||
UpdatedAt: c.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
func ContestsListItemDTO(c models.ContestsListItem) testerv1.ContestsListItem {
|
||||
return testerv1.ContestsListItem{
|
||||
Id: c.Id,
|
||||
Title: c.Title,
|
||||
CreatedAt: c.CreatedAt,
|
||||
UpdatedAt: c.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
func TasksListItemDTO(t models.TasksListItem) testerv1.TasksListItem {
|
||||
return testerv1.TasksListItem{
|
||||
Id: t.Id,
|
||||
Position: t.Position,
|
||||
Title: t.Title,
|
||||
MemoryLimit: t.MemoryLimit,
|
||||
ProblemId: t.ProblemId,
|
||||
TimeLimit: t.TimeLimit,
|
||||
CreatedAt: t.CreatedAt,
|
||||
UpdatedAt: t.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
func TaskDTO(t *models.Task) *testerv1.Task {
|
||||
return &testerv1.Task{
|
||||
Id: t.Id,
|
||||
Title: t.Title,
|
||||
MemoryLimit: t.MemoryLimit,
|
||||
TimeLimit: t.TimeLimit,
|
||||
|
||||
InputFormatHtml: t.InputFormatHtml,
|
||||
LegendHtml: t.LegendHtml,
|
||||
NotesHtml: t.NotesHtml,
|
||||
OutputFormatHtml: t.OutputFormatHtml,
|
||||
Position: t.Position,
|
||||
ScoringHtml: t.ScoringHtml,
|
||||
|
||||
CreatedAt: t.CreatedAt,
|
||||
UpdatedAt: t.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
func ParticipantsListItemDTO(p models.ParticipantsListItem) testerv1.ParticipantsListItem {
|
||||
return testerv1.ParticipantsListItem{
|
||||
Id: p.Id,
|
||||
UserId: p.UserId,
|
||||
Name: p.Name,
|
||||
CreatedAt: p.CreatedAt,
|
||||
UpdatedAt: p.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
func SolutionsListItemDTO(s models.SolutionsListItem) testerv1.SolutionsListItem {
|
||||
return testerv1.SolutionsListItem{
|
||||
Id: s.Id,
|
||||
|
||||
ParticipantId: s.ParticipantId,
|
||||
ParticipantName: s.ParticipantName,
|
||||
|
||||
State: s.State,
|
||||
Score: s.Score,
|
||||
Penalty: s.Penalty,
|
||||
TimeStat: s.TimeStat,
|
||||
MemoryStat: s.MemoryStat,
|
||||
Language: s.Language,
|
||||
|
||||
TaskId: s.TaskId,
|
||||
TaskPosition: s.TaskPosition,
|
||||
TaskTitle: s.TaskTitle,
|
||||
|
||||
ContestId: s.ContestId,
|
||||
ContestTitle: s.ContestTitle,
|
||||
|
||||
CreatedAt: s.CreatedAt,
|
||||
UpdatedAt: s.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
func SolutionDTO(s models.Solution) testerv1.Solution {
|
||||
return testerv1.Solution{
|
||||
Id: s.Id,
|
||||
|
||||
ParticipantId: s.ParticipantId,
|
||||
ParticipantName: s.ParticipantName,
|
||||
|
||||
Solution: s.Solution,
|
||||
|
||||
State: s.State,
|
||||
Score: s.Score,
|
||||
Penalty: s.Penalty,
|
||||
TimeStat: s.TimeStat,
|
||||
MemoryStat: s.MemoryStat,
|
||||
Language: s.Language,
|
||||
|
||||
TaskId: s.TaskId,
|
||||
TaskPosition: s.TaskPosition,
|
||||
TaskTitle: s.TaskTitle,
|
||||
|
||||
ContestId: s.ContestId,
|
||||
ContestTitle: s.ContestTitle,
|
||||
|
||||
CreatedAt: s.CreatedAt,
|
||||
UpdatedAt: s.UpdatedAt,
|
||||
}
|
||||
}
|
71
internal/contests/delivery/rest/monitor_handlers.go
Normal file
71
internal/contests/delivery/rest/monitor_handlers.go
Normal file
|
@ -0,0 +1,71 @@
|
|||
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"
|
||||
)
|
||||
|
||||
func (h *Handlers) GetMonitor(c *fiber.Ctx, params testerv1.GetMonitorParams) 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:
|
||||
contest, err := h.contestsUC.GetContest(ctx, params.ContestId)
|
||||
if err != nil {
|
||||
return c.SendStatus(pkg.ToREST(err))
|
||||
}
|
||||
|
||||
monitor, err := h.contestsUC.GetMonitor(ctx, params.ContestId)
|
||||
if err != nil {
|
||||
return c.SendStatus(pkg.ToREST(err))
|
||||
}
|
||||
|
||||
tasks, err := h.contestsUC.GetTasks(ctx, params.ContestId)
|
||||
if err != nil {
|
||||
return c.SendStatus(pkg.ToREST(err))
|
||||
}
|
||||
|
||||
resp := testerv1.GetMonitorResponse{
|
||||
Contest: ContestDTO(*contest),
|
||||
Tasks: make([]testerv1.TasksListItem, len(tasks)),
|
||||
Participants: make([]testerv1.ParticipantsStat, len(monitor.Participants)),
|
||||
SummaryPerProblem: make([]testerv1.ProblemStatSummary, len(monitor.Summary)),
|
||||
}
|
||||
|
||||
for i, participant := range monitor.Participants {
|
||||
resp.Participants[i] = testerv1.ParticipantsStat{
|
||||
Id: participant.Id,
|
||||
Name: participant.Name,
|
||||
PenaltyInTotal: participant.PenaltyInTotal,
|
||||
Solutions: make([]testerv1.SolutionsListItem, len(participant.Solutions)),
|
||||
SolvedInTotal: participant.SolvedInTotal,
|
||||
}
|
||||
|
||||
for j, solution := range participant.Solutions {
|
||||
resp.Participants[i].Solutions[j] = SolutionsListItemDTO(*solution)
|
||||
}
|
||||
}
|
||||
|
||||
for i, problem := range monitor.Summary {
|
||||
resp.SummaryPerProblem[i] = testerv1.ProblemStatSummary{
|
||||
Id: problem.Id,
|
||||
Success: problem.Success,
|
||||
Total: problem.Total,
|
||||
}
|
||||
}
|
||||
|
||||
for i, task := range tasks {
|
||||
resp.Tasks[i] = TasksListItemDTO(*task)
|
||||
}
|
||||
return c.JSON(resp)
|
||||
default:
|
||||
return c.SendStatus(pkg.ToREST(pkg.NoPermission))
|
||||
}
|
||||
}
|
116
internal/contests/delivery/rest/participants_handlers.go
Normal file
116
internal/contests/delivery/rest/participants_handlers.go
Normal file
|
@ -0,0 +1,116 @@
|
|||
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"
|
||||
)
|
||||
|
||||
func (h *Handlers) CreateParticipant(c *fiber.Ctx, params testerv1.CreateParticipantParams) 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.CreateParticipant(ctx, params.ContestId, params.UserId)
|
||||
if err != nil {
|
||||
return c.SendStatus(pkg.ToREST(err))
|
||||
}
|
||||
|
||||
return c.JSON(testerv1.CreateParticipantResponse{
|
||||
Id: id,
|
||||
})
|
||||
default:
|
||||
return c.SendStatus(pkg.ToREST(pkg.NoPermission))
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handlers) UpdateParticipant(c *fiber.Ctx, params testerv1.UpdateParticipantParams) 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.UpdateParticipantRequest
|
||||
err := c.BodyParser(&req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = h.contestsUC.UpdateParticipant(ctx, params.ParticipantId, models.ParticipantUpdate{
|
||||
Name: req.Name,
|
||||
})
|
||||
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) DeleteParticipant(c *fiber.Ctx, params testerv1.DeleteParticipantParams) 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.DeleteParticipant(c.Context(), params.ParticipantId)
|
||||
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) ListParticipants(c *fiber.Ctx, params testerv1.ListParticipantsParams) 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:
|
||||
participantsList, err := h.contestsUC.ListParticipants(c.Context(), models.ParticipantsFilter{
|
||||
Page: params.Page,
|
||||
PageSize: params.PageSize,
|
||||
ContestId: params.ContestId,
|
||||
})
|
||||
if err != nil {
|
||||
return c.SendStatus(pkg.ToREST(err))
|
||||
}
|
||||
|
||||
resp := testerv1.ListParticipantsResponse{
|
||||
Participants: make([]testerv1.ParticipantsListItem, len(participantsList.Participants)),
|
||||
Pagination: PaginationDTO(participantsList.Pagination),
|
||||
}
|
||||
|
||||
for i, participant := range participantsList.Participants {
|
||||
resp.Participants[i] = ParticipantsListItemDTO(*participant)
|
||||
}
|
||||
|
||||
return c.JSON(resp)
|
||||
default:
|
||||
return c.SendStatus(pkg.ToREST(pkg.NoPermission))
|
||||
}
|
||||
}
|
148
internal/contests/delivery/rest/solutions_handlers.go
Normal file
148
internal/contests/delivery/rest/solutions_handlers.go
Normal file
|
@ -0,0 +1,148 @@
|
|||
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))
|
||||
}
|
||||
}
|
105
internal/contests/delivery/rest/tasks_handlers.go
Normal file
105
internal/contests/delivery/rest/tasks_handlers.go
Normal file
|
@ -0,0 +1,105 @@
|
|||
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"
|
||||
)
|
||||
|
||||
func (h *Handlers) CreateTask(c *fiber.Ctx, params testerv1.CreateTaskParams) 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.CreateTask(ctx, params.ContestId, params.ProblemId)
|
||||
if err != nil {
|
||||
return c.SendStatus(pkg.ToREST(err))
|
||||
}
|
||||
|
||||
return c.JSON(testerv1.CreateTaskResponse{
|
||||
Id: id,
|
||||
})
|
||||
default:
|
||||
return c.SendStatus(pkg.ToREST(pkg.NoPermission))
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handlers) GetTask(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(c.Context(), id)
|
||||
if err != nil {
|
||||
return c.SendStatus(pkg.ToREST(err))
|
||||
}
|
||||
|
||||
tasks, err := h.contestsUC.GetTasks(c.Context(), id)
|
||||
if err != nil {
|
||||
return c.SendStatus(pkg.ToREST(err))
|
||||
}
|
||||
|
||||
t, err := h.contestsUC.GetTask(c.Context(), id)
|
||||
if err != nil {
|
||||
return c.SendStatus(pkg.ToREST(err))
|
||||
}
|
||||
|
||||
return c.JSON(GetTaskResponseDTO(contest, tasks, t))
|
||||
case models.RoleStudent:
|
||||
_, err = h.contestsUC.GetParticipantId2(ctx, id, session.UserId)
|
||||
if err != nil {
|
||||
return c.SendStatus(pkg.ToREST(pkg.NoPermission))
|
||||
}
|
||||
|
||||
contest, err := h.contestsUC.GetContest(c.Context(), id)
|
||||
if err != nil {
|
||||
return c.SendStatus(pkg.ToREST(err))
|
||||
}
|
||||
|
||||
tasks, err := h.contestsUC.GetTasks(c.Context(), id)
|
||||
if err != nil {
|
||||
return c.SendStatus(pkg.ToREST(err))
|
||||
}
|
||||
|
||||
t, err := h.contestsUC.GetTask(c.Context(), id)
|
||||
if err != nil {
|
||||
return c.SendStatus(pkg.ToREST(err))
|
||||
}
|
||||
|
||||
return c.JSON(GetTaskResponseDTO(contest, tasks, t))
|
||||
default:
|
||||
return c.SendStatus(pkg.ToREST(pkg.NoPermission))
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handlers) DeleteTask(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.DeleteTask(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))
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue