Skip to content
This repository was archived by the owner on Feb 20, 2024. It is now read-only.

Commit 22b734d

Browse files
authored
Merge pull request #30 from Virtual-Finland-Development/feat/general-data-product
Feat/general data product
2 parents 3e28bd0 + acd13c9 commit 22b734d

File tree

25 files changed

+580
-304
lines changed

25 files changed

+580
-304
lines changed

.github/workflows/build-and-test.yml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,10 @@ jobs:
1919
runs-on: ubuntu-latest
2020
steps:
2121
- uses: actions/checkout@v3
22-
- name: Build 🔧
23-
run: |
24-
make build
25-
- name: Test 🧪
22+
- name: Test & Build 🧪🔧
2623
run: |
2724
make test
25+
make build
2826
- name: Archive the build artifacts 🐪
2927
if: ${{ inputs.wants_artifacts }}
3028
uses: actions/upload-artifact@v3

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@ itertools = "^0.10.5"
1818
libmath = "^0.2.1"
1919
stopwatch = "^0.0.7"
2020
utoipa = "3"
21+
tokio = { version = "^1.21.2", features = ["full"] }
2122

2223
[dependencies]
2324
hot-lib-reloader = { version = "^0.6", optional = true }
24-
tokio = { version = "^1.21.2", features = ["full"] }
2525
dotenv = "^0.15.0"
26+
tokio = { workspace = true }
2627
log = { workspace = true }
2728
simple_logger = { workspace = true }
2829
lambda_http = { workspace = true }

src/lib/api_app/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ itertools = { workspace = true }
1919
libmath = { workspace = true }
2020
stopwatch = { workspace = true }
2121
utoipa = { workspace = true }
22+
tokio = { workspace = true }
2223
lazy_static = "1.4.0"
2324

2425
app = { path = "./src/lib/app" }

src/lib/api_app/src/api/routes/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub mod testbed;
2525
application::health_check,
2626
application::wake_up_external_services,
2727
testbed::engage_reverse_proxy_request,
28+
testbed::get_general_data_product,
2829
testbed::productizers::figure::get_population,
2930
testbed::productizers::job::find_job_postings,
3031
testbed::productizers::user::fetch_user_profile,

src/lib/api_app/src/api/routes/testbed/mod.rs

Lines changed: 42 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,55 @@
1-
use std::collections::HashMap;
2-
use utoipa::ToSchema;
3-
41
use http::HeaderMap;
5-
use serde::{Deserialize, Serialize};
62
use serde_json::Value as JSONValue;
73

8-
use crate::api::routes::application::get_external_service_bad_response;
9-
104
use app::{
115
responses::{APIResponse, APIRoutingError, APIRoutingResponse},
126
router::ParsedRequest,
137
};
8+
9+
use utils::api::{parse_path_param, parse_query_param};
10+
11+
use crate::api::routes::application::get_external_service_bad_response;
12+
use serde::{Deserialize, Serialize};
13+
use std::collections::HashMap;
1414
use utils::api::get_cors_response_headers;
15+
use utoipa::ToSchema;
1516

1617
pub mod productizers;
18+
pub mod testbed_utils;
19+
20+
use testbed_utils::{access_control_check, service::post_data_product};
21+
22+
#[utoipa::path(
23+
post,
24+
path = "/testbed/data-product/{data_product}",
25+
request_body(content = Object, description = "Data product request", example = json!({
26+
"lat": 60.192059,
27+
"lon": 24.945831
28+
})),
29+
responses((status = 200, body = Object, description = "Data product response")),
30+
params(
31+
("data_product" = str, Path, description = "Data product name", example = "draft/Weather/Current/Metric"),
32+
("source" = str, Query, description = "Data source name", example = "openweather")
33+
),
34+
)]
35+
pub async fn get_general_data_product(request: ParsedRequest) -> APIResponse {
36+
log::debug!("Path: {:#?}", request.path);
37+
log::debug!("Query: {:#?}", request.query);
38+
log::debug!("Path params: {:#?}", request.path_params);
39+
40+
let path_params = request.path_params.clone();
41+
let query = request.query.clone();
42+
43+
let data_product = parse_path_param(path_params, "data_product")?;
44+
let data_source = parse_query_param(query, "source")?;
45+
46+
log::debug!("Data product: {:#?}", data_product);
47+
log::debug!("Data source: {:#?}", data_source);
48+
49+
let result =
50+
post_data_product(data_product.as_str(), data_source.as_str(), request).await?;
51+
Ok(result)
52+
}
1753

1854
#[derive(Deserialize, Serialize, Debug, ToSchema)]
1955
pub struct ProxyRequestInput {
@@ -69,24 +105,3 @@ pub async fn engage_reverse_proxy_request(request: ParsedRequest) -> APIResponse
69105
get_cors_response_headers(),
70106
))
71107
}
72-
73-
/**
74-
* Access control check
75-
*
76-
* @param proxy_destination_url
77-
* @returns {boolean} - true if access is denied
78-
*/
79-
fn access_control_check(proxy_destination_url: &str) -> bool {
80-
// Access control list check
81-
let acl = ["https://consent.testbed.fi/", "https://gateway.testbed.fi/"];
82-
83-
let mut acl_is_satisfied = false;
84-
for url in acl {
85-
if proxy_destination_url.starts_with(url) {
86-
acl_is_satisfied = true;
87-
break;
88-
}
89-
}
90-
91-
!acl_is_satisfied
92-
}

src/lib/api_app/src/api/routes/testbed/productizers/figure/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::env;
22

3-
use super::parse_testbed_request_headers;
3+
use crate::api::routes::testbed::testbed_utils::parse_testbed_request_headers;
44

55
use app::{requests::post_json_request, responses::APIResponse, router::ParsedRequest};
66

src/lib/api_app/src/api/routes/testbed/productizers/job/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use http::{Method, StatusCode};
22
use math::round;
33
use std::{cmp::Ordering, collections::hash_map::DefaultHasher, env, hash::Hasher};
44

5-
use super::parse_testbed_request_headers;
5+
use crate::api::routes::testbed::testbed_utils::parse_testbed_request_headers;
66

77
use app::{
88
requests::engage_many_json_requests,
Lines changed: 0 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,107 +1,5 @@
1-
use http::{HeaderMap, HeaderValue};
2-
use std::env;
3-
4-
use app::{responses::APIRoutingError, router::ParsedRequest};
5-
use utils::environment::get_stage;
6-
71
pub mod figure;
82
pub mod job;
93
pub mod nsg;
104
pub mod person;
115
pub mod user;
12-
13-
/**
14-
* Parses the authorization headers from the input request
15-
*/
16-
fn parse_testbed_request_headers(request: ParsedRequest) -> Result<HeaderMap, APIRoutingError> {
17-
// Prep auth header forwarding
18-
let mut request_headers = HeaderMap::new();
19-
request_headers.insert("Content-Type", HeaderValue::from_static("application/json"));
20-
request_headers.insert(
21-
"authorization",
22-
request
23-
.headers
24-
.get("authorization")
25-
.ok_or_else(|| {
26-
APIRoutingError::UnprocessableEntity("No authorization header".to_string())
27-
})?
28-
.clone(),
29-
);
30-
31-
if request.headers.contains_key("x-consent-token") {
32-
request_headers.insert(
33-
"x-consent-token",
34-
request
35-
.headers
36-
.get("x-consent-token")
37-
.ok_or_else(|| {
38-
APIRoutingError::UnprocessableEntity(
39-
"No x-consent-token header".to_string(),
40-
)
41-
})?
42-
.clone(),
43-
);
44-
}
45-
Ok(request_headers)
46-
}
47-
48-
/**
49-
* Builds the URI for the testbed data product
50-
*/
51-
fn build_data_product_stage_uri(data_product: &str, data_source: &str) -> String {
52-
let testbed_environment =
53-
env::var("TESTBED_ENVIRONMENT").expect("TESTBED_ENVIRONMENT must be set");
54-
build_data_product_uri(
55-
data_product,
56-
format!("{data_source}:{testbed_environment}").as_str(),
57-
)
58-
}
59-
60-
fn build_data_product_uri(data_product: &str, data_source: &str) -> String {
61-
let mut testbed_base_url =
62-
env::var("TESTBED_BASE_URL").expect("TESTBED_BASE_URL must be set");
63-
64-
if get_stage() == "local" {
65-
// @TODO: needs a local testbed data product gw simulation
66-
match data_product {
67-
"test/lassipatanen/User/Profile" => {
68-
testbed_base_url = env::var("USER_PROFILE_PRODUCTIZER_ENDPOINT")
69-
.expect("USER_PROFILE_PRODUCTIZER_ENDPOINT must be set");
70-
}
71-
"test/lsipii/User/StatusInfo" => {
72-
testbed_base_url = env::var("USER_STATUS_INFO_PRODUCTIZER_ENDPOINT")
73-
.expect("USER_STATUS_INFO_PRODUCTIZER_ENDPOINT must be set");
74-
}
75-
"test/lsipii/User/StatusInfo/Write" => {
76-
testbed_base_url = env::var("USER_STATUS_INFO_PRODUCTIZER_ENDPOINT")
77-
.expect("USER_STATUS_INFO_PRODUCTIZER_ENDPOINT must be set");
78-
}
79-
"draft/NSG/Agent/LegalEntity/NonListedCompany/Establishment/Write" => {
80-
testbed_base_url = env::var("PRH_MOCK_PRODUCTIZER_ENDPOINT")
81-
.expect("PRH_MOCK_PRODUCTIZER_ENDPOINT must be set");
82-
}
83-
"draft/NSG/Agent/LegalEntity/NonListedCompany/BeneficialOwners" => {
84-
testbed_base_url = env::var("PRH_MOCK_PRODUCTIZER_ENDPOINT")
85-
.expect("PRH_MOCK_PRODUCTIZER_ENDPOINT must be set");
86-
}
87-
"draft/NSG/Agent/LegalEntity/NonListedCompany/SignatoryRights" => {
88-
testbed_base_url = env::var("PRH_MOCK_PRODUCTIZER_ENDPOINT")
89-
.expect("PRH_MOCK_PRODUCTIZER_ENDPOINT must be set");
90-
}
91-
"draft/NSG/Agent/BasicInformation" => {
92-
if data_source.starts_with("virtualfinland") {
93-
testbed_base_url = env::var("PRH_MOCK_PRODUCTIZER_ENDPOINT")
94-
.expect("PRH_MOCK_PRODUCTIZER_ENDPOINT must be set");
95-
}
96-
}
97-
_ => {}
98-
}
99-
}
100-
101-
// Remove trailing slash from base url
102-
if testbed_base_url.ends_with('/') {
103-
testbed_base_url.pop();
104-
}
105-
106-
format!("{testbed_base_url}/{data_product}?source={data_source}")
107-
}

src/lib/api_app/src/api/routes/testbed/productizers/nsg/basic_information.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ use app::{
44
router::ParsedRequest,
55
};
66
use serde::{Deserialize, Serialize};
7-
use serde_json::Value as JSONValue;
87
use utils::api::get_default_headers;
98
use utoipa::ToSchema;
109

11-
use crate::api::routes::testbed::productizers::{
12-
build_data_product_stage_uri, build_data_product_uri,
10+
use crate::api::routes::testbed::testbed_utils::{
11+
build_data_product_staged_uri, build_data_product_uri,
1312
};
13+
use serde_json::Value as JSONValue;
1414

1515
#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, Clone, ToSchema)]
1616
pub struct NSGAgentBasicInformationRequest {
@@ -62,7 +62,7 @@ pub async fn get_nsg_basic_information(request: ParsedRequest) -> APIResponse {
6262
"Missing source parameter".to_string(),
6363
));
6464
}
65-
"virtualfinland" => build_data_product_stage_uri(data_product, data_source),
65+
"virtualfinland" => build_data_product_staged_uri(data_product, data_source),
6666
_ => build_data_product_uri(data_product, data_source),
6767
};
6868

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,2 @@
1-
use serde_json::{json, Value as JSONValue};
2-
3-
use app::{requests::post_json_request, responses::APIResponse, router::ParsedRequest};
4-
5-
use super::{build_data_product_stage_uri, parse_testbed_request_headers};
6-
71
pub mod basic_information;
82
pub mod non_listed_company;
9-
10-
pub async fn post_data_product(
11-
data_product: &str,
12-
data_source: &str,
13-
request: ParsedRequest,
14-
) -> APIResponse {
15-
let request_input: JSONValue =
16-
serde_json::from_str(request.body.as_str()).unwrap_or_else(|_| json!({}));
17-
let request_headers = parse_testbed_request_headers(request)?;
18-
let response = post_json_request::<JSONValue, JSONValue>(
19-
build_data_product_stage_uri(data_product, data_source),
20-
&request_input,
21-
request_headers,
22-
)
23-
.await?;
24-
Ok(response)
25-
}

0 commit comments

Comments
 (0)