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] 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(()) }