Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions openwisp_controller/config/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ def __setmodels__(self):
self.org_limits = load_model("config", "OrganizationLimits")
self.cert_model = load_model("django_x509", "Cert")
self.org_model = load_model("openwisp_users", "Organization")
self.organization_config_settings_model = load_model(
"config", "OrganizationConfigSettings"
)

def connect_signals(self):
"""
Expand Down Expand Up @@ -270,6 +273,8 @@ def enable_cache_invalidation(self):
device_cache_invalidation_handler,
devicegroup_change_handler,
devicegroup_delete_handler,
organization_config_settings_post_save_handler,
organization_config_settings_pre_save_handler,
vpn_server_change_handler,
)

Expand Down Expand Up @@ -336,6 +341,16 @@ def enable_cache_invalidation(self):
sender=self.vpn_model,
dispatch_uid="vpn.invalidate_checksum_cache",
)
pre_save.connect(
organization_config_settings_pre_save_handler,
sender=self.organization_config_settings_model,
dispatch_uid="organization_config_settings.store_original_context",
)
post_save.connect(
organization_config_settings_post_save_handler,
sender=self.organization_config_settings_model,
dispatch_uid="organization_config_settings.invalidate_vpn_cache",
)

def register_dashboard_charts(self):
register_dashboard_chart(
Expand Down
26 changes: 26 additions & 0 deletions openwisp_controller/config/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,29 @@ def organization_disabled_handler(instance, **kwargs):
# No change in is_active
return
tasks.invalidate_controller_views_cache.delay(str(instance.id))


def organization_config_settings_pre_save_handler(instance, **kwargs):
"""
Stores original context before save to detect changes.
"""
if instance._state.adding:
return
try:
db_instance = instance.__class__.objects.only("context").get(id=instance.id)
instance._original_context = db_instance.context
except instance.__class__.DoesNotExist:
instance._original_context = None


def organization_config_settings_post_save_handler(instance, **kwargs):
"""
Invalidates VPN cache when OrganizationConfigSettings context changes.
"""
original_context = getattr(instance, "_original_context", None)
if original_context is not None and original_context != instance.context:
transaction.on_commit(
lambda: tasks.invalidate_organization_vpn_cache.delay(
str(instance.organization_id)
)
)
22 changes: 22 additions & 0 deletions openwisp_controller/config/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,28 @@ def invalidate_vpn_server_devices_cache_change(vpn_pk):
VpnClient.invalidate_clients_cache(vpn)


@shared_task(soft_time_limit=7200)
def invalidate_organization_vpn_cache(organization_id):
"""
Invalidates VPN cache for all VPNs in an organization when
organization configuration variables change.
"""
Vpn = load_model("config", "Vpn")
from .controller.views import GetVpnView

try:
for vpn in (
Vpn.objects.filter(organization_id=organization_id).only("id").iterator()
):
GetVpnView.invalidate_get_vpn_cache(vpn)
vpn.invalidate_checksum_cache()
except SoftTimeLimitExceeded:
logger.exception(
"soft time limit hit while executing "
f"invalidate_organization_vpn_cache for organization {organization_id}"
)


@shared_task(soft_time_limit=7200)
def invalidate_devicegroup_cache_delete(instance_id, model_name, **kwargs):
from .api.views import DeviceGroupCommonName
Expand Down
17 changes: 0 additions & 17 deletions openwisp_controller/config/tests/test_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,3 @@ def test_organization_disabled_handler(self, mocked_task):
org.is_active = False
org.save()
mocked_task.assert_called_once()

mocked_task.reset_mock()
with self.subTest("Test task not executed on saving inactive org"):
org.name = "Changed named"
org.save()
mocked_task.assert_not_called()

with self.subTest("Test task not executed on creating inactive org"):
inactive_org = self._create_org(
is_active=False, name="inactive", slug="inactive"
)
mocked_task.assert_not_called()

with self.subTest("Test task not executed on changing inactive to active org"):
inactive_org.is_active = True
inactive_org.save()
mocked_task.assert_not_called()
Loading