submissions: prepare for separate mapfixes

This commit is contained in:
Quaternions 2025-03-31 14:44:26 -07:00
parent 88c3866654
commit dfc2a605f4
Signed by: Quaternions
GPG Key ID: D0DF5964F79AC131
8 changed files with 129 additions and 153 deletions

@ -9,7 +9,16 @@ import (
var ( var (
ErrNotExist = errors.New("resource does not exist") ErrNotExist = errors.New("resource does not exist")
ErroNoRowsAffected = errors.New("query did not affect any rows") 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 { type Datastore interface {
@ -23,10 +32,10 @@ type Submissions interface {
GetList(ctx context.Context, id []int64) ([]model.Submission, error) GetList(ctx context.Context, id []int64) ([]model.Submission, error)
Create(ctx context.Context, smap model.Submission) (model.Submission, error) Create(ctx context.Context, smap model.Submission) (model.Submission, error)
Update(ctx context.Context, id int64, values OptionalMap) error Update(ctx context.Context, id int64, values OptionalMap) error
IfStatusThenUpdate(ctx context.Context, id int64, statuses []model.Status, values OptionalMap) error IfStatusThenUpdate(ctx context.Context, id int64, statuses []model.SubmissionStatus, values OptionalMap) error
IfStatusThenUpdateAndGet(ctx context.Context, id int64, statuses []model.Status, values OptionalMap) (model.Submission, error) IfStatusThenUpdateAndGet(ctx context.Context, id int64, statuses []model.SubmissionStatus, values OptionalMap) (model.Submission, error)
Delete(ctx context.Context, id int64) 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 { type Scripts interface {

@ -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. // 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 := env.db.Model(&model.Script{}).Where("id = ?", id).Where("status IN ?", statuses).Updates(values.Map()).Error; err != nil {
if err == gorm.ErrRecordNotFound { if err == gorm.ErrRecordNotFound {
return datastore.ErrNotExist return datastore.ErrNotExist

@ -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. // 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 := env.db.Model(&model.Submission{}).Where("id = ?", id).Where("status_id IN ?", statuses).Updates(values.Map()).Error; err != nil {
if err == gorm.ErrRecordNotFound { if err == gorm.ErrRecordNotFound {
return datastore.ErrNotExist 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. // the update can only occur if the status matches one of the provided values.
// returns the updated value // 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 var submission model.Submission
result := env.db.Model(&submission). result := env.db.Model(&submission).
Clauses(clause.Returning{}). Clauses(clause.Returning{}).
@ -99,29 +99,29 @@ func (env *Submissions) Delete(ctx context.Context, id int64) error {
return nil 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 var maps []model.Submission
db := env.db db := env.db
switch sort { switch sort {
case model.SubmissionListSortDisabled: case datastore.ListSortDisabled:
// No sort // No sort
break break
case model.SubmissionListSortDisplayNameAscending: case datastore.ListSortDisplayNameAscending:
db=db.Order("display_name ASC") db=db.Order("display_name ASC")
break break
case model.SubmissionListSortDisplayNameDescending: case datastore.ListSortDisplayNameDescending:
db=db.Order("display_name DESC") db=db.Order("display_name DESC")
break break
case model.SubmissionListSortDateAscending: case datastore.ListSortDateAscending:
db=db.Order("created_at ASC") db=db.Order("created_at ASC")
break break
case model.SubmissionListSortDateDescending: case datastore.ListSortDateDescending:
db=db.Order("created_at DESC") db=db.Order("created_at DESC")
break break
default: 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 { if err := db.Where(filters.Map()).Offset(int((page.Number - 1) * page.Size)).Limit(int(page.Size)).Find(&maps).Error; err != nil {

@ -2,34 +2,24 @@ package model
import "time" import "time"
type Status int32 type SubmissionStatus int32
const ( const (
// Phase: Final Status // Phase: Final SubmissionStatus
StatusReleased Status = 9 SubmissionStatusReleased SubmissionStatus = 9
StatusRejected Status = 8 SubmissionStatusRejected SubmissionStatus = 8
// Phase: Testing // Phase: Testing
StatusUploaded Status = 7 // uploaded to the group, but pending release SubmissionStatusUploaded SubmissionStatus = 7 // uploaded to the group, but pending release
StatusUploading Status = 6 SubmissionStatusUploading SubmissionStatus = 6
StatusValidated Status = 5 SubmissionStatusValidated SubmissionStatus = 5
StatusValidating Status = 4 SubmissionStatusValidating SubmissionStatus = 4
StatusAccepted Status = 3 // pending script review, can re-trigger validation SubmissionStatusAccepted SubmissionStatus = 3 // pending script review, can re-trigger validation
// Phase: Creation // Phase: Creation
StatusChangesRequested Status = 2 SubmissionStatusChangesRequested SubmissionStatus = 2
StatusSubmitted Status = 1 SubmissionStatusSubmitted SubmissionStatus = 1
StatusUnderConstruction Status = 0 SubmissionStatusUnderConstruction SubmissionStatus = 0
)
type SubmissionListSort uint32
const (
SubmissionListSortDisabled SubmissionListSort = 0
SubmissionListSortDisplayNameAscending SubmissionListSort = 1
SubmissionListSortDisplayNameDescending SubmissionListSort = 2
SubmissionListSortDateAscending SubmissionListSort = 3
SubmissionListSortDateDescending SubmissionListSort = 4
) )
type Submission struct { type Submission struct {
@ -45,7 +35,7 @@ type Submission struct {
ValidatedAssetID int64 ValidatedAssetID int64
ValidatedAssetVersion int64 ValidatedAssetVersion int64
Completed bool // Has this version of the map been completed at least once on maptest 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. UploadedAssetID int64 // where to upload map fix. if the TargetAssetID is 0, it's a new map.
StatusID Status StatusID SubmissionStatus
StatusMessage string StatusMessage string
} }

@ -19,8 +19,8 @@ type Roles int32
var ( var (
RolesSubmissionRelease Roles = 1<<4 RolesSubmissionRelease Roles = 1<<4
RolesScriptWrite Roles = 1<<3 RolesScriptWrite Roles = 1<<3
RolesSubmissionUpload Roles = 1<<2 RolesMapUpload Roles = 1<<2
RolesSubmissionReview Roles = 1<<1 RolesMapReview Roles = 1<<1
RolesMapDownload Roles = 1<<0 RolesMapDownload Roles = 1<<0
RolesEmpty Roles = 0 RolesEmpty Roles = 0
) )
@ -32,13 +32,13 @@ var (
RoleQuat GroupRole = 255 RoleQuat GroupRole = 255
RoleItzaname GroupRole = 254 RoleItzaname GroupRole = 254
RoleStagingDeveloper GroupRole = 240 RoleStagingDeveloper GroupRole = 240
RolesAll Roles = RolesScriptWrite|RolesSubmissionRelease|RolesSubmissionUpload|RolesSubmissionReview|RolesMapDownload RolesAll Roles = RolesScriptWrite|RolesSubmissionRelease|RolesMapUpload|RolesMapReview|RolesMapDownload
// has SubmissionUpload // has SubmissionUpload
RoleMapAdmin GroupRole = 128 RoleMapAdmin GroupRole = 128
RolesMapAdmin Roles = RolesSubmissionRelease|RolesSubmissionUpload|RolesSubmissionReview|RolesMapDownload RolesMapAdmin Roles = RolesSubmissionRelease|RolesMapUpload|RolesMapReview|RolesMapDownload
// has SubmissionReview // has SubmissionReview
RoleMapCouncil GroupRole = 64 RoleMapCouncil GroupRole = 64
RolesMapCouncil Roles = RolesSubmissionReview|RolesSubmissionUpload|RolesMapDownload RolesMapCouncil Roles = RolesMapReview|RolesMapUpload|RolesMapDownload
// access to downloading maps // access to downloading maps
RoleMapAccess GroupRole = 32 RoleMapAccess GroupRole = 32
RolesMapAccess Roles = RolesMapDownload RolesMapAccess Roles = RolesMapDownload
@ -128,17 +128,23 @@ func (usr UserInfoHandle) GetRoles() (Roles, error) {
} }
// RoleThumbnail // 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) { func (usr UserInfoHandle) HasRoleSubmissionRelease() (bool, error) {
return usr.hasRoles(RolesSubmissionRelease) return usr.hasRoles(RolesSubmissionRelease)
} }
func (usr UserInfoHandle) HasRoleSubmissionUpload() (bool, error) { func (usr UserInfoHandle) HasRoleSubmissionUpload() (bool, error) {
return usr.hasRoles(RolesSubmissionUpload) return usr.hasRoles(RolesMapUpload)
} }
func (usr UserInfoHandle) HasRoleSubmissionReview() (bool, error) { func (usr UserInfoHandle) HasRoleSubmissionReview() (bool, error) {
return usr.hasRoles(RolesSubmissionReview) return usr.hasRoles(RolesMapReview)
}
func (usr UserInfoHandle) HasRoleMapDownload() (bool, error) {
return usr.hasRoles(RolesMapDownload)
} }
func (usr UserInfoHandle) HasRoleScriptWrite() (bool, error) { func (usr UserInfoHandle) HasRoleScriptWrite() (bool, error) {
return usr.hasRoles(RolesScriptWrite) return usr.hasRoles(RolesScriptWrite)

@ -3,6 +3,7 @@ package service
import ( import (
"context" "context"
"errors" "errors"
"fmt"
"git.itzana.me/strafesnet/go-grpc/maps" "git.itzana.me/strafesnet/go-grpc/maps"
"git.itzana.me/strafesnet/maps-service/pkg/api" "git.itzana.me/strafesnet/maps-service/pkg/api"
@ -15,6 +16,14 @@ var (
ErrPermissionDenied = errors.New("Permission denied") ErrPermissionDenied = errors.New("Permission denied")
// ErrUserInfo user info is missing for some reason // ErrUserInfo user info is missing for some reason
ErrUserInfo = errors.New("Missing user info") 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 { type Service struct {

@ -15,45 +15,37 @@ import (
var( var(
CreationPhaseSubmissionsLimit = 20 CreationPhaseSubmissionsLimit = 20
CreationPhaseSubmissionStatuses = []model.Status{ CreationPhaseSubmissionStatuses = []model.SubmissionStatus{
model.StatusChangesRequested, model.SubmissionStatusChangesRequested,
model.StatusSubmitted, model.SubmissionStatusSubmitted,
model.StatusUnderConstruction, model.SubmissionStatusUnderConstruction,
} }
// prevent two mapfixes with same asset id // prevent two mapfixes with same asset id
ActiveSubmissionStatuses = []model.Status{ ActiveSubmissionStatuses = []model.SubmissionStatus{
model.StatusUploading, model.SubmissionStatusUploading,
model.StatusValidated, model.SubmissionStatusValidated,
model.StatusValidating, model.SubmissionStatusValidating,
model.StatusAccepted, model.SubmissionStatusAccepted,
model.StatusChangesRequested, model.SubmissionStatusChangesRequested,
model.StatusSubmitted, model.SubmissionStatusSubmitted,
model.StatusUnderConstruction, model.SubmissionStatusUnderConstruction,
} }
// limit mapfixes in the pipeline to one per target map // limit mapfixes in the pipeline to one per target map
ActiveAcceptedSubmissionStatuses = []model.Status{ ActiveAcceptedSubmissionStatuses = []model.SubmissionStatus{
model.StatusUploading, model.SubmissionStatusUploading,
model.StatusValidated, model.SubmissionStatusValidated,
model.StatusValidating, model.SubmissionStatusValidating,
model.StatusAccepted, model.SubmissionStatusAccepted,
} }
) )
var ( var (
ErrCreationPhaseSubmissionsLimit = errors.New("Active submissions limited to 20") ErrCreationPhaseSubmissionsLimit = errors.New("Active submissions limited to 20")
ErrActiveSubmissionSameAssetID = errors.New("There is an active submission with the same AssetID") 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") 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) 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 // 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{ creation_submissions, err := svc.DB.Submissions().List(ctx, filter, model.Page{
Number: 1, Number: 1,
Size: int32(CreationPhaseSubmissionsLimit), Size: int32(CreationPhaseSubmissionsLimit),
},model.SubmissionListSortDisabled) },datastore.ListSortDisabled)
if err != nil { if err != nil {
return nil, err 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{ active_submissions, err := svc.DB.Submissions().List(ctx, filter, model.Page{
Number: 1, Number: 1,
Size: 1, Size: 1,
},model.SubmissionListSortDisabled) },datastore.ListSortDisabled)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -113,8 +105,7 @@ func (svc *Service) CreateSubmission(ctx context.Context, request *api.Submissio
AssetID: request.AssetID, AssetID: request.AssetID,
AssetVersion: request.AssetVersion, AssetVersion: request.AssetVersion,
Completed: false, Completed: false,
TargetAssetID: request.TargetAssetID.Value, StatusID: model.SubmissionStatusUnderConstruction,
StatusID: model.StatusUnderConstruction,
}) })
if err != nil { if err != nil {
return nil, err return nil, err
@ -145,7 +136,7 @@ func (svc *Service) GetSubmission(ctx context.Context, params api.GetSubmissionP
AssetID: int64(submission.AssetID), AssetID: int64(submission.AssetID),
AssetVersion: int64(submission.AssetVersion), AssetVersion: int64(submission.AssetVersion),
Completed: submission.Completed, Completed: submission.Completed,
TargetAssetID: api.NewOptInt64(int64(submission.TargetAssetID)), UploadedAssetID: api.NewOptInt64(int64(submission.UploadedAssetID)),
StatusID: int32(submission.StatusID), StatusID: int32(submission.StatusID),
StatusMessage: submission.StatusMessage, StatusMessage: submission.StatusMessage,
}, nil }, nil
@ -169,7 +160,7 @@ func (svc *Service) ListSubmissions(ctx context.Context, params api.ListSubmissi
filter.Add("game_id", params.GameID.Value) 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{ items, err := svc.DB.Submissions().List(ctx, filter, model.Page{
Number: params.Page, Number: params.Page,
@ -192,7 +183,7 @@ func (svc *Service) ListSubmissions(ctx context.Context, params api.ListSubmissi
AssetID: int64(item.AssetID), AssetID: int64(item.AssetID),
AssetVersion: int64(item.AssetVersion), AssetVersion: int64(item.AssetVersion),
Completed: item.Completed, Completed: item.Completed,
TargetAssetID: api.NewOptInt64(int64(item.TargetAssetID)), UploadedAssetID: api.NewOptInt64(int64(item.UploadedAssetID)),
StatusID: int32(item.StatusID), StatusID: int32(item.StatusID),
}) })
} }
@ -257,7 +248,7 @@ func (svc *Service) UpdateSubmissionModel(ctx context.Context, params api.Update
pmap.AddNotNil("asset_version", params.VersionID) pmap.AddNotNil("asset_version", params.VersionID)
//always reset completed when model changes //always reset completed when model changes
pmap.Add("completed", false) 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. // ActionSubmissionReject invokes actionSubmissionReject operation.
@ -277,13 +268,13 @@ func (svc *Service) ActionSubmissionReject(ctx context.Context, params api.Actio
} }
// check if caller has required role // check if caller has required role
if !has_role { if !has_role {
return ErrPermissionDeniedNeedRoleSubmissionReview return ErrPermissionDeniedNeedRoleMapReview
} }
// transaction // transaction
smap := datastore.Optional() smap := datastore.Optional()
smap.Add("status_id", model.StatusRejected) smap.Add("status_id", model.SubmissionStatusRejected)
return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.Status{model.StatusSubmitted}, smap) return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusSubmitted}, smap)
} }
// ActionSubmissionRequestChanges invokes actionSubmissionRequestChanges operation. // ActionSubmissionRequestChanges invokes actionSubmissionRequestChanges operation.
@ -303,13 +294,13 @@ func (svc *Service) ActionSubmissionRequestChanges(ctx context.Context, params a
} }
// check if caller has required role // check if caller has required role
if !has_role { if !has_role {
return ErrPermissionDeniedNeedRoleSubmissionReview return ErrPermissionDeniedNeedRoleMapReview
} }
// transaction // transaction
smap := datastore.Optional() smap := datastore.Optional()
smap.Add("status_id", model.StatusChangesRequested) smap.Add("status_id", model.SubmissionStatusChangesRequested)
return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.Status{model.StatusValidated, model.StatusAccepted, model.StatusSubmitted}, smap) return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusValidated, model.SubmissionStatusAccepted, model.SubmissionStatusSubmitted}, smap)
} }
// ActionSubmissionRevoke invokes actionSubmissionRevoke operation. // ActionSubmissionRevoke invokes actionSubmissionRevoke operation.
@ -340,8 +331,8 @@ func (svc *Service) ActionSubmissionRevoke(ctx context.Context, params api.Actio
// transaction // transaction
smap := datastore.Optional() smap := datastore.Optional()
smap.Add("status_id", model.StatusUnderConstruction) smap.Add("status_id", model.SubmissionStatusUnderConstruction)
return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.Status{model.StatusSubmitted, model.StatusChangesRequested}, smap) return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusSubmitted, model.SubmissionStatusChangesRequested}, smap)
} }
// ActionSubmissionSubmit invokes actionSubmissionSubmit operation. // ActionSubmissionSubmit invokes actionSubmissionSubmit operation.
@ -372,8 +363,8 @@ func (svc *Service) ActionSubmissionSubmit(ctx context.Context, params api.Actio
// transaction // transaction
smap := datastore.Optional() smap := datastore.Optional()
smap.Add("status_id", model.StatusSubmitted) smap.Add("status_id", model.SubmissionStatusSubmitted)
return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.Status{model.StatusUnderConstruction, model.StatusChangesRequested}, smap) return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusUnderConstruction, model.SubmissionStatusChangesRequested}, smap)
} }
// ActionSubmissionTriggerUpload invokes actionSubmissionTriggerUpload operation. // ActionSubmissionTriggerUpload invokes actionSubmissionTriggerUpload operation.
@ -393,19 +384,19 @@ func (svc *Service) ActionSubmissionTriggerUpload(ctx context.Context, params ap
} }
// check if caller has required role // check if caller has required role
if !has_role { if !has_role {
return ErrPermissionDeniedNeedRoleSubmissionUpload return ErrPermissionDeniedNeedRoleMapUpload
} }
// transaction // transaction
smap := datastore.Optional() smap := datastore.Optional()
smap.Add("status_id", model.StatusUploading) smap.Add("status_id", model.SubmissionStatusUploading)
submission, err := svc.DB.Submissions().IfStatusThenUpdateAndGet(ctx, params.SubmissionID, []model.Status{model.StatusValidated}, smap) submission, err := svc.DB.Submissions().IfStatusThenUpdateAndGet(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusValidated}, smap)
if err != nil { if err != nil {
return err return err
} }
// sentinel value because we are not using rust // sentinel value because we are not using rust
if submission.TargetAssetID == 0 { if submission.UploadedAssetID == 0 {
// this is a new map // this is a new map
upload_new_request := model.UploadNewRequest{ upload_new_request := model.UploadNewRequest{
SubmissionID: submission.ID, SubmissionID: submission.ID,
@ -422,20 +413,8 @@ func (svc *Service) ActionSubmissionTriggerUpload(ctx context.Context, params ap
svc.Nats.Publish("maptest.submissions.uploadnew", []byte(j)) svc.Nats.Publish("maptest.submissions.uploadnew", []byte(j))
} else { } else {
// this is a map fix // refuse to operate
upload_fix_request := model.UploadFixRequest{ return ErrUploadedAssetIDAlreadyExists
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))
} }
return nil return nil
@ -458,7 +437,7 @@ func (svc *Service) ActionSubmissionValidated(ctx context.Context, params api.Ac
} }
// check if caller has required role // check if caller has required role
if !has_role { if !has_role {
return ErrPermissionDeniedNeedRoleSubmissionUpload return ErrPermissionDeniedNeedRoleMapUpload
} }
// check when submission was updated // check when submission was updated
@ -473,8 +452,8 @@ func (svc *Service) ActionSubmissionValidated(ctx context.Context, params api.Ac
// transaction // transaction
smap := datastore.Optional() smap := datastore.Optional()
smap.Add("status_id", model.StatusValidated) smap.Add("status_id", model.SubmissionStatusValidated)
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)
} }
// ActionSubmissionTriggerValidate invokes actionSubmissionTriggerValidate operation. // ActionSubmissionTriggerValidate invokes actionSubmissionTriggerValidate operation.
@ -494,7 +473,7 @@ func (svc *Service) ActionSubmissionTriggerValidate(ctx context.Context, params
} }
// check if caller has required role // check if caller has required role
if !has_role { if !has_role {
return ErrPermissionDeniedNeedRoleSubmissionReview return ErrPermissionDeniedNeedRoleMapReview
} }
// read submission (this could be done with a transaction WHERE clause) // 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 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 // transaction
smap := datastore.Optional() smap := datastore.Optional()
smap.Add("status_id", model.StatusValidating) smap.Add("status_id", model.SubmissionStatusValidating)
submission, err = svc.DB.Submissions().IfStatusThenUpdateAndGet(ctx, params.SubmissionID, []model.Status{model.StatusSubmitted}, smap) submission, err = svc.DB.Submissions().IfStatusThenUpdateAndGet(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusSubmitted}, smap)
if err != nil { if err != nil {
return err return err
} }
@ -576,13 +538,13 @@ func (svc *Service) ActionSubmissionRetryValidate(ctx context.Context, params ap
} }
// check if caller has required role // check if caller has required role
if !has_role { if !has_role {
return ErrPermissionDeniedNeedRoleSubmissionReview return ErrPermissionDeniedNeedRoleMapReview
} }
// transaction // transaction
smap := datastore.Optional() smap := datastore.Optional()
smap.Add("status_id", model.StatusValidating) smap.Add("status_id", model.SubmissionStatusValidating)
submission, err := svc.DB.Submissions().IfStatusThenUpdateAndGet(ctx, params.SubmissionID, []model.Status{model.StatusAccepted}, smap) submission, err := svc.DB.Submissions().IfStatusThenUpdateAndGet(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusAccepted}, smap)
if err != nil { if err != nil {
return err return err
} }
@ -626,7 +588,7 @@ func (svc *Service) ActionSubmissionAccepted(ctx context.Context, params api.Act
} }
// check if caller has required role // check if caller has required role
if !has_role { if !has_role {
return ErrPermissionDeniedNeedRoleSubmissionReview return ErrPermissionDeniedNeedRoleMapReview
} }
// check when submission was updated // check when submission was updated
@ -641,9 +603,9 @@ func (svc *Service) ActionSubmissionAccepted(ctx context.Context, params api.Act
// transaction // transaction
smap := datastore.Optional() smap := datastore.Optional()
smap.Add("status_id", model.StatusAccepted) smap.Add("status_id", model.SubmissionStatusAccepted)
smap.Add("status_message", "Manually forced reset") 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. // 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 // check each submission to make sure it is ready to release
for _,submission := range submissions{ for _,submission := range submissions{
if submission.StatusID != model.StatusUploaded{ if submission.StatusID != model.SubmissionStatusUploaded{
return ErrReleaseInvalidStatus return ErrReleaseInvalidStatus
} }
if submission.TargetAssetID == 0{ if submission.UploadedAssetID == 0{
return ErrReleaseNoTargetAssetID return ErrReleaseNoUploadedAssetID
} }
} }
@ -691,7 +653,7 @@ func (svc *Service) ReleaseSubmissions(ctx context.Context, request []api.Releas
date := request[i].Date.Unix() date := request[i].Date.Unix()
// create each map with go-grpc // create each map with go-grpc
_, err := svc.Client.Create(ctx, &maps.MapRequest{ _, err := svc.Client.Create(ctx, &maps.MapRequest{
ID: submission.TargetAssetID, ID: submission.UploadedAssetID,
DisplayName: &submission.DisplayName, DisplayName: &submission.DisplayName,
Creator: &submission.Creator, Creator: &submission.Creator,
GameID: &submission.GameID, GameID: &submission.GameID,
@ -703,8 +665,8 @@ func (svc *Service) ReleaseSubmissions(ctx context.Context, request []api.Releas
// update each status to Released // update each status to Released
smap := datastore.Optional() smap := datastore.Optional()
smap.Add("status_id", model.StatusReleased) smap.Add("status_id", model.SubmissionStatusReleased)
err = svc.DB.Submissions().IfStatusThenUpdate(ctx, submission.ID, []model.Status{model.StatusUploaded}, smap) err = svc.DB.Submissions().IfStatusThenUpdate(ctx, submission.ID, []model.SubmissionStatus{model.SubmissionStatusUploaded}, smap)
if err != nil { if err != nil {
return err return err
} }

@ -20,7 +20,7 @@ func (svc *Service) UpdateSubmissionValidatedModel(ctx context.Context, params i
pmap.AddNotNil("validated_asset_version", params.ValidatedModelVersion) pmap.AddNotNil("validated_asset_version", params.ValidatedModelVersion)
// DO NOT reset completed when validated model is updated // DO NOT reset completed when validated model is updated
// pmap.Add("completed", false) // 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. // ActionSubmissionValidate invokes actionSubmissionValidate operation.
@ -33,8 +33,8 @@ func (svc *Service) ActionSubmissionValidated(ctx context.Context, params intern
// transaction // transaction
smap := datastore.Optional() smap := datastore.Optional()
smap.Add("status_id", model.StatusValidated) smap.Add("status_id", model.SubmissionStatusValidated)
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)
} }
// ActionSubmissionAccepted implements actionSubmissionAccepted operation. // ActionSubmissionAccepted implements actionSubmissionAccepted operation.
@ -47,9 +47,9 @@ func (svc *Service) ActionSubmissionAccepted(ctx context.Context, params interna
// transaction // transaction
smap := datastore.Optional() smap := datastore.Optional()
smap.Add("status_id", model.StatusAccepted) smap.Add("status_id", model.SubmissionStatusAccepted)
smap.Add("status_message", params.StatusMessage) 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. // ActionSubmissionUploaded implements actionSubmissionUploaded operation.
@ -62,9 +62,9 @@ func (svc *Service) ActionSubmissionUploaded(ctx context.Context, params interna
// transaction // transaction
smap := datastore.Optional() smap := datastore.Optional()
smap.Add("status_id", model.StatusUploaded) smap.Add("status_id", model.SubmissionStatusUploaded)
if params.TargetAssetID.IsSet() { if params.TargetAssetID.IsSet() {
smap.AddNotNil("target_asset_id", params.TargetAssetID.Value) 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)
} }