From 88c38666542c10d8971182311b68ebdec93076c1 Mon Sep 17 00:00:00 2001 From: Quaternions <krakow20@gmail.com> Date: Mon, 31 Mar 2025 14:39:06 -0700 Subject: [PATCH 01/18] Revert "submissions: add AcceptedBy, UploadedBy fields to model" This reverts commit 4c17a3c9e966c5af5c0da2001f0a59c39edac87d. --- pkg/model/submission.go | 4 ---- pkg/service/submissions.go | 13 ++----------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/pkg/model/submission.go b/pkg/model/submission.go index a01e1cd..11f1775 100644 --- a/pkg/model/submission.go +++ b/pkg/model/submission.go @@ -40,10 +40,6 @@ type Submission struct { CreatedAt time.Time UpdatedAt time.Time Submitter int64 // UserID - // Who clicked the Accept button - AcceptedBy int64 // UserID - // Who clicked the Upload button - UploadedBy int64 // UserID AssetID int64 AssetVersion int64 ValidatedAssetID int64 diff --git a/pkg/service/submissions.go b/pkg/service/submissions.go index 940d39f..94a76c1 100644 --- a/pkg/service/submissions.go +++ b/pkg/service/submissions.go @@ -396,16 +396,9 @@ func (svc *Service) ActionSubmissionTriggerUpload(ctx context.Context, params ap return ErrPermissionDeniedNeedRoleSubmissionUpload } - // track who is performing the upload action - userId, err := userInfo.GetUserID() - if err != nil { - return err - } - // transaction smap := datastore.Optional() smap.Add("status_id", model.StatusUploading) - smap.Add("uploaded_by", userId) submission, err := svc.DB.Submissions().IfStatusThenUpdateAndGet(ctx, params.SubmissionID, []model.Status{model.StatusValidated}, smap) if err != nil { return err @@ -510,13 +503,12 @@ func (svc *Service) ActionSubmissionTriggerValidate(ctx context.Context, params return err } - // track who is performing the accept action - userId, err := userInfo.GetUserID() + has_role, err = userInfo.IsSubmitter(uint64(submission.Submitter)) if err != nil { return err } // check if caller is NOT the submitter - if userId == uint64(submission.Submitter) { + if has_role { return ErrAcceptOwnSubmission } @@ -540,7 +532,6 @@ func (svc *Service) ActionSubmissionTriggerValidate(ctx context.Context, params // transaction smap := datastore.Optional() smap.Add("status_id", model.StatusValidating) - smap.Add("accepted_by", userId) submission, err = svc.DB.Submissions().IfStatusThenUpdateAndGet(ctx, params.SubmissionID, []model.Status{model.StatusSubmitted}, smap) if err != nil { return err -- 2.47.1 From dfc2a605f4b881bb52b112ecf8bd6df8cd5ad618 Mon Sep 17 00:00:00 2001 From: Quaternions <krakow20@gmail.com> Date: Mon, 31 Mar 2025 14:44:26 -0700 Subject: [PATCH 02/18] submissions: prepare for separate mapfixes --- pkg/datastore/datastore.go | 17 ++- pkg/datastore/gormstore/scripts.go | 2 +- pkg/datastore/gormstore/submissions.go | 18 +-- pkg/model/submission.go | 38 +++--- pkg/service/security.go | 26 ++-- pkg/service/service.go | 9 ++ pkg/service/submissions.go | 158 ++++++++++--------------- pkg/service_internal/submissions.go | 14 +-- 8 files changed, 129 insertions(+), 153 deletions(-) diff --git a/pkg/datastore/datastore.go b/pkg/datastore/datastore.go index eb7ca73..8a256b1 100644 --- a/pkg/datastore/datastore.go +++ b/pkg/datastore/datastore.go @@ -9,7 +9,16 @@ import ( var ( ErrNotExist = errors.New("resource does not exist") ErroNoRowsAffected = errors.New("query did not affect any rows") - ErrInvalidSubmissionListSort = errors.New("invalid submission list sort parameter [1,2,3,4]") + ErrInvalidListSort = errors.New("invalid list sort parameter [1,2,3,4]") +) + +type ListSort uint32 +const ( + ListSortDisabled ListSort = 0 + ListSortDisplayNameAscending ListSort = 1 + ListSortDisplayNameDescending ListSort = 2 + ListSortDateAscending ListSort = 3 + ListSortDateDescending ListSort = 4 ) type Datastore interface { @@ -23,10 +32,10 @@ type Submissions interface { GetList(ctx context.Context, id []int64) ([]model.Submission, error) Create(ctx context.Context, smap model.Submission) (model.Submission, error) Update(ctx context.Context, id int64, values OptionalMap) error - IfStatusThenUpdate(ctx context.Context, id int64, statuses []model.Status, values OptionalMap) error - IfStatusThenUpdateAndGet(ctx context.Context, id int64, statuses []model.Status, values OptionalMap) (model.Submission, error) + IfStatusThenUpdate(ctx context.Context, id int64, statuses []model.SubmissionStatus, values OptionalMap) error + IfStatusThenUpdateAndGet(ctx context.Context, id int64, statuses []model.SubmissionStatus, values OptionalMap) (model.Submission, error) Delete(ctx context.Context, id int64) error - List(ctx context.Context, filters OptionalMap, page model.Page, sort model.SubmissionListSort) ([]model.Submission, error) + List(ctx context.Context, filters OptionalMap, page model.Page, sort ListSort) ([]model.Submission, error) } type Scripts interface { diff --git a/pkg/datastore/gormstore/scripts.go b/pkg/datastore/gormstore/scripts.go index 1aa7f1f..600d107 100644 --- a/pkg/datastore/gormstore/scripts.go +++ b/pkg/datastore/gormstore/scripts.go @@ -53,7 +53,7 @@ func (env *Scripts) Update(ctx context.Context, id int64, values datastore.Optio } // the update can only occur if the status matches one of the provided values. -func (env *Scripts) IfStatusThenUpdate(ctx context.Context, id int64, statuses []model.Status, values datastore.OptionalMap) error { +func (env *Scripts) IfStatusThenUpdate(ctx context.Context, id int64, statuses []model.SubmissionStatus, values datastore.OptionalMap) error { if err := env.db.Model(&model.Script{}).Where("id = ?", id).Where("status IN ?", statuses).Updates(values.Map()).Error; err != nil { if err == gorm.ErrRecordNotFound { return datastore.ErrNotExist diff --git a/pkg/datastore/gormstore/submissions.go b/pkg/datastore/gormstore/submissions.go index b7073ab..dc384c6 100644 --- a/pkg/datastore/gormstore/submissions.go +++ b/pkg/datastore/gormstore/submissions.go @@ -54,7 +54,7 @@ func (env *Submissions) Update(ctx context.Context, id int64, values datastore.O } // the update can only occur if the status matches one of the provided values. -func (env *Submissions) IfStatusThenUpdate(ctx context.Context, id int64, statuses []model.Status, values datastore.OptionalMap) error { +func (env *Submissions) IfStatusThenUpdate(ctx context.Context, id int64, statuses []model.SubmissionStatus, values datastore.OptionalMap) error { if err := env.db.Model(&model.Submission{}).Where("id = ?", id).Where("status_id IN ?", statuses).Updates(values.Map()).Error; err != nil { if err == gorm.ErrRecordNotFound { return datastore.ErrNotExist @@ -67,7 +67,7 @@ func (env *Submissions) IfStatusThenUpdate(ctx context.Context, id int64, status // the update can only occur if the status matches one of the provided values. // returns the updated value -func (env *Submissions) IfStatusThenUpdateAndGet(ctx context.Context, id int64, statuses []model.Status, values datastore.OptionalMap) (model.Submission, error) { +func (env *Submissions) IfStatusThenUpdateAndGet(ctx context.Context, id int64, statuses []model.SubmissionStatus, values datastore.OptionalMap) (model.Submission, error) { var submission model.Submission result := env.db.Model(&submission). Clauses(clause.Returning{}). @@ -99,29 +99,29 @@ func (env *Submissions) Delete(ctx context.Context, id int64) error { return nil } -func (env *Submissions) List(ctx context.Context, filters datastore.OptionalMap, page model.Page, sort model.SubmissionListSort) ([]model.Submission, error) { +func (env *Submissions) List(ctx context.Context, filters datastore.OptionalMap, page model.Page, sort datastore.ListSort) ([]model.Submission, error) { var maps []model.Submission db := env.db switch sort { - case model.SubmissionListSortDisabled: + case datastore.ListSortDisabled: // No sort break - case model.SubmissionListSortDisplayNameAscending: + case datastore.ListSortDisplayNameAscending: db=db.Order("display_name ASC") break - case model.SubmissionListSortDisplayNameDescending: + case datastore.ListSortDisplayNameDescending: db=db.Order("display_name DESC") break - case model.SubmissionListSortDateAscending: + case datastore.ListSortDateAscending: db=db.Order("created_at ASC") break - case model.SubmissionListSortDateDescending: + case datastore.ListSortDateDescending: db=db.Order("created_at DESC") break default: - return nil, datastore.ErrInvalidSubmissionListSort + return nil, datastore.ErrInvalidListSort } if err := db.Where(filters.Map()).Offset(int((page.Number - 1) * page.Size)).Limit(int(page.Size)).Find(&maps).Error; err != nil { diff --git a/pkg/model/submission.go b/pkg/model/submission.go index 11f1775..aa2c708 100644 --- a/pkg/model/submission.go +++ b/pkg/model/submission.go @@ -2,34 +2,24 @@ package model import "time" -type Status int32 +type SubmissionStatus int32 const ( - // Phase: Final Status - StatusReleased Status = 9 - StatusRejected Status = 8 + // Phase: Final SubmissionStatus + SubmissionStatusReleased SubmissionStatus = 9 + SubmissionStatusRejected SubmissionStatus = 8 // Phase: Testing - StatusUploaded Status = 7 // uploaded to the group, but pending release - StatusUploading Status = 6 - StatusValidated Status = 5 - StatusValidating Status = 4 - StatusAccepted Status = 3 // pending script review, can re-trigger validation + SubmissionStatusUploaded SubmissionStatus = 7 // uploaded to the group, but pending release + SubmissionStatusUploading SubmissionStatus = 6 + SubmissionStatusValidated SubmissionStatus = 5 + SubmissionStatusValidating SubmissionStatus = 4 + SubmissionStatusAccepted SubmissionStatus = 3 // pending script review, can re-trigger validation // Phase: Creation - StatusChangesRequested Status = 2 - StatusSubmitted Status = 1 - StatusUnderConstruction Status = 0 -) - -type SubmissionListSort uint32 - -const ( - SubmissionListSortDisabled SubmissionListSort = 0 - SubmissionListSortDisplayNameAscending SubmissionListSort = 1 - SubmissionListSortDisplayNameDescending SubmissionListSort = 2 - SubmissionListSortDateAscending SubmissionListSort = 3 - SubmissionListSortDateDescending SubmissionListSort = 4 + SubmissionStatusChangesRequested SubmissionStatus = 2 + SubmissionStatusSubmitted SubmissionStatus = 1 + SubmissionStatusUnderConstruction SubmissionStatus = 0 ) type Submission struct { @@ -45,7 +35,7 @@ type Submission struct { ValidatedAssetID int64 ValidatedAssetVersion int64 Completed bool // Has this version of the map been completed at least once on maptest - TargetAssetID int64 // where to upload map fix. if the TargetAssetID is 0, it's a new map. - StatusID Status + UploadedAssetID int64 // where to upload map fix. if the TargetAssetID is 0, it's a new map. + StatusID SubmissionStatus StatusMessage string } diff --git a/pkg/service/security.go b/pkg/service/security.go index 9584672..8bc2efb 100644 --- a/pkg/service/security.go +++ b/pkg/service/security.go @@ -19,8 +19,8 @@ type Roles int32 var ( RolesSubmissionRelease Roles = 1<<4 RolesScriptWrite Roles = 1<<3 - RolesSubmissionUpload Roles = 1<<2 - RolesSubmissionReview Roles = 1<<1 + RolesMapUpload Roles = 1<<2 + RolesMapReview Roles = 1<<1 RolesMapDownload Roles = 1<<0 RolesEmpty Roles = 0 ) @@ -32,13 +32,13 @@ var ( RoleQuat GroupRole = 255 RoleItzaname GroupRole = 254 RoleStagingDeveloper GroupRole = 240 - RolesAll Roles = RolesScriptWrite|RolesSubmissionRelease|RolesSubmissionUpload|RolesSubmissionReview|RolesMapDownload + RolesAll Roles = RolesScriptWrite|RolesSubmissionRelease|RolesMapUpload|RolesMapReview|RolesMapDownload // has SubmissionUpload RoleMapAdmin GroupRole = 128 - RolesMapAdmin Roles = RolesSubmissionRelease|RolesSubmissionUpload|RolesSubmissionReview|RolesMapDownload + RolesMapAdmin Roles = RolesSubmissionRelease|RolesMapUpload|RolesMapReview|RolesMapDownload // has SubmissionReview RoleMapCouncil GroupRole = 64 - RolesMapCouncil Roles = RolesSubmissionReview|RolesSubmissionUpload|RolesMapDownload + RolesMapCouncil Roles = RolesMapReview|RolesMapUpload|RolesMapDownload // access to downloading maps RoleMapAccess GroupRole = 32 RolesMapAccess Roles = RolesMapDownload @@ -128,17 +128,23 @@ func (usr UserInfoHandle) GetRoles() (Roles, error) { } // RoleThumbnail +func (usr UserInfoHandle) HasRoleMapfixUpload() (bool, error) { + return usr.hasRoles(RolesMapUpload) +} +func (usr UserInfoHandle) HasRoleMapfixReview() (bool, error) { + return usr.hasRoles(RolesMapReview) +} +func (usr UserInfoHandle) HasRoleMapDownload() (bool, error) { + return usr.hasRoles(RolesMapDownload) +} func (usr UserInfoHandle) HasRoleSubmissionRelease() (bool, error) { return usr.hasRoles(RolesSubmissionRelease) } func (usr UserInfoHandle) HasRoleSubmissionUpload() (bool, error) { - return usr.hasRoles(RolesSubmissionUpload) + return usr.hasRoles(RolesMapUpload) } func (usr UserInfoHandle) HasRoleSubmissionReview() (bool, error) { - return usr.hasRoles(RolesSubmissionReview) -} -func (usr UserInfoHandle) HasRoleMapDownload() (bool, error) { - return usr.hasRoles(RolesMapDownload) + return usr.hasRoles(RolesMapReview) } func (usr UserInfoHandle) HasRoleScriptWrite() (bool, error) { return usr.hasRoles(RolesScriptWrite) diff --git a/pkg/service/service.go b/pkg/service/service.go index ac0c2f6..1815060 100644 --- a/pkg/service/service.go +++ b/pkg/service/service.go @@ -3,6 +3,7 @@ package service import ( "context" "errors" + "fmt" "git.itzana.me/strafesnet/go-grpc/maps" "git.itzana.me/strafesnet/maps-service/pkg/api" @@ -15,6 +16,14 @@ var ( ErrPermissionDenied = errors.New("Permission denied") // ErrUserInfo user info is missing for some reason ErrUserInfo = errors.New("Missing user info") + ErrDelayReset = errors.New("Please give the validator at least 10 seconds to operate before attempting to reset the status") + ErrPermissionDeniedNotSubmitter = fmt.Errorf("%w: You must be the submitter to perform this action", ErrPermissionDenied) + ErrPermissionDeniedNeedRoleSubmissionRelease = fmt.Errorf("%w: Need Role SubmissionRelease", ErrPermissionDenied) + ErrPermissionDeniedNeedRoleMapUpload = fmt.Errorf("%w: Need Role MapUpload", ErrPermissionDenied) + ErrPermissionDeniedNeedRoleMapReview = fmt.Errorf("%w: Need Role MapReview", ErrPermissionDenied) + ErrPermissionDeniedNeedRoleMapDownload = fmt.Errorf("%w: Need Role MapDownload", ErrPermissionDenied) + ErrPermissionDeniedNeedRoleScriptWrite = fmt.Errorf("%w: Need Role ScriptWrite", ErrPermissionDenied) + ErrPermissionDeniedNeedRoleMaptest = fmt.Errorf("%w: Need Role Maptest", ErrPermissionDenied) ) type Service struct { diff --git a/pkg/service/submissions.go b/pkg/service/submissions.go index 94a76c1..8583675 100644 --- a/pkg/service/submissions.go +++ b/pkg/service/submissions.go @@ -15,45 +15,37 @@ import ( var( CreationPhaseSubmissionsLimit = 20 - CreationPhaseSubmissionStatuses = []model.Status{ - model.StatusChangesRequested, - model.StatusSubmitted, - model.StatusUnderConstruction, + CreationPhaseSubmissionStatuses = []model.SubmissionStatus{ + model.SubmissionStatusChangesRequested, + model.SubmissionStatusSubmitted, + model.SubmissionStatusUnderConstruction, } // prevent two mapfixes with same asset id - ActiveSubmissionStatuses = []model.Status{ - model.StatusUploading, - model.StatusValidated, - model.StatusValidating, - model.StatusAccepted, - model.StatusChangesRequested, - model.StatusSubmitted, - model.StatusUnderConstruction, + ActiveSubmissionStatuses = []model.SubmissionStatus{ + model.SubmissionStatusUploading, + model.SubmissionStatusValidated, + model.SubmissionStatusValidating, + model.SubmissionStatusAccepted, + model.SubmissionStatusChangesRequested, + model.SubmissionStatusSubmitted, + model.SubmissionStatusUnderConstruction, } // limit mapfixes in the pipeline to one per target map - ActiveAcceptedSubmissionStatuses = []model.Status{ - model.StatusUploading, - model.StatusValidated, - model.StatusValidating, - model.StatusAccepted, + ActiveAcceptedSubmissionStatuses = []model.SubmissionStatus{ + model.SubmissionStatusUploading, + model.SubmissionStatusValidated, + model.SubmissionStatusValidating, + model.SubmissionStatusAccepted, } ) var ( ErrCreationPhaseSubmissionsLimit = errors.New("Active submissions limited to 20") ErrActiveSubmissionSameAssetID = errors.New("There is an active submission with the same AssetID") - ErrActiveSubmissionSameTargetAssetID = errors.New("There is an active submission with the same TargetAssetID") + ErrUploadedAssetIDAlreadyExists = errors.New("The submission UploadedAssetID is already set") ErrReleaseInvalidStatus = errors.New("Only submissions with Uploaded status can be released") - ErrReleaseNoTargetAssetID = errors.New("Only submissions with a TargetAssetID can be released") + ErrReleaseNoUploadedAssetID = errors.New("Only submissions with a UploadedAssetID can be released") ErrAcceptOwnSubmission = fmt.Errorf("%w: You cannot accept your own submission as the submitter", ErrPermissionDenied) - ErrDelayReset = errors.New("Please give the validator at least 10 seconds to operate before attempting to reset the status") - ErrPermissionDeniedNotSubmitter = fmt.Errorf("%w: You must be the submitter to perform this action", ErrPermissionDenied) - ErrPermissionDeniedNeedRoleSubmissionRelease = fmt.Errorf("%w: Need Role SubmissionRelease", ErrPermissionDenied) - ErrPermissionDeniedNeedRoleSubmissionUpload = fmt.Errorf("%w: Need Role SubmissionUpload", ErrPermissionDenied) - ErrPermissionDeniedNeedRoleSubmissionReview = fmt.Errorf("%w: Need Role SubmissionReview", ErrPermissionDenied) - ErrPermissionDeniedNeedRoleMapDownload = fmt.Errorf("%w: Need Role MapDownload", ErrPermissionDenied) - ErrPermissionDeniedNeedRoleScriptWrite = fmt.Errorf("%w: Need Role ScriptWrite", ErrPermissionDenied) - ErrPermissionDeniedNeedRoleMaptest = fmt.Errorf("%w: Need Role Maptest", ErrPermissionDenied) ) // POST /submissions @@ -76,7 +68,7 @@ func (svc *Service) CreateSubmission(ctx context.Context, request *api.Submissio creation_submissions, err := svc.DB.Submissions().List(ctx, filter, model.Page{ Number: 1, Size: int32(CreationPhaseSubmissionsLimit), - },model.SubmissionListSortDisabled) + },datastore.ListSortDisabled) if err != nil { return nil, err } @@ -95,7 +87,7 @@ func (svc *Service) CreateSubmission(ctx context.Context, request *api.Submissio active_submissions, err := svc.DB.Submissions().List(ctx, filter, model.Page{ Number: 1, Size: 1, - },model.SubmissionListSortDisabled) + },datastore.ListSortDisabled) if err != nil { return nil, err } @@ -113,8 +105,7 @@ func (svc *Service) CreateSubmission(ctx context.Context, request *api.Submissio AssetID: request.AssetID, AssetVersion: request.AssetVersion, Completed: false, - TargetAssetID: request.TargetAssetID.Value, - StatusID: model.StatusUnderConstruction, + StatusID: model.SubmissionStatusUnderConstruction, }) if err != nil { return nil, err @@ -145,7 +136,7 @@ func (svc *Service) GetSubmission(ctx context.Context, params api.GetSubmissionP AssetID: int64(submission.AssetID), AssetVersion: int64(submission.AssetVersion), Completed: submission.Completed, - TargetAssetID: api.NewOptInt64(int64(submission.TargetAssetID)), + UploadedAssetID: api.NewOptInt64(int64(submission.UploadedAssetID)), StatusID: int32(submission.StatusID), StatusMessage: submission.StatusMessage, }, nil @@ -169,7 +160,7 @@ func (svc *Service) ListSubmissions(ctx context.Context, params api.ListSubmissi filter.Add("game_id", params.GameID.Value) } - sort := model.SubmissionListSort(params.Sort.Or(int32(model.SubmissionListSortDisabled))) + sort := datastore.ListSort(params.Sort.Or(int32(datastore.ListSortDisabled))) items, err := svc.DB.Submissions().List(ctx, filter, model.Page{ Number: params.Page, @@ -192,7 +183,7 @@ func (svc *Service) ListSubmissions(ctx context.Context, params api.ListSubmissi AssetID: int64(item.AssetID), AssetVersion: int64(item.AssetVersion), Completed: item.Completed, - TargetAssetID: api.NewOptInt64(int64(item.TargetAssetID)), + UploadedAssetID: api.NewOptInt64(int64(item.UploadedAssetID)), StatusID: int32(item.StatusID), }) } @@ -257,7 +248,7 @@ func (svc *Service) UpdateSubmissionModel(ctx context.Context, params api.Update pmap.AddNotNil("asset_version", params.VersionID) //always reset completed when model changes pmap.Add("completed", false) - return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.Status{model.StatusChangesRequested, model.StatusSubmitted, model.StatusUnderConstruction}, pmap) + return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusChangesRequested, model.SubmissionStatusSubmitted, model.SubmissionStatusUnderConstruction}, pmap) } // ActionSubmissionReject invokes actionSubmissionReject operation. @@ -277,13 +268,13 @@ func (svc *Service) ActionSubmissionReject(ctx context.Context, params api.Actio } // check if caller has required role if !has_role { - return ErrPermissionDeniedNeedRoleSubmissionReview + return ErrPermissionDeniedNeedRoleMapReview } // transaction smap := datastore.Optional() - smap.Add("status_id", model.StatusRejected) - return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.Status{model.StatusSubmitted}, smap) + smap.Add("status_id", model.SubmissionStatusRejected) + return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusSubmitted}, smap) } // ActionSubmissionRequestChanges invokes actionSubmissionRequestChanges operation. @@ -303,13 +294,13 @@ func (svc *Service) ActionSubmissionRequestChanges(ctx context.Context, params a } // check if caller has required role if !has_role { - return ErrPermissionDeniedNeedRoleSubmissionReview + return ErrPermissionDeniedNeedRoleMapReview } // transaction smap := datastore.Optional() - smap.Add("status_id", model.StatusChangesRequested) - return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.Status{model.StatusValidated, model.StatusAccepted, model.StatusSubmitted}, smap) + smap.Add("status_id", model.SubmissionStatusChangesRequested) + return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusValidated, model.SubmissionStatusAccepted, model.SubmissionStatusSubmitted}, smap) } // ActionSubmissionRevoke invokes actionSubmissionRevoke operation. @@ -340,8 +331,8 @@ func (svc *Service) ActionSubmissionRevoke(ctx context.Context, params api.Actio // transaction smap := datastore.Optional() - smap.Add("status_id", model.StatusUnderConstruction) - return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.Status{model.StatusSubmitted, model.StatusChangesRequested}, smap) + smap.Add("status_id", model.SubmissionStatusUnderConstruction) + return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusSubmitted, model.SubmissionStatusChangesRequested}, smap) } // ActionSubmissionSubmit invokes actionSubmissionSubmit operation. @@ -372,8 +363,8 @@ func (svc *Service) ActionSubmissionSubmit(ctx context.Context, params api.Actio // transaction smap := datastore.Optional() - smap.Add("status_id", model.StatusSubmitted) - return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.Status{model.StatusUnderConstruction, model.StatusChangesRequested}, smap) + smap.Add("status_id", model.SubmissionStatusSubmitted) + return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusUnderConstruction, model.SubmissionStatusChangesRequested}, smap) } // ActionSubmissionTriggerUpload invokes actionSubmissionTriggerUpload operation. @@ -393,19 +384,19 @@ func (svc *Service) ActionSubmissionTriggerUpload(ctx context.Context, params ap } // check if caller has required role if !has_role { - return ErrPermissionDeniedNeedRoleSubmissionUpload + return ErrPermissionDeniedNeedRoleMapUpload } // transaction smap := datastore.Optional() - smap.Add("status_id", model.StatusUploading) - submission, err := svc.DB.Submissions().IfStatusThenUpdateAndGet(ctx, params.SubmissionID, []model.Status{model.StatusValidated}, smap) + smap.Add("status_id", model.SubmissionStatusUploading) + submission, err := svc.DB.Submissions().IfStatusThenUpdateAndGet(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusValidated}, smap) if err != nil { return err } // sentinel value because we are not using rust - if submission.TargetAssetID == 0 { + if submission.UploadedAssetID == 0 { // this is a new map upload_new_request := model.UploadNewRequest{ SubmissionID: submission.ID, @@ -422,20 +413,8 @@ func (svc *Service) ActionSubmissionTriggerUpload(ctx context.Context, params ap svc.Nats.Publish("maptest.submissions.uploadnew", []byte(j)) } else { - // this is a map fix - upload_fix_request := model.UploadFixRequest{ - SubmissionID: submission.ID, - ModelID: submission.ValidatedAssetID, - ModelVersion: submission.ValidatedAssetVersion, - TargetAssetID: submission.TargetAssetID, - } - - j, err := json.Marshal(upload_fix_request) - if err != nil { - return err - } - - svc.Nats.Publish("maptest.submissions.uploadfix", []byte(j)) + // refuse to operate + return ErrUploadedAssetIDAlreadyExists } return nil @@ -458,7 +437,7 @@ func (svc *Service) ActionSubmissionValidated(ctx context.Context, params api.Ac } // check if caller has required role if !has_role { - return ErrPermissionDeniedNeedRoleSubmissionUpload + return ErrPermissionDeniedNeedRoleMapUpload } // check when submission was updated @@ -473,8 +452,8 @@ func (svc *Service) ActionSubmissionValidated(ctx context.Context, params api.Ac // transaction smap := datastore.Optional() - smap.Add("status_id", model.StatusValidated) - return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.Status{model.StatusUploading}, smap) + smap.Add("status_id", model.SubmissionStatusValidated) + return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusUploading}, smap) } // ActionSubmissionTriggerValidate invokes actionSubmissionTriggerValidate operation. @@ -494,7 +473,7 @@ func (svc *Service) ActionSubmissionTriggerValidate(ctx context.Context, params } // check if caller has required role if !has_role { - return ErrPermissionDeniedNeedRoleSubmissionReview + return ErrPermissionDeniedNeedRoleMapReview } // read submission (this could be done with a transaction WHERE clause) @@ -512,27 +491,10 @@ func (svc *Service) ActionSubmissionTriggerValidate(ctx context.Context, params return ErrAcceptOwnSubmission } - // Check if an active submission with the same target asset id exists - if submission.TargetAssetID != 0 { - filter := datastore.Optional() - filter.Add("target_asset_id", submission.TargetAssetID) - filter.Add("status_id", ActiveAcceptedSubmissionStatuses) - active_submissions, err := svc.DB.Submissions().List(ctx, filter, model.Page{ - Number: 1, - Size: 1, - },model.SubmissionListSortDisabled) - if err != nil { - return err - } - if len(active_submissions) != 0{ - return ErrActiveSubmissionSameTargetAssetID - } - } - // transaction smap := datastore.Optional() - smap.Add("status_id", model.StatusValidating) - submission, err = svc.DB.Submissions().IfStatusThenUpdateAndGet(ctx, params.SubmissionID, []model.Status{model.StatusSubmitted}, smap) + smap.Add("status_id", model.SubmissionStatusValidating) + submission, err = svc.DB.Submissions().IfStatusThenUpdateAndGet(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusSubmitted}, smap) if err != nil { return err } @@ -576,13 +538,13 @@ func (svc *Service) ActionSubmissionRetryValidate(ctx context.Context, params ap } // check if caller has required role if !has_role { - return ErrPermissionDeniedNeedRoleSubmissionReview + return ErrPermissionDeniedNeedRoleMapReview } // transaction smap := datastore.Optional() - smap.Add("status_id", model.StatusValidating) - submission, err := svc.DB.Submissions().IfStatusThenUpdateAndGet(ctx, params.SubmissionID, []model.Status{model.StatusAccepted}, smap) + smap.Add("status_id", model.SubmissionStatusValidating) + submission, err := svc.DB.Submissions().IfStatusThenUpdateAndGet(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusAccepted}, smap) if err != nil { return err } @@ -626,7 +588,7 @@ func (svc *Service) ActionSubmissionAccepted(ctx context.Context, params api.Act } // check if caller has required role if !has_role { - return ErrPermissionDeniedNeedRoleSubmissionReview + return ErrPermissionDeniedNeedRoleMapReview } // check when submission was updated @@ -641,9 +603,9 @@ func (svc *Service) ActionSubmissionAccepted(ctx context.Context, params api.Act // transaction smap := datastore.Optional() - smap.Add("status_id", model.StatusAccepted) + smap.Add("status_id", model.SubmissionStatusAccepted) smap.Add("status_message", "Manually forced reset") - return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.Status{model.StatusValidating}, smap) + return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusValidating}, smap) } // ReleaseSubmissions invokes releaseSubmissions operation. @@ -679,11 +641,11 @@ func (svc *Service) ReleaseSubmissions(ctx context.Context, request []api.Releas // check each submission to make sure it is ready to release for _,submission := range submissions{ - if submission.StatusID != model.StatusUploaded{ + if submission.StatusID != model.SubmissionStatusUploaded{ return ErrReleaseInvalidStatus } - if submission.TargetAssetID == 0{ - return ErrReleaseNoTargetAssetID + if submission.UploadedAssetID == 0{ + return ErrReleaseNoUploadedAssetID } } @@ -691,7 +653,7 @@ func (svc *Service) ReleaseSubmissions(ctx context.Context, request []api.Releas date := request[i].Date.Unix() // create each map with go-grpc _, err := svc.Client.Create(ctx, &maps.MapRequest{ - ID: submission.TargetAssetID, + ID: submission.UploadedAssetID, DisplayName: &submission.DisplayName, Creator: &submission.Creator, GameID: &submission.GameID, @@ -703,8 +665,8 @@ func (svc *Service) ReleaseSubmissions(ctx context.Context, request []api.Releas // update each status to Released smap := datastore.Optional() - smap.Add("status_id", model.StatusReleased) - err = svc.DB.Submissions().IfStatusThenUpdate(ctx, submission.ID, []model.Status{model.StatusUploaded}, smap) + smap.Add("status_id", model.SubmissionStatusReleased) + err = svc.DB.Submissions().IfStatusThenUpdate(ctx, submission.ID, []model.SubmissionStatus{model.SubmissionStatusUploaded}, smap) if err != nil { return err } diff --git a/pkg/service_internal/submissions.go b/pkg/service_internal/submissions.go index 0d3a33a..93b6daf 100644 --- a/pkg/service_internal/submissions.go +++ b/pkg/service_internal/submissions.go @@ -20,7 +20,7 @@ func (svc *Service) UpdateSubmissionValidatedModel(ctx context.Context, params i pmap.AddNotNil("validated_asset_version", params.ValidatedModelVersion) // DO NOT reset completed when validated model is updated // pmap.Add("completed", false) - return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.Status{model.StatusValidating}, pmap) + return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusValidating}, pmap) } // ActionSubmissionValidate invokes actionSubmissionValidate operation. @@ -33,8 +33,8 @@ func (svc *Service) ActionSubmissionValidated(ctx context.Context, params intern // transaction smap := datastore.Optional() - smap.Add("status_id", model.StatusValidated) - return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.Status{model.StatusValidating}, smap) + smap.Add("status_id", model.SubmissionStatusValidated) + return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusValidating}, smap) } // ActionSubmissionAccepted implements actionSubmissionAccepted operation. @@ -47,9 +47,9 @@ func (svc *Service) ActionSubmissionAccepted(ctx context.Context, params interna // transaction smap := datastore.Optional() - smap.Add("status_id", model.StatusAccepted) + smap.Add("status_id", model.SubmissionStatusAccepted) smap.Add("status_message", params.StatusMessage) - return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.Status{model.StatusValidating}, smap) + return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusValidating}, smap) } // ActionSubmissionUploaded implements actionSubmissionUploaded operation. @@ -62,9 +62,9 @@ func (svc *Service) ActionSubmissionUploaded(ctx context.Context, params interna // transaction smap := datastore.Optional() - smap.Add("status_id", model.StatusUploaded) + smap.Add("status_id", model.SubmissionStatusUploaded) if params.TargetAssetID.IsSet() { smap.AddNotNil("target_asset_id", params.TargetAssetID.Value) } - return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.Status{model.StatusUploading}, smap) + return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusUploading}, smap) } -- 2.47.1 From 2d2691b5518223202f9a93b7aae59d1211d71841 Mon Sep 17 00:00:00 2001 From: Quaternions <krakow20@gmail.com> Date: Mon, 31 Mar 2025 15:23:07 -0700 Subject: [PATCH 03/18] openapi: tweak Submission fields --- openapi.yaml | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/openapi.yaml b/openapi.yaml index 21e2748..b17a186 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -737,8 +737,7 @@ components: - AssetID - AssetVersion - Completed - - SubmissionType -# - TargetAssetID +# - UploadedAssetID - StatusID - StatusMessage type: object @@ -772,10 +771,7 @@ components: format: int64 Completed: type: boolean - SubmissionType: - type: integer - format: int32 - TargetAssetID: + UploadedAssetID: type: integer format: int64 StatusID: @@ -791,7 +787,6 @@ components: - GameID - AssetID - AssetVersion -# - TargetAssetID type: object properties: DisplayName: @@ -809,9 +804,6 @@ components: AssetVersion: type: integer format: int64 - TargetAssetID: - type: integer - format: int64 ReleaseInfo: required: - SubmissionID -- 2.47.1 From 9740cbe91a2e25caff62cf9dd7039b47ce0ba13b Mon Sep 17 00:00:00 2001 From: Quaternions <krakow20@gmail.com> Date: Mon, 31 Mar 2025 15:23:22 -0700 Subject: [PATCH 04/18] openapi: generate --- pkg/api/oas_json_gen.go | 64 ++++++++-------------------------- pkg/api/oas_schemas_gen.go | 70 +++++++++++++------------------------- 2 files changed, 39 insertions(+), 95 deletions(-) diff --git a/pkg/api/oas_json_gen.go b/pkg/api/oas_json_gen.go index ab1cd86..756801d 100644 --- a/pkg/api/oas_json_gen.go +++ b/pkg/api/oas_json_gen.go @@ -1451,13 +1451,9 @@ func (s *Submission) encodeFields(e *jx.Encoder) { e.Bool(s.Completed) } { - e.FieldStart("SubmissionType") - e.Int32(s.SubmissionType) - } - { - if s.TargetAssetID.Set { - e.FieldStart("TargetAssetID") - s.TargetAssetID.Encode(e) + if s.UploadedAssetID.Set { + e.FieldStart("UploadedAssetID") + s.UploadedAssetID.Encode(e) } } { @@ -1470,7 +1466,7 @@ func (s *Submission) encodeFields(e *jx.Encoder) { } } -var jsonFieldsNameOfSubmission = [14]string{ +var jsonFieldsNameOfSubmission = [13]string{ 0: "ID", 1: "DisplayName", 2: "Creator", @@ -1481,10 +1477,9 @@ var jsonFieldsNameOfSubmission = [14]string{ 7: "AssetID", 8: "AssetVersion", 9: "Completed", - 10: "SubmissionType", - 11: "TargetAssetID", - 12: "StatusID", - 13: "StatusMessage", + 10: "UploadedAssetID", + 11: "StatusID", + 12: "StatusMessage", } // Decode decodes Submission from json. @@ -1616,30 +1611,18 @@ func (s *Submission) Decode(d *jx.Decoder) error { }(); err != nil { return errors.Wrap(err, "decode field \"Completed\"") } - case "SubmissionType": - requiredBitSet[1] |= 1 << 2 + case "UploadedAssetID": if err := func() error { - v, err := d.Int32() - s.SubmissionType = int32(v) - if err != nil { + s.UploadedAssetID.Reset() + if err := s.UploadedAssetID.Decode(d); err != nil { return err } return nil }(); err != nil { - return errors.Wrap(err, "decode field \"SubmissionType\"") - } - case "TargetAssetID": - if err := func() error { - s.TargetAssetID.Reset() - if err := s.TargetAssetID.Decode(d); err != nil { - return err - } - return nil - }(); err != nil { - return errors.Wrap(err, "decode field \"TargetAssetID\"") + return errors.Wrap(err, "decode field \"UploadedAssetID\"") } case "StatusID": - requiredBitSet[1] |= 1 << 4 + requiredBitSet[1] |= 1 << 3 if err := func() error { v, err := d.Int32() s.StatusID = int32(v) @@ -1651,7 +1634,7 @@ func (s *Submission) Decode(d *jx.Decoder) error { return errors.Wrap(err, "decode field \"StatusID\"") } case "StatusMessage": - requiredBitSet[1] |= 1 << 5 + requiredBitSet[1] |= 1 << 4 if err := func() error { v, err := d.Str() s.StatusMessage = string(v) @@ -1673,7 +1656,7 @@ func (s *Submission) Decode(d *jx.Decoder) error { var failures []validate.FieldError for i, mask := range [2]uint8{ 0b11111111, - 0b00110111, + 0b00011011, } { if result := (requiredBitSet[i] & mask) ^ mask; result != 0 { // Mask only required fields and check equality to mask using XOR. @@ -1748,21 +1731,14 @@ func (s *SubmissionCreate) encodeFields(e *jx.Encoder) { e.FieldStart("AssetVersion") e.Int64(s.AssetVersion) } - { - if s.TargetAssetID.Set { - e.FieldStart("TargetAssetID") - s.TargetAssetID.Encode(e) - } - } } -var jsonFieldsNameOfSubmissionCreate = [6]string{ +var jsonFieldsNameOfSubmissionCreate = [5]string{ 0: "DisplayName", 1: "Creator", 2: "GameID", 3: "AssetID", 4: "AssetVersion", - 5: "TargetAssetID", } // Decode decodes SubmissionCreate from json. @@ -1834,16 +1810,6 @@ func (s *SubmissionCreate) Decode(d *jx.Decoder) error { }(); err != nil { return errors.Wrap(err, "decode field \"AssetVersion\"") } - case "TargetAssetID": - if err := func() error { - s.TargetAssetID.Reset() - if err := s.TargetAssetID.Decode(d); err != nil { - return err - } - return nil - }(); err != nil { - return errors.Wrap(err, "decode field \"TargetAssetID\"") - } default: return d.Skip() } diff --git a/pkg/api/oas_schemas_gen.go b/pkg/api/oas_schemas_gen.go index b463864..b779939 100644 --- a/pkg/api/oas_schemas_gen.go +++ b/pkg/api/oas_schemas_gen.go @@ -590,20 +590,19 @@ type SetSubmissionCompletedNoContent struct{} // Ref: #/components/schemas/Submission type Submission struct { - ID int64 `json:"ID"` - DisplayName string `json:"DisplayName"` - Creator string `json:"Creator"` - GameID int32 `json:"GameID"` - CreatedAt int64 `json:"CreatedAt"` - UpdatedAt int64 `json:"UpdatedAt"` - Submitter int64 `json:"Submitter"` - AssetID int64 `json:"AssetID"` - AssetVersion int64 `json:"AssetVersion"` - Completed bool `json:"Completed"` - SubmissionType int32 `json:"SubmissionType"` - TargetAssetID OptInt64 `json:"TargetAssetID"` - StatusID int32 `json:"StatusID"` - StatusMessage string `json:"StatusMessage"` + ID int64 `json:"ID"` + DisplayName string `json:"DisplayName"` + Creator string `json:"Creator"` + GameID int32 `json:"GameID"` + CreatedAt int64 `json:"CreatedAt"` + UpdatedAt int64 `json:"UpdatedAt"` + Submitter int64 `json:"Submitter"` + AssetID int64 `json:"AssetID"` + AssetVersion int64 `json:"AssetVersion"` + Completed bool `json:"Completed"` + UploadedAssetID OptInt64 `json:"UploadedAssetID"` + StatusID int32 `json:"StatusID"` + StatusMessage string `json:"StatusMessage"` } // GetID returns the value of ID. @@ -656,14 +655,9 @@ func (s *Submission) GetCompleted() bool { return s.Completed } -// GetSubmissionType returns the value of SubmissionType. -func (s *Submission) GetSubmissionType() int32 { - return s.SubmissionType -} - -// GetTargetAssetID returns the value of TargetAssetID. -func (s *Submission) GetTargetAssetID() OptInt64 { - return s.TargetAssetID +// GetUploadedAssetID returns the value of UploadedAssetID. +func (s *Submission) GetUploadedAssetID() OptInt64 { + return s.UploadedAssetID } // GetStatusID returns the value of StatusID. @@ -726,14 +720,9 @@ func (s *Submission) SetCompleted(val bool) { s.Completed = val } -// SetSubmissionType sets the value of SubmissionType. -func (s *Submission) SetSubmissionType(val int32) { - s.SubmissionType = val -} - -// SetTargetAssetID sets the value of TargetAssetID. -func (s *Submission) SetTargetAssetID(val OptInt64) { - s.TargetAssetID = val +// SetUploadedAssetID sets the value of UploadedAssetID. +func (s *Submission) SetUploadedAssetID(val OptInt64) { + s.UploadedAssetID = val } // SetStatusID sets the value of StatusID. @@ -748,12 +737,11 @@ func (s *Submission) SetStatusMessage(val string) { // Ref: #/components/schemas/SubmissionCreate type SubmissionCreate struct { - DisplayName string `json:"DisplayName"` - Creator string `json:"Creator"` - GameID int32 `json:"GameID"` - AssetID int64 `json:"AssetID"` - AssetVersion int64 `json:"AssetVersion"` - TargetAssetID OptInt64 `json:"TargetAssetID"` + DisplayName string `json:"DisplayName"` + Creator string `json:"Creator"` + GameID int32 `json:"GameID"` + AssetID int64 `json:"AssetID"` + AssetVersion int64 `json:"AssetVersion"` } // GetDisplayName returns the value of DisplayName. @@ -781,11 +769,6 @@ func (s *SubmissionCreate) GetAssetVersion() int64 { return s.AssetVersion } -// GetTargetAssetID returns the value of TargetAssetID. -func (s *SubmissionCreate) GetTargetAssetID() OptInt64 { - return s.TargetAssetID -} - // SetDisplayName sets the value of DisplayName. func (s *SubmissionCreate) SetDisplayName(val string) { s.DisplayName = val @@ -811,11 +794,6 @@ func (s *SubmissionCreate) SetAssetVersion(val int64) { s.AssetVersion = val } -// SetTargetAssetID sets the value of TargetAssetID. -func (s *SubmissionCreate) SetTargetAssetID(val OptInt64) { - s.TargetAssetID = val -} - // UpdateScriptNoContent is response for UpdateScript operation. type UpdateScriptNoContent struct{} -- 2.47.1 From 0e29ca98dd7fa0a8135351c962db46800b88fa5f Mon Sep 17 00:00:00 2001 From: Quaternions <krakow20@gmail.com> Date: Mon, 31 Mar 2025 15:36:58 -0700 Subject: [PATCH 05/18] web: remove TargetAssetID --- web/src/app/submit/page.tsx | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/web/src/app/submit/page.tsx b/web/src/app/submit/page.tsx index 6f3c1b7..38cc9e3 100644 --- a/web/src/app/submit/page.tsx +++ b/web/src/app/submit/page.tsx @@ -1,6 +1,6 @@ "use client" -import { FormControl, FormControlLabel, Button, TextField, Checkbox } from "@mui/material" +import { Button, TextField } from "@mui/material" import GameSelection from "./_game"; import SendIcon from '@mui/icons-material/Send'; @@ -15,7 +15,6 @@ interface SubmissionPayload { GameID: number; AssetID: number; AssetVersion: number; - TargetAssetID: number; } interface IdResponse { ID: number; @@ -23,7 +22,6 @@ interface IdResponse { export default function SubmissionInfoPage() { const [game, setGame] = useState(1); - const [isFixingMap, setIsFixingMap] = useState(false); const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); @@ -37,7 +35,6 @@ export default function SubmissionInfoPage() { GameID: game, AssetID: Number((formData.get("asset-id") as string) ?? "0"), AssetVersion: 0, - TargetAssetID: isFixingMap ? Number((formData.get("target-asset-id") as string) ?? "0") : 0, }; console.log(payload) @@ -84,15 +81,6 @@ export default function SubmissionInfoPage() { <TextField className="form-field" id="asset-id" name="asset-id" label="Asset ID" variant="outlined"/> {/* I think this is Quat's job to figure this one out (to be set when someone clicks review(?)) */} {/* <TextField className="form-field" id="asset-version" label="Asset Version" variant="outlined"/> */} <GameSelection game={game} setGame={setGame} /> - <FormControl> - <FormControlLabel control={<Checkbox sx={{ - color: "#646464", - '&.Mui-checked': { - color: "#66BB6A", - }, - }} onChange={(e) => setIsFixingMap(e.target.checked)} />} label="Fixing an Existing Map?" /> - </FormControl> - <TextField className="form-field" id="target-asset-id" name="target-asset-id" label="Target Asset ID (group model)" variant="outlined"/> <span className="spacer form-spacer"></span> <Button type="submit" variant="contained" startIcon={<SendIcon/>} sx={{ width: "400px", -- 2.47.1 From 0b644409759298397ccc02a2fdee08938c2313d7 Mon Sep 17 00:00:00 2001 From: Quaternions <krakow20@gmail.com> Date: Mon, 31 Mar 2025 15:41:57 -0700 Subject: [PATCH 06/18] openapi-internal: tweak validator-uploaded endpoint --- openapi-internal.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openapi-internal.yaml b/openapi-internal.yaml index 83e24a4..34d861c 100644 --- a/openapi-internal.yaml +++ b/openapi-internal.yaml @@ -85,8 +85,9 @@ paths: - Submissions parameters: - $ref: '#/components/parameters/SubmissionID' - - name: TargetAssetID + - name: UploadedAssetID in: query + required: true schema: type: integer format: int64 -- 2.47.1 From e5e85db1fd955551bc8bafc5eb3325a223a372e5 Mon Sep 17 00:00:00 2001 From: Quaternions <krakow20@gmail.com> Date: Mon, 31 Mar 2025 15:42:12 -0700 Subject: [PATCH 07/18] openapi-internal: generate --- pkg/internal/oas_client_gen.go | 9 +++---- pkg/internal/oas_handlers_gen.go | 4 +-- pkg/internal/oas_parameters_gen.go | 43 +++++++++++++----------------- 3 files changed, 23 insertions(+), 33 deletions(-) diff --git a/pkg/internal/oas_client_gen.go b/pkg/internal/oas_client_gen.go index 7350ba5..26e4930 100644 --- a/pkg/internal/oas_client_gen.go +++ b/pkg/internal/oas_client_gen.go @@ -312,18 +312,15 @@ func (c *Client) sendActionSubmissionUploaded(ctx context.Context, params Action stage = "EncodeQueryParams" q := uri.NewQueryEncoder() { - // Encode "TargetAssetID" parameter. + // Encode "UploadedAssetID" parameter. cfg := uri.QueryParameterEncodingConfig{ - Name: "TargetAssetID", + Name: "UploadedAssetID", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { - if val, ok := params.TargetAssetID.Get(); ok { - return e.EncodeValue(conv.Int64ToString(val)) - } - return nil + return e.EncodeValue(conv.Int64ToString(params.UploadedAssetID)) }); err != nil { return res, errors.Wrap(err, "encode query") } diff --git a/pkg/internal/oas_handlers_gen.go b/pkg/internal/oas_handlers_gen.go index 0a85800..e783223 100644 --- a/pkg/internal/oas_handlers_gen.go +++ b/pkg/internal/oas_handlers_gen.go @@ -282,9 +282,9 @@ func (s *Server) handleActionSubmissionUploadedRequest(args [1]string, argsEscap In: "path", }: params.SubmissionID, { - Name: "TargetAssetID", + Name: "UploadedAssetID", In: "query", - }: params.TargetAssetID, + }: params.UploadedAssetID, }, Raw: r, } diff --git a/pkg/internal/oas_parameters_gen.go b/pkg/internal/oas_parameters_gen.go index 5bc3afd..c127a23 100644 --- a/pkg/internal/oas_parameters_gen.go +++ b/pkg/internal/oas_parameters_gen.go @@ -145,8 +145,8 @@ func decodeActionSubmissionAcceptedParams(args [1]string, argsEscaped bool, r *h // ActionSubmissionUploadedParams is parameters of actionSubmissionUploaded operation. type ActionSubmissionUploadedParams struct { // The unique identifier for a submission. - SubmissionID int64 - TargetAssetID OptInt64 + SubmissionID int64 + UploadedAssetID int64 } func unpackActionSubmissionUploadedParams(packed middleware.Parameters) (params ActionSubmissionUploadedParams) { @@ -159,12 +159,10 @@ func unpackActionSubmissionUploadedParams(packed middleware.Parameters) (params } { key := middleware.ParameterKey{ - Name: "TargetAssetID", + Name: "UploadedAssetID", In: "query", } - if v, ok := packed[key]; ok { - params.TargetAssetID = v.(OptInt64) - } + params.UploadedAssetID = packed[key].(int64) } return params } @@ -216,43 +214,38 @@ func decodeActionSubmissionUploadedParams(args [1]string, argsEscaped bool, r *h Err: err, } } - // Decode query: TargetAssetID. + // Decode query: UploadedAssetID. if err := func() error { cfg := uri.QueryParameterDecodingConfig{ - Name: "TargetAssetID", + Name: "UploadedAssetID", Style: uri.QueryStyleForm, Explode: true, } if err := q.HasParam(cfg); err == nil { if err := q.DecodeParam(cfg, func(d uri.Decoder) error { - var paramsDotTargetAssetIDVal int64 - if err := func() error { - val, err := d.DecodeValue() - if err != nil { - return err - } - - c, err := conv.ToInt64(val) - if err != nil { - return err - } - - paramsDotTargetAssetIDVal = c - return nil - }(); err != nil { + val, err := d.DecodeValue() + if err != nil { return err } - params.TargetAssetID.SetTo(paramsDotTargetAssetIDVal) + + c, err := conv.ToInt64(val) + if err != nil { + return err + } + + params.UploadedAssetID = c return nil }); err != nil { return err } + } else { + return err } return nil }(); err != nil { return params, &ogenerrors.DecodeParamError{ - Name: "TargetAssetID", + Name: "UploadedAssetID", In: "query", Err: err, } -- 2.47.1 From f7d7a0891d89a636cb7fe849fa0520d2d422be28 Mon Sep 17 00:00:00 2001 From: Quaternions <krakow20@gmail.com> Date: Mon, 31 Mar 2025 15:43:07 -0700 Subject: [PATCH 08/18] submissions: tweak validator-uploaded endpoint --- pkg/service_internal/submissions.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkg/service_internal/submissions.go b/pkg/service_internal/submissions.go index 93b6daf..8a30f36 100644 --- a/pkg/service_internal/submissions.go +++ b/pkg/service_internal/submissions.go @@ -63,8 +63,6 @@ func (svc *Service) ActionSubmissionUploaded(ctx context.Context, params interna // transaction smap := datastore.Optional() smap.Add("status_id", model.SubmissionStatusUploaded) - if params.TargetAssetID.IsSet() { - smap.AddNotNil("target_asset_id", params.TargetAssetID.Value) - } + smap.Add("uploaded_asset_id", params.UploadedAssetID) return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusUploading}, smap) } -- 2.47.1 From a60ccd22f08c96b9d6860af480f2b8185d078157 Mon Sep 17 00:00:00 2001 From: Quaternions <krakow20@gmail.com> Date: Mon, 31 Mar 2025 15:43:44 -0700 Subject: [PATCH 09/18] submissions: remove prints --- pkg/service_internal/submissions.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pkg/service_internal/submissions.go b/pkg/service_internal/submissions.go index 8a30f36..c9846d1 100644 --- a/pkg/service_internal/submissions.go +++ b/pkg/service_internal/submissions.go @@ -29,8 +29,6 @@ func (svc *Service) UpdateSubmissionValidatedModel(ctx context.Context, params i // // POST /submissions/{SubmissionID}/status/validator-validated func (svc *Service) ActionSubmissionValidated(ctx context.Context, params internal.ActionSubmissionValidatedParams) error { - println("[ActionSubmissionValidated] Implicit Validator permission granted!") - // transaction smap := datastore.Optional() smap.Add("status_id", model.SubmissionStatusValidated) @@ -43,8 +41,6 @@ func (svc *Service) ActionSubmissionValidated(ctx context.Context, params intern // // POST /submissions/{SubmissionID}/status/validator-failed func (svc *Service) ActionSubmissionAccepted(ctx context.Context, params internal.ActionSubmissionAcceptedParams) error { - println("[ActionSubmissionAccepted] Implicit Validator permission granted!") - // transaction smap := datastore.Optional() smap.Add("status_id", model.SubmissionStatusAccepted) @@ -58,8 +54,6 @@ func (svc *Service) ActionSubmissionAccepted(ctx context.Context, params interna // // POST /submissions/{SubmissionID}/status/validator-uploaded func (svc *Service) ActionSubmissionUploaded(ctx context.Context, params internal.ActionSubmissionUploadedParams) error { - println("[ActionSubmissionUploaded] Implicit Validator permission granted!") - // transaction smap := datastore.Optional() smap.Add("status_id", model.SubmissionStatusUploaded) -- 2.47.1 From ffcba574082a8b0952fae12b05e9d4bb731c4bc2 Mon Sep 17 00:00:00 2001 From: Quaternions <krakow20@gmail.com> Date: Mon, 31 Mar 2025 15:45:06 -0700 Subject: [PATCH 10/18] validation: tweak validator-uploaded endpoint --- validation/api/src/internal.rs | 4 ++-- validation/api/src/types.rs | 2 +- validation/src/upload_fix.rs | 6 +++++- validation/src/upload_new.rs | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/validation/api/src/internal.rs b/validation/api/src/internal.rs index b4bf484..54429e6 100644 --- a/validation/api/src/internal.rs +++ b/validation/api/src/internal.rs @@ -151,9 +151,9 @@ impl Context{ let url_raw=format!("{}/submissions/{}/status/validator-uploaded",self.0.base_url,config.SubmissionID); let mut url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::Parse)?; - if let Some(target_asset_id)=config.TargetAssetID{ + { url.query_pairs_mut() - .append_pair("TargetAssetID",target_asset_id.to_string().as_str()); + .append_pair("UploadedAssetID",config.UploadedAssetID.to_string().as_str()); } response_ok( self.0.post_empty_body(url).await.map_err(Error::Reqwest)? diff --git a/validation/api/src/types.rs b/validation/api/src/types.rs index 41e282e..21da6aa 100644 --- a/validation/api/src/types.rs +++ b/validation/api/src/types.rs @@ -177,7 +177,7 @@ pub struct UpdateSubmissionModelRequest{ #[derive(Clone,Debug)] pub struct ActionSubmissionUploadedRequest{ pub SubmissionID:i64, - pub TargetAssetID:Option<u64>, + pub UploadedAssetID:u64, } #[allow(nonstandard_style)] diff --git a/validation/src/upload_fix.rs b/validation/src/upload_fix.rs index 8aa3bac..23b375c 100644 --- a/validation/src/upload_fix.rs +++ b/validation/src/upload_fix.rs @@ -7,6 +7,7 @@ pub enum UploadError{ Json(serde_json::Error), Upload(rbx_asset::cookie::UploadError), ApiActionSubmissionUploaded(submissions_api::Error), + Unimplemented, } impl std::fmt::Display for UploadError{ fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ @@ -51,10 +52,13 @@ impl Uploader{ // that's it, the database entry does not need to be changed. + //TEMP + return Err(UploadError::Unimplemented); + // mark submission as uploaded, TargetAssetID is unchanged self.api_internal.action_submission_uploaded(submissions_api::types::ActionSubmissionUploadedRequest{ SubmissionID:upload_info.SubmissionID, - TargetAssetID:None, + UploadedAssetID:0, //TEMP }).await.map_err(UploadError::ApiActionSubmissionUploaded)?; Ok(()) diff --git a/validation/src/upload_new.rs b/validation/src/upload_new.rs index 6e4f074..2a0a6be 100644 --- a/validation/src/upload_new.rs +++ b/validation/src/upload_new.rs @@ -52,7 +52,7 @@ impl Uploader{ // note the asset id of the created model for later release, and mark the submission as uploaded self.api.action_submission_uploaded(submissions_api::types::ActionSubmissionUploadedRequest{ SubmissionID:upload_info.SubmissionID, - TargetAssetID:Some(upload_response.AssetId), + UploadedAssetID:upload_response.AssetId, }).await.map_err(UploadError::ApiActionSubmissionUploaded)?; Ok(()) -- 2.47.1 From 3404251c1426a30bad72367a6ac7d1b0b5b022c8 Mon Sep 17 00:00:00 2001 From: Quaternions <krakow20@gmail.com> Date: Mon, 31 Mar 2025 16:46:49 -0700 Subject: [PATCH 11/18] nats: rename events --- pkg/service/submissions.go | 2 +- validation/src/main.rs | 2 +- validation/src/message_handler.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/service/submissions.go b/pkg/service/submissions.go index 8583675..430e6d0 100644 --- a/pkg/service/submissions.go +++ b/pkg/service/submissions.go @@ -411,7 +411,7 @@ func (svc *Service) ActionSubmissionTriggerUpload(ctx context.Context, params ap return err } - svc.Nats.Publish("maptest.submissions.uploadnew", []byte(j)) + svc.Nats.Publish("maptest.submissions.upload", []byte(j)) } else { // refuse to operate return ErrUploadedAssetIDAlreadyExists diff --git a/validation/src/main.rs b/validation/src/main.rs index 2ee02e1..0ee2e2b 100644 --- a/validation/src/main.rs +++ b/validation/src/main.rs @@ -52,7 +52,7 @@ async fn main()->Result<(),StartupError>{ .get_or_create_consumer("validation",async_nats::jetstream::consumer::pull::Config{ name:Some("validation".to_owned()), durable_name:Some("validation".to_owned()), - filter_subject:"maptest.submissions.>".to_owned(), + filter_subject:"maptest.>".to_owned(), ..Default::default() }).await.map_err(StartupError::NatsConsumer)? .messages().await.map_err(StartupError::NatsStream) diff --git a/validation/src/message_handler.rs b/validation/src/message_handler.rs index c0a5dc2..519baf7 100644 --- a/validation/src/message_handler.rs +++ b/validation/src/message_handler.rs @@ -44,8 +44,8 @@ impl MessageHandler{ let message=message_result.map_err(HandleMessageError::Messages)?; message.double_ack().await.map_err(HandleMessageError::DoubleAck)?; match message.subject.as_str(){ - "maptest.submissions.uploadnew"=>self.upload_new.upload(from_slice(&message.payload)?).await.map_err(HandleMessageError::UploadNew), - "maptest.submissions.uploadfix"=>self.upload_fix.upload(from_slice(&message.payload)?).await.map_err(HandleMessageError::UploadFix), + "maptest.mapfixes.upload"=>self.upload_fix.upload(from_slice(&message.payload)?).await.map_err(HandleMessageError::UploadFix), + "maptest.submissions.upload"=>self.upload_new.upload(from_slice(&message.payload)?).await.map_err(HandleMessageError::UploadNew), "maptest.submissions.validate"=>self.validator.validate(from_slice(&message.payload)?).await.map_err(HandleMessageError::Validation), other=>Err(HandleMessageError::UnknownSubject(other.to_owned())) } -- 2.47.1 From 9671c357f40132215f374ab348f5a1d494f65a30 Mon Sep 17 00:00:00 2001 From: Quaternions <krakow20@gmail.com> Date: Mon, 31 Mar 2025 18:06:39 -0700 Subject: [PATCH 12/18] submissions: ruin script data model --- pkg/model/script.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pkg/model/script.go b/pkg/model/script.go index e736c98..61b011e 100644 --- a/pkg/model/script.go +++ b/pkg/model/script.go @@ -23,12 +23,20 @@ func HashParse(hash string) (uint64, error){ return strconv.ParseUint(hash, 16, 64) } +type ResourceType int32 +const ( + ResourceUnknown ResourceType = 0 + ResourceMapfix ResourceType = 1 + ResourceSubmission ResourceType = 2 +) + type Script struct { ID int64 `gorm:"primaryKey"` Name string Hash int64 // postgres does not support unsigned integers, so we have to pretend Source string - SubmissionID int64 // which submission did this script first appear in + ResourceType ResourceType // is this a submission or is it a mapfix + ResourceID int64 // which submission / mapfix did this script first appear in CreatedAt time.Time UpdatedAt time.Time } -- 2.47.1 From 930eb470967c0ed0ae18a416904dcad2e407456f Mon Sep 17 00:00:00 2001 From: Quaternions <krakow20@gmail.com> Date: Mon, 31 Mar 2025 18:09:25 -0700 Subject: [PATCH 13/18] openapi: tweak script data model --- openapi-internal.yaml | 16 ++++++++++++---- openapi.yaml | 21 ++++++++++++++++----- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/openapi-internal.yaml b/openapi-internal.yaml index 34d861c..0d7f2c5 100644 --- a/openapi-internal.yaml +++ b/openapi-internal.yaml @@ -304,7 +304,8 @@ components: - Name - Hash - Source - - SubmissionID + - ResourceType + - ResourceID type: object properties: ID: @@ -320,14 +321,18 @@ components: Source: type: string maxLength: 1048576 - SubmissionID: + ResourceType: + type: integer + format: int32 + ResourceID: type: integer format: int64 ScriptCreate: required: - Name - Source -# - SubmissionID + - ResourceType +# - ResourceID type: object properties: Name: @@ -336,7 +341,10 @@ components: Source: type: string maxLength: 1048576 - SubmissionID: + ResourceType: + type: integer + format: int32 + ResourceID: type: integer format: int64 ScriptPolicy: diff --git a/openapi.yaml b/openapi.yaml index b17a186..57b3dac 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -822,7 +822,8 @@ components: - Name - Hash - Source - - SubmissionID + - ResourceType + - ResourceID type: object properties: ID: @@ -838,14 +839,18 @@ components: Source: type: string maxLength: 1048576 - SubmissionID: + ResourceType: + type: integer + format: int32 + ResourceID: type: integer format: int64 ScriptCreate: required: - Name - Source -# - SubmissionID + - ResourceType +# - ResourceID type: object properties: Name: @@ -854,7 +859,10 @@ components: Source: type: string maxLength: 1048576 - SubmissionID: + ResourceType: + type: integer + format: int32 + ResourceID: type: integer format: int64 ScriptUpdate: @@ -871,7 +879,10 @@ components: Source: type: string maxLength: 1048576 - SubmissionID: + ResourceType: + type: integer + format: int32 + ResourceID: type: integer format: int64 ScriptPolicy: -- 2.47.1 From 746c7aa9b7a0c6a6ad3a543faec337d1e907cdf4 Mon Sep 17 00:00:00 2001 From: Quaternions <krakow20@gmail.com> Date: Mon, 31 Mar 2025 18:09:50 -0700 Subject: [PATCH 14/18] openapi: generate --- pkg/api/oas_json_gen.go | 107 +++++++++++++++++++++++--------- pkg/api/oas_schemas_gen.go | 75 +++++++++++++++------- pkg/internal/oas_json_gen.go | 72 +++++++++++++++------ pkg/internal/oas_schemas_gen.go | 50 ++++++++++----- 4 files changed, 222 insertions(+), 82 deletions(-) diff --git a/pkg/api/oas_json_gen.go b/pkg/api/oas_json_gen.go index 756801d..1fec134 100644 --- a/pkg/api/oas_json_gen.go +++ b/pkg/api/oas_json_gen.go @@ -562,17 +562,22 @@ func (s *Script) encodeFields(e *jx.Encoder) { e.Str(s.Source) } { - e.FieldStart("SubmissionID") - e.Int64(s.SubmissionID) + e.FieldStart("ResourceType") + e.Int32(s.ResourceType) + } + { + e.FieldStart("ResourceID") + e.Int64(s.ResourceID) } } -var jsonFieldsNameOfScript = [5]string{ +var jsonFieldsNameOfScript = [6]string{ 0: "ID", 1: "Name", 2: "Hash", 3: "Source", - 4: "SubmissionID", + 4: "ResourceType", + 5: "ResourceID", } // Decode decodes Script from json. @@ -632,17 +637,29 @@ func (s *Script) Decode(d *jx.Decoder) error { }(); err != nil { return errors.Wrap(err, "decode field \"Source\"") } - case "SubmissionID": + case "ResourceType": requiredBitSet[0] |= 1 << 4 if err := func() error { - v, err := d.Int64() - s.SubmissionID = int64(v) + v, err := d.Int32() + s.ResourceType = int32(v) if err != nil { return err } return nil }(); err != nil { - return errors.Wrap(err, "decode field \"SubmissionID\"") + return errors.Wrap(err, "decode field \"ResourceType\"") + } + case "ResourceID": + requiredBitSet[0] |= 1 << 5 + if err := func() error { + v, err := d.Int64() + s.ResourceID = int64(v) + if err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"ResourceID\"") } default: return d.Skip() @@ -654,7 +671,7 @@ func (s *Script) Decode(d *jx.Decoder) error { // Validate required fields. var failures []validate.FieldError for i, mask := range [1]uint8{ - 0b00011111, + 0b00111111, } { if result := (requiredBitSet[i] & mask) ^ mask; result != 0 { // Mask only required fields and check equality to mask using XOR. @@ -718,17 +735,22 @@ func (s *ScriptCreate) encodeFields(e *jx.Encoder) { e.Str(s.Source) } { - if s.SubmissionID.Set { - e.FieldStart("SubmissionID") - s.SubmissionID.Encode(e) + e.FieldStart("ResourceType") + e.Int32(s.ResourceType) + } + { + if s.ResourceID.Set { + e.FieldStart("ResourceID") + s.ResourceID.Encode(e) } } } -var jsonFieldsNameOfScriptCreate = [3]string{ +var jsonFieldsNameOfScriptCreate = [4]string{ 0: "Name", 1: "Source", - 2: "SubmissionID", + 2: "ResourceType", + 3: "ResourceID", } // Decode decodes ScriptCreate from json. @@ -764,15 +786,27 @@ func (s *ScriptCreate) Decode(d *jx.Decoder) error { }(); err != nil { return errors.Wrap(err, "decode field \"Source\"") } - case "SubmissionID": + case "ResourceType": + requiredBitSet[0] |= 1 << 2 if err := func() error { - s.SubmissionID.Reset() - if err := s.SubmissionID.Decode(d); err != nil { + v, err := d.Int32() + s.ResourceType = int32(v) + if err != nil { return err } return nil }(); err != nil { - return errors.Wrap(err, "decode field \"SubmissionID\"") + return errors.Wrap(err, "decode field \"ResourceType\"") + } + case "ResourceID": + if err := func() error { + s.ResourceID.Reset() + if err := s.ResourceID.Decode(d); err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"ResourceID\"") } default: return d.Skip() @@ -784,7 +818,7 @@ func (s *ScriptCreate) Decode(d *jx.Decoder) error { // Validate required fields. var failures []validate.FieldError for i, mask := range [1]uint8{ - 0b00000011, + 0b00000111, } { if result := (requiredBitSet[i] & mask) ^ mask; result != 0 { // Mask only required fields and check equality to mask using XOR. @@ -1280,18 +1314,25 @@ func (s *ScriptUpdate) encodeFields(e *jx.Encoder) { } } { - if s.SubmissionID.Set { - e.FieldStart("SubmissionID") - s.SubmissionID.Encode(e) + if s.ResourceType.Set { + e.FieldStart("ResourceType") + s.ResourceType.Encode(e) + } + } + { + if s.ResourceID.Set { + e.FieldStart("ResourceID") + s.ResourceID.Encode(e) } } } -var jsonFieldsNameOfScriptUpdate = [4]string{ +var jsonFieldsNameOfScriptUpdate = [5]string{ 0: "ID", 1: "Name", 2: "Source", - 3: "SubmissionID", + 3: "ResourceType", + 4: "ResourceID", } // Decode decodes ScriptUpdate from json. @@ -1335,15 +1376,25 @@ func (s *ScriptUpdate) Decode(d *jx.Decoder) error { }(); err != nil { return errors.Wrap(err, "decode field \"Source\"") } - case "SubmissionID": + case "ResourceType": if err := func() error { - s.SubmissionID.Reset() - if err := s.SubmissionID.Decode(d); err != nil { + s.ResourceType.Reset() + if err := s.ResourceType.Decode(d); err != nil { return err } return nil }(); err != nil { - return errors.Wrap(err, "decode field \"SubmissionID\"") + return errors.Wrap(err, "decode field \"ResourceType\"") + } + case "ResourceID": + if err := func() error { + s.ResourceID.Reset() + if err := s.ResourceID.Decode(d); err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"ResourceID\"") } default: return d.Skip() diff --git a/pkg/api/oas_schemas_gen.go b/pkg/api/oas_schemas_gen.go index b779939..ce8774f 100644 --- a/pkg/api/oas_schemas_gen.go +++ b/pkg/api/oas_schemas_gen.go @@ -314,7 +314,8 @@ type Script struct { Name string `json:"Name"` Hash string `json:"Hash"` Source string `json:"Source"` - SubmissionID int64 `json:"SubmissionID"` + ResourceType int32 `json:"ResourceType"` + ResourceID int64 `json:"ResourceID"` } // GetID returns the value of ID. @@ -337,9 +338,14 @@ func (s *Script) GetSource() string { return s.Source } -// GetSubmissionID returns the value of SubmissionID. -func (s *Script) GetSubmissionID() int64 { - return s.SubmissionID +// GetResourceType returns the value of ResourceType. +func (s *Script) GetResourceType() int32 { + return s.ResourceType +} + +// GetResourceID returns the value of ResourceID. +func (s *Script) GetResourceID() int64 { + return s.ResourceID } // SetID sets the value of ID. @@ -362,16 +368,22 @@ func (s *Script) SetSource(val string) { s.Source = val } -// SetSubmissionID sets the value of SubmissionID. -func (s *Script) SetSubmissionID(val int64) { - s.SubmissionID = val +// SetResourceType sets the value of ResourceType. +func (s *Script) SetResourceType(val int32) { + s.ResourceType = val +} + +// SetResourceID sets the value of ResourceID. +func (s *Script) SetResourceID(val int64) { + s.ResourceID = val } // Ref: #/components/schemas/ScriptCreate type ScriptCreate struct { Name string `json:"Name"` Source string `json:"Source"` - SubmissionID OptInt64 `json:"SubmissionID"` + ResourceType int32 `json:"ResourceType"` + ResourceID OptInt64 `json:"ResourceID"` } // GetName returns the value of Name. @@ -384,9 +396,14 @@ func (s *ScriptCreate) GetSource() string { return s.Source } -// GetSubmissionID returns the value of SubmissionID. -func (s *ScriptCreate) GetSubmissionID() OptInt64 { - return s.SubmissionID +// GetResourceType returns the value of ResourceType. +func (s *ScriptCreate) GetResourceType() int32 { + return s.ResourceType +} + +// GetResourceID returns the value of ResourceID. +func (s *ScriptCreate) GetResourceID() OptInt64 { + return s.ResourceID } // SetName sets the value of Name. @@ -399,9 +416,14 @@ func (s *ScriptCreate) SetSource(val string) { s.Source = val } -// SetSubmissionID sets the value of SubmissionID. -func (s *ScriptCreate) SetSubmissionID(val OptInt64) { - s.SubmissionID = val +// SetResourceType sets the value of ResourceType. +func (s *ScriptCreate) SetResourceType(val int32) { + s.ResourceType = val +} + +// SetResourceID sets the value of ResourceID. +func (s *ScriptCreate) SetResourceID(val OptInt64) { + s.ResourceID = val } // Ref: #/components/schemas/ScriptPolicy @@ -542,7 +564,8 @@ type ScriptUpdate struct { ID int64 `json:"ID"` Name OptString `json:"Name"` Source OptString `json:"Source"` - SubmissionID OptInt64 `json:"SubmissionID"` + ResourceType OptInt32 `json:"ResourceType"` + ResourceID OptInt64 `json:"ResourceID"` } // GetID returns the value of ID. @@ -560,9 +583,14 @@ func (s *ScriptUpdate) GetSource() OptString { return s.Source } -// GetSubmissionID returns the value of SubmissionID. -func (s *ScriptUpdate) GetSubmissionID() OptInt64 { - return s.SubmissionID +// GetResourceType returns the value of ResourceType. +func (s *ScriptUpdate) GetResourceType() OptInt32 { + return s.ResourceType +} + +// GetResourceID returns the value of ResourceID. +func (s *ScriptUpdate) GetResourceID() OptInt64 { + return s.ResourceID } // SetID sets the value of ID. @@ -580,9 +608,14 @@ func (s *ScriptUpdate) SetSource(val OptString) { s.Source = val } -// SetSubmissionID sets the value of SubmissionID. -func (s *ScriptUpdate) SetSubmissionID(val OptInt64) { - s.SubmissionID = val +// SetResourceType sets the value of ResourceType. +func (s *ScriptUpdate) SetResourceType(val OptInt32) { + s.ResourceType = val +} + +// SetResourceID sets the value of ResourceID. +func (s *ScriptUpdate) SetResourceID(val OptInt64) { + s.ResourceID = val } // SetSubmissionCompletedNoContent is response for SetSubmissionCompleted operation. diff --git a/pkg/internal/oas_json_gen.go b/pkg/internal/oas_json_gen.go index 47793c8..7b03e7b 100644 --- a/pkg/internal/oas_json_gen.go +++ b/pkg/internal/oas_json_gen.go @@ -282,17 +282,22 @@ func (s *Script) encodeFields(e *jx.Encoder) { e.Str(s.Source) } { - e.FieldStart("SubmissionID") - e.Int64(s.SubmissionID) + e.FieldStart("ResourceType") + e.Int32(s.ResourceType) + } + { + e.FieldStart("ResourceID") + e.Int64(s.ResourceID) } } -var jsonFieldsNameOfScript = [5]string{ +var jsonFieldsNameOfScript = [6]string{ 0: "ID", 1: "Name", 2: "Hash", 3: "Source", - 4: "SubmissionID", + 4: "ResourceType", + 5: "ResourceID", } // Decode decodes Script from json. @@ -352,17 +357,29 @@ func (s *Script) Decode(d *jx.Decoder) error { }(); err != nil { return errors.Wrap(err, "decode field \"Source\"") } - case "SubmissionID": + case "ResourceType": requiredBitSet[0] |= 1 << 4 if err := func() error { - v, err := d.Int64() - s.SubmissionID = int64(v) + v, err := d.Int32() + s.ResourceType = int32(v) if err != nil { return err } return nil }(); err != nil { - return errors.Wrap(err, "decode field \"SubmissionID\"") + return errors.Wrap(err, "decode field \"ResourceType\"") + } + case "ResourceID": + requiredBitSet[0] |= 1 << 5 + if err := func() error { + v, err := d.Int64() + s.ResourceID = int64(v) + if err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"ResourceID\"") } default: return d.Skip() @@ -374,7 +391,7 @@ func (s *Script) Decode(d *jx.Decoder) error { // Validate required fields. var failures []validate.FieldError for i, mask := range [1]uint8{ - 0b00011111, + 0b00111111, } { if result := (requiredBitSet[i] & mask) ^ mask; result != 0 { // Mask only required fields and check equality to mask using XOR. @@ -438,17 +455,22 @@ func (s *ScriptCreate) encodeFields(e *jx.Encoder) { e.Str(s.Source) } { - if s.SubmissionID.Set { - e.FieldStart("SubmissionID") - s.SubmissionID.Encode(e) + e.FieldStart("ResourceType") + e.Int32(s.ResourceType) + } + { + if s.ResourceID.Set { + e.FieldStart("ResourceID") + s.ResourceID.Encode(e) } } } -var jsonFieldsNameOfScriptCreate = [3]string{ +var jsonFieldsNameOfScriptCreate = [4]string{ 0: "Name", 1: "Source", - 2: "SubmissionID", + 2: "ResourceType", + 3: "ResourceID", } // Decode decodes ScriptCreate from json. @@ -484,15 +506,27 @@ func (s *ScriptCreate) Decode(d *jx.Decoder) error { }(); err != nil { return errors.Wrap(err, "decode field \"Source\"") } - case "SubmissionID": + case "ResourceType": + requiredBitSet[0] |= 1 << 2 if err := func() error { - s.SubmissionID.Reset() - if err := s.SubmissionID.Decode(d); err != nil { + v, err := d.Int32() + s.ResourceType = int32(v) + if err != nil { return err } return nil }(); err != nil { - return errors.Wrap(err, "decode field \"SubmissionID\"") + return errors.Wrap(err, "decode field \"ResourceType\"") + } + case "ResourceID": + if err := func() error { + s.ResourceID.Reset() + if err := s.ResourceID.Decode(d); err != nil { + return err + } + return nil + }(); err != nil { + return errors.Wrap(err, "decode field \"ResourceID\"") } default: return d.Skip() @@ -504,7 +538,7 @@ func (s *ScriptCreate) Decode(d *jx.Decoder) error { // Validate required fields. var failures []validate.FieldError for i, mask := range [1]uint8{ - 0b00000011, + 0b00000111, } { if result := (requiredBitSet[i] & mask) ^ mask; result != 0 { // Mask only required fields and check equality to mask using XOR. diff --git a/pkg/internal/oas_schemas_gen.go b/pkg/internal/oas_schemas_gen.go index c2bcdad..4805a04 100644 --- a/pkg/internal/oas_schemas_gen.go +++ b/pkg/internal/oas_schemas_gen.go @@ -231,7 +231,8 @@ type Script struct { Name string `json:"Name"` Hash string `json:"Hash"` Source string `json:"Source"` - SubmissionID int64 `json:"SubmissionID"` + ResourceType int32 `json:"ResourceType"` + ResourceID int64 `json:"ResourceID"` } // GetID returns the value of ID. @@ -254,9 +255,14 @@ func (s *Script) GetSource() string { return s.Source } -// GetSubmissionID returns the value of SubmissionID. -func (s *Script) GetSubmissionID() int64 { - return s.SubmissionID +// GetResourceType returns the value of ResourceType. +func (s *Script) GetResourceType() int32 { + return s.ResourceType +} + +// GetResourceID returns the value of ResourceID. +func (s *Script) GetResourceID() int64 { + return s.ResourceID } // SetID sets the value of ID. @@ -279,16 +285,22 @@ func (s *Script) SetSource(val string) { s.Source = val } -// SetSubmissionID sets the value of SubmissionID. -func (s *Script) SetSubmissionID(val int64) { - s.SubmissionID = val +// SetResourceType sets the value of ResourceType. +func (s *Script) SetResourceType(val int32) { + s.ResourceType = val +} + +// SetResourceID sets the value of ResourceID. +func (s *Script) SetResourceID(val int64) { + s.ResourceID = val } // Ref: #/components/schemas/ScriptCreate type ScriptCreate struct { Name string `json:"Name"` Source string `json:"Source"` - SubmissionID OptInt64 `json:"SubmissionID"` + ResourceType int32 `json:"ResourceType"` + ResourceID OptInt64 `json:"ResourceID"` } // GetName returns the value of Name. @@ -301,9 +313,14 @@ func (s *ScriptCreate) GetSource() string { return s.Source } -// GetSubmissionID returns the value of SubmissionID. -func (s *ScriptCreate) GetSubmissionID() OptInt64 { - return s.SubmissionID +// GetResourceType returns the value of ResourceType. +func (s *ScriptCreate) GetResourceType() int32 { + return s.ResourceType +} + +// GetResourceID returns the value of ResourceID. +func (s *ScriptCreate) GetResourceID() OptInt64 { + return s.ResourceID } // SetName sets the value of Name. @@ -316,9 +333,14 @@ func (s *ScriptCreate) SetSource(val string) { s.Source = val } -// SetSubmissionID sets the value of SubmissionID. -func (s *ScriptCreate) SetSubmissionID(val OptInt64) { - s.SubmissionID = val +// SetResourceType sets the value of ResourceType. +func (s *ScriptCreate) SetResourceType(val int32) { + s.ResourceType = val +} + +// SetResourceID sets the value of ResourceID. +func (s *ScriptCreate) SetResourceID(val OptInt64) { + s.ResourceID = val } // Ref: #/components/schemas/ScriptPolicy -- 2.47.1 From 8366b84d909a19cfdc1de7b13f0aede8875d8ee1 Mon Sep 17 00:00:00 2001 From: Quaternions <krakow20@gmail.com> Date: Mon, 31 Mar 2025 18:13:31 -0700 Subject: [PATCH 15/18] submissions: tweak script data model --- pkg/service/scripts.go | 16 +++++++++++----- pkg/service_internal/scripts.go | 9 ++++++--- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/pkg/service/scripts.go b/pkg/service/scripts.go index 2a67e84..931d607 100644 --- a/pkg/service/scripts.go +++ b/pkg/service/scripts.go @@ -32,7 +32,8 @@ func (svc *Service) CreateScript(ctx context.Context, req *api.ScriptCreate) (*a Name: req.Name, Hash: int64(model.HashSource(req.Source)), Source: req.Source, - SubmissionID: req.SubmissionID.Or(0), + ResourceType: model.ResourceType(req.ResourceType), + ResourceID: req.ResourceID.Or(0), }) if err != nil { return nil, err @@ -82,7 +83,8 @@ func (svc *Service) ListScripts(ctx context.Context, params api.ListScriptsParam ID: item.ID, Hash: model.HashFormat(uint64(item.Hash)), Source: item.Source, - SubmissionID: item.SubmissionID, + ResourceType: int32(item.ResourceType), + ResourceID: item.ResourceID, }) } @@ -134,7 +136,8 @@ func (svc *Service) GetScript(ctx context.Context, params api.GetScriptParams) ( Name: script.Name, Hash: model.HashFormat(uint64(script.Hash)), Source: script.Source, - SubmissionID: script.SubmissionID, + ResourceType: int32(script.ResourceType), + ResourceID: script.ResourceID, }, nil } @@ -165,8 +168,11 @@ func (svc *Service) UpdateScript(ctx context.Context, req *api.ScriptUpdate, par pmap.Add("source", source) pmap.Add("hash", int64(model.HashSource(source))) // No type safety! } - if SubmissionID, ok := req.SubmissionID.Get(); ok { - pmap.Add("submission_id", SubmissionID) + if ResourceType, ok := req.ResourceType.Get(); ok { + pmap.Add("resource_type", ResourceType) + } + if ResourceID, ok := req.ResourceID.Get(); ok { + pmap.Add("resource_id", ResourceID) } return svc.DB.Scripts().Update(ctx, req.ID, pmap) } diff --git a/pkg/service_internal/scripts.go b/pkg/service_internal/scripts.go index 3cb0280..afa4868 100644 --- a/pkg/service_internal/scripts.go +++ b/pkg/service_internal/scripts.go @@ -19,7 +19,8 @@ func (svc *Service) CreateScript(ctx context.Context, req *api.ScriptCreate) (*a Name: req.Name, Hash: int64(model.HashSource(req.Source)), Source: req.Source, - SubmissionID: req.SubmissionID.Or(0), + ResourceType: model.ResourceType(req.ResourceType), + ResourceID: req.ResourceID.Or(0), }) if err != nil { return nil, err @@ -69,7 +70,8 @@ func (svc *Service) ListScripts(ctx context.Context, params api.ListScriptsParam ID: item.ID, Hash: model.HashFormat(uint64(item.Hash)), Source: item.Source, - SubmissionID: item.SubmissionID, + ResourceType: int32(item.ResourceType), + ResourceID: item.ResourceID, }) } @@ -92,6 +94,7 @@ func (svc *Service) GetScript(ctx context.Context, params api.GetScriptParams) ( Name: script.Name, Hash: model.HashFormat(uint64(script.Hash)), Source: script.Source, - SubmissionID: script.SubmissionID, + ResourceType: int32(script.ResourceType), + ResourceID: script.ResourceID, }, nil } -- 2.47.1 From 01785bb190254a7cb4dadd29b0eec763a7ba7d80 Mon Sep 17 00:00:00 2001 From: Quaternions <krakow20@gmail.com> Date: Mon, 31 Mar 2025 16:59:07 -0700 Subject: [PATCH 16/18] validator: move files --- validation/src/main.rs | 4 ++-- validation/src/{upload_fix.rs => upload_mapfix.rs} | 0 validation/src/{upload_new.rs => upload_submission.rs} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename validation/src/{upload_fix.rs => upload_mapfix.rs} (100%) rename validation/src/{upload_new.rs => upload_submission.rs} (100%) diff --git a/validation/src/main.rs b/validation/src/main.rs index 0ee2e2b..f557b50 100644 --- a/validation/src/main.rs +++ b/validation/src/main.rs @@ -2,8 +2,8 @@ use futures::StreamExt; mod nats_types; mod validator; -mod upload_new; -mod upload_fix; +mod upload_submission; +mod upload_mapfix; mod message_handler; #[allow(dead_code)] diff --git a/validation/src/upload_fix.rs b/validation/src/upload_mapfix.rs similarity index 100% rename from validation/src/upload_fix.rs rename to validation/src/upload_mapfix.rs diff --git a/validation/src/upload_new.rs b/validation/src/upload_submission.rs similarity index 100% rename from validation/src/upload_new.rs rename to validation/src/upload_submission.rs -- 2.47.1 From ade54ee6626553a8af8db51ad7309fbb3a525a52 Mon Sep 17 00:00:00 2001 From: Quaternions <krakow20@gmail.com> Date: Mon, 31 Mar 2025 17:57:00 -0700 Subject: [PATCH 17/18] validator: refactor + remove mapfix capability --- validation/api/src/external.rs | 10 ++- validation/api/src/internal.rs | 10 ++- validation/api/src/types.rs | 18 +++++- validation/src/main.rs | 10 +-- validation/src/message_handler.rs | 20 +++--- validation/src/nats_types.rs | 23 +++---- validation/src/types.rs | 4 ++ validation/src/upload_mapfix.rs | 44 +++++-------- validation/src/upload_submission.rs | 31 +++------ validation/src/uploader.rs | 18 ++++++ validation/src/validate_mapfix.rs | 45 +++++++++++++ validation/src/validate_submission.rs | 45 +++++++++++++ validation/src/validator.rs | 91 ++++++++++++++++----------- 13 files changed, 247 insertions(+), 122 deletions(-) create mode 100644 validation/src/types.rs create mode 100644 validation/src/uploader.rs create mode 100644 validation/src/validate_mapfix.rs create mode 100644 validation/src/validate_submission.rs diff --git a/validation/api/src/external.rs b/validation/api/src/external.rs index d89c2f9..b31ee1b 100644 --- a/validation/api/src/external.rs +++ b/validation/api/src/external.rs @@ -33,8 +33,11 @@ impl Context{ if let Some(source)=config.Source{ query_pairs.append_pair("Source",source); } - if let Some(submission_id)=config.SubmissionID{ - query_pairs.append_pair("SubmissionID",submission_id.to_string().as_str()); + if let Some(resource_type)=config.ResourceType{ + query_pairs.append_pair("ResourceType",(resource_type as i32).to_string().as_str()); + } + if let Some(resource_id)=config.ResourceID{ + query_pairs.append_pair("ResourceID",resource_id.to_string().as_str()); } } @@ -50,7 +53,8 @@ impl Context{ Hash:Some(config.hash), Name:None, Source:None, - SubmissionID:None, + ResourceType:None, + ResourceID:None, }).await.map_err(SingleItemError::Other)?; if 1<scripts.len(){ return Err(SingleItemError::DuplicateItems); diff --git a/validation/api/src/internal.rs b/validation/api/src/internal.rs index 54429e6..347f70a 100644 --- a/validation/api/src/internal.rs +++ b/validation/api/src/internal.rs @@ -48,8 +48,11 @@ impl Context{ if let Some(source)=config.Source{ query_pairs.append_pair("Source",source); } - if let Some(submission_id)=config.SubmissionID{ - query_pairs.append_pair("SubmissionID",submission_id.to_string().as_str()); + if let Some(resource_type)=config.ResourceType{ + query_pairs.append_pair("ResourceType",(resource_type as i32).to_string().as_str()); + } + if let Some(resource_id)=config.ResourceID{ + query_pairs.append_pair("ResourceID",resource_id.to_string().as_str()); } } @@ -65,7 +68,8 @@ impl Context{ Hash:Some(config.hash), Name:None, Source:None, - SubmissionID:None, + ResourceType:None, + ResourceID:None, }).await.map_err(SingleItemError::Other)?; if 1<scripts.len(){ return Err(SingleItemError::DuplicateItems); diff --git a/validation/api/src/types.rs b/validation/api/src/types.rs index 21da6aa..d09d502 100644 --- a/validation/api/src/types.rs +++ b/validation/api/src/types.rs @@ -65,6 +65,14 @@ pub struct ScriptID(pub(crate)i64); #[derive(Clone,Copy,Debug,serde::Serialize,serde::Deserialize)] pub struct ScriptPolicyID(pub(crate)i64); +#[derive(Clone,Copy,Debug,PartialEq,Eq,serde_repr::Serialize_repr,serde_repr::Deserialize_repr)] +#[repr(i32)] +pub enum ResourceType{ + Unknown=0, + Mapfix=1, + Submission=2, +} + #[allow(nonstandard_style)] pub struct GetScriptRequest{ pub ScriptID:ScriptID, @@ -81,7 +89,9 @@ pub struct GetScriptsRequest<'a>{ #[serde(skip_serializing_if="Option::is_none")] pub Source:Option<&'a str>, #[serde(skip_serializing_if="Option::is_none")] - pub SubmissionID:Option<i64>, + pub ResourceType:Option<ResourceType>, + #[serde(skip_serializing_if="Option::is_none")] + pub ResourceID:Option<i64>, } #[derive(Clone,Copy,Debug)] pub struct HashRequest<'a>{ @@ -94,15 +104,17 @@ pub struct ScriptResponse{ pub Name:String, pub Hash:String, pub Source:String, - pub SubmissionID:i64, + pub ResourceType:ResourceType, + pub ResourceID:i64, } #[allow(nonstandard_style)] #[derive(Clone,Debug,serde::Serialize)] pub struct CreateScriptRequest<'a>{ pub Name:&'a str, pub Source:&'a str, + pub ResourceType:ResourceType, #[serde(skip_serializing_if="Option::is_none")] - pub SubmissionID:Option<i64>, + pub ResourceID:Option<i64>, } #[allow(nonstandard_style)] #[derive(Clone,Debug,serde::Deserialize)] diff --git a/validation/src/main.rs b/validation/src/main.rs index f557b50..681e529 100644 --- a/validation/src/main.rs +++ b/validation/src/main.rs @@ -1,10 +1,12 @@ use futures::StreamExt; -mod nats_types; -mod validator; -mod upload_submission; -mod upload_mapfix; mod message_handler; +mod nats_types; +mod types; +mod uploader; +mod upload_submission; +mod validator; +mod validate_submission; #[allow(dead_code)] #[derive(Debug)] diff --git a/validation/src/message_handler.rs b/validation/src/message_handler.rs index 519baf7..3b7bdb8 100644 --- a/validation/src/message_handler.rs +++ b/validation/src/message_handler.rs @@ -5,9 +5,8 @@ pub enum HandleMessageError{ DoubleAck(async_nats::Error), Json(serde_json::Error), UnknownSubject(String), - UploadNew(crate::upload_new::UploadError), - UploadFix(crate::upload_fix::UploadError), - Validation(crate::validator::ValidateError), + UploadSubmission(crate::upload_submission::UploadError), + ValidateSubmission(crate::validate_submission::ValidateSubmissionError), } impl std::fmt::Display for HandleMessageError{ fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ @@ -23,9 +22,8 @@ fn from_slice<'a,T:serde::de::Deserialize<'a>>(slice:&'a [u8])->Result<T,HandleM } pub struct MessageHandler{ - upload_new:crate::upload_new::Uploader, - upload_fix:crate::upload_fix::Uploader, - validator:crate::validator::Validator, + upload_submission:crate::upload_submission::Uploader, + validate_submission:crate::validate_submission::Validator, } impl MessageHandler{ @@ -35,18 +33,16 @@ impl MessageHandler{ api:submissions_api::internal::Context, )->Self{ Self{ - upload_new:crate::upload_new::Uploader::new(cookie_context.clone(),group_id,api.clone()), - upload_fix:crate::upload_fix::Uploader::new(cookie_context.clone(),group_id,api.clone()), - validator:crate::validator::Validator::new(cookie_context,api), + upload_submission:crate::upload_submission::Uploader::new(crate::uploader::Uploader::new(cookie_context.clone(),group_id,api.clone())), + validate_submission:crate::validate_submission::Validator::new(crate::validator::Validator::new(cookie_context,api)), } } pub async fn handle_message_result(&self,message_result:MessageResult)->Result<(),HandleMessageError>{ let message=message_result.map_err(HandleMessageError::Messages)?; message.double_ack().await.map_err(HandleMessageError::DoubleAck)?; match message.subject.as_str(){ - "maptest.mapfixes.upload"=>self.upload_fix.upload(from_slice(&message.payload)?).await.map_err(HandleMessageError::UploadFix), - "maptest.submissions.upload"=>self.upload_new.upload(from_slice(&message.payload)?).await.map_err(HandleMessageError::UploadNew), - "maptest.submissions.validate"=>self.validator.validate(from_slice(&message.payload)?).await.map_err(HandleMessageError::Validation), + "maptest.submissions.upload"=>self.upload_submission.upload(from_slice(&message.payload)?).await.map_err(HandleMessageError::UploadSubmission), + "maptest.submissions.validate"=>self.validate_submission.validate(from_slice(&message.payload)?).await.map_err(HandleMessageError::ValidateSubmission), other=>Err(HandleMessageError::UnknownSubject(other.to_owned())) } } diff --git a/validation/src/nats_types.rs b/validation/src/nats_types.rs index de41e7d..dc2369c 100644 --- a/validation/src/nats_types.rs +++ b/validation/src/nats_types.rs @@ -6,7 +6,7 @@ #[allow(nonstandard_style)] #[derive(serde::Deserialize)] -pub struct ValidateRequest{ +pub struct ValidateSubmissionRequest{ // submission_id is passed back in the response message pub SubmissionID:i64, pub ModelID:u64, @@ -14,21 +14,22 @@ pub struct ValidateRequest{ pub ValidatedModelID:Option<u64>, } +#[allow(nonstandard_style)] +#[derive(serde::Deserialize)] +pub struct ValidateMapfixRequest{ + // submission_id is passed back in the response message + pub MapfixID:i64, + pub ModelID:u64, + pub ModelVersion:u64, + pub ValidatedModelID:Option<u64>, +} + // Create a new map #[allow(nonstandard_style)] #[derive(serde::Deserialize)] -pub struct UploadNewRequest{ +pub struct UploadSubmissionRequest{ pub SubmissionID:i64, pub ModelID:u64, pub ModelVersion:u64, pub ModelName:String, } - -#[allow(nonstandard_style)] -#[derive(serde::Deserialize)] -pub struct UploadFixRequest{ - pub SubmissionID:i64, - pub ModelID:u64, - pub ModelVersion:u64, - pub TargetAssetID:u64, -} diff --git a/validation/src/types.rs b/validation/src/types.rs new file mode 100644 index 0000000..875c18e --- /dev/null +++ b/validation/src/types.rs @@ -0,0 +1,4 @@ +pub enum ResourceID{ + Mapfix(i64), + Submission(i64), +} diff --git a/validation/src/upload_mapfix.rs b/validation/src/upload_mapfix.rs index 23b375c..71c37fd 100644 --- a/validation/src/upload_mapfix.rs +++ b/validation/src/upload_mapfix.rs @@ -1,4 +1,4 @@ -use crate::nats_types::UploadFixRequest; +use crate::nats_types::UploadMapfixRequest; #[allow(dead_code)] #[derive(Debug)] @@ -6,8 +6,7 @@ pub enum UploadError{ Get(rbx_asset::cookie::GetError), Json(serde_json::Error), Upload(rbx_asset::cookie::UploadError), - ApiActionSubmissionUploaded(submissions_api::Error), - Unimplemented, + ApiActionMapfixUploaded(submissions_api::Error), } impl std::fmt::Display for UploadError{ fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ @@ -16,34 +15,23 @@ impl std::fmt::Display for UploadError{ } impl std::error::Error for UploadError{} -pub struct Uploader{ - roblox_cookie:rbx_asset::cookie::CookieContext, - group_id:Option<u64>, - api_internal:submissions_api::internal::Context, -} +pub struct Uploader(crate::uploader::Uploader); impl Uploader{ - pub const fn new( - roblox_cookie:rbx_asset::cookie::CookieContext, - group_id:Option<u64>, - api_internal:submissions_api::internal::Context, - )->Self{ - Self{ - roblox_cookie, - group_id, - api_internal, - } + pub const fn new(inner:crate::uploader::Uploader)->Self{ + Self(inner) } - pub async fn upload(&self,upload_info:UploadFixRequest)->Result<(),UploadError>{ + pub async fn upload(&self,upload_info:UploadMapfixRequest)->Result<(),UploadError>{ + let Self(uploader)=self; // download the map model version - let model_data=self.roblox_cookie.get_asset(rbx_asset::cookie::GetAssetRequest{ + let model_data=uploader.roblox_cookie.get_asset(rbx_asset::cookie::GetAssetRequest{ asset_id:upload_info.ModelID, version:Some(upload_info.ModelVersion), }).await.map_err(UploadError::Get)?; // upload the map to the strafesnet group - let _upload_response=self.roblox_cookie.upload(rbx_asset::cookie::UploadRequest{ + let _upload_response=uploader.roblox_cookie.upload(rbx_asset::cookie::UploadRequest{ assetid:upload_info.TargetAssetID, - groupId:self.group_id, + groupId:uploader.group_id, name:None, description:None, ispublic:None, @@ -52,14 +40,10 @@ impl Uploader{ // that's it, the database entry does not need to be changed. - //TEMP - return Err(UploadError::Unimplemented); - - // mark submission as uploaded, TargetAssetID is unchanged - self.api_internal.action_submission_uploaded(submissions_api::types::ActionSubmissionUploadedRequest{ - SubmissionID:upload_info.SubmissionID, - UploadedAssetID:0, //TEMP - }).await.map_err(UploadError::ApiActionSubmissionUploaded)?; + // mark mapfix as uploaded, TargetAssetID is unchanged + uploader.api.action_mapfix_uploaded(submissions_api::types::ActionMapfixUploadedRequest{ + MapfixID:upload_info.MapfixID, + }).await.map_err(UploadError::ApiActionMapfixUploaded)?; Ok(()) } diff --git a/validation/src/upload_submission.rs b/validation/src/upload_submission.rs index 2a0a6be..d5c0983 100644 --- a/validation/src/upload_submission.rs +++ b/validation/src/upload_submission.rs @@ -1,4 +1,4 @@ -use crate::nats_types::UploadNewRequest; +use crate::nats_types::UploadSubmissionRequest; #[allow(dead_code)] #[derive(Debug)] @@ -16,41 +16,30 @@ impl std::fmt::Display for UploadError{ } impl std::error::Error for UploadError{} -pub struct Uploader{ - roblox_cookie:rbx_asset::cookie::CookieContext, - group_id:Option<u64>, - api:submissions_api::internal::Context, -} +pub struct Uploader(crate::uploader::Uploader); impl Uploader{ - pub const fn new( - roblox_cookie:rbx_asset::cookie::CookieContext, - group_id:Option<u64>, - api:submissions_api::internal::Context, - )->Self{ - Self{ - roblox_cookie, - group_id, - api, - } + pub const fn new(inner:crate::uploader::Uploader)->Self{ + Self(inner) } - pub async fn upload(&self,upload_info:UploadNewRequest)->Result<(),UploadError>{ + pub async fn upload(&self,upload_info:UploadSubmissionRequest)->Result<(),UploadError>{ + let Self(uploader)=self; // download the map model version - let model_data=self.roblox_cookie.get_asset(rbx_asset::cookie::GetAssetRequest{ + let model_data=uploader.roblox_cookie.get_asset(rbx_asset::cookie::GetAssetRequest{ asset_id:upload_info.ModelID, version:Some(upload_info.ModelVersion), }).await.map_err(UploadError::Get)?; // upload the map to the strafesnet group - let upload_response=self.roblox_cookie.create(rbx_asset::cookie::CreateRequest{ + let upload_response=uploader.roblox_cookie.create(rbx_asset::cookie::CreateRequest{ name:upload_info.ModelName.clone(), description:"".to_owned(), ispublic:false, allowComments:false, - groupId:self.group_id, + groupId:uploader.group_id, },model_data).await.map_err(UploadError::Create)?; // note the asset id of the created model for later release, and mark the submission as uploaded - self.api.action_submission_uploaded(submissions_api::types::ActionSubmissionUploadedRequest{ + uploader.api.action_submission_uploaded(submissions_api::types::ActionSubmissionUploadedRequest{ SubmissionID:upload_info.SubmissionID, UploadedAssetID:upload_response.AssetId, }).await.map_err(UploadError::ApiActionSubmissionUploaded)?; diff --git a/validation/src/uploader.rs b/validation/src/uploader.rs new file mode 100644 index 0000000..ca1ba06 --- /dev/null +++ b/validation/src/uploader.rs @@ -0,0 +1,18 @@ +pub struct Uploader{ + pub(crate) roblox_cookie:rbx_asset::cookie::CookieContext, + pub(crate) group_id:Option<u64>, + pub(crate) api:submissions_api::internal::Context, +} +impl Uploader{ + pub const fn new( + roblox_cookie:rbx_asset::cookie::CookieContext, + group_id:Option<u64>, + api:submissions_api::internal::Context, + )->Self{ + Self{ + roblox_cookie, + group_id, + api, + } + } +} diff --git a/validation/src/validate_mapfix.rs b/validation/src/validate_mapfix.rs new file mode 100644 index 0000000..f9334d5 --- /dev/null +++ b/validation/src/validate_mapfix.rs @@ -0,0 +1,45 @@ +use crate::nats_types::ValidateMapfixRequest; + +#[allow(dead_code)] +#[derive(Debug)] +pub enum ValidateMapfixError{ + ApiActionMapfixValidate(submissions_api::Error), +} +impl std::fmt::Display for ValidateMapfixError{ + fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ + write!(f,"{self:?}") + } +} +impl std::error::Error for ValidateMapfixError{} + +pub struct Validator(crate::validator::Validator); +impl Validator{ + pub const fn new(inner:crate::validator::Validator)->Self{ + Self(inner) + } + pub async fn validate(&self,validate_info:ValidateMapfixRequest)->Result<(),ValidateMapfixError>{ + let Self(validator)=self; + + let mapfix_id=validate_info.MapfixID; + let validate_result=validator.validate(validate_info.into()).await; + + // update the mapfix depending on the result + match &validate_result{ + Ok(())=>{ + // update the mapfix model status to validated + validator.api.action_mapfix_validated( + submissions_api::types::MapfixID(mapfix_id) + ).await.map_err(ValidateMapfixError::ApiActionMapfixValidate)?; + }, + Err(e)=>{ + // update the mapfix model status to accepted + validator.api.action_mapfix_accepted(submissions_api::types::ActionMapfixAcceptedRequest{ + MapfixID:mapfix_id, + StatusMessage:format!("{e}"), + }).await.map_err(ValidateMapfixError::ApiActionMapfixValidate)?; + }, + } + + Ok(()) + } +} diff --git a/validation/src/validate_submission.rs b/validation/src/validate_submission.rs new file mode 100644 index 0000000..51ae1f3 --- /dev/null +++ b/validation/src/validate_submission.rs @@ -0,0 +1,45 @@ +use crate::nats_types::ValidateSubmissionRequest; + +#[allow(dead_code)] +#[derive(Debug)] +pub enum ValidateSubmissionError{ + ApiActionSubmissionValidate(submissions_api::Error), +} +impl std::fmt::Display for ValidateSubmissionError{ + fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ + write!(f,"{self:?}") + } +} +impl std::error::Error for ValidateSubmissionError{} + +pub struct Validator(crate::validator::Validator); +impl Validator{ + pub const fn new(inner:crate::validator::Validator)->Self{ + Self(inner) + } + pub async fn validate(&self,validate_info:ValidateSubmissionRequest)->Result<(),ValidateSubmissionError>{ + let Self(validator)=self; + + let submission_id=validate_info.SubmissionID; + let validate_result=validator.validate(validate_info.into()).await; + + // update the submission depending on the result + match &validate_result{ + Ok(())=>{ + // update the submission model status to validated + validator.api.action_submission_validated( + submissions_api::types::SubmissionID(submission_id) + ).await.map_err(ValidateSubmissionError::ApiActionSubmissionValidate)?; + }, + Err(e)=>{ + // update the submission model status to accepted + validator.api.action_submission_accepted(submissions_api::types::ActionSubmissionAcceptedRequest{ + SubmissionID:submission_id, + StatusMessage:format!("{e}"), + }).await.map_err(ValidateSubmissionError::ApiActionSubmissionValidate)?; + }, + } + + Ok(()) + } +} diff --git a/validation/src/validator.rs b/validation/src/validator.rs index 3b9e58f..6babbf4 100644 --- a/validation/src/validator.rs +++ b/validation/src/validator.rs @@ -1,6 +1,7 @@ use futures::TryStreamExt; +use submissions_api::types::ResourceType; -use crate::nats_types::ValidateRequest; +use crate::types::ResourceID; const SCRIPT_CONCURRENCY:usize=16; @@ -41,8 +42,8 @@ pub enum ValidateError{ ApiCreateScript(submissions_api::Error), ApiCreateScriptPolicy(submissions_api::Error), ApiGetScriptFromHash(submissions_api::types::SingleItemError), + ApiUpdateMapfixModelUnimplemented, ApiUpdateSubmissionModel(submissions_api::Error), - ApiActionSubmissionValidate(submissions_api::Error), ModelFileRootMustHaveOneChild, ModelFileChildRefIsNil, ModelFileEncode(rbx_binary::EncodeError), @@ -56,9 +57,38 @@ impl std::fmt::Display for ValidateError{ } impl std::error::Error for ValidateError{} +#[allow(nonstandard_style)] +pub struct ValidateRequest{ + pub ModelID:u64, + pub ModelVersion:u64, + pub ValidatedModelID:Option<u64>, + pub ResourceID:ResourceID, +} + +impl From<crate::nats_types::ValidateMapfixRequest> for ValidateRequest{ + fn from(value:crate::nats_types::ValidateMapfixRequest)->Self{ + Self{ + ModelID:value.ModelID, + ModelVersion:value.ModelVersion, + ValidatedModelID:value.ValidatedModelID, + ResourceID:ResourceID::Mapfix(value.MapfixID), + } + } +} +impl From<crate::nats_types::ValidateSubmissionRequest> for ValidateRequest{ + fn from(value:crate::nats_types::ValidateSubmissionRequest)->Self{ + Self{ + ModelID:value.ModelID, + ModelVersion:value.ModelVersion, + ValidatedModelID:value.ValidatedModelID, + ResourceID:ResourceID::Submission(value.SubmissionID), + } + } +} + pub struct Validator{ - roblox_cookie:rbx_asset::cookie::CookieContext, - api:submissions_api::internal::Context, + pub(crate) roblox_cookie:rbx_asset::cookie::CookieContext, + pub(crate) api:submissions_api::internal::Context, } impl Validator{ @@ -72,29 +102,6 @@ impl Validator{ } } pub async fn validate(&self,validate_info:ValidateRequest)->Result<(),ValidateError>{ - let submission_id=validate_info.SubmissionID; - let validate_result=self.validate_inner(validate_info).await; - - // update the submission depending on the result - match &validate_result{ - Ok(())=>{ - // update the submission model status to validated - self.api.action_submission_validated( - submissions_api::types::SubmissionID(submission_id) - ).await.map_err(ValidateError::ApiActionSubmissionValidate)?; - }, - Err(e)=>{ - // update the submission model status to accepted - self.api.action_submission_accepted(submissions_api::types::ActionSubmissionAcceptedRequest{ - SubmissionID:submission_id, - StatusMessage:format!("{e}"), - }).await.map_err(ValidateError::ApiActionSubmissionValidate)?; - }, - } - - validate_result - } - pub async fn validate_inner(&self,validate_info:ValidateRequest)->Result<(),ValidateError>{ // download map let data=self.roblox_cookie.get_asset(rbx_asset::cookie::GetAssetRequest{ asset_id:validate_info.ModelID, @@ -155,11 +162,17 @@ impl Validator{ }, }; }else{ + let (resource_type,resource_id)=match validate_info.ResourceID{ + ResourceID::Mapfix(mapfix_id)=>(ResourceType::Mapfix,mapfix_id), + ResourceID::Submission(submission_id)=>(ResourceType::Submission,submission_id), + }; + // upload the script let script=self.api.create_script(submissions_api::types::CreateScriptRequest{ Name:name.as_str(), Source:source.as_str(), - SubmissionID:Some(validate_info.SubmissionID), + ResourceType:resource_type, + ResourceID:Some(resource_id), }).await.map_err(ValidateError::ApiCreateScript)?; // create a None policy (pending review by yours truly) @@ -252,13 +265,21 @@ impl Validator{ response.AssetId }; - // update the submission to use the validated model - self.api.update_submission_validated_model(submissions_api::types::UpdateSubmissionModelRequest{ - SubmissionID:validate_info.SubmissionID, - ModelID:model_id, - ModelVersion:1, //TODO - }).await.map_err(ValidateError::ApiUpdateSubmissionModel)?; - }; + match validate_info.ResourceID{ + ResourceID::Mapfix(_mapfix_id)=>{ + // update the mapfix to use the validated model + return Err(ValidateError::ApiUpdateMapfixModelUnimplemented); + }, + ResourceID::Submission(submission_id)=>{ + // update the submission to use the validated model + self.api.update_submission_validated_model(submissions_api::types::UpdateSubmissionModelRequest{ + SubmissionID:submission_id, + ModelID:model_id, + ModelVersion:1, //TODO + }).await.map_err(ValidateError::ApiUpdateSubmissionModel)?; + }, + } + } Ok(()) } -- 2.47.1 From 758c2254ebaf44bd59aa7fe71580b68061b5b6b6 Mon Sep 17 00:00:00 2001 From: Quaternions <krakow20@gmail.com> Date: Mon, 31 Mar 2025 19:09:22 -0700 Subject: [PATCH 18/18] submissions-api: create new error variant --- validation/api/src/external.rs | 10 +++++----- validation/api/src/internal.rs | 10 +++++----- validation/api/src/types.rs | 1 + 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/validation/api/src/external.rs b/validation/api/src/external.rs index b31ee1b..8aa00d2 100644 --- a/validation/api/src/external.rs +++ b/validation/api/src/external.rs @@ -14,7 +14,7 @@ impl Context{ response_ok( self.0.get(url).await.map_err(Error::Reqwest)? ).await.map_err(Error::Response)? - .json().await.map_err(Error::Reqwest) + .json().await.map_err(Error::ReqwestJson) } pub async fn get_scripts<'a>(&self,config:GetScriptsRequest<'a>)->Result<Vec<ScriptResponse>,Error>{ let url_raw=format!("{}/scripts",self.0.base_url); @@ -44,7 +44,7 @@ impl Context{ response_ok( self.0.get(url).await.map_err(Error::Reqwest)? ).await.map_err(Error::Response)? - .json().await.map_err(Error::Reqwest) + .json().await.map_err(Error::ReqwestJson) } pub async fn get_script_from_hash<'a>(&self,config:HashRequest<'a>)->Result<Option<ScriptResponse>,SingleItemError>{ let scripts=self.get_scripts(GetScriptsRequest{ @@ -70,7 +70,7 @@ impl Context{ response_ok( self.0.post(url,body).await.map_err(Error::Reqwest)? ).await.map_err(Error::Response)? - .json().await.map_err(Error::Reqwest) + .json().await.map_err(Error::ReqwestJson) } pub async fn get_script_policies<'a>(&self,config:GetScriptPoliciesRequest<'a>)->Result<Vec<ScriptPolicyResponse>,Error>{ let url_raw=format!("{}/script-policy",self.0.base_url); @@ -94,7 +94,7 @@ impl Context{ response_ok( self.0.get(url).await.map_err(Error::Reqwest)? ).await.map_err(Error::Response)? - .json().await.map_err(Error::Reqwest) + .json().await.map_err(Error::ReqwestJson) } pub async fn get_script_policy_from_hash<'a>(&self,config:HashRequest<'a>)->Result<Option<ScriptPolicyResponse>,SingleItemError>{ let policies=self.get_script_policies(GetScriptPoliciesRequest{ @@ -118,7 +118,7 @@ impl Context{ response_ok( self.0.post(url,body).await.map_err(Error::Reqwest)? ).await.map_err(Error::Response)? - .json().await.map_err(Error::Reqwest) + .json().await.map_err(Error::ReqwestJson) } pub async fn update_script_policy(&self,config:UpdateScriptPolicyRequest)->Result<(),Error>{ let url_raw=format!("{}/script-policy/{}",self.0.base_url,config.ID.0); diff --git a/validation/api/src/internal.rs b/validation/api/src/internal.rs index 347f70a..990466d 100644 --- a/validation/api/src/internal.rs +++ b/validation/api/src/internal.rs @@ -29,7 +29,7 @@ impl Context{ response_ok( self.0.get(url).await.map_err(Error::Reqwest)? ).await.map_err(Error::Response)? - .json().await.map_err(Error::Reqwest) + .json().await.map_err(Error::ReqwestJson) } pub async fn get_scripts<'a>(&self,config:GetScriptsRequest<'a>)->Result<Vec<ScriptResponse>,Error>{ let url_raw=format!("{}/scripts",self.0.base_url); @@ -59,7 +59,7 @@ impl Context{ response_ok( self.0.get(url).await.map_err(Error::Reqwest)? ).await.map_err(Error::Response)? - .json().await.map_err(Error::Reqwest) + .json().await.map_err(Error::ReqwestJson) } pub async fn get_script_from_hash<'a>(&self,config:HashRequest<'a>)->Result<Option<ScriptResponse>,SingleItemError>{ let scripts=self.get_scripts(GetScriptsRequest{ @@ -85,7 +85,7 @@ impl Context{ response_ok( self.0.post(url,body).await.map_err(Error::Reqwest)? ).await.map_err(Error::Response)? - .json().await.map_err(Error::Reqwest) + .json().await.map_err(Error::ReqwestJson) } pub async fn get_script_policies<'a>(&self,config:GetScriptPoliciesRequest<'a>)->Result<Vec<ScriptPolicyResponse>,Error>{ let url_raw=format!("{}/script-policy",self.0.base_url); @@ -109,7 +109,7 @@ impl Context{ response_ok( self.0.get(url).await.map_err(Error::Reqwest)? ).await.map_err(Error::Response)? - .json().await.map_err(Error::Reqwest) + .json().await.map_err(Error::ReqwestJson) } pub async fn get_script_policy_from_hash<'a>(&self,config:HashRequest<'a>)->Result<Option<ScriptPolicyResponse>,SingleItemError>{ let policies=self.get_script_policies(GetScriptPoliciesRequest{ @@ -133,7 +133,7 @@ impl Context{ response_ok( self.0.post(url,body).await.map_err(Error::Reqwest)? ).await.map_err(Error::Response)? - .json().await.map_err(Error::Reqwest) + .json().await.map_err(Error::ReqwestJson) } pub async fn update_submission_validated_model(&self,config:UpdateSubmissionModelRequest)->Result<(),Error>{ let url_raw=format!("{}/submissions/{}/validated-model",self.0.base_url,config.SubmissionID); diff --git a/validation/api/src/types.rs b/validation/api/src/types.rs index d09d502..60d1f4c 100644 --- a/validation/api/src/types.rs +++ b/validation/api/src/types.rs @@ -2,6 +2,7 @@ pub enum Error{ Parse(url::ParseError), Reqwest(reqwest::Error), + ReqwestJson(reqwest::Error), Response(ResponseError), JSON(serde_json::Error), } -- 2.47.1