📁 File Manager Pro
v10.0.2 | PHP: 8.1.34
Server: LiteSpeed
2026-06-29 04:22:37
📂
/
/
opt
/
imunify360
/
venv
/
lib
/
python3.11
/
site-packages
/
defence360agent
/
feature_management
/
plugins
✏️
Editing: proactive_log_migration.py
"""Promote stale `proactive: na` perms to `log` when the deployment toggle ``FEATURE_MANAGEMENT.proactive_disable_target == "log"`` is set. DEF-42523. Without this, customers (notably Cloudways) flipping the toggle post-upgrade would only see the new behavior on users whose add-on state changes; pre-existing disabled users would linger in NA / mode=DISABLED indefinitely. Re-firing the proactive hook with LOG writes ``mode=LOG`` to user_config and updates the perm row. Idempotent: once promoted, no NA proactive perms remain, so subsequent boots no-op. """ import asyncio from logging import getLogger from defence360agent.contracts.config import ConfigFile from defence360agent.contracts.plugins import MessageSink, thisguy from defence360agent.feature_management.constants import LOG, NA, PROACTIVE from defence360agent.feature_management.model import FeatureManagementPerms from defence360agent.feature_management.utils import set_feature from defence360agent.utils import Scope, create_task_and_log_exceptions logger = getLogger(__name__) @thisguy class ProactiveLogMigration(MessageSink): # Proactive Defence is an Imunify360-only feature. ImunifyAV-only # installs have no proactive permissions to migrate and no # FEATURE_MANAGEMENT.proactive_disable_target schema key. SCOPE = Scope.IM360 async def create_sink(self, loop: asyncio.AbstractEventLoop): # Spawn the migration as a background task so the agent's other # MessageSinks (and serving traffic) come up immediately. The # migration is idempotent on retry, so cancellation at shutdown # is safe. create_task_and_log_exceptions surfaces failures # to the agent's exception handler instead of silently dropping # them (the bare loop.create_task would). self._migration_task = create_task_and_log_exceptions( loop, self._migrate ) async def shutdown(self): task = getattr(self, "_migration_task", None) if task is None or task.done(): return task.cancel() try: await task except asyncio.CancelledError: pass @staticmethod async def _migrate(): target = ConfigFile().get( "FEATURE_MANAGEMENT", "proactive_disable_target" ) if target != "log": return users = [ row.user for row in FeatureManagementPerms.select().where( (FeatureManagementPerms.proactive == NA) & ( FeatureManagementPerms.user != FeatureManagementPerms.DEFAULT ) ) ] if not users: return logger.info( "Promoting %d proactive=na users to log (DEF-42523)", len(users), ) promoted = 0 for user in users: try: if await set_feature(user, PROACTIVE, LOG): promoted += 1 except Exception: logger.exception( "Failed to promote proactive=na user %s to log", user ) logger.info( "Promoted %d/%d users to proactive=log", promoted, len(users), )
💾 Save Changes
❌ Cancel