From 5b45d4354f6e58bd609e69a45ef100acfed3dbf4 Mon Sep 17 00:00:00 2001 From: Fringg Date: Fri, 24 Apr 2026 04:24:20 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20bulk=20actions=20review=20=E2=80=94=20ro?= =?UTF-8?q?llback=20on=20error,=20multi-tariff=20constraint=20checks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add db.rollback() in per-user exception handler to prevent session poisoning (one failed commit would abort all subsequent users) - Add multi-tariff duplicate subscription check in activate_subscription (prevents uq_subscriptions_user_tariff_active violation) - Add multi-tariff duplicate subscription check in change_tariff (prevents switching to a tariff the user already holds) --- app/cabinet/routes/admin_bulk_actions.py | 30 ++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/app/cabinet/routes/admin_bulk_actions.py b/app/cabinet/routes/admin_bulk_actions.py index 9a6a7c52..f2dd7ce8 100644 --- a/app/cabinet/routes/admin_bulk_actions.py +++ b/app/cabinet/routes/admin_bulk_actions.py @@ -177,6 +177,19 @@ async def _do_activate_subscription( if not sub: return BulkUserResult(user_id=user.id, success=False, message='No subscription found', username=user.username) + # Проверка дубликата в мультитарифном режиме + if settings.is_multi_tariff_enabled() and sub.tariff_id: + from app.database.crud.subscription import get_subscription_by_user_and_tariff + + existing = await get_subscription_by_user_and_tariff(db, user.id, sub.tariff_id) + if existing and existing.id != sub.id: + return BulkUserResult( + user_id=user.id, + success=False, + message='Cannot activate: user already has an active subscription for this tariff', + username=user.username, + ) + if dry_run: return BulkUserResult( user_id=user.id, @@ -212,6 +225,19 @@ async def _do_change_tariff( if not sub: return BulkUserResult(user_id=user.id, success=False, message='No subscription found', username=user.username) + # Проверка дубликата в мультитарифном режиме + if settings.is_multi_tariff_enabled() and tariff.id != sub.tariff_id: + from app.database.crud.subscription import get_subscription_by_user_and_tariff + + existing = await get_subscription_by_user_and_tariff(db, user.id, tariff.id) + if existing and existing.id != sub.id: + return BulkUserResult( + user_id=user.id, + success=False, + message='User already has an active subscription for the target tariff', + username=user.username, + ) + if dry_run: return BulkUserResult( user_id=user.id, @@ -494,6 +520,10 @@ async def bulk_execute( except Exception as exc: logger.error('Bulk action failed for user', user_id=uid, action=action, error=str(exc)) + try: + await db.rollback() + except Exception: + pass results.append(BulkUserResult(user_id=uid, success=False, message=str(exc))) error_count += 1