maps-service/pkg/service/submissions.go

345 lines
11 KiB
Go
Raw Normal View History

2024-11-26 23:30:58 +00:00
package service
2024-11-26 23:28:48 +00:00
import (
2024-11-27 23:38:17 +00:00
"time"
2024-11-28 02:19:19 +00:00
"errors"
2024-11-26 23:28:48 +00:00
"context"
"git.itzana.me/strafesnet/maps-service/pkg/api"
2024-11-27 23:38:17 +00:00
"git.itzana.me/strafesnet/maps-service/pkg/model"
2024-11-28 00:38:22 +00:00
"git.itzana.me/strafesnet/maps-service/pkg/datastore"
2024-11-26 23:28:48 +00:00
)
2024-11-28 02:19:19 +00:00
var (
// ErrInvalidSourceStatus current submission status cannot change to destination status
ErrInvalidSourceStatus = errors.New("Invalid source status")
)
2024-11-26 23:28:48 +00:00
// POST /submissions
2024-12-06 02:48:26 +00:00
func (svc *Service) CreateSubmission(ctx context.Context, request *api.SubmissionCreate) (*api.ID, error) {
2024-12-10 05:19:38 +00:00
userInfo, ok := ctx.Value("UserInfo").(UserInfo)
2024-11-29 21:58:47 +00:00
if !ok{
return nil, ErrUserInfo
}
2024-11-27 23:38:17 +00:00
submission, err := svc.DB.Submissions().Create(ctx, model.Submission{
ID: 0,
2024-12-06 02:48:26 +00:00
DisplayName: request.DisplayName,
Creator: request.Creator,
GameID: request.GameID,
2024-11-27 23:38:17 +00:00
Date: time.Now(),
2024-11-29 21:58:47 +00:00
Submitter: int64(userInfo.UserID),
2024-12-06 02:48:26 +00:00
AssetID: request.AssetID,
AssetVersion: request.AssetVersion,
2024-11-27 23:38:17 +00:00
Completed: false,
2024-12-06 02:48:26 +00:00
TargetAssetID: request.TargetAssetID.Value,
StatusID: model.StatusUnderConstruction,
2024-11-27 23:38:17 +00:00
})
if err != nil{
return nil, err
}
return &api.ID{
2024-12-06 00:41:06 +00:00
ID:submission.ID,
2024-11-27 23:38:17 +00:00
}, nil
2024-11-26 23:28:48 +00:00
}
// GetSubmission implements getSubmission operation.
//
// Retrieve map with ID.
//
// GET /submissions/{SubmissionID}
2024-11-26 23:30:58 +00:00
func (svc *Service) GetSubmission(ctx context.Context, params api.GetSubmissionParams) (*api.Submission, error) {
2024-11-26 23:55:56 +00:00
submission, err := svc.DB.Submissions().Get(ctx, params.SubmissionID)
if err != nil{
return nil, err
}
return &api.Submission{
2024-12-06 00:41:06 +00:00
ID: submission.ID,
DisplayName: submission.DisplayName,
Creator: submission.Creator,
GameID: submission.GameID,
Date: submission.Date.Unix(),
Submitter: submission.Submitter,
AssetID: submission.AssetID,
AssetVersion: submission.AssetVersion,
Completed: submission.Completed,
2024-11-26 23:55:56 +00:00
TargetAssetID: api.NewOptInt64(submission.TargetAssetID),
2024-12-06 00:41:06 +00:00
StatusID: int32(submission.StatusID),
2024-11-26 23:55:56 +00:00
}, nil
2024-11-26 23:28:48 +00:00
}
// ListSubmissions implements listSubmissions operation.
//
// Get list of submissions.
//
// GET /submissions
2024-11-28 00:38:22 +00:00
func (svc *Service) ListSubmissions(ctx context.Context, request api.ListSubmissionsParams) ([]api.Submission, error) {
filter := datastore.Optional()
//fmt.Println(request)
if request.Filter.IsSet() {
filter.AddNotNil("display_name", request.Filter.Value.DisplayName)
filter.AddNotNil("creator", request.Filter.Value.Creator)
filter.AddNotNil("game_id", request.Filter.Value.GameID)
}
items, err := svc.DB.Submissions().List(ctx, filter, model.Page{
Number: request.Page.GetPage(),
Size: request.Page.GetLimit(),
})
if err != nil{
return nil, err
}
var resp []api.Submission
for i := 0; i < len(items); i++ {
resp = append(resp, api.Submission{
2024-12-06 00:41:06 +00:00
ID: items[i].ID,
DisplayName: items[i].DisplayName,
Creator: items[i].Creator,
GameID: items[i].GameID,
Date: items[i].Date.Unix(),
Submitter: items[i].Submitter,
AssetID: items[i].AssetID,
AssetVersion: items[i].AssetVersion,
Completed: items[i].Completed,
2024-11-28 00:38:22 +00:00
TargetAssetID: api.NewOptInt64(items[i].TargetAssetID),
2024-12-06 00:41:06 +00:00
StatusID: int32(items[i].StatusID),
2024-11-28 00:38:22 +00:00
})
}
return resp, nil
2024-11-26 23:28:48 +00:00
}
// PatchSubmissionCompleted implements patchSubmissionCompleted operation.
//
// Retrieve map with ID.
//
// PATCH /submissions/{SubmissionID}/completed
2024-11-26 23:30:58 +00:00
func (svc *Service) PatchSubmissionCompleted(ctx context.Context, params api.PatchSubmissionCompletedParams) error {
2024-12-10 05:19:38 +00:00
userInfo, ok := ctx.Value("UserInfo").(UserInfo)
2024-11-29 21:58:47 +00:00
if !ok{
return ErrUserInfo
}
2024-11-28 01:27:40 +00:00
// check if caller has MaptestGame role (request must originate from a maptest roblox game)
2024-11-29 21:58:47 +00:00
if !userInfo.Roles.Maptest{
return ErrPermissionDenied
}
2024-11-28 00:44:50 +00:00
pmap := datastore.Optional()
2024-11-28 01:22:59 +00:00
pmap.Add("completed", true)
2024-11-28 00:44:50 +00:00
err := svc.DB.Submissions().Update(ctx, params.SubmissionID, pmap)
return err
2024-11-26 23:28:48 +00:00
}
// PatchSubmissionModel implements patchSubmissionModel operation.
//
// Update model following role restrictions.
//
// PATCH /submissions/{SubmissionID}/model
2024-11-26 23:30:58 +00:00
func (svc *Service) PatchSubmissionModel(ctx context.Context, params api.PatchSubmissionModelParams) error {
2024-12-10 05:19:38 +00:00
userInfo, ok := ctx.Value("UserInfo").(UserInfo)
2024-11-29 21:58:47 +00:00
if !ok{
return ErrUserInfo
}
// read submission (this could be done with a transaction WHERE clause)
submission, err := svc.DB.Submissions().Get(ctx, params.SubmissionID)
if err != nil{
return err
}
// check if caller is the submitter
if !userInfo.IsSubmitter(submission.Submitter){
return ErrPermissionDenied
}
2024-11-28 01:27:40 +00:00
// check if Status is ChangesRequested|Submitted|UnderConstruction
2024-11-28 00:44:50 +00:00
pmap := datastore.Optional()
pmap.AddNotNil("asset_id", params.ModelID)
pmap.AddNotNil("asset_version", params.VersionID)
//always reset completed when model changes
pmap.Add("completed",false)
2024-11-29 21:58:47 +00:00
return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.Status{model.StatusChangesRequested,model.StatusSubmitted,model.StatusUnderConstruction}, pmap)
2024-11-26 23:28:48 +00:00
}
// ActionSubmissionPublish invokes actionSubmissionPublish operation.
2024-11-26 23:28:48 +00:00
//
// Role Validator changes status from Publishing -> Published.
2024-11-26 23:28:48 +00:00
//
// PATCH /submissions/{SubmissionID}/status/publish
func (svc *Service) ActionSubmissionPublish(ctx context.Context, params api.ActionSubmissionPublishParams) error {
2024-12-10 05:19:38 +00:00
userInfo, ok := ctx.Value("UserInfo").(UserInfo)
2024-11-29 21:58:47 +00:00
if !ok{
return ErrUserInfo
}
2024-11-28 02:19:19 +00:00
// check if caller has required role
2024-11-29 21:58:47 +00:00
if !userInfo.Roles.Validator{
return ErrPermissionDenied
}
2024-11-28 02:57:42 +00:00
// transaction
2024-11-28 02:19:19 +00:00
smap := datastore.Optional()
smap.Add("status_id",model.StatusPublished)
2024-11-28 02:57:42 +00:00
return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.Status{model.StatusPublishing}, smap)
}
// ActionSubmissionReject invokes actionSubmissionReject operation.
//
// Role Reviewer changes status from Submitted -> Rejected.
//
// PATCH /submissions/{SubmissionID}/status/reject
func (svc *Service) ActionSubmissionReject(ctx context.Context, params api.ActionSubmissionRejectParams) error {
2024-12-10 05:19:38 +00:00
userInfo, ok := ctx.Value("UserInfo").(UserInfo)
2024-11-29 21:58:47 +00:00
if !ok{
return ErrUserInfo
}
2024-11-28 02:19:19 +00:00
// check if caller has required role
2024-12-06 03:10:01 +00:00
if !userInfo.Roles.SubmissionReview{
2024-11-29 21:58:47 +00:00
return ErrPermissionDenied
}
2024-11-28 02:57:42 +00:00
// transaction
2024-11-28 02:19:19 +00:00
smap := datastore.Optional()
smap.Add("status_id",model.StatusRejected)
2024-11-28 02:57:42 +00:00
return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.Status{model.StatusSubmitted}, smap)
}
// ActionSubmissionRequestChanges invokes actionSubmissionRequestChanges operation.
//
// Role Reviewer changes status from Validated|Accepted|Submitted -> ChangesRequested.
//
// PATCH /submissions/{SubmissionID}/status/request-changes
func (svc *Service) ActionSubmissionRequestChanges(ctx context.Context, params api.ActionSubmissionRequestChangesParams) error {
2024-12-10 05:19:38 +00:00
userInfo, ok := ctx.Value("UserInfo").(UserInfo)
2024-11-29 21:58:47 +00:00
if !ok{
return ErrUserInfo
}
2024-11-28 02:19:19 +00:00
// check if caller has required role
2024-12-06 03:10:01 +00:00
if !userInfo.Roles.SubmissionReview{
2024-11-29 21:58:47 +00:00
return ErrPermissionDenied
}
2024-11-28 02:57:42 +00:00
// transaction
2024-11-28 02:19:19 +00:00
smap := datastore.Optional()
smap.Add("status_id",model.StatusChangesRequested)
2024-11-28 02:57:42 +00:00
return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.Status{model.StatusValidated,model.StatusAccepted,model.StatusSubmitted}, smap)
}
// ActionSubmissionRevoke invokes actionSubmissionRevoke operation.
//
// Role Submitter changes status from Submitted|ChangesRequested -> UnderConstruction.
//
// PATCH /submissions/{SubmissionID}/status/revoke
func (svc *Service) ActionSubmissionRevoke(ctx context.Context, params api.ActionSubmissionRevokeParams) error {
2024-12-10 05:19:38 +00:00
userInfo, ok := ctx.Value("UserInfo").(UserInfo)
2024-11-29 21:58:47 +00:00
if !ok{
return ErrUserInfo
}
// read submission (this could be done with a transaction WHERE clause)
submission, err := svc.DB.Submissions().Get(ctx, params.SubmissionID)
if err != nil{
return err
}
// check if caller is the submitter
if !userInfo.IsSubmitter(submission.Submitter){
return ErrPermissionDenied
}
2024-11-28 02:57:42 +00:00
// transaction
2024-11-28 02:19:19 +00:00
smap := datastore.Optional()
smap.Add("status_id",model.StatusUnderConstruction)
2024-11-28 02:57:42 +00:00
return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.Status{model.StatusSubmitted,model.StatusChangesRequested}, smap)
}
// ActionSubmissionSubmit invokes actionSubmissionSubmit operation.
//
// Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitted.
//
// PATCH /submissions/{SubmissionID}/status/submit
func (svc *Service) ActionSubmissionSubmit(ctx context.Context, params api.ActionSubmissionSubmitParams) error {
2024-12-10 05:19:38 +00:00
userInfo, ok := ctx.Value("UserInfo").(UserInfo)
2024-11-29 21:58:47 +00:00
if !ok{
return ErrUserInfo
}
// read submission (this could be done with a transaction WHERE clause)
submission, err := svc.DB.Submissions().Get(ctx, params.SubmissionID)
if err != nil{
return err
}
// check if caller is the submitter
if !userInfo.IsSubmitter(submission.Submitter){
return ErrPermissionDenied
}
2024-11-28 02:57:42 +00:00
// transaction
2024-11-28 02:19:19 +00:00
smap := datastore.Optional()
smap.Add("status_id",model.StatusSubmitted)
2024-11-28 02:57:42 +00:00
return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.Status{model.StatusUnderConstruction,model.StatusChangesRequested}, smap)
}
// ActionSubmissionTriggerPublish invokes actionSubmissionTriggerPublish operation.
//
// Role Admin changes status from Validated -> Publishing.
//
// PATCH /submissions/{SubmissionID}/status/trigger-publish
func (svc *Service) ActionSubmissionTriggerPublish(ctx context.Context, params api.ActionSubmissionTriggerPublishParams) error {
2024-12-10 05:19:38 +00:00
userInfo, ok := ctx.Value("UserInfo").(UserInfo)
2024-11-29 21:58:47 +00:00
if !ok{
return ErrUserInfo
}
2024-11-28 02:19:19 +00:00
// check if caller has required role
2024-12-06 03:10:01 +00:00
if !userInfo.Roles.SubmissionPublish{
2024-11-29 21:58:47 +00:00
return ErrPermissionDenied
}
2024-11-28 02:57:42 +00:00
// transaction
2024-11-28 02:19:19 +00:00
smap := datastore.Optional()
smap.Add("status_id",model.StatusPublishing)
2024-11-28 02:57:42 +00:00
return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.Status{model.StatusValidated}, smap)
}
// ActionSubmissionTriggerValidate invokes actionSubmissionTriggerValidate operation.
//
// Role Reviewer triggers validation and changes status from Submitted|Accepted -> Validating.
//
// PATCH /submissions/{SubmissionID}/status/trigger-validate
func (svc *Service) ActionSubmissionTriggerValidate(ctx context.Context, params api.ActionSubmissionTriggerValidateParams) error {
2024-12-10 05:19:38 +00:00
userInfo, ok := ctx.Value("UserInfo").(UserInfo)
2024-11-29 21:58:47 +00:00
if !ok{
return ErrUserInfo
}
2024-11-28 02:19:19 +00:00
// check if caller has required role
2024-12-06 03:10:01 +00:00
if !userInfo.Roles.SubmissionReview{
2024-11-29 21:58:47 +00:00
return ErrPermissionDenied
}
2024-11-28 02:57:42 +00:00
// transaction
2024-11-28 02:19:19 +00:00
smap := datastore.Optional()
smap.Add("status_id",model.StatusValidating)
2024-11-28 02:57:42 +00:00
return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.Status{model.StatusSubmitted,model.StatusAccepted}, smap)
}
// ActionSubmissionValidate invokes actionSubmissionValidate operation.
//
// Role Validator changes status from Validating -> Validated.
//
// PATCH /submissions/{SubmissionID}/status/validate
func (svc *Service) ActionSubmissionValidate(ctx context.Context, params api.ActionSubmissionValidateParams) error {
2024-12-10 05:19:38 +00:00
userInfo, ok := ctx.Value("UserInfo").(UserInfo)
2024-11-29 21:58:47 +00:00
if !ok{
return ErrUserInfo
}
2024-11-28 02:19:19 +00:00
// check if caller has required role
2024-11-29 21:58:47 +00:00
if !userInfo.Roles.Validator{
return ErrPermissionDenied
}
2024-11-28 02:57:42 +00:00
// transaction
2024-11-28 02:19:19 +00:00
smap := datastore.Optional()
smap.Add("status_id",model.StatusValidated)
2024-11-28 02:57:42 +00:00
return svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.Status{model.StatusValidating}, smap)
2024-11-26 23:28:48 +00:00
}