feat: add Wireguard interface model
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
116
src/models/interface.rs
Normal file
116
src/models/interface.rs
Normal file
@@ -0,0 +1,116 @@
|
||||
use std::error::Error;
|
||||
|
||||
use base64::{Engine, prelude::BASE64_STANDARD};
|
||||
use sqlx::{PgPool, query, query_as, types::ipnetwork::IpNetwork};
|
||||
use x25519_dalek::StaticSecret;
|
||||
|
||||
use crate::config::WireguardConfig;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Interface {
|
||||
pub name: String,
|
||||
pub address: IpNetwork,
|
||||
pub port: u16,
|
||||
pub private_key: StaticSecret,
|
||||
pub default_network_netmask: u8,
|
||||
}
|
||||
|
||||
struct InterfacePostgres {
|
||||
name: String,
|
||||
address: IpNetwork,
|
||||
port: i32,
|
||||
private_key: Vec<u8>,
|
||||
default_network_netmask: i16,
|
||||
}
|
||||
|
||||
impl TryFrom<WireguardConfig> for Interface {
|
||||
type Error = Box<dyn Error + Send + Sync>;
|
||||
|
||||
fn try_from(config: WireguardConfig) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
name: config.interface,
|
||||
address: config.address,
|
||||
port: config.port,
|
||||
private_key: {
|
||||
let decoded_key = BASE64_STANDARD.decode(config.private_key)?;
|
||||
let key_array: [u8; 32] =
|
||||
decoded_key.try_into().map_err(|_| "Invalid key length")?;
|
||||
StaticSecret::from(key_array)
|
||||
},
|
||||
default_network_netmask: config.default_network_netmask,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// We allow .unwrap() here because we set the lengths of the variables ourselves
|
||||
#[allow(clippy::fallible_impl_from)]
|
||||
impl From<InterfacePostgres> for Interface {
|
||||
fn from(row: InterfacePostgres) -> Self {
|
||||
Self {
|
||||
name: row.name,
|
||||
address: row.address,
|
||||
port: row.port.try_into().unwrap(),
|
||||
private_key: {
|
||||
let key_array: [u8; 32] = row.private_key.try_into().unwrap();
|
||||
StaticSecret::from(key_array)
|
||||
},
|
||||
default_network_netmask: row.default_network_netmask.try_into().unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Interface> for InterfacePostgres {
|
||||
fn from(interface: Interface) -> Self {
|
||||
Self {
|
||||
name: interface.name,
|
||||
address: interface.address,
|
||||
port: i32::from(interface.port),
|
||||
private_key: interface.private_key.to_bytes().to_vec(),
|
||||
default_network_netmask: i16::from(interface.default_network_netmask),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Interface {
|
||||
pub async fn insert(
|
||||
pool: &PgPool,
|
||||
interface: Self,
|
||||
) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
let interface = InterfacePostgres::from(interface);
|
||||
|
||||
query!(
|
||||
r#"
|
||||
INSERT INTO interfaces (name, address, port, private_key, default_network_netmask)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
"#,
|
||||
interface.name,
|
||||
interface.address,
|
||||
interface.port,
|
||||
interface.private_key,
|
||||
interface.default_network_netmask,
|
||||
)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn select_by_name(
|
||||
pool: &PgPool,
|
||||
name: &str,
|
||||
) -> Result<Option<Self>, Box<dyn Error + Send + Sync>> {
|
||||
let row = query_as!(
|
||||
InterfacePostgres,
|
||||
r#"
|
||||
SELECT name, address, port, private_key, default_network_netmask
|
||||
FROM interfaces
|
||||
WHERE name = $1
|
||||
"#,
|
||||
name
|
||||
)
|
||||
.fetch_optional(pool)
|
||||
.await?;
|
||||
|
||||
row.map_or_else(|| Ok(None), |row| Ok(Some(Self::from(row))))
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user