1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
use sqlx::ConnectOptions;

use secrecy::ExposeSecret;
use secrecy::Secret;

use sqlx::postgres::PgPoolOptions;
use sqlx::postgres::{PgConnectOptions, PgSslMode};
use sqlx::Pool;
use sqlx::Postgres;

#[derive(serde::Deserialize, Clone)]
pub struct DatabaseSettings {
    pub username: String,
    pub password: Secret<String>,
    pub port: u16,
    pub host: String,
    pub database_name: String,
    pub require_ssl: bool,
}

impl DatabaseSettings {
    pub fn connection_string(&self) -> String {
        format!(
            "postgres://{}:{}@{}:{}/{}",
            self.username,
            self.password.expose_secret(),
            self.host,
            self.port,
            self.database_name
        )
    }

    pub fn connection_string_with_secret(&self) -> String {
        format!(
            "postgres://{}:{}@{}:{}/{}",
            self.username, "*******", self.host, self.port, self.database_name
        )
    }

    // Renamed from `connection_string_without_db`
    pub fn without_db(&self) -> PgConnectOptions {
        let ssl_mode = if self.require_ssl {
            PgSslMode::Require
        } else {
            // Try an encrypted connection, fallback to unencrypted if it fails
            PgSslMode::Prefer
        };

        PgConnectOptions::new()
            .host(&self.host)
            .username(&self.username)
            .password(self.password.expose_secret())
            .port(self.port)
            .ssl_mode(ssl_mode)
    }

    // Renamed from `connection_string`
    pub fn with_db(&self) -> PgConnectOptions {
        let mut options = self.without_db().database(&self.database_name);
        options.log_statements(log::LevelFilter::Debug);
        // options.log_statements(log::LevelFilter::Info);
        // options.disable_statement_logging();

        options
    }

    pub fn connect(&self) -> Pool<Postgres> {
        self.log();

        PgPoolOptions::new()
            .acquire_timeout(std::time::Duration::from_secs(2))
            // `connect_lazy_with` instead of `connect_lazy`
            .connect_lazy_with(self.with_db())
    }

    fn log(&self) {
        let line = format!(
            "PgConnect: connection_string={}",
            self.connection_string_with_secret()
        );

        if !crate::core::cacheable::exists2s(&line) {
            log::info!("{}", line);
            crate::core::cacheable::put2s(&line, "");
        }
    }
}