Skip to content

Commit

Permalink
Handle invalid UUIDs using uuid_hex property (#523)
Browse files Browse the repository at this point in the history
  • Loading branch information
jace authored Sep 2, 2024
1 parent 1cd1e1d commit ec5e268
Show file tree
Hide file tree
Showing 13 changed files with 40 additions and 33 deletions.
5 changes: 3 additions & 2 deletions boxoffice/models/discount_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
IdMixin,
Mapped,
Model,
UuidMixin,
db,
relationship,
sa,
Expand Down Expand Up @@ -50,7 +51,7 @@
)


class DiscountPolicy(BaseScopedNameMixin[UUID, User], Model):
class DiscountPolicy(UuidMixin, BaseScopedNameMixin[UUID, User], Model):
"""
Consists of the discount rules applicable on tickets.
Expand Down Expand Up @@ -329,7 +330,7 @@ def generate_coupon_code(
return ''.join(secrets.choice(chars) for _ in range(size))


class DiscountCoupon(IdMixin[UUID], Model):
class DiscountCoupon(UuidMixin, IdMixin[UUID], Model):
__tablename__ = 'discount_coupon'

def __init__(self, *args, **kwargs) -> None:
Expand Down
3 changes: 2 additions & 1 deletion boxoffice/models/menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
DynamicMapped,
Mapped,
Model,
UuidMixin,
db,
markdown_column,
relationship,
Expand All @@ -26,7 +27,7 @@
__all__ = ['Menu']


class Menu(BaseScopedNameMixin[UUID, User], Model):
class Menu(UuidMixin, BaseScopedNameMixin[UUID, User], Model):
"""Represent a collection of tickets."""

__tablename__ = 'item_collection'
Expand Down
5 changes: 3 additions & 2 deletions boxoffice/models/order.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
DynamicMapped,
Mapped,
Model,
UuidMixin,
relationship,
sa,
timestamptz,
Expand Down Expand Up @@ -53,7 +54,7 @@ def gen_receipt_no(organization: Organization) -> sa.ScalarSelect[int]:
)


class Order(BaseMixin[UUID, User], Model):
class Order(UuidMixin, BaseMixin[UUID, User], Model):
__tablename__ = 'customer_order'
user_id: Mapped[int | None] = sa.orm.mapped_column(sa.ForeignKey('user.id'))
user: Mapped[User | None] = relationship(back_populates='orders')
Expand Down Expand Up @@ -225,7 +226,7 @@ def net_amount(self) -> Decimal:
return self.paid_amount - self.refunded_amount


class OrderSession(BaseMixin[UUID, User], Model):
class OrderSession(UuidMixin, BaseMixin[UUID, User], Model):
"""Records the referrer and utm headers for an order."""

__tablename__ = 'order_session'
Expand Down
5 changes: 3 additions & 2 deletions boxoffice/models/payment.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
BaseMixin,
Mapped,
Model,
UuidMixin,
db,
markdown_column,
relationship,
Expand All @@ -32,7 +33,7 @@
__all__ = ['OnlinePayment', 'PaymentTransaction']


class OnlinePayment(BaseMixin[UUID, User], Model):
class OnlinePayment(UuidMixin, BaseMixin[UUID, User], Model):
"""Represents payments made through a payment gateway. Supports Razorpay only."""

__tablename__ = 'online_payment'
Expand Down Expand Up @@ -62,7 +63,7 @@ def fail(self) -> None:
self.failed_at = func.utcnow()


class PaymentTransaction(BaseMixin[UUID, User], Model):
class PaymentTransaction(UuidMixin, BaseMixin[UUID, User], Model):
"""
Models transactions made by a customer.
Expand Down
5 changes: 3 additions & 2 deletions boxoffice/models/ticket.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
DynamicMapped,
Mapped,
Model,
UuidMixin,
db,
markdown_column,
relationship,
Expand All @@ -39,7 +40,7 @@ class AvailabilityData(NamedTuple):
line_item_count: int


class Ticket(BaseScopedNameMixin[UUID, User], Model):
class Ticket(UuidMixin, BaseScopedNameMixin[UUID, User], Model):
__tablename__ = 'item'

description = markdown_column('description', default='', nullable=False)
Expand Down Expand Up @@ -234,7 +235,7 @@ def demand_curve(self) -> Sequence[sa.engine.Row[tuple[Decimal, int]]]:
).fetchall()


