1pub mod indexer;
5pub mod models;
6pub mod schema;
7
8use dotenvy::dotenv;
9use std::env;
10
11use diesel::{ConnectionError, ConnectionResult};
12use diesel_async::AsyncPgConnection;
13use diesel_async::pooled_connection::AsyncDieselConnectionManager;
14use diesel_async::pooled_connection::ManagerConfig;
15use diesel_async::pooled_connection::bb8::Pool;
16use futures_util::FutureExt;
17use futures_util::future::BoxFuture;
18use std::time::Duration;
19
20pub type PgConnectionPool =
21 diesel_async::pooled_connection::bb8::Pool<diesel_async::AsyncPgConnection>;
22pub type PgPoolConnection<'a> =
23 diesel_async::pooled_connection::bb8::PooledConnection<'a, AsyncPgConnection>;
24
25pub async fn get_connection_pool() -> PgConnectionPool {
26 dotenv().ok();
27
28 let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
29
30 let mut config = ManagerConfig::default();
31 config.custom_setup = Box::new(establish_connection);
32
33 let manager = AsyncDieselConnectionManager::<diesel_async::AsyncPgConnection>::new_with_config(
34 database_url,
35 config,
36 );
37
38 Pool::builder()
39 .connection_timeout(Duration::from_secs(30))
40 .build(manager)
41 .await
42 .expect("Could not build Postgres DB connection pool")
43}
44
45fn establish_connection(config: &str) -> BoxFuture<'_, ConnectionResult<AsyncPgConnection>> {
46 let fut = async {
47 let rustls_config = rustls::ClientConfig::builder()
49 .dangerous()
50 .with_custom_certificate_verifier(std::sync::Arc::new(SkipServerCertCheck))
51 .with_no_client_auth();
52 let tls = tokio_postgres_rustls::MakeRustlsConnect::new(rustls_config);
53 let (client, conn) = tokio_postgres::connect(config, tls)
54 .await
55 .map_err(|e| ConnectionError::BadConnection(e.to_string()))?;
56 tokio::spawn(async move {
57 if let Err(e) = conn.await {
58 eprintln!("Database connection: {e}");
59 }
60 });
61 AsyncPgConnection::try_from(client).await
62 };
63 fut.boxed()
64}
65
66fn root_certs() -> rustls::RootCertStore {
67 rustls::RootCertStore {
68 roots: webpki_roots::TLS_SERVER_ROOTS.to_vec(),
69 }
70}
71
72#[derive(Debug)]
75struct SkipServerCertCheck;
76
77impl rustls::client::danger::ServerCertVerifier for SkipServerCertCheck {
78 fn verify_server_cert(
79 &self,
80 _end_entity: &rustls::pki_types::CertificateDer<'_>,
81 _intermediates: &[rustls::pki_types::CertificateDer<'_>],
82 _server_name: &rustls::pki_types::ServerName<'_>,
83 _ocsp_response: &[u8],
84 _now: rustls::pki_types::UnixTime,
85 ) -> Result<rustls::client::danger::ServerCertVerified, rustls::Error> {
86 Ok(rustls::client::danger::ServerCertVerified::assertion())
87 }
88
89 fn verify_tls12_signature(
90 &self,
91 _message: &[u8],
92 _cert: &rustls::pki_types::CertificateDer<'_>,
93 _dss: &rustls::DigitallySignedStruct,
94 ) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
95 Ok(rustls::client::danger::HandshakeSignatureValid::assertion())
96 }
97
98 fn verify_tls13_signature(
99 &self,
100 _message: &[u8],
101 _cert: &rustls::pki_types::CertificateDer<'_>,
102 _dss: &rustls::DigitallySignedStruct,
103 ) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
104 Ok(rustls::client::danger::HandshakeSignatureValid::assertion())
105 }
106
107 fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
108 rustls::client::WebPkiServerVerifier::builder(std::sync::Arc::new(root_certs()))
109 .build()
110 .unwrap()
111 .supported_verify_schemes()
112 }
113}