openwisp-controller 1.1.1__tar.gz → 1.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/CHANGES.rst +36 -1
- {openwisp_controller-1.1.1/openwisp_controller.egg-info → openwisp_controller-1.1.2}/PKG-INFO +7 -6
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/README.rst +4 -4
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/__init__.py +1 -1
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/admin.py +2 -1
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/apps.py +27 -1
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/base/base.py +79 -1
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/base/config.py +103 -50
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/base/template.py +22 -21
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/base/vpn.py +9 -7
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/controller/views.py +37 -6
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/handlers.py +2 -2
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/tasks.py +31 -2
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/tests/test_admin.py +265 -8
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/tests/test_api.py +70 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/tests/test_config.py +65 -5
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/tests/test_controller.py +92 -12
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/tests/test_handlers.py +1 -1
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/tests/test_vpn.py +55 -14
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/tests/utils.py +1 -1
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/utils.py +2 -1
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/validators.py +4 -4
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/admin.py +9 -1
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/api/serializer.py +13 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/base/models.py +30 -8
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/channels/consumers.py +4 -2
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/commands.py +1 -1
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/connectors/openwrt/ssh.py +5 -2
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/tests/pytest.py +42 -9
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/tests/test_api.py +38 -2
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/tests/test_models.py +18 -3
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/api/views.py +2 -3
- openwisp_controller-1.1.2/openwisp_controller/geo/static/leaflet/draw/leaflet.draw.i18n.js +116 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/tests/test_api.py +47 -17
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/tests/utils.py +7 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/utils.py +5 -5
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/mixins.py +2 -2
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2/openwisp_controller.egg-info}/PKG-INFO +7 -6
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller.egg-info/SOURCES.txt +1 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/LICENSE +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/MANIFEST.in +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/admin.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/base.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/checks.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/api/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/api/download_views.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/api/filters.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/api/serializers.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/api/urls.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/api/views.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/api/zerotier_service.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/base/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/base/channels_consumer.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/base/device.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/base/device_group.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/base/multitenancy.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/base/tag.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/controller/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/controller/urls.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/crypto.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/exceptions.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/exportable.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/filters.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/fixtures/test_templates.json +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0001_squashed_0002_config_settings_uuid.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0003_template_tags.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0004_add_device_model.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0005_populate_device.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0006_config_device_not_null.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0007_simplify_config.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0008_update_indexes.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0009_device_system.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0010_auto_20180106_1814.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0011_update_device_mac_address.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0012_auto_20180219_1501.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0013_last_ip_management_ip_and_status_applied.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0014_device_hardware_id.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0015_default_groups_permissions.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0016_default_organization_config_settings.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0017_template_name_organization_unique_together.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0018_config_context.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0019_organization_mac_add_hardware_id_name_unique_together.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0020_remove_config_organization.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0021_vpn_key.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0022_vpn_format_dh.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0023_update_context.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0024_update_context_data.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0025_update_device_key.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0026_hardware_id_not_unique.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0027_add_indexes_on_ip_fields.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0028_template_default_values.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0029_merge_django_netjsonconfig.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0030_django_taggit_update.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0031_update_vpn_dh_param.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0032_update_legacy_vpn_backend.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0033_name_unique_per_organization.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0034_template_required.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0035_device_name_unique_optional.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0036_device_group.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0037_alter_taggedtemplate.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0038_vpn_subnet.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0039_wireguard_vxlan_ipam.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0040_vpnclient_ip_setnull.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0041_default_groups_organizationconfigsettings_permission.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0042_multiple_wireguard_tunnels.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0043_devicegroup_templates.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0044_config_error_reason.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0045_alter_vpn_webhook_endpoint.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0046_organizationlimits.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0047_add_organizationlimits.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0048_wifi_radio_band_migration.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0049_devicegroup_context.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0050_alter_vpnclient_unique_together.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0051_organizationconfigsettings_context.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0052_vpn_node_network_id.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0053_vpnclient_secret.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0054_device__is_deactivated.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/0055_alter_config_status.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/migrations/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/models.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/settings.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/signals.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/sortedm2m/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/sortedm2m/fields.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/sortedm2m/forms.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/static/config/css/admin.css +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/static/config/css/device-delete-confirmation.css +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/static/config/css/devicegroup.css +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/static/config/css/lib/advanced-mode.css +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/static/config/css/lib/img/jsoneditor-icons.svg +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/static/config/css/lib/jsonschema-ui.css +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/static/config/js/device-delete-confirmation.js +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/static/config/js/lib/advanced-mode.js +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/static/config/js/lib/jsonschema-ui.js +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/static/config/js/lib/tomorrow_night_bright.js +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/static/config/js/management_ip.js +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/static/config/js/preview.js +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/static/config/js/relevant_templates.js +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/static/config/js/switcher.js +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/static/config/js/tabs.js +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/static/config/js/unsaved_changes.js +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/static/config/js/utils.js +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/static/config/js/vpn.js +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/static/config/js/widget.js +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/static/import_export/import-openwisp.css +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/static/sortedm2m/patch_sortedm2m.js +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/static/support.css +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/tasks_zerotier.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/templates/admin/config/change_device_group.html +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/templates/admin/config/change_form.html +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/templates/admin/config/change_list_device.html +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/templates/admin/config/clone_template_form.html +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/templates/admin/config/device/change_form.html +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/templates/admin/config/device/delete_confirmation.html +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/templates/admin/config/device/delete_selected_confirmation.html +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/templates/admin/config/device_recover_form.html +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/templates/admin/config/jsonschema-widget.html +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/templates/admin/config/preview.html +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/templates/admin/config/system_context.html +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/templates/admin/device_group/change_form.html +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/templates/admin/import_export/import.html +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/templates/reversion/config/revision_form.html +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/tests/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/tests/pytest.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/tests/test_apps.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/tests/test_device.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/tests/test_device_group.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/tests/test_notifications.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/tests/test_selenium.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/tests/test_tag.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/tests/test_template.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/tests/test_views.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/urls.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/views.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/widgets.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/api/urls.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/api/views.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/apps.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/base/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/channels/routing.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/connectors/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/connectors/airos/snmp.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/connectors/exceptions.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/connectors/openwrt/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/connectors/openwrt/snmp.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/connectors/snmp.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/connectors/ssh.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/exceptions.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/migrations/0001_initial.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/migrations/0002_credentials_auto_add.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/migrations/0003_default_group_permissions.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/migrations/0004_django3_1_upgrade.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/migrations/0005_device_connection_failure_reason.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/migrations/0006_name_unique_per_organization.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/migrations/0007_command.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/migrations/0008_remove_conflicting_deviceconnections.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/migrations/0009_alter_deviceconnection_unique_together.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/migrations/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/models.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/schema.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/settings.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/signals.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/static/connection/css/command-inline.css +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/static/connection/css/credentials.css +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/static/connection/js/commands.js +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/static/connection/js/credentials.js +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/static/connection/js/lib/reconnecting-websocket.min.js +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/tasks.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/tests/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/tests/base.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/tests/test-key.ed25519 +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/tests/test-key.rsa +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/tests/test_admin.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/tests/test_command_utilities.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/tests/test_notifications.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/tests/test_selenium.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/tests/test_snmp.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/tests/test_ssh.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/tests/test_tasks.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/tests/utils.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/utils.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/connection/widgets.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/context_processors.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/admin.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/api/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/api/filters.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/api/serializers.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/api/urls.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/apps.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/base/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/base/models.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/channels/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/channels/consumers.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/channels/routing.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/exportable.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/migrations/0001_initial.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/migrations/0002_default_groups_permissions.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/migrations/0003_alter_devicelocation_floorplan_location.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/migrations/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/models.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/templates/admin/widgets/foreign_key_raw_id.html +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/tests/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/tests/pytest.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/tests/test_admin.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/tests/test_admin_inline.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/tests/test_apps.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/geo/tests/test_models.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/migrations.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/admin.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/api/serializers.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/api/urls.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/api/views.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/apps.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/base/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/base/models.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/migrations/0001_initial.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/migrations/0002_add_organization_name.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/migrations/0003_fill_organization_name.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/migrations/0004_auto_20180106_1814.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/migrations/0005_organizational_unit_name.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/migrations/0006_add_x509_passphrase_field.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/migrations/0007_default_groups_permissions.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/migrations/0008_serial_number_length.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/migrations/0009_common_name_maxlength_64.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/migrations/0010_common_name_organization_unique.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/migrations/0011_disallowed_blank_key_length_or_digest.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/migrations/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/models.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/static/admin/pki/js/show-org-field.js +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/templates/admin/pki/change_form.html +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/tests/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/tests/test_admin.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/tests/test_api.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/tests/test_models.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/tests/utils.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/urls.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/pki/utils.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/routing.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/settings.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/admin.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/apps.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/base/models.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/filters.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/migrations/0001_initial.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/migrations/0002_default_group_migration.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/migrations/0003_related_field_allow_blank.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/migrations/0004_index_rule_on_delete.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/migrations/0005_number_of_subnets_and_ips.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/migrations/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/models.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/rule_types/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/rule_types/base.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/rule_types/device.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/rule_types/vpn.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/settings.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/signals.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/static/subnet-division/css/subnet-division.css +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/static/subnet-division/js/subnet-division.js +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/tasks.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/tests/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/tests/helpers.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/tests/test_admin.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/tests/test_models.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/tests/test_rule.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/subnet_division/utils.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/tests/__init__.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/tests/mixins.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/tests/test_selenium.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/tests/test_users_integration.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/tests/test_utilities.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/tests/utils.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/urls.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/vpn_backends.py +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller.egg-info/dependency_links.txt +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller.egg-info/not-zip-safe +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller.egg-info/requires.txt +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller.egg-info/top_level.txt +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/pyproject.toml +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/requirements.txt +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/setup.cfg +0 -0
- {openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/setup.py +0 -0
|
@@ -1,6 +1,41 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
+
Version 1.1.2 [2025-08-01]
|
|
5
|
+
--------------------------
|
|
6
|
+
|
|
7
|
+
Bugfixes
|
|
8
|
+
~~~~~~~~
|
|
9
|
+
|
|
10
|
+
- Fixed `compatibility of OpenWrt.update_config with openwisp-config >=
|
|
11
|
+
1.1.0 <https://github.com/openwisp/openwisp-controller/issues/964>`__.
|
|
12
|
+
- Fixed `VPN-client template switch issue when switching between VPN
|
|
13
|
+
servers with the same address
|
|
14
|
+
<https://github.com/openwisp/openwisp-controller/issues/973>`__.
|
|
15
|
+
- Fixed `missing config_changed signal when reverting a template
|
|
16
|
+
<https://github.com/openwisp/openwisp-controller/issues/836>`__.
|
|
17
|
+
- Fixed `Zerotier network name being set to "ow_zt" instead of "global"
|
|
18
|
+
<https://github.com/openwisp/openwisp-controller/issues/982>`__.
|
|
19
|
+
- Fixed error in preview when device has no name set.
|
|
20
|
+
- Fixed live updates for "Send commands" when multiple websocket
|
|
21
|
+
connections are open for the same device.
|
|
22
|
+
- Limited command results in the device admin to 30 entries to avoid
|
|
23
|
+
loading issues.
|
|
24
|
+
- Fixed uncaught exception in ``leaflet.draw.i18n.js``.
|
|
25
|
+
- Fixed `handling of devices without a DeviceConnection when creating
|
|
26
|
+
commands
|
|
27
|
+
<https://github.com/openwisp/openwisp-controller/issues/1016>`__.
|
|
28
|
+
- Prevented `adding multiple VPN client templates pointing to the same VPN
|
|
29
|
+
server <https://github.com/openwisp/openwisp-controller/issues/832>`__.
|
|
30
|
+
- Fixed timeout issues in VPN checksum and download configuration views
|
|
31
|
+
for large VPN setups (e.g., 2000+ WireGuard peers) by caching the
|
|
32
|
+
checksum and generated configuration.
|
|
33
|
+
- Fixed an issue where enforcing required templates was accidentally
|
|
34
|
+
deleting `VpnClient` objects, causing them to be recreated whenever
|
|
35
|
+
device templates were modified in the Django admin.
|
|
36
|
+
- Fixed ``HTTP 500 Server Error`` when geographic REST API endpoints
|
|
37
|
+
receive a malformed resource ID.
|
|
38
|
+
|
|
4
39
|
Version 1.1.1 [2025-01-31]
|
|
5
40
|
--------------------------
|
|
6
41
|
|
|
@@ -9,7 +44,7 @@ Bugfixes
|
|
|
9
44
|
|
|
10
45
|
- Fixed `recovering deleted device with related location
|
|
11
46
|
<https://github.com/openwisp/openwisp-controller/issues/936>`__.
|
|
12
|
-
- Fixed `deleting device with
|
|
47
|
+
- Fixed `deleting device with "deactivating" config status
|
|
13
48
|
<https://github.com/openwisp/openwisp-controller/issues/949>`__.
|
|
14
49
|
- Fixed `conversion of MAC address to uppercase format
|
|
15
50
|
<https://github.com/openwisp/openwisp-controller/issues/922>`__ with the
|
{openwisp_controller-1.1.1/openwisp_controller.egg-info → openwisp_controller-1.1.2}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: openwisp-controller
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.2
|
|
4
4
|
Summary: OpenWISP Controller
|
|
5
5
|
Home-page: http://openwisp.org
|
|
6
6
|
Download-URL: https://github.com/openwisp/openwisp-controller/releases
|
|
@@ -45,6 +45,7 @@ Dynamic: download-url
|
|
|
45
45
|
Dynamic: home-page
|
|
46
46
|
Dynamic: keywords
|
|
47
47
|
Dynamic: license
|
|
48
|
+
Dynamic: license-file
|
|
48
49
|
Dynamic: platform
|
|
49
50
|
Dynamic: requires-dist
|
|
50
51
|
Dynamic: summary
|
|
@@ -106,10 +107,10 @@ Other popular building blocks that are part of the OpenWISP ecosystem are:
|
|
|
106
107
|
- `openwisp-firmware-upgrader
|
|
107
108
|
<https://openwisp.io/docs/stable/firmware-upgrader/>`_: automated
|
|
108
109
|
firmware upgrades (single devices or mass network upgrades)
|
|
109
|
-
- `openwisp-radius <https://openwisp.io/docs/stable/
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
- `openwisp-radius <https://openwisp.io/docs/stable/radius/>`_: based on
|
|
111
|
+
FreeRADIUS, allows to implement network access authentication systems
|
|
112
|
+
like 802.1x WPA2 Enterprise, captive portal authentication, Hotspot 2.0
|
|
113
|
+
(802.11u)
|
|
113
114
|
- `openwisp-network-topology
|
|
114
115
|
<https://openwisp.io/docs/stable/network-topology/>`_: provides way to
|
|
115
116
|
collect and visualize network topology data from dynamic mesh routing
|
|
@@ -55,10 +55,10 @@ Other popular building blocks that are part of the OpenWISP ecosystem are:
|
|
|
55
55
|
- `openwisp-firmware-upgrader
|
|
56
56
|
<https://openwisp.io/docs/stable/firmware-upgrader/>`_: automated
|
|
57
57
|
firmware upgrades (single devices or mass network upgrades)
|
|
58
|
-
- `openwisp-radius <https://openwisp.io/docs/stable/
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
- `openwisp-radius <https://openwisp.io/docs/stable/radius/>`_: based on
|
|
59
|
+
FreeRADIUS, allows to implement network access authentication systems
|
|
60
|
+
like 802.1x WPA2 Enterprise, captive portal authentication, Hotspot 2.0
|
|
61
|
+
(802.11u)
|
|
62
62
|
- `openwisp-network-topology
|
|
63
63
|
<https://openwisp.io/docs/stable/network-topology/>`_: provides way to
|
|
64
64
|
collect and visualize network topology data from dynamic mesh routing
|
|
@@ -311,7 +311,8 @@ class BaseConfigAdmin(BaseAdmin):
|
|
|
311
311
|
config = instance.config
|
|
312
312
|
else:
|
|
313
313
|
raise Http404()
|
|
314
|
-
|
|
314
|
+
get_configuration = getattr(config, "get_cached_configuration", config.generate)
|
|
315
|
+
config_archive = get_configuration()
|
|
315
316
|
return send_file(
|
|
316
317
|
filename='{0}.tar.gz'.format(config.name),
|
|
317
318
|
contents=config_archive.getvalue(),
|
|
@@ -55,6 +55,7 @@ class ConfigConfig(AppConfig):
|
|
|
55
55
|
|
|
56
56
|
def __setmodels__(self):
|
|
57
57
|
self.device_model = load_model('config', 'Device')
|
|
58
|
+
self.template_model = load_model('config', 'Template')
|
|
58
59
|
self.devicegroup_model = load_model('config', 'DeviceGroup')
|
|
59
60
|
self.config_model = load_model('config', 'Config')
|
|
60
61
|
self.vpn_model = load_model('config', 'Vpn')
|
|
@@ -135,11 +136,21 @@ class ConfigConfig(AppConfig):
|
|
|
135
136
|
sender=self.config_model,
|
|
136
137
|
dispatch_uid='devicegroup_templates_change_handler.backend_changed',
|
|
137
138
|
)
|
|
139
|
+
pre_save.connect(
|
|
140
|
+
self.template_model.pre_save_handler,
|
|
141
|
+
sender=self.template_model,
|
|
142
|
+
dispatch_uid='template_pre_save_handler',
|
|
143
|
+
)
|
|
138
144
|
pre_save.connect(
|
|
139
145
|
handlers.organization_disabled_handler,
|
|
140
146
|
sender=self.org_model,
|
|
141
147
|
dispatch_uid='organization_disabled_pre_save_clear_device_checksum_cache',
|
|
142
148
|
)
|
|
149
|
+
post_save.connect(
|
|
150
|
+
self.template_model.post_save_handler,
|
|
151
|
+
sender=self.template_model,
|
|
152
|
+
dispatch_uid='template_post_save_handler',
|
|
153
|
+
)
|
|
143
154
|
post_save.connect(
|
|
144
155
|
self.org_limits.post_save_handler,
|
|
145
156
|
sender=self.org_model,
|
|
@@ -294,7 +305,7 @@ class ConfigConfig(AppConfig):
|
|
|
294
305
|
Triggers the cache invalidation for the
|
|
295
306
|
device config checksum (view and model method)
|
|
296
307
|
"""
|
|
297
|
-
from .controller.views import DeviceChecksumView
|
|
308
|
+
from .controller.views import DeviceChecksumView, GetVpnView
|
|
298
309
|
from .handlers import (
|
|
299
310
|
device_cache_invalidation_handler,
|
|
300
311
|
devicegroup_change_handler,
|
|
@@ -323,6 +334,21 @@ class ConfigConfig(AppConfig):
|
|
|
323
334
|
DeviceChecksumView.invalidate_checksum_cache,
|
|
324
335
|
dispatch_uid='invalidate_checksum_cache',
|
|
325
336
|
)
|
|
337
|
+
# VPN cache invalidation
|
|
338
|
+
post_save.connect(
|
|
339
|
+
GetVpnView.invalidate_get_vpn_cache,
|
|
340
|
+
sender=self.vpn_model,
|
|
341
|
+
dispatch_uid="invalidate_get_vpn_cache",
|
|
342
|
+
)
|
|
343
|
+
pre_delete.connect(
|
|
344
|
+
GetVpnView.invalidate_get_vpn_cache,
|
|
345
|
+
sender=self.vpn_model,
|
|
346
|
+
dispatch_uid="vpn_server_pre_delete_invalidate_get_vpn_cache",
|
|
347
|
+
)
|
|
348
|
+
vpn_server_modified.connect(
|
|
349
|
+
GetVpnView.invalidate_get_vpn_cache,
|
|
350
|
+
dispatch_uid="vpn_server_modified_invalidate_get_vpn_cache",
|
|
351
|
+
)
|
|
326
352
|
device_group_changed.connect(
|
|
327
353
|
devicegroup_change_handler,
|
|
328
354
|
sender=self.device_model,
|
{openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/base/base.py
RENAMED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import collections
|
|
2
2
|
import hashlib
|
|
3
3
|
import json
|
|
4
|
+
import logging
|
|
4
5
|
from copy import deepcopy
|
|
5
6
|
|
|
7
|
+
from cache_memoize import cache_memoize
|
|
6
8
|
from django.core.exceptions import ValidationError
|
|
7
9
|
from django.db import models
|
|
8
10
|
from django.utils.functional import cached_property
|
|
@@ -15,6 +17,82 @@ from openwisp_utils.base import TimeStampedEditableModel
|
|
|
15
17
|
|
|
16
18
|
from .. import settings as app_settings
|
|
17
19
|
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def get_cached_args_rewrite(instance):
|
|
24
|
+
"""
|
|
25
|
+
Use only the PK parameter for calculating the cache key
|
|
26
|
+
"""
|
|
27
|
+
return instance.pk.hex
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class ChecksumCacheMixin:
|
|
31
|
+
"""
|
|
32
|
+
Mixin that provides caching for checksum.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
_CHECKSUM_CACHE_TIMEOUT = 60 * 60 * 24 * 30 # 30 days
|
|
36
|
+
|
|
37
|
+
@cache_memoize(
|
|
38
|
+
timeout=_CHECKSUM_CACHE_TIMEOUT, args_rewrite=get_cached_args_rewrite
|
|
39
|
+
)
|
|
40
|
+
def get_cached_checksum(self):
|
|
41
|
+
"""
|
|
42
|
+
Handles caching,
|
|
43
|
+
timeout=None means value is cached indefinitely
|
|
44
|
+
(invalidation handled on post_save/post_delete signal)
|
|
45
|
+
"""
|
|
46
|
+
logger.debug(f"calculating checksum for {self.__class__.__name__} ID {self.pk}")
|
|
47
|
+
return self.checksum
|
|
48
|
+
|
|
49
|
+
@classmethod
|
|
50
|
+
def bulk_invalidate_get_cached_checksum(cls, query_params):
|
|
51
|
+
"""
|
|
52
|
+
Bulk invalidate checksum cache for multiple instances
|
|
53
|
+
"""
|
|
54
|
+
for instance in cls.objects.only("id").filter(**query_params).iterator():
|
|
55
|
+
instance.get_cached_checksum.invalidate(instance)
|
|
56
|
+
|
|
57
|
+
def invalidate_checksum_cache(self):
|
|
58
|
+
"""
|
|
59
|
+
Invalidate the checksum cache for this instance
|
|
60
|
+
"""
|
|
61
|
+
self.get_cached_checksum.invalidate(self)
|
|
62
|
+
logger.debug(
|
|
63
|
+
f"invalidated checksum cache for {self.__class__.__name__} ID {self.pk}"
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class ConfigChecksumCacheMixin(ChecksumCacheMixin):
|
|
68
|
+
"""
|
|
69
|
+
Mixin that provides caching for both checksum and configuration.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
@cache_memoize(
|
|
73
|
+
timeout=ChecksumCacheMixin._CHECKSUM_CACHE_TIMEOUT,
|
|
74
|
+
args_rewrite=get_cached_args_rewrite,
|
|
75
|
+
)
|
|
76
|
+
def get_cached_configuration(self):
|
|
77
|
+
"""
|
|
78
|
+
Returns cached configuration
|
|
79
|
+
"""
|
|
80
|
+
return self.generate()
|
|
81
|
+
|
|
82
|
+
def invalidate_configuration_cache(self):
|
|
83
|
+
"""
|
|
84
|
+
Invalidate the configuration cache for this instance
|
|
85
|
+
"""
|
|
86
|
+
self.get_cached_configuration.invalidate(self)
|
|
87
|
+
logger.debug(
|
|
88
|
+
f"invalidated configuration cache for {self.__class__.__name__}"
|
|
89
|
+
f" ID {self.pk}"
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
def invalidate_checksum_cache(self):
|
|
93
|
+
super().invalidate_checksum_cache()
|
|
94
|
+
self.invalidate_configuration_cache()
|
|
95
|
+
|
|
18
96
|
|
|
19
97
|
class BaseModel(TimeStampedEditableModel):
|
|
20
98
|
"""
|
|
@@ -89,7 +167,7 @@ class BaseConfig(BaseModel):
|
|
|
89
167
|
return config
|
|
90
168
|
c = deepcopy(config)
|
|
91
169
|
is_config = not any([self.__template__, self.__vpn__])
|
|
92
|
-
if 'hostname' not in c.get('general', {})
|
|
170
|
+
if all(('hostname' not in c.get('general', {}), is_config, self.name)):
|
|
93
171
|
c.setdefault('general', {})
|
|
94
172
|
c['general']['hostname'] = self.name.replace(':', '-')
|
|
95
173
|
return c
|
{openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/base/config.py
RENAMED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import collections
|
|
2
2
|
import logging
|
|
3
3
|
import re
|
|
4
|
+
from collections import defaultdict
|
|
4
5
|
|
|
5
|
-
from cache_memoize import cache_memoize
|
|
6
6
|
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied, ValidationError
|
|
7
7
|
from django.db import models, transaction
|
|
8
8
|
from django.utils.translation import gettext_lazy as _
|
|
@@ -23,11 +23,20 @@ from ..signals import (
|
|
|
23
23
|
)
|
|
24
24
|
from ..sortedm2m.fields import SortedManyToManyField
|
|
25
25
|
from ..utils import get_default_templates_queryset
|
|
26
|
-
from .base import BaseConfig
|
|
26
|
+
from .base import BaseConfig, ChecksumCacheMixin, get_cached_args_rewrite
|
|
27
27
|
|
|
28
28
|
logger = logging.getLogger(__name__)
|
|
29
29
|
|
|
30
30
|
|
|
31
|
+
def get_cached_checksum_args_rewrite(config):
|
|
32
|
+
"""
|
|
33
|
+
DEPRECATED: Use get_cached_args_rewrite instead.
|
|
34
|
+
|
|
35
|
+
TODO: Remove this in 1.2.0 release.
|
|
36
|
+
"""
|
|
37
|
+
return get_cached_args_rewrite(config)
|
|
38
|
+
|
|
39
|
+
|
|
31
40
|
class TemplatesThrough(object):
|
|
32
41
|
"""
|
|
33
42
|
Improves string representation of m2m relationship objects
|
|
@@ -37,14 +46,7 @@ class TemplatesThrough(object):
|
|
|
37
46
|
return _('Relationship with {0}').format(self.template.name)
|
|
38
47
|
|
|
39
48
|
|
|
40
|
-
|
|
41
|
-
"""
|
|
42
|
-
Use only the PK parameter for calculating the cache key
|
|
43
|
-
"""
|
|
44
|
-
return config.pk.hex
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
class AbstractConfig(BaseConfig):
|
|
49
|
+
class AbstractConfig(ChecksumCacheMixin, BaseConfig):
|
|
48
50
|
"""
|
|
49
51
|
Abstract model implementing the
|
|
50
52
|
NetJSON DeviceConfiguration object
|
|
@@ -149,23 +151,6 @@ class AbstractConfig(BaseConfig):
|
|
|
149
151
|
"""
|
|
150
152
|
return self.device.key
|
|
151
153
|
|
|
152
|
-
@cache_memoize(
|
|
153
|
-
timeout=_CHECKSUM_CACHE_TIMEOUT, args_rewrite=get_cached_checksum_args_rewrite
|
|
154
|
-
)
|
|
155
|
-
def get_cached_checksum(self):
|
|
156
|
-
"""
|
|
157
|
-
Handles caching,
|
|
158
|
-
timeout=None means value is cached indefinitely
|
|
159
|
-
(invalidation handled on post_save/post_delete signal)
|
|
160
|
-
"""
|
|
161
|
-
logger.debug(f'calculating checksum for config ID {self.pk}')
|
|
162
|
-
return self.checksum
|
|
163
|
-
|
|
164
|
-
@classmethod
|
|
165
|
-
def bulk_invalidate_get_cached_checksum(cls, query_params):
|
|
166
|
-
for config in cls.objects.only('id').filter(**query_params).iterator():
|
|
167
|
-
config.get_cached_checksum.invalidate(config)
|
|
168
|
-
|
|
169
154
|
@classmethod
|
|
170
155
|
def get_template_model(cls):
|
|
171
156
|
return cls.templates.rel.model
|
|
@@ -185,6 +170,60 @@ class AbstractConfig(BaseConfig):
|
|
|
185
170
|
templates = pk_set
|
|
186
171
|
return templates
|
|
187
172
|
|
|
173
|
+
@classmethod
|
|
174
|
+
def clean_duplicate_vpn_client_templates(
|
|
175
|
+
cls, action, instance, templates, raw_data=None
|
|
176
|
+
):
|
|
177
|
+
"""
|
|
178
|
+
Multiple VPN client templates related to the same VPN server are not allowed:
|
|
179
|
+
it hardly makes sense, preventing it keeps things simple and avoids headaches.
|
|
180
|
+
Raises a ValidationError if duplicates are found.
|
|
181
|
+
"""
|
|
182
|
+
if action != "pre_add":
|
|
183
|
+
return
|
|
184
|
+
|
|
185
|
+
def format_template_list(names):
|
|
186
|
+
quoted = [f'"{name}"' for name in names]
|
|
187
|
+
if len(quoted) == 2:
|
|
188
|
+
return " and ".join(quoted)
|
|
189
|
+
return ", ".join(quoted[:-1]) + " and " + quoted[-1]
|
|
190
|
+
|
|
191
|
+
def add_vpn_templates(templates_queryset):
|
|
192
|
+
for template in templates_queryset.filter(type="vpn"):
|
|
193
|
+
if template.name not in vpn_templates[template.vpn.name]:
|
|
194
|
+
vpn_templates[template.vpn.name].append(template.name)
|
|
195
|
+
|
|
196
|
+
raw_data = raw_data or {}
|
|
197
|
+
vpn_templates = defaultdict(list)
|
|
198
|
+
if not raw_data:
|
|
199
|
+
# When raw_data is present, validation is triggered by a
|
|
200
|
+
# ConfigForm submission.
|
|
201
|
+
# In this case, the "templates" queryset already contains only the templates
|
|
202
|
+
# that are intended to be assigned. Templates that would be removed
|
|
203
|
+
# (e.g., in a pre_clear action) have already been excluded from the
|
|
204
|
+
# queryset.
|
|
205
|
+
add_vpn_templates(instance.templates)
|
|
206
|
+
add_vpn_templates(templates)
|
|
207
|
+
|
|
208
|
+
error_lines = [
|
|
209
|
+
_(
|
|
210
|
+
"You cannot select multiple VPN client templates related to"
|
|
211
|
+
" the same VPN server."
|
|
212
|
+
)
|
|
213
|
+
]
|
|
214
|
+
for vpn_name, template_names in vpn_templates.items():
|
|
215
|
+
if len(template_names) < 2:
|
|
216
|
+
continue
|
|
217
|
+
template_list = format_template_list(sorted(template_names))
|
|
218
|
+
error_lines.append(
|
|
219
|
+
_(
|
|
220
|
+
"The templates {template_list} are all linked"
|
|
221
|
+
' to the same VPN server: "{vpn_name}".'
|
|
222
|
+
).format(template_list=template_list, vpn_name=vpn_name)
|
|
223
|
+
)
|
|
224
|
+
if len(error_lines) > 1:
|
|
225
|
+
raise ValidationError("\n".join(str(line) for line in error_lines))
|
|
226
|
+
|
|
188
227
|
@classmethod
|
|
189
228
|
def clean_templates(cls, action, instance, pk_set, raw_data=None, **kwargs):
|
|
190
229
|
"""
|
|
@@ -203,6 +242,9 @@ class AbstractConfig(BaseConfig):
|
|
|
203
242
|
)
|
|
204
243
|
if not templates:
|
|
205
244
|
return
|
|
245
|
+
cls.clean_duplicate_vpn_client_templates(
|
|
246
|
+
action, instance, templates, raw_data=raw_data
|
|
247
|
+
)
|
|
206
248
|
backend = instance.get_backend_instance(template_instances=templates)
|
|
207
249
|
try:
|
|
208
250
|
cls.clean_netjsonconfig_backend(backend)
|
|
@@ -256,7 +298,7 @@ class AbstractConfig(BaseConfig):
|
|
|
256
298
|
|
|
257
299
|
if action == 'post_clear':
|
|
258
300
|
if instance.is_deactivating_or_deactivated():
|
|
259
|
-
# If the device is deactivated or in the process of
|
|
301
|
+
# If the device is deactivated or in the process of deactivating, then
|
|
260
302
|
# delete all vpn clients and return.
|
|
261
303
|
instance.vpnclient_set.all().delete()
|
|
262
304
|
return
|
|
@@ -265,37 +307,48 @@ class AbstractConfig(BaseConfig):
|
|
|
265
307
|
# coming from signal
|
|
266
308
|
if isinstance(pk_set, set):
|
|
267
309
|
template_model = cls.get_template_model()
|
|
268
|
-
# Ordering the queryset here doesn't affect the functionality
|
|
269
|
-
# since pk_set is a set. Though ordering the queryset is required
|
|
270
|
-
# for tests.
|
|
271
310
|
templates = template_model.objects.filter(pk__in=list(pk_set)).order_by(
|
|
272
311
|
'created'
|
|
273
312
|
)
|
|
274
313
|
# coming from admin ModelForm
|
|
275
314
|
else:
|
|
276
315
|
templates = pk_set
|
|
277
|
-
|
|
278
|
-
#
|
|
279
|
-
if action == 'post_add':
|
|
280
|
-
vpn_list = instance.templates.filter(type='vpn').values_list('vpn')
|
|
281
|
-
instance.vpnclient_set.exclude(vpn__in=vpn_list).delete()
|
|
282
|
-
# when adding or removing specific templates
|
|
316
|
+
|
|
317
|
+
# Handle template actions
|
|
283
318
|
for template in templates.filter(type='vpn'):
|
|
284
319
|
if action == 'post_add':
|
|
285
|
-
if
|
|
320
|
+
# Create VPN client if needed
|
|
321
|
+
if not vpn_client_model.objects.filter(
|
|
286
322
|
config=instance, vpn=template.vpn
|
|
287
323
|
).exists():
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
324
|
+
client = vpn_client_model(
|
|
325
|
+
config=instance,
|
|
326
|
+
vpn=template.vpn,
|
|
327
|
+
auto_cert=template.auto_cert,
|
|
328
|
+
)
|
|
329
|
+
client.full_clean()
|
|
330
|
+
client.save()
|
|
331
|
+
|
|
332
|
+
if len(pk_set) != templates.filter(required=True).count():
|
|
333
|
+
# Explanation:
|
|
334
|
+
# SortedManyToManyField clears all existing templates before adding
|
|
335
|
+
# new ones. This triggers an m2m_changed signal with the "post_clear"
|
|
336
|
+
# action, which is handled by the "enforce_required_templates" signal
|
|
337
|
+
# receiver. That receiver re-adds the required templates.
|
|
338
|
+
#
|
|
339
|
+
# Re-adding required templates triggers another m2m_changed signal
|
|
340
|
+
# with the "post_add" action. At this stage, only required templates
|
|
341
|
+
# exist in the DB, so we cannot yet determine which VpnClient objects
|
|
342
|
+
# should be deleted based on the new selection.
|
|
343
|
+
#
|
|
344
|
+
# Therefore, we defer deletion of VpnClient objects until the "post_add"
|
|
345
|
+
# signal is triggered again—after all templates, including the required
|
|
346
|
+
# ones, have been fully added. At that point, we can identify and
|
|
347
|
+
# delete VpnClient objects not linked to the final template set.
|
|
348
|
+
current_vpns = set(
|
|
349
|
+
instance.templates.filter(type='vpn').values_list('vpn_id', flat=True)
|
|
350
|
+
)
|
|
351
|
+
instance.vpnclient_set.exclude(vpn_id__in=current_vpns).delete()
|
|
299
352
|
|
|
300
353
|
@classmethod
|
|
301
354
|
def clean_templates_org(cls, action, instance, pk_set, raw_data=None, **kwargs):
|
|
@@ -428,7 +481,7 @@ class AbstractConfig(BaseConfig):
|
|
|
428
481
|
|
|
429
482
|
# Check if the device is using stock OpenWrt.
|
|
430
483
|
openwrt_match = re.search(
|
|
431
|
-
'[oO][pP][eE][nN][wW][rR][tT]\s*([\d.]+)', self.device.os
|
|
484
|
+
r'[oO][pP][eE][nN][wW][rR][tT]\s*([\d.]+)', self.device.os
|
|
432
485
|
)
|
|
433
486
|
if openwrt_match:
|
|
434
487
|
if version.parse(openwrt_match.group(1)) >= version.parse('21'):
|
{openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/base/template.py
RENAMED
|
@@ -106,30 +106,31 @@ class AbstractTemplate(ShareableOrgMixinUniqueName, BaseConfig):
|
|
|
106
106
|
verbose_name_plural = _('templates')
|
|
107
107
|
unique_together = (('organization', 'name'),)
|
|
108
108
|
|
|
109
|
-
|
|
109
|
+
@classmethod
|
|
110
|
+
def pre_save_handler(cls, instance, *args, **kwargs):
|
|
110
111
|
"""
|
|
111
|
-
|
|
112
|
-
if key attributes have changed (queries the database)
|
|
112
|
+
Modifies status of related configs
|
|
113
113
|
"""
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
114
|
+
try:
|
|
115
|
+
current = cls.objects.get(id=instance.id)
|
|
116
|
+
except cls.DoesNotExist:
|
|
117
|
+
return
|
|
118
|
+
if hasattr(instance, 'backend_instance'):
|
|
119
|
+
del instance.backend_instance
|
|
120
|
+
try:
|
|
121
|
+
current_checksum = current.checksum
|
|
122
|
+
except NetjsonconfigValidationError:
|
|
123
|
+
# If the Netjsonconfig library upgrade changes the schema,
|
|
124
|
+
# the old configuration may become invalid, raising an exception.
|
|
125
|
+
# Setting the checksum to None forces related configurations to update.
|
|
126
|
+
current_checksum = None
|
|
127
|
+
instance._update_related_config_status = instance.checksum != current_checksum
|
|
128
|
+
|
|
129
|
+
@classmethod
|
|
130
|
+
def post_save_handler(cls, instance, created, *args, **kwargs):
|
|
131
|
+
if not created and getattr(instance, '_update_related_config_status', False):
|
|
131
132
|
transaction.on_commit(
|
|
132
|
-
lambda: update_template_related_config_status.delay(
|
|
133
|
+
lambda: update_template_related_config_status.delay(instance.pk)
|
|
133
134
|
)
|
|
134
135
|
|
|
135
136
|
def _update_related_config_status(self):
|
{openwisp_controller-1.1.1 → openwisp_controller-1.1.2}/openwisp_controller/config/base/vpn.py
RENAMED
|
@@ -34,7 +34,7 @@ from ..tasks_zerotier import (
|
|
|
34
34
|
trigger_zerotier_server_update,
|
|
35
35
|
trigger_zerotier_server_update_member,
|
|
36
36
|
)
|
|
37
|
-
from .base import BaseConfig
|
|
37
|
+
from .base import BaseConfig, ConfigChecksumCacheMixin
|
|
38
38
|
|
|
39
39
|
logger = logging.getLogger(__name__)
|
|
40
40
|
|
|
@@ -44,7 +44,7 @@ def _peer_cache_key(vpn):
|
|
|
44
44
|
return str(vpn.pk)
|
|
45
45
|
|
|
46
46
|
|
|
47
|
-
class AbstractVpn(ShareableOrgMixinUniqueName, BaseConfig):
|
|
47
|
+
class AbstractVpn(ConfigChecksumCacheMixin, ShareableOrgMixinUniqueName, BaseConfig):
|
|
48
48
|
"""
|
|
49
49
|
Abstract VPN model
|
|
50
50
|
"""
|
|
@@ -282,6 +282,7 @@ class AbstractVpn(ShareableOrgMixinUniqueName, BaseConfig):
|
|
|
282
282
|
if create_dh:
|
|
283
283
|
transaction.on_commit(lambda: create_vpn_dh.delay(self.id))
|
|
284
284
|
if not created and self._send_vpn_modified_after_save:
|
|
285
|
+
self.invalidate_checksum_cache()
|
|
285
286
|
self._send_vpn_modified_signal()
|
|
286
287
|
self._send_vpn_modified_after_save = False
|
|
287
288
|
# For ZeroTier VPN server, if the
|
|
@@ -309,10 +310,9 @@ class AbstractVpn(ShareableOrgMixinUniqueName, BaseConfig):
|
|
|
309
310
|
]
|
|
310
311
|
current = self._meta.model.objects.only(*attrs).get(pk=self.pk)
|
|
311
312
|
for attr in attrs:
|
|
312
|
-
if getattr(self, attr)
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
break
|
|
313
|
+
if getattr(self, attr) != getattr(current, attr):
|
|
314
|
+
self._send_vpn_modified_after_save = True
|
|
315
|
+
break
|
|
316
316
|
|
|
317
317
|
def _send_vpn_modified_signal(self):
|
|
318
318
|
vpn_server_modified.send(sender=self.__class__, instance=self)
|
|
@@ -634,7 +634,7 @@ class AbstractVpn(ShareableOrgMixinUniqueName, BaseConfig):
|
|
|
634
634
|
# call auto_client and update the config
|
|
635
635
|
elif self._is_backend_type('zerotier') and template_backend_class:
|
|
636
636
|
auto = getattr(template_backend_class, 'zerotier_auto_client')(
|
|
637
|
-
name='
|
|
637
|
+
name='global',
|
|
638
638
|
networks=[
|
|
639
639
|
{'id': self.network_id, 'ifname': f'owzt{self.network_id[-6:]}'}
|
|
640
640
|
],
|
|
@@ -688,8 +688,10 @@ class AbstractVpn(ShareableOrgMixinUniqueName, BaseConfig):
|
|
|
688
688
|
for backend in ['wireguard', 'vxlan']:
|
|
689
689
|
if self._is_backend_type(backend):
|
|
690
690
|
getattr(self, f'_get_{backend}_peers').invalidate(self)
|
|
691
|
+
self.invalidate_checksum_cache()
|
|
691
692
|
if update:
|
|
692
693
|
getattr(self, f'_get_{backend}_peers')()
|
|
694
|
+
self.get_cached_configuration()
|
|
693
695
|
# Send signal for peers changed
|
|
694
696
|
vpn_peers_changed.send(sender=self.__class__, instance=self)
|
|
695
697
|
|