Skip to content

Commit

Permalink
fix: improve facades
Browse files Browse the repository at this point in the history
  • Loading branch information
conblem committed Feb 11, 2021
1 parent 12fcb18 commit 4cc2397
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 84 deletions.
39 changes: 31 additions & 8 deletions src/api/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,24 +105,47 @@ impl<F: CertFacade> Acceptor<F> {

#[cfg(test)]
mod tests {
use rustls::{ClientConfig, NoClientAuth, ServerConfig};
use futures_util::{future, stream, StreamExt};
use rustls::{
Certificate, ClientConfig, RootCertStore, ServerCertVerified, ServerCertVerifier, TLSError,
};
use std::sync::Arc;
use tokio_rustls::webpki::DNSNameRef;
use tokio_rustls::{TlsAcceptor, TlsConnector};
use tokio_rustls::TlsConnector;

use super::wrap;
use crate::facade::TestFacade;

async fn _test() {
let (client, server) = tokio::io::duplex(64);
let server = stream::once(future::ready(Ok(future::ready(Ok(server)))));
let mut acceptor = wrap(server, TestFacade::default());

let server_future = tokio::spawn(async move {
let server_config = ServerConfig::new(NoClientAuth::new());
let acceptor = TlsAcceptor::from(Arc::new(server_config));

acceptor.accept(server).await.unwrap();
acceptor.next().await.unwrap().unwrap().await.unwrap();
});

struct TestVerifier;
impl ServerCertVerifier for TestVerifier {
fn verify_server_cert(
&self,
_roots: &RootCertStore,
presented_certs: &[Certificate],
_dns_name: DNSNameRef<'_>,
_ocsp_response: &[u8],
) -> Result<ServerCertVerified, TLSError> {
println!("{:?}", presented_certs);
Ok(ServerCertVerified::assertion())
}
}

let client_future = tokio::spawn(async move {
let client_config = Arc::new(ClientConfig::new());
let connector = TlsConnector::from(client_config);
let mut client_config = ClientConfig::new();
client_config
.dangerous()
.set_certificate_verifier(Arc::new(TestVerifier {}));

let connector = TlsConnector::from(Arc::new(client_config));

let domain = DNSNameRef::try_from_ascii_str("google.com").unwrap();
connector.connect(domain, client).await.unwrap();
Expand Down
158 changes: 107 additions & 51 deletions src/facade/cert.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use anyhow::Result;
use async_trait::async_trait;
use sqlx::FromRow;
use sqlx::{Executor, Postgres};
use sqlx::{Database, Executor, Postgres};
use tracing::info;
use uuid::Uuid;

use super::domain::{create_domain, Domain};
use super::PostgresFacade;
use super::domain::{Domain, DomainFacadeInternal};
use super::DatabaseFacade;
use crate::facade::TestFacade;
use crate::util::{now, to_i64, HOUR};

#[derive(sqlx::Type, Debug, PartialEq, Clone)]
Expand Down Expand Up @@ -56,71 +57,97 @@ pub trait CertFacade {
async fn stop_cert(&self, memory_cert: &mut Cert) -> Result<(), sqlx::Error>;
}

async fn first_cert<'a, E: Executor<'a, Database = Postgres>>(
executor: E,
) -> Result<Option<Cert>, sqlx::Error> {
sqlx::query_as("SELECT * FROM cert LIMIT 1")
.fetch_optional(executor)
.await
#[async_trait]
trait CertFacadeInternal<DB: Database> {
async fn first_cert<'a, E: Executor<'a, Database = DB>>(
&self,
executor: E,
) -> Result<Option<Cert>, sqlx::Error>;

async fn update_cert<'a, E: Executor<'a, Database = DB>>(
&self,
executor: E,
cert: &Cert,
) -> Result<(), sqlx::Error>;

async fn create_cert<'a, E: Executor<'a, Database = DB>>(
&self,
executor: E,
cert: &Cert,
) -> Result<(), sqlx::Error>;
}

async fn update_cert<'a, E: Executor<'a, Database = Postgres>>(
executor: E,
cert: &Cert,
) -> Result<(), sqlx::Error> {
sqlx::query("UPDATE cert SET update = $1, state = $2, cert = $3, private = $4, domain_id = $5 WHERE id = $6")
.bind(&cert.update)
.bind(&cert.state)
.bind(&cert.cert)
.bind(&cert.private)
.bind(&cert.domain)
.bind(&cert.id)
.execute(executor)
.await?;

Ok(())
}
#[async_trait]
impl CertFacadeInternal<Postgres> for DatabaseFacade<Postgres> {
async fn first_cert<'a, E: Executor<'a, Database = Postgres>>(
&self,
executor: E,
) -> Result<Option<Cert>, sqlx::Error> {
sqlx::query_as("SELECT * FROM cert LIMIT 1")
.fetch_optional(executor)
.await
}

async fn update_cert<'a, E: Executor<'a, Database = Postgres>>(
&self,
executor: E,
cert: &Cert,
) -> Result<(), sqlx::Error> {
sqlx::query("UPDATE cert SET update = $1, state = $2, cert = $3, private = $4, domain_id = $5 WHERE id = $6")
.bind(&cert.update)
.bind(&cert.state)
.bind(&cert.cert)
.bind(&cert.private)
.bind(&cert.domain)
.bind(&cert.id)
.execute(executor)
.await?;

Ok(())
}

async fn create_cert<'a, E: Executor<'a, Database = Postgres>>(
executor: E,
cert: &Cert,
) -> Result<(), sqlx::Error> {
sqlx::query("INSERT INTO cert (id, update, state, cert, private, domain_id) VALUES ($1, $2, $3, $4, $5, $6)")
.bind(&cert.id)
.bind(&cert.update)
.bind(&cert.state)
.bind(&cert.cert)
.bind(&cert.private)
.bind(&cert.domain)
.execute(executor)
.await?;

Ok(())
async fn create_cert<'a, E: Executor<'a, Database = Postgres>>(
&self,
executor: E,
cert: &Cert,
) -> Result<(), sqlx::Error> {
sqlx::query("INSERT INTO cert (id, update, state, cert, private, domain_id) VALUES ($1, $2, $3, $4, $5, $6)")
.bind(&cert.id)
.bind(&cert.update)
.bind(&cert.state)
.bind(&cert.cert)
.bind(&cert.private)
.bind(&cert.domain)
.execute(executor)
.await?;

Ok(())
}
}

#[async_trait]
impl CertFacade for PostgresFacade {
impl CertFacade for DatabaseFacade<Postgres> {
async fn first_cert(&self) -> Result<Option<Cert>, sqlx::Error> {
first_cert(&self.pool).await
CertFacadeInternal::first_cert(self, &self.pool).await
}

async fn update_cert(&self, cert: &Cert) -> Result<(), sqlx::Error> {
update_cert(&self.pool, cert).await
CertFacadeInternal::update_cert(self, &self.pool, cert).await
}

async fn create_cert(&self, cert: &Cert) -> Result<(), sqlx::Error> {
create_cert(&self.pool, cert).await
CertFacadeInternal::create_cert(self, &self.pool, cert).await
}

async fn start_cert(&self) -> Result<Option<Cert>> {
let mut transaction = self.pool.begin().await?;

let cert = first_cert(&mut transaction).await?;
let cert = CertFacadeInternal::first_cert(self, &mut transaction).await?;

let cert = match cert {
Some(mut cert) if cert.state == State::Ok => {
cert.state = State::Updating;
update_cert(&mut transaction, &cert).await?;
CertFacadeInternal::update_cert(self, &mut transaction, &cert).await?;
Some(cert)
}
Some(mut cert) => {
Expand All @@ -130,7 +157,7 @@ impl CertFacade for PostgresFacade {
if cert.update < one_hour_ago {
cert.update = now;
cert.state = State::Updating;
update_cert(&mut transaction, &cert).await?;
CertFacadeInternal::update_cert(self, &mut transaction, &cert).await?;
Some(cert)
} else {
info!("job still in progress");
Expand All @@ -141,8 +168,8 @@ impl CertFacade for PostgresFacade {
let domain = Domain::new()?;
let cert = Cert::new(&domain);

create_domain(&mut transaction, &domain).await?;
create_cert(&mut transaction, &cert).await?;
DomainFacadeInternal::create_domain(self, &mut transaction, &domain).await?;
CertFacadeInternal::create_cert(self, &mut transaction, &cert).await?;
Some(cert)
}
};
Expand All @@ -155,10 +182,10 @@ impl CertFacade for PostgresFacade {
async fn stop_cert(&self, memory_cert: &mut Cert) -> Result<(), sqlx::Error> {
let mut transaction = self.pool.begin().await?;

match first_cert(&mut transaction).await? {
match CertFacadeInternal::first_cert(self, &mut transaction).await? {
Some(cert) if cert.state == State::Updating && cert.update == memory_cert.update => {
memory_cert.state = State::Ok;
update_cert(&self.pool, &memory_cert).await?;
CertFacadeInternal::update_cert(self, &self.pool, &memory_cert).await?;
}
_ => {}
}
Expand All @@ -167,3 +194,32 @@ impl CertFacade for PostgresFacade {
Ok(())
}
}

#[async_trait]
impl CertFacade for TestFacade {
async fn first_cert(&self) -> Result<Option<Cert>, sqlx::Error> {
let certs = self.certs.lock();
Ok(certs.values().next().map(Clone::clone))
}

async fn update_cert(&self, cert: &Cert) -> Result<(), sqlx::Error> {
let mut certs = self.certs.lock();
*certs.get_mut(&cert.id).unwrap() = cert.clone();

Ok(())
}

async fn create_cert(&self, cert: &Cert) -> Result<(), sqlx::Error> {
self.certs.lock().insert(cert.id.clone(), cert.clone());

Ok(())
}

async fn start_cert(&self) -> Result<Option<Cert>> {
unimplemented!()
}

async fn stop_cert(&self, _memory_cert: &mut Cert) -> Result<(), sqlx::Error> {
unimplemented!()
}
}
47 changes: 30 additions & 17 deletions src/facade/domain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use anyhow::{Error, Result};
use async_trait::async_trait;
use core::convert::TryFrom;
use serde::{Deserialize, Serialize};
use sqlx::{Executor, Postgres};
use sqlx::{Database, Executor, Postgres};

use super::PostgresFacade;
use super::DatabaseFacade;
use crate::util::uuid;

#[derive(Debug, Serialize, Clone)]
Expand Down Expand Up @@ -66,23 +66,36 @@ pub trait DomainFacade {
async fn update_domain(&self, domain: &Domain) -> Result<(), sqlx::Error>;
}

pub(super) async fn create_domain<'a, E: Executor<'a, Database = Postgres>>(
executor: E,
domain: &Domain,
) -> Result<(), sqlx::Error> {
sqlx::query("INSERT INTO domain (id, username, password, txt) VALUES ($1, $2, $3, $4)")
.bind(&domain.id)
.bind(&domain.username)
.bind(&domain.password)
.bind(&domain.txt)
.execute(executor)
.await?;

Ok(())
#[async_trait]
pub(super) trait DomainFacadeInternal<DB: Database> {
async fn create_domain<'a, E: Executor<'a, Database = DB>>(
&self,
executor: E,
domain: &Domain,
) -> Result<(), sqlx::Error>;
}

#[async_trait]
impl DomainFacadeInternal<Postgres> for DatabaseFacade<Postgres> {
async fn create_domain<'a, E: Executor<'a, Database = Postgres>>(
&self,
executor: E,
domain: &Domain,
) -> Result<(), sqlx::Error> {
sqlx::query("INSERT INTO domain (id, username, password, txt) VALUES ($1, $2, $3, $4)")
.bind(&domain.id)
.bind(&domain.username)
.bind(&domain.password)
.bind(&domain.txt)
.execute(executor)
.await?;

Ok(())
}
}

#[async_trait]
impl DomainFacade for PostgresFacade {
impl DomainFacade for DatabaseFacade<Postgres> {
async fn find_domain_by_id(&self, id: &str) -> Result<Option<Domain>, sqlx::Error> {
sqlx::query_as("SELECT * FROM domain WHERE id = $1 LIMIT 1")
.bind(id)
Expand All @@ -91,7 +104,7 @@ impl DomainFacade for PostgresFacade {
}

async fn create_domain(&self, domain: &Domain) -> Result<(), sqlx::Error> {
create_domain(&self.pool, domain).await
DomainFacadeInternal::create_domain(self, &self.pool, domain).await
}

async fn update_domain(&self, domain: &Domain) -> Result<(), sqlx::Error> {
Expand Down
29 changes: 23 additions & 6 deletions src/facade/mod.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,35 @@
use sqlx::PgPool;
use parking_lot::Mutex;
use sqlx::{Database, PgPool, Pool, Postgres};
use std::collections::HashMap;
use std::sync::Arc;

mod cert;
mod domain;

pub use cert::{Cert, CertFacade, State};
pub use domain::{Domain, DomainDTO, DomainFacade};

#[derive(Debug, Clone)]
pub(super) struct PostgresFacade {
pool: PgPool,
#[derive(Debug)]
pub(super) struct DatabaseFacade<DB: Database> {
pool: Pool<DB>,
}

impl From<PgPool> for PostgresFacade {
impl<DB: Database> Clone for DatabaseFacade<DB> {
fn clone(&self) -> Self {
DatabaseFacade {
pool: self.pool.clone(),
}
}
}

impl From<PgPool> for DatabaseFacade<Postgres> {
fn from(pool: PgPool) -> Self {
PostgresFacade { pool }
DatabaseFacade { pool }
}
}

#[derive(Default, Clone)]
pub(super) struct TestFacade {
certs: Arc<Mutex<HashMap<String, Cert>>>,
//domains: Mutex<HashMap<String, Domain>>,
}
Loading

0 comments on commit 4cc2397

Please sign in to comment.