1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
use axum::{extract::State, response::IntoResponse};
use warden_core::configuration::rule::{
RuleConfiguration, mutate_rule_configuration_server::MutateRuleConfiguration,
};
use crate::{
server::{error::AppError, http_svc::TAG_RULES, version::Version},
state::AppHandle,
};
/// Create rule configuration
#[utoipa::path(
post,
path = "/{version}/rule",
params(
("version" = Version, Path, description = "API version, e.g., v1, v2, v3"),
),
responses((
status = CREATED,
body = RuleConfiguration,
)),
operation_id = "create_rule_configuration", // https://github.com/juhaku/utoipa/issues/1170
tag = TAG_RULES,
)
]
#[axum::debug_handler]
#[tracing::instrument(skip(state))]
pub async fn create_rule(
version: Version,
State(state): State<AppHandle>,
axum::Json(body): axum::Json<RuleConfiguration>,
) -> Result<impl IntoResponse, AppError> {
let response = state
.create_rule_configuration(tonic::Request::new(body))
.await?
.into_inner();
Ok((axum::http::StatusCode::CREATED, axum::Json(response)))
}
#[cfg(test)]
mod tests {
use axum::{
body::Body,
http::{Request, StatusCode},
};
use sqlx::PgPool;
use tower::ServiceExt;
use warden_stack::cache::RedisManager;
use crate::{
server::http_svc::{build_router, routes::test_config},
state::{AppState, Services},
};
#[sqlx::test]
async fn post_rule(pool: PgPool) {
let config = test_config();
let cache = RedisManager::new(&config.cache).await.unwrap();
let client = async_nats::connect(&config.nats.hosts[0]).await.unwrap();
let jetstream = async_nats::jetstream::new(client);
let state = AppState::create(
Services {
postgres: pool,
cache,
jetstream,
},
&test_config(),
)
.await
.unwrap();
let app = build_router(state);
let rule = serde_json::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"
}
]
}
});
let body = serde_json::to_vec(&rule).unwrap();
let response = app
.clone()
.oneshot(
Request::builder()
.method("POST")
.header("Content-Type", "application/json")
.uri("/api/v0/rule")
.body(Body::from(body))
.unwrap(),
)
.await
.unwrap();
assert_eq!(response.status(), StatusCode::CREATED);
}
}
|