class Price(BaseScopedNameMixin[UUID, User], Model):
class Price(UuidMixin, BaseScopedNameMixin[UUID, User], Model):
__tablename__ = 'price'
ticket_id: Mapped[UUID] = sa.orm.mapped_column('item_id', sa.ForeignKey('item.id'))
ticket: Mapped[Ticket] = relationship(back_populates='prices')
Expand Down
2 changes: 1 addition & 1 deletion boxoffice/views/admin_category.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

@app.route('/admin/menu/<menu_id>/category/new', methods=['GET', 'POST'])
@lastuser.requires_login
@load_models((Menu, {'id': 'menu_id'}, 'menu'), permission='org_admin')
@load_models((Menu, {'uuid_hex': 'menu_id'}, 'menu'), permission='org_admin')
def admin_new_category(menu: Menu) -> ResponseReturnValue:
if not request_wants_json():
return render_template('index.html.jinja2')
Expand Down
6 changes: 3 additions & 3 deletions boxoffice/views/admin_discount.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ def admin_new_discount_policy(organization: Organization) -> Response:
@lastuser.requires_login
@xhr_only
@load_models(
(DiscountPolicy, {'id': 'discount_policy_id'}, 'discount_policy'),
(DiscountPolicy, {'uuid_hex': 'discount_policy_id'}, 'discount_policy'),
permission='org_admin',
)
def admin_edit_discount_policy(discount_policy: DiscountPolicy) -> Response:
Expand Down Expand Up @@ -235,7 +235,7 @@ def admin_edit_discount_policy(discount_policy: DiscountPolicy) -> Response:
@lastuser.requires_login
@xhr_only
@load_models(
(DiscountPolicy, {'id': 'discount_policy_id'}, 'discount_policy'),
(DiscountPolicy, {'uuid_hex': 'discount_policy_id'}, 'discount_policy'),
permission='org_admin',
)
def admin_delete_discount_policy(
Expand Down Expand Up @@ -268,7 +268,7 @@ def admin_delete_discount_policy(
@lastuser.requires_login
@xhr_only
@load_models(
(DiscountPolicy, {'id': 'discount_policy_id'}, 'discount_policy'),
(DiscountPolicy, {'uuid_hex': 'discount_policy_id'}, 'discount_policy'),
permission='org_admin',
)
def admin_new_coupon(discount_policy: DiscountPolicy) -> Response:
Expand Down
4 changes: 2 additions & 2 deletions boxoffice/views/admin_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

@app.route('/admin/menu/<menu_id>')
@lastuser.requires_login
@load_models((Menu, {'id': 'menu_id'}, 'menu'), permission='org_admin')
@load_models((Menu, {'uuid_hex': 'menu_id'}, 'menu'), permission='org_admin')
def admin_menu(menu: Menu) -> ResponseReturnValue:
ticket_ids = [str(ticket.id) for ticket in menu.tickets]
date_ticket_counts = {}
Expand Down Expand Up @@ -96,7 +96,7 @@ def admin_new_ic(organization: Organization) -> ResponseReturnValue:

@app.route('/admin/menu/<menu_id>/edit', methods=['POST', 'GET'])
@lastuser.requires_login
@load_models((Menu, {'id': 'menu_id'}, 'menu'), permission='org_admin')
@load_models((Menu, {'uuid_hex': 'menu_id'}, 'menu'), permission='org_admin')
def admin_edit_ic(menu: Menu) -> ResponseReturnValue:
if not request_wants_json():
return render_template('index.html.jinja2')
Expand Down
4 changes: 2 additions & 2 deletions boxoffice/views/admin_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def format_line_items(line_items: list[LineItem]) -> list[LineItemDict]:

@app.route('/admin/menu/<menu_id>/orders')
@lastuser.requires_login
@load_models((Menu, {'id': 'menu_id'}, 'menu'), permission='org_admin')
@load_models((Menu, {'uuid_hex': 'menu_id'}, 'menu'), permission='org_admin')
def admin_orders(menu: Menu) -> ResponseReturnValue:
if not request_wants_json():
return render_template('index.html.jinja2', title=menu.title)
Expand Down Expand Up @@ -132,7 +132,7 @@ def admin_orders(menu: Menu) -> ResponseReturnValue:
@app.route('/admin/order/<order_id>')
@lastuser.requires_login
@xhr_only
@load_models((Order, {'id': 'order_id'}, 'order'), permission='org_admin')
@load_models((Order, {'uuid_hex': 'order_id'}, 'order'), permission='org_admin')
def admin_order(order: Order) -> ResponseReturnValue:
line_items = LineItem.query.filter(
LineItem.order == order,
Expand Down
8 changes: 4 additions & 4 deletions boxoffice/views/admin_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

@app.route('/admin/menu/<menu_id>/reports')
@lastuser.requires_login
@load_models((Menu, {'id': 'menu_id'}, 'menu'), permission='org_admin')
@load_models((Menu, {'uuid_hex': 'menu_id'}, 'menu'), permission='org_admin')
def admin_report(menu: Menu) -> ResponseReturnValue:
if not request_wants_json():
return render_template('index.html.jinja2')
Expand All @@ -43,7 +43,7 @@ def admin_org_report(organization: Organization) -> ResponseReturnValue:

@app.route('/admin/menu/<menu_id>/tickets.csv')
@lastuser.requires_login
@load_models((Menu, {'id': 'menu_id'}, 'menu'), permission='org_admin')
@load_models((Menu, {'uuid_hex': 'menu_id'}, 'menu'), permission='org_admin')
def tickets_report(menu: Menu) -> Response:
headers, rows = menu.fetch_all_details()
assignee_url_index = headers.index('assignee_url')
Expand Down Expand Up @@ -73,7 +73,7 @@ def row_handler(row: list[Any]) -> list[Any]:

@app.route('/admin/menu/<menu_id>/attendees.csv')
@lastuser.requires_login
@load_models((Menu, {'id': 'menu_id'}, 'menu'), permission='org_admin')
@load_models((Menu, {'uuid_hex': 'menu_id'}, 'menu'), permission='org_admin')
def attendees_report(menu: Menu) -> Response:
# Generated a unique list of headers for all 'assignee_details' keys in all items in
# this menu. This flattens the 'assignee_details' dict. This will need to
Expand Down Expand Up @@ -128,7 +128,7 @@ def row_handler(row: list[dict | datetime | str]) -> dict[str, Any]:
(Organization, {'name': 'org'}, 'organization'),
(
Menu,
{'id': 'menu_id', 'organization': 'organization'},
{'uuid_hex': 'menu_id', 'organization': 'organization'},
'menu',
),
)
Expand Down
10 changes: 5 additions & 5 deletions boxoffice/views/admin_ticket.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def format_ticket_details(ticket: Ticket) -> dict[str, Any]:

@app.route('/admin/ticket/<ticket_id>', methods=['GET'])
@lastuser.requires_login
@load_models((Ticket, {'id': 'ticket_id'}, 'ticket'), permission='org_admin')
@load_models((Ticket, {'uuid_hex': 'ticket_id'}, 'ticket'), permission='org_admin')
def admin_item(ticket: Ticket) -> ResponseReturnValue:
if not request_wants_json():
return render_template('index.html.jinja2')
Expand All @@ -127,7 +127,7 @@ def admin_item(ticket: Ticket) -> ResponseReturnValue:

@app.route('/admin/menu/<menu_id>/ticket/new', methods=['GET', 'POST'])
@lastuser.requires_login
@load_models((Menu, {'id': 'menu_id'}, 'menu'), permission='org_admin')
@load_models((Menu, {'uuid_hex': 'menu_id'}, 'menu'), permission='org_admin')
def admin_new_item(menu: Menu) -> ResponseReturnValue:
if not request_wants_json():
return render_template('index.html.jinja2')
Expand Down Expand Up @@ -162,7 +162,7 @@ def admin_new_item(menu: Menu) -> ResponseReturnValue:

@app.route('/admin/ticket/<ticket_id>/edit', methods=['GET', 'POST'])
@lastuser.requires_login
@load_models((Ticket, {'id': 'ticket_id'}, 'ticket'), permission='org_admin')
@load_models((Ticket, {'uuid_hex': 'ticket_id'}, 'ticket'), permission='org_admin')
def admin_edit_item(ticket: Ticket) -> ResponseReturnValue:
if not request_wants_json():
return render_template('index.html.jinja2')
Expand Down Expand Up @@ -193,7 +193,7 @@ def admin_edit_item(ticket: Ticket) -> ResponseReturnValue:

@app.route('/admin/ticket/<ticket_id>/price/new', methods=['GET', 'POST'])
@lastuser.requires_login
@load_models((Ticket, {'id': 'ticket_id'}, 'ticket'), permission='org_admin')
@load_models((Ticket, {'uuid_hex': 'ticket_id'}, 'ticket'), permission='org_admin')
def admin_new_price(ticket: Ticket) -> ResponseReturnValue:
if not request_wants_json():
return render_template('index.html.jinja2')
Expand Down Expand Up @@ -229,7 +229,7 @@ def admin_new_price(ticket: Ticket) -> ResponseReturnValue:

@app.route('/admin/ticket/<ticket_id>/price/<price_id>/edit', methods=['GET', 'POST'])
@lastuser.requires_login
@load_models((Price, {'id': 'price_id'}, 'price'), permission='org_admin')
@load_models((Price, {'uuid_hex': 'price_id'}, 'price'), permission='org_admin')
def admin_edit_price(price: Price) -> ResponseReturnValue:
if not request_wants_json():
return render_template('index.html.jinja2')
Expand Down
2 changes: 1 addition & 1 deletion boxoffice/views/menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ def boxofficejs() -> ResponseReturnValue:
@app.route('/menu/<menu_id>', methods=['GET', 'OPTIONS'])
@xhr_only
@cors
@load_models((Menu, {'id': 'menu_id'}, 'menu'))
@load_models((Menu, {'uuid_hex': 'menu_id'}, 'menu'))
def view_menu(menu: Menu) -> ResponseReturnValue:
categories_json = [
category_json
Expand Down
14 changes: 8 additions & 6 deletions boxoffice/views/order.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ def kharcha() -> ResponseReturnValue:
@app.route('/menu/<menu_id>/order', methods=['GET', 'OPTIONS', 'POST'])
@xhr_only
@cors
@load_models((Menu, {'id': 'menu_id'}, 'menu'))
@load_models((Menu, {'uuid_hex': 'menu_id'}, 'menu'))
def create_order(menu: Menu) -> ResponseReturnValue:
"""
Create an order.
Expand Down Expand Up @@ -354,7 +354,7 @@ def create_order(menu: Menu) -> ResponseReturnValue:
@app.route('/order/<order>/free', methods=['GET', 'OPTIONS', 'POST'])
@xhr_only
@cors
@load_models((Order, {'id': 'order'}, 'order'))
@load_models((Order, {'uuid_hex': 'order'}, 'order'))
def free(order: Order) -> ResponseReturnValue:
"""Complete a order which has a final_amount of 0."""
order_amounts = order.get_amounts(LineItemStatus.PURCHASE_ORDER)
Expand Down Expand Up @@ -388,7 +388,7 @@ def free(order: Order) -> ResponseReturnValue:
@app.route('/order/<order>/payment', methods=['GET', 'OPTIONS', 'POST'])
@xhr_only
@cors
@load_models((Order, {'id': 'order'}, 'order'))
@load_models((Order, {'uuid_hex': 'order'}, 'order'))
def capture_payment(order: Order) -> ResponseReturnValue:
"""
Capture a payment.
Expand Down Expand Up @@ -854,7 +854,9 @@ def process_line_item_cancellation(line_item: LineItem) -> Decimal:

@app.route('/line_item/<line_item_id>/cancel', methods=['POST'])
@lastuser.requires_login
@load_models((LineItem, {'id': 'line_item_id'}, 'line_item'), permission='org_admin')
@load_models(
(LineItem, {'uuid_hex': 'line_item_id'}, 'line_item'), permission='org_admin'
)
def cancel_line_item(line_item: LineItem) -> Response:
if not line_item.is_cancellable():
return api_error(
Expand All @@ -876,7 +878,7 @@ def cancel_line_item(line_item: LineItem) -> Response:
'/admin/menu/<menu_id>/order/<order_id>/partial_refund', methods=['GET', 'POST']
)
@lastuser.requires_login
@load_models((Order, {'id': 'order_id'}, 'order'), permission='org_admin')
@load_models((Order, {'uuid_hex': 'order_id'}, 'order'), permission='org_admin')
def partial_refund_order(order: Order) -> ResponseReturnValue:
if not request_wants_json():
return render_template('index.html.jinja2')
Expand Down Expand Up @@ -935,7 +937,7 @@ def partial_refund_order(order: Order) -> ResponseReturnValue:

@app.route('/api/1/ic/<menu_id>/orders', methods=['GET', 'OPTIONS'])
@app.route('/api/1/menu/<menu_id>/orders', methods=['GET', 'OPTIONS'])
@load_models((Menu, {'id': 'menu_id'}, 'menu'))
@load_models((Menu, {'uuid_hex': 'menu_id'}, 'menu'))
def menu_orders(menu: Menu) -> ResponseReturnValue:
organization = menu.organization
# TODO: Replace with a better authentication system
Expand Down

0 comments on commit ec5e268

Please sign in to comment.