Skip to content

Commit dc8636d

Browse files
Merge pull request #406 from code0-tech/#261-body-validation
body validation
2 parents 73cc460 + feb65f3 commit dc8636d

17 files changed

Lines changed: 987 additions & 24 deletions

File tree

Cargo.lock

Lines changed: 576 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ tonic = "0.14.1"
1414
tucana = { version = "0.0.77", features = ["aquila", "sagittarius_gateway"] }
1515
code0-flow = { version = "0.0.42", features = ["flow_config", "flow_health", "flow_telemetry"] }
1616
serde_json = "1.0.140"
17+
lupus = "0.0.2"
1718
async-nats = "0.50.0"
1819
tonic-health = "0.14.1"
1920
tokio-stream = "0.1.17"

src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub mod sagittarius;
1919
pub mod server;
2020
pub mod startup;
2121
pub mod telemetry;
22+
pub mod validation;
2223
pub mod version;
2324

2425
const CONFIG_PATH_ENV: &str = "AQUILA_CONFIG_PATH";

src/sagittarius/flow_service_client_impl/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ impl SagittariusFlowClient {
128128
dev_export::overwrite(&self.flow_export_path, flows.clone()).await;
129129
}
130130

131-
let (purged_count, stored_count) = flow_store::replace_all(&self.store, flows).await;
131+
let (purged_count, stored_count) =
132+
flow_store::replace_all(&self.store, flows).await;
132133
log::info!(
133134
"Finished replacing stored flows received_count={} purged_count={} stored_count={}",
134135
received_count,

src/sagittarius/module_configuration_client_impl.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ impl SagittariusModuleConfigurationClient {
109109
}
110110

111111
log::warn!("Sagittarius closed the module configuration stream; reconnecting");
112-
Err(tonic::Status::unavailable("module configuration stream ended"))
112+
Err(tonic::Status::unavailable(
113+
"module configuration stream ended",
114+
))
113115
}
114116
}

