Skip to content

Commit

Permalink
fix: openRPC validation (#668)
Browse files Browse the repository at this point in the history
  • Loading branch information
maggie98choy authored Nov 4, 2024
1 parent b1e3f9d commit 03bd06a
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 11 deletions.
2 changes: 1 addition & 1 deletion core/main/src/firebolt/firebolt_gateway.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ fn validate_request(
let major_version = open_rpc_state.get_version().major.to_string();
let openrpc_validator = open_rpc_state.get_openrpc_validator();
// Get Method from the validator
if let Some(rpc_method) = openrpc_validator.get_method_by_name(&method_name) {
if let Some(rpc_method) = openrpc_validator.get_method(&method_name) {
// Get schema validator
let validator = openrpc_validator
.params_validator(major_version, &rpc_method.name)
Expand Down
4 changes: 2 additions & 2 deletions core/main/src/firebolt/handlers/provider_registrar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ impl ProviderRegistrar {
.platform_state
.open_rpc_state
.get_openrpc_validator()
.get_result_properties_schema_by_name(event)
.get_result_properties_schema(event)
{
// Populate the event result, injecting the app ID if the field exists in the event schema

Expand Down Expand Up @@ -457,7 +457,7 @@ impl ProviderRegistrar {
.platform_state
.open_rpc_state
.get_openrpc_validator()
.get_result_properties_schema_by_name(&context.method)
.get_result_properties_schema(&context.method)
{
// Inject the provider app ID if the field exists in the provided-to response schema, the other field will be
// the provider response. The firebolt spec is not ideal in that the provider response data is captured
Expand Down
15 changes: 7 additions & 8 deletions core/main/src/state/openrpc_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use std::{
sync::{Arc, RwLock},
};

use openrpc_validator::FireboltOpenRpc as FireboltOpenRpcValidator;
use openrpc_validator::{FireboltOpenRpc as FireboltOpenRpcValidator, RpcMethodValidator};

#[derive(Debug, Clone)]
pub enum ApiSurface {
Expand Down Expand Up @@ -75,7 +75,7 @@ pub struct OpenRpcState {
cap_policies: Arc<RwLock<HashMap<String, CapabilityPolicy>>>,
extended_rpc: Arc<RwLock<Vec<FireboltOpenRpc>>>,
provider_relation_map: Arc<RwLock<HashMap<String, ProviderRelationSet>>>,
openrpc_validator: Arc<RwLock<FireboltOpenRpcValidator>>,
openrpc_validator: Arc<RwLock<RpcMethodValidator>>,
provider_registrations: Vec<String>,
json_schema_cache: Arc<RwLock<HashMap<String, JSONSchema>>>,
}
Expand Down Expand Up @@ -127,6 +127,8 @@ impl OpenRpcState {
let ripple_open_rpc: FireboltOpenRpc = FireboltOpenRpc::default();
let openrpc_validator: FireboltOpenRpcValidator = serde_json::from_str(&open_rpc_path)
.expect("Failed parsing FireboltOpenRpcValidator from open RPC file");
let mut rpc_method_validator = RpcMethodValidator::new();
rpc_method_validator.add_schema(openrpc_validator);
let v = OpenRpcState {
firebolt_cap_map: Arc::new(RwLock::new(firebolt_open_rpc.get_methods_caps())),
ripple_cap_map: Arc::new(RwLock::new(ripple_open_rpc.get_methods_caps())),
Expand All @@ -135,12 +137,11 @@ impl OpenRpcState {
open_rpc: firebolt_open_rpc.clone(),
extended_rpc: Arc::new(RwLock::new(Vec::new())),
provider_relation_map: Arc::new(RwLock::new(HashMap::new())),
openrpc_validator: Arc::new(RwLock::new(openrpc_validator)),
openrpc_validator: Arc::new(RwLock::new(rpc_method_validator)),
provider_registrations,
json_schema_cache: Arc::new(RwLock::new(HashMap::new())),
};
v.build_provider_relation_sets(&firebolt_open_rpc.methods);

for path in extn_sdks {
if v.add_extension_open_rpc(&path).is_err() {
error!("Error adding extn_sdk from {path}");
Expand Down Expand Up @@ -176,9 +177,7 @@ impl OpenRpcState {
return match serde_json::from_str::<FireboltOpenRpcValidator>(&open_rpc) {
Ok(additional_open_rpc_validator) => {
let mut validator = self.openrpc_validator.write().unwrap();
for (k, v) in additional_open_rpc_validator.apis {
validator.apis.insert(k, v);
}
validator.add_schema(additional_open_rpc_validator);
return Ok(());
}
Err(_) => Err(RippleError::ParseError),
Expand Down Expand Up @@ -332,7 +331,7 @@ impl OpenRpcState {
self.open_rpc.info.clone()
}

pub fn get_openrpc_validator(&self) -> FireboltOpenRpcValidator {
pub fn get_openrpc_validator(&self) -> RpcMethodValidator {
self.openrpc_validator.read().unwrap().clone()
}

Expand Down
53 changes: 53 additions & 0 deletions openrpc_validator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,59 @@ use serde_json::{json, Map, Value};

pub extern crate jsonschema;

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct RpcMethodValidator {
pub validators: Vec<FireboltOpenRpc>,
}

impl Default for RpcMethodValidator {
fn default() -> Self {
Self::new()
}
}

impl RpcMethodValidator {
pub fn new() -> RpcMethodValidator {
RpcMethodValidator { validators: vec![] }
}

pub fn add_schema(&mut self, schema: FireboltOpenRpc) {
self.validators.push(schema);
}

pub fn get_method(&self, name: &str) -> Option<RpcMethod> {
for validator in &self.validators {
if let Some(method) = validator.get_method_by_name(name) {
return Some(method);
}
}
None
}

pub fn get_result_properties_schema(&self, name: &str) -> Option<Map<String, Value>> {
for validator in &self.validators {
if let Some(method) = validator.get_result_properties_schema_by_name(name) {
return Some(method);
}
}
None
}

pub fn params_validator(
&self,
version: String,
method: &str,
) -> Result<JSONSchema, ValidationError> {
for validator in &self.validators {
let validator = validator.params_validator(version.clone(), method);
if validator.is_ok() {
return validator;
}
}
Err(ValidationError::SpecVersionNotFound)
}
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct FireboltOpenRpc {
pub apis: HashMap<String, FireboltOpenRpcSpec>,
Expand Down

0 comments on commit 03bd06a

Please sign in to comment.