feat: extend problem fields

This commit is contained in:
Vyacheslav1557 2024-10-17 00:34:43 +05:00
parent 3ed195bb58
commit 6dc8f05675
14 changed files with 70 additions and 362 deletions

View file

@ -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
}

View file

@ -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)
}

View file

@ -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"`
CreatedAt *time.Time `db:"created_at"`
UpdatedAt *time.Time `db:"updated_at"`
}

View file

@ -5,11 +5,14 @@ import "time"
type Problem struct {
Id *int32 `db:"id"`
Title *string `db:"title"`
Content *string `db:"content"`
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"`
TestingStrategy *int32 `db:"testing_strategy"`
TestingOrder *string `db:"testing_order"`
CreatedAt *time.Time `db:"created_at"`
UpdatedAt *time.Time `db:"updated_at"`
}

View file

@ -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"`
}

View file

@ -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"`
ContestId *int32 `db:"contest_id"`
Position *int32 `db:"position"`
PositionName *string `db:"position_name"`
CreatedAt *time.Time `db:"created_at"`
UpdatedAt *time.Time `db:"updated_at"`
}

View file

@ -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"`
}

View file

@ -38,11 +38,14 @@ func (h *problemHandlers) ReadProblem(ctx context.Context, req *problemv1.ReadPr
Problem: &problemv1.ReadProblemResponse_Problem{
Id: *problem.Id,
Title: *problem.Title,
Content: *problem.Content,
Legend: *problem.Legend,
InputFormat: *problem.InputFormat,
OutputFormat: *problem.OutputFormat,
Notes: *problem.Notes,
Tutorial: *problem.Tutorial,
LatexSummary: *problem.LatexSummary,
TimeLimit: *problem.TimeLimit,
MemoryLimit: *problem.MemoryLimit,
TestingStrategy: *problem.TestingStrategy,
TestingOrder: *problem.TestingOrder,
CreatedAt: utils.TimestampP(problem.CreatedAt),
UpdatedAt: utils.TimestampP(problem.UpdatedAt),
},

View file

@ -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
//}

View file

@ -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
}

View file

@ -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
}

View file

@ -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)
}

View file

@ -3,19 +3,21 @@
CREATE TABLE IF NOT EXISTS problems
(
id serial NOT NULL,
title varchar(255) NOT NULL,
content varchar(65536) NOT NULL DEFAULT '',
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,
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(),
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
@ -27,7 +29,7 @@ EXECUTE PROCEDURE updated_at_update();
CREATE TABLE IF NOT EXISTS contests
(
id serial NOT NULL,
title varchar(255) NOT NULL,
title varchar(64) NOT NULL,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
PRIMARY KEY (id),
@ -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)
);
@ -65,7 +67,7 @@ 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,
name varchar(64) NOT NULL,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
PRIMARY KEY (id),
@ -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

2
proto

@ -1 +1 @@
Subproject commit e6de2af416b636ffc84d2bedccdc3c79592af1b9
Subproject commit c6824ea56aee42b5491fada04eb1f1b33162c1ea