From cefdfc54cc8baea3b4e36740d6913b74a8072b6a Mon Sep 17 00:00:00 2001 From: c0mrade Date: Mon, 23 Mar 2026 18:47:57 +0300 Subject: [PATCH] fix: add period_days validation and zero-price guard to tariff purchase Port validations from dev monolith that were missing after sub-router split: - Validate period_days against tariff's configured periods - Allow custom days only if tariff explicitly supports them - Reject zero-price purchases for non-daily tariffs (defense in depth) --- .../routes/subscription_modules/purchase.py | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/app/cabinet/routes/subscription_modules/purchase.py b/app/cabinet/routes/subscription_modules/purchase.py index 5cec27e9..2ad2bf86 100644 --- a/app/cabinet/routes/subscription_modules/purchase.py +++ b/app/cabinet/routes/subscription_modules/purchase.py @@ -600,6 +600,26 @@ async def purchase_tariff( else: period_days = request.period_days + # Validate period_days against tariff's configured periods (prevent arbitrary periods) + if not is_daily_tariff: + if tariff.period_prices: + available_periods = [int(p) for p in tariff.period_prices.keys()] + else: + available_periods = [] + + custom_days_allowed = ( + hasattr(tariff, 'can_purchase_custom_days') + and tariff.can_purchase_custom_days() + and hasattr(tariff, 'get_price_for_custom_days') + and tariff.get_price_for_custom_days(period_days) is not None + ) + + if period_days not in available_periods and not custom_days_allowed: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail='Selected period is not available for this tariff', + ) + # Determine traffic limit (custom traffic support) traffic_limit_gb = tariff.traffic_limit_gb custom_traffic_gb = None @@ -638,6 +658,13 @@ async def purchase_tariff( promo_offer_discount_value = result.promo_offer_discount price_before_promo_offer = price_kopeks + promo_offer_discount_value + # Safety guard: reject zero-price purchases for non-daily tariffs (defense in depth) + if price_kopeks <= 0 and result.base_price <= 0 and not is_daily_tariff: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail='Invalid tariff period or pricing configuration', + ) + # Check balance if user.balance_kopeks < price_kopeks: missing = price_kopeks - user.balance_kopeks