feat: extend problem fields
This commit is contained in:
parent
3ed195bb58
commit
6dc8f05675
14 changed files with 70 additions and 362 deletions
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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"`
|
||||
}
|
||||
|
|
|
@ -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"`
|
||||
}
|
||||
|
|
|
@ -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"`
|
||||
}
|
||||
|
|
|
@ -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"`
|
||||
}
|
||||
|
|
|
@ -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"`
|
||||
}
|
|
@ -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),
|
||||
},
|
||||
|
|
|
@ -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
|
||||
//}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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
2
proto
|
@ -1 +1 @@
|
|||
Subproject commit e6de2af416b636ffc84d2bedccdc3c79592af1b9
|
||||
Subproject commit c6824ea56aee42b5491fada04eb1f1b33162c1ea
|
Loading…
Reference in a new issue