From 1ce91749aa12ffcefcf66bea714cea218739f3fe Mon Sep 17 00:00:00 2001 From: Fringg Date: Wed, 25 Feb 2026 11:53:49 +0300 Subject: [PATCH] fix: resolve sync 404 errors, user deletion FK constraint, and device limit not sent to RemnaWave MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Remove pointless HWID reset during auto-sync deactivation — user doesn't exist in panel, API returns 404, UUID is cleaned up below. 2. Clean up RESTRICT FK references (AdminAuditLog, WithdrawalRequest, AdminRole, UserRole, AccessPolicy) before deleting user to prevent IntegrityError on admin_audit_log_user_id_fkey. 3. Fix device limit not being sent to RemnaWave when DEVICES_SELECTION_DISABLED_AMOUNT=0: treat 0 as "no forced override" instead of sending hwidDeviceLimit:0 (which Remnawave interprets as unlimited). Now falls through to subscription.device_limit from tariff. 4. Add info-level logging to POST /api/users (was debug) to match existing PATCH logging for device limit diagnostics. --- app/config.py | 4 ++-- app/external/remnawave_api.py | 12 +++++++++++- app/services/remnawave_service.py | 15 ++------------- app/services/user_service.py | 16 ++++++++++++++++ app/utils/subscription_utils.py | 4 ++-- 5 files changed, 33 insertions(+), 18 deletions(-) diff --git a/app/config.py b/app/config.py index 15d1c87d..9d3fa4eb 100644 --- a/app/config.py +++ b/app/config.py @@ -1525,8 +1525,8 @@ class Settings(BaseSettings): logger.warning('Некорректное значение DEVICES_SELECTION_DISABLED_AMOUNT', raw_value=raw_value) return None - if value < 0: - return 0 + if value <= 0: + return None return value diff --git a/app/external/remnawave_api.py b/app/external/remnawave_api.py index 0e7d6250..50a09d1f 100644 --- a/app/external/remnawave_api.py +++ b/app/external/remnawave_api.py @@ -461,9 +461,19 @@ class RemnaWaveAPI: if active_internal_squads: data['activeInternalSquads'] = active_internal_squads - logger.debug('Создание пользователя в панели', data=data) + logger.info( + 'POST /api/users payload', + username=data.get('username'), + hwidDeviceLimit=data.get('hwidDeviceLimit'), + status=data.get('status'), + ) response = await self._make_request('POST', '/api/users', data) user = self._parse_user(response['response']) + logger.info( + 'POST /api/users response', + uuid=user.uuid, + response_hwidDeviceLimit=user.hwid_device_limit, + ) return await self.enrich_user_with_happ_link(user) async def get_user_by_uuid(self, uuid: str) -> RemnaWaveUser | None: diff --git a/app/services/remnawave_service.py b/app/services/remnawave_service.py index 4677ba4c..9708ed37 100644 --- a/app/services/remnawave_service.py +++ b/app/services/remnawave_service.py @@ -1499,19 +1499,8 @@ class RemnaWaveService: logger.info('🗑️ Деактивация подписки пользователя (нет в панели)', telegram_id=telegram_id) - if db_user.remnawave_uuid and hwid_api_client: - try: - devices_reset = await hwid_api_client.reset_user_devices(db_user.remnawave_uuid) - if devices_reset: - logger.info( - '🔧 Сброшены HWID устройства для пользователя', telegram_id=telegram_id - ) - except Exception as hwid_error: - logger.error( - '❌ Ошибка сброса HWID устройств для', - telegram_id=telegram_id, - hwid_error=hwid_error, - ) + # NOTE: Не сбрасываем HWID здесь — пользователь уже удалён из панели, + # API вернёт 404, UUID очищается ниже (cleanup_mutation) try: from sqlalchemy import delete diff --git a/app/services/user_service.py b/app/services/user_service.py index 97991230..091d5bde 100644 --- a/app/services/user_service.py +++ b/app/services/user_service.py @@ -1203,6 +1203,22 @@ class UserService: logger.error('❌ Ошибка удаления подписки', error=e) try: + from app.database.models import ( + AccessPolicy, + AdminAuditLog, + AdminRole, + UserRole, + WithdrawalRequest, + ) + + await db.execute(delete(AdminAuditLog).where(AdminAuditLog.user_id == user_id)) + await db.execute(delete(WithdrawalRequest).where(WithdrawalRequest.user_id == user_id)) + await db.execute( + update(WithdrawalRequest).where(WithdrawalRequest.processed_by == user_id).values(processed_by=None) + ) + await db.execute(update(AdminRole).where(AdminRole.created_by == user_id).values(created_by=None)) + await db.execute(update(UserRole).where(UserRole.assigned_by == user_id).values(assigned_by=None)) + await db.execute(update(AccessPolicy).where(AccessPolicy.created_by == user_id).values(created_by=None)) await db.execute(delete(User).where(User.id == user_id)) await db.commit() logger.info('✅ Пользователь окончательно удален из базы', user_id=user_id) diff --git a/app/utils/subscription_utils.py b/app/utils/subscription_utils.py index 59ea9bcb..0aaecbc5 100644 --- a/app/utils/subscription_utils.py +++ b/app/utils/subscription_utils.py @@ -181,7 +181,7 @@ def resolve_hwid_device_limit(subscription: Subscription | None) -> int | None: if not settings.is_devices_selection_enabled(): forced_limit = settings.get_disabled_mode_device_limit() - if forced_limit is not None: + if forced_limit is not None and forced_limit > 0: _logger.info( 'DEVICES_SELECTION disabled, using forced limit', forced_limit=forced_limit, @@ -189,7 +189,7 @@ def resolve_hwid_device_limit(subscription: Subscription | None) -> int | None: subscription_id=getattr(subscription, 'id', None), ) return forced_limit - # Если forced_limit не задан, используем device_limit из подписки + # forced_limit не задан или равен 0 — используем device_limit из подписки, # чтобы при смене тарифа лимит устройств обновлялся в панели limit = getattr(subscription, 'device_limit', None)