impl GatewaysDetailsStore for OnDiskGatewaysDetails

without the underlying sql
This commit is contained in:
Jędrzej Stuczyński
2024-03-08 16:02:06 +00:00
parent b4e45ef3ef
commit 40f08dcbb2
7 changed files with 234 additions and 39 deletions
@@ -34,3 +34,6 @@ CREATE TABLE custom_gateway_details
data BLOB
);
INSERT INTO active_gateway(id, active_gateway_id_bs58)
values (0, NULL);
@@ -1,7 +1,12 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::backend::fs_backend::error::StorageError;
use crate::{
backend::fs_backend::error::StorageError,
types::{
RawActiveGateway, RawCustomGatewayDetails, RawRegisteredGateway, RawRemoteGatewayDetails,
},
};
use log::{error, info};
use sqlx::ConnectOptions;
use std::path::Path;
@@ -47,4 +52,89 @@ impl StorageManager {
info!("Database migration finished!");
Ok(StorageManager { connection_pool })
}
pub(crate) async fn get_active_gateway(&self) -> Result<RawActiveGateway, sqlx::Error> {
todo!()
}
pub(crate) async fn set_active_gateway(
&self,
gateway_id: Option<&str>,
) -> Result<(), sqlx::Error> {
todo!()
}
pub(crate) async fn maybe_get_registered_gateway(
&self,
gateway_id: &str,
) -> Result<Option<RawRegisteredGateway>, sqlx::Error> {
todo!()
}
pub(crate) async fn must_get_registered_gateway(
&self,
gateway_id: &str,
) -> Result<RawRegisteredGateway, sqlx::Error> {
todo!()
}
pub(crate) async fn set_registered_gateway(
&self,
registered_gateway: &RawRegisteredGateway,
) -> Result<(), sqlx::Error> {
todo!()
}
pub(crate) async fn remove_registered_gateway(
&self,
gateway_id: &str,
) -> Result<(), sqlx::Error> {
todo!()
}
pub(crate) async fn get_remote_gateway_details(
&self,
gateway_id: &str,
) -> Result<RawRemoteGatewayDetails, sqlx::Error> {
todo!()
}
pub(crate) async fn set_remote_gateway_details(
&self,
remote: &RawRemoteGatewayDetails,
) -> Result<(), sqlx::Error> {
todo!()
}
pub(crate) async fn remove_remote_gateway_details(
&self,
gateway_id: &str,
) -> Result<(), sqlx::Error> {
todo!()
}
pub(crate) async fn get_custom_gateway_details(
&self,
gateway_id: &str,
) -> Result<RawCustomGatewayDetails, sqlx::Error> {
todo!()
}
pub(crate) async fn set_custom_gateway_details(
&self,
custom: &RawCustomGatewayDetails,
) -> Result<(), sqlx::Error> {
todo!()
}
pub(crate) async fn remove_custom_gateway_details(
&self,
gateway_id: &str,
) -> Result<(), sqlx::Error> {
todo!()
}
pub(crate) async fn registered_gateways(&self) -> Result<Vec<String>, sqlx::Error> {
todo!()
}
}
@@ -1,10 +1,13 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::types::GatewayRegistration;
use crate::{ActiveGateway, GatewaysDetailsStore, StorageError};
use crate::{
ActiveGateway, BadGateway, GatewayDetails, GatewayRegistration, GatewayType,
GatewaysDetailsStore, StorageError,
};
use async_trait::async_trait;
use manager::StorageManager;
use nym_crypto::asymmetric::identity::PublicKey;
use std::path::Path;
pub mod error;
@@ -28,36 +31,120 @@ impl GatewaysDetailsStore for OnDiskGatewaysDetails {
type StorageError = error::StorageError;
async fn has_gateway_details(&self, gateway_id: &str) -> Result<bool, Self::StorageError> {
todo!()
Ok(self
.manager
.maybe_get_registered_gateway(gateway_id)
.await?
.is_some())
}
async fn active_gateway(&self) -> Result<ActiveGateway, Self::StorageError> {
todo!()
let raw_active = self.manager.get_active_gateway().await?;
let registration = match raw_active.active_gateway_id_bs58 {
None => None,
Some(gateway_id) => Some(self.load_gateway_details(&gateway_id).await?),
};
Ok(ActiveGateway { registration })
}
async fn set_active_gateway(&self, gateway_id: &str) -> Result<(), Self::StorageError> {
todo!()
Ok(self.manager.set_active_gateway(Some(gateway_id)).await?)
}
async fn all_gateways(&self) -> Result<Vec<GatewayRegistration>, Self::StorageError> {
todo!()
let identities = self.manager.registered_gateways().await?;
let mut registered = Vec::with_capacity(identities.len());
for gateway_id in identities {
registered.push(self.load_gateway_details(&gateway_id).await?)
}
Ok(registered)
}
async fn all_gateways_identities(&self) -> Result<Vec<PublicKey>, Self::StorageError> {
Ok(self
.manager
.registered_gateways()
.await?
.into_iter()
.map(|gateway_id| {
gateway_id
.as_str()
.parse()
.map_err(|source| BadGateway::MalformedGatewayIdentity { gateway_id, source })
})
.collect::<Result<_, _>>()?)
}
async fn load_gateway_details(
&self,
gateway_id: &str,
) -> Result<GatewayRegistration, Self::StorageError> {
todo!()
let raw_registration = self.manager.must_get_registered_gateway(gateway_id).await?;
let typ: GatewayType = raw_registration.gateway_type.parse()?;
let details = match typ {
GatewayType::Remote => {
let raw_details = self.manager.get_remote_gateway_details(gateway_id).await?;
GatewayDetails::Remote(raw_details.try_into()?)
}
GatewayType::Custom => {
let raw_details = self.manager.get_custom_gateway_details(gateway_id).await?;
GatewayDetails::Custom(raw_details.try_into()?)
}
};
Ok(GatewayRegistration {
details,
registration_timestamp: raw_registration.registration_timestamp,
})
}
async fn store_gateway_details(
&self,
details: &GatewayRegistration,
) -> Result<(), Self::StorageError> {
todo!()
let raw_registration = details.into();
self.manager
.set_registered_gateway(&raw_registration)
.await?;
match &details.details {
GatewayDetails::Remote(remote_details) => {
let raw_details = remote_details.into();
self.manager
.set_remote_gateway_details(&raw_details)
.await?;
}
GatewayDetails::Custom(custom_details) => {
let raw_details = custom_details.into();
self.manager
.set_custom_gateway_details(&raw_details)
.await?;
}
}
Ok(())
}
// ideally all of those should be run under a storage tx to ensure storage consistency,
// but at that point it's fine
async fn remove_gateway_details(&self, gateway_id: &str) -> Result<(), Self::StorageError> {
todo!()
let active = self.manager.get_active_gateway().await?;
if let Some(currently_active) = &active.active_gateway_id_bs58 {
if currently_active == gateway_id {
self.manager.set_active_gateway(None).await?;
}
}
// just try remove it from all tables even if it doesn't actually exist
self.manager.remove_registered_gateway(gateway_id).await?;
self.manager
.remove_remote_gateway_details(gateway_id)
.await?;
self.manager
.remove_custom_gateway_details(gateway_id)
.await?;
Ok(())
}
}
+12 -19
View File
@@ -37,6 +37,18 @@ pub trait GatewaysDetailsStore {
/// Returns details of all registered gateways.
async fn all_gateways(&self) -> Result<Vec<GatewayRegistration>, Self::StorageError>;
/// Return identity keys of all registered gateways.
async fn all_gateways_identities(
&self,
) -> Result<Vec<identity::PublicKey>, Self::StorageError> {
Ok(self
.all_gateways()
.await?
.into_iter()
.map(|gateway| gateway.details.gateway_id())
.collect())
}
/// Check if the gateway with the provided id already exists in the store.
async fn has_gateway_details(&self, gateway_id: &str) -> Result<bool, Self::StorageError>;
@@ -55,22 +67,3 @@ pub trait GatewaysDetailsStore {
/// Remove given gateway details from the underlying store.
async fn remove_gateway_details(&self, gateway_id: &str) -> Result<(), Self::StorageError>;
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait GatewaysDetailsStoreExt: GatewaysDetailsStore {
async fn all_gateways_identities(
&self,
) -> Result<Vec<identity::PublicKey>, Self::StorageError> {
Ok(self
.all_gateways()
.await?
.into_iter()
.map(|gateway| gateway.details.gateway_id())
.collect())
}
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl<T> GatewaysDetailsStoreExt for T where T: GatewaysDetailsStore {}
@@ -27,6 +27,16 @@ pub struct GatewayRegistration {
pub registration_timestamp: OffsetDateTime,
}
impl<'a> From<&'a GatewayRegistration> for RawRegisteredGateway {
fn from(value: &'a GatewayRegistration) -> Self {
RawRegisteredGateway {
gateway_id_bs58: value.details.gateway_id().to_base58_string(),
registration_timestamp: value.registration_timestamp,
gateway_type: value.details.typ().to_string(),
}
}
}
#[derive(Debug, Clone)]
pub enum GatewayDetails {
/// Standard details of a remote gateway
@@ -83,6 +93,13 @@ impl GatewayDetails {
pub fn is_custom(&self) -> bool {
matches!(self, GatewayDetails::Custom(..))
}
pub fn typ(&self) -> GatewayType {
match self {
GatewayDetails::Remote(_) => GatewayType::Remote,
GatewayDetails::Custom(_) => GatewayType::Custom,
}
}
}
#[derive(Debug, Copy, Clone, Default)]
@@ -116,6 +133,12 @@ impl Display for GatewayType {
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
pub struct RawActiveGateway {
pub active_gateway_id_bs58: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
pub struct RawRegisteredGateway {
@@ -205,8 +228,8 @@ impl TryFrom<RawRemoteGatewayDetails> for RemoteGatewayDetails {
}
}
impl From<RemoteGatewayDetails> for RawRemoteGatewayDetails {
fn from(value: RemoteGatewayDetails) -> Self {
impl<'a> From<&'a RemoteGatewayDetails> for RawRemoteGatewayDetails {
fn from(value: &'a RemoteGatewayDetails) -> Self {
RawRemoteGatewayDetails {
gateway_id_bs58: value.gateway_id.to_base58_string(),
derived_aes128_ctr_blake3_hmac_keys_bs58: value
@@ -214,7 +237,7 @@ impl From<RemoteGatewayDetails> for RawRemoteGatewayDetails {
.to_base58_string(),
gateway_owner_address: value.gateway_owner_address.to_string(),
gateway_listener: value.gateway_listener.to_string(),
wg_tun_address: value.wg_tun_address.map(|addr| addr.to_string()),
wg_tun_address: value.wg_tun_address.as_ref().map(|addr| addr.to_string()),
}
}
}
@@ -260,11 +283,12 @@ impl TryFrom<RawCustomGatewayDetails> for CustomGatewayDetails {
}
}
impl From<CustomGatewayDetails> for RawCustomGatewayDetails {
fn from(value: CustomGatewayDetails) -> Self {
impl<'a> From<&'a CustomGatewayDetails> for RawCustomGatewayDetails {
fn from(value: &'a CustomGatewayDetails) -> Self {
RawCustomGatewayDetails {
gateway_id_bs58: value.gateway_id.to_base58_string(),
data: value.data,
// I don't know what to feel about that clone here given it might contain possibly sensitive data
data: value.data.clone(),
}
}
}
@@ -4,9 +4,7 @@
use crate::client::key_manager::persistence::KeyStore;
use crate::client::key_manager::ClientKeys;
use crate::error::ClientCoreError;
use nym_client_core_gateways_storage::{
ActiveGateway, GatewayRegistration, GatewaysDetailsStore, GatewaysDetailsStoreExt,
};
use nym_client_core_gateways_storage::{ActiveGateway, GatewayRegistration, GatewaysDetailsStore};
use nym_crypto::asymmetric::identity;
// helpers for error wrapping
@@ -28,7 +28,7 @@ use nym_credential_storage::persistent_storage::PersistentStorage as PersistentC
pub use nym_client_core_gateways_storage::{
CustomGatewayDetails, GatewayDetails, GatewayRegistration, GatewayType, GatewaysDetailsStore,
GatewaysDetailsStoreExt, InMemGatewaysDetails, RegisteredGateway, RemoteGatewayDetails,
InMemGatewaysDetails, RegisteredGateway, RemoteGatewayDetails,
};
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-gateways-storage"))]