mirror of
https://github.com/launchbadge/sqlx.git
synced 2025-12-29 21:00:54 +00:00
fix(postgres): Match ~/.pgpass password after URL parsing and fix user and database ordering (#1566)
* fix(postgres): Fixes pgpass so it applies after parsing and matches usernames & databases correctly * chore: Updated unit test * refactor: Previous semantics of PgConnectOptions::default() * refactor: formatting
This commit is contained in:
parent
fca866d0bc
commit
f79d321b78
@ -89,7 +89,7 @@ pub struct PgConnectOptions {
|
||||
|
||||
impl Default for PgConnectOptions {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
Self::new_without_pgpass().apply_pgpass()
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,6 +115,10 @@ impl PgConnectOptions {
|
||||
/// let options = PgConnectOptions::new();
|
||||
/// ```
|
||||
pub fn new() -> Self {
|
||||
Self::new_without_pgpass().apply_pgpass()
|
||||
}
|
||||
|
||||
pub fn new_without_pgpass() -> Self {
|
||||
let port = var("PGPORT")
|
||||
.ok()
|
||||
.and_then(|v| v.parse().ok())
|
||||
@ -126,16 +130,12 @@ impl PgConnectOptions {
|
||||
|
||||
let database = var("PGDATABASE").ok();
|
||||
|
||||
let password = var("PGPASSWORD")
|
||||
.ok()
|
||||
.or_else(|| pgpass::load_password(&host, port, &username, database.as_deref()));
|
||||
|
||||
PgConnectOptions {
|
||||
port,
|
||||
host,
|
||||
socket: None,
|
||||
username,
|
||||
password,
|
||||
password: var("PGPASSWORD").ok(),
|
||||
database,
|
||||
ssl_root_cert: var("PGSSLROOTCERT").ok().map(CertificateInput::from),
|
||||
ssl_mode: var("PGSSLMODE")
|
||||
@ -148,6 +148,19 @@ impl PgConnectOptions {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn apply_pgpass(mut self) -> Self {
|
||||
if self.password.is_none() {
|
||||
self.password = pgpass::load_password(
|
||||
&self.host,
|
||||
self.port,
|
||||
&self.username,
|
||||
self.database.as_deref(),
|
||||
);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the name of the host to connect to.
|
||||
///
|
||||
/// If a host name begins with a slash, it specifies
|
||||
|
||||
@ -11,7 +11,7 @@ impl FromStr for PgConnectOptions {
|
||||
fn from_str(s: &str) -> Result<Self, Error> {
|
||||
let url: Url = s.parse().map_err(Error::config)?;
|
||||
|
||||
let mut options = Self::default();
|
||||
let mut options = Self::new_without_pgpass();
|
||||
|
||||
if let Some(host) = url.host_str() {
|
||||
let host_decoded = percent_decode_str(host);
|
||||
@ -89,6 +89,8 @@ impl FromStr for PgConnectOptions {
|
||||
}
|
||||
}
|
||||
|
||||
let options = options.apply_pgpass();
|
||||
|
||||
Ok(options)
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,13 +90,15 @@ fn load_password_from_line(
|
||||
) -> Option<String> {
|
||||
let whole_line = line;
|
||||
|
||||
// Pgpass line ordering: hostname, port, database, username, password
|
||||
// See: https://www.postgresql.org/docs/9.3/libpq-pgpass.html
|
||||
match line.trim_start().chars().next() {
|
||||
None | Some('#') => None,
|
||||
_ => {
|
||||
matches_next_field(whole_line, &mut line, host)?;
|
||||
matches_next_field(whole_line, &mut line, &port.to_string())?;
|
||||
matches_next_field(whole_line, &mut line, username)?;
|
||||
matches_next_field(whole_line, &mut line, database.unwrap_or_default())?;
|
||||
matches_next_field(whole_line, &mut line, username)?;
|
||||
Some(line.to_owned())
|
||||
}
|
||||
}
|
||||
@ -219,7 +221,7 @@ mod tests {
|
||||
// normal
|
||||
assert_eq!(
|
||||
load_password_from_line(
|
||||
"localhost:5432:foo:bar:baz",
|
||||
"localhost:5432:bar:foo:baz",
|
||||
"localhost",
|
||||
5432,
|
||||
"foo",
|
||||
@ -229,19 +231,19 @@ mod tests {
|
||||
);
|
||||
// wildcard
|
||||
assert_eq!(
|
||||
load_password_from_line("*:5432:foo:bar:baz", "localhost", 5432, "foo", Some("bar")),
|
||||
load_password_from_line("*:5432:bar:foo:baz", "localhost", 5432, "foo", Some("bar")),
|
||||
Some("baz".to_owned())
|
||||
);
|
||||
// accept wildcard with missing db
|
||||
assert_eq!(
|
||||
load_password_from_line("localhost:5432:foo:*:baz", "localhost", 5432, "foo", None),
|
||||
load_password_from_line("localhost:5432:*:foo:baz", "localhost", 5432, "foo", None),
|
||||
Some("baz".to_owned())
|
||||
);
|
||||
|
||||
// doesn't match
|
||||
assert_eq!(
|
||||
load_password_from_line(
|
||||
"thishost:5432:foo:bar:baz",
|
||||
"thishost:5432:bar:foo:baz",
|
||||
"thathost",
|
||||
5432,
|
||||
"foo",
|
||||
@ -252,7 +254,7 @@ mod tests {
|
||||
// malformed entry
|
||||
assert_eq!(
|
||||
load_password_from_line(
|
||||
"localhost:5432:foo:bar",
|
||||
"localhost:5432:bar:foo",
|
||||
"localhost",
|
||||
5432,
|
||||
"foo",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user