-
Notifications
You must be signed in to change notification settings - Fork 13
Improve checkout process with error handling and inventory management #23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,10 +1,15 @@ | ||||||||||||||||||||
import os | ||||||||||||||||||||
from flask import Flask, request, json, abort | ||||||||||||||||||||
from flask import Flask, request, json, abort, jsonify | ||||||||||||||||||||
from flask_cors import CORS | ||||||||||||||||||||
|
||||||||||||||||||||
import sentry_sdk | ||||||||||||||||||||
from sentry_sdk.integrations.flask import FlaskIntegration | ||||||||||||||||||||
|
||||||||||||||||||||
class InsufficientInventoryError(Exception): | ||||||||||||||||||||
def __init__(self, message, product_id=None): | ||||||||||||||||||||
super().__init__(message) | ||||||||||||||||||||
self.product_id = product_id | ||||||||||||||||||||
|
||||||||||||||||||||
sentry_sdk.init( | ||||||||||||||||||||
dsn="https://[email protected]/1316515", | ||||||||||||||||||||
integrations=[FlaskIntegration()], | ||||||||||||||||||||
|
@@ -30,20 +35,28 @@ | |||||||||||||||||||
obj['keyDoesntExist'] | ||||||||||||||||||||
|
||||||||||||||||||||
Inventory = { | ||||||||||||||||||||
'wrench': 1, | ||||||||||||||||||||
'nails': 1, | ||||||||||||||||||||
'hammer': 1 | ||||||||||||||||||||
'wrench': 10, | ||||||||||||||||||||
'nails': 100, | ||||||||||||||||||||
'hammer': 5, | ||||||||||||||||||||
'4': 2 # Botana Voice with ID '4' and 2 in stock | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
def process_order(cart): | ||||||||||||||||||||
def process_order(cart_items, cart_quantities): | ||||||||||||||||||||
global Inventory | ||||||||||||||||||||
tempInventory = Inventory | ||||||||||||||||||||
for item in cart: | ||||||||||||||||||||
if Inventory[item['id']] <= 0: | ||||||||||||||||||||
raise Exception("Not enough inventory for " + item['id']) | ||||||||||||||||||||
else: | ||||||||||||||||||||
tempInventory[item['id']] -= 1 | ||||||||||||||||||||
print 'Success: ' + item['id'] + ' was purchased, remaining stock is ' + str(tempInventory[item['id']]) | ||||||||||||||||||||
tempInventory = Inventory.copy() | ||||||||||||||||||||
for item_in_cart in cart_items: | ||||||||||||||||||||
product_id = str(item_in_cart['id']) | ||||||||||||||||||||
if product_id not in tempInventory: | ||||||||||||||||||||
raise ValueError(f"Product ID '{product_id}' not found.") | ||||||||||||||||||||
requested_quantity = cart_quantities.get(product_id) | ||||||||||||||||||||
if not isinstance(requested_quantity, int) or requested_quantity <= 0: | ||||||||||||||||||||
raise ValueError(f"Invalid quantity for product ID '{product_id}'.") | ||||||||||||||||||||
available_stock = tempInventory[product_id] | ||||||||||||||||||||
if available_stock < requested_quantity: | ||||||||||||||||||||
raise InsufficientInventoryError( | ||||||||||||||||||||
f"Not enough inventory for product ID '{product_id}'.", product_id=product_id) | ||||||||||||||||||||
tempInventory[product_id] -= requested_quantity | ||||||||||||||||||||
print(f'Success: {product_id} was purchased, remaining stock is {tempInventory[product_id]}') | ||||||||||||||||||||
Inventory = tempInventory | ||||||||||||||||||||
|
||||||||||||||||||||
@app.before_request | ||||||||||||||||||||
|
@@ -65,11 +78,24 @@ | |||||||||||||||||||
|
||||||||||||||||||||
@app.route('/checkout', methods=['POST']) | ||||||||||||||||||||
def checkout(): | ||||||||||||||||||||
|
||||||||||||||||||||
order = json.loads(request.data) | ||||||||||||||||||||
print "Processing order for: " + order["email"] | ||||||||||||||||||||
cart = order["cart"] | ||||||||||||||||||||
|
||||||||||||||||||||
process_order(cart) | ||||||||||||||||||||
|
||||||||||||||||||||
return 'Success' | ||||||||||||||||||||
try: | ||||||||||||||||||||
order_data = request.get_json() | ||||||||||||||||||||
print(f"Processing order for: {order_data['form']['email']}") | ||||||||||||||||||||
cart = order_data["cart"] | ||||||||||||||||||||
cart_items = cart['items'] | ||||||||||||||||||||
cart_quantities = cart['quantities'] | ||||||||||||||||||||
|
||||||||||||||||||||
process_order(cart_items, cart_quantities) | ||||||||||||||||||||
return jsonify({"message": "Order successful"}), 200 | ||||||||||||||||||||
except InsufficientInventoryError as e: | ||||||||||||||||||||
return jsonify({ | ||||||||||||||||||||
"error": "InsufficientInventory", | ||||||||||||||||||||
"message": str(e), | ||||||||||||||||||||
"product_id": e.product_id | ||||||||||||||||||||
}), 409 | ||||||||||||||||||||
except ValueError as e: | ||||||||||||||||||||
return jsonify({"error": "BadRequest", "message": str(e)}), 400 | ||||||||||||||||||||
Check warningCode scanning / CodeQL Information exposure through an exception Medium Stack trace information Error loading related location Loading
Copilot AutofixAI 6 days ago To fix the issue, we will replace the direct use of
This change will ensure that sensitive information is not exposed to the user while still allowing developers to debug the issue using the logs.
Suggested changeset
1
app.py
Copilot is powered by AI and may make mistakes. Always verify output.
Positive FeedbackNegative Feedback
Refresh and try again.
|
||||||||||||||||||||
except Exception as e: | ||||||||||||||||||||
# Fallback for unexpected errors | ||||||||||||||||||||
sentry_sdk.capture_exception(e) | ||||||||||||||||||||
return jsonify({"error": "InternalServerError", "message": "An unexpected error occurred."}), 500 |
Check warning
Code scanning / CodeQL
Information exposure through an exception Medium
Copilot Autofix
AI 6 days ago
To fix the issue, the exception messages should not be directly included in the response sent to the client. Instead, a generic error message should be returned, and the detailed exception message should be logged for internal use. This ensures that sensitive information is not exposed to external users while still allowing developers to debug issues using the logs.
The changes required are:
str(e)
usage in the JSON response with a generic error message.sentry_sdk.capture_exception(e)
or another logging mechanism.