Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: openRPC validation #668

Merged
merged 1 commit into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading