wildland_http_client/sc/
client.rs

1//
2// Wildland Project
3//
4// Copyright © 2022 Golem Foundation
5//
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License version 3 as published by
8// the Free Software Foundation.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program.  If not, see <https://www.gnu.org/licenses/>.
17
18use std::rc::Rc;
19
20use serde::Serialize;
21use wildland_crypto::identity::signing_keypair::SigningKeypair;
22
23use super::constants::WILDLAND_SIGNATURE_HEADER;
24use super::models::{
25    CreateCredentialsReq,
26    CreateCredentialsRes,
27    CreateStorageRes,
28    RequestMetricsReq,
29    RequestMetricsRes,
30    SignatureRequestReq,
31    SignatureRequestRes,
32};
33use crate::cross_platform_http_client::{CurrentPlatformClient, HttpClient, Request};
34use crate::error::WildlandHttpClientError;
35use crate::response_handler::check_status_code;
36
37#[derive(Debug)]
38pub struct Credentials {
39    pub id: String,
40    pub secret: String,
41}
42
43#[derive(Clone)]
44pub struct StorageControllerClient {
45    // TODO:WILX-210 credentials are provided here only for test purposes. Remove it and get real id and secret assigned to a lease
46    pub credential_id: String,
47    pub credential_secret: String,
48    http_client: Rc<dyn HttpClient>,
49}
50
51impl StorageControllerClient {
52    #[tracing::instrument(level = "debug", skip_all)]
53    pub fn new(base_url: &str) -> Self {
54        let http_client = Rc::new(CurrentPlatformClient {
55            base_url: base_url.into(),
56        });
57
58        Self {
59            credential_id: String::default(),
60            credential_secret: String::default(),
61            http_client,
62        }
63    }
64
65    #[tracing::instrument(level = "debug", skip_all)]
66    pub fn create_storage(&self) -> Result<CreateStorageRes, WildlandHttpClientError> {
67        let request = Request::new("/storage/create");
68        let response = self.http_client.post(request)?;
69        let response = check_status_code(response)?;
70        Ok(response.deserialize()?)
71    }
72
73    #[tracing::instrument(level = "debug", skip_all)]
74    pub fn create_credentials(
75        &self,
76        request: CreateCredentialsReq,
77    ) -> Result<CreateCredentialsRes, WildlandHttpClientError> {
78        let signature = self.sign_request(&request)?;
79        let http_request = Request::new("/credential/create")
80            .with_json(&request)
81            .with_header(WILDLAND_SIGNATURE_HEADER, signature);
82        let response = self.http_client.post(http_request)?;
83        let response = check_status_code(response)?;
84        Ok(response.deserialize()?)
85    }
86
87    #[tracing::instrument(level = "debug", skip_all)]
88    pub fn request_signature(
89        &self,
90        request: SignatureRequestReq,
91    ) -> Result<SignatureRequestRes, WildlandHttpClientError> {
92        let signature = self.sign_request(&request)?;
93        let http_request = Request::new("/signature/request")
94            .with_json(&request)
95            .with_header(WILDLAND_SIGNATURE_HEADER, signature);
96        let response = self.http_client.post(http_request)?;
97        let response = check_status_code(response)?;
98        Ok(response.deserialize()?)
99    }
100
101    #[tracing::instrument(level = "debug", skip_all)]
102    pub fn request_metrics(
103        &self,
104        request: RequestMetricsReq,
105    ) -> Result<RequestMetricsRes, WildlandHttpClientError> {
106        let signature = self.sign_request(&request)?;
107        let http_request = Request::new("/metrics")
108            .with_json(&request)
109            .with_header(WILDLAND_SIGNATURE_HEADER, signature);
110        let response = self.http_client.post(http_request)?;
111        let response = check_status_code(response)?;
112        Ok(response.deserialize()?)
113    }
114
115    #[tracing::instrument(level = "debug", skip_all)]
116    pub fn get_credential_id(&self) -> &str {
117        &self.credential_id
118    }
119
120    #[tracing::instrument(level = "debug", skip_all)]
121    pub fn get_credential_secret(&self) -> &str {
122        &self.credential_secret
123    }
124
125    #[tracing::instrument(level = "debug", skip_all)]
126    fn sign_request<T>(&self, request: &T) -> Result<String, WildlandHttpClientError>
127    where
128        T: Serialize,
129    {
130        let message = serde_json::to_vec(request).map_err(Rc::new)?;
131        let keypair =
132            SigningKeypair::try_from_str(self.get_credential_id(), self.get_credential_secret())?;
133        let signature = keypair.sign(&message);
134        Ok(signature.encode_signature())
135    }
136}