src/sagittarius/test_execution_client_impl/flow_id_cache.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,9 @@ fn prune_expired(entries: &mut HashMap<String, ExecutionFlowIdMapping>, now: Ins
123123

124124
/// Evicts whichever entry is closest to expiring, since that's the best
125125
/// approximation of "oldest" without tracking insertion order separately.
126-
fn remove_soonest_to_expire(entries: &mut HashMap<String, ExecutionFlowIdMapping>) -> Option<String> {
126+
fn remove_soonest_to_expire(
127+
entries: &mut HashMap<String, ExecutionFlowIdMapping>,
128+
) -> Option<String> {
127129
let soonest_execution_id = entries
128130
.iter()
129131
.min_by_key(|(_, mapping)| mapping.expires_at)

src/sagittarius/test_execution_client_impl/mod.rs

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ use tucana::sagittarius_gateway::execution_service_client::ExecutionServiceClien
2828
use tucana::sagittarius_gateway::{ExecutionLogonRequest, Logon};
2929
use tucana::shared::{ExecutionFlow, ValidationFlow};
3030

31-
use crate::{authorization::authorization::get_authentication_metadata, flow::key_has_flow_id};
31+
use crate::{
32+
authorization::authorization::get_authentication_metadata, flow::key_has_flow_id, validation,
33+
};
3234

3335
pub struct SagittariusTestExecutionServiceClient {
3436
nats_client: async_nats::Client,
@@ -205,8 +207,44 @@ impl SagittariusTestExecutionServiceClient {
205207
}
206208
};
207209

208-
// TODO: When the new validator is ready, the body needs to be validated at this
209-
// point.
210+
if validation::is_rest_flow(&validation_flow) {
211+
let input_schema = validation::extract_input_schema(&validation_flow);
212+
if let Err(err) = validation::validate_body_against_schema(
213+
input_schema,
214+
request.body.as_ref(),
215+
) {
216+
log::warn!(
217+
"Rejecting Sagittarius execution request due to input schema validation failure requested_execution_id={} flow_id={} error={}",
218+
request.execution_identifier,
219+
request.flow_id,
220+
err
221+
);
222+
223+
let execution_id = if request.execution_identifier.is_empty() {
224+
uuid::Uuid::new_v4().to_string()
225+
} else {
226+
request.execution_identifier.clone()
227+
};
228+
229+
let rejection = validation::rejection_result(
230+
execution_id,
231+
request.flow_id,
232+
&err,
233+
);
234+
235+
if let Err(status) =
236+
self.response_sender.send_execution_result(rejection).await
237+
{
238+
log::error!(
239+
"Failed to send input schema validation rejection result flow_id={} error={:?}",
240+
request.flow_id,
241+
status
242+
);
243+
}
244+
245+
continue;
246+
}
247+
}
210248

211249
let execution_id = if request.execution_identifier.is_empty() {
212250
uuid::Uuid::new_v4().to_string()

src/sagittarius/test_execution_client_impl/response_sender.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use std::sync::Arc;
66

77
use tokio::sync::Mutex;
88
use tonic::Status;
9-
use tucana::sagittarius_gateway::execution_logon_request::Data;
109
use tucana::sagittarius_gateway::ExecutionLogonRequest;
10+
use tucana::sagittarius_gateway::execution_logon_request::Data;
1111
use tucana::shared::ExecutionResult;
1212

1313
use super::flow_id_cache::ExecutionFlowIdCache;
@@ -50,7 +50,9 @@ impl SagittariusExecutionResponseSender {
5050
}
5151

5252
pub(super) async fn remember_execution_flow(&self, execution_id: &str, flow_id: i64) {
53-
self.execution_flow_ids.remember(execution_id, flow_id).await;
53+
self.execution_flow_ids
54+
.remember(execution_id, flow_id)
55+
.await;
5456
}
5557

5658
pub(super) async fn forget_execution_flow(&self, execution_id: &str) {

src/server/action_transfer/logon.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,21 @@ pub(super) fn extract_token(
4646
/// Whether a broadcasted config update is meant for `action_identifier`, since
4747
/// [`spawn_cfg_forwarder`] subscribes to a single broadcast channel shared by
4848
/// every connected action.
49-
fn applies_to_action(configs: &tucana::shared::ModuleConfigurations, action_identifier: &str) -> bool {
49+
fn applies_to_action(
50+
configs: &tucana::shared::ModuleConfigurations,
51+
action_identifier: &str,
52+
) -> bool {
5053
configs.module_identifier == action_identifier
5154
}
5255

5356
/// Rewrites every definition's `definition_source` on the module an action
5457
/// logs on with, so downstream consumers can tell it came from this action
5558
/// rather than from whatever source the action's module definition was
5659
/// authored against.
57-
fn overwrite_module_definition_sources(module: &mut tucana::shared::Module, action_identifier: &str) {
60+
fn overwrite_module_definition_sources(
61+
module: &mut tucana::shared::Module,
62+
action_identifier: &str,
63+
) {
5864
let source = format!("action.{}", action_identifier);
5965

6066
for flow_type in &mut module.flow_types {

src/server/action_transfer/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ use tokio_stream::wrappers::ReceiverStream;
2121
use tonic::Status;
2222
use tracing::Instrument;
2323
use tucana::aquila::{
24-
ActionTransferRequest, ActionTransferResponse, action_transfer_service_server::ActionTransferService,
24+
ActionTransferRequest, ActionTransferResponse,
25+
action_transfer_service_server::ActionTransferService,
2526
};
2627

2728
use crate::{
2829
configuration::service::ServiceConfiguration,
29-
sagittarius::module_service_client_impl::SagittariusModuleServiceClient,
30-
telemetry::metrics,
30+
sagittarius::module_service_client_impl::SagittariusModuleServiceClient, telemetry::metrics,
3131
};
3232

3333
use logon::{extract_token, handle_logon};

0 commit comments

Comments
 (0)