Fix indempotent updates

This commit is contained in:
Pierre HUBERT 2025-04-19 22:23:07 +02:00
parent 2a1b1ea45a
commit f5b0ae49ca
2 changed files with 21 additions and 10 deletions

View File

@ -8,7 +8,7 @@ use actix_web::{HttpResponse, web};
/// Create a new movement /// Create a new movement
pub async fn create(auth: AuthExtractor, req: web::Json<UpdateMovementQuery>) -> HttpResult { pub async fn create(auth: AuthExtractor, req: web::Json<UpdateMovementQuery>) -> HttpResult {
if let Some(err) = req.check_error(auth.user_id()).await? { if let Some(err) = req.check_error(auth.user_id(), None).await? {
return Ok(HttpResponse::BadRequest().json(err)); return Ok(HttpResponse::BadRequest().json(err));
} }
@ -34,7 +34,10 @@ pub async fn update(
movement: MovementInPath, movement: MovementInPath,
req: web::Json<UpdateMovementQuery>, req: web::Json<UpdateMovementQuery>,
) -> HttpResult { ) -> HttpResult {
if let Some(err) = req.check_error(auth.user_id()).await? { if let Some(err) = req
.check_error(auth.user_id(), Some(movement.movement().id()))
.await?
{
return Ok(HttpResponse::BadRequest().json(err)); return Ok(HttpResponse::BadRequest().json(err));
} }

View File

@ -21,7 +21,11 @@ pub struct UpdateMovementQuery {
} }
impl UpdateMovementQuery { impl UpdateMovementQuery {
pub async fn check_error(&self, user_id: UserID) -> anyhow::Result<Option<&'static str>> { pub async fn check_error(
&self,
user_id: UserID,
ref_movement: Option<MovementID>,
) -> anyhow::Result<Option<&'static str>> {
let constraints = ServerConstraints::default(); let constraints = ServerConstraints::default();
// Check movement label // Check movement label
@ -30,7 +34,9 @@ impl UpdateMovementQuery {
} }
// Check the account // Check the account
let account = accounts_service::get_by_id(self.account_id).await?; let Ok(account) = accounts_service::get_by_id(self.account_id).await else {
return Ok(Some("The specified account does not exists!"));
};
if account.user_id() != user_id { if account.user_id() != user_id {
return Ok(Some("The user does not own the account!")); return Ok(Some("The user does not own the account!"));
} }
@ -45,13 +51,15 @@ impl UpdateMovementQuery {
} }
// Check for conflict with other movements // Check for conflict with other movements
if get_by_account_label_amount_time(self.account_id, &self.label, self.amount, self.time) if let Ok(movement) =
.await get_by_account_label_amount_time(self.account_id, &self.label, self.amount, self.time)
.is_ok() .await
{ {
return Ok(Some( if Some(movement.id()) != ref_movement {
"A movement taken at the same time with the same label and the same amount already exists!", return Ok(Some(
)); "A movement taken at the same time with the same label and the same amount already exists!",
));
}
} }
Ok(None) Ok(None)