From 6dc8f05675454ca676dd0805be6ca9aff68645b6 Mon Sep 17 00:00:00 2001 From: Vyacheslav1557 Date: Thu, 17 Oct 2024 00:34:43 +0500 Subject: [PATCH] feat: extend problem fields --- internal/contests/usecase/contest.rego | 44 ------------- internal/contests/usecase/policy_agent.go | 39 ------------ internal/models/participant.go | 12 ++-- internal/models/problem.go | 21 ++++--- internal/models/solution.go | 9 +-- internal/models/task.go | 13 ++-- internal/models/user.go | 9 --- internal/problems/delivery/grpc/handlers.go | 21 ++++--- internal/problems/usecase/policy_agent.go | 67 -------------------- internal/problems/usecase/problem.rego | 44 ------------- internal/tester/usecase/all.rego | 44 ------------- internal/tester/usecase/permission.go | 39 ------------ migrations/20240727123308_initial.sql | 68 ++++++++------------- proto | 2 +- 14 files changed, 70 insertions(+), 362 deletions(-) delete mode 100644 internal/contests/usecase/contest.rego delete mode 100644 internal/contests/usecase/policy_agent.go delete mode 100644 internal/models/user.go delete mode 100644 internal/problems/usecase/policy_agent.go delete mode 100644 internal/problems/usecase/problem.rego delete mode 100644 internal/tester/usecase/all.rego delete mode 100644 internal/tester/usecase/permission.go diff --git a/internal/contests/usecase/contest.rego b/internal/contests/usecase/contest.rego deleted file mode 100644 index 8525c6a..0000000 --- a/internal/contests/usecase/contest.rego +++ /dev/null @@ -1,44 +0,0 @@ -package problem.rbac - -import rego.v1 - -spectator := 0 -participant := 1 -moderator := 2 -admin := 3 - -permissions := { - "read": is_spectator, - "participate": is_participant, - "update": is_moderator, - "create": is_moderator, - "delete": is_moderator, -} - -default allow := false - -allow if is_admin - -allow if { - permissions[input.action] -} - -default is_admin := false -is_admin if { - input.user.role == admin -} - -default is_moderator := false -is_moderator if { - input.user.role >= moderator -} - -default is_participant := false -is_participant if { - input.user.role >= participant -} - -default is_spectator := true -is_spectator if { - input.user.role >= spectator -} diff --git a/internal/contests/usecase/policy_agent.go b/internal/contests/usecase/policy_agent.go deleted file mode 100644 index a83c19c..0000000 --- a/internal/contests/usecase/policy_agent.go +++ /dev/null @@ -1,39 +0,0 @@ -package usecase - -import ( - "context" - "git.sch9.ru/new_gate/ms-tester/internal/models" - "github.com/open-policy-agent/opa/rego" -) - -type PermissionService struct { - query *rego.PreparedEvalQuery -} - -func NewPermissionService() *PermissionService { - query, err := rego.New( - rego.Query("allow = data.problem.rbac.allow"), - rego.Load([]string{"./opa/problem.rego"}, nil), - ).PrepareForEval(context.TODO()) - - if err != nil { - panic(err) - } - - return &PermissionService{ - query: &query, - } -} - -func (s *PermissionService) Allowed(ctx context.Context, user *models.User, action string) bool { - input := map[string]interface{}{ - "user": user, - "action": action, - } - - result, err := s.query.Eval(ctx, rego.EvalInput(input)) - if err != nil { - panic(err) - } - return result[0].Bindings["allow"].(bool) -} diff --git a/internal/models/participant.go b/internal/models/participant.go index 8db6814..69c61c3 100644 --- a/internal/models/participant.go +++ b/internal/models/participant.go @@ -1,8 +1,12 @@ package models +import "time" + type Participant struct { - Id *int32 `db:"id"` - UserId *int32 `db:"user_id"` - ContestId *int32 `db:"contest_id"` - Name *string `db:"name"` + Id *int32 `db:"id"` + UserId *int32 `db:"user_id"` + ContestId *int32 `db:"contest_id"` + Name *string `db:"name"` + CreatedAt *time.Time `db:"created_at"` + UpdatedAt *time.Time `db:"updated_at"` } diff --git a/internal/models/problem.go b/internal/models/problem.go index 5708170..c334c10 100644 --- a/internal/models/problem.go +++ b/internal/models/problem.go @@ -3,13 +3,16 @@ package models import "time" type Problem struct { - Id *int32 `db:"id"` - Title *string `db:"title"` - Content *string `db:"content"` - TimeLimit *int32 `db:"time_limit"` - MemoryLimit *int32 `db:"memory_limit"` - TestingStrategy *int32 `db:"testing_strategy"` - TestingOrder *string `db:"testing_order"` - CreatedAt *time.Time `db:"created_at"` - UpdatedAt *time.Time `db:"updated_at"` + Id *int32 `db:"id"` + Title *string `db:"title"` + Legend *string `db:"legend"` + InputFormat *string `db:"input_format"` + OutputFormat *string `db:"output_format"` + Notes *string `db:"notes"` + Tutorial *string `db:"tutorial"` + LatexSummary *string `db:"latex_summary"` + TimeLimit *int32 `db:"time_limit"` + MemoryLimit *int32 `db:"memory_limit"` + CreatedAt *time.Time `db:"created_at"` + UpdatedAt *time.Time `db:"updated_at"` } diff --git a/internal/models/solution.go b/internal/models/solution.go index 4064a5a..7c8bc24 100644 --- a/internal/models/solution.go +++ b/internal/models/solution.go @@ -4,11 +4,12 @@ import "time" type Solution struct { Id *int32 `db:"id"` - ParticipantId *int32 `db:"participant_id"` TaskId *int32 `db:"task_id"` - LanguageId *int32 `db:"language_id"` - SolutionHash *string `db:"solution_hash"` - Result *int32 `db:"result"` + ParticipantId *int32 `db:"participant_id"` + State *int32 `db:"state"` Score *int32 `db:"score"` + Penalty *int32 `db:"penalty"` + TotalScore *int32 `db:"total_score"` + Language *int32 `db:"language"` CreatedAt *time.Time `db:"created_at"` } diff --git a/internal/models/task.go b/internal/models/task.go index 4fb57a4..aa945a1 100644 --- a/internal/models/task.go +++ b/internal/models/task.go @@ -1,9 +1,12 @@ package models +import "time" + type Task struct { - Id *int32 `db:"id"` - ContestId *int32 `db:"contest_id"` - ProblemId *int32 `db:"problem_id"` - Position *int32 `db:"position"` - PositionName *string `db:"position_name"` + Id *int32 `db:"id"` + ProblemId *int32 `db:"problem_id"` + ContestId *int32 `db:"contest_id"` + Position *int32 `db:"position"` + CreatedAt *time.Time `db:"created_at"` + UpdatedAt *time.Time `db:"updated_at"` } diff --git a/internal/models/user.go b/internal/models/user.go deleted file mode 100644 index 357600c..0000000 --- a/internal/models/user.go +++ /dev/null @@ -1,9 +0,0 @@ -package models - -import "time" - -type User struct { - UserId *int32 `json:"user_id" db:"user_id"` - Role *Role `json:"role" db:"role"` - UpdatedAt *time.Time `json:"updated_at" db:"updated_at"` -} diff --git a/internal/problems/delivery/grpc/handlers.go b/internal/problems/delivery/grpc/handlers.go index 989462a..8143a6f 100644 --- a/internal/problems/delivery/grpc/handlers.go +++ b/internal/problems/delivery/grpc/handlers.go @@ -36,15 +36,18 @@ func (h *problemHandlers) ReadProblem(ctx context.Context, req *problemv1.ReadPr } return &problemv1.ReadProblemResponse{ Problem: &problemv1.ReadProblemResponse_Problem{ - Id: *problem.Id, - Title: *problem.Title, - Content: *problem.Content, - TimeLimit: *problem.TimeLimit, - MemoryLimit: *problem.MemoryLimit, - TestingStrategy: *problem.TestingStrategy, - TestingOrder: *problem.TestingOrder, - CreatedAt: utils.TimestampP(problem.CreatedAt), - UpdatedAt: utils.TimestampP(problem.UpdatedAt), + Id: *problem.Id, + Title: *problem.Title, + Legend: *problem.Legend, + InputFormat: *problem.InputFormat, + OutputFormat: *problem.OutputFormat, + Notes: *problem.Notes, + Tutorial: *problem.Tutorial, + LatexSummary: *problem.LatexSummary, + TimeLimit: *problem.TimeLimit, + MemoryLimit: *problem.MemoryLimit, + CreatedAt: utils.TimestampP(problem.CreatedAt), + UpdatedAt: utils.TimestampP(problem.UpdatedAt), }, }, nil } diff --git a/internal/problems/usecase/policy_agent.go b/internal/problems/usecase/policy_agent.go deleted file mode 100644 index 4406f4b..0000000 --- a/internal/problems/usecase/policy_agent.go +++ /dev/null @@ -1,67 +0,0 @@ -package usecase - -import ( - "context" - "git.sch9.ru/new_gate/ms-tester/internal/models" - "github.com/open-policy-agent/opa/rego" -) - -type PermissionService struct { - query *rego.PreparedEvalQuery -} - -func NewPermissionService() *PermissionService { - query, err := rego.New( - rego.Query("allow = data.problem.rbac.allow"), - rego.Load([]string{"./opa/problem.rego"}, nil), - ).PrepareForEval(context.TODO()) - - if err != nil { - panic(err) - } - - return &PermissionService{ - query: &query, - } -} - -func (s *PermissionService) Allowed(ctx context.Context, user *models.User, action string) bool { - input := map[string]interface{}{ - "user": user, - "action": action, - } - - result, err := s.query.Eval(ctx, rego.EvalInput(input)) - if err != nil { - panic(err) - } - return result[0].Bindings["allow"].(bool) -} - -//func (service *ProblemUseCase) CanCreateProblem(ctx context.Context) error { -// if !service.permissionService.Allowed(ctx, extractUser(ctx), "create") { -// return utils.ServiceError(nil, utils.ErrNoPermission, "permission denied") -// } -// return nil -//} -// -//func (service *ProblemUseCase) CanReadProblemById(ctx context.Context) error { -// if !service.permissionService.Allowed(ctx, extractUser(ctx), "read") { -// return utils.ServiceError(nil, utils.ErrNoPermission, "permission denied") -// } -// return nil -//} -// -//func (service *ProblemUseCase) CanUpdateProblem(ctx context.Context) error { -// if !service.permissionService.Allowed(ctx, extractUser(ctx), "update") { -// return utils.ServiceError(nil, utils.ErrNoPermission, "permission denied") -// } -// return nil -//} -// -//func (service *ProblemUseCase) CanDeleteProblem(ctx context.Context) error { -// if !service.permissionService.Allowed(ctx, extractUser(ctx), "delete") { -// return utils.ServiceError(nil, utils.ErrNoPermission, "permission denied") -// } -// return nil -//} diff --git a/internal/problems/usecase/problem.rego b/internal/problems/usecase/problem.rego deleted file mode 100644 index 8525c6a..0000000 --- a/internal/problems/usecase/problem.rego +++ /dev/null @@ -1,44 +0,0 @@ -package problem.rbac - -import rego.v1 - -spectator := 0 -participant := 1 -moderator := 2 -admin := 3 - -permissions := { - "read": is_spectator, - "participate": is_participant, - "update": is_moderator, - "create": is_moderator, - "delete": is_moderator, -} - -default allow := false - -allow if is_admin - -allow if { - permissions[input.action] -} - -default is_admin := false -is_admin if { - input.user.role == admin -} - -default is_moderator := false -is_moderator if { - input.user.role >= moderator -} - -default is_participant := false -is_participant if { - input.user.role >= participant -} - -default is_spectator := true -is_spectator if { - input.user.role >= spectator -} diff --git a/internal/tester/usecase/all.rego b/internal/tester/usecase/all.rego deleted file mode 100644 index 8525c6a..0000000 --- a/internal/tester/usecase/all.rego +++ /dev/null @@ -1,44 +0,0 @@ -package problem.rbac - -import rego.v1 - -spectator := 0 -participant := 1 -moderator := 2 -admin := 3 - -permissions := { - "read": is_spectator, - "participate": is_participant, - "update": is_moderator, - "create": is_moderator, - "delete": is_moderator, -} - -default allow := false - -allow if is_admin - -allow if { - permissions[input.action] -} - -default is_admin := false -is_admin if { - input.user.role == admin -} - -default is_moderator := false -is_moderator if { - input.user.role >= moderator -} - -default is_participant := false -is_participant if { - input.user.role >= participant -} - -default is_spectator := true -is_spectator if { - input.user.role >= spectator -} diff --git a/internal/tester/usecase/permission.go b/internal/tester/usecase/permission.go deleted file mode 100644 index a83c19c..0000000 --- a/internal/tester/usecase/permission.go +++ /dev/null @@ -1,39 +0,0 @@ -package usecase - -import ( - "context" - "git.sch9.ru/new_gate/ms-tester/internal/models" - "github.com/open-policy-agent/opa/rego" -) - -type PermissionService struct { - query *rego.PreparedEvalQuery -} - -func NewPermissionService() *PermissionService { - query, err := rego.New( - rego.Query("allow = data.problem.rbac.allow"), - rego.Load([]string{"./opa/problem.rego"}, nil), - ).PrepareForEval(context.TODO()) - - if err != nil { - panic(err) - } - - return &PermissionService{ - query: &query, - } -} - -func (s *PermissionService) Allowed(ctx context.Context, user *models.User, action string) bool { - input := map[string]interface{}{ - "user": user, - "action": action, - } - - result, err := s.query.Eval(ctx, rego.EvalInput(input)) - if err != nil { - panic(err) - } - return result[0].Bindings["allow"].(bool) -} diff --git a/migrations/20240727123308_initial.sql b/migrations/20240727123308_initial.sql index eec43d1..9a2d71d 100644 --- a/migrations/20240727123308_initial.sql +++ b/migrations/20240727123308_initial.sql @@ -2,20 +2,22 @@ -- +goose StatementBegin CREATE TABLE IF NOT EXISTS problems ( - id serial NOT NULL, - title varchar(255) NOT NULL, - content varchar(65536) NOT NULL DEFAULT '', - time_limit integer NOT NULL DEFAULT 1000, - memory_limit integer NOT NULL DEFAULT 65536, - testing_strategy integer NOT NULL DEFAULT 1, - testing_order varchar(1024) NOT NULL DEFAULT '', - created_at timestamptz NOT NULL DEFAULT now(), - updated_at timestamptz NOT NULL DEFAULT now(), + id serial NOT NULL, + title varchar(64) NOT NULL, + legend varchar(10240) NOT NULL DEFAULT '', + input_format varchar(10240) NOT NULL DEFAULT '', + output_format varchar(10240) NOT NULL DEFAULT '', + notes varchar(10240) NOT NULL DEFAULT '', + tutorial varchar(10240) NOT NULL DEFAULT '', + latex_summary varchar(10240) NOT NULL DEFAULT '', + time_limit integer NOT NULL DEFAULT 1000, + memory_limit integer NOT NULL DEFAULT 65536, + created_at timestamptz NOT NULL DEFAULT now(), + updated_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (id), CHECK (length(title) != 0), CHECK (memory_limit > 0), - CHECK (time_limit > 0), - CHECK (testing_strategy > 0) + CHECK (time_limit > 0) ); CREATE TRIGGER on_problems_update @@ -26,10 +28,10 @@ EXECUTE PROCEDURE updated_at_update(); CREATE TABLE IF NOT EXISTS contests ( - id serial NOT NULL, - title varchar(255) NOT NULL, - created_at timestamptz NOT NULL DEFAULT now(), - updated_at timestamptz NOT NULL DEFAULT now(), + id serial NOT NULL, + title varchar(64) NOT NULL, + created_at timestamptz NOT NULL DEFAULT now(), + updated_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (id), CHECK (length(title) != 0) ); @@ -46,11 +48,11 @@ CREATE TABLE IF NOT EXISTS tasks problem_id integer NOT NULL REFERENCES problems (id), contest_id integer NOT NULL REFERENCES contests (id), position integer NOT NULL, - prefix varchar(10) NOT NULL, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (id), UNIQUE (problem_id, contest_id), + UNIQUE (contest_id, position), CHECK (position >= 0) ); @@ -62,12 +64,12 @@ EXECUTE PROCEDURE updated_at_update(); CREATE TABLE IF NOT EXISTS participants ( - id serial NOT NULL, - user_id integer NOT NULL, - contest_id integer NOT NULL REFERENCES contests (id), - name varchar(255) NOT NULL, - created_at timestamptz NOT NULL DEFAULT now(), - updated_at timestamptz NOT NULL DEFAULT now(), + id serial NOT NULL, + user_id integer NOT NULL, + contest_id integer NOT NULL REFERENCES contests (id), + name varchar(64) NOT NULL, + created_at timestamptz NOT NULL DEFAULT now(), + updated_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (id), UNIQUE (user_id, contest_id), CHECK (length(name) != 0) @@ -86,7 +88,6 @@ CREATE TABLE IF NOT EXISTS solutions participant_id integer NOT NULL REFERENCES participants (id), solution varchar(1048576) NOT NULL, state integer NOT NULL DEFAULT 1, - results varchar(1000) NOT NULL, score integer NOT NULL, penalty integer NOT NULL, total_score integer NOT NULL, @@ -102,25 +103,6 @@ CREATE TRIGGER on_solutions_update FOR EACH ROW EXECUTE PROCEDURE updated_at_update(); -CREATE TABLE IF NOT EXISTS best_solutions -( - id serial NOT NULL, - participant_id integer NOT NULL REFERENCES participants (id), - task_id integer NOT NULL REFERENCES tasks (id), - solution_id integer NOT NULL REFERENCES solutions (id), - best_total_score integer NOT NULL, - created_at timestamptz NOT NULL DEFAULT now(), - updated_at timestamptz NOT NULL DEFAULT now(), - PRIMARY KEY (id), - UNIQUE (participant_id, task_id) -); - -CREATE TRIGGER on_best_solutions_update - BEFORE UPDATE - ON best_solutions - FOR EACH ROW -EXECUTE PROCEDURE updated_at_update(); - CREATE FUNCTION updated_at_update() RETURNS TRIGGER LANGUAGE plpgsql AS $$ @@ -144,7 +126,5 @@ DROP TRIGGER IF EXISTS on_participants_update ON participants; DROP TABLE IF EXISTS participants; DROP TRIGGER IF EXISTS on_solutions_update ON solutions; DROP TABLE IF EXISTS solutions; -DROP TRIGGER IF EXISTS on_best_solutions_update ON best_solutions; -DROP TABLE IF EXISTS best_solutions; DROP FUNCTION updated_at_update(); -- +goose StatementEnd diff --git a/proto b/proto index e6de2af..c6824ea 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit e6de2af416b636ffc84d2bedccdc3c79592af1b9 +Subproject commit c6824ea56aee42b5491fada04eb1f1b33162c1ea