commit 1629f1318b95ce4a14e99fc61ab858561e0b4859
parent 5cb097630d761bc37d8654bc49ab5003513e81d3
Author: Antoine A <>
Date: Thu, 16 Jul 2026 12:30:26 +0200
bank: reconfig password without transaction
Diffstat:
3 files changed, 37 insertions(+), 37 deletions(-)
diff --git a/libeufin-bank/src/api/account.rs b/libeufin-bank/src/api/account.rs
@@ -975,7 +975,7 @@ pub mod test {
}
let name = "Jane";
- let payto = &rand_iban_payto();
+ let payto = rand_iban_payto().full(name);
let req = json!({
"username": "foo",
"password": "password",
@@ -986,7 +986,7 @@ pub mod test {
});
// Check given payto
{
- let full: FullBankPayto = payto.full(name).convert();
+ let full: FullBankPayto = payto.clone().convert();
// Check ok
assert_eq!(
full,
diff --git a/libeufin-bank/src/db/account.rs b/libeufin-bank/src/db/account.rs
@@ -513,46 +513,46 @@ pub async fn reconfig_password(
old_pw: Option<&str>,
is2fa: bool,
) -> sqlx::Result<PatchAuthResult> {
- serialized!(async {
- // TODO use optimistic replace instead of transaction
- let mut tx = db.begin().await?;
-
- let Some((customer_id, currenc_pwh, tan_required)): Option<(i64, String, bool)> =
- sqlx::query_as(
- "
+ let Some((customer_id, currenc_pwh, tan_required)): Option<(i64, String, bool)> = serialized!(
+ sqlx::query_as(
+ "
SELECT customer_id, password_hash, NOT $1 AND cardinality(tan_channels) > 0
FROM customers WHERE username=$2 AND deleted_at IS NULL
",
- )
- .bind(is2fa)
- .bind(username)
- .fetch_optional(&mut *tx)
- .await?
- else {
- return Ok(PatchAuthResult::UnknownAccount);
- };
+ )
+ .bind(is2fa)
+ .bind(username)
+ .fetch_optional(db)
+ )?
+ else {
+ return Ok(PatchAuthResult::UnknownAccount);
+ };
- let res = if let Some(old_pw) = old_pw
- && !pw_crypto.checkpw(old_pw, ¤c_pwh).unwrap().matches
- {
- PatchAuthResult::OldPasswordMismatch
- } else if tan_required {
- PatchAuthResult::TanRequired
- } else {
- let new_pwh = pw_crypto.hashpw(new_pw);
+ let res = if let Some(old_pw) = old_pw
+ && !pw_crypto.checkpw(old_pw, ¤c_pwh).unwrap().matches
+ {
+ PatchAuthResult::OldPasswordMismatch
+ } else if tan_required {
+ PatchAuthResult::TanRequired
+ } else {
+ let new_pwh = pw_crypto.hashpw(new_pw);
+ if serialized!(
sqlx::query(
- "UPDATE customers SET password_hash=$1, token_creation_counter=0 WHERE customer_id=$2",
- )
- .bind(new_pwh)
- .bind(customer_id)
- .execute(&mut *tx)
- .await?;
+ "UPDATE customers SET password_hash=$1, token_creation_counter=0 WHERE customer_id=$2 AND password_hash=$3",
+ )
+ .bind(&new_pwh)
+ .bind(customer_id)
+ .bind(¤c_pwh)
+ .execute(db)
+ )?.rows_affected() > 0 {
PatchAuthResult::Success
- };
+ } else {
+ // If the password hash has changed, it was updated concurrently
+ PatchAuthResult::OldPasswordMismatch
+ }
+ };
- tx.commit().await?;
- Ok(res)
- })
+ Ok(res)
}
/** Result status of customer account password check */
diff --git a/testbench/src/integration.rs b/testbench/src/integration.rs
@@ -311,7 +311,7 @@ async fn errors() {
// Check success
let valid_payment = InTx {
- subject: Some(format!("Sucess {reserve_pub}")),
+ subject: Some(format!("Success {reserve_pub}")),
id: InId::new(None, Some("success".into()), None),
..reserve_payment
};
@@ -327,7 +327,7 @@ async fn errors() {
&db,
&cfg,
&InTx {
- subject: Some(format!("Sucess 2 {reserve_pub}")),
+ subject: Some(format!("Success 2 {reserve_pub}")),
..valid_payment
},
)