diff options
-rw-r--r-- | contrib/bruno/configuration/routing/03-update-routing.bru | 23 | ||||
-rw-r--r-- | contrib/bruno/configuration/routing/04-delete-routing.bru | 23 | ||||
-rw-r--r-- | contrib/bruno/configuration/rule/01-create.bru | 52 | ||||
-rw-r--r-- | contrib/bruno/configuration/rule/folder.bru | 8 | ||||
-rw-r--r-- | crates/configuration/src/server/http_svc/routes.rs | 2 | ||||
-rw-r--r-- | lib/warden-core/build.rs | 12 | ||||
-rw-r--r-- | lib/warden-core/src/configuration.rs | 2 | ||||
-rw-r--r-- | lib/warden-core/src/configuration/conv.rs | 109 |
8 files changed, 231 insertions, 0 deletions
diff --git a/contrib/bruno/configuration/routing/03-update-routing.bru b/contrib/bruno/configuration/routing/03-update-routing.bru new file mode 100644 index 0000000..43d3ea4 --- /dev/null +++ b/contrib/bruno/configuration/routing/03-update-routing.bru @@ -0,0 +1,23 @@ +meta { + name: 03-update-routing + type: http + seq: 3 +} + +put { + url: {{WARDEN_CFG_HOST}}/api/{{WARDEN_CFG_VERSION}}/routing/:id + body: none + auth: inherit +} + +params:path { + id: +} + +assert { + res.status: eq 201 +} + +settings { + encodeUrl: true +} diff --git a/contrib/bruno/configuration/routing/04-delete-routing.bru b/contrib/bruno/configuration/routing/04-delete-routing.bru new file mode 100644 index 0000000..b5abaa8 --- /dev/null +++ b/contrib/bruno/configuration/routing/04-delete-routing.bru @@ -0,0 +1,23 @@ +meta { + name: 04-delete-routing + type: http + seq: 4 +} + +delete { + url: {{WARDEN_CFG_HOST}}/api/{{WARDEN_CFG_VERSION}}/routing/:id + body: none + auth: inherit +} + +params:path { + id: +} + +assert { + res.status: eq 200 +} + +settings { + encodeUrl: true +} diff --git a/contrib/bruno/configuration/rule/01-create.bru b/contrib/bruno/configuration/rule/01-create.bru new file mode 100644 index 0000000..cc98aee --- /dev/null +++ b/contrib/bruno/configuration/rule/01-create.bru @@ -0,0 +1,52 @@ +meta { + name: 01-create + type: http + seq: 1 +} + +post { + url: {{WARDEN_CFG_HOST}}/api/{{WARDEN_CFG_VERSION}}/rule + body: json + auth: inherit +} + +body:json { + { + "id": "901", + "version": "1.0.0", + "description": "Number of outgoing transactions - debtor", + "configuration": { + "parameters": { + "max_query_range": 86400000 + }, + "exit_conditions": [ + { + "sub_rule_ref": ".x00", + "reason": "Incoming transaction is unsuccessful" + } + ], + "bands": [ + { + "sub_rule_ref": ".01", + "upper_limit": 2, + "reason": "The debtor has performed one transaction to date" + }, + { + "sub_rule_ref": ".02", + "lower_limit": 2, + "upper_limit": 3, + "reason": "The debtor has performed two transactions to date" + }, + { + "sub_rule_ref": ".03", + "lower_limit": 3, + "reason": "The debtor has performed three or more transactions to date" + } + ] + } + } +} + +settings { + encodeUrl: true +} diff --git a/contrib/bruno/configuration/rule/folder.bru b/contrib/bruno/configuration/rule/folder.bru new file mode 100644 index 0000000..c486c46 --- /dev/null +++ b/contrib/bruno/configuration/rule/folder.bru @@ -0,0 +1,8 @@ +meta { + name: rule + seq: 2 +} + +auth { + mode: inherit +} diff --git a/crates/configuration/src/server/http_svc/routes.rs b/crates/configuration/src/server/http_svc/routes.rs index 281b231..7663da2 100644 --- a/crates/configuration/src/server/http_svc/routes.rs +++ b/crates/configuration/src/server/http_svc/routes.rs @@ -13,6 +13,8 @@ pub fn router(store: AppHandle) -> OpenApiRouter { routing::post_routing::post_routing, routing::delete_routing::delete, routing::replace_routing::replace, + )) + .routes(routes!( /* rule */ rule::create::create_rule, rule::update::update_rule_config, diff --git a/lib/warden-core/build.rs b/lib/warden-core/build.rs index c0496d9..abc6e37 100644 --- a/lib/warden-core/build.rs +++ b/lib/warden-core/build.rs @@ -121,6 +121,18 @@ fn add_serde(config: tonic_prost_build::Builder) -> tonic_prost_build::Builder { "#[serde(try_from = \"crate::google::parser::dt::DateItem\")] #[serde(into = \"String\")]", ).type_attribute(".google.type.Date", "#[serde(try_from = \"crate::google::parser::dt::DateItem\")] #[serde(into = \"String\")]"); + #[cfg(feature = "configuration")] + let config = config + .field_attribute(".configuration.rule.Config.cases", "#[serde(default)]") + .field_attribute( + ".configuration.rule.Config.time_frames", + "#[serde(default)]", + ) + .type_attribute( + ".google.protobuf.Value", + "#[serde(try_from = \"serde_json::Value\")] #[serde(into = \"crate::configuration::conv::GenericParameter\")]", + ); + config } diff --git a/lib/warden-core/src/configuration.rs b/lib/warden-core/src/configuration.rs index 798c079..c6b24ce 100644 --- a/lib/warden-core/src/configuration.rs +++ b/lib/warden-core/src/configuration.rs @@ -1,3 +1,5 @@ +pub(crate) mod conv; + tonic::include_proto!("configuration"); pub mod routing { diff --git a/lib/warden-core/src/configuration/conv.rs b/lib/warden-core/src/configuration/conv.rs new file mode 100644 index 0000000..c5c7768 --- /dev/null +++ b/lib/warden-core/src/configuration/conv.rs @@ -0,0 +1,109 @@ +use crate::google::protobuf::{ListValue, NullValue, Struct, Value, value}; + +#[derive(Debug)] +/// Generic JSON value +pub struct GenericParameter(pub(crate) serde_json::Value); + +impl From<Value> for GenericParameter { + fn from(value: Value) -> Self { + Self(value.into()) + } +} + +impl From<value::Kind> for GenericParameter { + fn from(value: value::Kind) -> Self { + Self(value.into()) + } +} + +impl TryFrom<serde_json::Value> for value::Kind { + type Error = String; + + fn try_from(value: serde_json::Value) -> Result<Self, Self::Error> { + match value { + serde_json::Value::Null => Ok(value::Kind::NullValue(NullValue::NullValue as i32)), + serde_json::Value::Bool(b) => Ok(value::Kind::BoolValue(b)), + serde_json::Value::Number(n) => n + .as_f64() + .map(value::Kind::NumberValue) + .ok_or_else(|| "Invalid number".to_string()), + serde_json::Value::String(s) => Ok(value::Kind::StringValue(s)), + serde_json::Value::Array(arr) => { + let values = arr + .into_iter() + .map(Value::try_from) + .collect::<Result<Vec<_>, _>>()?; + Ok(value::Kind::ListValue(ListValue { values })) + } + serde_json::Value::Object(map) => { + let mut fields = std::collections::HashMap::new(); + for (k, v) in map { + let v = Value::try_from(v)?; + fields.insert(k, v); + } + Ok(value::Kind::StructValue(Struct { fields })) + } + } + } +} + +impl TryFrom<serde_json::Value> for Value { + type Error = String; + + fn try_from(value: serde_json::Value) -> Result<Self, Self::Error> { + let kind = Some(value::Kind::try_from(value)?); + Ok(Value { kind }) + } +} + +impl From<value::Kind> for serde_json::Value { + fn from(kind: value::Kind) -> Self { + match kind { + value::Kind::NullValue(_) => serde_json::Value::Null, + value::Kind::BoolValue(b) => serde_json::Value::Bool(b), + value::Kind::NumberValue(n) => serde_json::Value::Number( + serde_json::Number::from_f64(n).unwrap_or_else(|| serde_json::Number::from(0)), + ), + value::Kind::StringValue(s) => serde_json::Value::String(s), + value::Kind::StructValue(s) => serde_json::Value::from(s), + value::Kind::ListValue(l) => serde_json::Value::from(l), + } + } +} + +impl From<Value> for serde_json::Value { + fn from(value: Value) -> Self { + match value.kind { + Some(kind) => kind.into(), + None => serde_json::Value::Null, + } + } +} + +impl From<Struct> for serde_json::Value { + fn from(s: Struct) -> Self { + let map = s + .fields + .into_iter() + .map(|(k, v)| (k, serde_json::Value::from(v))) + .collect(); + serde_json::Value::Object(map) + } +} + +impl From<ListValue> for serde_json::Value { + fn from(l: ListValue) -> Self { + let list = l.values.into_iter().map(serde_json::Value::from).collect(); + serde_json::Value::Array(list) + } +} + +impl serde::Serialize for GenericParameter { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: serde::Serializer, + { + let json = serde_json::Value::from(self.0.clone()); + json.serialize(serializer) + } +} |