This repository has been archived on 2025-07-31. You can view files and clone it, but cannot push or open issues or pull requests.
Files
veil/src/models/interface.rs
2025-03-29 11:56:35 +00:00

117 lines
3.3 KiB
Rust

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))))
}
}