Skip to content

Commit 49d752e

Browse files
committed
fix: errors in Postgres examples, update examples/x.py
1 parent 643aa7a commit 49d752e

14 files changed

Lines changed: 92 additions & 53 deletions

File tree

examples/postgres/chat/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ workspace = "../../../"
77
[dependencies]
88
sqlx = { path = "../../../", features = [ "postgres", "runtime-tokio", "tls-native-tls" ] }
99
tokio = { version = "1.25.0", features = [ "rt-multi-thread", "macros" ] }
10-
ratatui = "0.27.0"
11-
crossterm = "0.27.0"
12-
unicode-width = "0.1.13"
10+
ratatui = "0.30.0"
11+
crossterm = "0.29.0"
12+
unicode-width = "0.2.2"

examples/postgres/chat/src/main.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,10 @@ impl ChatApp {
3838
mut self,
3939
terminal: &mut Terminal<B>,
4040
mut listener: PgListener,
41-
) -> Result<(), Box<dyn Error>> {
41+
) -> Result<(), Box<dyn Error>>
42+
where
43+
<B as Backend>::Error: 'static,
44+
{
4245
// setup listener task
4346
let messages = self.messages.clone();
4447
tokio::spawn(async move {

examples/postgres/multi-database/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ authors.workspace = true
1111
[dependencies]
1212
tokio = { version = "1.25.0", features = ["rt-multi-thread", "macros"] }
1313

14-
color-eyre = "0.6.3"
14+
color-eyre = "0.6.5"
1515
dotenvy = "0.15.7"
1616
tracing-subscriber = "0.3.19"
1717

examples/postgres/multi-database/accounts/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ edition = "2021"
77
sqlx = { workspace = true, features = ["postgres", "time", "uuid", "macros", "sqlx-toml"] }
88
tokio = { version = "1.25.0", features = ["rt", "sync"] }
99

10-
argon2 = { version = "0.5.3", features = ["password-hash"] }
10+
# FIXME: update when `0.6.0` is released
11+
argon2 = { version = "0.6.0-rc.8", features = ["password-hash"] }
1112
password-hash = { version = "0.6.1", features = ["alloc"] }
1213

1314
uuid = { version = "1.12.1", features = ["serde"] }

examples/postgres/multi-database/accounts/sqlx.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ database-url-var = "ACCOUNTS_DATABASE_URL"
33

44
[macros.table-overrides.'account']
55
'account_id' = "crate::AccountId"
6-
'password_hash' = "sqlx::types::Text<password_hash::PasswordHashString>"
6+
'password_hash' = "sqlx::types::Text<password_hash::phc::PasswordHash>"
77

88
[macros.table-overrides.'session']
99
'session_token' = "crate::SessionToken"

examples/postgres/multi-database/accounts/src/lib.rs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use argon2::{password_hash, Argon2, PasswordHasher, PasswordVerifier};
2-
use password_hash::PasswordHashString;
3-
use rand::distributions::{Alphanumeric, DistString};
2+
use password_hash::phc::PasswordHash;
3+
use rand::distr::{Alphanumeric, SampleString};
44
use sqlx::PgPool;
55
use std::sync::Arc;
66
use uuid::Uuid;
@@ -130,7 +130,7 @@ impl AccountsManager {
130130
})
131131
}
132132

133-
async fn hash_password(&self, password: String) -> Result<PasswordHashString, GeneralError> {
133+
async fn hash_password(&self, password: String) -> Result<PasswordHash, GeneralError> {
134134
let guard = self
135135
.hashing_semaphore
136136
.clone()
@@ -141,13 +141,7 @@ impl AccountsManager {
141141
// We transfer ownership to the blocking task and back to ensure Tokio doesn't spawn
142142
// excess threads.
143143
let (_guard, res) = tokio::task::spawn_blocking(move || {
144-
let salt = password_hash::SaltString::generate(rand::thread_rng());
145-
(
146-
guard,
147-
Argon2::default()
148-
.hash_password(password.as_bytes(), &salt)
149-
.map(|hash| hash.serialize()),
150-
)
144+
(guard, Argon2::default().hash_password(password.as_bytes()))
151145
})
152146
.await?;
153147

@@ -157,7 +151,7 @@ impl AccountsManager {
157151
async fn verify_password(
158152
&self,
159153
password: String,
160-
hash: PasswordHashString,
154+
hash: PasswordHash,
161155
) -> Result<(), CreateSessionError> {
162156
let guard = self
163157
.hashing_semaphore
@@ -169,13 +163,13 @@ impl AccountsManager {
169163
let (_guard, res) = tokio::task::spawn_blocking(move || {
170164
(
171165
guard,
172-
Argon2::default().verify_password(password.as_bytes(), &hash.password_hash()),
166+
Argon2::default().verify_password(password.as_bytes(), &hash),
173167
)
174168
})
175169
.await
176170
.map_err(GeneralError::from)?;
177171

178-
if let Err(password_hash::Error::Password) = res {
172+
if let Err(password_hash::Error::PasswordInvalid) = res {
179173
return Err(CreateSessionError::InvalidPassword);
180174
}
181175

@@ -200,7 +194,9 @@ impl AccountsManager {
200194
values ($1, $2) \
201195
returning account_id",
202196
email,
203-
hash.as_str(),
197+
// However, since arguments don't link back to the target column,
198+
// SQLx doesn't know that `PasswordHash` would be a valid argument here.
199+
hash.to_string(),
204200
)
205201
.fetch_one(&self.pool)
206202
.await
@@ -230,7 +226,7 @@ impl AccountsManager {
230226

231227
// Thanks to `sqlx.toml`:
232228
// * `account_id` maps to `AccountId`
233-
// * `password_hash` maps to `Text<PasswordHashString>`
229+
// * `password_hash` maps to `Text<PasswordHash>`
234230
// * `session_token` maps to `SessionToken`
235231
let maybe_account = sqlx::query!(
236232
// language=PostgreSQL
@@ -288,6 +284,6 @@ impl SessionToken {
288284
const LEN: usize = 32;
289285

290286
fn generate() -> Self {
291-
SessionToken(Alphanumeric.sample_string(&mut rand::thread_rng(), Self::LEN))
287+
SessionToken(Alphanumeric.sample_string(&mut rand::rng(), Self::LEN))
292288
}
293289
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from os import path
2+
3+
def setup(database_url, cwd, sqlx):
4+
accounts_url = f"{database_url}-accounts"
5+
payments_url = f"{database_url}-payments"
6+
7+
sqlx("db reset -y", accounts_url, cwd=path.join(cwd, "accounts"))
8+
sqlx("db reset -y", payments_url, cwd=path.join(cwd, "payments"))
9+
10+
return {"ACCOUNTS_DATABASE_URL": accounts_url, "PAYMENTS_DATABASE_URL": payments_url}

examples/postgres/multi-database/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use accounts::AccountsManager;
22
use color_eyre::eyre;
33
use color_eyre::eyre::{Context, OptionExt};
44
use payments::PaymentsManager;
5-
use rand::distributions::{Alphanumeric, DistString};
5+
use rand::distr::{Alphanumeric, SampleString};
66
use sqlx::Connection;
77

88
#[tokio::main]
@@ -42,7 +42,7 @@ async fn main() -> eyre::Result<()> {
4242

4343
// POST /account
4444
let user_email = format!("user{}@example.com", rand::random::<u32>());
45-
let user_password = Alphanumeric.sample_string(&mut rand::thread_rng(), 16);
45+
let user_password = Alphanumeric.sample_string(&mut rand::rng(), 16);
4646

4747
// Requires an externally managed transaction in case any application-specific records
4848
// should be created after the actual account record.

examples/postgres/multi-tenant/accounts/sqlx.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ table-name = "accounts._sqlx_migrations"
44

55
[macros.table-overrides.'accounts.account']
66
'account_id' = "crate::AccountId"
7-
'password_hash' = "sqlx::types::Text<password_hash::PasswordHashString>"
7+
'password_hash' = "sqlx::types::Text<password_hash::phc::PasswordHash>"
88

99
[macros.table-overrides.'accounts.session']
1010
'session_token' = "crate::SessionToken"

examples/postgres/multi-tenant/accounts/src/lib.rs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use argon2::{password_hash, Argon2, PasswordHasher, PasswordVerifier};
2-
use password_hash::PasswordHashString;
3-
use rand::distributions::{Alphanumeric, DistString};
2+
use password_hash::phc::PasswordHash;
3+
use rand::distr::{Alphanumeric, SampleString};
44
use sqlx::{Acquire, Executor, PgTransaction, Postgres};
55
use std::sync::Arc;
66
use uuid::Uuid;
@@ -118,7 +118,7 @@ impl AccountsManager {
118118
})
119119
}
120120

121-
async fn hash_password(&self, password: String) -> Result<PasswordHashString, GeneralError> {
121+
async fn hash_password(&self, password: String) -> Result<PasswordHash, GeneralError> {
122122
let guard = self
123123
.hashing_semaphore
124124
.clone()
@@ -129,13 +129,7 @@ impl AccountsManager {
129129
// We transfer ownership to the blocking task and back to ensure Tokio doesn't spawn
130130
// excess threads.
131131
let (_guard, res) = tokio::task::spawn_blocking(move || {
132-
let salt = password_hash::SaltString::generate(rand::thread_rng());
133-
(
134-
guard,
135-
Argon2::default()
136-
.hash_password(password.as_bytes(), &salt)
137-
.map(|hash| hash.serialize()),
138-
)
132+
(guard, Argon2::default().hash_password(password.as_bytes()))
139133
})
140134
.await?;
141135

@@ -145,7 +139,7 @@ impl AccountsManager {
145139
async fn verify_password(
146140
&self,
147141
password: String,
148-
hash: PasswordHashString,
142+
hash: PasswordHash,
149143
) -> Result<(), CreateSessionError> {
150144
let guard = self
151145
.hashing_semaphore
@@ -157,13 +151,13 @@ impl AccountsManager {
157151
let (_guard, res) = tokio::task::spawn_blocking(move || {
158152
(
159153
guard,
160-
Argon2::default().verify_password(password.as_bytes(), &hash.password_hash()),
154+
Argon2::default().verify_password(password.as_bytes(), &hash),
161155
)
162156
})
163157
.await
164158
.map_err(GeneralError::from)?;
165159

166-
if let Err(password_hash::Error::Password) = res {
160+
if let Err(password_hash::Error::PasswordInvalid) = res {
167161
return Err(CreateSessionError::InvalidPassword);
168162
}
169163

@@ -189,7 +183,9 @@ impl AccountsManager {
189183
values ($1, $2) \
190184
returning account_id",
191185
email,
192-
hash.as_str(),
186+
// However, since arguments don't link back to the target column,
187+
// SQLx doesn't know that `PasswordHash` would be a valid argument here.
188+
hash.to_string(),
193189
)
194190
.fetch_one(&mut **txn)
195191
.await
@@ -220,7 +216,7 @@ impl AccountsManager {
220216

221217
// Thanks to `sqlx.toml`:
222218
// * `account_id` maps to `AccountId`
223-
// * `password_hash` maps to `Text<PasswordHashString>`
219+
// * `password_hash` maps to `Text<PasswordHash>`
224220
// * `session_token` maps to `SessionToken`
225221
let maybe_account = sqlx::query!(
226222
// language=PostgreSQL
@@ -279,6 +275,6 @@ impl SessionToken {
279275
const LEN: usize = 32;
280276

281277
fn generate() -> Self {
282-
SessionToken(Alphanumeric.sample_string(&mut rand::thread_rng(), Self::LEN))
278+
SessionToken(Alphanumeric.sample_string(&mut rand::rng(), Self::LEN))
283279
}
284280
}

0 commit comments

Comments
 (0)