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,14 +51,16 @@ 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) =
get_by_account_label_amount_time(self.account_id, &self.label, self.amount, self.time)
.await .await
.is_ok()
{ {
if Some(movement.id()) != ref_movement {
return Ok(Some( return Ok(Some(
"A movement taken at the same time with the same label and the same amount already exists!", "A movement taken at the same time with the same label and the same amount already exists!",
)); ));
} }
}
Ok(None) Ok(None)
} }