db_pool/common/config/
mysql.rs

1/// Privileged MySQL configuration
2#[derive(Clone)]
3pub struct PrivilegedMySQLConfig {
4    pub(crate) username: String,
5    pub(crate) password: Option<String>,
6    pub(crate) host: String,
7    pub(crate) port: u16,
8}
9
10impl PrivilegedMySQLConfig {
11    const DEFAULT_USERNAME: &'static str = "root";
12    const DEFAULT_PASSWORD: Option<String> = None;
13    const DEFAULT_HOST: &'static str = "localhost";
14    const DEFAULT_PORT: u16 = 3306;
15
16    /// Creates a new privileged MySQL configuration
17    /// # Example
18    /// ```
19    /// # use db_pool::PrivilegedMySQLConfig;
20    /// #
21    /// let config = PrivilegedMySQLConfig::new();
22    /// ```
23    /// # Defaults
24    /// - Username: root
25    /// - Password: {blank}
26    /// - Host: localhost
27    /// - Port: 3306
28    #[must_use]
29    pub fn new() -> Self {
30        Self {
31            username: Self::DEFAULT_USERNAME.to_owned(),
32            password: Self::DEFAULT_PASSWORD,
33            host: Self::DEFAULT_HOST.to_owned(),
34            port: Self::DEFAULT_PORT,
35        }
36    }
37
38    /// Creates a new privileged MySQL configuration from environment variables
39    /// # Environment variables
40    /// - `MYSQL_USERNAME`
41    /// - `MYSQL_PASSWORD`
42    /// - `MYSQL_HOST`
43    /// - `MYSQL_PORT`
44    /// # Defaults
45    /// - Username: root
46    /// - Password: {blank}
47    /// - Host: localhost
48    /// - Port: 3306
49    pub fn from_env() -> Result<Self, Error> {
50        use std::env;
51
52        let username = env::var("MYSQL_USERNAME").unwrap_or(Self::DEFAULT_USERNAME.to_owned());
53        let password = env::var("MYSQL_PASSWORD").ok();
54        let host = env::var("MYSQL_HOST").unwrap_or(Self::DEFAULT_HOST.to_owned());
55        let port = env::var("MYSQL_PORT")
56            .map_or(Ok(Self::DEFAULT_PORT), |port| port.parse())
57            .map_err(Error::InvalidPort)?;
58
59        Ok(Self {
60            username,
61            password,
62            host,
63            port,
64        })
65    }
66
67    /// Sets a new username
68    /// # Example
69    /// ```
70    /// # use db_pool::PrivilegedMySQLConfig;
71    /// #
72    /// let config =
73    ///     PrivilegedMySQLConfig::new().username("postgres".to_owned());
74    /// ```
75    #[must_use]
76    pub fn username(self, value: String) -> Self {
77        Self {
78            username: value,
79            ..self
80        }
81    }
82
83    /// Sets a new password
84    /// # Example
85    /// ```
86    /// # use db_pool::PrivilegedMySQLConfig;
87    /// #
88    /// let config = PrivilegedMySQLConfig::new().password(Some("root".to_owned()));
89    /// ```
90    #[must_use]
91    pub fn password(self, value: Option<String>) -> Self {
92        Self {
93            password: value,
94            ..self
95        }
96    }
97
98    /// Sets a new host
99    /// # Example
100    /// ```
101    /// # use db_pool::PrivilegedMySQLConfig;
102    /// #
103    /// let config = PrivilegedMySQLConfig::new().host("localhost".to_owned());
104    /// ```
105    #[must_use]
106    pub fn host(self, value: String) -> Self {
107        Self {
108            host: value,
109            ..self
110        }
111    }
112
113    /// Sets a new port
114    /// # Example
115    /// ```
116    /// # use db_pool::PrivilegedMySQLConfig;
117    /// #
118    /// let config = PrivilegedMySQLConfig::new().port(3306);
119    /// ```
120    #[must_use]
121    pub fn port(self, value: u16) -> Self {
122        Self {
123            port: value,
124            ..self
125        }
126    }
127
128    pub(crate) fn default_connection_url(&self) -> String {
129        let Self {
130            username,
131            password,
132            host,
133            port,
134        } = self;
135        if let Some(password) = password {
136            format!("mysql://{username}:{password}@{host}:{port}")
137        } else {
138            format!("mysql://{username}@{host}:{port}")
139        }
140    }
141
142    pub(crate) fn privileged_database_connection_url(&self, db_name: &str) -> String {
143        let Self {
144            username,
145            password,
146            host,
147            port,
148            ..
149        } = self;
150        if let Some(password) = password {
151            format!("mysql://{username}:{password}@{host}:{port}/{db_name}")
152        } else {
153            format!("mysql://{username}@{host}:{port}/{db_name}")
154        }
155    }
156
157    pub(crate) fn restricted_database_connection_url(
158        &self,
159        username: &str,
160        password: Option<&str>,
161        db_name: &str,
162    ) -> String {
163        let Self { host, port, .. } = self;
164        if let Some(password) = password {
165            format!("mysql://{username}:{password}@{host}:{port}/{db_name}")
166        } else {
167            format!("mysql://{username}@{host}:{port}/{db_name}")
168        }
169    }
170}
171
172#[derive(Debug)]
173pub enum Error {
174    InvalidPort(std::num::ParseIntError),
175}
176
177impl Default for PrivilegedMySQLConfig {
178    fn default() -> Self {
179        Self::new()
180    }
181}
182
183#[cfg(feature = "mysql")]
184impl From<PrivilegedMySQLConfig> for r2d2_mysql::mysql::OptsBuilder {
185    fn from(value: PrivilegedMySQLConfig) -> Self {
186        Self::new()
187            .user(Some(value.username.clone()))
188            .pass(value.password.clone())
189            .ip_or_hostname(Some(value.host.clone()))
190            .tcp_port(value.port)
191    }
192}
193
194#[cfg(feature = "mysql")]
195impl From<PrivilegedMySQLConfig> for r2d2_mysql::mysql::Opts {
196    fn from(value: PrivilegedMySQLConfig) -> Self {
197        r2d2_mysql::mysql::OptsBuilder::from(value).into()
198    }
199}
200
201#[cfg(feature = "sqlx-mysql")]
202impl From<PrivilegedMySQLConfig> for sqlx::mysql::MySqlConnectOptions {
203    fn from(value: PrivilegedMySQLConfig) -> Self {
204        let PrivilegedMySQLConfig {
205            username,
206            password,
207            host,
208            port,
209        } = value;
210
211        let opts = Self::new()
212            .username(username.as_str())
213            .host(host.as_str())
214            .port(port);
215
216        if let Some(password) = password {
217            opts.password(password.as_str())
218        } else {
219            opts
220        }
221    }
222}