From 6a521669016f11e6239d6748ae47e8582e2cfab1 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Wed, 11 Jun 2025 04:11:21 +0000 Subject: [PATCH 1/5] submissions-api: Add Releaser Endpoints (#194) Also uses enums over ints for GameID. Reviewed-on: https://git.itzana.me/StrafesNET/maps-service/pulls/194 Co-authored-by: Quaternions Co-committed-by: Quaternions --- Cargo.lock | 3 +- validation/api/Cargo.toml | 3 +- validation/api/src/external.rs | 78 ++++++++++++++++++ validation/api/src/internal.rs | 4 +- validation/api/src/types.rs | 120 ++++++++++++++++++++++++++-- validation/src/check_mapfix.rs | 2 +- validation/src/check_submission.rs | 2 +- validation/src/create_mapfix.rs | 2 +- validation/src/create_submission.rs | 2 +- validation/src/rbx_util.rs | 9 +++ 10 files changed, 212 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 74a1c20..ee6861c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1903,8 +1903,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "submissions-api" -version = "0.7.2" +version = "0.8.0" dependencies = [ + "chrono", "reqwest", "serde", "serde_json", diff --git a/validation/api/Cargo.toml b/validation/api/Cargo.toml index e4080ef..1bbcd73 100644 --- a/validation/api/Cargo.toml +++ b/validation/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "submissions-api" -version = "0.7.2" +version = "0.8.0" edition = "2021" publish = ["strafesnet"] repository = "https://git.itzana.me/StrafesNET/maps-service" @@ -11,6 +11,7 @@ authors = ["Rhys Lloyd "] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +chrono = { version = "0.4.41", features = ["serde"] } reqwest = { version = "0", features = ["json"] } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/validation/api/src/external.rs b/validation/api/src/external.rs index 4d19bef..82ade93 100644 --- a/validation/api/src/external.rs +++ b/validation/api/src/external.rs @@ -150,6 +150,84 @@ impl Context{ self.0.delete(url).await.map_err(Error::Reqwest)? ).await.map_err(Error::Response)?; + Ok(()) + } + pub async fn get_submissions(&self,config:GetSubmissionsRequest<'_>)->Result{ + let url_raw=format!("{}/submissions",self.0.base_url); + let mut url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::Parse)?; + + { + let mut query_pairs=url.query_pairs_mut(); + query_pairs.append_pair("Page",config.Page.to_string().as_str()); + query_pairs.append_pair("Limit",config.Limit.to_string().as_str()); + if let Some(sort)=config.Sort{ + query_pairs.append_pair("Sort",(sort as u8).to_string().as_str()); + } + if let Some(display_name)=config.DisplayName{ + query_pairs.append_pair("DisplayName",display_name); + } + if let Some(creator)=config.Creator{ + query_pairs.append_pair("Creator",creator); + } + if let Some(game_id)=config.GameID{ + query_pairs.append_pair("GameID",(game_id as u8).to_string().as_str()); + } + if let Some(submitter)=config.Submitter{ + query_pairs.append_pair("Submitter",submitter.to_string().as_str()); + } + if let Some(asset_id)=config.AssetID{ + query_pairs.append_pair("AssetID",asset_id.to_string().as_str()); + } + if let Some(uploaded_asset_id)=config.UploadedAssetID{ + query_pairs.append_pair("UploadedAssetID",uploaded_asset_id.to_string().as_str()); + } + if let Some(status_id)=config.StatusID{ + query_pairs.append_pair("StatusID",(status_id as u8).to_string().as_str()); + } + } + + response_ok( + self.0.get(url).await.map_err(Error::Reqwest)? + ).await.map_err(Error::Response)? + .json().await.map_err(Error::ReqwestJson) + } + pub async fn get_maps(&self,config:GetMapsRequest<'_>)->Result,Error>{ + let url_raw=format!("{}/maps",self.0.base_url); + let mut url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::Parse)?; + + { + let mut query_pairs=url.query_pairs_mut(); + query_pairs.append_pair("Page",config.Page.to_string().as_str()); + query_pairs.append_pair("Limit",config.Limit.to_string().as_str()); + if let Some(sort)=config.Sort{ + query_pairs.append_pair("Sort",(sort as u8).to_string().as_str()); + } + if let Some(display_name)=config.DisplayName{ + query_pairs.append_pair("DisplayName",display_name); + } + if let Some(creator)=config.Creator{ + query_pairs.append_pair("Creator",creator); + } + if let Some(game_id)=config.GameID{ + query_pairs.append_pair("GameID",(game_id as u8).to_string().as_str()); + } + } + + response_ok( + self.0.get(url).await.map_err(Error::Reqwest)? + ).await.map_err(Error::Response)? + .json().await.map_err(Error::ReqwestJson) + } + pub async fn release_submissions(&self,config:ReleaseRequest<'_>)->Result<(),Error>{ + let url_raw=format!("{}/release-submissions",self.0.base_url); + let url=reqwest::Url::parse(url_raw.as_str()).map_err(Error::Parse)?; + + let body=serde_json::to_string(config.schedule).map_err(Error::JSON)?; + + response_ok( + self.0.post(url,body).await.map_err(Error::Reqwest)? + ).await.map_err(Error::Response)?; + Ok(()) } } diff --git a/validation/api/src/internal.rs b/validation/api/src/internal.rs index 0375300..f9717cc 100644 --- a/validation/api/src/internal.rs +++ b/validation/api/src/internal.rs @@ -169,7 +169,7 @@ impl Context{ ("ModelVersion",config.ModelVersion.to_string().as_str()) ("DisplayName",config.DisplayName.as_str()) ("Creator",config.Creator.as_str()) - ("GameID",config.GameID.to_string().as_str()) + ("GameID",(config.GameID as u8).to_string().as_str()) ); action!("submissions",action_submission_validated,config,SubmissionID,"status/validator-validated",config.0,); action!("submissions",update_submission_validated_model,config,UpdateSubmissionModelRequest,"validated-model",config.SubmissionID, @@ -201,7 +201,7 @@ impl Context{ ("ModelVersion",config.ModelVersion.to_string().as_str()) ("DisplayName",config.DisplayName.as_str()) ("Creator",config.Creator.as_str()) - ("GameID",config.GameID.to_string().as_str()) + ("GameID",(config.GameID as u8).to_string().as_str()) ); action!("mapfixes",action_mapfix_validated,config,MapfixID,"status/validator-validated",config.0,); action!("mapfixes",update_mapfix_validated_model,config,UpdateMapfixModelRequest,"validated-model",config.MapfixID, diff --git a/validation/api/src/types.rs b/validation/api/src/types.rs index be8ca5f..14207c4 100644 --- a/validation/api/src/types.rs +++ b/validation/api/src/types.rs @@ -67,6 +67,14 @@ pub async fn response_ok(response:reqwest::Response)->Result{ pub AssetOwner:i64, pub DisplayName:&'a str, pub Creator:&'a str, - pub GameID:i32, + pub GameID:GameID, pub AssetID:u64, pub AssetVersion:u64, pub TargetAssetID:u64, @@ -94,7 +102,7 @@ pub struct CreateSubmissionRequest<'a>{ pub AssetOwner:i64, pub DisplayName:&'a str, pub Creator:&'a str, - pub GameID:i32, + pub GameID:GameID, pub AssetID:u64, pub AssetVersion:u64, pub Status:u32, @@ -235,6 +243,97 @@ pub struct UpdateSubmissionModelRequest{ pub ModelVersion:u64, } +#[derive(Clone,Debug)] +pub enum Sort{ + Disabled=0, + DisplayNameAscending=1, + DisplayNameDescending=2, + DateAscending=3, + DateDescending=4, +} + +#[derive(Clone,Debug,serde_repr::Deserialize_repr)] +#[repr(u8)] +pub enum SubmissionStatus{ + // Phase: Creation + UnderConstruction=0, + ChangesRequested=1, + + // Phase: Review + Submitting=2, + Submitted=3, + + // Phase: Testing + AcceptedUnvalidated=4, // pending script review, can re-trigger validation + Validating=5, + Validated=6, + Uploading=7, + Uploaded=8, // uploaded to the group, but pending release + + // Phase: Final SubmissionStatus + Rejected=9, + Released=10, +} + +#[allow(nonstandard_style)] +#[derive(Clone,Debug)] +pub struct GetSubmissionsRequest<'a>{ + pub Page:u32, + pub Limit:u32, + pub Sort:Option, + pub DisplayName:Option<&'a str>, + pub Creator:Option<&'a str>, + pub GameID:Option, + pub Submitter:Option, + pub AssetID:Option, + pub UploadedAssetID:Option, + pub StatusID:Option, +} + +#[allow(nonstandard_style)] +#[derive(Clone,Debug,serde::Deserialize)] +pub struct SubmissionResponse{ + pub ID:i64, + pub DisplayName:String, + pub Creator:String, + pub GameID:GameID, + pub CreatedAt:i64, + pub UpdatedAt:i64, + pub Submitter:u64, + pub AssetID:u64, + pub AssetVersion:u64, + pub UploadedAssetID:u64, + pub StatusID:SubmissionStatus, +} + +#[allow(nonstandard_style)] +#[derive(Clone,Debug,serde::Deserialize)] +pub struct SubmissionsResponse{ + pub Total:u64, + pub Submissions:Vec, +} + +#[allow(nonstandard_style)] +#[derive(Clone,Debug)] +pub struct GetMapsRequest<'a>{ + pub Page:u32, + pub Limit:u32, + pub Sort:Option, + pub DisplayName:Option<&'a str>, + pub Creator:Option<&'a str>, + pub GameID:Option, +} + +#[allow(nonstandard_style)] +#[derive(Clone,Debug,serde::Deserialize)] +pub struct MapResponse{ + pub ID:i64, + pub DisplayName:String, + pub Creator:String, + pub GameID:GameID, + pub Date:i64, +} + #[allow(nonstandard_style)] #[derive(Clone,Debug)] pub struct ActionSubmissionSubmittedRequest{ @@ -242,7 +341,7 @@ pub struct ActionSubmissionSubmittedRequest{ pub ModelVersion:u64, pub DisplayName:String, pub Creator:String, - pub GameID:u32, + pub GameID:GameID, } #[allow(nonstandard_style)] @@ -266,7 +365,7 @@ pub struct ActionSubmissionAcceptedRequest{ pub ErrorMessage:String, } -#[derive(Clone,Copy,Debug,serde::Deserialize)] +#[derive(Clone,Copy,Debug,serde::Serialize,serde::Deserialize)] pub struct SubmissionID(pub i64); #[allow(nonstandard_style)] @@ -284,7 +383,7 @@ pub struct ActionMapfixSubmittedRequest{ pub ModelVersion:u64, pub DisplayName:String, pub Creator:String, - pub GameID:u32, + pub GameID:GameID, } #[allow(nonstandard_style)] @@ -316,3 +415,14 @@ pub struct ActionOperationFailedRequest{ pub OperationID:i32, pub StatusMessage:String, } + +#[allow(nonstandard_style)] +#[derive(Clone,Debug,serde::Serialize)] +pub struct ReleaseInfo{ + pub SubmissionID:SubmissionID, + pub Date:chrono::DateTime, +} + +pub struct ReleaseRequest<'a>{ + pub schedule:&'a [ReleaseInfo], +} diff --git a/validation/src/check_mapfix.rs b/validation/src/check_mapfix.rs index d8ed2fd..c2eed90 100644 --- a/validation/src/check_mapfix.rs +++ b/validation/src/check_mapfix.rs @@ -27,7 +27,7 @@ impl crate::message_handler::MessageHandler{ ModelVersion:version, DisplayName:map_info.display_name, Creator:map_info.creator, - GameID:map_info.game_id as u32, + GameID:map_info.game_id.into(), } ).await.map_err(Error::ApiActionMapfixCheck)?, // update the mapfix model status to request changes diff --git a/validation/src/check_submission.rs b/validation/src/check_submission.rs index 7e6463a..37ae360 100644 --- a/validation/src/check_submission.rs +++ b/validation/src/check_submission.rs @@ -28,7 +28,7 @@ impl crate::message_handler::MessageHandler{ ModelVersion:version, DisplayName:map_info.display_name, Creator:map_info.creator, - GameID:map_info.game_id as u32, + GameID:map_info.game_id.into(), } ).await.map_err(Error::ApiActionSubmissionCheck)?, // update the submission model status to request changes diff --git a/validation/src/create_mapfix.rs b/validation/src/create_mapfix.rs index 0884efc..d697675 100644 --- a/validation/src/create_mapfix.rs +++ b/validation/src/create_mapfix.rs @@ -28,7 +28,7 @@ impl crate::message_handler::MessageHandler{ DisplayName:create_request.DisplayName.as_deref().unwrap_or_default(), Creator:create_request.Creator.as_deref().unwrap_or_default(), // not great TODO: make this great - GameID:create_request.GameID.unwrap_or(crate::rbx_util::GameID::Bhop) as i32, + GameID:create_request.GameID.unwrap_or(crate::rbx_util::GameID::Bhop).into(), AssetID:create_info.ModelID, AssetVersion:create_request.AssetVersion, TargetAssetID:create_info.TargetAssetID, diff --git a/validation/src/create_submission.rs b/validation/src/create_submission.rs index 56b3bd0..807044f 100644 --- a/validation/src/create_submission.rs +++ b/validation/src/create_submission.rs @@ -42,7 +42,7 @@ impl crate::message_handler::MessageHandler{ AssetOwner:create_request.AssetOwner as i64, DisplayName:display_name, Creator:creator, - GameID:game_id as i32, + GameID:game_id.into(), AssetID:create_info.ModelID, AssetVersion:create_request.AssetVersion, Status:create_info.Status, diff --git a/validation/src/rbx_util.rs b/validation/src/rbx_util.rs index 59cff0d..4f4451c 100644 --- a/validation/src/rbx_util.rs +++ b/validation/src/rbx_util.rs @@ -37,6 +37,15 @@ pub enum GameID{ Surf=2, FlyTrials=5, } +impl From for submissions_api::types::GameID{ + fn from(value:GameID)->Self{ + match value{ + GameID::Bhop=>submissions_api::types::GameID::Bhop, + GameID::Surf=>submissions_api::types::GameID::Surf, + GameID::FlyTrials=>submissions_api::types::GameID::FlyTrials, + } + } +} #[derive(Debug)] pub struct ParseGameIDError; impl std::str::FromStr for GameID{ -- 2.49.1 From 463d14d2b57ddfffcdad26159544504d811a2f66 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Wed, 11 Jun 2025 05:11:14 +0000 Subject: [PATCH 2/5] submissions-api: type all ids (#195) Reviewed-on: https://git.itzana.me/StrafesNET/maps-service/pulls/195 Co-authored-by: Quaternions Co-committed-by: Quaternions --- Cargo.lock | 2 +- validation/api/Cargo.toml | 2 +- validation/api/src/external.rs | 2 +- validation/api/src/internal.rs | 24 +++++------ validation/api/src/types.rs | 60 ++++++++++++++++++--------- validation/src/main.rs | 1 - validation/src/nats_types.rs | 18 ++++---- validation/src/types.rs | 4 -- validation/src/validate_mapfix.rs | 2 +- validation/src/validate_submission.rs | 2 +- validation/src/validator.rs | 20 ++++----- 11 files changed, 75 insertions(+), 62 deletions(-) delete mode 100644 validation/src/types.rs diff --git a/Cargo.lock b/Cargo.lock index ee6861c..4de520c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1903,7 +1903,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "submissions-api" -version = "0.8.0" +version = "0.8.1" dependencies = [ "chrono", "reqwest", diff --git a/validation/api/Cargo.toml b/validation/api/Cargo.toml index 1bbcd73..cb5cb77 100644 --- a/validation/api/Cargo.toml +++ b/validation/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "submissions-api" -version = "0.8.0" +version = "0.8.1" edition = "2021" publish = ["strafesnet"] repository = "https://git.itzana.me/StrafesNET/maps-service" diff --git a/validation/api/src/external.rs b/validation/api/src/external.rs index 82ade93..8523d12 100644 --- a/validation/api/src/external.rs +++ b/validation/api/src/external.rs @@ -36,7 +36,7 @@ impl Context{ 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{ + if let Some(ResourceID(resource_id))=config.ResourceID{ query_pairs.append_pair("ResourceID",resource_id.to_string().as_str()); } } diff --git a/validation/api/src/internal.rs b/validation/api/src/internal.rs index f9717cc..7ed9516 100644 --- a/validation/api/src/internal.rs +++ b/validation/api/src/internal.rs @@ -66,7 +66,7 @@ impl Context{ 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{ + if let Some(ResourceID(resource_id))=config.ResourceID{ query_pairs.append_pair("ResourceID",resource_id.to_string().as_str()); } } @@ -162,24 +162,24 @@ impl Context{ .json().await.map_err(Error::ReqwestJson) } // simple submission endpoints - action!("submissions",action_submission_request_changes,config,ActionSubmissionRequestChangesRequest,"status/validator-request-changes",config.SubmissionID, + action!("submissions",action_submission_request_changes,config,ActionSubmissionRequestChangesRequest,"status/validator-request-changes",config.SubmissionID.0, ("ErrorMessage",config.ErrorMessage.as_str()) ); - action!("submissions",action_submission_submitted,config,ActionSubmissionSubmittedRequest,"status/validator-submitted",config.SubmissionID, + action!("submissions",action_submission_submitted,config,ActionSubmissionSubmittedRequest,"status/validator-submitted",config.SubmissionID.0, ("ModelVersion",config.ModelVersion.to_string().as_str()) ("DisplayName",config.DisplayName.as_str()) ("Creator",config.Creator.as_str()) ("GameID",(config.GameID as u8).to_string().as_str()) ); action!("submissions",action_submission_validated,config,SubmissionID,"status/validator-validated",config.0,); - action!("submissions",update_submission_validated_model,config,UpdateSubmissionModelRequest,"validated-model",config.SubmissionID, + action!("submissions",update_submission_validated_model,config,UpdateSubmissionModelRequest,"validated-model",config.SubmissionID.0, ("ValidatedModelID",config.ModelID.to_string().as_str()) ("ValidatedModelVersion",config.ModelVersion.to_string().as_str()) ); - action!("submissions",action_submission_uploaded,config,ActionSubmissionUploadedRequest,"status/validator-uploaded",config.SubmissionID, + action!("submissions",action_submission_uploaded,config,ActionSubmissionUploadedRequest,"status/validator-uploaded",config.SubmissionID.0, ("UploadedAssetID",config.UploadedAssetID.to_string().as_str()) ); - action!("submissions",action_submission_accepted,config,ActionSubmissionAcceptedRequest,"status/validator-failed",config.SubmissionID, + action!("submissions",action_submission_accepted,config,ActionSubmissionAcceptedRequest,"status/validator-failed",config.SubmissionID.0, ("ErrorMessage",config.ErrorMessage.as_str()) ); pub async fn create_mapfix(&self,config:CreateMapfixRequest<'_>)->Result{ @@ -194,26 +194,26 @@ impl Context{ .json().await.map_err(Error::ReqwestJson) } // simple mapfixes endpoints - action!("mapfixes",action_mapfix_request_changes,config,ActionMapfixRequestChangesRequest,"status/validator-request-changes",config.MapfixID, + action!("mapfixes",action_mapfix_request_changes,config,ActionMapfixRequestChangesRequest,"status/validator-request-changes",config.MapfixID.0, ("ErrorMessage",config.ErrorMessage.as_str()) ); - action!("mapfixes",action_mapfix_submitted,config,ActionMapfixSubmittedRequest,"status/validator-submitted",config.MapfixID, + action!("mapfixes",action_mapfix_submitted,config,ActionMapfixSubmittedRequest,"status/validator-submitted",config.MapfixID.0, ("ModelVersion",config.ModelVersion.to_string().as_str()) ("DisplayName",config.DisplayName.as_str()) ("Creator",config.Creator.as_str()) ("GameID",(config.GameID as u8).to_string().as_str()) ); action!("mapfixes",action_mapfix_validated,config,MapfixID,"status/validator-validated",config.0,); - action!("mapfixes",update_mapfix_validated_model,config,UpdateMapfixModelRequest,"validated-model",config.MapfixID, + action!("mapfixes",update_mapfix_validated_model,config,UpdateMapfixModelRequest,"validated-model",config.MapfixID.0, ("ValidatedModelID",config.ModelID.to_string().as_str()) ("ValidatedModelVersion",config.ModelVersion.to_string().as_str()) ); - action!("mapfixes",action_mapfix_uploaded,config,ActionMapfixUploadedRequest,"status/validator-uploaded",config.MapfixID,); - action!("mapfixes",action_mapfix_accepted,config,ActionMapfixAcceptedRequest,"status/validator-failed",config.MapfixID, + action!("mapfixes",action_mapfix_uploaded,config,ActionMapfixUploadedRequest,"status/validator-uploaded",config.MapfixID.0,); + action!("mapfixes",action_mapfix_accepted,config,ActionMapfixAcceptedRequest,"status/validator-failed",config.MapfixID.0, ("ErrorMessage",config.ErrorMessage.as_str()) ); // simple operation endpoint - action!("operations",action_operation_failed,config,ActionOperationFailedRequest,"status/operation-failed",config.OperationID, + action!("operations",action_operation_failed,config,ActionOperationFailedRequest,"status/operation-failed",config.OperationID.0, ("StatusMessage",config.StatusMessage.as_str()) ); } diff --git a/validation/api/src/types.rs b/validation/api/src/types.rs index 14207c4..1969599 100644 --- a/validation/api/src/types.rs +++ b/validation/api/src/types.rs @@ -79,7 +79,7 @@ pub enum GameID{ #[allow(nonstandard_style)] #[derive(Clone,Debug,serde::Serialize)] pub struct CreateMapfixRequest<'a>{ - pub OperationID:i32, + pub OperationID:OperationID, pub AssetOwner:i64, pub DisplayName:&'a str, pub Creator:&'a str, @@ -98,7 +98,7 @@ pub struct MapfixIDResponse{ #[allow(nonstandard_style)] #[derive(Clone,Debug,serde::Serialize)] pub struct CreateSubmissionRequest<'a>{ - pub OperationID:i32, + pub OperationID:OperationID, pub AssetOwner:i64, pub DisplayName:&'a str, pub Creator:&'a str, @@ -145,7 +145,7 @@ pub struct GetScriptsRequest<'a>{ #[serde(skip_serializing_if="Option::is_none")] pub ResourceType:Option, #[serde(skip_serializing_if="Option::is_none")] - pub ResourceID:Option, + pub ResourceID:Option, } #[derive(Clone,Copy,Debug)] pub struct HashRequest<'a>{ @@ -159,7 +159,7 @@ pub struct ScriptResponse{ pub Hash:String, pub Source:String, pub ResourceType:ResourceType, - pub ResourceID:i64, + pub ResourceID:ResourceID, } #[allow(nonstandard_style)] #[derive(Clone,Debug,serde::Serialize)] @@ -168,7 +168,7 @@ pub struct CreateScriptRequest<'a>{ pub Source:&'a str, pub ResourceType:ResourceType, #[serde(skip_serializing_if="Option::is_none")] - pub ResourceID:Option, + pub ResourceID:Option, } #[allow(nonstandard_style)] #[derive(Clone,Debug,serde::Deserialize)] @@ -238,7 +238,7 @@ pub struct UpdateScriptPolicyRequest{ #[allow(nonstandard_style)] #[derive(Clone,Debug)] pub struct UpdateSubmissionModelRequest{ - pub SubmissionID:i64, + pub SubmissionID:SubmissionID, pub ModelID:u64, pub ModelVersion:u64, } @@ -293,7 +293,7 @@ pub struct GetSubmissionsRequest<'a>{ #[allow(nonstandard_style)] #[derive(Clone,Debug,serde::Deserialize)] pub struct SubmissionResponse{ - pub ID:i64, + pub ID:SubmissionID, pub DisplayName:String, pub Creator:String, pub GameID:GameID, @@ -337,7 +337,7 @@ pub struct MapResponse{ #[allow(nonstandard_style)] #[derive(Clone,Debug)] pub struct ActionSubmissionSubmittedRequest{ - pub SubmissionID:i64, + pub SubmissionID:SubmissionID, pub ModelVersion:u64, pub DisplayName:String, pub Creator:String, @@ -347,31 +347,31 @@ pub struct ActionSubmissionSubmittedRequest{ #[allow(nonstandard_style)] #[derive(Clone,Debug)] pub struct ActionSubmissionRequestChangesRequest{ - pub SubmissionID:i64, + pub SubmissionID:SubmissionID, pub ErrorMessage:String, } #[allow(nonstandard_style)] #[derive(Clone,Debug)] pub struct ActionSubmissionUploadedRequest{ - pub SubmissionID:i64, + pub SubmissionID:SubmissionID, pub UploadedAssetID:u64, } #[allow(nonstandard_style)] #[derive(Clone,Debug)] pub struct ActionSubmissionAcceptedRequest{ - pub SubmissionID:i64, + pub SubmissionID:SubmissionID, pub ErrorMessage:String, } #[derive(Clone,Copy,Debug,serde::Serialize,serde::Deserialize)] -pub struct SubmissionID(pub i64); +pub struct SubmissionID(pub(crate)i64); #[allow(nonstandard_style)] #[derive(Clone,Debug)] pub struct UpdateMapfixModelRequest{ - pub MapfixID:i64, + pub MapfixID:MapfixID, pub ModelID:u64, pub ModelVersion:u64, } @@ -379,7 +379,7 @@ pub struct UpdateMapfixModelRequest{ #[allow(nonstandard_style)] #[derive(Clone,Debug)] pub struct ActionMapfixSubmittedRequest{ - pub MapfixID:i64, + pub MapfixID:MapfixID, pub ModelVersion:u64, pub DisplayName:String, pub Creator:String, @@ -389,33 +389,53 @@ pub struct ActionMapfixSubmittedRequest{ #[allow(nonstandard_style)] #[derive(Clone,Debug)] pub struct ActionMapfixRequestChangesRequest{ - pub MapfixID:i64, + pub MapfixID:MapfixID, pub ErrorMessage:String, } #[allow(nonstandard_style)] #[derive(Clone,Debug)] pub struct ActionMapfixUploadedRequest{ - pub MapfixID:i64, + pub MapfixID:MapfixID, } #[allow(nonstandard_style)] #[derive(Clone,Debug)] pub struct ActionMapfixAcceptedRequest{ - pub MapfixID:i64, + pub MapfixID:MapfixID, pub ErrorMessage:String, } -#[derive(Clone,Copy,Debug,serde::Deserialize)] -pub struct MapfixID(pub i64); +#[derive(Clone,Copy,Debug,serde::Serialize,serde::Deserialize)] +pub struct MapfixID(pub(crate)i64); #[allow(nonstandard_style)] #[derive(Clone,Debug)] pub struct ActionOperationFailedRequest{ - pub OperationID:i32, + pub OperationID:OperationID, pub StatusMessage:String, } +#[derive(Clone,Copy,Debug,serde::Serialize,serde::Deserialize)] +pub struct OperationID(pub(crate)i64); + +#[derive(Clone,Copy,Debug,serde::Serialize,serde::Deserialize)] +pub struct ResourceID(pub(crate)i64); + +#[derive(Clone,Copy,Debug)] +pub enum Resource{ + Submission(SubmissionID), + Mapfix(MapfixID), +} +impl Resource{ + pub fn split(self)->(ResourceType,ResourceID){ + match self{ + Resource::Mapfix(MapfixID(mapfix_id))=>(ResourceType::Mapfix,ResourceID(mapfix_id)), + Resource::Submission(SubmissionID(submission_id))=>(ResourceType::Submission,ResourceID(submission_id)), + } + } +} + #[allow(nonstandard_style)] #[derive(Clone,Debug,serde::Serialize)] pub struct ReleaseInfo{ diff --git a/validation/src/main.rs b/validation/src/main.rs index 69ea99a..02d1d3a 100644 --- a/validation/src/main.rs +++ b/validation/src/main.rs @@ -3,7 +3,6 @@ use futures::StreamExt; mod rbx_util; mod message_handler; mod nats_types; -mod types; mod download; mod check; mod check_mapfix; diff --git a/validation/src/nats_types.rs b/validation/src/nats_types.rs index 6d8d712..db2a7e2 100644 --- a/validation/src/nats_types.rs +++ b/validation/src/nats_types.rs @@ -1,3 +1,5 @@ +use submissions_api::types::{SubmissionID,MapfixID,OperationID}; + // These represent the information needed in the nats message // to perform the operation, not necessarily the over-the-wire format @@ -8,7 +10,7 @@ #[derive(serde::Deserialize)] pub struct CreateSubmissionRequest{ // operation_id is passed back in the response message - pub OperationID:i32, + pub OperationID:OperationID, pub ModelID:u64, pub DisplayName:String, pub Creator:String, @@ -21,7 +23,7 @@ pub struct CreateSubmissionRequest{ #[allow(nonstandard_style)] #[derive(serde::Deserialize)] pub struct CreateMapfixRequest{ - pub OperationID:i32, + pub OperationID:OperationID, pub ModelID:u64, pub TargetAssetID:u64, pub Description:String, @@ -30,14 +32,14 @@ pub struct CreateMapfixRequest{ #[allow(nonstandard_style)] #[derive(serde::Deserialize)] pub struct CheckSubmissionRequest{ - pub SubmissionID:i64, + pub SubmissionID:SubmissionID, pub ModelID:u64, } #[allow(nonstandard_style)] #[derive(serde::Deserialize)] pub struct CheckMapfixRequest{ - pub MapfixID:i64, + pub MapfixID:MapfixID, pub ModelID:u64, } @@ -45,7 +47,7 @@ pub struct CheckMapfixRequest{ #[derive(serde::Deserialize)] pub struct ValidateSubmissionRequest{ // submission_id is passed back in the response message - pub SubmissionID:i64, + pub SubmissionID:SubmissionID, pub ModelID:u64, pub ModelVersion:u64, pub ValidatedModelID:Option, @@ -55,7 +57,7 @@ pub struct ValidateSubmissionRequest{ #[derive(serde::Deserialize)] pub struct ValidateMapfixRequest{ // submission_id is passed back in the response message - pub MapfixID:i64, + pub MapfixID:MapfixID, pub ModelID:u64, pub ModelVersion:u64, pub ValidatedModelID:Option, @@ -65,7 +67,7 @@ pub struct ValidateMapfixRequest{ #[allow(nonstandard_style)] #[derive(serde::Deserialize)] pub struct UploadSubmissionRequest{ - pub SubmissionID:i64, + pub SubmissionID:SubmissionID, pub ModelID:u64, pub ModelVersion:u64, pub ModelName:String, @@ -74,7 +76,7 @@ pub struct UploadSubmissionRequest{ #[allow(nonstandard_style)] #[derive(serde::Deserialize)] pub struct UploadMapfixRequest{ - pub MapfixID:i64, + pub MapfixID:MapfixID, pub ModelID:u64, pub ModelVersion:u64, pub TargetAssetID:u64, diff --git a/validation/src/types.rs b/validation/src/types.rs deleted file mode 100644 index 875c18e..0000000 --- a/validation/src/types.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub enum ResourceID{ - Mapfix(i64), - Submission(i64), -} diff --git a/validation/src/validate_mapfix.rs b/validation/src/validate_mapfix.rs index e08197d..93e087f 100644 --- a/validation/src/validate_mapfix.rs +++ b/validation/src/validate_mapfix.rs @@ -22,7 +22,7 @@ impl crate::message_handler::MessageHandler{ Ok(())=>{ // update the mapfix model status to validated self.api.action_mapfix_validated( - submissions_api::types::MapfixID(mapfix_id) + mapfix_id ).await.map_err(Error::ApiActionMapfixValidate)?; }, Err(e)=>{ diff --git a/validation/src/validate_submission.rs b/validation/src/validate_submission.rs index 5bf97b3..6f6b4c4 100644 --- a/validation/src/validate_submission.rs +++ b/validation/src/validate_submission.rs @@ -22,7 +22,7 @@ impl crate::message_handler::MessageHandler{ Ok(())=>{ // update the submission model status to validated self.api.action_submission_validated( - submissions_api::types::SubmissionID(submission_id) + submission_id ).await.map_err(Error::ApiActionSubmissionValidate)?; }, Err(e)=>{ diff --git a/validation/src/validator.rs b/validation/src/validator.rs index 7912b99..39ffa0c 100644 --- a/validation/src/validator.rs +++ b/validation/src/validator.rs @@ -1,9 +1,8 @@ use futures::TryStreamExt; -use submissions_api::types::ResourceType; +use submissions_api::types::Resource; use crate::download::download_asset_version; use crate::rbx_util::{read_dom,static_ustr,ReadDomError}; -use crate::types::ResourceID; const SCRIPT_CONCURRENCY:usize=16; @@ -70,7 +69,7 @@ pub struct ValidateRequest{ pub ModelID:u64, pub ModelVersion:u64, pub ValidatedModelID:Option, - pub ResourceID:ResourceID, + pub Resource:Resource, } impl From for ValidateRequest{ @@ -79,7 +78,7 @@ impl From for ValidateRequest{ ModelID:value.ModelID, ModelVersion:value.ModelVersion, ValidatedModelID:value.ValidatedModelID, - ResourceID:ResourceID::Mapfix(value.MapfixID), + Resource:Resource::Mapfix(value.MapfixID), } } } @@ -89,7 +88,7 @@ impl From for ValidateRequest{ ModelID:value.ModelID, ModelVersion:value.ModelVersion, ValidatedModelID:value.ValidatedModelID, - ResourceID:ResourceID::Submission(value.SubmissionID), + Resource:Resource::Submission(value.SubmissionID), } } } @@ -177,10 +176,7 @@ impl crate::message_handler::MessageHandler{ }, }; }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), - }; + let (resource_type,resource_id)=validate_info.Resource.split(); // upload the script let script=self.api.create_script(submissions_api::types::CreateScriptRequest{ @@ -281,8 +277,8 @@ impl crate::message_handler::MessageHandler{ (validate_info.ModelID,validate_info.ModelVersion) }; - match validate_info.ResourceID{ - ResourceID::Mapfix(mapfix_id)=>{ + match validate_info.Resource{ + Resource::Mapfix(mapfix_id)=>{ // update the mapfix to use the validated model self.api.update_mapfix_validated_model(submissions_api::types::UpdateMapfixModelRequest{ MapfixID:mapfix_id, @@ -290,7 +286,7 @@ impl crate::message_handler::MessageHandler{ ModelVersion:validated_model_version, }).await.map_err(Error::ApiUpdateMapfixModel)?; }, - ResourceID::Submission(submission_id)=>{ + Resource::Submission(submission_id)=>{ // update the submission to use the validated model self.api.update_submission_validated_model(submissions_api::types::UpdateSubmissionModelRequest{ SubmissionID:submission_id, -- 2.49.1 From 0834400c05da1faeec1d560d24a7110051b10749 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Thu, 12 Jun 2025 00:19:56 +0000 Subject: [PATCH 3/5] Compartmentalize Monolith (#196) This isn't the full job, notably Operations are still sprinkled about, and having some code sharing between `service` and `service_internal` would be nice, but that is sketchy without the explicitness of Rust's traits. Reviewed-on: https://git.itzana.me/StrafesNET/maps-service/pulls/196 Co-authored-by: Quaternions Co-committed-by: Quaternions --- pkg/model/resource.go | 13 + pkg/model/script.go | 7 - pkg/service/audit_events.go | 222 +++------------ pkg/service/mapfixes.go | 397 ++++++++++++--------------- pkg/service/submissions.go | 397 ++++++++++++--------------- pkg/service_internal/audit_events.go | 71 +++++ pkg/service_internal/mapfixes.go | 180 +++++------- pkg/service_internal/submissions.go | 207 +++++--------- 8 files changed, 624 insertions(+), 870 deletions(-) create mode 100644 pkg/model/resource.go create mode 100644 pkg/service_internal/audit_events.go diff --git a/pkg/model/resource.go b/pkg/model/resource.go new file mode 100644 index 0000000..712f528 --- /dev/null +++ b/pkg/model/resource.go @@ -0,0 +1,13 @@ +package model + +type ResourceType int32 +const ( + ResourceUnknown ResourceType = 0 + ResourceMapfix ResourceType = 1 + ResourceSubmission ResourceType = 2 +) + +type Resource struct{ + ID int64 + Type ResourceType +} diff --git a/pkg/model/script.go b/pkg/model/script.go index 61b011e..f2d7ade 100644 --- a/pkg/model/script.go +++ b/pkg/model/script.go @@ -23,13 +23,6 @@ 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 diff --git a/pkg/service/audit_events.go b/pkg/service/audit_events.go index 8dfaf6e..d8ab5a6 100644 --- a/pkg/service/audit_events.go +++ b/pkg/service/audit_events.go @@ -3,7 +3,6 @@ package service import ( "context" "encoding/json" - "io" "git.itzana.me/strafesnet/go-grpc/users" "git.itzana.me/strafesnet/maps-service/pkg/api" @@ -11,83 +10,13 @@ import ( "git.itzana.me/strafesnet/maps-service/pkg/model" ) -// CreateMapfixAuditComment implements createMapfixAuditComment operation. -// -// Post a comment to the audit log -// -// POST /mapfixes/{MapfixID}/comment -func (svc *Service) CreateMapfixAuditComment(ctx context.Context, req api.CreateMapfixAuditCommentReq, params api.CreateMapfixAuditCommentParams) (error) { - userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle) - if !ok { - return ErrUserInfo - } - - has_role, err := userInfo.HasRoleMapfixReview() - if err != nil { - return err - } - - userId, err := userInfo.GetUserID() - if err != nil { - return err - } - - if !has_role { - // Submitter has special permission to comment on their mapfix - mapfix, err := svc.DB.Mapfixes().Get(ctx, params.MapfixID) - if err != nil { - return err - } - - if mapfix.Submitter != userId { - return ErrPermissionDeniedNeedRoleMapfixReview - } - } - - data, err := io.ReadAll(req) - if err != nil { - return err - } - - event_data := model.AuditEventDataComment{ - Comment: string(data), - } - - EventData, err := json.Marshal(&event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceMapfix, - ResourceID: params.MapfixID, - EventType: model.AuditEventTypeComment, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil -} - -// ListMapfixAuditEvents invokes listMapfixAuditEvents operation. -// -// Retrieve a list of audit events. -// -// GET /mapfixes/{MapfixID}/audit-events -func (svc *Service) ListMapfixAuditEvents(ctx context.Context, params api.ListMapfixAuditEventsParams) ([]api.AuditEvent, error) { +func (svc *Service) ListAuditEvents(ctx context.Context, resource model.Resource, page model.Page) ([]api.AuditEvent, error){ filter := datastore.Optional() - filter.Add("resource_type", model.ResourceMapfix) - filter.Add("resource_id", params.MapfixID) + filter.Add("resource_type", resource.Type) + filter.Add("resource_id", resource.ID) - items, err := svc.DB.AuditEvents().List(ctx, filter, model.Page{ - Number: params.Page, - Size: params.Limit, - }) + items, err := svc.DB.AuditEvents().List(ctx, filter, page) if err != nil { return nil, err } @@ -139,49 +68,8 @@ func (svc *Service) ListMapfixAuditEvents(ctx context.Context, params api.ListMa return resp, nil } -// CreateSubmissionAuditComment implements createSubmissionAuditComment operation. -// -// Post a comment to the audit log -// -// POST /submissions/{SubmissionID}/comment -func (svc *Service) CreateSubmissionAuditComment(ctx context.Context, req api.CreateSubmissionAuditCommentReq, params api.CreateSubmissionAuditCommentParams) (error) { - userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle) - if !ok { - return ErrUserInfo - } - - has_role, err := userInfo.HasRoleSubmissionReview() - if err != nil { - return err - } - - userId, err := userInfo.GetUserID() - if err != nil { - return err - } - - if !has_role { - // Submitter has special permission to comment on their submission - submission, err := svc.DB.Submissions().Get(ctx, params.SubmissionID) - if err != nil { - return err - } - - if submission.Submitter != userId { - return ErrPermissionDeniedNeedRoleSubmissionReview - } - } - - data, err := io.ReadAll(req) - if err != nil { - return err - } - - event_data := model.AuditEventDataComment{ - Comment: string(data), - } - - EventData, err := json.Marshal(&event_data) +func (svc *Service) CreateAuditEventAction(ctx context.Context, userId uint64, resource model.Resource, event_data model.AuditEventDataAction) error { + EventData, err := json.Marshal(event_data) if err != nil { return err } @@ -189,8 +77,29 @@ func (svc *Service) CreateSubmissionAuditComment(ctx context.Context, req api.Cr _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ ID: 0, User: userId, - ResourceType: model.ResourceSubmission, - ResourceID: params.SubmissionID, + ResourceType: resource.Type, + ResourceID: resource.ID, + EventType: model.AuditEventTypeAction, + EventData: EventData, + }) + if err != nil { + return err + } + + return nil +} + +func (svc *Service) CreateAuditEventComment(ctx context.Context, userId uint64, resource model.Resource, event_data model.AuditEventDataComment) error { + EventData, err := json.Marshal(event_data) + if err != nil { + return err + } + + _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ + ID: 0, + User: userId, + ResourceType: resource.Type, + ResourceID: resource.ID, EventType: model.AuditEventTypeComment, EventData: EventData, }) @@ -201,68 +110,23 @@ func (svc *Service) CreateSubmissionAuditComment(ctx context.Context, req api.Cr return nil } -// ListSubmissionAuditEvents invokes listSubmissionAuditEvents operation. -// -// Retrieve a list of audit events. -// -// GET /submissions/{SubmissionID}/audit-events -func (svc *Service) ListSubmissionAuditEvents(ctx context.Context, params api.ListSubmissionAuditEventsParams) ([]api.AuditEvent, error) { - filter := datastore.Optional() +func (svc *Service) CreateAuditEventChangeModel(ctx context.Context, userId uint64, resource model.Resource, event_data model.AuditEventDataChangeModel) error { + EventData, err := json.Marshal(event_data) + if err != nil { + return err + } - filter.Add("resource_type", model.ResourceSubmission) - filter.Add("resource_id", params.SubmissionID) - - items, err := svc.DB.AuditEvents().List(ctx, filter, model.Page{ - Number: params.Page, - Size: params.Limit, + _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ + ID: 0, + User: userId, + ResourceType: resource.Type, + ResourceID: resource.ID, + EventType: model.AuditEventTypeChangeModel, + EventData: EventData, }) if err != nil { - return nil, err + return err } - idMap := make(map[int64]bool) - for _, item := range items { - idMap[int64(item.User)] = true - } - - var idList users.IdList - idList.ID = make([]int64,len(idMap)) - for userId := range idMap { - idList.ID = append(idList.ID, userId) - } - - userList, err := svc.Users.GetList(ctx, &idList) - if err != nil { - return nil, err - } - - userMap := make(map[int64]*users.UserResponse) - for _,user := range userList.Users { - userMap[user.ID] = user - } - - var resp []api.AuditEvent - for _, item := range items { - EventData := api.AuditEventEventData{} - err = EventData.UnmarshalJSON(item.EventData) - if err != nil { - return nil, err - } - username := "" - if userMap[int64(item.User)] != nil { - username = userMap[int64(item.User)].Username - } - resp = append(resp, api.AuditEvent{ - ID: item.ID, - Date: item.CreatedAt.Unix(), - User: int64(item.User), - Username: username, - ResourceType: int32(item.ResourceType), - ResourceID: item.ResourceID, - EventType: int32(item.EventType), - EventData: EventData, - }) - } - - return resp, nil + return nil } diff --git a/pkg/service/mapfixes.go b/pkg/service/mapfixes.go index c43f708..4c40393 100644 --- a/pkg/service/mapfixes.go +++ b/pkg/service/mapfixes.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "fmt" + "io" "time" "git.itzana.me/strafesnet/go-grpc/maps" @@ -298,24 +299,15 @@ func (svc *Service) UpdateMapfixModel(ctx context.Context, params api.UpdateMapf NewModelVersion: NewModelVersion, } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceMapfix, - ResourceID: params.MapfixID, - EventType: model.AuditEventTypeChangeModel, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventChangeModel( + ctx, + userId, + model.Resource{ + ID: params.MapfixID, + Type: model.ResourceMapfix, + }, + event_data, + ) } // ActionMapfixReject invokes actionMapfixReject operation. @@ -356,24 +348,15 @@ func (svc *Service) ActionMapfixReject(ctx context.Context, params api.ActionMap TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceMapfix, - ResourceID: params.MapfixID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + userId, + model.Resource{ + ID: params.MapfixID, + Type: model.ResourceMapfix, + }, + event_data, + ) } // ActionMapfixRequestChanges invokes actionMapfixRequestChanges operation. @@ -414,24 +397,15 @@ func (svc *Service) ActionMapfixRequestChanges(ctx context.Context, params api.A TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceMapfix, - ResourceID: params.MapfixID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + userId, + model.Resource{ + ID: params.MapfixID, + Type: model.ResourceMapfix, + }, + event_data, + ) } // ActionMapfixRevoke invokes actionMapfixRevoke operation. @@ -475,24 +449,15 @@ func (svc *Service) ActionMapfixRevoke(ctx context.Context, params api.ActionMap TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceMapfix, - ResourceID: params.MapfixID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + userId, + model.Resource{ + ID: params.MapfixID, + Type: model.ResourceMapfix, + }, + event_data, + ) } // ActionMapfixTriggerSubmit invokes actionMapfixTriggerSubmit operation. @@ -551,24 +516,15 @@ func (svc *Service) ActionMapfixTriggerSubmit(ctx context.Context, params api.Ac TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceMapfix, - ResourceID: params.MapfixID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + userId, + model.Resource{ + ID: params.MapfixID, + Type: model.ResourceMapfix, + }, + event_data, + ) } // ActionMapfixBypassSubmit invokes actionMapfixBypassSubmit operation. @@ -621,24 +577,15 @@ func (svc *Service) ActionMapfixBypassSubmit(ctx context.Context, params api.Act TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceMapfix, - ResourceID: params.MapfixID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + userId, + model.Resource{ + ID: params.MapfixID, + Type: model.ResourceMapfix, + }, + event_data, + ) } // ActionMapfixResetSubmitting implements actionMapfixResetSubmitting operation. @@ -686,24 +633,15 @@ func (svc *Service) ActionMapfixResetSubmitting(ctx context.Context, params api. TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceMapfix, - ResourceID: params.MapfixID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + userId, + model.Resource{ + ID: params.MapfixID, + Type: model.ResourceMapfix, + }, + event_data, + ) } // ActionMapfixTriggerUpload invokes actionMapfixTriggerUpload operation. @@ -762,24 +700,15 @@ func (svc *Service) ActionMapfixTriggerUpload(ctx context.Context, params api.Ac TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceMapfix, - ResourceID: params.MapfixID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + userId, + model.Resource{ + ID: params.MapfixID, + Type: model.ResourceMapfix, + }, + event_data, + ) } // ActionMapfixValidate invokes actionMapfixValidate operation. @@ -830,24 +759,15 @@ func (svc *Service) ActionMapfixValidated(ctx context.Context, params api.Action TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceMapfix, - ResourceID: params.MapfixID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + userId, + model.Resource{ + ID: params.MapfixID, + Type: model.ResourceMapfix, + }, + event_data, + ) } // ActionMapfixTriggerValidate invokes actionMapfixTriggerValidate operation. @@ -939,24 +859,15 @@ func (svc *Service) ActionMapfixTriggerValidate(ctx context.Context, params api. TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceMapfix, - ResourceID: params.MapfixID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + userId, + model.Resource{ + ID: params.MapfixID, + Type: model.ResourceMapfix, + }, + event_data, + ) } // ActionMapfixRetryValidate invokes actionMapfixRetryValidate operation. @@ -1019,24 +930,15 @@ func (svc *Service) ActionMapfixRetryValidate(ctx context.Context, params api.Ac TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceMapfix, - ResourceID: params.MapfixID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + userId, + model.Resource{ + ID: params.MapfixID, + Type: model.ResourceMapfix, + }, + event_data, + ) } // ActionMapfixAccepted implements actionMapfixAccepted operation. @@ -1087,22 +989,85 @@ func (svc *Service) ActionMapfixAccepted(ctx context.Context, params api.ActionM TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceMapfix, - ResourceID: params.MapfixID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + userId, + model.Resource{ + ID: params.MapfixID, + Type: model.ResourceMapfix, + }, + event_data, + ) +} + +// CreateMapfixAuditComment implements createMapfixAuditComment operation. +// +// Post a comment to the audit log +// +// POST /mapfixes/{MapfixID}/comment +func (svc *Service) CreateMapfixAuditComment(ctx context.Context, req api.CreateMapfixAuditCommentReq, params api.CreateMapfixAuditCommentParams) (error) { + userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle) + if !ok { + return ErrUserInfo + } + + has_role, err := userInfo.HasRoleMapfixReview() + if err != nil { + return err + } + + userId, err := userInfo.GetUserID() + if err != nil { + return err + } + + if !has_role { + // Submitter has special permission to comment on their mapfix + mapfix, err := svc.DB.Mapfixes().Get(ctx, params.MapfixID) + if err != nil { + return err + } + + if mapfix.Submitter != userId { + return ErrPermissionDeniedNeedRoleMapfixReview + } + } + + data, err := io.ReadAll(req) + if err != nil { + return err + } + + event_data := model.AuditEventDataComment{ + Comment: string(data), + } + + return svc.CreateAuditEventComment( + ctx, + userId, + model.Resource{ + ID: params.MapfixID, + Type: model.ResourceMapfix, + }, + event_data, + ) +} + +// ListMapfixAuditEvents invokes listMapfixAuditEvents operation. +// +// Retrieve a list of audit events. +// +// GET /mapfixes/{MapfixID}/audit-events +func (svc *Service) ListMapfixAuditEvents(ctx context.Context, params api.ListMapfixAuditEventsParams) ([]api.AuditEvent, error) { + return svc.ListAuditEvents( + ctx, + model.Resource{ + ID: params.MapfixID, + Type: model.ResourceMapfix, + }, + model.Page{ + Number: params.Page, + Size: params.Limit, + }, + ) } diff --git a/pkg/service/submissions.go b/pkg/service/submissions.go index b2f0538..dc4543e 100644 --- a/pkg/service/submissions.go +++ b/pkg/service/submissions.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "fmt" + "io" "time" "git.itzana.me/strafesnet/go-grpc/maps" @@ -365,24 +366,15 @@ func (svc *Service) UpdateSubmissionModel(ctx context.Context, params api.Update NewModelVersion: NewModelVersion, } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceSubmission, - ResourceID: submission.ID, - EventType: model.AuditEventTypeChangeModel, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventChangeModel( + ctx, + userId, + model.Resource{ + ID: params.SubmissionID, + Type: model.ResourceSubmission, + }, + event_data, + ) } // ActionSubmissionReject invokes actionSubmissionReject operation. @@ -423,24 +415,15 @@ func (svc *Service) ActionSubmissionReject(ctx context.Context, params api.Actio TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceSubmission, - ResourceID: params.SubmissionID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + userId, + model.Resource{ + ID: params.SubmissionID, + Type: model.ResourceSubmission, + }, + event_data, + ) } // ActionSubmissionRequestChanges invokes actionSubmissionRequestChanges operation. @@ -481,24 +464,15 @@ func (svc *Service) ActionSubmissionRequestChanges(ctx context.Context, params a TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceSubmission, - ResourceID: params.SubmissionID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + userId, + model.Resource{ + ID: params.SubmissionID, + Type: model.ResourceSubmission, + }, + event_data, + ) } // ActionSubmissionRevoke invokes actionSubmissionRevoke operation. @@ -542,24 +516,15 @@ func (svc *Service) ActionSubmissionRevoke(ctx context.Context, params api.Actio TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceSubmission, - ResourceID: params.SubmissionID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + userId, + model.Resource{ + ID: params.SubmissionID, + Type: model.ResourceSubmission, + }, + event_data, + ) } // ActionSubmissionTriggerSubmit invokes actionSubmissionTriggerSubmit operation. @@ -626,24 +591,15 @@ func (svc *Service) ActionSubmissionTriggerSubmit(ctx context.Context, params ap TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceSubmission, - ResourceID: params.SubmissionID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + userId, + model.Resource{ + ID: params.SubmissionID, + Type: model.ResourceSubmission, + }, + event_data, + ) } // ActionSubmissionBypassSubmit invokes actionSubmissionBypassSubmit operation. @@ -696,24 +652,15 @@ func (svc *Service) ActionSubmissionBypassSubmit(ctx context.Context, params api TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceSubmission, - ResourceID: params.SubmissionID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + userId, + model.Resource{ + ID: params.SubmissionID, + Type: model.ResourceSubmission, + }, + event_data, + ) } // ActionSubmissionResetSubmitting implements actionSubmissionResetSubmitting operation. @@ -761,24 +708,15 @@ func (svc *Service) ActionSubmissionResetSubmitting(ctx context.Context, params TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceSubmission, - ResourceID: params.SubmissionID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + userId, + model.Resource{ + ID: params.SubmissionID, + Type: model.ResourceSubmission, + }, + event_data, + ) } // ActionSubmissionTriggerUpload invokes actionSubmissionTriggerUpload operation. @@ -844,24 +782,15 @@ func (svc *Service) ActionSubmissionTriggerUpload(ctx context.Context, params ap TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceSubmission, - ResourceID: params.SubmissionID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + userId, + model.Resource{ + ID: params.SubmissionID, + Type: model.ResourceSubmission, + }, + event_data, + ) } // ActionSubmissionValidate invokes actionSubmissionValidate operation. @@ -912,24 +841,15 @@ func (svc *Service) ActionSubmissionValidated(ctx context.Context, params api.Ac TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceSubmission, - ResourceID: params.SubmissionID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + userId, + model.Resource{ + ID: params.SubmissionID, + Type: model.ResourceSubmission, + }, + event_data, + ) } // ActionSubmissionTriggerValidate invokes actionSubmissionTriggerValidate operation. @@ -1004,24 +924,15 @@ func (svc *Service) ActionSubmissionTriggerValidate(ctx context.Context, params TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceSubmission, - ResourceID: params.SubmissionID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + userId, + model.Resource{ + ID: params.SubmissionID, + Type: model.ResourceSubmission, + }, + event_data, + ) } // ActionSubmissionRetryValidate invokes actionSubmissionRetryValidate operation. @@ -1084,24 +995,15 @@ func (svc *Service) ActionSubmissionRetryValidate(ctx context.Context, params ap TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceSubmission, - ResourceID: params.SubmissionID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + userId, + model.Resource{ + ID: params.SubmissionID, + Type: model.ResourceSubmission, + }, + event_data, + ) } // ActionSubmissionAccepted implements actionSubmissionAccepted operation. @@ -1152,24 +1054,15 @@ func (svc *Service) ActionSubmissionAccepted(ctx context.Context, params api.Act TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: userId, - ResourceType: model.ResourceSubmission, - ResourceID: params.SubmissionID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + userId, + model.Resource{ + ID: params.SubmissionID, + Type: model.ResourceSubmission, + }, + event_data, + ) } // ReleaseSubmissions invokes releaseSubmissions operation. @@ -1239,3 +1132,75 @@ func (svc *Service) ReleaseSubmissions(ctx context.Context, request []api.Releas return nil } + +// CreateSubmissionAuditComment implements createSubmissionAuditComment operation. +// +// Post a comment to the audit log +// +// POST /submissions/{SubmissionID}/comment +func (svc *Service) CreateSubmissionAuditComment(ctx context.Context, req api.CreateSubmissionAuditCommentReq, params api.CreateSubmissionAuditCommentParams) (error) { + userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle) + if !ok { + return ErrUserInfo + } + + has_role, err := userInfo.HasRoleSubmissionReview() + if err != nil { + return err + } + + userId, err := userInfo.GetUserID() + if err != nil { + return err + } + + if !has_role { + // Submitter has special permission to comment on their submission + submission, err := svc.DB.Submissions().Get(ctx, params.SubmissionID) + if err != nil { + return err + } + + if submission.Submitter != userId { + return ErrPermissionDeniedNeedRoleSubmissionReview + } + } + + data, err := io.ReadAll(req) + if err != nil { + return err + } + + event_data := model.AuditEventDataComment{ + Comment: string(data), + } + + return svc.CreateAuditEventComment( + ctx, + userId, + model.Resource{ + ID: params.SubmissionID, + Type: model.ResourceSubmission, + }, + event_data, + ) +} + +// ListSubmissionAuditEvents invokes listSubmissionAuditEvents operation. +// +// Retrieve a list of audit events. +// +// GET /submissions/{SubmissionID}/audit-events +func (svc *Service) ListSubmissionAuditEvents(ctx context.Context, params api.ListSubmissionAuditEventsParams) ([]api.AuditEvent, error) { + return svc.ListAuditEvents( + ctx, + model.Resource{ + ID: params.SubmissionID, + Type: model.ResourceSubmission, + }, + model.Page{ + Number: params.Page, + Size: params.Limit, + }, + ) +} diff --git a/pkg/service_internal/audit_events.go b/pkg/service_internal/audit_events.go new file mode 100644 index 0000000..82e6dd6 --- /dev/null +++ b/pkg/service_internal/audit_events.go @@ -0,0 +1,71 @@ +package service_internal + +import ( + "context" + "encoding/json" + + "git.itzana.me/strafesnet/maps-service/pkg/model" +) + +func (svc *Service) CreateAuditEventAction(ctx context.Context, userId uint64, resource model.Resource, event_data model.AuditEventDataAction) error { + EventData, err := json.Marshal(event_data) + if err != nil { + return err + } + + _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ + ID: 0, + User: userId, + ResourceType: resource.Type, + ResourceID: resource.ID, + EventType: model.AuditEventTypeAction, + EventData: EventData, + }) + if err != nil { + return err + } + + return nil +} + +func (svc *Service) CreateAuditEventChangeValidatedModel(ctx context.Context, userId uint64, resource model.Resource, event_data model.AuditEventDataChangeValidatedModel) error { + EventData, err := json.Marshal(event_data) + if err != nil { + return err + } + + _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ + ID: 0, + User: userId, + ResourceType: resource.Type, + ResourceID: resource.ID, + EventType: model.AuditEventTypeChangeValidatedModel, + EventData: EventData, + }) + if err != nil { + return err + } + + return nil +} + +func (svc *Service) CreateAuditEventError(ctx context.Context, userId uint64, resource model.Resource, event_data model.AuditEventDataError) error { + EventData, err := json.Marshal(event_data) + if err != nil { + return err + } + + _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ + ID: 0, + User: userId, + ResourceType: resource.Type, + ResourceID: resource.ID, + EventType: model.AuditEventTypeError, + EventData: EventData, + }) + if err != nil { + return err + } + + return nil +} diff --git a/pkg/service_internal/mapfixes.go b/pkg/service_internal/mapfixes.go index e6a4e74..3a86ae9 100644 --- a/pkg/service_internal/mapfixes.go +++ b/pkg/service_internal/mapfixes.go @@ -2,7 +2,6 @@ package service_internal import ( "context" - "encoding/json" "errors" "fmt" @@ -54,24 +53,15 @@ func (svc *Service) UpdateMapfixValidatedModel(ctx context.Context, params inter ValidatedModelVersion: ValidatedModelVersion, } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: ValidtorUserID, - ResourceType: model.ResourceMapfix, - ResourceID: params.MapfixID, - EventType: model.AuditEventTypeChangeValidatedModel, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventChangeValidatedModel( + ctx, + ValidtorUserID, + model.Resource{ + ID: params.MapfixID, + Type: model.ResourceMapfix, + }, + event_data, + ) } // ActionMapfixSubmitted invokes actionMapfixSubmitted operation. @@ -97,24 +87,15 @@ func (svc *Service) ActionMapfixSubmitted(ctx context.Context, params internal.A TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: ValidtorUserID, - ResourceType: model.ResourceMapfix, - ResourceID: params.MapfixID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + ValidtorUserID, + model.Resource{ + ID: params.MapfixID, + Type: model.ResourceMapfix, + }, + event_data, + ) } // ActionMapfixRequestChanges implements actionMapfixRequestChanges operation. @@ -137,19 +118,15 @@ func (svc *Service) ActionMapfixRequestChanges(ctx context.Context, params inter Error: params.ErrorMessage, } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: ValidtorUserID, - ResourceType: model.ResourceMapfix, - ResourceID: params.MapfixID, - EventType: model.AuditEventTypeError, - EventData: EventData, - }) + err = svc.CreateAuditEventError( + ctx, + ValidtorUserID, + model.Resource{ + ID: params.MapfixID, + Type: model.ResourceMapfix, + }, + event_data, + ) if err != nil { return err } @@ -159,24 +136,15 @@ func (svc *Service) ActionMapfixRequestChanges(ctx context.Context, params inter TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: ValidtorUserID, - ResourceType: model.ResourceMapfix, - ResourceID: params.MapfixID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + ValidtorUserID, + model.Resource{ + ID: params.MapfixID, + Type: model.ResourceMapfix, + }, + event_data, + ) } // ActionMapfixValidate invokes actionMapfixValidate operation. @@ -212,19 +180,15 @@ func (svc *Service) ActionMapfixAccepted(ctx context.Context, params internal.Ac Error: params.ErrorMessage, } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: ValidtorUserID, - ResourceType: model.ResourceMapfix, - ResourceID: params.MapfixID, - EventType: model.AuditEventTypeError, - EventData: EventData, - }) + err = svc.CreateAuditEventError( + ctx, + ValidtorUserID, + model.Resource{ + ID: params.MapfixID, + Type: model.ResourceMapfix, + }, + event_data, + ) if err != nil { return err } @@ -235,24 +199,15 @@ func (svc *Service) ActionMapfixAccepted(ctx context.Context, params internal.Ac TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: ValidtorUserID, - ResourceType: model.ResourceMapfix, - ResourceID: params.MapfixID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + ValidtorUserID, + model.Resource{ + ID: params.MapfixID, + Type: model.ResourceMapfix, + }, + event_data, + ) } // ActionMapfixUploaded implements actionMapfixUploaded operation. @@ -274,24 +229,15 @@ func (svc *Service) ActionMapfixUploaded(ctx context.Context, params internal.Ac TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: ValidtorUserID, - ResourceType: model.ResourceMapfix, - ResourceID: params.MapfixID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + ValidtorUserID, + model.Resource{ + ID: params.MapfixID, + Type: model.ResourceMapfix, + }, + event_data, + ) } // POST /mapfixes diff --git a/pkg/service_internal/submissions.go b/pkg/service_internal/submissions.go index 1ce1e4c..23d7415 100644 --- a/pkg/service_internal/submissions.go +++ b/pkg/service_internal/submissions.go @@ -2,7 +2,6 @@ package service_internal import ( "context" - "encoding/json" "errors" "fmt" @@ -54,24 +53,15 @@ func (svc *Service) UpdateSubmissionValidatedModel(ctx context.Context, params i ValidatedModelVersion: ValidatedModelVersion, } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: ValidtorUserID, - ResourceType: model.ResourceSubmission, - ResourceID: params.SubmissionID, - EventType: model.AuditEventTypeChangeValidatedModel, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventChangeValidatedModel( + ctx, + ValidtorUserID, + model.Resource{ + ID: params.SubmissionID, + Type: model.ResourceSubmission, + }, + event_data, + ) } // ActionSubmissionSubmitted invokes actionSubmissionSubmitted operation. @@ -97,24 +87,15 @@ func (svc *Service) ActionSubmissionSubmitted(ctx context.Context, params intern TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: ValidtorUserID, - ResourceType: model.ResourceSubmission, - ResourceID: params.SubmissionID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + ValidtorUserID, + model.Resource{ + ID: params.SubmissionID, + Type: model.ResourceSubmission, + }, + event_data, + ) } // ActionSubmissionRequestChanges implements actionSubmissionRequestChanges operation. @@ -138,19 +119,15 @@ func (svc *Service) ActionSubmissionRequestChanges(ctx context.Context, params i Error: params.ErrorMessage, } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: ValidtorUserID, - ResourceType: model.ResourceSubmission, - ResourceID: params.SubmissionID, - EventType: model.AuditEventTypeError, - EventData: EventData, - }) + err = svc.CreateAuditEventError( + ctx, + ValidtorUserID, + model.Resource{ + ID: params.SubmissionID, + Type: model.ResourceSubmission, + }, + event_data, + ) if err != nil { return err } @@ -161,24 +138,15 @@ func (svc *Service) ActionSubmissionRequestChanges(ctx context.Context, params i TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: ValidtorUserID, - ResourceType: model.ResourceSubmission, - ResourceID: params.SubmissionID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + ValidtorUserID, + model.Resource{ + ID: params.SubmissionID, + Type: model.ResourceSubmission, + }, + event_data, + ) } // ActionSubmissionValidate invokes actionSubmissionValidate operation. @@ -200,24 +168,15 @@ func (svc *Service) ActionSubmissionValidated(ctx context.Context, params intern TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: ValidtorUserID, - ResourceType: model.ResourceSubmission, - ResourceID: params.SubmissionID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + ValidtorUserID, + model.Resource{ + ID: params.SubmissionID, + Type: model.ResourceSubmission, + }, + event_data, + ) } // ActionSubmissionAccepted implements actionSubmissionAccepted operation. @@ -242,19 +201,15 @@ func (svc *Service) ActionSubmissionAccepted(ctx context.Context, params interna Error: params.ErrorMessage, } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: ValidtorUserID, - ResourceType: model.ResourceSubmission, - ResourceID: params.SubmissionID, - EventType: model.AuditEventTypeError, - EventData: EventData, - }) + err = svc.CreateAuditEventError( + ctx, + ValidtorUserID, + model.Resource{ + ID: params.SubmissionID, + Type: model.ResourceSubmission, + }, + event_data, + ) if err != nil { return err } @@ -265,24 +220,15 @@ func (svc *Service) ActionSubmissionAccepted(ctx context.Context, params interna TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: ValidtorUserID, - ResourceType: model.ResourceSubmission, - ResourceID: params.SubmissionID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + ValidtorUserID, + model.Resource{ + ID: params.SubmissionID, + Type: model.ResourceSubmission, + }, + event_data, + ) } // ActionSubmissionUploaded implements actionSubmissionUploaded operation. @@ -305,24 +251,15 @@ func (svc *Service) ActionSubmissionUploaded(ctx context.Context, params interna TargetStatus: uint32(target_status), } - EventData, err := json.Marshal(event_data) - if err != nil { - return err - } - - _, err = svc.DB.AuditEvents().Create(ctx, model.AuditEvent{ - ID: 0, - User: ValidtorUserID, - ResourceType: model.ResourceSubmission, - ResourceID: params.SubmissionID, - EventType: model.AuditEventTypeAction, - EventData: EventData, - }) - if err != nil { - return err - } - - return nil + return svc.CreateAuditEventAction( + ctx, + ValidtorUserID, + model.Resource{ + ID: params.SubmissionID, + Type: model.ResourceSubmission, + }, + event_data, + ) } // POST /submissions -- 2.49.1 From c4d97b6537a00cfb1ac8e5f6d13b7453a321266e Mon Sep 17 00:00:00 2001 From: Quaternions Date: Thu, 12 Jun 2025 00:55:09 +0000 Subject: [PATCH 4/5] Change Error to Explicit Endpoint (#197) This changes the way that the internal api works. The backend used to implicitly create an error for specifc endpoints, but now the validator explicitly creates the error itself. Reviewed-on: https://git.itzana.me/StrafesNET/maps-service/pulls/197 Co-authored-by: Quaternions Co-committed-by: Quaternions --- openapi-internal.yaml | 76 +-- pkg/internal/oas_client_gen.go | 302 +++++++++--- pkg/internal/oas_handlers_gen.go | 322 ++++++++++++- pkg/internal/oas_operations_gen.go | 2 + pkg/internal/oas_parameters_gen.go | 536 ++++++++++++---------- pkg/internal/oas_response_decoders_gen.go | 120 +++++ pkg/internal/oas_response_encoders_gen.go | 14 + pkg/internal/oas_router_gen.go | 92 ++++ pkg/internal/oas_schemas_gen.go | 6 + pkg/internal/oas_server_gen.go | 12 + pkg/internal/oas_unimplemented_gen.go | 18 + pkg/service_internal/mapfixes.go | 60 +-- pkg/service_internal/submissions.go | 62 +-- validation/api/src/internal.rs | 18 +- validation/api/src/types.rs | 14 +- validation/src/check_mapfix.rs | 37 +- validation/src/check_submission.rs | 37 +- validation/src/validate_mapfix.rs | 8 +- validation/src/validate_submission.rs | 8 +- 19 files changed, 1262 insertions(+), 482 deletions(-) diff --git a/openapi-internal.yaml b/openapi-internal.yaml index 29a4d12..8166333 100644 --- a/openapi-internal.yaml +++ b/openapi-internal.yaml @@ -65,6 +65,30 @@ paths: application/json: schema: $ref: "#/components/schemas/Error" + /mapfixes/{MapfixID}/error: + post: + summary: Validator posts an error to the audit log + operationId: createMapfixAuditError + tags: + - Mapfixes + parameters: + - $ref: '#/components/parameters/MapfixID' + - name: ErrorMessage + in: query + required: true + schema: + type: string + minLength: 0 + maxLength: 4096 + responses: + "204": + description: Successful response + default: + description: General Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" /mapfixes/{MapfixID}/status/validator-submitted: post: summary: (Internal endpoint) Role Validator changes status from Submitting -> Submitted @@ -116,13 +140,6 @@ paths: - Mapfixes parameters: - $ref: '#/components/parameters/MapfixID' - - name: ErrorMessage - in: query - required: true - schema: - type: string - minLength: 0 - maxLength: 4096 responses: "204": description: Successful response @@ -157,13 +174,6 @@ paths: - Mapfixes parameters: - $ref: '#/components/parameters/MapfixID' - - name: ErrorMessage - in: query - required: true - schema: - type: string - minLength: 0 - maxLength: 4096 responses: "204": description: Successful response @@ -270,6 +280,30 @@ paths: application/json: schema: $ref: "#/components/schemas/Error" + /submissions/{SubmissionID}/error: + post: + summary: Validator posts an error to the audit log + operationId: createSubmissionAuditError + tags: + - Submissions + parameters: + - $ref: '#/components/parameters/SubmissionID' + - name: ErrorMessage + in: query + required: true + schema: + type: string + minLength: 0 + maxLength: 4096 + responses: + "204": + description: Successful response + default: + description: General Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" /submissions/{SubmissionID}/status/validator-submitted: post: summary: (Internal endpoint) Role Validator changes status from Submitting -> Submitted @@ -321,13 +355,6 @@ paths: - Submissions parameters: - $ref: '#/components/parameters/SubmissionID' - - name: ErrorMessage - in: query - required: true - schema: - type: string - minLength: 0 - maxLength: 4096 responses: "204": description: Successful response @@ -362,13 +389,6 @@ paths: - Submissions parameters: - $ref: '#/components/parameters/SubmissionID' - - name: ErrorMessage - in: query - required: true - schema: - type: string - minLength: 0 - maxLength: 4096 responses: "204": description: Successful response diff --git a/pkg/internal/oas_client_gen.go b/pkg/internal/oas_client_gen.go index f7e2439..927f983 100644 --- a/pkg/internal/oas_client_gen.go +++ b/pkg/internal/oas_client_gen.go @@ -100,6 +100,12 @@ type Invoker interface { // // POST /mapfixes CreateMapfix(ctx context.Context, request *MapfixCreate) (*MapfixID, error) + // CreateMapfixAuditError invokes createMapfixAuditError operation. + // + // Validator posts an error to the audit log. + // + // POST /mapfixes/{MapfixID}/error + CreateMapfixAuditError(ctx context.Context, params CreateMapfixAuditErrorParams) error // CreateScript invokes createScript operation. // // Create a new script. @@ -118,6 +124,12 @@ type Invoker interface { // // POST /submissions CreateSubmission(ctx context.Context, request *SubmissionCreate) (*SubmissionID, error) + // CreateSubmissionAuditError invokes createSubmissionAuditError operation. + // + // Validator posts an error to the audit log. + // + // POST /submissions/{SubmissionID}/error + CreateSubmissionAuditError(ctx context.Context, params CreateSubmissionAuditErrorParams) error // GetScript invokes getScript operation. // // Get the specified script by ID. @@ -266,24 +278,6 @@ func (c *Client) sendActionMapfixAccepted(ctx context.Context, params ActionMapf pathParts[2] = "/status/validator-failed" uri.AddPathParts(u, pathParts[:]...) - stage = "EncodeQueryParams" - q := uri.NewQueryEncoder() - { - // Encode "ErrorMessage" parameter. - cfg := uri.QueryParameterEncodingConfig{ - Name: "ErrorMessage", - Style: uri.QueryStyleForm, - Explode: true, - } - - if err := q.EncodeParam(cfg, func(e uri.Encoder) error { - return e.EncodeValue(conv.StringToString(params.ErrorMessage)) - }); err != nil { - return res, errors.Wrap(err, "encode query") - } - } - u.RawQuery = q.Values().Encode() - stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "POST", u) if err != nil { @@ -375,24 +369,6 @@ func (c *Client) sendActionMapfixRequestChanges(ctx context.Context, params Acti pathParts[2] = "/status/validator-request-changes" uri.AddPathParts(u, pathParts[:]...) - stage = "EncodeQueryParams" - q := uri.NewQueryEncoder() - { - // Encode "ErrorMessage" parameter. - cfg := uri.QueryParameterEncodingConfig{ - Name: "ErrorMessage", - Style: uri.QueryStyleForm, - Explode: true, - } - - if err := q.EncodeParam(cfg, func(e uri.Encoder) error { - return e.EncodeValue(conv.StringToString(params.ErrorMessage)) - }); err != nil { - return res, errors.Wrap(err, "encode query") - } - } - u.RawQuery = q.Values().Encode() - stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "POST", u) if err != nil { @@ -926,24 +902,6 @@ func (c *Client) sendActionSubmissionAccepted(ctx context.Context, params Action pathParts[2] = "/status/validator-failed" uri.AddPathParts(u, pathParts[:]...) - stage = "EncodeQueryParams" - q := uri.NewQueryEncoder() - { - // Encode "ErrorMessage" parameter. - cfg := uri.QueryParameterEncodingConfig{ - Name: "ErrorMessage", - Style: uri.QueryStyleForm, - Explode: true, - } - - if err := q.EncodeParam(cfg, func(e uri.Encoder) error { - return e.EncodeValue(conv.StringToString(params.ErrorMessage)) - }); err != nil { - return res, errors.Wrap(err, "encode query") - } - } - u.RawQuery = q.Values().Encode() - stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "POST", u) if err != nil { @@ -1035,24 +993,6 @@ func (c *Client) sendActionSubmissionRequestChanges(ctx context.Context, params pathParts[2] = "/status/validator-request-changes" uri.AddPathParts(u, pathParts[:]...) - stage = "EncodeQueryParams" - q := uri.NewQueryEncoder() - { - // Encode "ErrorMessage" parameter. - cfg := uri.QueryParameterEncodingConfig{ - Name: "ErrorMessage", - Style: uri.QueryStyleForm, - Explode: true, - } - - if err := q.EncodeParam(cfg, func(e uri.Encoder) error { - return e.EncodeValue(conv.StringToString(params.ErrorMessage)) - }); err != nil { - return res, errors.Wrap(err, "encode query") - } - } - u.RawQuery = q.Values().Encode() - stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "POST", u) if err != nil { @@ -1501,6 +1441,115 @@ func (c *Client) sendCreateMapfix(ctx context.Context, request *MapfixCreate) (r return result, nil } +// CreateMapfixAuditError invokes createMapfixAuditError operation. +// +// Validator posts an error to the audit log. +// +// POST /mapfixes/{MapfixID}/error +func (c *Client) CreateMapfixAuditError(ctx context.Context, params CreateMapfixAuditErrorParams) error { + _, err := c.sendCreateMapfixAuditError(ctx, params) + return err +} + +func (c *Client) sendCreateMapfixAuditError(ctx context.Context, params CreateMapfixAuditErrorParams) (res *CreateMapfixAuditErrorNoContent, err error) { + otelAttrs := []attribute.KeyValue{ + otelogen.OperationID("createMapfixAuditError"), + semconv.HTTPRequestMethodKey.String("POST"), + semconv.HTTPRouteKey.String("/mapfixes/{MapfixID}/error"), + } + + // Run stopwatch. + startTime := time.Now() + defer func() { + // Use floating point division here for higher precision (instead of Millisecond method). + elapsedDuration := time.Since(startTime) + c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) + }() + + // Increment request counter. + c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) + + // Start a span for this request. + ctx, span := c.cfg.Tracer.Start(ctx, CreateMapfixAuditErrorOperation, + trace.WithAttributes(otelAttrs...), + clientSpanKind, + ) + // Track stage for error reporting. + var stage string + defer func() { + if err != nil { + span.RecordError(err) + span.SetStatus(codes.Error, stage) + c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) + } + span.End() + }() + + stage = "BuildURL" + u := uri.Clone(c.requestURL(ctx)) + var pathParts [3]string + pathParts[0] = "/mapfixes/" + { + // Encode "MapfixID" parameter. + e := uri.NewPathEncoder(uri.PathEncoderConfig{ + Param: "MapfixID", + Style: uri.PathStyleSimple, + Explode: false, + }) + if err := func() error { + return e.EncodeValue(conv.Int64ToString(params.MapfixID)) + }(); err != nil { + return res, errors.Wrap(err, "encode path") + } + encoded, err := e.Result() + if err != nil { + return res, errors.Wrap(err, "encode path") + } + pathParts[1] = encoded + } + pathParts[2] = "/error" + uri.AddPathParts(u, pathParts[:]...) + + stage = "EncodeQueryParams" + q := uri.NewQueryEncoder() + { + // Encode "ErrorMessage" parameter. + cfg := uri.QueryParameterEncodingConfig{ + Name: "ErrorMessage", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.EncodeParam(cfg, func(e uri.Encoder) error { + return e.EncodeValue(conv.StringToString(params.ErrorMessage)) + }); err != nil { + return res, errors.Wrap(err, "encode query") + } + } + u.RawQuery = q.Values().Encode() + + stage = "EncodeRequest" + r, err := ht.NewRequest(ctx, "POST", u) + if err != nil { + return res, errors.Wrap(err, "create request") + } + + stage = "SendRequest" + resp, err := c.cfg.Client.Do(r) + if err != nil { + return res, errors.Wrap(err, "do request") + } + defer resp.Body.Close() + + stage = "DecodeResponse" + result, err := decodeCreateMapfixAuditErrorResponse(resp) + if err != nil { + return res, errors.Wrap(err, "decode response") + } + + return result, nil +} + // CreateScript invokes createScript operation. // // Create a new script. @@ -1726,6 +1775,115 @@ func (c *Client) sendCreateSubmission(ctx context.Context, request *SubmissionCr return result, nil } +// CreateSubmissionAuditError invokes createSubmissionAuditError operation. +// +// Validator posts an error to the audit log. +// +// POST /submissions/{SubmissionID}/error +func (c *Client) CreateSubmissionAuditError(ctx context.Context, params CreateSubmissionAuditErrorParams) error { + _, err := c.sendCreateSubmissionAuditError(ctx, params) + return err +} + +func (c *Client) sendCreateSubmissionAuditError(ctx context.Context, params CreateSubmissionAuditErrorParams) (res *CreateSubmissionAuditErrorNoContent, err error) { + otelAttrs := []attribute.KeyValue{ + otelogen.OperationID("createSubmissionAuditError"), + semconv.HTTPRequestMethodKey.String("POST"), + semconv.HTTPRouteKey.String("/submissions/{SubmissionID}/error"), + } + + // Run stopwatch. + startTime := time.Now() + defer func() { + // Use floating point division here for higher precision (instead of Millisecond method). + elapsedDuration := time.Since(startTime) + c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) + }() + + // Increment request counter. + c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) + + // Start a span for this request. + ctx, span := c.cfg.Tracer.Start(ctx, CreateSubmissionAuditErrorOperation, + trace.WithAttributes(otelAttrs...), + clientSpanKind, + ) + // Track stage for error reporting. + var stage string + defer func() { + if err != nil { + span.RecordError(err) + span.SetStatus(codes.Error, stage) + c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) + } + span.End() + }() + + stage = "BuildURL" + u := uri.Clone(c.requestURL(ctx)) + var pathParts [3]string + pathParts[0] = "/submissions/" + { + // Encode "SubmissionID" parameter. + e := uri.NewPathEncoder(uri.PathEncoderConfig{ + Param: "SubmissionID", + Style: uri.PathStyleSimple, + Explode: false, + }) + if err := func() error { + return e.EncodeValue(conv.Int64ToString(params.SubmissionID)) + }(); err != nil { + return res, errors.Wrap(err, "encode path") + } + encoded, err := e.Result() + if err != nil { + return res, errors.Wrap(err, "encode path") + } + pathParts[1] = encoded + } + pathParts[2] = "/error" + uri.AddPathParts(u, pathParts[:]...) + + stage = "EncodeQueryParams" + q := uri.NewQueryEncoder() + { + // Encode "ErrorMessage" parameter. + cfg := uri.QueryParameterEncodingConfig{ + Name: "ErrorMessage", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.EncodeParam(cfg, func(e uri.Encoder) error { + return e.EncodeValue(conv.StringToString(params.ErrorMessage)) + }); err != nil { + return res, errors.Wrap(err, "encode query") + } + } + u.RawQuery = q.Values().Encode() + + stage = "EncodeRequest" + r, err := ht.NewRequest(ctx, "POST", u) + if err != nil { + return res, errors.Wrap(err, "create request") + } + + stage = "SendRequest" + resp, err := c.cfg.Client.Do(r) + if err != nil { + return res, errors.Wrap(err, "do request") + } + defer resp.Body.Close() + + stage = "DecodeResponse" + result, err := decodeCreateSubmissionAuditErrorResponse(resp) + if err != nil { + return res, errors.Wrap(err, "decode response") + } + + return result, nil +} + // GetScript invokes getScript operation. // // Get the specified script by ID. diff --git a/pkg/internal/oas_handlers_gen.go b/pkg/internal/oas_handlers_gen.go index 638edd6..a7c67c7 100644 --- a/pkg/internal/oas_handlers_gen.go +++ b/pkg/internal/oas_handlers_gen.go @@ -128,10 +128,6 @@ func (s *Server) handleActionMapfixAcceptedRequest(args [1]string, argsEscaped b Name: "MapfixID", In: "path", }: params.MapfixID, - { - Name: "ErrorMessage", - In: "query", - }: params.ErrorMessage, }, Raw: r, } @@ -281,10 +277,6 @@ func (s *Server) handleActionMapfixRequestChangesRequest(args [1]string, argsEsc Name: "MapfixID", In: "path", }: params.MapfixID, - { - Name: "ErrorMessage", - In: "query", - }: params.ErrorMessage, }, Raw: r, } @@ -1050,10 +1042,6 @@ func (s *Server) handleActionSubmissionAcceptedRequest(args [1]string, argsEscap Name: "SubmissionID", In: "path", }: params.SubmissionID, - { - Name: "ErrorMessage", - In: "query", - }: params.ErrorMessage, }, Raw: r, } @@ -1203,10 +1191,6 @@ func (s *Server) handleActionSubmissionRequestChangesRequest(args [1]string, arg Name: "SubmissionID", In: "path", }: params.SubmissionID, - { - Name: "ErrorMessage", - In: "query", - }: params.ErrorMessage, }, Raw: r, } @@ -1874,6 +1858,159 @@ func (s *Server) handleCreateMapfixRequest(args [0]string, argsEscaped bool, w h } } +// handleCreateMapfixAuditErrorRequest handles createMapfixAuditError operation. +// +// Validator posts an error to the audit log. +// +// POST /mapfixes/{MapfixID}/error +func (s *Server) handleCreateMapfixAuditErrorRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) { + statusWriter := &codeRecorder{ResponseWriter: w} + w = statusWriter + otelAttrs := []attribute.KeyValue{ + otelogen.OperationID("createMapfixAuditError"), + semconv.HTTPRequestMethodKey.String("POST"), + semconv.HTTPRouteKey.String("/mapfixes/{MapfixID}/error"), + } + + // Start a span for this request. + ctx, span := s.cfg.Tracer.Start(r.Context(), CreateMapfixAuditErrorOperation, + trace.WithAttributes(otelAttrs...), + serverSpanKind, + ) + defer span.End() + + // Add Labeler to context. + labeler := &Labeler{attrs: otelAttrs} + ctx = contextWithLabeler(ctx, labeler) + + // Run stopwatch. + startTime := time.Now() + defer func() { + elapsedDuration := time.Since(startTime) + + attrSet := labeler.AttributeSet() + attrs := attrSet.ToSlice() + code := statusWriter.status + if code != 0 { + codeAttr := semconv.HTTPResponseStatusCode(code) + attrs = append(attrs, codeAttr) + span.SetAttributes(codeAttr) + } + attrOpt := metric.WithAttributes(attrs...) + + // Increment request counter. + s.requests.Add(ctx, 1, attrOpt) + + // Use floating point division here for higher precision (instead of Millisecond method). + s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt) + }() + + var ( + recordError = func(stage string, err error) { + span.RecordError(err) + + // https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status + // Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges, + // unless there was another error (e.g., network error receiving the response body; or 3xx codes with + // max redirects exceeded), in which case status MUST be set to Error. + code := statusWriter.status + if code >= 100 && code < 500 { + span.SetStatus(codes.Error, stage) + } + + attrSet := labeler.AttributeSet() + attrs := attrSet.ToSlice() + if code != 0 { + attrs = append(attrs, semconv.HTTPResponseStatusCode(code)) + } + + s.errors.Add(ctx, 1, metric.WithAttributes(attrs...)) + } + err error + opErrContext = ogenerrors.OperationContext{ + Name: CreateMapfixAuditErrorOperation, + ID: "createMapfixAuditError", + } + ) + params, err := decodeCreateMapfixAuditErrorParams(args, argsEscaped, r) + if err != nil { + err = &ogenerrors.DecodeParamsError{ + OperationContext: opErrContext, + Err: err, + } + defer recordError("DecodeParams", err) + s.cfg.ErrorHandler(ctx, w, r, err) + return + } + + var response *CreateMapfixAuditErrorNoContent + if m := s.cfg.Middleware; m != nil { + mreq := middleware.Request{ + Context: ctx, + OperationName: CreateMapfixAuditErrorOperation, + OperationSummary: "Validator posts an error to the audit log", + OperationID: "createMapfixAuditError", + Body: nil, + Params: middleware.Parameters{ + { + Name: "MapfixID", + In: "path", + }: params.MapfixID, + { + Name: "ErrorMessage", + In: "query", + }: params.ErrorMessage, + }, + Raw: r, + } + + type ( + Request = struct{} + Params = CreateMapfixAuditErrorParams + Response = *CreateMapfixAuditErrorNoContent + ) + response, err = middleware.HookMiddleware[ + Request, + Params, + Response, + ]( + m, + mreq, + unpackCreateMapfixAuditErrorParams, + func(ctx context.Context, request Request, params Params) (response Response, err error) { + err = s.h.CreateMapfixAuditError(ctx, params) + return response, err + }, + ) + } else { + err = s.h.CreateMapfixAuditError(ctx, params) + } + if err != nil { + if errRes, ok := errors.Into[*ErrorStatusCode](err); ok { + if err := encodeErrorResponse(errRes, w, span); err != nil { + defer recordError("Internal", err) + } + return + } + if errors.Is(err, ht.ErrNotImplemented) { + s.cfg.ErrorHandler(ctx, w, r, err) + return + } + if err := encodeErrorResponse(s.h.NewError(ctx, err), w, span); err != nil { + defer recordError("Internal", err) + } + return + } + + if err := encodeCreateMapfixAuditErrorResponse(response, w, span); err != nil { + defer recordError("EncodeResponse", err) + if !errors.Is(err, ht.ErrInternalServerErrorResponse) { + s.cfg.ErrorHandler(ctx, w, r, err) + } + return + } +} + // handleCreateScriptRequest handles createScript operation. // // Create a new script. @@ -2321,6 +2458,159 @@ func (s *Server) handleCreateSubmissionRequest(args [0]string, argsEscaped bool, } } +// handleCreateSubmissionAuditErrorRequest handles createSubmissionAuditError operation. +// +// Validator posts an error to the audit log. +// +// POST /submissions/{SubmissionID}/error +func (s *Server) handleCreateSubmissionAuditErrorRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) { + statusWriter := &codeRecorder{ResponseWriter: w} + w = statusWriter + otelAttrs := []attribute.KeyValue{ + otelogen.OperationID("createSubmissionAuditError"), + semconv.HTTPRequestMethodKey.String("POST"), + semconv.HTTPRouteKey.String("/submissions/{SubmissionID}/error"), + } + + // Start a span for this request. + ctx, span := s.cfg.Tracer.Start(r.Context(), CreateSubmissionAuditErrorOperation, + trace.WithAttributes(otelAttrs...), + serverSpanKind, + ) + defer span.End() + + // Add Labeler to context. + labeler := &Labeler{attrs: otelAttrs} + ctx = contextWithLabeler(ctx, labeler) + + // Run stopwatch. + startTime := time.Now() + defer func() { + elapsedDuration := time.Since(startTime) + + attrSet := labeler.AttributeSet() + attrs := attrSet.ToSlice() + code := statusWriter.status + if code != 0 { + codeAttr := semconv.HTTPResponseStatusCode(code) + attrs = append(attrs, codeAttr) + span.SetAttributes(codeAttr) + } + attrOpt := metric.WithAttributes(attrs...) + + // Increment request counter. + s.requests.Add(ctx, 1, attrOpt) + + // Use floating point division here for higher precision (instead of Millisecond method). + s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt) + }() + + var ( + recordError = func(stage string, err error) { + span.RecordError(err) + + // https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status + // Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges, + // unless there was another error (e.g., network error receiving the response body; or 3xx codes with + // max redirects exceeded), in which case status MUST be set to Error. + code := statusWriter.status + if code >= 100 && code < 500 { + span.SetStatus(codes.Error, stage) + } + + attrSet := labeler.AttributeSet() + attrs := attrSet.ToSlice() + if code != 0 { + attrs = append(attrs, semconv.HTTPResponseStatusCode(code)) + } + + s.errors.Add(ctx, 1, metric.WithAttributes(attrs...)) + } + err error + opErrContext = ogenerrors.OperationContext{ + Name: CreateSubmissionAuditErrorOperation, + ID: "createSubmissionAuditError", + } + ) + params, err := decodeCreateSubmissionAuditErrorParams(args, argsEscaped, r) + if err != nil { + err = &ogenerrors.DecodeParamsError{ + OperationContext: opErrContext, + Err: err, + } + defer recordError("DecodeParams", err) + s.cfg.ErrorHandler(ctx, w, r, err) + return + } + + var response *CreateSubmissionAuditErrorNoContent + if m := s.cfg.Middleware; m != nil { + mreq := middleware.Request{ + Context: ctx, + OperationName: CreateSubmissionAuditErrorOperation, + OperationSummary: "Validator posts an error to the audit log", + OperationID: "createSubmissionAuditError", + Body: nil, + Params: middleware.Parameters{ + { + Name: "SubmissionID", + In: "path", + }: params.SubmissionID, + { + Name: "ErrorMessage", + In: "query", + }: params.ErrorMessage, + }, + Raw: r, + } + + type ( + Request = struct{} + Params = CreateSubmissionAuditErrorParams + Response = *CreateSubmissionAuditErrorNoContent + ) + response, err = middleware.HookMiddleware[ + Request, + Params, + Response, + ]( + m, + mreq, + unpackCreateSubmissionAuditErrorParams, + func(ctx context.Context, request Request, params Params) (response Response, err error) { + err = s.h.CreateSubmissionAuditError(ctx, params) + return response, err + }, + ) + } else { + err = s.h.CreateSubmissionAuditError(ctx, params) + } + if err != nil { + if errRes, ok := errors.Into[*ErrorStatusCode](err); ok { + if err := encodeErrorResponse(errRes, w, span); err != nil { + defer recordError("Internal", err) + } + return + } + if errors.Is(err, ht.ErrNotImplemented) { + s.cfg.ErrorHandler(ctx, w, r, err) + return + } + if err := encodeErrorResponse(s.h.NewError(ctx, err), w, span); err != nil { + defer recordError("Internal", err) + } + return + } + + if err := encodeCreateSubmissionAuditErrorResponse(response, w, span); err != nil { + defer recordError("EncodeResponse", err) + if !errors.Is(err, ht.ErrInternalServerErrorResponse) { + s.cfg.ErrorHandler(ctx, w, r, err) + } + return + } +} + // handleGetScriptRequest handles getScript operation. // // Get the specified script by ID. diff --git a/pkg/internal/oas_operations_gen.go b/pkg/internal/oas_operations_gen.go index 9ddc04b..1ee0aac 100644 --- a/pkg/internal/oas_operations_gen.go +++ b/pkg/internal/oas_operations_gen.go @@ -18,9 +18,11 @@ const ( ActionSubmissionUploadedOperation OperationName = "ActionSubmissionUploaded" ActionSubmissionValidatedOperation OperationName = "ActionSubmissionValidated" CreateMapfixOperation OperationName = "CreateMapfix" + CreateMapfixAuditErrorOperation OperationName = "CreateMapfixAuditError" CreateScriptOperation OperationName = "CreateScript" CreateScriptPolicyOperation OperationName = "CreateScriptPolicy" CreateSubmissionOperation OperationName = "CreateSubmission" + CreateSubmissionAuditErrorOperation OperationName = "CreateSubmissionAuditError" GetScriptOperation OperationName = "GetScript" ListScriptPolicyOperation OperationName = "ListScriptPolicy" ListScriptsOperation OperationName = "ListScripts" diff --git a/pkg/internal/oas_parameters_gen.go b/pkg/internal/oas_parameters_gen.go index f041c7f..e8f11fd 100644 --- a/pkg/internal/oas_parameters_gen.go +++ b/pkg/internal/oas_parameters_gen.go @@ -18,8 +18,7 @@ import ( // ActionMapfixAcceptedParams is parameters of actionMapfixAccepted operation. type ActionMapfixAcceptedParams struct { // The unique identifier for a submission. - MapfixID int64 - ErrorMessage string + MapfixID int64 } func unpackActionMapfixAcceptedParams(packed middleware.Parameters) (params ActionMapfixAcceptedParams) { @@ -30,18 +29,10 @@ func unpackActionMapfixAcceptedParams(packed middleware.Parameters) (params Acti } params.MapfixID = packed[key].(int64) } - { - key := middleware.ParameterKey{ - Name: "ErrorMessage", - In: "query", - } - params.ErrorMessage = packed[key].(string) - } return params } func decodeActionMapfixAcceptedParams(args [1]string, argsEscaped bool, r *http.Request) (params ActionMapfixAcceptedParams, _ error) { - q := uri.NewQueryDecoder(r.URL.Query()) // Decode path: MapfixID. if err := func() error { param := args[0] @@ -104,66 +95,13 @@ func decodeActionMapfixAcceptedParams(args [1]string, argsEscaped bool, r *http. Err: err, } } - // Decode query: ErrorMessage. - if err := func() error { - cfg := uri.QueryParameterDecodingConfig{ - Name: "ErrorMessage", - Style: uri.QueryStyleForm, - Explode: true, - } - - if err := q.HasParam(cfg); err == nil { - if err := q.DecodeParam(cfg, func(d uri.Decoder) error { - val, err := d.DecodeValue() - if err != nil { - return err - } - - c, err := conv.ToString(val) - if err != nil { - return err - } - - params.ErrorMessage = c - return nil - }); err != nil { - return err - } - if err := func() error { - if err := (validate.String{ - MinLength: 0, - MinLengthSet: true, - MaxLength: 4096, - MaxLengthSet: true, - Email: false, - Hostname: false, - Regex: nil, - }).Validate(string(params.ErrorMessage)); err != nil { - return errors.Wrap(err, "string") - } - return nil - }(); err != nil { - return err - } - } else { - return err - } - return nil - }(); err != nil { - return params, &ogenerrors.DecodeParamError{ - Name: "ErrorMessage", - In: "query", - Err: err, - } - } return params, nil } // ActionMapfixRequestChangesParams is parameters of actionMapfixRequestChanges operation. type ActionMapfixRequestChangesParams struct { // The unique identifier for a submission. - MapfixID int64 - ErrorMessage string + MapfixID int64 } func unpackActionMapfixRequestChangesParams(packed middleware.Parameters) (params ActionMapfixRequestChangesParams) { @@ -174,18 +112,10 @@ func unpackActionMapfixRequestChangesParams(packed middleware.Parameters) (param } params.MapfixID = packed[key].(int64) } - { - key := middleware.ParameterKey{ - Name: "ErrorMessage", - In: "query", - } - params.ErrorMessage = packed[key].(string) - } return params } func decodeActionMapfixRequestChangesParams(args [1]string, argsEscaped bool, r *http.Request) (params ActionMapfixRequestChangesParams, _ error) { - q := uri.NewQueryDecoder(r.URL.Query()) // Decode path: MapfixID. if err := func() error { param := args[0] @@ -248,58 +178,6 @@ func decodeActionMapfixRequestChangesParams(args [1]string, argsEscaped bool, r Err: err, } } - // Decode query: ErrorMessage. - if err := func() error { - cfg := uri.QueryParameterDecodingConfig{ - Name: "ErrorMessage", - Style: uri.QueryStyleForm, - Explode: true, - } - - if err := q.HasParam(cfg); err == nil { - if err := q.DecodeParam(cfg, func(d uri.Decoder) error { - val, err := d.DecodeValue() - if err != nil { - return err - } - - c, err := conv.ToString(val) - if err != nil { - return err - } - - params.ErrorMessage = c - return nil - }); err != nil { - return err - } - if err := func() error { - if err := (validate.String{ - MinLength: 0, - MinLengthSet: true, - MaxLength: 4096, - MaxLengthSet: true, - Email: false, - Hostname: false, - Regex: nil, - }).Validate(string(params.ErrorMessage)); err != nil { - return errors.Wrap(err, "string") - } - return nil - }(); err != nil { - return err - } - } else { - return err - } - return nil - }(); err != nil { - return params, &ogenerrors.DecodeParamError{ - Name: "ErrorMessage", - In: "query", - Err: err, - } - } return params, nil } @@ -943,7 +821,6 @@ func decodeActionOperationFailedParams(args [1]string, argsEscaped bool, r *http type ActionSubmissionAcceptedParams struct { // The unique identifier for a submission. SubmissionID int64 - ErrorMessage string } func unpackActionSubmissionAcceptedParams(packed middleware.Parameters) (params ActionSubmissionAcceptedParams) { @@ -954,18 +831,10 @@ func unpackActionSubmissionAcceptedParams(packed middleware.Parameters) (params } params.SubmissionID = packed[key].(int64) } - { - key := middleware.ParameterKey{ - Name: "ErrorMessage", - In: "query", - } - params.ErrorMessage = packed[key].(string) - } return params } func decodeActionSubmissionAcceptedParams(args [1]string, argsEscaped bool, r *http.Request) (params ActionSubmissionAcceptedParams, _ error) { - q := uri.NewQueryDecoder(r.URL.Query()) // Decode path: SubmissionID. if err := func() error { param := args[0] @@ -1028,58 +897,6 @@ func decodeActionSubmissionAcceptedParams(args [1]string, argsEscaped bool, r *h Err: err, } } - // Decode query: ErrorMessage. - if err := func() error { - cfg := uri.QueryParameterDecodingConfig{ - Name: "ErrorMessage", - Style: uri.QueryStyleForm, - Explode: true, - } - - if err := q.HasParam(cfg); err == nil { - if err := q.DecodeParam(cfg, func(d uri.Decoder) error { - val, err := d.DecodeValue() - if err != nil { - return err - } - - c, err := conv.ToString(val) - if err != nil { - return err - } - - params.ErrorMessage = c - return nil - }); err != nil { - return err - } - if err := func() error { - if err := (validate.String{ - MinLength: 0, - MinLengthSet: true, - MaxLength: 4096, - MaxLengthSet: true, - Email: false, - Hostname: false, - Regex: nil, - }).Validate(string(params.ErrorMessage)); err != nil { - return errors.Wrap(err, "string") - } - return nil - }(); err != nil { - return err - } - } else { - return err - } - return nil - }(); err != nil { - return params, &ogenerrors.DecodeParamError{ - Name: "ErrorMessage", - In: "query", - Err: err, - } - } return params, nil } @@ -1087,7 +904,6 @@ func decodeActionSubmissionAcceptedParams(args [1]string, argsEscaped bool, r *h type ActionSubmissionRequestChangesParams struct { // The unique identifier for a submission. SubmissionID int64 - ErrorMessage string } func unpackActionSubmissionRequestChangesParams(packed middleware.Parameters) (params ActionSubmissionRequestChangesParams) { @@ -1098,18 +914,10 @@ func unpackActionSubmissionRequestChangesParams(packed middleware.Parameters) (p } params.SubmissionID = packed[key].(int64) } - { - key := middleware.ParameterKey{ - Name: "ErrorMessage", - In: "query", - } - params.ErrorMessage = packed[key].(string) - } return params } func decodeActionSubmissionRequestChangesParams(args [1]string, argsEscaped bool, r *http.Request) (params ActionSubmissionRequestChangesParams, _ error) { - q := uri.NewQueryDecoder(r.URL.Query()) // Decode path: SubmissionID. if err := func() error { param := args[0] @@ -1172,58 +980,6 @@ func decodeActionSubmissionRequestChangesParams(args [1]string, argsEscaped bool Err: err, } } - // Decode query: ErrorMessage. - if err := func() error { - cfg := uri.QueryParameterDecodingConfig{ - Name: "ErrorMessage", - Style: uri.QueryStyleForm, - Explode: true, - } - - if err := q.HasParam(cfg); err == nil { - if err := q.DecodeParam(cfg, func(d uri.Decoder) error { - val, err := d.DecodeValue() - if err != nil { - return err - } - - c, err := conv.ToString(val) - if err != nil { - return err - } - - params.ErrorMessage = c - return nil - }); err != nil { - return err - } - if err := func() error { - if err := (validate.String{ - MinLength: 0, - MinLengthSet: true, - MaxLength: 4096, - MaxLengthSet: true, - Email: false, - Hostname: false, - Regex: nil, - }).Validate(string(params.ErrorMessage)); err != nil { - return errors.Wrap(err, "string") - } - return nil - }(); err != nil { - return err - } - } else { - return err - } - return nil - }(); err != nil { - return params, &ogenerrors.DecodeParamError{ - Name: "ErrorMessage", - In: "query", - Err: err, - } - } return params, nil } @@ -1781,6 +1537,294 @@ func decodeActionSubmissionValidatedParams(args [1]string, argsEscaped bool, r * return params, nil } +// CreateMapfixAuditErrorParams is parameters of createMapfixAuditError operation. +type CreateMapfixAuditErrorParams struct { + // The unique identifier for a submission. + MapfixID int64 + ErrorMessage string +} + +func unpackCreateMapfixAuditErrorParams(packed middleware.Parameters) (params CreateMapfixAuditErrorParams) { + { + key := middleware.ParameterKey{ + Name: "MapfixID", + In: "path", + } + params.MapfixID = packed[key].(int64) + } + { + key := middleware.ParameterKey{ + Name: "ErrorMessage", + In: "query", + } + params.ErrorMessage = packed[key].(string) + } + return params +} + +func decodeCreateMapfixAuditErrorParams(args [1]string, argsEscaped bool, r *http.Request) (params CreateMapfixAuditErrorParams, _ error) { + q := uri.NewQueryDecoder(r.URL.Query()) + // Decode path: MapfixID. + if err := func() error { + param := args[0] + if argsEscaped { + unescaped, err := url.PathUnescape(args[0]) + if err != nil { + return errors.Wrap(err, "unescape path") + } + param = unescaped + } + if len(param) > 0 { + d := uri.NewPathDecoder(uri.PathDecoderConfig{ + Param: "MapfixID", + Value: param, + Style: uri.PathStyleSimple, + Explode: false, + }) + + if err := func() error { + val, err := d.DecodeValue() + if err != nil { + return err + } + + c, err := conv.ToInt64(val) + if err != nil { + return err + } + + params.MapfixID = c + return nil + }(); err != nil { + return err + } + if err := func() error { + if err := (validate.Int{ + MinSet: true, + Min: 0, + MaxSet: false, + Max: 0, + MinExclusive: false, + MaxExclusive: false, + MultipleOfSet: false, + MultipleOf: 0, + }).Validate(int64(params.MapfixID)); err != nil { + return errors.Wrap(err, "int") + } + return nil + }(); err != nil { + return err + } + } else { + return validate.ErrFieldRequired + } + return nil + }(); err != nil { + return params, &ogenerrors.DecodeParamError{ + Name: "MapfixID", + In: "path", + Err: err, + } + } + // Decode query: ErrorMessage. + if err := func() error { + cfg := uri.QueryParameterDecodingConfig{ + Name: "ErrorMessage", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.HasParam(cfg); err == nil { + if err := q.DecodeParam(cfg, func(d uri.Decoder) error { + val, err := d.DecodeValue() + if err != nil { + return err + } + + c, err := conv.ToString(val) + if err != nil { + return err + } + + params.ErrorMessage = c + return nil + }); err != nil { + return err + } + if err := func() error { + if err := (validate.String{ + MinLength: 0, + MinLengthSet: true, + MaxLength: 4096, + MaxLengthSet: true, + Email: false, + Hostname: false, + Regex: nil, + }).Validate(string(params.ErrorMessage)); err != nil { + return errors.Wrap(err, "string") + } + return nil + }(); err != nil { + return err + } + } else { + return err + } + return nil + }(); err != nil { + return params, &ogenerrors.DecodeParamError{ + Name: "ErrorMessage", + In: "query", + Err: err, + } + } + return params, nil +} + +// CreateSubmissionAuditErrorParams is parameters of createSubmissionAuditError operation. +type CreateSubmissionAuditErrorParams struct { + // The unique identifier for a submission. + SubmissionID int64 + ErrorMessage string +} + +func unpackCreateSubmissionAuditErrorParams(packed middleware.Parameters) (params CreateSubmissionAuditErrorParams) { + { + key := middleware.ParameterKey{ + Name: "SubmissionID", + In: "path", + } + params.SubmissionID = packed[key].(int64) + } + { + key := middleware.ParameterKey{ + Name: "ErrorMessage", + In: "query", + } + params.ErrorMessage = packed[key].(string) + } + return params +} + +func decodeCreateSubmissionAuditErrorParams(args [1]string, argsEscaped bool, r *http.Request) (params CreateSubmissionAuditErrorParams, _ error) { + q := uri.NewQueryDecoder(r.URL.Query()) + // Decode path: SubmissionID. + if err := func() error { + param := args[0] + if argsEscaped { + unescaped, err := url.PathUnescape(args[0]) + if err != nil { + return errors.Wrap(err, "unescape path") + } + param = unescaped + } + if len(param) > 0 { + d := uri.NewPathDecoder(uri.PathDecoderConfig{ + Param: "SubmissionID", + Value: param, + Style: uri.PathStyleSimple, + Explode: false, + }) + + if err := func() error { + val, err := d.DecodeValue() + if err != nil { + return err + } + + c, err := conv.ToInt64(val) + if err != nil { + return err + } + + params.SubmissionID = c + return nil + }(); err != nil { + return err + } + if err := func() error { + if err := (validate.Int{ + MinSet: true, + Min: 0, + MaxSet: false, + Max: 0, + MinExclusive: false, + MaxExclusive: false, + MultipleOfSet: false, + MultipleOf: 0, + }).Validate(int64(params.SubmissionID)); err != nil { + return errors.Wrap(err, "int") + } + return nil + }(); err != nil { + return err + } + } else { + return validate.ErrFieldRequired + } + return nil + }(); err != nil { + return params, &ogenerrors.DecodeParamError{ + Name: "SubmissionID", + In: "path", + Err: err, + } + } + // Decode query: ErrorMessage. + if err := func() error { + cfg := uri.QueryParameterDecodingConfig{ + Name: "ErrorMessage", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.HasParam(cfg); err == nil { + if err := q.DecodeParam(cfg, func(d uri.Decoder) error { + val, err := d.DecodeValue() + if err != nil { + return err + } + + c, err := conv.ToString(val) + if err != nil { + return err + } + + params.ErrorMessage = c + return nil + }); err != nil { + return err + } + if err := func() error { + if err := (validate.String{ + MinLength: 0, + MinLengthSet: true, + MaxLength: 4096, + MaxLengthSet: true, + Email: false, + Hostname: false, + Regex: nil, + }).Validate(string(params.ErrorMessage)); err != nil { + return errors.Wrap(err, "string") + } + return nil + }(); err != nil { + return err + } + } else { + return err + } + return nil + }(); err != nil { + return params, &ogenerrors.DecodeParamError{ + Name: "ErrorMessage", + In: "query", + Err: err, + } + } + return params, nil +} + // GetScriptParams is parameters of getScript operation. type GetScriptParams struct { // The unique identifier for a script. diff --git a/pkg/internal/oas_response_decoders_gen.go b/pkg/internal/oas_response_decoders_gen.go index 77616ac..28f2f29 100644 --- a/pkg/internal/oas_response_decoders_gen.go +++ b/pkg/internal/oas_response_decoders_gen.go @@ -776,6 +776,66 @@ func decodeCreateMapfixResponse(resp *http.Response) (res *MapfixID, _ error) { return res, errors.Wrap(defRes, "error") } +func decodeCreateMapfixAuditErrorResponse(resp *http.Response) (res *CreateMapfixAuditErrorNoContent, _ error) { + switch resp.StatusCode { + case 204: + // Code 204. + return &CreateMapfixAuditErrorNoContent{}, nil + } + // Convenient error response. + defRes, err := func() (res *ErrorStatusCode, err error) { + ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type")) + if err != nil { + return res, errors.Wrap(err, "parse media type") + } + switch { + case ct == "application/json": + buf, err := io.ReadAll(resp.Body) + if err != nil { + return res, err + } + d := jx.DecodeBytes(buf) + + var response Error + if err := func() error { + if err := response.Decode(d); err != nil { + return err + } + if err := d.Skip(); err != io.EOF { + return errors.New("unexpected trailing data") + } + return nil + }(); err != nil { + err = &ogenerrors.DecodeBodyError{ + ContentType: ct, + Body: buf, + Err: err, + } + return res, err + } + // Validate response. + if err := func() error { + if err := response.Validate(); err != nil { + return err + } + return nil + }(); err != nil { + return res, errors.Wrap(err, "validate") + } + return &ErrorStatusCode{ + StatusCode: resp.StatusCode, + Response: response, + }, nil + default: + return res, validate.InvalidContentType(ct) + } + }() + if err != nil { + return res, errors.Wrapf(err, "default (code %d)", resp.StatusCode) + } + return res, errors.Wrap(defRes, "error") +} + func decodeCreateScriptResponse(resp *http.Response) (res *ScriptID, _ error) { switch resp.StatusCode { case 201: @@ -1079,6 +1139,66 @@ func decodeCreateSubmissionResponse(resp *http.Response) (res *SubmissionID, _ e return res, errors.Wrap(defRes, "error") } +func decodeCreateSubmissionAuditErrorResponse(resp *http.Response) (res *CreateSubmissionAuditErrorNoContent, _ error) { + switch resp.StatusCode { + case 204: + // Code 204. + return &CreateSubmissionAuditErrorNoContent{}, nil + } + // Convenient error response. + defRes, err := func() (res *ErrorStatusCode, err error) { + ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type")) + if err != nil { + return res, errors.Wrap(err, "parse media type") + } + switch { + case ct == "application/json": + buf, err := io.ReadAll(resp.Body) + if err != nil { + return res, err + } + d := jx.DecodeBytes(buf) + + var response Error + if err := func() error { + if err := response.Decode(d); err != nil { + return err + } + if err := d.Skip(); err != io.EOF { + return errors.New("unexpected trailing data") + } + return nil + }(); err != nil { + err = &ogenerrors.DecodeBodyError{ + ContentType: ct, + Body: buf, + Err: err, + } + return res, err + } + // Validate response. + if err := func() error { + if err := response.Validate(); err != nil { + return err + } + return nil + }(); err != nil { + return res, errors.Wrap(err, "validate") + } + return &ErrorStatusCode{ + StatusCode: resp.StatusCode, + Response: response, + }, nil + default: + return res, validate.InvalidContentType(ct) + } + }() + if err != nil { + return res, errors.Wrapf(err, "default (code %d)", resp.StatusCode) + } + return res, errors.Wrap(defRes, "error") +} + func decodeGetScriptResponse(resp *http.Response) (res *Script, _ error) { switch resp.StatusCode { case 200: diff --git a/pkg/internal/oas_response_encoders_gen.go b/pkg/internal/oas_response_encoders_gen.go index 024126c..5cde190 100644 --- a/pkg/internal/oas_response_encoders_gen.go +++ b/pkg/internal/oas_response_encoders_gen.go @@ -104,6 +104,13 @@ func encodeCreateMapfixResponse(response *MapfixID, w http.ResponseWriter, span return nil } +func encodeCreateMapfixAuditErrorResponse(response *CreateMapfixAuditErrorNoContent, w http.ResponseWriter, span trace.Span) error { + w.WriteHeader(204) + span.SetStatus(codes.Ok, http.StatusText(204)) + + return nil +} + func encodeCreateScriptResponse(response *ScriptID, w http.ResponseWriter, span trace.Span) error { w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(201) @@ -146,6 +153,13 @@ func encodeCreateSubmissionResponse(response *SubmissionID, w http.ResponseWrite return nil } +func encodeCreateSubmissionAuditErrorResponse(response *CreateSubmissionAuditErrorNoContent, w http.ResponseWriter, span trace.Span) error { + w.WriteHeader(204) + span.SetStatus(codes.Ok, http.StatusText(204)) + + return nil +} + func encodeGetScriptResponse(response *Script, w http.ResponseWriter, span trace.Span) error { w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(200) diff --git a/pkg/internal/oas_router_gen.go b/pkg/internal/oas_router_gen.go index 43be2cc..a6615a9 100644 --- a/pkg/internal/oas_router_gen.go +++ b/pkg/internal/oas_router_gen.go @@ -113,6 +113,28 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { break } switch elem[0] { + case 'e': // Prefix: "error" + + if l := len("error"); len(elem) >= l && elem[0:l] == "error" { + elem = elem[l:] + } else { + break + } + + if len(elem) == 0 { + // Leaf node. + switch r.Method { + case "POST": + s.handleCreateMapfixAuditErrorRequest([1]string{ + args[0], + }, elemIsEscaped, w, r) + default: + s.notAllowed(w, r, "POST") + } + + return + } + case 's': // Prefix: "status/validator-" if l := len("status/validator-"); len(elem) >= l && elem[0:l] == "status/validator-" { @@ -464,6 +486,28 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { break } switch elem[0] { + case 'e': // Prefix: "error" + + if l := len("error"); len(elem) >= l && elem[0:l] == "error" { + elem = elem[l:] + } else { + break + } + + if len(elem) == 0 { + // Leaf node. + switch r.Method { + case "POST": + s.handleCreateSubmissionAuditErrorRequest([1]string{ + args[0], + }, elemIsEscaped, w, r) + default: + s.notAllowed(w, r, "POST") + } + + return + } + case 's': // Prefix: "status/validator-" if l := len("status/validator-"); len(elem) >= l && elem[0:l] == "status/validator-" { @@ -768,6 +812,30 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) { break } switch elem[0] { + case 'e': // Prefix: "error" + + if l := len("error"); len(elem) >= l && elem[0:l] == "error" { + elem = elem[l:] + } else { + break + } + + if len(elem) == 0 { + // Leaf node. + switch method { + case "POST": + r.name = CreateMapfixAuditErrorOperation + r.summary = "Validator posts an error to the audit log" + r.operationID = "createMapfixAuditError" + r.pathPattern = "/mapfixes/{MapfixID}/error" + r.args = args + r.count = 1 + return r, true + default: + return + } + } + case 's': // Prefix: "status/validator-" if l := len("status/validator-"); len(elem) >= l && elem[0:l] == "status/validator-" { @@ -1159,6 +1227,30 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) { break } switch elem[0] { + case 'e': // Prefix: "error" + + if l := len("error"); len(elem) >= l && elem[0:l] == "error" { + elem = elem[l:] + } else { + break + } + + if len(elem) == 0 { + // Leaf node. + switch method { + case "POST": + r.name = CreateSubmissionAuditErrorOperation + r.summary = "Validator posts an error to the audit log" + r.operationID = "createSubmissionAuditError" + r.pathPattern = "/submissions/{SubmissionID}/error" + r.args = args + r.count = 1 + return r, true + default: + return + } + } + case 's': // Prefix: "status/validator-" if l := len("status/validator-"); len(elem) >= l && elem[0:l] == "status/validator-" { diff --git a/pkg/internal/oas_schemas_gen.go b/pkg/internal/oas_schemas_gen.go index 86ef488..16c6e42 100644 --- a/pkg/internal/oas_schemas_gen.go +++ b/pkg/internal/oas_schemas_gen.go @@ -43,6 +43,12 @@ type ActionSubmissionUploadedNoContent struct{} // ActionSubmissionValidatedNoContent is response for ActionSubmissionValidated operation. type ActionSubmissionValidatedNoContent struct{} +// CreateMapfixAuditErrorNoContent is response for CreateMapfixAuditError operation. +type CreateMapfixAuditErrorNoContent struct{} + +// CreateSubmissionAuditErrorNoContent is response for CreateSubmissionAuditError operation. +type CreateSubmissionAuditErrorNoContent struct{} + // Represents error object. // Ref: #/components/schemas/Error type Error struct { diff --git a/pkg/internal/oas_server_gen.go b/pkg/internal/oas_server_gen.go index 7350a9c..b091f81 100644 --- a/pkg/internal/oas_server_gen.go +++ b/pkg/internal/oas_server_gen.go @@ -80,6 +80,12 @@ type Handler interface { // // POST /mapfixes CreateMapfix(ctx context.Context, req *MapfixCreate) (*MapfixID, error) + // CreateMapfixAuditError implements createMapfixAuditError operation. + // + // Validator posts an error to the audit log. + // + // POST /mapfixes/{MapfixID}/error + CreateMapfixAuditError(ctx context.Context, params CreateMapfixAuditErrorParams) error // CreateScript implements createScript operation. // // Create a new script. @@ -98,6 +104,12 @@ type Handler interface { // // POST /submissions CreateSubmission(ctx context.Context, req *SubmissionCreate) (*SubmissionID, error) + // CreateSubmissionAuditError implements createSubmissionAuditError operation. + // + // Validator posts an error to the audit log. + // + // POST /submissions/{SubmissionID}/error + CreateSubmissionAuditError(ctx context.Context, params CreateSubmissionAuditErrorParams) error // GetScript implements getScript operation. // // Get the specified script by ID. diff --git a/pkg/internal/oas_unimplemented_gen.go b/pkg/internal/oas_unimplemented_gen.go index 46a4c7e..666fc14 100644 --- a/pkg/internal/oas_unimplemented_gen.go +++ b/pkg/internal/oas_unimplemented_gen.go @@ -121,6 +121,15 @@ func (UnimplementedHandler) CreateMapfix(ctx context.Context, req *MapfixCreate) return r, ht.ErrNotImplemented } +// CreateMapfixAuditError implements createMapfixAuditError operation. +// +// Validator posts an error to the audit log. +// +// POST /mapfixes/{MapfixID}/error +func (UnimplementedHandler) CreateMapfixAuditError(ctx context.Context, params CreateMapfixAuditErrorParams) error { + return ht.ErrNotImplemented +} + // CreateScript implements createScript operation. // // Create a new script. @@ -148,6 +157,15 @@ func (UnimplementedHandler) CreateSubmission(ctx context.Context, req *Submissio return r, ht.ErrNotImplemented } +// CreateSubmissionAuditError implements createSubmissionAuditError operation. +// +// Validator posts an error to the audit log. +// +// POST /submissions/{SubmissionID}/error +func (UnimplementedHandler) CreateSubmissionAuditError(ctx context.Context, params CreateSubmissionAuditErrorParams) error { + return ht.ErrNotImplemented +} + // GetScript implements getScript operation. // // Get the specified script by ID. diff --git a/pkg/service_internal/mapfixes.go b/pkg/service_internal/mapfixes.go index 3a86ae9..7c44a89 100644 --- a/pkg/service_internal/mapfixes.go +++ b/pkg/service_internal/mapfixes.go @@ -113,25 +113,6 @@ func (svc *Service) ActionMapfixRequestChanges(ctx context.Context, params inter return err } - { - event_data := model.AuditEventDataError{ - Error: params.ErrorMessage, - } - - err = svc.CreateAuditEventError( - ctx, - ValidtorUserID, - model.Resource{ - ID: params.MapfixID, - Type: model.ResourceMapfix, - }, - event_data, - ) - if err != nil { - return err - } - } - event_data := model.AuditEventDataAction{ TargetStatus: uint32(target_status), } @@ -174,26 +155,6 @@ func (svc *Service) ActionMapfixAccepted(ctx context.Context, params internal.Ac return err } - //push an error audit event - { - event_data := model.AuditEventDataError{ - Error: params.ErrorMessage, - } - - err = svc.CreateAuditEventError( - ctx, - ValidtorUserID, - model.Resource{ - ID: params.MapfixID, - Type: model.ResourceMapfix, - }, - event_data, - ) - if err != nil { - return err - } - } - // push an action audit event event_data := model.AuditEventDataAction{ TargetStatus: uint32(target_status), @@ -240,6 +201,27 @@ func (svc *Service) ActionMapfixUploaded(ctx context.Context, params internal.Ac ) } +// CreateMapfixAuditError implements createMapfixAuditError operation. +// +// Post an error to the audit log +// +// POST /mapfixes/{MapfixID}/error +func (svc *Service) CreateMapfixAuditError(ctx context.Context, params internal.CreateMapfixAuditErrorParams) (error) { + event_data := model.AuditEventDataError{ + Error: params.ErrorMessage, + } + + return svc.CreateAuditEventError( + ctx, + ValidtorUserID, + model.Resource{ + ID: params.MapfixID, + Type: model.ResourceMapfix, + }, + event_data, + ) +} + // POST /mapfixes func (svc *Service) CreateMapfix(ctx context.Context, request *internal.MapfixCreate) (*internal.MapfixID, error) { // sanitization diff --git a/pkg/service_internal/submissions.go b/pkg/service_internal/submissions.go index 23d7415..910b8f8 100644 --- a/pkg/service_internal/submissions.go +++ b/pkg/service_internal/submissions.go @@ -113,26 +113,6 @@ func (svc *Service) ActionSubmissionRequestChanges(ctx context.Context, params i return err } - //push an error audit event - { - event_data := model.AuditEventDataError{ - Error: params.ErrorMessage, - } - - err = svc.CreateAuditEventError( - ctx, - ValidtorUserID, - model.Resource{ - ID: params.SubmissionID, - Type: model.ResourceSubmission, - }, - event_data, - ) - if err != nil { - return err - } - } - // push an action audit event event_data := model.AuditEventDataAction{ TargetStatus: uint32(target_status), @@ -194,27 +174,6 @@ func (svc *Service) ActionSubmissionAccepted(ctx context.Context, params interna return err } - - //push an error audit event - { - event_data := model.AuditEventDataError{ - Error: params.ErrorMessage, - } - - err = svc.CreateAuditEventError( - ctx, - ValidtorUserID, - model.Resource{ - ID: params.SubmissionID, - Type: model.ResourceSubmission, - }, - event_data, - ) - if err != nil { - return err - } - } - // push an action audit event event_data := model.AuditEventDataAction{ TargetStatus: uint32(target_status), @@ -262,6 +221,27 @@ func (svc *Service) ActionSubmissionUploaded(ctx context.Context, params interna ) } +// CreateSubmissionAuditError implements createSubmissionAuditError operation. +// +// Post an error to the audit log +// +// POST /submissions/{SubmissionID}/error +func (svc *Service) CreateSubmissionAuditError(ctx context.Context, params internal.CreateSubmissionAuditErrorParams) (error) { + event_data := model.AuditEventDataError{ + Error: params.ErrorMessage, + } + + return svc.CreateAuditEventError( + ctx, + ValidtorUserID, + model.Resource{ + ID: params.SubmissionID, + Type: model.ResourceSubmission, + }, + event_data, + ) +} + // POST /submissions func (svc *Service) CreateSubmission(ctx context.Context, request *internal.SubmissionCreate) (*internal.SubmissionID, error) { // sanitization diff --git a/validation/api/src/internal.rs b/validation/api/src/internal.rs index 7ed9516..28fe19c 100644 --- a/validation/api/src/internal.rs +++ b/validation/api/src/internal.rs @@ -162,9 +162,7 @@ impl Context{ .json().await.map_err(Error::ReqwestJson) } // simple submission endpoints - action!("submissions",action_submission_request_changes,config,ActionSubmissionRequestChangesRequest,"status/validator-request-changes",config.SubmissionID.0, - ("ErrorMessage",config.ErrorMessage.as_str()) - ); + action!("submissions",action_submission_request_changes,config,ActionSubmissionRequestChangesRequest,"status/validator-request-changes",config.SubmissionID.0,); action!("submissions",action_submission_submitted,config,ActionSubmissionSubmittedRequest,"status/validator-submitted",config.SubmissionID.0, ("ModelVersion",config.ModelVersion.to_string().as_str()) ("DisplayName",config.DisplayName.as_str()) @@ -179,7 +177,8 @@ impl Context{ action!("submissions",action_submission_uploaded,config,ActionSubmissionUploadedRequest,"status/validator-uploaded",config.SubmissionID.0, ("UploadedAssetID",config.UploadedAssetID.to_string().as_str()) ); - action!("submissions",action_submission_accepted,config,ActionSubmissionAcceptedRequest,"status/validator-failed",config.SubmissionID.0, + action!("submissions",action_submission_accepted,config,ActionSubmissionAcceptedRequest,"status/validator-failed",config.SubmissionID.0,); + action!("submissions",create_submission_audit_error,config,CreateSubmissionAuditErrorRequest,"error",config.SubmissionID.0, ("ErrorMessage",config.ErrorMessage.as_str()) ); pub async fn create_mapfix(&self,config:CreateMapfixRequest<'_>)->Result{ @@ -194,9 +193,7 @@ impl Context{ .json().await.map_err(Error::ReqwestJson) } // simple mapfixes endpoints - action!("mapfixes",action_mapfix_request_changes,config,ActionMapfixRequestChangesRequest,"status/validator-request-changes",config.MapfixID.0, - ("ErrorMessage",config.ErrorMessage.as_str()) - ); + action!("mapfixes",action_mapfix_request_changes,config,ActionMapfixRequestChangesRequest,"status/validator-request-changes",config.MapfixID.0,); action!("mapfixes",action_mapfix_submitted,config,ActionMapfixSubmittedRequest,"status/validator-submitted",config.MapfixID.0, ("ModelVersion",config.ModelVersion.to_string().as_str()) ("DisplayName",config.DisplayName.as_str()) @@ -209,11 +206,12 @@ impl Context{ ("ValidatedModelVersion",config.ModelVersion.to_string().as_str()) ); action!("mapfixes",action_mapfix_uploaded,config,ActionMapfixUploadedRequest,"status/validator-uploaded",config.MapfixID.0,); - action!("mapfixes",action_mapfix_accepted,config,ActionMapfixAcceptedRequest,"status/validator-failed",config.MapfixID.0, - ("ErrorMessage",config.ErrorMessage.as_str()) - ); + action!("mapfixes",action_mapfix_accepted,config,ActionMapfixAcceptedRequest,"status/validator-failed",config.MapfixID.0,); // simple operation endpoint action!("operations",action_operation_failed,config,ActionOperationFailedRequest,"status/operation-failed",config.OperationID.0, ("StatusMessage",config.StatusMessage.as_str()) ); + action!("mapfixes",create_mapfix_audit_error,config,CreateMapfixAuditErrorRequest,"error",config.MapfixID.0, + ("ErrorMessage",config.ErrorMessage.as_str()) + ); } diff --git a/validation/api/src/types.rs b/validation/api/src/types.rs index 1969599..0ccb5d1 100644 --- a/validation/api/src/types.rs +++ b/validation/api/src/types.rs @@ -348,7 +348,6 @@ pub struct ActionSubmissionSubmittedRequest{ #[derive(Clone,Debug)] pub struct ActionSubmissionRequestChangesRequest{ pub SubmissionID:SubmissionID, - pub ErrorMessage:String, } #[allow(nonstandard_style)] @@ -362,6 +361,12 @@ pub struct ActionSubmissionUploadedRequest{ #[derive(Clone,Debug)] pub struct ActionSubmissionAcceptedRequest{ pub SubmissionID:SubmissionID, +} + +#[allow(nonstandard_style)] +#[derive(Clone,Debug)] +pub struct CreateSubmissionAuditErrorRequest{ + pub SubmissionID:SubmissionID, pub ErrorMessage:String, } @@ -390,7 +395,6 @@ pub struct ActionMapfixSubmittedRequest{ #[derive(Clone,Debug)] pub struct ActionMapfixRequestChangesRequest{ pub MapfixID:MapfixID, - pub ErrorMessage:String, } #[allow(nonstandard_style)] @@ -403,6 +407,12 @@ pub struct ActionMapfixUploadedRequest{ #[derive(Clone,Debug)] pub struct ActionMapfixAcceptedRequest{ pub MapfixID:MapfixID, +} + +#[allow(nonstandard_style)] +#[derive(Clone,Debug)] +pub struct CreateMapfixAuditErrorRequest{ + pub MapfixID:MapfixID, pub ErrorMessage:String, } diff --git a/validation/src/check_mapfix.rs b/validation/src/check_mapfix.rs index c2eed90..e66b323 100644 --- a/validation/src/check_mapfix.rs +++ b/validation/src/check_mapfix.rs @@ -21,18 +21,23 @@ impl crate::message_handler::MessageHandler{ // update the mapfix depending on the result match check_result{ - Ok(CheckReportAndVersion{status:Ok(map_info),version})=>self.api.action_mapfix_submitted( - submissions_api::types::ActionMapfixSubmittedRequest{ - MapfixID:mapfix_id, - ModelVersion:version, - DisplayName:map_info.display_name, - Creator:map_info.creator, - GameID:map_info.game_id.into(), - } - ).await.map_err(Error::ApiActionMapfixCheck)?, + Ok(CheckReportAndVersion{status:Ok(map_info),version})=>{ + self.api.action_mapfix_submitted( + submissions_api::types::ActionMapfixSubmittedRequest{ + MapfixID:mapfix_id, + ModelVersion:version, + DisplayName:map_info.display_name, + Creator:map_info.creator, + GameID:map_info.game_id.into(), + } + ).await.map_err(Error::ApiActionMapfixCheck)?; + + // Do not proceed to request changes + return Ok(()); + }, // update the mapfix model status to request changes - Ok(CheckReportAndVersion{status:Err(report),..})=>self.api.action_mapfix_request_changes( - submissions_api::types::ActionMapfixRequestChangesRequest{ + Ok(CheckReportAndVersion{status:Err(report),..})=>self.api.create_mapfix_audit_error( + submissions_api::types::CreateMapfixAuditErrorRequest{ MapfixID:mapfix_id, ErrorMessage:report.summary, } @@ -42,8 +47,8 @@ impl crate::message_handler::MessageHandler{ // log error println!("[check_mapfix] Error: {e}"); - self.api.action_mapfix_request_changes( - submissions_api::types::ActionMapfixRequestChangesRequest{ + self.api.create_mapfix_audit_error( + submissions_api::types::CreateMapfixAuditErrorRequest{ MapfixID:mapfix_id, ErrorMessage:e.to_string(), } @@ -51,6 +56,12 @@ impl crate::message_handler::MessageHandler{ }, } + self.api.action_mapfix_request_changes( + submissions_api::types::ActionMapfixRequestChangesRequest{ + MapfixID:mapfix_id, + } + ).await.map_err(Error::ApiActionMapfixCheck)?; + Ok(()) } } diff --git a/validation/src/check_submission.rs b/validation/src/check_submission.rs index 37ae360..596f8e0 100644 --- a/validation/src/check_submission.rs +++ b/validation/src/check_submission.rs @@ -22,18 +22,23 @@ impl crate::message_handler::MessageHandler{ // update the submission depending on the result match check_result{ // update the submission model status to submitted - Ok(CheckReportAndVersion{status:Ok(map_info),version})=>self.api.action_submission_submitted( - submissions_api::types::ActionSubmissionSubmittedRequest{ - SubmissionID:submission_id, - ModelVersion:version, - DisplayName:map_info.display_name, - Creator:map_info.creator, - GameID:map_info.game_id.into(), - } - ).await.map_err(Error::ApiActionSubmissionCheck)?, + Ok(CheckReportAndVersion{status:Ok(map_info),version})=>{ + self.api.action_submission_submitted( + submissions_api::types::ActionSubmissionSubmittedRequest{ + SubmissionID:submission_id, + ModelVersion:version, + DisplayName:map_info.display_name, + Creator:map_info.creator, + GameID:map_info.game_id.into(), + } + ).await.map_err(Error::ApiActionSubmissionCheck)?; + + // Do not proceed to request changes + return Ok(()); + }, // update the submission model status to request changes - Ok(CheckReportAndVersion{status:Err(report),..})=>self.api.action_submission_request_changes( - submissions_api::types::ActionSubmissionRequestChangesRequest{ + Ok(CheckReportAndVersion{status:Err(report),..})=>self.api.create_submission_audit_error( + submissions_api::types::CreateSubmissionAuditErrorRequest{ SubmissionID:submission_id, ErrorMessage:report.summary, } @@ -43,8 +48,8 @@ impl crate::message_handler::MessageHandler{ // log error println!("[check_submission] Error: {e}"); - self.api.action_submission_request_changes( - submissions_api::types::ActionSubmissionRequestChangesRequest{ + self.api.create_submission_audit_error( + submissions_api::types::CreateSubmissionAuditErrorRequest{ SubmissionID:submission_id, ErrorMessage:e.to_string(), } @@ -52,6 +57,12 @@ impl crate::message_handler::MessageHandler{ }, } + self.api.action_submission_request_changes( + submissions_api::types::ActionSubmissionRequestChangesRequest{ + SubmissionID:submission_id, + } + ).await.map_err(Error::ApiActionSubmissionCheck)?; + Ok(()) } } diff --git a/validation/src/validate_mapfix.rs b/validation/src/validate_mapfix.rs index 93e087f..bce1639 100644 --- a/validation/src/validate_mapfix.rs +++ b/validation/src/validate_mapfix.rs @@ -29,10 +29,16 @@ impl crate::message_handler::MessageHandler{ // log error println!("[validate_mapfix] Error: {e}"); + self.api.create_mapfix_audit_error( + submissions_api::types::CreateMapfixAuditErrorRequest{ + MapfixID:mapfix_id, + ErrorMessage:e.to_string(), + } + ).await.map_err(Error::ApiActionMapfixValidate)?; + // update the mapfix model status to accepted self.api.action_mapfix_accepted(submissions_api::types::ActionMapfixAcceptedRequest{ MapfixID:mapfix_id, - ErrorMessage:e.to_string(), }).await.map_err(Error::ApiActionMapfixValidate)?; }, } diff --git a/validation/src/validate_submission.rs b/validation/src/validate_submission.rs index 6f6b4c4..000ce41 100644 --- a/validation/src/validate_submission.rs +++ b/validation/src/validate_submission.rs @@ -29,10 +29,16 @@ impl crate::message_handler::MessageHandler{ // log error println!("[validate_submission] Error: {e}"); + self.api.create_submission_audit_error( + submissions_api::types::CreateSubmissionAuditErrorRequest{ + SubmissionID:submission_id, + ErrorMessage:e.to_string(), + } + ).await.map_err(Error::ApiActionSubmissionValidate)?; + // update the submission model status to accepted self.api.action_submission_accepted(submissions_api::types::ActionSubmissionAcceptedRequest{ SubmissionID:submission_id, - ErrorMessage:e.to_string(), }).await.map_err(Error::ApiActionSubmissionValidate)?; }, } -- 2.49.1 From 215c39000bc488d3ea27800baaf5f2d05cb140aa Mon Sep 17 00:00:00 2001 From: Quaternions Date: Fri, 13 Jun 2025 00:15:16 +0000 Subject: [PATCH 5/5] Replace `bypass-submit` with `trigger-submit-unchecked` (#199) Bypassing the submit process means that the map revision is not updated. Change the endpoint and include a flag to skip the map checks but update the revision. Reviewed-on: https://git.itzana.me/StrafesNET/maps-service/pulls/199 Co-authored-by: Quaternions Co-committed-by: Quaternions --- openapi.yaml | 12 +- pkg/api/oas_client_gen.go | 520 ++++++------ pkg/api/oas_handlers_gen.go | 780 +++++++++--------- pkg/api/oas_operations_gen.go | 108 +-- pkg/api/oas_parameters_gen.go | 332 ++++---- pkg/api/oas_response_decoders_gen.go | 240 +++--- pkg/api/oas_response_encoders_gen.go | 28 +- pkg/api/oas_router_gen.go | 196 ++--- pkg/api/oas_schemas_gen.go | 12 +- pkg/api/oas_security_gen.go | 84 +- pkg/api/oas_server_gen.go | 24 +- pkg/api/oas_unimplemented_gen.go | 36 +- pkg/model/nats.go | 6 +- pkg/service/mapfixes.go | 31 +- pkg/service/submissions.go | 27 +- validation/src/check.rs | 33 +- validation/src/nats_types.rs | 2 + .../app/_components/review/ReviewButtons.tsx | 6 +- 18 files changed, 1275 insertions(+), 1202 deletions(-) diff --git a/openapi.yaml b/openapi.yaml index fa1736e..f3008a5 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -421,10 +421,10 @@ paths: application/json: schema: $ref: "#/components/schemas/Error" - /mapfixes/{MapfixID}/status/bypass-submit: + /mapfixes/{MapfixID}/status/trigger-submit-unchecked: post: - summary: Role Reviewer changes status from ChangesRequested -> Submitted - operationId: actionMapfixBypassSubmit + summary: Role Reviewer changes status from ChangesRequested -> Submitting + operationId: actionMapfixTriggerSubmitUnchecked tags: - Mapfixes parameters: @@ -901,10 +901,10 @@ paths: application/json: schema: $ref: "#/components/schemas/Error" - /submissions/{SubmissionID}/status/bypass-submit: + /submissions/{SubmissionID}/status/trigger-submit-unchecked: post: - summary: Role Reviewer changes status from ChangesRequested -> Submitted - operationId: actionSubmissionBypassSubmit + summary: Role Reviewer changes status from ChangesRequested -> Submitting + operationId: actionSubmissionTriggerSubmitUnchecked tags: - Submissions parameters: diff --git a/pkg/api/oas_client_gen.go b/pkg/api/oas_client_gen.go index b5fa438..98464be 100644 --- a/pkg/api/oas_client_gen.go +++ b/pkg/api/oas_client_gen.go @@ -35,12 +35,6 @@ type Invoker interface { // // POST /mapfixes/{MapfixID}/status/reset-validating ActionMapfixAccepted(ctx context.Context, params ActionMapfixAcceptedParams) error - // ActionMapfixBypassSubmit invokes actionMapfixBypassSubmit operation. - // - // Role Reviewer changes status from ChangesRequested -> Submitted. - // - // POST /mapfixes/{MapfixID}/status/bypass-submit - ActionMapfixBypassSubmit(ctx context.Context, params ActionMapfixBypassSubmitParams) error // ActionMapfixReject invokes actionMapfixReject operation. // // Role Reviewer changes status from Submitted -> Rejected. @@ -78,6 +72,12 @@ type Invoker interface { // // POST /mapfixes/{MapfixID}/status/trigger-submit ActionMapfixTriggerSubmit(ctx context.Context, params ActionMapfixTriggerSubmitParams) error + // ActionMapfixTriggerSubmitUnchecked invokes actionMapfixTriggerSubmitUnchecked operation. + // + // Role Reviewer changes status from ChangesRequested -> Submitting. + // + // POST /mapfixes/{MapfixID}/status/trigger-submit-unchecked + ActionMapfixTriggerSubmitUnchecked(ctx context.Context, params ActionMapfixTriggerSubmitUncheckedParams) error // ActionMapfixTriggerUpload invokes actionMapfixTriggerUpload operation. // // Role Admin changes status from Validated -> Uploading. @@ -102,12 +102,6 @@ type Invoker interface { // // POST /submissions/{SubmissionID}/status/reset-validating ActionSubmissionAccepted(ctx context.Context, params ActionSubmissionAcceptedParams) error - // ActionSubmissionBypassSubmit invokes actionSubmissionBypassSubmit operation. - // - // Role Reviewer changes status from ChangesRequested -> Submitted. - // - // POST /submissions/{SubmissionID}/status/bypass-submit - ActionSubmissionBypassSubmit(ctx context.Context, params ActionSubmissionBypassSubmitParams) error // ActionSubmissionReject invokes actionSubmissionReject operation. // // Role Reviewer changes status from Submitted -> Rejected. @@ -145,6 +139,12 @@ type Invoker interface { // // POST /submissions/{SubmissionID}/status/trigger-submit ActionSubmissionTriggerSubmit(ctx context.Context, params ActionSubmissionTriggerSubmitParams) error + // ActionSubmissionTriggerSubmitUnchecked invokes actionSubmissionTriggerSubmitUnchecked operation. + // + // Role Reviewer changes status from ChangesRequested -> Submitting. + // + // POST /submissions/{SubmissionID}/status/trigger-submit-unchecked + ActionSubmissionTriggerSubmitUnchecked(ctx context.Context, params ActionSubmissionTriggerSubmitUncheckedParams) error // ActionSubmissionTriggerUpload invokes actionSubmissionTriggerUpload operation. // // Role Admin changes status from Validated -> Uploading. @@ -530,130 +530,6 @@ func (c *Client) sendActionMapfixAccepted(ctx context.Context, params ActionMapf return result, nil } -// ActionMapfixBypassSubmit invokes actionMapfixBypassSubmit operation. -// -// Role Reviewer changes status from ChangesRequested -> Submitted. -// -// POST /mapfixes/{MapfixID}/status/bypass-submit -func (c *Client) ActionMapfixBypassSubmit(ctx context.Context, params ActionMapfixBypassSubmitParams) error { - _, err := c.sendActionMapfixBypassSubmit(ctx, params) - return err -} - -func (c *Client) sendActionMapfixBypassSubmit(ctx context.Context, params ActionMapfixBypassSubmitParams) (res *ActionMapfixBypassSubmitNoContent, err error) { - otelAttrs := []attribute.KeyValue{ - otelogen.OperationID("actionMapfixBypassSubmit"), - semconv.HTTPRequestMethodKey.String("POST"), - semconv.HTTPRouteKey.String("/mapfixes/{MapfixID}/status/bypass-submit"), - } - - // Run stopwatch. - startTime := time.Now() - defer func() { - // Use floating point division here for higher precision (instead of Millisecond method). - elapsedDuration := time.Since(startTime) - c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) - }() - - // Increment request counter. - c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) - - // Start a span for this request. - ctx, span := c.cfg.Tracer.Start(ctx, ActionMapfixBypassSubmitOperation, - trace.WithAttributes(otelAttrs...), - clientSpanKind, - ) - // Track stage for error reporting. - var stage string - defer func() { - if err != nil { - span.RecordError(err) - span.SetStatus(codes.Error, stage) - c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) - } - span.End() - }() - - stage = "BuildURL" - u := uri.Clone(c.requestURL(ctx)) - var pathParts [3]string - pathParts[0] = "/mapfixes/" - { - // Encode "MapfixID" parameter. - e := uri.NewPathEncoder(uri.PathEncoderConfig{ - Param: "MapfixID", - Style: uri.PathStyleSimple, - Explode: false, - }) - if err := func() error { - return e.EncodeValue(conv.Int64ToString(params.MapfixID)) - }(); err != nil { - return res, errors.Wrap(err, "encode path") - } - encoded, err := e.Result() - if err != nil { - return res, errors.Wrap(err, "encode path") - } - pathParts[1] = encoded - } - pathParts[2] = "/status/bypass-submit" - uri.AddPathParts(u, pathParts[:]...) - - stage = "EncodeRequest" - r, err := ht.NewRequest(ctx, "POST", u) - if err != nil { - return res, errors.Wrap(err, "create request") - } - - { - type bitset = [1]uint8 - var satisfied bitset - { - stage = "Security:CookieAuth" - switch err := c.securityCookieAuth(ctx, ActionMapfixBypassSubmitOperation, r); { - case err == nil: // if NO error - satisfied[0] |= 1 << 0 - case errors.Is(err, ogenerrors.ErrSkipClientSecurity): - // Skip this security. - default: - return res, errors.Wrap(err, "security \"CookieAuth\"") - } - } - - if ok := func() bool { - nextRequirement: - for _, requirement := range []bitset{ - {0b00000001}, - } { - for i, mask := range requirement { - if satisfied[i]&mask != mask { - continue nextRequirement - } - } - return true - } - return false - }(); !ok { - return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied - } - } - - stage = "SendRequest" - resp, err := c.cfg.Client.Do(r) - if err != nil { - return res, errors.Wrap(err, "do request") - } - defer resp.Body.Close() - - stage = "DecodeResponse" - result, err := decodeActionMapfixBypassSubmitResponse(resp) - if err != nil { - return res, errors.Wrap(err, "decode response") - } - - return result, nil -} - // ActionMapfixReject invokes actionMapfixReject operation. // // Role Reviewer changes status from Submitted -> Rejected. @@ -1399,6 +1275,130 @@ func (c *Client) sendActionMapfixTriggerSubmit(ctx context.Context, params Actio return result, nil } +// ActionMapfixTriggerSubmitUnchecked invokes actionMapfixTriggerSubmitUnchecked operation. +// +// Role Reviewer changes status from ChangesRequested -> Submitting. +// +// POST /mapfixes/{MapfixID}/status/trigger-submit-unchecked +func (c *Client) ActionMapfixTriggerSubmitUnchecked(ctx context.Context, params ActionMapfixTriggerSubmitUncheckedParams) error { + _, err := c.sendActionMapfixTriggerSubmitUnchecked(ctx, params) + return err +} + +func (c *Client) sendActionMapfixTriggerSubmitUnchecked(ctx context.Context, params ActionMapfixTriggerSubmitUncheckedParams) (res *ActionMapfixTriggerSubmitUncheckedNoContent, err error) { + otelAttrs := []attribute.KeyValue{ + otelogen.OperationID("actionMapfixTriggerSubmitUnchecked"), + semconv.HTTPRequestMethodKey.String("POST"), + semconv.HTTPRouteKey.String("/mapfixes/{MapfixID}/status/trigger-submit-unchecked"), + } + + // Run stopwatch. + startTime := time.Now() + defer func() { + // Use floating point division here for higher precision (instead of Millisecond method). + elapsedDuration := time.Since(startTime) + c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) + }() + + // Increment request counter. + c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) + + // Start a span for this request. + ctx, span := c.cfg.Tracer.Start(ctx, ActionMapfixTriggerSubmitUncheckedOperation, + trace.WithAttributes(otelAttrs...), + clientSpanKind, + ) + // Track stage for error reporting. + var stage string + defer func() { + if err != nil { + span.RecordError(err) + span.SetStatus(codes.Error, stage) + c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) + } + span.End() + }() + + stage = "BuildURL" + u := uri.Clone(c.requestURL(ctx)) + var pathParts [3]string + pathParts[0] = "/mapfixes/" + { + // Encode "MapfixID" parameter. + e := uri.NewPathEncoder(uri.PathEncoderConfig{ + Param: "MapfixID", + Style: uri.PathStyleSimple, + Explode: false, + }) + if err := func() error { + return e.EncodeValue(conv.Int64ToString(params.MapfixID)) + }(); err != nil { + return res, errors.Wrap(err, "encode path") + } + encoded, err := e.Result() + if err != nil { + return res, errors.Wrap(err, "encode path") + } + pathParts[1] = encoded + } + pathParts[2] = "/status/trigger-submit-unchecked" + uri.AddPathParts(u, pathParts[:]...) + + stage = "EncodeRequest" + r, err := ht.NewRequest(ctx, "POST", u) + if err != nil { + return res, errors.Wrap(err, "create request") + } + + { + type bitset = [1]uint8 + var satisfied bitset + { + stage = "Security:CookieAuth" + switch err := c.securityCookieAuth(ctx, ActionMapfixTriggerSubmitUncheckedOperation, r); { + case err == nil: // if NO error + satisfied[0] |= 1 << 0 + case errors.Is(err, ogenerrors.ErrSkipClientSecurity): + // Skip this security. + default: + return res, errors.Wrap(err, "security \"CookieAuth\"") + } + } + + if ok := func() bool { + nextRequirement: + for _, requirement := range []bitset{ + {0b00000001}, + } { + for i, mask := range requirement { + if satisfied[i]&mask != mask { + continue nextRequirement + } + } + return true + } + return false + }(); !ok { + return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied + } + } + + stage = "SendRequest" + resp, err := c.cfg.Client.Do(r) + if err != nil { + return res, errors.Wrap(err, "do request") + } + defer resp.Body.Close() + + stage = "DecodeResponse" + result, err := decodeActionMapfixTriggerSubmitUncheckedResponse(resp) + if err != nil { + return res, errors.Wrap(err, "decode response") + } + + return result, nil +} + // ActionMapfixTriggerUpload invokes actionMapfixTriggerUpload operation. // // Role Admin changes status from Validated -> Uploading. @@ -1895,130 +1895,6 @@ func (c *Client) sendActionSubmissionAccepted(ctx context.Context, params Action return result, nil } -// ActionSubmissionBypassSubmit invokes actionSubmissionBypassSubmit operation. -// -// Role Reviewer changes status from ChangesRequested -> Submitted. -// -// POST /submissions/{SubmissionID}/status/bypass-submit -func (c *Client) ActionSubmissionBypassSubmit(ctx context.Context, params ActionSubmissionBypassSubmitParams) error { - _, err := c.sendActionSubmissionBypassSubmit(ctx, params) - return err -} - -func (c *Client) sendActionSubmissionBypassSubmit(ctx context.Context, params ActionSubmissionBypassSubmitParams) (res *ActionSubmissionBypassSubmitNoContent, err error) { - otelAttrs := []attribute.KeyValue{ - otelogen.OperationID("actionSubmissionBypassSubmit"), - semconv.HTTPRequestMethodKey.String("POST"), - semconv.HTTPRouteKey.String("/submissions/{SubmissionID}/status/bypass-submit"), - } - - // Run stopwatch. - startTime := time.Now() - defer func() { - // Use floating point division here for higher precision (instead of Millisecond method). - elapsedDuration := time.Since(startTime) - c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) - }() - - // Increment request counter. - c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) - - // Start a span for this request. - ctx, span := c.cfg.Tracer.Start(ctx, ActionSubmissionBypassSubmitOperation, - trace.WithAttributes(otelAttrs...), - clientSpanKind, - ) - // Track stage for error reporting. - var stage string - defer func() { - if err != nil { - span.RecordError(err) - span.SetStatus(codes.Error, stage) - c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) - } - span.End() - }() - - stage = "BuildURL" - u := uri.Clone(c.requestURL(ctx)) - var pathParts [3]string - pathParts[0] = "/submissions/" - { - // Encode "SubmissionID" parameter. - e := uri.NewPathEncoder(uri.PathEncoderConfig{ - Param: "SubmissionID", - Style: uri.PathStyleSimple, - Explode: false, - }) - if err := func() error { - return e.EncodeValue(conv.Int64ToString(params.SubmissionID)) - }(); err != nil { - return res, errors.Wrap(err, "encode path") - } - encoded, err := e.Result() - if err != nil { - return res, errors.Wrap(err, "encode path") - } - pathParts[1] = encoded - } - pathParts[2] = "/status/bypass-submit" - uri.AddPathParts(u, pathParts[:]...) - - stage = "EncodeRequest" - r, err := ht.NewRequest(ctx, "POST", u) - if err != nil { - return res, errors.Wrap(err, "create request") - } - - { - type bitset = [1]uint8 - var satisfied bitset - { - stage = "Security:CookieAuth" - switch err := c.securityCookieAuth(ctx, ActionSubmissionBypassSubmitOperation, r); { - case err == nil: // if NO error - satisfied[0] |= 1 << 0 - case errors.Is(err, ogenerrors.ErrSkipClientSecurity): - // Skip this security. - default: - return res, errors.Wrap(err, "security \"CookieAuth\"") - } - } - - if ok := func() bool { - nextRequirement: - for _, requirement := range []bitset{ - {0b00000001}, - } { - for i, mask := range requirement { - if satisfied[i]&mask != mask { - continue nextRequirement - } - } - return true - } - return false - }(); !ok { - return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied - } - } - - stage = "SendRequest" - resp, err := c.cfg.Client.Do(r) - if err != nil { - return res, errors.Wrap(err, "do request") - } - defer resp.Body.Close() - - stage = "DecodeResponse" - result, err := decodeActionSubmissionBypassSubmitResponse(resp) - if err != nil { - return res, errors.Wrap(err, "decode response") - } - - return result, nil -} - // ActionSubmissionReject invokes actionSubmissionReject operation. // // Role Reviewer changes status from Submitted -> Rejected. @@ -2764,6 +2640,130 @@ func (c *Client) sendActionSubmissionTriggerSubmit(ctx context.Context, params A return result, nil } +// ActionSubmissionTriggerSubmitUnchecked invokes actionSubmissionTriggerSubmitUnchecked operation. +// +// Role Reviewer changes status from ChangesRequested -> Submitting. +// +// POST /submissions/{SubmissionID}/status/trigger-submit-unchecked +func (c *Client) ActionSubmissionTriggerSubmitUnchecked(ctx context.Context, params ActionSubmissionTriggerSubmitUncheckedParams) error { + _, err := c.sendActionSubmissionTriggerSubmitUnchecked(ctx, params) + return err +} + +func (c *Client) sendActionSubmissionTriggerSubmitUnchecked(ctx context.Context, params ActionSubmissionTriggerSubmitUncheckedParams) (res *ActionSubmissionTriggerSubmitUncheckedNoContent, err error) { + otelAttrs := []attribute.KeyValue{ + otelogen.OperationID("actionSubmissionTriggerSubmitUnchecked"), + semconv.HTTPRequestMethodKey.String("POST"), + semconv.HTTPRouteKey.String("/submissions/{SubmissionID}/status/trigger-submit-unchecked"), + } + + // Run stopwatch. + startTime := time.Now() + defer func() { + // Use floating point division here for higher precision (instead of Millisecond method). + elapsedDuration := time.Since(startTime) + c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) + }() + + // Increment request counter. + c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) + + // Start a span for this request. + ctx, span := c.cfg.Tracer.Start(ctx, ActionSubmissionTriggerSubmitUncheckedOperation, + trace.WithAttributes(otelAttrs...), + clientSpanKind, + ) + // Track stage for error reporting. + var stage string + defer func() { + if err != nil { + span.RecordError(err) + span.SetStatus(codes.Error, stage) + c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) + } + span.End() + }() + + stage = "BuildURL" + u := uri.Clone(c.requestURL(ctx)) + var pathParts [3]string + pathParts[0] = "/submissions/" + { + // Encode "SubmissionID" parameter. + e := uri.NewPathEncoder(uri.PathEncoderConfig{ + Param: "SubmissionID", + Style: uri.PathStyleSimple, + Explode: false, + }) + if err := func() error { + return e.EncodeValue(conv.Int64ToString(params.SubmissionID)) + }(); err != nil { + return res, errors.Wrap(err, "encode path") + } + encoded, err := e.Result() + if err != nil { + return res, errors.Wrap(err, "encode path") + } + pathParts[1] = encoded + } + pathParts[2] = "/status/trigger-submit-unchecked" + uri.AddPathParts(u, pathParts[:]...) + + stage = "EncodeRequest" + r, err := ht.NewRequest(ctx, "POST", u) + if err != nil { + return res, errors.Wrap(err, "create request") + } + + { + type bitset = [1]uint8 + var satisfied bitset + { + stage = "Security:CookieAuth" + switch err := c.securityCookieAuth(ctx, ActionSubmissionTriggerSubmitUncheckedOperation, r); { + case err == nil: // if NO error + satisfied[0] |= 1 << 0 + case errors.Is(err, ogenerrors.ErrSkipClientSecurity): + // Skip this security. + default: + return res, errors.Wrap(err, "security \"CookieAuth\"") + } + } + + if ok := func() bool { + nextRequirement: + for _, requirement := range []bitset{ + {0b00000001}, + } { + for i, mask := range requirement { + if satisfied[i]&mask != mask { + continue nextRequirement + } + } + return true + } + return false + }(); !ok { + return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied + } + } + + stage = "SendRequest" + resp, err := c.cfg.Client.Do(r) + if err != nil { + return res, errors.Wrap(err, "do request") + } + defer resp.Body.Close() + + stage = "DecodeResponse" + result, err := decodeActionSubmissionTriggerSubmitUncheckedResponse(resp) + if err != nil { + return res, errors.Wrap(err, "decode response") + } + + return result, nil +} + // ActionSubmissionTriggerUpload invokes actionSubmissionTriggerUpload operation. // // Role Admin changes status from Validated -> Uploading. diff --git a/pkg/api/oas_handlers_gen.go b/pkg/api/oas_handlers_gen.go index a2677d0..aad4887 100644 --- a/pkg/api/oas_handlers_gen.go +++ b/pkg/api/oas_handlers_gen.go @@ -225,201 +225,6 @@ func (s *Server) handleActionMapfixAcceptedRequest(args [1]string, argsEscaped b } } -// handleActionMapfixBypassSubmitRequest handles actionMapfixBypassSubmit operation. -// -// Role Reviewer changes status from ChangesRequested -> Submitted. -// -// POST /mapfixes/{MapfixID}/status/bypass-submit -func (s *Server) handleActionMapfixBypassSubmitRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) { - statusWriter := &codeRecorder{ResponseWriter: w} - w = statusWriter - otelAttrs := []attribute.KeyValue{ - otelogen.OperationID("actionMapfixBypassSubmit"), - semconv.HTTPRequestMethodKey.String("POST"), - semconv.HTTPRouteKey.String("/mapfixes/{MapfixID}/status/bypass-submit"), - } - - // Start a span for this request. - ctx, span := s.cfg.Tracer.Start(r.Context(), ActionMapfixBypassSubmitOperation, - trace.WithAttributes(otelAttrs...), - serverSpanKind, - ) - defer span.End() - - // Add Labeler to context. - labeler := &Labeler{attrs: otelAttrs} - ctx = contextWithLabeler(ctx, labeler) - - // Run stopwatch. - startTime := time.Now() - defer func() { - elapsedDuration := time.Since(startTime) - - attrSet := labeler.AttributeSet() - attrs := attrSet.ToSlice() - code := statusWriter.status - if code != 0 { - codeAttr := semconv.HTTPResponseStatusCode(code) - attrs = append(attrs, codeAttr) - span.SetAttributes(codeAttr) - } - attrOpt := metric.WithAttributes(attrs...) - - // Increment request counter. - s.requests.Add(ctx, 1, attrOpt) - - // Use floating point division here for higher precision (instead of Millisecond method). - s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt) - }() - - var ( - recordError = func(stage string, err error) { - span.RecordError(err) - - // https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status - // Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges, - // unless there was another error (e.g., network error receiving the response body; or 3xx codes with - // max redirects exceeded), in which case status MUST be set to Error. - code := statusWriter.status - if code >= 100 && code < 500 { - span.SetStatus(codes.Error, stage) - } - - attrSet := labeler.AttributeSet() - attrs := attrSet.ToSlice() - if code != 0 { - attrs = append(attrs, semconv.HTTPResponseStatusCode(code)) - } - - s.errors.Add(ctx, 1, metric.WithAttributes(attrs...)) - } - err error - opErrContext = ogenerrors.OperationContext{ - Name: ActionMapfixBypassSubmitOperation, - ID: "actionMapfixBypassSubmit", - } - ) - { - type bitset = [1]uint8 - var satisfied bitset - { - sctx, ok, err := s.securityCookieAuth(ctx, ActionMapfixBypassSubmitOperation, r) - if err != nil { - err = &ogenerrors.SecurityError{ - OperationContext: opErrContext, - Security: "CookieAuth", - Err: err, - } - if encodeErr := encodeErrorResponse(s.h.NewError(ctx, err), w, span); encodeErr != nil { - defer recordError("Security:CookieAuth", err) - } - return - } - if ok { - satisfied[0] |= 1 << 0 - ctx = sctx - } - } - - if ok := func() bool { - nextRequirement: - for _, requirement := range []bitset{ - {0b00000001}, - } { - for i, mask := range requirement { - if satisfied[i]&mask != mask { - continue nextRequirement - } - } - return true - } - return false - }(); !ok { - err = &ogenerrors.SecurityError{ - OperationContext: opErrContext, - Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied, - } - if encodeErr := encodeErrorResponse(s.h.NewError(ctx, err), w, span); encodeErr != nil { - defer recordError("Security", err) - } - return - } - } - params, err := decodeActionMapfixBypassSubmitParams(args, argsEscaped, r) - if err != nil { - err = &ogenerrors.DecodeParamsError{ - OperationContext: opErrContext, - Err: err, - } - defer recordError("DecodeParams", err) - s.cfg.ErrorHandler(ctx, w, r, err) - return - } - - var response *ActionMapfixBypassSubmitNoContent - if m := s.cfg.Middleware; m != nil { - mreq := middleware.Request{ - Context: ctx, - OperationName: ActionMapfixBypassSubmitOperation, - OperationSummary: "Role Reviewer changes status from ChangesRequested -> Submitted", - OperationID: "actionMapfixBypassSubmit", - Body: nil, - Params: middleware.Parameters{ - { - Name: "MapfixID", - In: "path", - }: params.MapfixID, - }, - Raw: r, - } - - type ( - Request = struct{} - Params = ActionMapfixBypassSubmitParams - Response = *ActionMapfixBypassSubmitNoContent - ) - response, err = middleware.HookMiddleware[ - Request, - Params, - Response, - ]( - m, - mreq, - unpackActionMapfixBypassSubmitParams, - func(ctx context.Context, request Request, params Params) (response Response, err error) { - err = s.h.ActionMapfixBypassSubmit(ctx, params) - return response, err - }, - ) - } else { - err = s.h.ActionMapfixBypassSubmit(ctx, params) - } - if err != nil { - if errRes, ok := errors.Into[*ErrorStatusCode](err); ok { - if err := encodeErrorResponse(errRes, w, span); err != nil { - defer recordError("Internal", err) - } - return - } - if errors.Is(err, ht.ErrNotImplemented) { - s.cfg.ErrorHandler(ctx, w, r, err) - return - } - if err := encodeErrorResponse(s.h.NewError(ctx, err), w, span); err != nil { - defer recordError("Internal", err) - } - return - } - - if err := encodeActionMapfixBypassSubmitResponse(response, w, span); err != nil { - defer recordError("EncodeResponse", err) - if !errors.Is(err, ht.ErrInternalServerErrorResponse) { - s.cfg.ErrorHandler(ctx, w, r, err) - } - return - } -} - // handleActionMapfixRejectRequest handles actionMapfixReject operation. // // Role Reviewer changes status from Submitted -> Rejected. @@ -1591,6 +1396,201 @@ func (s *Server) handleActionMapfixTriggerSubmitRequest(args [1]string, argsEsca } } +// handleActionMapfixTriggerSubmitUncheckedRequest handles actionMapfixTriggerSubmitUnchecked operation. +// +// Role Reviewer changes status from ChangesRequested -> Submitting. +// +// POST /mapfixes/{MapfixID}/status/trigger-submit-unchecked +func (s *Server) handleActionMapfixTriggerSubmitUncheckedRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) { + statusWriter := &codeRecorder{ResponseWriter: w} + w = statusWriter + otelAttrs := []attribute.KeyValue{ + otelogen.OperationID("actionMapfixTriggerSubmitUnchecked"), + semconv.HTTPRequestMethodKey.String("POST"), + semconv.HTTPRouteKey.String("/mapfixes/{MapfixID}/status/trigger-submit-unchecked"), + } + + // Start a span for this request. + ctx, span := s.cfg.Tracer.Start(r.Context(), ActionMapfixTriggerSubmitUncheckedOperation, + trace.WithAttributes(otelAttrs...), + serverSpanKind, + ) + defer span.End() + + // Add Labeler to context. + labeler := &Labeler{attrs: otelAttrs} + ctx = contextWithLabeler(ctx, labeler) + + // Run stopwatch. + startTime := time.Now() + defer func() { + elapsedDuration := time.Since(startTime) + + attrSet := labeler.AttributeSet() + attrs := attrSet.ToSlice() + code := statusWriter.status + if code != 0 { + codeAttr := semconv.HTTPResponseStatusCode(code) + attrs = append(attrs, codeAttr) + span.SetAttributes(codeAttr) + } + attrOpt := metric.WithAttributes(attrs...) + + // Increment request counter. + s.requests.Add(ctx, 1, attrOpt) + + // Use floating point division here for higher precision (instead of Millisecond method). + s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt) + }() + + var ( + recordError = func(stage string, err error) { + span.RecordError(err) + + // https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status + // Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges, + // unless there was another error (e.g., network error receiving the response body; or 3xx codes with + // max redirects exceeded), in which case status MUST be set to Error. + code := statusWriter.status + if code >= 100 && code < 500 { + span.SetStatus(codes.Error, stage) + } + + attrSet := labeler.AttributeSet() + attrs := attrSet.ToSlice() + if code != 0 { + attrs = append(attrs, semconv.HTTPResponseStatusCode(code)) + } + + s.errors.Add(ctx, 1, metric.WithAttributes(attrs...)) + } + err error + opErrContext = ogenerrors.OperationContext{ + Name: ActionMapfixTriggerSubmitUncheckedOperation, + ID: "actionMapfixTriggerSubmitUnchecked", + } + ) + { + type bitset = [1]uint8 + var satisfied bitset + { + sctx, ok, err := s.securityCookieAuth(ctx, ActionMapfixTriggerSubmitUncheckedOperation, r) + if err != nil { + err = &ogenerrors.SecurityError{ + OperationContext: opErrContext, + Security: "CookieAuth", + Err: err, + } + if encodeErr := encodeErrorResponse(s.h.NewError(ctx, err), w, span); encodeErr != nil { + defer recordError("Security:CookieAuth", err) + } + return + } + if ok { + satisfied[0] |= 1 << 0 + ctx = sctx + } + } + + if ok := func() bool { + nextRequirement: + for _, requirement := range []bitset{ + {0b00000001}, + } { + for i, mask := range requirement { + if satisfied[i]&mask != mask { + continue nextRequirement + } + } + return true + } + return false + }(); !ok { + err = &ogenerrors.SecurityError{ + OperationContext: opErrContext, + Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied, + } + if encodeErr := encodeErrorResponse(s.h.NewError(ctx, err), w, span); encodeErr != nil { + defer recordError("Security", err) + } + return + } + } + params, err := decodeActionMapfixTriggerSubmitUncheckedParams(args, argsEscaped, r) + if err != nil { + err = &ogenerrors.DecodeParamsError{ + OperationContext: opErrContext, + Err: err, + } + defer recordError("DecodeParams", err) + s.cfg.ErrorHandler(ctx, w, r, err) + return + } + + var response *ActionMapfixTriggerSubmitUncheckedNoContent + if m := s.cfg.Middleware; m != nil { + mreq := middleware.Request{ + Context: ctx, + OperationName: ActionMapfixTriggerSubmitUncheckedOperation, + OperationSummary: "Role Reviewer changes status from ChangesRequested -> Submitting", + OperationID: "actionMapfixTriggerSubmitUnchecked", + Body: nil, + Params: middleware.Parameters{ + { + Name: "MapfixID", + In: "path", + }: params.MapfixID, + }, + Raw: r, + } + + type ( + Request = struct{} + Params = ActionMapfixTriggerSubmitUncheckedParams + Response = *ActionMapfixTriggerSubmitUncheckedNoContent + ) + response, err = middleware.HookMiddleware[ + Request, + Params, + Response, + ]( + m, + mreq, + unpackActionMapfixTriggerSubmitUncheckedParams, + func(ctx context.Context, request Request, params Params) (response Response, err error) { + err = s.h.ActionMapfixTriggerSubmitUnchecked(ctx, params) + return response, err + }, + ) + } else { + err = s.h.ActionMapfixTriggerSubmitUnchecked(ctx, params) + } + if err != nil { + if errRes, ok := errors.Into[*ErrorStatusCode](err); ok { + if err := encodeErrorResponse(errRes, w, span); err != nil { + defer recordError("Internal", err) + } + return + } + if errors.Is(err, ht.ErrNotImplemented) { + s.cfg.ErrorHandler(ctx, w, r, err) + return + } + if err := encodeErrorResponse(s.h.NewError(ctx, err), w, span); err != nil { + defer recordError("Internal", err) + } + return + } + + if err := encodeActionMapfixTriggerSubmitUncheckedResponse(response, w, span); err != nil { + defer recordError("EncodeResponse", err) + if !errors.Is(err, ht.ErrInternalServerErrorResponse) { + s.cfg.ErrorHandler(ctx, w, r, err) + } + return + } +} + // handleActionMapfixTriggerUploadRequest handles actionMapfixTriggerUpload operation. // // Role Admin changes status from Validated -> Uploading. @@ -2371,201 +2371,6 @@ func (s *Server) handleActionSubmissionAcceptedRequest(args [1]string, argsEscap } } -// handleActionSubmissionBypassSubmitRequest handles actionSubmissionBypassSubmit operation. -// -// Role Reviewer changes status from ChangesRequested -> Submitted. -// -// POST /submissions/{SubmissionID}/status/bypass-submit -func (s *Server) handleActionSubmissionBypassSubmitRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) { - statusWriter := &codeRecorder{ResponseWriter: w} - w = statusWriter - otelAttrs := []attribute.KeyValue{ - otelogen.OperationID("actionSubmissionBypassSubmit"), - semconv.HTTPRequestMethodKey.String("POST"), - semconv.HTTPRouteKey.String("/submissions/{SubmissionID}/status/bypass-submit"), - } - - // Start a span for this request. - ctx, span := s.cfg.Tracer.Start(r.Context(), ActionSubmissionBypassSubmitOperation, - trace.WithAttributes(otelAttrs...), - serverSpanKind, - ) - defer span.End() - - // Add Labeler to context. - labeler := &Labeler{attrs: otelAttrs} - ctx = contextWithLabeler(ctx, labeler) - - // Run stopwatch. - startTime := time.Now() - defer func() { - elapsedDuration := time.Since(startTime) - - attrSet := labeler.AttributeSet() - attrs := attrSet.ToSlice() - code := statusWriter.status - if code != 0 { - codeAttr := semconv.HTTPResponseStatusCode(code) - attrs = append(attrs, codeAttr) - span.SetAttributes(codeAttr) - } - attrOpt := metric.WithAttributes(attrs...) - - // Increment request counter. - s.requests.Add(ctx, 1, attrOpt) - - // Use floating point division here for higher precision (instead of Millisecond method). - s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt) - }() - - var ( - recordError = func(stage string, err error) { - span.RecordError(err) - - // https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status - // Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges, - // unless there was another error (e.g., network error receiving the response body; or 3xx codes with - // max redirects exceeded), in which case status MUST be set to Error. - code := statusWriter.status - if code >= 100 && code < 500 { - span.SetStatus(codes.Error, stage) - } - - attrSet := labeler.AttributeSet() - attrs := attrSet.ToSlice() - if code != 0 { - attrs = append(attrs, semconv.HTTPResponseStatusCode(code)) - } - - s.errors.Add(ctx, 1, metric.WithAttributes(attrs...)) - } - err error - opErrContext = ogenerrors.OperationContext{ - Name: ActionSubmissionBypassSubmitOperation, - ID: "actionSubmissionBypassSubmit", - } - ) - { - type bitset = [1]uint8 - var satisfied bitset - { - sctx, ok, err := s.securityCookieAuth(ctx, ActionSubmissionBypassSubmitOperation, r) - if err != nil { - err = &ogenerrors.SecurityError{ - OperationContext: opErrContext, - Security: "CookieAuth", - Err: err, - } - if encodeErr := encodeErrorResponse(s.h.NewError(ctx, err), w, span); encodeErr != nil { - defer recordError("Security:CookieAuth", err) - } - return - } - if ok { - satisfied[0] |= 1 << 0 - ctx = sctx - } - } - - if ok := func() bool { - nextRequirement: - for _, requirement := range []bitset{ - {0b00000001}, - } { - for i, mask := range requirement { - if satisfied[i]&mask != mask { - continue nextRequirement - } - } - return true - } - return false - }(); !ok { - err = &ogenerrors.SecurityError{ - OperationContext: opErrContext, - Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied, - } - if encodeErr := encodeErrorResponse(s.h.NewError(ctx, err), w, span); encodeErr != nil { - defer recordError("Security", err) - } - return - } - } - params, err := decodeActionSubmissionBypassSubmitParams(args, argsEscaped, r) - if err != nil { - err = &ogenerrors.DecodeParamsError{ - OperationContext: opErrContext, - Err: err, - } - defer recordError("DecodeParams", err) - s.cfg.ErrorHandler(ctx, w, r, err) - return - } - - var response *ActionSubmissionBypassSubmitNoContent - if m := s.cfg.Middleware; m != nil { - mreq := middleware.Request{ - Context: ctx, - OperationName: ActionSubmissionBypassSubmitOperation, - OperationSummary: "Role Reviewer changes status from ChangesRequested -> Submitted", - OperationID: "actionSubmissionBypassSubmit", - Body: nil, - Params: middleware.Parameters{ - { - Name: "SubmissionID", - In: "path", - }: params.SubmissionID, - }, - Raw: r, - } - - type ( - Request = struct{} - Params = ActionSubmissionBypassSubmitParams - Response = *ActionSubmissionBypassSubmitNoContent - ) - response, err = middleware.HookMiddleware[ - Request, - Params, - Response, - ]( - m, - mreq, - unpackActionSubmissionBypassSubmitParams, - func(ctx context.Context, request Request, params Params) (response Response, err error) { - err = s.h.ActionSubmissionBypassSubmit(ctx, params) - return response, err - }, - ) - } else { - err = s.h.ActionSubmissionBypassSubmit(ctx, params) - } - if err != nil { - if errRes, ok := errors.Into[*ErrorStatusCode](err); ok { - if err := encodeErrorResponse(errRes, w, span); err != nil { - defer recordError("Internal", err) - } - return - } - if errors.Is(err, ht.ErrNotImplemented) { - s.cfg.ErrorHandler(ctx, w, r, err) - return - } - if err := encodeErrorResponse(s.h.NewError(ctx, err), w, span); err != nil { - defer recordError("Internal", err) - } - return - } - - if err := encodeActionSubmissionBypassSubmitResponse(response, w, span); err != nil { - defer recordError("EncodeResponse", err) - if !errors.Is(err, ht.ErrInternalServerErrorResponse) { - s.cfg.ErrorHandler(ctx, w, r, err) - } - return - } -} - // handleActionSubmissionRejectRequest handles actionSubmissionReject operation. // // Role Reviewer changes status from Submitted -> Rejected. @@ -3737,6 +3542,201 @@ func (s *Server) handleActionSubmissionTriggerSubmitRequest(args [1]string, args } } +// handleActionSubmissionTriggerSubmitUncheckedRequest handles actionSubmissionTriggerSubmitUnchecked operation. +// +// Role Reviewer changes status from ChangesRequested -> Submitting. +// +// POST /submissions/{SubmissionID}/status/trigger-submit-unchecked +func (s *Server) handleActionSubmissionTriggerSubmitUncheckedRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) { + statusWriter := &codeRecorder{ResponseWriter: w} + w = statusWriter + otelAttrs := []attribute.KeyValue{ + otelogen.OperationID("actionSubmissionTriggerSubmitUnchecked"), + semconv.HTTPRequestMethodKey.String("POST"), + semconv.HTTPRouteKey.String("/submissions/{SubmissionID}/status/trigger-submit-unchecked"), + } + + // Start a span for this request. + ctx, span := s.cfg.Tracer.Start(r.Context(), ActionSubmissionTriggerSubmitUncheckedOperation, + trace.WithAttributes(otelAttrs...), + serverSpanKind, + ) + defer span.End() + + // Add Labeler to context. + labeler := &Labeler{attrs: otelAttrs} + ctx = contextWithLabeler(ctx, labeler) + + // Run stopwatch. + startTime := time.Now() + defer func() { + elapsedDuration := time.Since(startTime) + + attrSet := labeler.AttributeSet() + attrs := attrSet.ToSlice() + code := statusWriter.status + if code != 0 { + codeAttr := semconv.HTTPResponseStatusCode(code) + attrs = append(attrs, codeAttr) + span.SetAttributes(codeAttr) + } + attrOpt := metric.WithAttributes(attrs...) + + // Increment request counter. + s.requests.Add(ctx, 1, attrOpt) + + // Use floating point division here for higher precision (instead of Millisecond method). + s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt) + }() + + var ( + recordError = func(stage string, err error) { + span.RecordError(err) + + // https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status + // Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges, + // unless there was another error (e.g., network error receiving the response body; or 3xx codes with + // max redirects exceeded), in which case status MUST be set to Error. + code := statusWriter.status + if code >= 100 && code < 500 { + span.SetStatus(codes.Error, stage) + } + + attrSet := labeler.AttributeSet() + attrs := attrSet.ToSlice() + if code != 0 { + attrs = append(attrs, semconv.HTTPResponseStatusCode(code)) + } + + s.errors.Add(ctx, 1, metric.WithAttributes(attrs...)) + } + err error + opErrContext = ogenerrors.OperationContext{ + Name: ActionSubmissionTriggerSubmitUncheckedOperation, + ID: "actionSubmissionTriggerSubmitUnchecked", + } + ) + { + type bitset = [1]uint8 + var satisfied bitset + { + sctx, ok, err := s.securityCookieAuth(ctx, ActionSubmissionTriggerSubmitUncheckedOperation, r) + if err != nil { + err = &ogenerrors.SecurityError{ + OperationContext: opErrContext, + Security: "CookieAuth", + Err: err, + } + if encodeErr := encodeErrorResponse(s.h.NewError(ctx, err), w, span); encodeErr != nil { + defer recordError("Security:CookieAuth", err) + } + return + } + if ok { + satisfied[0] |= 1 << 0 + ctx = sctx + } + } + + if ok := func() bool { + nextRequirement: + for _, requirement := range []bitset{ + {0b00000001}, + } { + for i, mask := range requirement { + if satisfied[i]&mask != mask { + continue nextRequirement + } + } + return true + } + return false + }(); !ok { + err = &ogenerrors.SecurityError{ + OperationContext: opErrContext, + Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied, + } + if encodeErr := encodeErrorResponse(s.h.NewError(ctx, err), w, span); encodeErr != nil { + defer recordError("Security", err) + } + return + } + } + params, err := decodeActionSubmissionTriggerSubmitUncheckedParams(args, argsEscaped, r) + if err != nil { + err = &ogenerrors.DecodeParamsError{ + OperationContext: opErrContext, + Err: err, + } + defer recordError("DecodeParams", err) + s.cfg.ErrorHandler(ctx, w, r, err) + return + } + + var response *ActionSubmissionTriggerSubmitUncheckedNoContent + if m := s.cfg.Middleware; m != nil { + mreq := middleware.Request{ + Context: ctx, + OperationName: ActionSubmissionTriggerSubmitUncheckedOperation, + OperationSummary: "Role Reviewer changes status from ChangesRequested -> Submitting", + OperationID: "actionSubmissionTriggerSubmitUnchecked", + Body: nil, + Params: middleware.Parameters{ + { + Name: "SubmissionID", + In: "path", + }: params.SubmissionID, + }, + Raw: r, + } + + type ( + Request = struct{} + Params = ActionSubmissionTriggerSubmitUncheckedParams + Response = *ActionSubmissionTriggerSubmitUncheckedNoContent + ) + response, err = middleware.HookMiddleware[ + Request, + Params, + Response, + ]( + m, + mreq, + unpackActionSubmissionTriggerSubmitUncheckedParams, + func(ctx context.Context, request Request, params Params) (response Response, err error) { + err = s.h.ActionSubmissionTriggerSubmitUnchecked(ctx, params) + return response, err + }, + ) + } else { + err = s.h.ActionSubmissionTriggerSubmitUnchecked(ctx, params) + } + if err != nil { + if errRes, ok := errors.Into[*ErrorStatusCode](err); ok { + if err := encodeErrorResponse(errRes, w, span); err != nil { + defer recordError("Internal", err) + } + return + } + if errors.Is(err, ht.ErrNotImplemented) { + s.cfg.ErrorHandler(ctx, w, r, err) + return + } + if err := encodeErrorResponse(s.h.NewError(ctx, err), w, span); err != nil { + defer recordError("Internal", err) + } + return + } + + if err := encodeActionSubmissionTriggerSubmitUncheckedResponse(response, w, span); err != nil { + defer recordError("EncodeResponse", err) + if !errors.Is(err, ht.ErrInternalServerErrorResponse) { + s.cfg.ErrorHandler(ctx, w, r, err) + } + return + } +} + // handleActionSubmissionTriggerUploadRequest handles actionSubmissionTriggerUpload operation. // // Role Admin changes status from Validated -> Uploading. diff --git a/pkg/api/oas_operations_gen.go b/pkg/api/oas_operations_gen.go index 0ed67d8..80ed8f5 100644 --- a/pkg/api/oas_operations_gen.go +++ b/pkg/api/oas_operations_gen.go @@ -6,58 +6,58 @@ package api type OperationName = string const ( - ActionMapfixAcceptedOperation OperationName = "ActionMapfixAccepted" - ActionMapfixBypassSubmitOperation OperationName = "ActionMapfixBypassSubmit" - ActionMapfixRejectOperation OperationName = "ActionMapfixReject" - ActionMapfixRequestChangesOperation OperationName = "ActionMapfixRequestChanges" - ActionMapfixResetSubmittingOperation OperationName = "ActionMapfixResetSubmitting" - ActionMapfixRetryValidateOperation OperationName = "ActionMapfixRetryValidate" - ActionMapfixRevokeOperation OperationName = "ActionMapfixRevoke" - ActionMapfixTriggerSubmitOperation OperationName = "ActionMapfixTriggerSubmit" - ActionMapfixTriggerUploadOperation OperationName = "ActionMapfixTriggerUpload" - ActionMapfixTriggerValidateOperation OperationName = "ActionMapfixTriggerValidate" - ActionMapfixValidatedOperation OperationName = "ActionMapfixValidated" - ActionSubmissionAcceptedOperation OperationName = "ActionSubmissionAccepted" - ActionSubmissionBypassSubmitOperation OperationName = "ActionSubmissionBypassSubmit" - ActionSubmissionRejectOperation OperationName = "ActionSubmissionReject" - ActionSubmissionRequestChangesOperation OperationName = "ActionSubmissionRequestChanges" - ActionSubmissionResetSubmittingOperation OperationName = "ActionSubmissionResetSubmitting" - ActionSubmissionRetryValidateOperation OperationName = "ActionSubmissionRetryValidate" - ActionSubmissionRevokeOperation OperationName = "ActionSubmissionRevoke" - ActionSubmissionTriggerSubmitOperation OperationName = "ActionSubmissionTriggerSubmit" - ActionSubmissionTriggerUploadOperation OperationName = "ActionSubmissionTriggerUpload" - ActionSubmissionTriggerValidateOperation OperationName = "ActionSubmissionTriggerValidate" - ActionSubmissionValidatedOperation OperationName = "ActionSubmissionValidated" - CreateMapfixOperation OperationName = "CreateMapfix" - CreateMapfixAuditCommentOperation OperationName = "CreateMapfixAuditComment" - CreateScriptOperation OperationName = "CreateScript" - CreateScriptPolicyOperation OperationName = "CreateScriptPolicy" - CreateSubmissionOperation OperationName = "CreateSubmission" - CreateSubmissionAdminOperation OperationName = "CreateSubmissionAdmin" - CreateSubmissionAuditCommentOperation OperationName = "CreateSubmissionAuditComment" - DeleteScriptOperation OperationName = "DeleteScript" - DeleteScriptPolicyOperation OperationName = "DeleteScriptPolicy" - GetMapOperation OperationName = "GetMap" - GetMapfixOperation OperationName = "GetMapfix" - GetOperationOperation OperationName = "GetOperation" - GetScriptOperation OperationName = "GetScript" - GetScriptPolicyOperation OperationName = "GetScriptPolicy" - GetSubmissionOperation OperationName = "GetSubmission" - ListMapfixAuditEventsOperation OperationName = "ListMapfixAuditEvents" - ListMapfixesOperation OperationName = "ListMapfixes" - ListMapsOperation OperationName = "ListMaps" - ListScriptPolicyOperation OperationName = "ListScriptPolicy" - ListScriptsOperation OperationName = "ListScripts" - ListSubmissionAuditEventsOperation OperationName = "ListSubmissionAuditEvents" - ListSubmissionsOperation OperationName = "ListSubmissions" - ReleaseSubmissionsOperation OperationName = "ReleaseSubmissions" - SessionRolesOperation OperationName = "SessionRoles" - SessionUserOperation OperationName = "SessionUser" - SessionValidateOperation OperationName = "SessionValidate" - SetMapfixCompletedOperation OperationName = "SetMapfixCompleted" - SetSubmissionCompletedOperation OperationName = "SetSubmissionCompleted" - UpdateMapfixModelOperation OperationName = "UpdateMapfixModel" - UpdateScriptOperation OperationName = "UpdateScript" - UpdateScriptPolicyOperation OperationName = "UpdateScriptPolicy" - UpdateSubmissionModelOperation OperationName = "UpdateSubmissionModel" + ActionMapfixAcceptedOperation OperationName = "ActionMapfixAccepted" + ActionMapfixRejectOperation OperationName = "ActionMapfixReject" + ActionMapfixRequestChangesOperation OperationName = "ActionMapfixRequestChanges" + ActionMapfixResetSubmittingOperation OperationName = "ActionMapfixResetSubmitting" + ActionMapfixRetryValidateOperation OperationName = "ActionMapfixRetryValidate" + ActionMapfixRevokeOperation OperationName = "ActionMapfixRevoke" + ActionMapfixTriggerSubmitOperation OperationName = "ActionMapfixTriggerSubmit" + ActionMapfixTriggerSubmitUncheckedOperation OperationName = "ActionMapfixTriggerSubmitUnchecked" + ActionMapfixTriggerUploadOperation OperationName = "ActionMapfixTriggerUpload" + ActionMapfixTriggerValidateOperation OperationName = "ActionMapfixTriggerValidate" + ActionMapfixValidatedOperation OperationName = "ActionMapfixValidated" + ActionSubmissionAcceptedOperation OperationName = "ActionSubmissionAccepted" + ActionSubmissionRejectOperation OperationName = "ActionSubmissionReject" + ActionSubmissionRequestChangesOperation OperationName = "ActionSubmissionRequestChanges" + ActionSubmissionResetSubmittingOperation OperationName = "ActionSubmissionResetSubmitting" + ActionSubmissionRetryValidateOperation OperationName = "ActionSubmissionRetryValidate" + ActionSubmissionRevokeOperation OperationName = "ActionSubmissionRevoke" + ActionSubmissionTriggerSubmitOperation OperationName = "ActionSubmissionTriggerSubmit" + ActionSubmissionTriggerSubmitUncheckedOperation OperationName = "ActionSubmissionTriggerSubmitUnchecked" + ActionSubmissionTriggerUploadOperation OperationName = "ActionSubmissionTriggerUpload" + ActionSubmissionTriggerValidateOperation OperationName = "ActionSubmissionTriggerValidate" + ActionSubmissionValidatedOperation OperationName = "ActionSubmissionValidated" + CreateMapfixOperation OperationName = "CreateMapfix" + CreateMapfixAuditCommentOperation OperationName = "CreateMapfixAuditComment" + CreateScriptOperation OperationName = "CreateScript" + CreateScriptPolicyOperation OperationName = "CreateScriptPolicy" + CreateSubmissionOperation OperationName = "CreateSubmission" + CreateSubmissionAdminOperation OperationName = "CreateSubmissionAdmin" + CreateSubmissionAuditCommentOperation OperationName = "CreateSubmissionAuditComment" + DeleteScriptOperation OperationName = "DeleteScript" + DeleteScriptPolicyOperation OperationName = "DeleteScriptPolicy" + GetMapOperation OperationName = "GetMap" + GetMapfixOperation OperationName = "GetMapfix" + GetOperationOperation OperationName = "GetOperation" + GetScriptOperation OperationName = "GetScript" + GetScriptPolicyOperation OperationName = "GetScriptPolicy" + GetSubmissionOperation OperationName = "GetSubmission" + ListMapfixAuditEventsOperation OperationName = "ListMapfixAuditEvents" + ListMapfixesOperation OperationName = "ListMapfixes" + ListMapsOperation OperationName = "ListMaps" + ListScriptPolicyOperation OperationName = "ListScriptPolicy" + ListScriptsOperation OperationName = "ListScripts" + ListSubmissionAuditEventsOperation OperationName = "ListSubmissionAuditEvents" + ListSubmissionsOperation OperationName = "ListSubmissions" + ReleaseSubmissionsOperation OperationName = "ReleaseSubmissions" + SessionRolesOperation OperationName = "SessionRoles" + SessionUserOperation OperationName = "SessionUser" + SessionValidateOperation OperationName = "SessionValidate" + SetMapfixCompletedOperation OperationName = "SetMapfixCompleted" + SetSubmissionCompletedOperation OperationName = "SetSubmissionCompleted" + UpdateMapfixModelOperation OperationName = "UpdateMapfixModel" + UpdateScriptOperation OperationName = "UpdateScript" + UpdateScriptPolicyOperation OperationName = "UpdateScriptPolicy" + UpdateSubmissionModelOperation OperationName = "UpdateSubmissionModel" ) diff --git a/pkg/api/oas_parameters_gen.go b/pkg/api/oas_parameters_gen.go index 262f791..df865e0 100644 --- a/pkg/api/oas_parameters_gen.go +++ b/pkg/api/oas_parameters_gen.go @@ -98,89 +98,6 @@ func decodeActionMapfixAcceptedParams(args [1]string, argsEscaped bool, r *http. return params, nil } -// ActionMapfixBypassSubmitParams is parameters of actionMapfixBypassSubmit operation. -type ActionMapfixBypassSubmitParams struct { - // The unique identifier for a mapfix. - MapfixID int64 -} - -func unpackActionMapfixBypassSubmitParams(packed middleware.Parameters) (params ActionMapfixBypassSubmitParams) { - { - key := middleware.ParameterKey{ - Name: "MapfixID", - In: "path", - } - params.MapfixID = packed[key].(int64) - } - return params -} - -func decodeActionMapfixBypassSubmitParams(args [1]string, argsEscaped bool, r *http.Request) (params ActionMapfixBypassSubmitParams, _ error) { - // Decode path: MapfixID. - if err := func() error { - param := args[0] - if argsEscaped { - unescaped, err := url.PathUnescape(args[0]) - if err != nil { - return errors.Wrap(err, "unescape path") - } - param = unescaped - } - if len(param) > 0 { - d := uri.NewPathDecoder(uri.PathDecoderConfig{ - Param: "MapfixID", - Value: param, - Style: uri.PathStyleSimple, - Explode: false, - }) - - if err := func() error { - val, err := d.DecodeValue() - if err != nil { - return err - } - - c, err := conv.ToInt64(val) - if err != nil { - return err - } - - params.MapfixID = c - return nil - }(); err != nil { - return err - } - if err := func() error { - if err := (validate.Int{ - MinSet: true, - Min: 0, - MaxSet: false, - Max: 0, - MinExclusive: false, - MaxExclusive: false, - MultipleOfSet: false, - MultipleOf: 0, - }).Validate(int64(params.MapfixID)); err != nil { - return errors.Wrap(err, "int") - } - return nil - }(); err != nil { - return err - } - } else { - return validate.ErrFieldRequired - } - return nil - }(); err != nil { - return params, &ogenerrors.DecodeParamError{ - Name: "MapfixID", - In: "path", - Err: err, - } - } - return params, nil -} - // ActionMapfixRejectParams is parameters of actionMapfixReject operation. type ActionMapfixRejectParams struct { // The unique identifier for a mapfix. @@ -679,6 +596,89 @@ func decodeActionMapfixTriggerSubmitParams(args [1]string, argsEscaped bool, r * return params, nil } +// ActionMapfixTriggerSubmitUncheckedParams is parameters of actionMapfixTriggerSubmitUnchecked operation. +type ActionMapfixTriggerSubmitUncheckedParams struct { + // The unique identifier for a mapfix. + MapfixID int64 +} + +func unpackActionMapfixTriggerSubmitUncheckedParams(packed middleware.Parameters) (params ActionMapfixTriggerSubmitUncheckedParams) { + { + key := middleware.ParameterKey{ + Name: "MapfixID", + In: "path", + } + params.MapfixID = packed[key].(int64) + } + return params +} + +func decodeActionMapfixTriggerSubmitUncheckedParams(args [1]string, argsEscaped bool, r *http.Request) (params ActionMapfixTriggerSubmitUncheckedParams, _ error) { + // Decode path: MapfixID. + if err := func() error { + param := args[0] + if argsEscaped { + unescaped, err := url.PathUnescape(args[0]) + if err != nil { + return errors.Wrap(err, "unescape path") + } + param = unescaped + } + if len(param) > 0 { + d := uri.NewPathDecoder(uri.PathDecoderConfig{ + Param: "MapfixID", + Value: param, + Style: uri.PathStyleSimple, + Explode: false, + }) + + if err := func() error { + val, err := d.DecodeValue() + if err != nil { + return err + } + + c, err := conv.ToInt64(val) + if err != nil { + return err + } + + params.MapfixID = c + return nil + }(); err != nil { + return err + } + if err := func() error { + if err := (validate.Int{ + MinSet: true, + Min: 0, + MaxSet: false, + Max: 0, + MinExclusive: false, + MaxExclusive: false, + MultipleOfSet: false, + MultipleOf: 0, + }).Validate(int64(params.MapfixID)); err != nil { + return errors.Wrap(err, "int") + } + return nil + }(); err != nil { + return err + } + } else { + return validate.ErrFieldRequired + } + return nil + }(); err != nil { + return params, &ogenerrors.DecodeParamError{ + Name: "MapfixID", + In: "path", + Err: err, + } + } + return params, nil +} + // ActionMapfixTriggerUploadParams is parameters of actionMapfixTriggerUpload operation. type ActionMapfixTriggerUploadParams struct { // The unique identifier for a mapfix. @@ -1011,89 +1011,6 @@ func decodeActionSubmissionAcceptedParams(args [1]string, argsEscaped bool, r *h return params, nil } -// ActionSubmissionBypassSubmitParams is parameters of actionSubmissionBypassSubmit operation. -type ActionSubmissionBypassSubmitParams struct { - // The unique identifier for a submission. - SubmissionID int64 -} - -func unpackActionSubmissionBypassSubmitParams(packed middleware.Parameters) (params ActionSubmissionBypassSubmitParams) { - { - key := middleware.ParameterKey{ - Name: "SubmissionID", - In: "path", - } - params.SubmissionID = packed[key].(int64) - } - return params -} - -func decodeActionSubmissionBypassSubmitParams(args [1]string, argsEscaped bool, r *http.Request) (params ActionSubmissionBypassSubmitParams, _ error) { - // Decode path: SubmissionID. - if err := func() error { - param := args[0] - if argsEscaped { - unescaped, err := url.PathUnescape(args[0]) - if err != nil { - return errors.Wrap(err, "unescape path") - } - param = unescaped - } - if len(param) > 0 { - d := uri.NewPathDecoder(uri.PathDecoderConfig{ - Param: "SubmissionID", - Value: param, - Style: uri.PathStyleSimple, - Explode: false, - }) - - if err := func() error { - val, err := d.DecodeValue() - if err != nil { - return err - } - - c, err := conv.ToInt64(val) - if err != nil { - return err - } - - params.SubmissionID = c - return nil - }(); err != nil { - return err - } - if err := func() error { - if err := (validate.Int{ - MinSet: true, - Min: 0, - MaxSet: false, - Max: 0, - MinExclusive: false, - MaxExclusive: false, - MultipleOfSet: false, - MultipleOf: 0, - }).Validate(int64(params.SubmissionID)); err != nil { - return errors.Wrap(err, "int") - } - return nil - }(); err != nil { - return err - } - } else { - return validate.ErrFieldRequired - } - return nil - }(); err != nil { - return params, &ogenerrors.DecodeParamError{ - Name: "SubmissionID", - In: "path", - Err: err, - } - } - return params, nil -} - // ActionSubmissionRejectParams is parameters of actionSubmissionReject operation. type ActionSubmissionRejectParams struct { // The unique identifier for a submission. @@ -1592,6 +1509,89 @@ func decodeActionSubmissionTriggerSubmitParams(args [1]string, argsEscaped bool, return params, nil } +// ActionSubmissionTriggerSubmitUncheckedParams is parameters of actionSubmissionTriggerSubmitUnchecked operation. +type ActionSubmissionTriggerSubmitUncheckedParams struct { + // The unique identifier for a submission. + SubmissionID int64 +} + +func unpackActionSubmissionTriggerSubmitUncheckedParams(packed middleware.Parameters) (params ActionSubmissionTriggerSubmitUncheckedParams) { + { + key := middleware.ParameterKey{ + Name: "SubmissionID", + In: "path", + } + params.SubmissionID = packed[key].(int64) + } + return params +} + +func decodeActionSubmissionTriggerSubmitUncheckedParams(args [1]string, argsEscaped bool, r *http.Request) (params ActionSubmissionTriggerSubmitUncheckedParams, _ error) { + // Decode path: SubmissionID. + if err := func() error { + param := args[0] + if argsEscaped { + unescaped, err := url.PathUnescape(args[0]) + if err != nil { + return errors.Wrap(err, "unescape path") + } + param = unescaped + } + if len(param) > 0 { + d := uri.NewPathDecoder(uri.PathDecoderConfig{ + Param: "SubmissionID", + Value: param, + Style: uri.PathStyleSimple, + Explode: false, + }) + + if err := func() error { + val, err := d.DecodeValue() + if err != nil { + return err + } + + c, err := conv.ToInt64(val) + if err != nil { + return err + } + + params.SubmissionID = c + return nil + }(); err != nil { + return err + } + if err := func() error { + if err := (validate.Int{ + MinSet: true, + Min: 0, + MaxSet: false, + Max: 0, + MinExclusive: false, + MaxExclusive: false, + MultipleOfSet: false, + MultipleOf: 0, + }).Validate(int64(params.SubmissionID)); err != nil { + return errors.Wrap(err, "int") + } + return nil + }(); err != nil { + return err + } + } else { + return validate.ErrFieldRequired + } + return nil + }(); err != nil { + return params, &ogenerrors.DecodeParamError{ + Name: "SubmissionID", + In: "path", + Err: err, + } + } + return params, nil +} + // ActionSubmissionTriggerUploadParams is parameters of actionSubmissionTriggerUpload operation. type ActionSubmissionTriggerUploadParams struct { // The unique identifier for a submission. diff --git a/pkg/api/oas_response_decoders_gen.go b/pkg/api/oas_response_decoders_gen.go index f1227af..4270eb1 100644 --- a/pkg/api/oas_response_decoders_gen.go +++ b/pkg/api/oas_response_decoders_gen.go @@ -75,66 +75,6 @@ func decodeActionMapfixAcceptedResponse(resp *http.Response) (res *ActionMapfixA return res, errors.Wrap(defRes, "error") } -func decodeActionMapfixBypassSubmitResponse(resp *http.Response) (res *ActionMapfixBypassSubmitNoContent, _ error) { - switch resp.StatusCode { - case 204: - // Code 204. - return &ActionMapfixBypassSubmitNoContent{}, nil - } - // Convenient error response. - defRes, err := func() (res *ErrorStatusCode, err error) { - ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type")) - if err != nil { - return res, errors.Wrap(err, "parse media type") - } - switch { - case ct == "application/json": - buf, err := io.ReadAll(resp.Body) - if err != nil { - return res, err - } - d := jx.DecodeBytes(buf) - - var response Error - if err := func() error { - if err := response.Decode(d); err != nil { - return err - } - if err := d.Skip(); err != io.EOF { - return errors.New("unexpected trailing data") - } - return nil - }(); err != nil { - err = &ogenerrors.DecodeBodyError{ - ContentType: ct, - Body: buf, - Err: err, - } - return res, err - } - // Validate response. - if err := func() error { - if err := response.Validate(); err != nil { - return err - } - return nil - }(); err != nil { - return res, errors.Wrap(err, "validate") - } - return &ErrorStatusCode{ - StatusCode: resp.StatusCode, - Response: response, - }, nil - default: - return res, validate.InvalidContentType(ct) - } - }() - if err != nil { - return res, errors.Wrapf(err, "default (code %d)", resp.StatusCode) - } - return res, errors.Wrap(defRes, "error") -} - func decodeActionMapfixRejectResponse(resp *http.Response) (res *ActionMapfixRejectNoContent, _ error) { switch resp.StatusCode { case 204: @@ -495,6 +435,66 @@ func decodeActionMapfixTriggerSubmitResponse(resp *http.Response) (res *ActionMa return res, errors.Wrap(defRes, "error") } +func decodeActionMapfixTriggerSubmitUncheckedResponse(resp *http.Response) (res *ActionMapfixTriggerSubmitUncheckedNoContent, _ error) { + switch resp.StatusCode { + case 204: + // Code 204. + return &ActionMapfixTriggerSubmitUncheckedNoContent{}, nil + } + // Convenient error response. + defRes, err := func() (res *ErrorStatusCode, err error) { + ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type")) + if err != nil { + return res, errors.Wrap(err, "parse media type") + } + switch { + case ct == "application/json": + buf, err := io.ReadAll(resp.Body) + if err != nil { + return res, err + } + d := jx.DecodeBytes(buf) + + var response Error + if err := func() error { + if err := response.Decode(d); err != nil { + return err + } + if err := d.Skip(); err != io.EOF { + return errors.New("unexpected trailing data") + } + return nil + }(); err != nil { + err = &ogenerrors.DecodeBodyError{ + ContentType: ct, + Body: buf, + Err: err, + } + return res, err + } + // Validate response. + if err := func() error { + if err := response.Validate(); err != nil { + return err + } + return nil + }(); err != nil { + return res, errors.Wrap(err, "validate") + } + return &ErrorStatusCode{ + StatusCode: resp.StatusCode, + Response: response, + }, nil + default: + return res, validate.InvalidContentType(ct) + } + }() + if err != nil { + return res, errors.Wrapf(err, "default (code %d)", resp.StatusCode) + } + return res, errors.Wrap(defRes, "error") +} + func decodeActionMapfixTriggerUploadResponse(resp *http.Response) (res *ActionMapfixTriggerUploadNoContent, _ error) { switch resp.StatusCode { case 204: @@ -735,66 +735,6 @@ func decodeActionSubmissionAcceptedResponse(resp *http.Response) (res *ActionSub return res, errors.Wrap(defRes, "error") } -func decodeActionSubmissionBypassSubmitResponse(resp *http.Response) (res *ActionSubmissionBypassSubmitNoContent, _ error) { - switch resp.StatusCode { - case 204: - // Code 204. - return &ActionSubmissionBypassSubmitNoContent{}, nil - } - // Convenient error response. - defRes, err := func() (res *ErrorStatusCode, err error) { - ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type")) - if err != nil { - return res, errors.Wrap(err, "parse media type") - } - switch { - case ct == "application/json": - buf, err := io.ReadAll(resp.Body) - if err != nil { - return res, err - } - d := jx.DecodeBytes(buf) - - var response Error - if err := func() error { - if err := response.Decode(d); err != nil { - return err - } - if err := d.Skip(); err != io.EOF { - return errors.New("unexpected trailing data") - } - return nil - }(); err != nil { - err = &ogenerrors.DecodeBodyError{ - ContentType: ct, - Body: buf, - Err: err, - } - return res, err - } - // Validate response. - if err := func() error { - if err := response.Validate(); err != nil { - return err - } - return nil - }(); err != nil { - return res, errors.Wrap(err, "validate") - } - return &ErrorStatusCode{ - StatusCode: resp.StatusCode, - Response: response, - }, nil - default: - return res, validate.InvalidContentType(ct) - } - }() - if err != nil { - return res, errors.Wrapf(err, "default (code %d)", resp.StatusCode) - } - return res, errors.Wrap(defRes, "error") -} - func decodeActionSubmissionRejectResponse(resp *http.Response) (res *ActionSubmissionRejectNoContent, _ error) { switch resp.StatusCode { case 204: @@ -1155,6 +1095,66 @@ func decodeActionSubmissionTriggerSubmitResponse(resp *http.Response) (res *Acti return res, errors.Wrap(defRes, "error") } +func decodeActionSubmissionTriggerSubmitUncheckedResponse(resp *http.Response) (res *ActionSubmissionTriggerSubmitUncheckedNoContent, _ error) { + switch resp.StatusCode { + case 204: + // Code 204. + return &ActionSubmissionTriggerSubmitUncheckedNoContent{}, nil + } + // Convenient error response. + defRes, err := func() (res *ErrorStatusCode, err error) { + ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type")) + if err != nil { + return res, errors.Wrap(err, "parse media type") + } + switch { + case ct == "application/json": + buf, err := io.ReadAll(resp.Body) + if err != nil { + return res, err + } + d := jx.DecodeBytes(buf) + + var response Error + if err := func() error { + if err := response.Decode(d); err != nil { + return err + } + if err := d.Skip(); err != io.EOF { + return errors.New("unexpected trailing data") + } + return nil + }(); err != nil { + err = &ogenerrors.DecodeBodyError{ + ContentType: ct, + Body: buf, + Err: err, + } + return res, err + } + // Validate response. + if err := func() error { + if err := response.Validate(); err != nil { + return err + } + return nil + }(); err != nil { + return res, errors.Wrap(err, "validate") + } + return &ErrorStatusCode{ + StatusCode: resp.StatusCode, + Response: response, + }, nil + default: + return res, validate.InvalidContentType(ct) + } + }() + if err != nil { + return res, errors.Wrapf(err, "default (code %d)", resp.StatusCode) + } + return res, errors.Wrap(defRes, "error") +} + func decodeActionSubmissionTriggerUploadResponse(resp *http.Response) (res *ActionSubmissionTriggerUploadNoContent, _ error) { switch resp.StatusCode { case 204: diff --git a/pkg/api/oas_response_encoders_gen.go b/pkg/api/oas_response_encoders_gen.go index 6279a81..6d277e7 100644 --- a/pkg/api/oas_response_encoders_gen.go +++ b/pkg/api/oas_response_encoders_gen.go @@ -20,13 +20,6 @@ func encodeActionMapfixAcceptedResponse(response *ActionMapfixAcceptedNoContent, return nil } -func encodeActionMapfixBypassSubmitResponse(response *ActionMapfixBypassSubmitNoContent, w http.ResponseWriter, span trace.Span) error { - w.WriteHeader(204) - span.SetStatus(codes.Ok, http.StatusText(204)) - - return nil -} - func encodeActionMapfixRejectResponse(response *ActionMapfixRejectNoContent, w http.ResponseWriter, span trace.Span) error { w.WriteHeader(204) span.SetStatus(codes.Ok, http.StatusText(204)) @@ -69,6 +62,13 @@ func encodeActionMapfixTriggerSubmitResponse(response *ActionMapfixTriggerSubmit return nil } +func encodeActionMapfixTriggerSubmitUncheckedResponse(response *ActionMapfixTriggerSubmitUncheckedNoContent, w http.ResponseWriter, span trace.Span) error { + w.WriteHeader(204) + span.SetStatus(codes.Ok, http.StatusText(204)) + + return nil +} + func encodeActionMapfixTriggerUploadResponse(response *ActionMapfixTriggerUploadNoContent, w http.ResponseWriter, span trace.Span) error { w.WriteHeader(204) span.SetStatus(codes.Ok, http.StatusText(204)) @@ -97,13 +97,6 @@ func encodeActionSubmissionAcceptedResponse(response *ActionSubmissionAcceptedNo return nil } -func encodeActionSubmissionBypassSubmitResponse(response *ActionSubmissionBypassSubmitNoContent, w http.ResponseWriter, span trace.Span) error { - w.WriteHeader(204) - span.SetStatus(codes.Ok, http.StatusText(204)) - - return nil -} - func encodeActionSubmissionRejectResponse(response *ActionSubmissionRejectNoContent, w http.ResponseWriter, span trace.Span) error { w.WriteHeader(204) span.SetStatus(codes.Ok, http.StatusText(204)) @@ -146,6 +139,13 @@ func encodeActionSubmissionTriggerSubmitResponse(response *ActionSubmissionTrigg return nil } +func encodeActionSubmissionTriggerSubmitUncheckedResponse(response *ActionSubmissionTriggerSubmitUncheckedNoContent, w http.ResponseWriter, span trace.Span) error { + w.WriteHeader(204) + span.SetStatus(codes.Ok, http.StatusText(204)) + + return nil +} + func encodeActionSubmissionTriggerUploadResponse(response *ActionSubmissionTriggerUploadNoContent, w http.ResponseWriter, span trace.Span) error { w.WriteHeader(204) span.SetStatus(codes.Ok, http.StatusText(204)) diff --git a/pkg/api/oas_router_gen.go b/pkg/api/oas_router_gen.go index d74b7b5..f92ea12 100644 --- a/pkg/api/oas_router_gen.go +++ b/pkg/api/oas_router_gen.go @@ -250,28 +250,6 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { break } switch elem[0] { - case 'b': // Prefix: "bypass-submit" - - if l := len("bypass-submit"); len(elem) >= l && elem[0:l] == "bypass-submit" { - elem = elem[l:] - } else { - break - } - - if len(elem) == 0 { - // Leaf node. - switch r.Method { - case "POST": - s.handleActionMapfixBypassSubmitRequest([1]string{ - args[0], - }, elemIsEscaped, w, r) - default: - s.notAllowed(w, r, "POST") - } - - return - } - case 'r': // Prefix: "re" if l := len("re"); len(elem) >= l && elem[0:l] == "re" { @@ -475,7 +453,6 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { } if len(elem) == 0 { - // Leaf node. switch r.Method { case "POST": s.handleActionMapfixTriggerSubmitRequest([1]string{ @@ -487,6 +464,30 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } + switch elem[0] { + case '-': // Prefix: "-unchecked" + + if l := len("-unchecked"); len(elem) >= l && elem[0:l] == "-unchecked" { + elem = elem[l:] + } else { + break + } + + if len(elem) == 0 { + // Leaf node. + switch r.Method { + case "POST": + s.handleActionMapfixTriggerSubmitUncheckedRequest([1]string{ + args[0], + }, elemIsEscaped, w, r) + default: + s.notAllowed(w, r, "POST") + } + + return + } + + } case 'u': // Prefix: "upload" @@ -1068,28 +1069,6 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { break } switch elem[0] { - case 'b': // Prefix: "bypass-submit" - - if l := len("bypass-submit"); len(elem) >= l && elem[0:l] == "bypass-submit" { - elem = elem[l:] - } else { - break - } - - if len(elem) == 0 { - // Leaf node. - switch r.Method { - case "POST": - s.handleActionSubmissionBypassSubmitRequest([1]string{ - args[0], - }, elemIsEscaped, w, r) - default: - s.notAllowed(w, r, "POST") - } - - return - } - case 'r': // Prefix: "re" if l := len("re"); len(elem) >= l && elem[0:l] == "re" { @@ -1293,7 +1272,6 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { } if len(elem) == 0 { - // Leaf node. switch r.Method { case "POST": s.handleActionSubmissionTriggerSubmitRequest([1]string{ @@ -1305,6 +1283,30 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } + switch elem[0] { + case '-': // Prefix: "-unchecked" + + if l := len("-unchecked"); len(elem) >= l && elem[0:l] == "-unchecked" { + elem = elem[l:] + } else { + break + } + + if len(elem) == 0 { + // Leaf node. + switch r.Method { + case "POST": + s.handleActionSubmissionTriggerSubmitUncheckedRequest([1]string{ + args[0], + }, elemIsEscaped, w, r) + default: + s.notAllowed(w, r, "POST") + } + + return + } + + } case 'u': // Prefix: "upload" @@ -1665,30 +1667,6 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) { break } switch elem[0] { - case 'b': // Prefix: "bypass-submit" - - if l := len("bypass-submit"); len(elem) >= l && elem[0:l] == "bypass-submit" { - elem = elem[l:] - } else { - break - } - - if len(elem) == 0 { - // Leaf node. - switch method { - case "POST": - r.name = ActionMapfixBypassSubmitOperation - r.summary = "Role Reviewer changes status from ChangesRequested -> Submitted" - r.operationID = "actionMapfixBypassSubmit" - r.pathPattern = "/mapfixes/{MapfixID}/status/bypass-submit" - r.args = args - r.count = 1 - return r, true - default: - return - } - } - case 'r': // Prefix: "re" if l := len("re"); len(elem) >= l && elem[0:l] == "re" { @@ -1906,7 +1884,6 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) { } if len(elem) == 0 { - // Leaf node. switch method { case "POST": r.name = ActionMapfixTriggerSubmitOperation @@ -1920,6 +1897,32 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) { return } } + switch elem[0] { + case '-': // Prefix: "-unchecked" + + if l := len("-unchecked"); len(elem) >= l && elem[0:l] == "-unchecked" { + elem = elem[l:] + } else { + break + } + + if len(elem) == 0 { + // Leaf node. + switch method { + case "POST": + r.name = ActionMapfixTriggerSubmitUncheckedOperation + r.summary = "Role Reviewer changes status from ChangesRequested -> Submitting" + r.operationID = "actionMapfixTriggerSubmitUnchecked" + r.pathPattern = "/mapfixes/{MapfixID}/status/trigger-submit-unchecked" + r.args = args + r.count = 1 + return r, true + default: + return + } + } + + } case 'u': // Prefix: "upload" @@ -2593,30 +2596,6 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) { break } switch elem[0] { - case 'b': // Prefix: "bypass-submit" - - if l := len("bypass-submit"); len(elem) >= l && elem[0:l] == "bypass-submit" { - elem = elem[l:] - } else { - break - } - - if len(elem) == 0 { - // Leaf node. - switch method { - case "POST": - r.name = ActionSubmissionBypassSubmitOperation - r.summary = "Role Reviewer changes status from ChangesRequested -> Submitted" - r.operationID = "actionSubmissionBypassSubmit" - r.pathPattern = "/submissions/{SubmissionID}/status/bypass-submit" - r.args = args - r.count = 1 - return r, true - default: - return - } - } - case 'r': // Prefix: "re" if l := len("re"); len(elem) >= l && elem[0:l] == "re" { @@ -2834,7 +2813,6 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) { } if len(elem) == 0 { - // Leaf node. switch method { case "POST": r.name = ActionSubmissionTriggerSubmitOperation @@ -2848,6 +2826,32 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) { return } } + switch elem[0] { + case '-': // Prefix: "-unchecked" + + if l := len("-unchecked"); len(elem) >= l && elem[0:l] == "-unchecked" { + elem = elem[l:] + } else { + break + } + + if len(elem) == 0 { + // Leaf node. + switch method { + case "POST": + r.name = ActionSubmissionTriggerSubmitUncheckedOperation + r.summary = "Role Reviewer changes status from ChangesRequested -> Submitting" + r.operationID = "actionSubmissionTriggerSubmitUnchecked" + r.pathPattern = "/submissions/{SubmissionID}/status/trigger-submit-unchecked" + r.args = args + r.count = 1 + return r, true + default: + return + } + } + + } case 'u': // Prefix: "upload" diff --git a/pkg/api/oas_schemas_gen.go b/pkg/api/oas_schemas_gen.go index 6d355f5..3d1a5a7 100644 --- a/pkg/api/oas_schemas_gen.go +++ b/pkg/api/oas_schemas_gen.go @@ -17,9 +17,6 @@ func (s *ErrorStatusCode) Error() string { // ActionMapfixAcceptedNoContent is response for ActionMapfixAccepted operation. type ActionMapfixAcceptedNoContent struct{} -// ActionMapfixBypassSubmitNoContent is response for ActionMapfixBypassSubmit operation. -type ActionMapfixBypassSubmitNoContent struct{} - // ActionMapfixRejectNoContent is response for ActionMapfixReject operation. type ActionMapfixRejectNoContent struct{} @@ -38,6 +35,9 @@ type ActionMapfixRevokeNoContent struct{} // ActionMapfixTriggerSubmitNoContent is response for ActionMapfixTriggerSubmit operation. type ActionMapfixTriggerSubmitNoContent struct{} +// ActionMapfixTriggerSubmitUncheckedNoContent is response for ActionMapfixTriggerSubmitUnchecked operation. +type ActionMapfixTriggerSubmitUncheckedNoContent struct{} + // ActionMapfixTriggerUploadNoContent is response for ActionMapfixTriggerUpload operation. type ActionMapfixTriggerUploadNoContent struct{} @@ -50,9 +50,6 @@ type ActionMapfixValidatedNoContent struct{} // ActionSubmissionAcceptedNoContent is response for ActionSubmissionAccepted operation. type ActionSubmissionAcceptedNoContent struct{} -// ActionSubmissionBypassSubmitNoContent is response for ActionSubmissionBypassSubmit operation. -type ActionSubmissionBypassSubmitNoContent struct{} - // ActionSubmissionRejectNoContent is response for ActionSubmissionReject operation. type ActionSubmissionRejectNoContent struct{} @@ -71,6 +68,9 @@ type ActionSubmissionRevokeNoContent struct{} // ActionSubmissionTriggerSubmitNoContent is response for ActionSubmissionTriggerSubmit operation. type ActionSubmissionTriggerSubmitNoContent struct{} +// ActionSubmissionTriggerSubmitUncheckedNoContent is response for ActionSubmissionTriggerSubmitUnchecked operation. +type ActionSubmissionTriggerSubmitUncheckedNoContent struct{} + // ActionSubmissionTriggerUploadNoContent is response for ActionSubmissionTriggerUpload operation. type ActionSubmissionTriggerUploadNoContent struct{} diff --git a/pkg/api/oas_security_gen.go b/pkg/api/oas_security_gen.go index cb72d81..a9b56b8 100644 --- a/pkg/api/oas_security_gen.go +++ b/pkg/api/oas_security_gen.go @@ -34,48 +34,48 @@ func findAuthorization(h http.Header, prefix string) (string, bool) { } var operationRolesCookieAuth = map[string][]string{ - ActionMapfixAcceptedOperation: []string{}, - ActionMapfixBypassSubmitOperation: []string{}, - ActionMapfixRejectOperation: []string{}, - ActionMapfixRequestChangesOperation: []string{}, - ActionMapfixResetSubmittingOperation: []string{}, - ActionMapfixRetryValidateOperation: []string{}, - ActionMapfixRevokeOperation: []string{}, - ActionMapfixTriggerSubmitOperation: []string{}, - ActionMapfixTriggerUploadOperation: []string{}, - ActionMapfixTriggerValidateOperation: []string{}, - ActionMapfixValidatedOperation: []string{}, - ActionSubmissionAcceptedOperation: []string{}, - ActionSubmissionBypassSubmitOperation: []string{}, - ActionSubmissionRejectOperation: []string{}, - ActionSubmissionRequestChangesOperation: []string{}, - ActionSubmissionResetSubmittingOperation: []string{}, - ActionSubmissionRetryValidateOperation: []string{}, - ActionSubmissionRevokeOperation: []string{}, - ActionSubmissionTriggerSubmitOperation: []string{}, - ActionSubmissionTriggerUploadOperation: []string{}, - ActionSubmissionTriggerValidateOperation: []string{}, - ActionSubmissionValidatedOperation: []string{}, - CreateMapfixOperation: []string{}, - CreateMapfixAuditCommentOperation: []string{}, - CreateScriptOperation: []string{}, - CreateScriptPolicyOperation: []string{}, - CreateSubmissionOperation: []string{}, - CreateSubmissionAdminOperation: []string{}, - CreateSubmissionAuditCommentOperation: []string{}, - DeleteScriptOperation: []string{}, - DeleteScriptPolicyOperation: []string{}, - GetOperationOperation: []string{}, - ReleaseSubmissionsOperation: []string{}, - SessionRolesOperation: []string{}, - SessionUserOperation: []string{}, - SessionValidateOperation: []string{}, - SetMapfixCompletedOperation: []string{}, - SetSubmissionCompletedOperation: []string{}, - UpdateMapfixModelOperation: []string{}, - UpdateScriptOperation: []string{}, - UpdateScriptPolicyOperation: []string{}, - UpdateSubmissionModelOperation: []string{}, + ActionMapfixAcceptedOperation: []string{}, + ActionMapfixRejectOperation: []string{}, + ActionMapfixRequestChangesOperation: []string{}, + ActionMapfixResetSubmittingOperation: []string{}, + ActionMapfixRetryValidateOperation: []string{}, + ActionMapfixRevokeOperation: []string{}, + ActionMapfixTriggerSubmitOperation: []string{}, + ActionMapfixTriggerSubmitUncheckedOperation: []string{}, + ActionMapfixTriggerUploadOperation: []string{}, + ActionMapfixTriggerValidateOperation: []string{}, + ActionMapfixValidatedOperation: []string{}, + ActionSubmissionAcceptedOperation: []string{}, + ActionSubmissionRejectOperation: []string{}, + ActionSubmissionRequestChangesOperation: []string{}, + ActionSubmissionResetSubmittingOperation: []string{}, + ActionSubmissionRetryValidateOperation: []string{}, + ActionSubmissionRevokeOperation: []string{}, + ActionSubmissionTriggerSubmitOperation: []string{}, + ActionSubmissionTriggerSubmitUncheckedOperation: []string{}, + ActionSubmissionTriggerUploadOperation: []string{}, + ActionSubmissionTriggerValidateOperation: []string{}, + ActionSubmissionValidatedOperation: []string{}, + CreateMapfixOperation: []string{}, + CreateMapfixAuditCommentOperation: []string{}, + CreateScriptOperation: []string{}, + CreateScriptPolicyOperation: []string{}, + CreateSubmissionOperation: []string{}, + CreateSubmissionAdminOperation: []string{}, + CreateSubmissionAuditCommentOperation: []string{}, + DeleteScriptOperation: []string{}, + DeleteScriptPolicyOperation: []string{}, + GetOperationOperation: []string{}, + ReleaseSubmissionsOperation: []string{}, + SessionRolesOperation: []string{}, + SessionUserOperation: []string{}, + SessionValidateOperation: []string{}, + SetMapfixCompletedOperation: []string{}, + SetSubmissionCompletedOperation: []string{}, + UpdateMapfixModelOperation: []string{}, + UpdateScriptOperation: []string{}, + UpdateScriptPolicyOperation: []string{}, + UpdateSubmissionModelOperation: []string{}, } func (s *Server) securityCookieAuth(ctx context.Context, operationName OperationName, req *http.Request) (context.Context, bool, error) { diff --git a/pkg/api/oas_server_gen.go b/pkg/api/oas_server_gen.go index f2f961b..1e6d4a9 100644 --- a/pkg/api/oas_server_gen.go +++ b/pkg/api/oas_server_gen.go @@ -14,12 +14,6 @@ type Handler interface { // // POST /mapfixes/{MapfixID}/status/reset-validating ActionMapfixAccepted(ctx context.Context, params ActionMapfixAcceptedParams) error - // ActionMapfixBypassSubmit implements actionMapfixBypassSubmit operation. - // - // Role Reviewer changes status from ChangesRequested -> Submitted. - // - // POST /mapfixes/{MapfixID}/status/bypass-submit - ActionMapfixBypassSubmit(ctx context.Context, params ActionMapfixBypassSubmitParams) error // ActionMapfixReject implements actionMapfixReject operation. // // Role Reviewer changes status from Submitted -> Rejected. @@ -57,6 +51,12 @@ type Handler interface { // // POST /mapfixes/{MapfixID}/status/trigger-submit ActionMapfixTriggerSubmit(ctx context.Context, params ActionMapfixTriggerSubmitParams) error + // ActionMapfixTriggerSubmitUnchecked implements actionMapfixTriggerSubmitUnchecked operation. + // + // Role Reviewer changes status from ChangesRequested -> Submitting. + // + // POST /mapfixes/{MapfixID}/status/trigger-submit-unchecked + ActionMapfixTriggerSubmitUnchecked(ctx context.Context, params ActionMapfixTriggerSubmitUncheckedParams) error // ActionMapfixTriggerUpload implements actionMapfixTriggerUpload operation. // // Role Admin changes status from Validated -> Uploading. @@ -81,12 +81,6 @@ type Handler interface { // // POST /submissions/{SubmissionID}/status/reset-validating ActionSubmissionAccepted(ctx context.Context, params ActionSubmissionAcceptedParams) error - // ActionSubmissionBypassSubmit implements actionSubmissionBypassSubmit operation. - // - // Role Reviewer changes status from ChangesRequested -> Submitted. - // - // POST /submissions/{SubmissionID}/status/bypass-submit - ActionSubmissionBypassSubmit(ctx context.Context, params ActionSubmissionBypassSubmitParams) error // ActionSubmissionReject implements actionSubmissionReject operation. // // Role Reviewer changes status from Submitted -> Rejected. @@ -124,6 +118,12 @@ type Handler interface { // // POST /submissions/{SubmissionID}/status/trigger-submit ActionSubmissionTriggerSubmit(ctx context.Context, params ActionSubmissionTriggerSubmitParams) error + // ActionSubmissionTriggerSubmitUnchecked implements actionSubmissionTriggerSubmitUnchecked operation. + // + // Role Reviewer changes status from ChangesRequested -> Submitting. + // + // POST /submissions/{SubmissionID}/status/trigger-submit-unchecked + ActionSubmissionTriggerSubmitUnchecked(ctx context.Context, params ActionSubmissionTriggerSubmitUncheckedParams) error // ActionSubmissionTriggerUpload implements actionSubmissionTriggerUpload operation. // // Role Admin changes status from Validated -> Uploading. diff --git a/pkg/api/oas_unimplemented_gen.go b/pkg/api/oas_unimplemented_gen.go index 5f935de..c1b8fdb 100644 --- a/pkg/api/oas_unimplemented_gen.go +++ b/pkg/api/oas_unimplemented_gen.go @@ -22,15 +22,6 @@ func (UnimplementedHandler) ActionMapfixAccepted(ctx context.Context, params Act return ht.ErrNotImplemented } -// ActionMapfixBypassSubmit implements actionMapfixBypassSubmit operation. -// -// Role Reviewer changes status from ChangesRequested -> Submitted. -// -// POST /mapfixes/{MapfixID}/status/bypass-submit -func (UnimplementedHandler) ActionMapfixBypassSubmit(ctx context.Context, params ActionMapfixBypassSubmitParams) error { - return ht.ErrNotImplemented -} - // ActionMapfixReject implements actionMapfixReject operation. // // Role Reviewer changes status from Submitted -> Rejected. @@ -86,6 +77,15 @@ func (UnimplementedHandler) ActionMapfixTriggerSubmit(ctx context.Context, param return ht.ErrNotImplemented } +// ActionMapfixTriggerSubmitUnchecked implements actionMapfixTriggerSubmitUnchecked operation. +// +// Role Reviewer changes status from ChangesRequested -> Submitting. +// +// POST /mapfixes/{MapfixID}/status/trigger-submit-unchecked +func (UnimplementedHandler) ActionMapfixTriggerSubmitUnchecked(ctx context.Context, params ActionMapfixTriggerSubmitUncheckedParams) error { + return ht.ErrNotImplemented +} + // ActionMapfixTriggerUpload implements actionMapfixTriggerUpload operation. // // Role Admin changes status from Validated -> Uploading. @@ -122,15 +122,6 @@ func (UnimplementedHandler) ActionSubmissionAccepted(ctx context.Context, params return ht.ErrNotImplemented } -// ActionSubmissionBypassSubmit implements actionSubmissionBypassSubmit operation. -// -// Role Reviewer changes status from ChangesRequested -> Submitted. -// -// POST /submissions/{SubmissionID}/status/bypass-submit -func (UnimplementedHandler) ActionSubmissionBypassSubmit(ctx context.Context, params ActionSubmissionBypassSubmitParams) error { - return ht.ErrNotImplemented -} - // ActionSubmissionReject implements actionSubmissionReject operation. // // Role Reviewer changes status from Submitted -> Rejected. @@ -186,6 +177,15 @@ func (UnimplementedHandler) ActionSubmissionTriggerSubmit(ctx context.Context, p return ht.ErrNotImplemented } +// ActionSubmissionTriggerSubmitUnchecked implements actionSubmissionTriggerSubmitUnchecked operation. +// +// Role Reviewer changes status from ChangesRequested -> Submitting. +// +// POST /submissions/{SubmissionID}/status/trigger-submit-unchecked +func (UnimplementedHandler) ActionSubmissionTriggerSubmitUnchecked(ctx context.Context, params ActionSubmissionTriggerSubmitUncheckedParams) error { + return ht.ErrNotImplemented +} + // ActionSubmissionTriggerUpload implements actionSubmissionTriggerUpload operation. // // Role Admin changes status from Validated -> Uploading. diff --git a/pkg/model/nats.go b/pkg/model/nats.go index a0882e6..9a1a8fd 100644 --- a/pkg/model/nats.go +++ b/pkg/model/nats.go @@ -27,11 +27,13 @@ type CreateMapfixRequest struct { type CheckSubmissionRequest struct{ SubmissionID int64 ModelID uint64 + SkipChecks bool } type CheckMapfixRequest struct{ - MapfixID int64 - ModelID uint64 + MapfixID int64 + ModelID uint64 + SkipChecks bool } type ValidateSubmissionRequest struct { diff --git a/pkg/service/mapfixes.go b/pkg/service/mapfixes.go index 4c40393..2e95d2f 100644 --- a/pkg/service/mapfixes.go +++ b/pkg/service/mapfixes.go @@ -498,8 +498,9 @@ func (svc *Service) ActionMapfixTriggerSubmit(ctx context.Context, params api.Ac } validate_request := model.CheckMapfixRequest{ - MapfixID: mapfix.ID, - ModelID: mapfix.AssetID, + MapfixID: mapfix.ID, + ModelID: mapfix.AssetID, + SkipChecks: false, } j, err := json.Marshal(validate_request) @@ -527,12 +528,12 @@ func (svc *Service) ActionMapfixTriggerSubmit(ctx context.Context, params api.Ac ) } -// ActionMapfixBypassSubmit invokes actionMapfixBypassSubmit operation. +// ActionMapfixTriggerSubmitUnchecked invokes actionMapfixTriggerSubmitUnchecked operation. // -// Role Reviewer changes status from ChangesRequested -> Submitted. +// Role Reviewer changes status from ChangesRequested -> Submitting. // -// POST /mapfixes/{MapfixID}/status/bypass-submit -func (svc *Service) ActionMapfixBypassSubmit(ctx context.Context, params api.ActionMapfixBypassSubmitParams) error { +// POST /mapfixes/{MapfixID}/status/trigger-submit-unchecked +func (svc *Service) ActionMapfixTriggerSubmitUnchecked(ctx context.Context, params api.ActionMapfixTriggerSubmitUncheckedParams) error { userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle) if !ok { return ErrUserInfo @@ -565,7 +566,7 @@ func (svc *Service) ActionMapfixBypassSubmit(ctx context.Context, params api.Act } // transaction - target_status := model.MapfixStatusSubmitted + target_status := model.MapfixStatusSubmitting smap := datastore.Optional() smap.Add("status_id", target_status) err = svc.DB.Mapfixes().IfStatusThenUpdate(ctx, params.MapfixID, []model.MapfixStatus{model.MapfixStatusChangesRequested}, smap) @@ -573,6 +574,22 @@ func (svc *Service) ActionMapfixBypassSubmit(ctx context.Context, params api.Act return err } + validate_request := model.CheckMapfixRequest{ + MapfixID: mapfix.ID, + ModelID: mapfix.AssetID, + SkipChecks: true, + } + + j, err := json.Marshal(validate_request) + if err != nil { + return err + } + + _, err = svc.Nats.Publish("maptest.mapfixes.check", []byte(j)) + if err != nil { + return err + } + event_data := model.AuditEventDataAction{ TargetStatus: uint32(target_status), } diff --git a/pkg/service/submissions.go b/pkg/service/submissions.go index dc4543e..c8562e1 100644 --- a/pkg/service/submissions.go +++ b/pkg/service/submissions.go @@ -575,6 +575,7 @@ func (svc *Service) ActionSubmissionTriggerSubmit(ctx context.Context, params ap validate_request := model.CheckSubmissionRequest{ SubmissionID: submission.ID, ModelID: submission.AssetID, + SkipChecks: false, } j, err := json.Marshal(validate_request) @@ -602,12 +603,12 @@ func (svc *Service) ActionSubmissionTriggerSubmit(ctx context.Context, params ap ) } -// ActionSubmissionBypassSubmit invokes actionSubmissionBypassSubmit operation. +// ActionSubmissionTriggerSubmitUnchecked invokes actionSubmissionTriggerSubmitUnchecked operation. // -// Role Reviewer changes status from ChangesRequested -> Submitted. +// Role Reviewer changes status from ChangesRequested -> Submitting. // -// POST /submissions/{SubmissionID}/status/bypass-submit -func (svc *Service) ActionSubmissionBypassSubmit(ctx context.Context, params api.ActionSubmissionBypassSubmitParams) error { +// POST /submissions/{SubmissionID}/status/trigger-submit-unchecked +func (svc *Service) ActionSubmissionTriggerSubmitUnchecked(ctx context.Context, params api.ActionSubmissionTriggerSubmitUncheckedParams) error { userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle) if !ok { return ErrUserInfo @@ -640,7 +641,7 @@ func (svc *Service) ActionSubmissionBypassSubmit(ctx context.Context, params api } // transaction - target_status := model.SubmissionStatusSubmitted + target_status := model.SubmissionStatusSubmitting smap := datastore.Optional() smap.Add("status_id", target_status) err = svc.DB.Submissions().IfStatusThenUpdate(ctx, params.SubmissionID, []model.SubmissionStatus{model.SubmissionStatusChangesRequested}, smap) @@ -648,6 +649,22 @@ func (svc *Service) ActionSubmissionBypassSubmit(ctx context.Context, params api return err } + validate_request := model.CheckSubmissionRequest{ + SubmissionID: submission.ID, + ModelID: submission.AssetID, + SkipChecks: true, + } + + j, err := json.Marshal(validate_request) + if err != nil { + return err + } + + _, err = svc.Nats.Publish("maptest.submissions.check", []byte(j)) + if err != nil { + return err + } + event_data := model.AuditEventDataAction{ TargetStatus: uint32(target_status), } diff --git a/validation/src/check.rs b/validation/src/check.rs index 8c39abe..17121fe 100644 --- a/validation/src/check.rs +++ b/validation/src/check.rs @@ -12,6 +12,7 @@ pub enum Error{ Download(crate::download::Error), ModelFileDecode(ReadDomError), GetRootInstance(GetRootInstanceError), + IntoMapInfoOwned(IntoMapInfoOwnedError), ToJsonValue(serde_json::Error), } impl std::fmt::Display for Error{ @@ -23,13 +24,15 @@ impl std::error::Error for Error{} #[allow(nonstandard_style)] pub struct CheckRequest{ - pub ModelID:u64, + ModelID:u64, + SkipChecks:bool, } impl From for CheckRequest{ fn from(value:crate::nats_types::CheckMapfixRequest)->Self{ Self{ ModelID:value.ModelID, + SkipChecks:value.SkipChecks, } } } @@ -37,6 +40,7 @@ impl From for CheckRequest{ fn from(value:crate::nats_types::CheckSubmissionRequest)->Self{ Self{ ModelID:value.ModelID, + SkipChecks:value.SkipChecks, } } } @@ -382,6 +386,22 @@ pub struct MapInfoOwned{ pub creator:String, pub game_id:GameID, } +#[derive(Debug)] +pub enum IntoMapInfoOwnedError{ + DisplayName(StringValueError), + Creator(StringValueError), + GameID(ParseGameIDError), +} +impl TryFrom> for MapInfoOwned{ + type Error=IntoMapInfoOwnedError; + fn try_from(value:MapInfo<'_>)->Result{ + Ok(Self{ + display_name:value.display_name.map_err(IntoMapInfoOwnedError::DisplayName)?.to_owned(), + creator:value.creator.map_err(IntoMapInfoOwnedError::Creator)?.to_owned(), + game_id:value.game_id.map_err(IntoMapInfoOwnedError::GameID)?, + }) + } +} // Named dummy types for readability struct Exists; @@ -833,6 +853,17 @@ impl crate::message_handler::MessageHandler{ // extract the root instance let model_instance=get_root_instance(&dom).map_err(Error::GetRootInstance)?; + // skip checks + if check_info.SkipChecks{ + // extract required fields + let map_info=get_mapinfo(&dom,model_instance); + let map_info_owned=map_info.try_into().map_err(Error::IntoMapInfoOwned)?; + let status=Ok(map_info_owned); + + // return early + return Ok(CheckReportAndVersion{status,version}); + } + // extract information from the model let model_info=get_model_info(&dom,model_instance); diff --git a/validation/src/nats_types.rs b/validation/src/nats_types.rs index db2a7e2..203bef4 100644 --- a/validation/src/nats_types.rs +++ b/validation/src/nats_types.rs @@ -34,6 +34,7 @@ pub struct CreateMapfixRequest{ pub struct CheckSubmissionRequest{ pub SubmissionID:SubmissionID, pub ModelID:u64, + pub SkipChecks:bool, } #[allow(nonstandard_style)] @@ -41,6 +42,7 @@ pub struct CheckSubmissionRequest{ pub struct CheckMapfixRequest{ pub MapfixID:MapfixID, pub ModelID:u64, + pub SkipChecks:bool, } #[allow(nonstandard_style)] diff --git a/web/src/app/_components/review/ReviewButtons.tsx b/web/src/app/_components/review/ReviewButtons.tsx index 17c0c3c..a2abcd0 100644 --- a/web/src/app/_components/review/ReviewButtons.tsx +++ b/web/src/app/_components/review/ReviewButtons.tsx @@ -20,7 +20,7 @@ interface ReviewButtonsProps { const ReviewActions = { Submit: {name:"Submit",action:"trigger-submit"} as ReviewAction, - BypassSubmit: {name:"Bypass Submit", action:"bypass-submit"} as ReviewAction, + SubmitUnchecked: {name:"Submit Unchecked", action:"trigger-submit-unchecked"} as ReviewAction, ResetSubmitting: {name:"Reset Submitting",action:"reset-submitting"} as ReviewAction, Revoke: {name:"Revoke",action:"revoke"} as ReviewAction, Accept: {name:"Accept",action:"trigger-validate"} as ReviewAction, @@ -109,7 +109,7 @@ const ReviewButtons: React.FC = ({ if (status === Status.ChangesRequested) { buttons.push({ - action: ReviewActions.BypassSubmit, + action: ReviewActions.SubmitUnchecked, color: "warning" }); } @@ -152,4 +152,4 @@ const ReviewButtons: React.FC = ({ ); }; -export default ReviewButtons; \ No newline at end of file +export default ReviewButtons; -- 2.49.1