submissions: convert validator backend to gRPC

This commit is contained in:
2025-07-17 21:26:10 -07:00
parent e05f69ef7d
commit 524c56b6b5
10 changed files with 390 additions and 277 deletions

4
go.mod
View File

@@ -5,7 +5,7 @@ go 1.22
toolchain go1.23.3
require (
git.itzana.me/strafesnet/go-grpc v0.0.0-20241129081229-9e166b3d11f7
git.itzana.me/strafesnet/go-grpc v0.0.0-20250719033306-150dea07cf00
git.itzana.me/strafesnet/utils v0.0.0-20220716194944-d8ca164052f9
github.com/dchest/siphash v1.2.3
github.com/go-faster/errors v0.7.1
@@ -53,7 +53,7 @@ require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/segmentio/asm v1.2.0 // indirect
go.uber.org/multierr v1.11.0
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect
golang.org/x/net v0.25.0 // indirect

4
go.sum
View File

@@ -1,7 +1,7 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
git.itzana.me/strafesnet/go-grpc v0.0.0-20241129081229-9e166b3d11f7 h1:5XzWd3ZZjSw1M60IfHuILty2vRPBYiqM0FZ+E7uHCi8=
git.itzana.me/strafesnet/go-grpc v0.0.0-20241129081229-9e166b3d11f7/go.mod h1:X7XTRUScRkBWq8q8bplbeso105RPDlnY7J6Wy1IwBMs=
git.itzana.me/strafesnet/go-grpc v0.0.0-20250719033306-150dea07cf00 h1:L9HiJzMrXCKZhZz+RyUr5RXdMcGQMU85aap6L+QQDZ0=
git.itzana.me/strafesnet/go-grpc v0.0.0-20250719033306-150dea07cf00/go.mod h1:X7XTRUScRkBWq8q8bplbeso105RPDlnY7J6Wy1IwBMs=
git.itzana.me/strafesnet/utils v0.0.0-20220716194944-d8ca164052f9 h1:7lU6jyR7S7Rhh1dnUp7GyIRHUTBXZagw8F4n4hOyxLw=
git.itzana.me/strafesnet/utils v0.0.0-20220716194944-d8ca164052f9/go.mod h1:uyYerSieEt4v0MJCdPLppG0LtJ4Yj035vuTetWGsxjY=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=

View File

@@ -2,18 +2,19 @@ package cmds
import (
"fmt"
"net"
"net/http"
"git.itzana.me/strafesnet/go-grpc/auth"
"git.itzana.me/strafesnet/go-grpc/maps"
"git.itzana.me/strafesnet/go-grpc/users"
"git.itzana.me/strafesnet/go-grpc/validator"
"git.itzana.me/strafesnet/maps-service/pkg/api"
"git.itzana.me/strafesnet/maps-service/pkg/datastore/gormstore"
internal "git.itzana.me/strafesnet/maps-service/pkg/internal"
"git.itzana.me/strafesnet/maps-service/pkg/roblox"
"git.itzana.me/strafesnet/maps-service/pkg/web_api"
"git.itzana.me/strafesnet/maps-service/pkg/service"
"git.itzana.me/strafesnet/maps-service/pkg/validator_controller"
"git.itzana.me/strafesnet/maps-service/pkg/web_api"
"github.com/nats-io/nats.go"
log "github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
@@ -159,18 +160,31 @@ func serve(ctx *cli.Context) error {
log.WithError(err).Fatal("failed to initialize api server")
}
svc_internal := validator_controller.NewService(&svc_inner)
grpcServer := grpc.NewServer()
srv_internal, err := internal.NewServer(&svc_internal, internal.WithPathPrefix("/v1"))
mapfix_controller := validator_controller.NewMapfixesController(&svc_inner)
operation_controller := validator_controller.NewOperationsController(&svc_inner)
script_controller := validator_controller.NewScriptsController(&svc_inner)
script_policy_controller := validator_controller.NewScriptPolicyController(&svc_inner)
submission_controller := validator_controller.NewSubmissionsController(&svc_inner)
validator.RegisterValidatorMapfixServiceServer(grpcServer,&mapfix_controller)
validator.RegisterValidatorOperationServiceServer(grpcServer,&operation_controller)
validator.RegisterValidatorScriptServiceServer(grpcServer,&script_controller)
validator.RegisterValidatorScriptPolicyServiceServer(grpcServer,&script_policy_controller)
validator.RegisterValidatorSubmissionServiceServer(grpcServer,&submission_controller)
port := ctx.Int("port-internal")
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
log.WithError(err).Fatal("failed to initialize api server")
log.WithField("error", err).Fatalln("failed to net.Listen")
}
// Channel to collect errors
errChan := make(chan error, 2)
// First server
go func(errChan chan error) {
errChan <- http.ListenAndServe(fmt.Sprintf(":%d", ctx.Int("port-internal")), srv_internal)
errChan <- grpcServer.Serve(lis)
}(errChan)
// Second server

View File

@@ -2,9 +2,12 @@ package model
import (
"encoding/json"
"math"
"time"
)
const ValidatorUserID uint64 = uint64(math.MaxInt64)
type AuditEventType int32
// User clicked "Submit", "Accept" etc

View File

@@ -1,46 +0,0 @@
package validator_controller
import (
"context"
"errors"
"math"
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
internal "git.itzana.me/strafesnet/maps-service/pkg/internal"
"git.itzana.me/strafesnet/maps-service/pkg/service"
)
const (
ValidtorUserID uint64 = uint64(math.MaxInt64)
)
var (
ErrNegativeID = errors.New("A negative ID was provided")
)
type Controller struct {
inner *service.Service
}
func NewService(
inner *service.Service,
) Controller {
return Controller{
inner: inner,
}
}
// yay duplicate code
func (svc *Controller) NewError(ctx context.Context, err error) *internal.ErrorStatusCode {
status := 500
if errors.Is(err, datastore.ErrNotExist) {
status = 404
}
return &internal.ErrorStatusCode{
StatusCode: status,
Response: internal.Error{
Code: int64(status),
Message: err.Error(),
},
}
}

View File

@@ -5,12 +5,24 @@ import (
"errors"
"fmt"
"git.itzana.me/strafesnet/go-grpc/validator"
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
internal "git.itzana.me/strafesnet/maps-service/pkg/internal"
"git.itzana.me/strafesnet/maps-service/pkg/model"
"git.itzana.me/strafesnet/maps-service/pkg/service"
)
type Mapfixes struct {
*validator.UnimplementedValidatorMapfixServiceServer
inner *service.Service
}
func NewMapfixesController(
inner *service.Service,
) Mapfixes {
return Mapfixes{
inner: inner,
}
}
var(
// prevent two mapfixes with same asset id
ActiveMapfixStatuses = []model.MapfixStatus{
@@ -34,35 +46,40 @@ var(
// Update model following role restrictions.
//
// POST /mapfixes/{MapfixID}/validated-model
func (svc *Controller) UpdateMapfixValidatedModel(ctx context.Context, params internal.UpdateMapfixValidatedModelParams) error {
ValidatedModelID := uint64(params.ValidatedModelID)
ValidatedModelVersion := uint64(params.ValidatedModelVersion)
func (svc *Mapfixes) SetValidatedModel(ctx context.Context, params *validator.ValidatedModelRequest) (*validator.NullResponse, error) {
MapfixID := int64(params.ID)
// check if Status is ChangesRequested|Submitted|UnderConstruction
update := service.NewMapfixUpdate()
update.SetValidatedAssetID(ValidatedModelID)
update.SetValidatedAssetVersion(ValidatedModelVersion)
update.SetValidatedAssetID(params.ValidatedModelID)
update.SetValidatedAssetVersion(params.ValidatedModelVersion)
// DO NOT reset completed when validated model is updated
// update.Add("completed", false)
err := svc.inner.UpdateMapfixIfStatus(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusValidating}, update)
allow_statuses := []model.MapfixStatus{model.MapfixStatusValidating}
err := svc.inner.UpdateMapfixIfStatus(ctx, MapfixID, allow_statuses, update)
if err != nil {
return err
return nil, err
}
event_data := model.AuditEventDataChangeValidatedModel{
ValidatedModelID: ValidatedModelID,
ValidatedModelVersion: ValidatedModelVersion,
ValidatedModelID: params.ValidatedModelID,
ValidatedModelVersion: params.ValidatedModelVersion,
}
return svc.inner.CreateAuditEventChangeValidatedModel(
err = svc.inner.CreateAuditEventChangeValidatedModel(
ctx,
ValidtorUserID,
model.ValidatorUserID,
model.Resource{
ID: params.MapfixID,
ID: MapfixID,
Type: model.ResourceMapfix,
},
event_data,
)
if err != nil {
return nil, err
}
return &validator.NullResponse{}, nil
}
// ActionMapfixSubmitted invokes actionMapfixSubmitted operation.
@@ -70,7 +87,8 @@ func (svc *Controller) UpdateMapfixValidatedModel(ctx context.Context, params in
// Role Validator changes status from Submitting -> Submitted.
//
// POST /mapfixes/{MapfixID}/status/validator-submitted
func (svc *Controller) ActionMapfixSubmitted(ctx context.Context, params internal.ActionMapfixSubmittedParams) error {
func (svc *Mapfixes) SetStatusSubmitted(ctx context.Context, params *validator.SubmittedRequest) (*validator.NullResponse, error) {
MapfixID := int64(params.ID)
// transaction
target_status := model.MapfixStatusSubmitted
update := service.NewMapfixUpdate()
@@ -80,24 +98,29 @@ func (svc *Controller) ActionMapfixSubmitted(ctx context.Context, params interna
update.SetCreator(params.Creator)
update.SetGameID(uint32(params.GameID))
allow_statuses := []model.MapfixStatus{model.MapfixStatusSubmitting}
err := svc.inner.UpdateMapfixIfStatus(ctx, params.MapfixID, allow_statuses, update)
err := svc.inner.UpdateMapfixIfStatus(ctx, MapfixID, allow_statuses, update)
if err != nil {
return err
return nil, err
}
event_data := model.AuditEventDataAction{
TargetStatus: uint32(target_status),
}
return svc.inner.CreateAuditEventAction(
err = svc.inner.CreateAuditEventAction(
ctx,
ValidtorUserID,
model.ValidatorUserID,
model.Resource{
ID: params.MapfixID,
ID: MapfixID,
Type: model.ResourceMapfix,
},
event_data,
)
if err != nil {
return nil, err
}
return &validator.NullResponse{}, nil
}
// ActionMapfixRequestChanges implements actionMapfixRequestChanges operation.
@@ -105,29 +128,36 @@ func (svc *Controller) ActionMapfixSubmitted(ctx context.Context, params interna
// (Internal endpoint) Role Validator changes status from Submitting -> RequestChanges.
//
// POST /mapfixes/{MapfixID}/status/validator-request-changes
func (svc *Controller) ActionMapfixRequestChanges(ctx context.Context, params internal.ActionMapfixRequestChangesParams) error {
func (svc *Mapfixes) ActionMapfixRequestChanges(ctx context.Context, params *validator.MapfixID) (*validator.NullResponse, error) {
MapfixID := int64(params.ID)
// transaction
target_status := model.MapfixStatusChangesRequested
update := service.NewMapfixUpdate()
update.SetStatusID(target_status)
err := svc.inner.UpdateMapfixIfStatus(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusSubmitting}, update)
allow_statuses := []model.MapfixStatus{model.MapfixStatusSubmitting}
err := svc.inner.UpdateMapfixIfStatus(ctx, MapfixID, allow_statuses, update)
if err != nil {
return err
return nil, err
}
event_data := model.AuditEventDataAction{
TargetStatus: uint32(target_status),
}
return svc.inner.CreateAuditEventAction(
err = svc.inner.CreateAuditEventAction(
ctx,
ValidtorUserID,
model.ValidatorUserID,
model.Resource{
ID: params.MapfixID,
ID: MapfixID,
Type: model.ResourceMapfix,
},
event_data,
)
if err != nil {
return nil, err
}
return &validator.NullResponse{}, nil
}
// ActionMapfixValidate invokes actionMapfixValidate operation.
@@ -135,11 +165,18 @@ func (svc *Controller) ActionMapfixRequestChanges(ctx context.Context, params in
// Role Validator changes status from Validating -> Validated.
//
// POST /mapfixes/{MapfixID}/status/validator-validated
func (svc *Controller) ActionMapfixValidated(ctx context.Context, params internal.ActionMapfixValidatedParams) error {
func (svc *Mapfixes) ActionMapfixValidated(ctx context.Context, params *validator.MapfixID) (*validator.NullResponse, error) {
MapfixID := int64(params.ID)
// transaction
update := service.NewMapfixUpdate()
update.SetStatusID(model.MapfixStatusValidated)
return svc.inner.UpdateMapfixIfStatus(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusValidating}, update)
allow_statuses := []model.MapfixStatus{model.MapfixStatusValidating}
err := svc.inner.UpdateMapfixIfStatus(ctx, MapfixID, allow_statuses, update)
if err != nil {
return nil, err
}
return &validator.NullResponse{}, nil
}
// ActionMapfixAccepted implements actionMapfixAccepted operation.
@@ -147,14 +184,16 @@ func (svc *Controller) ActionMapfixValidated(ctx context.Context, params interna
// (Internal endpoint) Role Validator changes status from Validating -> Accepted.
//
// POST /mapfixes/{MapfixID}/status/validator-failed
func (svc *Controller) ActionMapfixAccepted(ctx context.Context, params internal.ActionMapfixAcceptedParams) error {
func (svc *Mapfixes) ActionMapfixAccepted(ctx context.Context, params *validator.MapfixID) (*validator.NullResponse, error) {
MapfixID := int64(params.ID)
// transaction
target_status := model.MapfixStatusAcceptedUnvalidated
update := service.NewMapfixUpdate()
update.SetStatusID(target_status)
err := svc.inner.UpdateMapfixIfStatus(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusValidating}, update)
allow_statuses := []model.MapfixStatus{model.MapfixStatusValidating}
err := svc.inner.UpdateMapfixIfStatus(ctx, MapfixID, allow_statuses, update)
if err != nil {
return err
return nil, err
}
// push an action audit event
@@ -162,15 +201,20 @@ func (svc *Controller) ActionMapfixAccepted(ctx context.Context, params internal
TargetStatus: uint32(target_status),
}
return svc.inner.CreateAuditEventAction(
err = svc.inner.CreateAuditEventAction(
ctx,
ValidtorUserID,
model.ValidatorUserID,
model.Resource{
ID: params.MapfixID,
ID: MapfixID,
Type: model.ResourceMapfix,
},
event_data,
)
if err != nil {
return nil, err
}
return &validator.NullResponse{}, nil
}
// ActionMapfixUploaded implements actionMapfixUploaded operation.
@@ -178,29 +222,36 @@ func (svc *Controller) ActionMapfixAccepted(ctx context.Context, params internal
// (Internal endpoint) Role Validator changes status from Uploading -> Uploaded.
//
// POST /mapfixes/{MapfixID}/status/validator-uploaded
func (svc *Controller) ActionMapfixUploaded(ctx context.Context, params internal.ActionMapfixUploadedParams) error {
func (svc *Mapfixes) ActionMapfixUploaded(ctx context.Context, params *validator.MapfixID) (*validator.NullResponse, error) {
MapfixID := int64(params.ID)
// transaction
target_status := model.MapfixStatusUploaded
update := service.NewMapfixUpdate()
update.SetStatusID(target_status)
err := svc.inner.UpdateMapfixIfStatus(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusUploading}, update)
allow_statuses := []model.MapfixStatus{model.MapfixStatusUploading}
err := svc.inner.UpdateMapfixIfStatus(ctx, MapfixID, allow_statuses, update)
if err != nil {
return err
return nil, err
}
event_data := model.AuditEventDataAction{
TargetStatus: uint32(target_status),
}
return svc.inner.CreateAuditEventAction(
err = svc.inner.CreateAuditEventAction(
ctx,
ValidtorUserID,
model.ValidatorUserID,
model.Resource{
ID: params.MapfixID,
ID: MapfixID,
Type: model.ResourceMapfix,
},
event_data,
)
if err != nil {
return nil, err
}
return &validator.NullResponse{}, nil
}
// CreateMapfixAuditError implements createMapfixAuditError operation.
@@ -208,20 +259,26 @@ func (svc *Controller) ActionMapfixUploaded(ctx context.Context, params internal
// Post an error to the audit log
//
// POST /mapfixes/{MapfixID}/error
func (svc *Controller) CreateMapfixAuditError(ctx context.Context, params internal.CreateMapfixAuditErrorParams) (error) {
func (svc *Mapfixes) CreateMapfixAuditError(ctx context.Context, params *validator.AuditErrorRequest) (*validator.NullResponse, error) {
MapfixID := int64(params.ID)
event_data := model.AuditEventDataError{
Error: params.ErrorMessage,
}
return svc.inner.CreateAuditEventError(
err := svc.inner.CreateAuditEventError(
ctx,
ValidtorUserID,
model.ValidatorUserID,
model.Resource{
ID: params.MapfixID,
ID: MapfixID,
Type: model.ResourceMapfix,
},
event_data,
)
if err != nil {
return nil, err
}
return &validator.NullResponse{}, nil
}
// CreateMapfixAuditCheckList implements createMapfixAuditCheckList operation.
@@ -229,10 +286,11 @@ func (svc *Controller) CreateMapfixAuditError(ctx context.Context, params intern
// Post a checklist to the audit log
//
// POST /mapfixes/{MapfixID}/checklist
func (svc *Controller) CreateMapfixAuditCheckList(ctx context.Context, check_list internal.CheckList, params internal.CreateMapfixAuditCheckListParams) (error) {
check_list2 := make([]model.Check, len(check_list))
for i, check := range check_list {
check_list2[i] = model.Check{
func (svc *Mapfixes) CreateMapfixAuditCheckList(ctx context.Context, params *validator.AuditChecklistRequest) (*validator.NullResponse, error) {
MapfixID := int64(params.ID)
check_list := make([]model.Check, len(params.CheckList))
for i, check := range params.CheckList {
check_list[i] = model.Check{
Name: check.Name,
Summary: check.Summary,
Passed: check.Passed,
@@ -240,41 +298,33 @@ func (svc *Controller) CreateMapfixAuditCheckList(ctx context.Context, check_lis
}
event_data := model.AuditEventDataCheckList{
CheckList: check_list2,
CheckList: check_list,
}
return svc.inner.CreateAuditEventCheckList(
err := svc.inner.CreateAuditEventCheckList(
ctx,
ValidtorUserID,
model.ValidatorUserID,
model.Resource{
ID: params.MapfixID,
ID: MapfixID,
Type: model.ResourceMapfix,
},
event_data,
)
if err != nil {
return nil, err
}
return &validator.NullResponse{}, nil
}
// POST /mapfixes
func (svc *Controller) CreateMapfix(ctx context.Context, request *internal.MapfixCreate) (*internal.MapfixID, error) {
// sanitization
if request.GameID<0||
request.AssetOwner<0||
request.AssetID<0||
request.AssetVersion<0||
request.TargetAssetID<0{
return nil, ErrNegativeID
}
var GameID=uint32(request.GameID);
var Submitter=uint64(request.AssetOwner);
var AssetID=uint64(request.AssetID);
var AssetVersion=uint64(request.AssetVersion);
var TargetAssetID=uint64(request.TargetAssetID);
func (svc *Mapfixes) Create(ctx context.Context, request *validator.MapfixCreate) (*validator.MapfixID, error) {
var Submitter=request.AssetOwner;
// Check if an active mapfix with the same asset id exists
{
filter := service.NewMapfixFilter()
filter.SetAssetID(AssetID)
filter.SetAssetVersion(AssetVersion)
filter.SetAssetID(request.AssetID)
filter.SetAssetVersion(request.AssetVersion)
filter.SetStatuses(ActiveMapfixStatuses)
active_mapfixes, err := svc.inner.ListMapfixes(ctx, filter, model.Page{
Number: 1,
@@ -288,7 +338,8 @@ func (svc *Controller) CreateMapfix(ctx context.Context, request *internal.Mapfi
}
}
operation, err := svc.inner.GetOperation(ctx, request.OperationID)
OperationID := int32(request.OperationID)
operation, err := svc.inner.GetOperation(ctx, OperationID)
if err != nil {
return nil, err
}
@@ -303,12 +354,12 @@ func (svc *Controller) CreateMapfix(ctx context.Context, request *internal.Mapfi
ID: 0,
DisplayName: request.DisplayName,
Creator: request.Creator,
GameID: GameID,
GameID: request.GameID,
Submitter: Submitter,
AssetID: AssetID,
AssetVersion: AssetVersion,
AssetID: request.AssetID,
AssetVersion: request.AssetVersion,
Completed: false,
TargetAssetID: TargetAssetID,
TargetAssetID: request.TargetAssetID,
StatusID: model.MapfixStatusUnderConstruction,
Description: request.Description,
})
@@ -318,12 +369,12 @@ func (svc *Controller) CreateMapfix(ctx context.Context, request *internal.Mapfi
// mark the operation as completed and provide the path
params := service.NewOperationCompleteParams(fmt.Sprintf("/mapfixes/%d", mapfix.ID))
err = svc.inner.CompleteOperation(ctx, request.OperationID, params)
err = svc.inner.CompleteOperation(ctx, OperationID, params)
if err != nil {
return nil, err
}
return &internal.MapfixID{
MapfixID: mapfix.ID,
return &validator.MapfixID{
ID: uint64(mapfix.ID),
}, nil
}

View File

@@ -3,18 +3,35 @@ package validator_controller
import (
"context"
internal "git.itzana.me/strafesnet/maps-service/pkg/internal"
"git.itzana.me/strafesnet/go-grpc/validator"
"git.itzana.me/strafesnet/maps-service/pkg/service"
)
type Operations struct {
*validator.UnimplementedValidatorOperationServiceServer
inner *service.Service
}
func NewOperationsController(
inner *service.Service,
) Operations {
return Operations{
inner: inner,
}
}
// ActionOperationFailed implements actionOperationFailed operation.
//
// Fail the specified OperationID with a StatusMessage.
//
// POST /operations/{OperationID}/status/operation-failed
func (svc *Controller) ActionOperationFailed(ctx context.Context, params internal.ActionOperationFailedParams) (error) {
func (svc *Operations) Fail(ctx context.Context, params *validator.OperationFailRequest) (*validator.NullResponse, error) {
fail_params := service.NewOperationFailParams(
params.StatusMessage,
)
return svc.inner.FailOperation(ctx, params.OperationID, fail_params)
err := svc.inner.FailOperation(ctx, int32(params.OperationID), fail_params)
if err != nil {
return nil, err
}
return &validator.NullResponse{}, nil
}

View File

@@ -3,18 +3,30 @@ package validator_controller
import (
"context"
api "git.itzana.me/strafesnet/maps-service/pkg/internal"
"git.itzana.me/strafesnet/go-grpc/validator"
"git.itzana.me/strafesnet/maps-service/pkg/model"
"git.itzana.me/strafesnet/maps-service/pkg/service"
)
type ScriptPolicy struct {
*validator.UnimplementedValidatorScriptPolicyServiceServer
inner *service.Service
}
func NewScriptPolicyController(
inner *service.Service,
) ScriptPolicy {
return ScriptPolicy{
inner: inner,
}
}
// CreateScriptPolicy implements createScriptPolicy operation.
//
// Create a new script policy.
//
// POST /script-policy
func (svc *Controller) CreateScriptPolicy(ctx context.Context, req *api.ScriptPolicyCreate) (*api.ScriptPolicyID, error) {
from_script, err := svc.inner.GetScript(ctx, req.FromScriptID)
func (svc *ScriptPolicy) Create(ctx context.Context, req *validator.ScriptPolicyCreate) (*validator.ScriptPolicyID, error) {
from_script, err := svc.inner.GetScript(ctx, int64(req.FromScriptID))
if err != nil {
return nil, err
}
@@ -24,15 +36,15 @@ func (svc *Controller) CreateScriptPolicy(ctx context.Context, req *api.ScriptPo
script, err := svc.inner.CreateScriptPolicy(ctx, model.ScriptPolicy{
ID: 0,
FromScriptHash: from_script.Hash,
ToScriptID: req.ToScriptID,
ToScriptID: int64(req.ToScriptID),
Policy: model.Policy(req.Policy),
})
if err != nil {
return nil, err
}
return &api.ScriptPolicyID{
ScriptPolicyID: script.ID,
return &validator.ScriptPolicyID{
ID: uint64(script.ID),
}, nil
}
@@ -41,40 +53,37 @@ func (svc *Controller) CreateScriptPolicy(ctx context.Context, req *api.ScriptPo
// Get list of script policies.
//
// GET /script-policy
func (svc *Controller) ListScriptPolicy(ctx context.Context, params api.ListScriptPolicyParams) ([]api.ScriptPolicy, error) {
func (svc *ScriptPolicy) List(ctx context.Context, params *validator.ScriptPolicyListRequest) (*validator.ScriptPolicyListResponse, error) {
filter := service.NewScriptPolicyFilter()
if hash_hex, ok := params.FromScriptHash.Get(); ok{
hash_parsed, err := model.HashParse(hash_hex)
if err != nil {
return nil, err
}
filter.SetFromScriptHash(int64(hash_parsed))
if params.Filter.FromScriptHash != nil {
filter.SetFromScriptHash(int64(*params.Filter.FromScriptHash))
}
if to_script_id, to_script_id_ok := params.ToScriptID.Get(); to_script_id_ok{
filter.SetToScriptID(to_script_id)
if params.Filter.ToScriptID != nil {
filter.SetToScriptID(int64(*params.Filter.ToScriptID))
}
if policy, policy_ok := params.Policy.Get(); policy_ok{
filter.SetPolicy(policy)
if params.Filter.Policy != nil {
filter.SetPolicy(int32(*params.Filter.Policy))
}
items, err := svc.inner.ListScriptPolicies(ctx, filter, model.Page{
Number: params.Page,
Size: params.Limit,
Number: int32(params.Page.Number),
Size: int32(params.Page.Size),
})
if err != nil {
return nil, err
}
var resp []api.ScriptPolicy
for _, item := range items {
resp = append(resp, api.ScriptPolicy{
ID: item.ID,
FromScriptHash: model.HashFormat(uint64(item.FromScriptHash)),
ToScriptID: item.ToScriptID,
Policy: int32(item.Policy),
})
resp := validator.ScriptPolicyListResponse{}
resp.ScriptPolicies = make([]*validator.ScriptPolicy, len(items))
for i, item := range items {
resp.ScriptPolicies[i] = &validator.ScriptPolicy{
ID: uint64(item.ID),
FromScriptHash: uint64(item.FromScriptHash),
ToScriptID: uint64(item.ToScriptID),
Policy: validator.Policy(int32(item.Policy)),
}
}
return resp, nil
return &resp, nil
}

View File

@@ -3,31 +3,47 @@ package validator_controller
import (
"context"
api "git.itzana.me/strafesnet/maps-service/pkg/internal"
"git.itzana.me/strafesnet/go-grpc/validator"
"git.itzana.me/strafesnet/maps-service/pkg/model"
"git.itzana.me/strafesnet/maps-service/pkg/service"
)
type Scripts struct {
*validator.UnimplementedValidatorScriptServiceServer
inner *service.Service
}
func NewScriptsController(
inner *service.Service,
) Scripts {
return Scripts{
inner: inner,
}
}
// CreateScript implements createScript operation.
//
// Create a new script.
//
// POST /scripts
func (svc *Controller) CreateScript(ctx context.Context, req *api.ScriptCreate) (*api.ScriptID, error) {
func (svc *Scripts) Create(ctx context.Context, req *validator.ScriptCreate) (*validator.ScriptID, error) {
ResourceID := int64(0)
if req.ResourceID != nil {
ResourceID = int64(*req.ResourceID)
}
script, err := svc.inner.CreateScript(ctx, model.Script{
ID: 0,
Name: req.Name,
Hash: int64(model.HashSource(req.Source)),
Source: req.Source,
ResourceType: model.ResourceType(req.ResourceType),
ResourceID: req.ResourceID.Or(0),
ResourceID: ResourceID,
})
if err != nil {
return nil, err
}
return &api.ScriptID{
ScriptID: script.ID,
return &validator.ScriptID{
ID: uint64(script.ID),
}, nil
}
@@ -36,49 +52,47 @@ func (svc *Controller) CreateScript(ctx context.Context, req *api.ScriptCreate)
// Get list of scripts.
//
// GET /scripts
func (svc *Controller) ListScripts(ctx context.Context, params api.ListScriptsParams) ([]api.Script, error) {
func (svc *Scripts) List(ctx context.Context, params *validator.ScriptListRequest) (*validator.ScriptListResponse, error) {
filter := service.NewScriptFilter()
if hash_hex, ok := params.Hash.Get(); ok{
hash_parsed, err := model.HashParse(hash_hex)
if err != nil {
return nil, err
}
filter.SetHash(int64(hash_parsed))
if params.Filter.Hash != nil {
filter.SetHash(int64(*params.Filter.Hash))
}
if name, name_ok := params.Name.Get(); name_ok{
filter.SetName(name)
if params.Filter.Name != nil {
filter.SetName(*params.Filter.Name)
}
if source, source_ok := params.Source.Get(); source_ok{
filter.SetSource(source)
if params.Filter.Source != nil {
filter.SetSource(*params.Filter.Source)
}
if resource_type, resource_type_ok := params.ResourceType.Get(); resource_type_ok{
filter.SetResourceType(resource_type)
if params.Filter.ResourceType != nil {
filter.SetResourceType(int32(*params.Filter.ResourceType))
}
if resource_id, resource_id_ok := params.ResourceID.Get(); resource_id_ok{
filter.SetResourceID(resource_id)
if params.Filter.ResourceID != nil {
filter.SetResourceID(int64(*params.Filter.ResourceID))
}
items, err := svc.inner.ListScripts(ctx, filter, model.Page{
Number: params.Page,
Size: params.Limit,
Number: int32(params.Page.Number),
Size: int32(params.Page.Size),
})
if err != nil {
return nil, err
}
var resp []api.Script
for _, item := range items {
resp = append(resp, api.Script{
ID: item.ID,
resp := validator.ScriptListResponse{}
resp.Scripts = make([]*validator.Script, len(items))
for i, item := range items {
resource_id := uint64(item.ResourceID)
resp.Scripts[i] = &validator.Script{
ID: uint64(item.ID),
Name: item.Name,
Hash: model.HashFormat(uint64(item.Hash)),
Hash: uint64(item.Hash),
Source: item.Source,
ResourceType: int32(item.ResourceType),
ResourceID: item.ResourceID,
})
ResourceType: validator.ResourceType(item.ResourceType),
ResourceID: &resource_id,
}
}
return resp, nil
return &resp, nil
}
// GetScript implements getScript operation.
@@ -86,18 +100,20 @@ func (svc *Controller) ListScripts(ctx context.Context, params api.ListScriptsPa
// Get the specified script by ID.
//
// GET /scripts/{ScriptID}
func (svc *Controller) GetScript(ctx context.Context, params api.GetScriptParams) (*api.Script, error) {
script, err := svc.inner.GetScript(ctx, params.ScriptID)
func (svc *Scripts) Get(ctx context.Context, params *validator.ScriptID) (*validator.Script, error) {
ScriptID := int64(params.ID)
script, err := svc.inner.GetScript(ctx, ScriptID)
if err != nil {
return nil, err
}
return &api.Script{
ID: script.ID,
ResourceID := uint64(script.ResourceID)
return &validator.Script{
ID: uint64(script.ID),
Name: script.Name,
Hash: model.HashFormat(uint64(script.Hash)),
Hash: uint64(script.Hash),
Source: script.Source,
ResourceType: int32(script.ResourceType),
ResourceID: script.ResourceID,
ResourceType: validator.ResourceType(script.ResourceType),
ResourceID: &ResourceID,
}, nil
}

View File

@@ -5,12 +5,24 @@ import (
"errors"
"fmt"
"git.itzana.me/strafesnet/go-grpc/validator"
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
internal "git.itzana.me/strafesnet/maps-service/pkg/internal"
"git.itzana.me/strafesnet/maps-service/pkg/model"
"git.itzana.me/strafesnet/maps-service/pkg/service"
)
type Submissions struct {
*validator.UnimplementedValidatorSubmissionServiceServer
inner *service.Service
}
func NewSubmissionsController(
inner *service.Service,
) Submissions {
return Submissions{
inner: inner,
}
}
var(
// prevent two mapfixes with same asset id
ActiveSubmissionStatuses = []model.SubmissionStatus{
@@ -33,36 +45,40 @@ var(
// Update model following role restrictions.
//
// POST /submissions/{SubmissionID}/validated-model
func (svc *Controller) UpdateSubmissionValidatedModel(ctx context.Context, params internal.UpdateSubmissionValidatedModelParams) error {
ValidatedModelID := uint64(params.ValidatedModelID)
ValidatedModelVersion := uint64(params.ValidatedModelVersion)
func (svc *Submissions) SetValidatedModel(ctx context.Context, params *validator.ValidatedModelRequest) (*validator.NullResponse, error) {
SubmissionID := int64(params.ID)
// check if Status is ChangesRequested|Submitted|UnderConstruction
update := service.NewSubmissionUpdate()
update.SetValidatedAssetID(ValidatedModelID)
update.SetValidatedAssetVersion(ValidatedModelVersion)
update.SetValidatedAssetID(params.ValidatedModelID)
update.SetValidatedAssetVersion(params.ValidatedModelVersion)
// DO NOT reset completed when validated model is updated
// update.Add("completed", false)
allowed_statuses := []model.SubmissionStatus{model.SubmissionStatusValidating}
err := svc.inner.UpdateSubmissionIfStatus(ctx, params.SubmissionID, allowed_statuses, update)
err := svc.inner.UpdateSubmissionIfStatus(ctx, SubmissionID, allowed_statuses, update)
if err != nil {
return err
return nil, err
}
event_data := model.AuditEventDataChangeValidatedModel{
ValidatedModelID: ValidatedModelID,
ValidatedModelVersion: ValidatedModelVersion,
ValidatedModelID: params.ValidatedModelID,
ValidatedModelVersion: params.ValidatedModelVersion,
}
return svc.inner.CreateAuditEventChangeValidatedModel(
err = svc.inner.CreateAuditEventChangeValidatedModel(
ctx,
ValidtorUserID,
model.ValidatorUserID,
model.Resource{
ID: params.SubmissionID,
ID: SubmissionID,
Type: model.ResourceSubmission,
},
event_data,
)
if err != nil {
return nil, err
}
return &validator.NullResponse{}, nil
}
// ActionSubmissionSubmitted invokes actionSubmissionSubmitted operation.
@@ -70,7 +86,8 @@ func (svc *Controller) UpdateSubmissionValidatedModel(ctx context.Context, param
// Role Validator changes status from Submitting -> Submitted.
//
// POST /submissions/{SubmissionID}/status/validator-submitted
func (svc *Controller) ActionSubmissionSubmitted(ctx context.Context, params internal.ActionSubmissionSubmittedParams) error {
func (svc *Submissions) SetStatusSubmitted(ctx context.Context, params *validator.SubmittedRequest) (*validator.NullResponse, error) {
SubmissionID := int64(params.ID)
// transaction
target_status := model.SubmissionStatusSubmitted
update := service.NewSubmissionUpdate()
@@ -80,24 +97,29 @@ func (svc *Controller) ActionSubmissionSubmitted(ctx context.Context, params int
update.SetCreator(params.Creator)
update.SetGameID(uint32(params.GameID))
allowed_statuses := []model.SubmissionStatus{model.SubmissionStatusSubmitting}
err := svc.inner.UpdateSubmissionIfStatus(ctx, params.SubmissionID, allowed_statuses, update)
err := svc.inner.UpdateSubmissionIfStatus(ctx, SubmissionID, allowed_statuses, update)
if err != nil {
return err
return nil, err
}
event_data := model.AuditEventDataAction{
TargetStatus: uint32(target_status),
}
return svc.inner.CreateAuditEventAction(
err = svc.inner.CreateAuditEventAction(
ctx,
ValidtorUserID,
model.ValidatorUserID,
model.Resource{
ID: params.SubmissionID,
ID: SubmissionID,
Type: model.ResourceSubmission,
},
event_data,
)
if err != nil {
return nil, err
}
return &validator.NullResponse{}, nil
}
// ActionSubmissionRequestChanges implements actionSubmissionRequestChanges operation.
@@ -105,15 +127,16 @@ func (svc *Controller) ActionSubmissionSubmitted(ctx context.Context, params int
// (Internal endpoint) Role Validator changes status from Submitting -> RequestChanges.
//
// POST /submissions/{SubmissionID}/status/validator-request-changes
func (svc *Controller) ActionSubmissionRequestChanges(ctx context.Context, params internal.ActionSubmissionRequestChangesParams) error {
func (svc *Submissions) SetStatusRequestChanges(ctx context.Context, params *validator.SubmissionID) (*validator.NullResponse, error) {
SubmissionID := int64(params.ID)
// transaction
target_status := model.SubmissionStatusChangesRequested
update := service.NewSubmissionUpdate()
update.SetStatusID(target_status)
allowed_statuses :=[]model.SubmissionStatus{model.SubmissionStatusSubmitting}
err := svc.inner.UpdateSubmissionIfStatus(ctx, params.SubmissionID, allowed_statuses, update)
err := svc.inner.UpdateSubmissionIfStatus(ctx, SubmissionID, allowed_statuses, update)
if err != nil {
return err
return nil, err
}
// push an action audit event
@@ -121,15 +144,20 @@ func (svc *Controller) ActionSubmissionRequestChanges(ctx context.Context, param
TargetStatus: uint32(target_status),
}
return svc.inner.CreateAuditEventAction(
err = svc.inner.CreateAuditEventAction(
ctx,
ValidtorUserID,
model.ValidatorUserID,
model.Resource{
ID: params.SubmissionID,
ID: SubmissionID,
Type: model.ResourceSubmission,
},
event_data,
)
if err != nil {
return nil, err
}
return &validator.NullResponse{}, nil
}
// ActionSubmissionValidate invokes actionSubmissionValidate operation.
@@ -137,30 +165,36 @@ func (svc *Controller) ActionSubmissionRequestChanges(ctx context.Context, param
// Role Validator changes status from Validating -> Validated.
//
// POST /submissions/{SubmissionID}/status/validator-validated
func (svc *Controller) ActionSubmissionValidated(ctx context.Context, params internal.ActionSubmissionValidatedParams) error {
func (svc *Submissions) SetStatusValidated(ctx context.Context, params *validator.SubmissionID) (*validator.NullResponse, error) {
SubmissionID := int64(params.ID)
// transaction
target_status := model.SubmissionStatusValidated
update := service.NewSubmissionUpdate()
update.SetStatusID(target_status)
allowed_statuses :=[]model.SubmissionStatus{model.SubmissionStatusValidating}
err := svc.inner.UpdateSubmissionIfStatus(ctx, params.SubmissionID, allowed_statuses, update)
err := svc.inner.UpdateSubmissionIfStatus(ctx, SubmissionID, allowed_statuses, update)
if err != nil {
return err
return nil, err
}
event_data := model.AuditEventDataAction{
TargetStatus: uint32(target_status),
}
return svc.inner.CreateAuditEventAction(
err = svc.inner.CreateAuditEventAction(
ctx,
ValidtorUserID,
model.ValidatorUserID,
model.Resource{
ID: params.SubmissionID,
ID: SubmissionID,
Type: model.ResourceSubmission,
},
event_data,
)
if err != nil {
return nil, err
}
return &validator.NullResponse{}, nil
}
// ActionSubmissionAccepted implements actionSubmissionAccepted operation.
@@ -168,15 +202,16 @@ func (svc *Controller) ActionSubmissionValidated(ctx context.Context, params int
// (Internal endpoint) Role Validator changes status from Validating -> Accepted.
//
// POST /submissions/{SubmissionID}/status/validator-failed
func (svc *Controller) ActionSubmissionAccepted(ctx context.Context, params internal.ActionSubmissionAcceptedParams) error {
func (svc *Submissions) SetStatusFailed(ctx context.Context, params *validator.SubmissionID) (*validator.NullResponse, error) {
SubmissionID := int64(params.ID)
// transaction
target_status := model.SubmissionStatusAcceptedUnvalidated
update := service.NewSubmissionUpdate()
update.SetStatusID(target_status)
allowed_statuses :=[]model.SubmissionStatus{model.SubmissionStatusValidating}
err := svc.inner.UpdateSubmissionIfStatus(ctx, params.SubmissionID, allowed_statuses, update)
err := svc.inner.UpdateSubmissionIfStatus(ctx, SubmissionID, allowed_statuses, update)
if err != nil {
return err
return nil, err
}
// push an action audit event
@@ -184,15 +219,20 @@ func (svc *Controller) ActionSubmissionAccepted(ctx context.Context, params inte
TargetStatus: uint32(target_status),
}
return svc.inner.CreateAuditEventAction(
err = svc.inner.CreateAuditEventAction(
ctx,
ValidtorUserID,
model.ValidatorUserID,
model.Resource{
ID: params.SubmissionID,
ID: SubmissionID,
Type: model.ResourceSubmission,
},
event_data,
)
if err != nil {
return nil, err
}
return &validator.NullResponse{}, nil
}
// ActionSubmissionUploaded implements actionSubmissionUploaded operation.
@@ -200,31 +240,37 @@ func (svc *Controller) ActionSubmissionAccepted(ctx context.Context, params inte
// (Internal endpoint) Role Validator changes status from Uploading -> Uploaded.
//
// POST /submissions/{SubmissionID}/status/validator-uploaded
func (svc *Controller) ActionSubmissionUploaded(ctx context.Context, params internal.ActionSubmissionUploadedParams) error {
func (svc *Submissions) SetStatusUploaded(ctx context.Context, params *validator.StatusUploadedRequest) (*validator.NullResponse, error) {
SubmissionID := int64(params.ID)
// transaction
target_status := model.SubmissionStatusUploaded
update := service.NewSubmissionUpdate()
update.SetStatusID(target_status)
update.SetUploadedAssetID(uint64(params.UploadedAssetID))
update.SetUploadedAssetID(params.UploadedAssetID)
allowed_statuses :=[]model.SubmissionStatus{model.SubmissionStatusUploading}
err := svc.inner.UpdateSubmissionIfStatus(ctx, params.SubmissionID, allowed_statuses, update)
err := svc.inner.UpdateSubmissionIfStatus(ctx, SubmissionID, allowed_statuses, update)
if err != nil {
return err
return nil, err
}
event_data := model.AuditEventDataAction{
TargetStatus: uint32(target_status),
}
return svc.inner.CreateAuditEventAction(
err = svc.inner.CreateAuditEventAction(
ctx,
ValidtorUserID,
model.ValidatorUserID,
model.Resource{
ID: params.SubmissionID,
ID: SubmissionID,
Type: model.ResourceSubmission,
},
event_data,
)
if err != nil {
return nil, err
}
return &validator.NullResponse{}, nil
}
// CreateSubmissionAuditError implements createSubmissionAuditError operation.
@@ -232,20 +278,26 @@ func (svc *Controller) ActionSubmissionUploaded(ctx context.Context, params inte
// Post an error to the audit log
//
// POST /submissions/{SubmissionID}/error
func (svc *Controller) CreateSubmissionAuditError(ctx context.Context, params internal.CreateSubmissionAuditErrorParams) (error) {
func (svc *Submissions) CreateAuditError(ctx context.Context, params *validator.AuditErrorRequest) (*validator.NullResponse, error) {
SubmissionID := int64(params.ID)
event_data := model.AuditEventDataError{
Error: params.ErrorMessage,
}
return svc.inner.CreateAuditEventError(
err := svc.inner.CreateAuditEventError(
ctx,
ValidtorUserID,
model.ValidatorUserID,
model.Resource{
ID: params.SubmissionID,
ID: SubmissionID,
Type: model.ResourceSubmission,
},
event_data,
)
if err != nil {
return nil, err
}
return &validator.NullResponse{}, nil
}
// CreateSubmissionAuditCheckList implements createSubmissionAuditCheckList operation.
@@ -253,10 +305,11 @@ func (svc *Controller) CreateSubmissionAuditError(ctx context.Context, params in
// Post a checklist to the audit log
//
// POST /submissions/{SubmissionID}/checklist
func (svc *Controller) CreateSubmissionAuditCheckList(ctx context.Context, check_list internal.CheckList, params internal.CreateSubmissionAuditCheckListParams) (error) {
check_list2 := make([]model.Check, len(check_list))
for i, check := range check_list {
check_list2[i] = model.Check{
func (svc *Submissions) CreateAuditChecklist(ctx context.Context, params *validator.AuditChecklistRequest) (*validator.NullResponse, error) {
SubmissionID := int64(params.ID)
check_list := make([]model.Check, len(params.CheckList))
for i, check := range params.CheckList {
check_list[i] = model.Check{
Name: check.Name,
Summary: check.Summary,
Passed: check.Passed,
@@ -264,41 +317,36 @@ func (svc *Controller) CreateSubmissionAuditCheckList(ctx context.Context, check
}
event_data := model.AuditEventDataCheckList{
CheckList: check_list2,
CheckList: check_list,
}
return svc.inner.CreateAuditEventCheckList(
err := svc.inner.CreateAuditEventCheckList(
ctx,
ValidtorUserID,
model.ValidatorUserID,
model.Resource{
ID: params.SubmissionID,
ID: SubmissionID,
Type: model.ResourceSubmission,
},
event_data,
)
if err != nil {
return nil, err
}
return &validator.NullResponse{}, nil
}
// POST /submissions
func (svc *Controller) CreateSubmission(ctx context.Context, request *internal.SubmissionCreate) (*internal.SubmissionID, error) {
// sanitization
if request.GameID<0||
request.AssetOwner<0||
request.AssetID<0||
request.AssetVersion<0{
return nil, ErrNegativeID
}
var GameID=uint32(request.GameID);
func (svc *Submissions) Create(ctx context.Context, request *validator.SubmissionCreate) (*validator.SubmissionID, error) {
var Submitter=uint64(request.AssetOwner);
var AssetID=uint64(request.AssetID);
var AssetVersion=uint64(request.AssetVersion);
var Status=model.SubmissionStatus(request.Status);
var roles=model.Roles(request.Roles);
// Check if an active submission with the same asset id exists
{
filter := service.NewSubmissionFilter()
filter.SetAssetID(AssetID)
filter.SetAssetVersion(AssetVersion)
filter.SetAssetID(request.AssetID)
filter.SetAssetVersion(request.AssetVersion)
filter.SetStatuses(ActiveSubmissionStatuses)
active_submissions, err := svc.inner.ListSubmissions(ctx, filter, model.Page{
Number: 1,
@@ -312,7 +360,8 @@ func (svc *Controller) CreateSubmission(ctx context.Context, request *internal.S
}
}
operation, err := svc.inner.GetOperation(ctx, request.OperationID)
operation_id := int32(request.OperationID)
operation, err := svc.inner.GetOperation(ctx, operation_id)
if err != nil {
return nil, err
}
@@ -330,10 +379,10 @@ func (svc *Controller) CreateSubmission(ctx context.Context, request *internal.S
ID: 0,
DisplayName: request.DisplayName,
Creator: request.Creator,
GameID: GameID,
GameID: request.GameID,
Submitter: Submitter,
AssetID: AssetID,
AssetVersion: AssetVersion,
AssetID: request.AssetID,
AssetVersion: request.AssetVersion,
Completed: false,
StatusID: Status,
})
@@ -343,12 +392,12 @@ func (svc *Controller) CreateSubmission(ctx context.Context, request *internal.S
// mark the operation as completed and provide the path
params := service.NewOperationCompleteParams(fmt.Sprintf("/submissions/%d", submission.ID))
err = svc.inner.CompleteOperation(ctx, request.OperationID, params)
err = svc.inner.CompleteOperation(ctx, operation_id, params)
if err != nil {
return nil, err
}
return &internal.SubmissionID{
SubmissionID: submission.ID,
return &validator.SubmissionID{
ID: uint64(submission.ID),
}, nil
}