diff --git a/app/controllers/OrderApiController.asp b/app/controllers/OrderApiController.asp index d3ad008..a0ae003 100644 --- a/app/controllers/OrderApiController.asp +++ b/app/controllers/OrderApiController.asp @@ -60,6 +60,11 @@ Class OrderApiController_Class Exit Sub End If + If Not IsNull(order("TokenUsedAt")) Then + WriteJsonError "410 Gone", "This order has already been submitted." + Exit Sub + End If + Dim csrfToken : csrfToken = Request.ServerVariables("HTTP_X_CSRF_TOKEN") If Not HTMLSecurity().IsValidAntiCSRFToken("Order.Continue", csrfToken) Then @@ -114,6 +119,7 @@ Class OrderApiController_Class End If On Error GoTo 0 + OrdersRepository().MarkTokenUsed order("OrderID") ' Best-effort: the order is already safely persisted at this point, so an SMTP hiccup ' should not turn a successful submission into a failed one. diff --git a/app/controllers/OrderController.asp b/app/controllers/OrderController.asp index 3403f7c..d4a8919 100644 --- a/app/controllers/OrderController.asp +++ b/app/controllers/OrderController.asp @@ -40,9 +40,13 @@ Class OrderController_Class If Len(token) > 0 Then Set order = OrdersRepository().FindByToken(token) If Not (order Is Nothing) Then + ' Only checks validity here - the token is marked used when the order is + ' actually submitted (OrderApiController.SubmitOrderDetails), not on this GET. + ' Marking it used here would burn a one-time link the moment it's merely + ' opened/previewed (e.g. by mail security link-scanners), before the + ' customer ever sees the form. If IsNull(order("TokenUsedAt")) And order("TokenExpiresAt") >= Now() Then isValid = True - OrdersRepository().MarkTokenUsed order("OrderID") End If End If End If