openwisp-controller 1.3.1__tar.gz → 1.3.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.
Files changed (378) hide show
  1. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/CHANGES.rst +55 -2
  2. {openwisp_controller-1.3.1/openwisp_controller.egg-info → openwisp_controller-1.3.2}/PKG-INFO +1 -1
  3. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/__init__.py +1 -1
  4. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/admin.py +12 -2
  5. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/api/download_views.py +6 -6
  6. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/templates/admin/config/device/delete_selected_confirmation.html +1 -1
  7. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/tests/test_admin.py +63 -0
  8. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/tests/test_api.py +62 -0
  9. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/connectors/openwrt/ssh.py +3 -1
  10. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/tests/test_models.py +44 -1
  11. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/api/views.py +2 -3
  12. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/tests/test_api.py +21 -0
  13. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2/openwisp_controller.egg-info}/PKG-INFO +1 -1
  14. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/LICENSE +0 -0
  15. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/MANIFEST.in +0 -0
  16. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/README.rst +0 -0
  17. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/admin.py +0 -0
  18. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/base.py +0 -0
  19. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/checks.py +0 -0
  20. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/__init__.py +0 -0
  21. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/api/__init__.py +0 -0
  22. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/api/filters.py +0 -0
  23. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/api/serializers.py +0 -0
  24. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/api/urls.py +0 -0
  25. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/api/views.py +0 -0
  26. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/api/zerotier_service.py +0 -0
  27. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/apps.py +0 -0
  28. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/base/__init__.py +0 -0
  29. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/base/base.py +0 -0
  30. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/base/cache.py +0 -0
  31. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/base/channels_consumer.py +0 -0
  32. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/base/config.py +0 -0
  33. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/base/device.py +0 -0
  34. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/base/device_group.py +0 -0
  35. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/base/multitenancy.py +0 -0
  36. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/base/tag.py +0 -0
  37. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/base/template.py +0 -0
  38. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/base/vpn.py +0 -0
  39. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/base/whois.py +0 -0
  40. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/controller/__init__.py +0 -0
  41. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/controller/urls.py +0 -0
  42. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/controller/views.py +0 -0
  43. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/converters.py +0 -0
  44. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/crypto.py +0 -0
  45. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/exceptions.py +0 -0
  46. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/exportable.py +0 -0
  47. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/filters.py +0 -0
  48. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/fixtures/test_templates.json +0 -0
  49. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/handlers.py +0 -0
  50. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/management/__init__.py +0 -0
  51. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/management/commands/__init__.py +0 -0
  52. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/management/commands/clear_last_ip.py +0 -0
  53. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/management/commands/print_cache_dependencies.py +0 -0
  54. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0001_squashed_0002_config_settings_uuid.py +0 -0
  55. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0003_template_tags.py +0 -0
  56. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0004_add_device_model.py +0 -0
  57. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0005_populate_device.py +0 -0
  58. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0006_config_device_not_null.py +0 -0
  59. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0007_simplify_config.py +0 -0
  60. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0008_update_indexes.py +0 -0
  61. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0009_device_system.py +0 -0
  62. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0010_auto_20180106_1814.py +0 -0
  63. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0011_update_device_mac_address.py +0 -0
  64. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0012_auto_20180219_1501.py +0 -0
  65. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0013_last_ip_management_ip_and_status_applied.py +0 -0
  66. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0014_device_hardware_id.py +0 -0
  67. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0015_default_groups_permissions.py +0 -0
  68. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0016_default_organization_config_settings.py +0 -0
  69. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0017_template_name_organization_unique_together.py +0 -0
  70. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0018_config_context.py +0 -0
  71. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0019_organization_mac_add_hardware_id_name_unique_together.py +0 -0
  72. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0020_remove_config_organization.py +0 -0
  73. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0021_vpn_key.py +0 -0
  74. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0022_vpn_format_dh.py +0 -0
  75. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0023_update_context.py +0 -0
  76. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0024_update_context_data.py +0 -0
  77. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0025_update_device_key.py +0 -0
  78. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0026_hardware_id_not_unique.py +0 -0
  79. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0027_add_indexes_on_ip_fields.py +0 -0
  80. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0028_template_default_values.py +0 -0
  81. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0029_merge_django_netjsonconfig.py +0 -0
  82. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0030_django_taggit_update.py +0 -0
  83. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0031_update_vpn_dh_param.py +0 -0
  84. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0032_update_legacy_vpn_backend.py +0 -0
  85. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0033_name_unique_per_organization.py +0 -0
  86. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0034_template_required.py +0 -0
  87. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0035_device_name_unique_optional.py +0 -0
  88. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0036_device_group.py +0 -0
  89. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0037_alter_taggedtemplate.py +0 -0
  90. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0038_vpn_subnet.py +0 -0
  91. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0039_wireguard_vxlan_ipam.py +0 -0
  92. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0040_vpnclient_ip_setnull.py +0 -0
  93. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0041_default_groups_organizationconfigsettings_permission.py +0 -0
  94. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0042_multiple_wireguard_tunnels.py +0 -0
  95. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0043_devicegroup_templates.py +0 -0
  96. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0044_config_error_reason.py +0 -0
  97. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0045_alter_vpn_webhook_endpoint.py +0 -0
  98. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0046_organizationlimits.py +0 -0
  99. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0047_add_organizationlimits.py +0 -0
  100. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0048_wifi_radio_band_migration.py +0 -0
  101. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0049_devicegroup_context.py +0 -0
  102. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0050_alter_vpnclient_unique_together.py +0 -0
  103. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0051_organizationconfigsettings_context.py +0 -0
  104. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0052_vpn_node_network_id.py +0 -0
  105. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0053_vpnclient_secret.py +0 -0
  106. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0054_device__is_deactivated.py +0 -0
  107. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0055_alter_config_status.py +0 -0
  108. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0056_vpnclient_template.py +0 -0
  109. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0057_populate_vpnclient_template.py +0 -0
  110. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0058_alter_vpnclient_template.py +0 -0
  111. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0059_zerotier_templates_ow_zt_to_global.py +0 -0
  112. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0060_cleanup_api_task_notification_types.py +0 -0
  113. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0061_config_checksum_db.py +0 -0
  114. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0062_whoisinfo.py +0 -0
  115. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0063_replace_jsonfield_with_django_builtin.py +0 -0
  116. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0064_template_notes.py +0 -0
  117. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/0065_whoisinfo_unreferenced_since.py +0 -0
  118. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/migrations/__init__.py +0 -0
  119. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/models.py +0 -0
  120. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/settings.py +0 -0
  121. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/signals.py +0 -0
  122. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/sortedm2m/__init__.py +0 -0
  123. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/sortedm2m/fields.py +0 -0
  124. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/sortedm2m/forms.py +0 -0
  125. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/config/css/admin.css +0 -0
  126. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/config/css/device-delete-confirmation.css +0 -0
  127. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/config/css/devicegroup.css +0 -0
  128. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/config/css/lib/advanced-mode.css +0 -0
  129. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/config/css/lib/img/jsoneditor-icons.svg +0 -0
  130. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/config/css/lib/jsonschema-ui.css +0 -0
  131. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/config/js/device-delete-confirmation.js +0 -0
  132. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/config/js/lib/advanced-mode.js +0 -0
  133. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/config/js/lib/jsonschema-ui.js +0 -0
  134. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/config/js/lib/tomorrow_night_bright.js +0 -0
  135. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/config/js/management_ip.js +0 -0
  136. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/config/js/preview.js +0 -0
  137. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/config/js/relevant_templates.js +0 -0
  138. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/config/js/switcher.js +0 -0
  139. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/config/js/tabs.js +0 -0
  140. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/config/js/unsaved_changes.js +0 -0
  141. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/config/js/utils.js +0 -0
  142. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/config/js/vpn.js +0 -0
  143. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/config/js/widget.js +0 -0
  144. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/import_export/import-openwisp.css +0 -0
  145. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/sortedm2m/patch_sortedm2m.js +0 -0
  146. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/support.css +0 -0
  147. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/whois/css/whois.css +0 -0
  148. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/whois/images/whois_globe.svg +0 -0
  149. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/static/whois/js/whois.js +0 -0
  150. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/tasks.py +0 -0
  151. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/tasks_zerotier.py +0 -0
  152. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/templates/admin/config/change_device_group.html +0 -0
  153. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/templates/admin/config/change_form.html +0 -0
  154. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/templates/admin/config/change_list_device.html +0 -0
  155. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/templates/admin/config/clone_template_form.html +0 -0
  156. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/templates/admin/config/device/change_form.html +0 -0
  157. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/templates/admin/config/device/delete_confirmation.html +0 -0
  158. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/templates/admin/config/device_recover_form.html +0 -0
  159. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/templates/admin/config/jsonschema-widget.html +0 -0
  160. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/templates/admin/config/preview.html +0 -0
  161. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/templates/admin/config/system_context.html +0 -0
  162. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/templates/admin/device_group/change_form.html +0 -0
  163. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/templates/admin/import_export/import.html +0 -0
  164. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/templates/reversion/config/revision_form.html +0 -0
  165. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/tests/__init__.py +0 -0
  166. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/tests/pytest.py +0 -0
  167. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/tests/test_apps.py +0 -0
  168. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/tests/test_config.py +0 -0
  169. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/tests/test_controller.py +0 -0
  170. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/tests/test_converters.py +0 -0
  171. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/tests/test_device.py +0 -0
  172. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/tests/test_device_group.py +0 -0
  173. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/tests/test_handlers.py +0 -0
  174. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/tests/test_notifications.py +0 -0
  175. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/tests/test_selenium.py +0 -0
  176. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/tests/test_tag.py +0 -0
  177. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/tests/test_template.py +0 -0
  178. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/tests/test_views.py +0 -0
  179. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/tests/test_vpn.py +0 -0
  180. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/tests/utils.py +0 -0
  181. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/urls.py +0 -0
  182. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/utils.py +0 -0
  183. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/validators.py +0 -0
  184. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/views.py +0 -0
  185. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/whois/__init__.py +0 -0
  186. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/whois/commands.py +0 -0
  187. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/whois/handlers.py +0 -0
  188. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/whois/mixins.py +0 -0
  189. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/whois/serializers.py +0 -0
  190. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/whois/service.py +0 -0
  191. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/whois/tasks.py +0 -0
  192. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/whois/tests/__init__.py +0 -0
  193. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/whois/tests/tests.py +0 -0
  194. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/whois/tests/utils.py +0 -0
  195. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/whois/utils.py +0 -0
  196. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/config/widgets.py +0 -0
  197. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/__init__.py +0 -0
  198. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/admin.py +0 -0
  199. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/api/serializers.py +0 -0
  200. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/api/urls.py +0 -0
  201. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/api/views.py +0 -0
  202. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/apps.py +0 -0
  203. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/base/__init__.py +0 -0
  204. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/base/models.py +0 -0
  205. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/channels/consumers.py +0 -0
  206. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/channels/routing.py +0 -0
  207. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/commands.py +0 -0
  208. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/connectors/__init__.py +0 -0
  209. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/connectors/airos/snmp.py +0 -0
  210. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/connectors/exceptions.py +0 -0
  211. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/connectors/openwrt/__init__.py +0 -0
  212. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/connectors/openwrt/snmp.py +0 -0
  213. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/connectors/snmp.py +0 -0
  214. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/connectors/ssh.py +0 -0
  215. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/exceptions.py +0 -0
  216. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/migrations/0001_initial.py +0 -0
  217. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/migrations/0002_credentials_auto_add.py +0 -0
  218. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/migrations/0003_default_group_permissions.py +0 -0
  219. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/migrations/0004_django3_1_upgrade.py +0 -0
  220. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/migrations/0005_device_connection_failure_reason.py +0 -0
  221. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/migrations/0006_name_unique_per_organization.py +0 -0
  222. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/migrations/0007_command.py +0 -0
  223. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/migrations/0008_remove_conflicting_deviceconnections.py +0 -0
  224. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/migrations/0009_alter_deviceconnection_unique_together.py +0 -0
  225. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/migrations/0010_replace_jsonfield_with_django_builtin.py +0 -0
  226. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/migrations/__init__.py +0 -0
  227. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/models.py +0 -0
  228. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/schema.py +0 -0
  229. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/settings.py +0 -0
  230. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/signals.py +0 -0
  231. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/static/connection/css/command-inline.css +0 -0
  232. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/static/connection/css/credentials.css +0 -0
  233. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/static/connection/js/commands.js +0 -0
  234. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/static/connection/js/credentials.js +0 -0
  235. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/static/connection/js/lib/reconnecting-websocket.min.js +0 -0
  236. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/tasks.py +0 -0
  237. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/tests/__init__.py +0 -0
  238. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/tests/base.py +0 -0
  239. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/tests/pytest.py +0 -0
  240. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/tests/test-key.ed25519 +0 -0
  241. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/tests/test-key.rsa +0 -0
  242. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/tests/test_admin.py +0 -0
  243. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/tests/test_api.py +0 -0
  244. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/tests/test_command_utilities.py +0 -0
  245. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/tests/test_notifications.py +0 -0
  246. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/tests/test_selenium.py +0 -0
  247. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/tests/test_snmp.py +0 -0
  248. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/tests/test_ssh.py +0 -0
  249. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/tests/test_tasks.py +0 -0
  250. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/tests/utils.py +0 -0
  251. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/utils.py +0 -0
  252. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/connection/widgets.py +0 -0
  253. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/context_processors.py +0 -0
  254. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/__init__.py +0 -0
  255. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/admin.py +0 -0
  256. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/api/__init__.py +0 -0
  257. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/api/filters.py +0 -0
  258. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/api/serializers.py +0 -0
  259. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/api/urls.py +0 -0
  260. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/api/views.py +0 -0
  261. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/apps.py +0 -0
  262. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/base/__init__.py +0 -0
  263. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/base/models.py +0 -0
  264. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/channels/__init__.py +0 -0
  265. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/channels/consumers.py +0 -0
  266. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/channels/routing.py +0 -0
  267. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/estimated_location/__init__.py +0 -0
  268. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/estimated_location/handlers.py +0 -0
  269. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/estimated_location/mixins.py +0 -0
  270. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/estimated_location/service.py +0 -0
  271. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/estimated_location/tasks.py +0 -0
  272. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/estimated_location/tests/__init__.py +0 -0
  273. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/estimated_location/tests/tests.py +0 -0
  274. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/estimated_location/tests/utils.py +0 -0
  275. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/estimated_location/utils.py +0 -0
  276. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/exportable.py +0 -0
  277. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/migrations/0001_initial.py +0 -0
  278. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/migrations/0002_default_groups_permissions.py +0 -0
  279. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/migrations/0003_alter_devicelocation_floorplan_location.py +0 -0
  280. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/migrations/0004_location_is_estimated.py +0 -0
  281. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/migrations/0005_organizationgeosettings.py +0 -0
  282. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/migrations/0006_create_geo_settings_for_existing_orgs.py +0 -0
  283. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/migrations/__init__.py +0 -0
  284. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/models.py +0 -0
  285. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/settings.py +0 -0
  286. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/tasks.py +0 -0
  287. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/templates/admin/geo/device_location_inline.html +0 -0
  288. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/templates/admin/geo/location/change_form.html +0 -0
  289. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/templates/admin/widgets/foreign_key_raw_id.html +0 -0
  290. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/tests/__init__.py +0 -0
  291. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/tests/pytest.py +0 -0
  292. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/tests/test_admin.py +0 -0
  293. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/tests/test_admin_inline.py +0 -0
  294. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/tests/test_api.py +0 -0
  295. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/tests/test_apps.py +0 -0
  296. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/tests/test_models.py +0 -0
  297. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/tests/test_selenium.py +0 -0
  298. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/tests/utils.py +0 -0
  299. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/geo/utils.py +0 -0
  300. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/migrations.py +0 -0
  301. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/mixins.py +0 -0
  302. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/__init__.py +0 -0
  303. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/admin.py +0 -0
  304. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/api/serializers.py +0 -0
  305. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/api/urls.py +0 -0
  306. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/apps.py +0 -0
  307. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/base/__init__.py +0 -0
  308. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/base/models.py +0 -0
  309. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/migrations/0001_initial.py +0 -0
  310. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/migrations/0002_add_organization_name.py +0 -0
  311. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/migrations/0003_fill_organization_name.py +0 -0
  312. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/migrations/0004_auto_20180106_1814.py +0 -0
  313. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/migrations/0005_organizational_unit_name.py +0 -0
  314. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/migrations/0006_add_x509_passphrase_field.py +0 -0
  315. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/migrations/0007_default_groups_permissions.py +0 -0
  316. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/migrations/0008_serial_number_length.py +0 -0
  317. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/migrations/0009_common_name_maxlength_64.py +0 -0
  318. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/migrations/0010_common_name_organization_unique.py +0 -0
  319. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/migrations/0011_disallowed_blank_key_length_or_digest.py +0 -0
  320. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/migrations/0012_alter_ca_extensions_alter_ca_key_length_and_more.py +0 -0
  321. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/migrations/__init__.py +0 -0
  322. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/models.py +0 -0
  323. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/static/admin/pki/js/show-org-field.js +0 -0
  324. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/templates/admin/pki/change_form.html +0 -0
  325. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/tests/__init__.py +0 -0
  326. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/tests/test_admin.py +0 -0
  327. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/tests/test_models.py +0 -0
  328. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/tests/utils.py +0 -0
  329. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/urls.py +0 -0
  330. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/pki/utils.py +0 -0
  331. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/routing.py +0 -0
  332. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/serializers.py +0 -0
  333. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/settings.py +0 -0
  334. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/__init__.py +0 -0
  335. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/admin.py +0 -0
  336. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/apps.py +0 -0
  337. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/base/models.py +0 -0
  338. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/filters.py +0 -0
  339. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/migrations/0001_initial.py +0 -0
  340. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/migrations/0002_default_group_migration.py +0 -0
  341. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/migrations/0003_related_field_allow_blank.py +0 -0
  342. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/migrations/0004_index_rule_on_delete.py +0 -0
  343. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/migrations/0005_number_of_subnets_and_ips.py +0 -0
  344. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/migrations/__init__.py +0 -0
  345. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/models.py +0 -0
  346. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/rule_types/__init__.py +0 -0
  347. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/rule_types/base.py +0 -0
  348. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/rule_types/device.py +0 -0
  349. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/rule_types/vpn.py +0 -0
  350. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/settings.py +0 -0
  351. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/signals.py +0 -0
  352. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/static/subnet-division/css/subnet-division.css +0 -0
  353. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/static/subnet-division/js/subnet-division.js +0 -0
  354. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/tasks.py +0 -0
  355. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/tests/__init__.py +0 -0
  356. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/tests/helpers.py +0 -0
  357. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/tests/test_admin.py +0 -0
  358. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/tests/test_models.py +0 -0
  359. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/tests/test_rule.py +0 -0
  360. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/subnet_division/utils.py +0 -0
  361. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/tests/__init__.py +0 -0
  362. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/tests/mixins.py +0 -0
  363. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/tests/test_migrationgraph.py +0 -0
  364. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/tests/test_selenium.py +0 -0
  365. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/tests/test_users_integration.py +0 -0
  366. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/tests/test_utilities.py +0 -0
  367. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/tests/utils.py +0 -0
  368. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/urls.py +0 -0
  369. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller/vpn_backends.py +0 -0
  370. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller.egg-info/SOURCES.txt +0 -0
  371. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller.egg-info/dependency_links.txt +0 -0
  372. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller.egg-info/not-zip-safe +0 -0
  373. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller.egg-info/requires.txt +0 -0
  374. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/openwisp_controller.egg-info/top_level.txt +0 -0
  375. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/pyproject.toml +0 -0
  376. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/requirements.txt +0 -0
  377. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/setup.cfg +0 -0
  378. {openwisp_controller-1.3.1 → openwisp_controller-1.3.2}/setup.py +0 -0
@@ -1,6 +1,57 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ Version 1.3.3 [2026-10-23]
5
+ --------------------------
6
+
7
+ Bugfixes
8
+ ~~~~~~~~
9
+
10
+ - Prevented cross-organization configuration access in admin
11
+
12
+ Updated admin configuration download and context views to resolve
13
+ devices, VPNs, and templates through organization-scoped querysets and
14
+ object permissions.
15
+
16
+ This ensures users cannot access configuration data for resources
17
+ belonging to unauthorized organizations.
18
+
19
+ Advisory: `GHSA-2x7f-qxwh-m483
20
+ <https://github.com/openwisp/openwisp-controller/security/advisories/GHSA-2x7f-qxwh-m483>`_.
21
+
22
+ - Prevented cross-organization access to configuration downloads
23
+
24
+ Updated API configuration download views to resolve devices, VPNs, and
25
+ templates through organization-scoped querysets and object permissions.
26
+
27
+ This ensures users cannot access configuration downloads for resources
28
+ belonging to unauthorized organizations.
29
+
30
+ Advisory: `GHSA-5c5w-h9xc-3mq5
31
+ <https://github.com/openwisp/openwisp-controller/security/advisories/GHSA-5c5w-h9xc-3mq5>`_.
32
+
33
+ - Escaped OpenWrt change_password SSH command
34
+
35
+ The password and confirm_password values were interpolated into the
36
+ remote shell command without escaping, allowing shell command injection
37
+ on the device. They are now quoted with shlex.quote() and passed to
38
+ printf instead of echo -e, so backslashes are no longer interpreted.
39
+
40
+ Advisory: `GHSA-rcf7-q946-fvpg
41
+ <https://github.com/openwisp/openwisp-controller/security/advisories/GHSA-rcf7-q946-fvpg>`_.
42
+
43
+ - Prevented cross-organization access to CA CRLs
44
+
45
+ Organization managers with permission to view CAs could guess CA IDs and
46
+ download certificate revocation lists belonging to other organizations.
47
+
48
+ The issue did not expose CA private keys or allow changes. It primarily
49
+ affected deployments configured to protect CRLs, because CRLs are
50
+ publicly accessible by default.
51
+
52
+ Advisory: `GHSA-9gh4-xw24-9xh5
53
+ <https://github.com/openwisp/openwisp-controller/security/advisories/GHSA-9gh4-xw24-9xh5>`_.
54
+
4
55
  Version 1.3.1 [2026-10-15]
5
56
  --------------------------
6
57
 
@@ -22,7 +73,8 @@ Security
22
73
  and run in a database transaction, preventing rejected requests from
23
74
  leaving related database objects or files behind.
24
75
 
25
- Advisory: **GHSA-39c4-xj33-j8j3**.
76
+ Advisory: `GHSA-39c4-xj33-j8j3
77
+ <https://github.com/openwisp/openwisp-controller/security/advisories/GHSA-39c4-xj33-j8j3>`_.
26
78
 
27
79
  - Fixed XSS vulnerabilities in device and command admin UI
28
80
 
@@ -36,7 +88,8 @@ Security
36
88
  These vulnerabilities could allow attackers to execute malicious
37
89
  JavaScript in an administrator's browser.
38
90
 
39
- Advisory: **GHSA-4f2x-pxjx-h8m3**.
91
+ Advisory: `GHSA-4f2x-pxjx-h8m3
92
+ <https://github.com/openwisp/openwisp-controller/security/advisories/GHSA-4f2x-pxjx-h8m3>`_.
40
93
 
41
94
  Bugfixes
42
95
  ~~~~~~~~
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openwisp-controller
3
- Version: 1.3.1
3
+ Version: 1.3.2
4
4
  Summary: OpenWISP Controller
5
5
  Home-page: http://openwisp.org
6
6
  Download-URL: https://github.com/openwisp/openwisp-controller/releases
@@ -1,4 +1,4 @@
1
- VERSION = (1, 3, 1, "final")
1
+ VERSION = (1, 3, 2, "final")
2
2
  __version__ = VERSION # alias
3
3
 
4
4
 
@@ -13,6 +13,7 @@ from django.contrib.contenttypes.models import ContentType
13
13
  from django.core.exceptions import (
14
14
  FieldDoesNotExist,
15
15
  ObjectDoesNotExist,
16
+ PermissionDenied,
16
17
  ValidationError,
17
18
  )
18
19
  from django.db import models
@@ -318,7 +319,10 @@ class BaseConfigAdmin(BaseAdmin):
318
319
  )
319
320
 
320
321
  def download_view(self, request, pk):
321
- instance = get_object_or_404(self.model, pk=pk)
322
+ instance = self._get_instance(request, pk)
323
+ return self.get_download_response(instance)
324
+
325
+ def get_download_response(self, instance):
322
326
  if hasattr(instance, "generate"):
323
327
  config = instance
324
328
  elif hasattr(instance, "config"):
@@ -333,10 +337,16 @@ class BaseConfigAdmin(BaseAdmin):
333
337
  )
334
338
 
335
339
  def context_view(self, request, pk):
336
- instance = get_object_or_404(self.model, pk=pk)
340
+ instance = self._get_instance(request, pk)
337
341
  context = json.dumps(instance.get_context())
338
342
  return HttpResponse(context, content_type="application/json")
339
343
 
344
+ def _get_instance(self, request, pk):
345
+ instance = get_object_or_404(self.get_queryset(request), pk=pk)
346
+ if not self.has_view_permission(request, instance):
347
+ raise PermissionDenied
348
+ return instance
349
+
340
350
 
341
351
  class BaseForm(forms.ModelForm):
342
352
  """
@@ -17,29 +17,29 @@ Template = load_model("config", "Template")
17
17
 
18
18
  class DownloadVpnView(ProtectedAPIMixin, RetrieveAPIView):
19
19
  serializer_class = VpnSerializer
20
- queryset = Vpn.objects.none()
20
+ queryset = Vpn.objects.all()
21
21
  model = Vpn
22
22
 
23
23
  def retrieve(self, request, *args, **kwargs):
24
- return BaseConfigAdmin.download_view(self, request, pk=kwargs["pk"])
24
+ return BaseConfigAdmin.get_download_response(self, self.get_object())
25
25
 
26
26
 
27
27
  class DownloadDeviceView(ProtectedAPIMixin, RetrieveAPIView):
28
28
  serializer_class = DeviceListSerializer
29
- queryset = Device.objects.none()
29
+ queryset = Device.objects.all()
30
30
  model = Device
31
31
 
32
32
  def retrieve(self, request, *args, **kwargs):
33
- return BaseConfigAdmin.download_view(self, request, pk=kwargs["pk"])
33
+ return BaseConfigAdmin.get_download_response(self, self.get_object())
34
34
 
35
35
 
36
36
  class DownloadTemplateconfiguration(ProtectedAPIMixin, RetrieveAPIView):
37
37
  serializer_class = TemplateSerializer
38
- queryset = Template.objects.none()
38
+ queryset = Template.objects.all()
39
39
  model = Template
40
40
 
41
41
  def retrieve(self, request, *args, **kwargs):
42
- return BaseConfigAdmin.download_view(self, request, pk=kwargs["pk"])
42
+ return BaseConfigAdmin.get_download_response(self, self.get_object())
43
43
 
44
44
 
45
45
  download_vpn_config = DownloadVpnView.as_view()
@@ -51,7 +51,7 @@
51
51
  {% endblocktranslate %}
52
52
  </p>
53
53
  <span>
54
- <button class="danger-btn" id="warning-ack">"{% blocktranslate count counter=active_devices|length %}I understand the risks, delete the device{% plural %}I understand the risks, delete the devices{% endblocktranslate %}</button>
54
+ <button class="danger-btn" id="warning-ack">{% blocktranslate count counter=active_devices|length %}I understand the risks, delete the device{% plural %}I understand the risks, delete the devices{% endblocktranslate %}</button>
55
55
  <button class="button cancel-link">{% translate 'No, take me back' %}</button>
56
56
  </span>
57
57
  </li>
@@ -507,6 +507,69 @@ class TestAdmin(
507
507
  ],
508
508
  )
509
509
 
510
+ def test_config_download_and_context_views_multitenancy(self):
511
+ data = self._create_multitenancy_test_env(vpn=True)
512
+ self.client.force_login(data["operator"])
513
+ instances = {
514
+ "device": (data["c1"].device, data["c2"].device),
515
+ "template": (data["t1"], data["t2"]),
516
+ "vpn": (data["vpn1"], data["vpn2"]),
517
+ }
518
+
519
+ for model, (managed, unmanaged) in instances.items():
520
+ with self.subTest(model=model, view="download", organization="managed"):
521
+ response = self.client.get(
522
+ reverse(
523
+ f"admin:{self.app_label}_{model}_download", args=[managed.pk]
524
+ )
525
+ )
526
+ self.assertEqual(response.status_code, 200)
527
+
528
+ with self.subTest(model=model, view="download", organization="unmanaged"):
529
+ response = self.client.get(
530
+ reverse(
531
+ f"admin:{self.app_label}_{model}_download", args=[unmanaged.pk]
532
+ )
533
+ )
534
+ self.assertEqual(response.status_code, 404)
535
+
536
+ with self.subTest(model=model, view="context", organization="managed"):
537
+ response = self.client.get(
538
+ reverse(
539
+ f"admin:{self.app_label}_{model}_context", args=[managed.pk]
540
+ )
541
+ )
542
+ self.assertEqual(response.status_code, 200)
543
+
544
+ with self.subTest(model=model, view="context", organization="unmanaged"):
545
+ response = self.client.get(
546
+ reverse(
547
+ f"admin:{self.app_label}_{model}_context", args=[unmanaged.pk]
548
+ )
549
+ )
550
+ self.assertEqual(response.status_code, 404)
551
+
552
+ with (
553
+ self.subTest(model=model, permission="denied"),
554
+ patch.object(
555
+ admin.site._registry[managed.__class__],
556
+ "has_view_permission",
557
+ return_value=False,
558
+ ),
559
+ ):
560
+ response = self.client.get(
561
+ reverse(
562
+ f"admin:{self.app_label}_{model}_download", args=[managed.pk]
563
+ )
564
+ )
565
+ self.assertEqual(response.status_code, 403)
566
+ response = self.client.get(
567
+ reverse(
568
+ f"admin:{self.app_label}_{model}_context", args=[managed.pk]
569
+ )
570
+ )
571
+ self.assertEqual(response.status_code, 403)
572
+
510
573
  def test_vpn_organization_fk_autocomplete_view(self):
511
574
  data = self._create_multitenancy_test_env()
512
575
  self._test_multitenant_admin(
@@ -559,6 +559,68 @@ class TestConfigApi(
559
559
  r = self.client.get(path)
560
560
  self.assertEqual(r.status_code, 200)
561
561
 
562
+ def test_download_api_multitenancy(self):
563
+ org1 = self._create_org(name="org1")
564
+ org2 = self._create_org(name="org2")
565
+ device1 = self._create_config(organization=org1).device
566
+ device2 = self._create_config(organization=org2).device
567
+ template1 = self._create_template(name="template1", organization=org1)
568
+ template2 = self._create_template(name="template2", organization=org2)
569
+ vpn1 = self._create_vpn(name="vpn1", organization=org1)
570
+ vpn2 = self._create_vpn(name="vpn2", organization=org2)
571
+ shared_vpn = self._create_vpn(name="shared-vpn", organization=None)
572
+ operator = self._create_operator(organizations=[org1])
573
+ self.client.force_login(operator)
574
+
575
+ with self.subTest("Device of managed organization"):
576
+ r = self.client.get(
577
+ reverse("config_api:download_device_config", args=[device1.pk])
578
+ )
579
+ self.assertEqual(r.status_code, 200)
580
+
581
+ with self.subTest("Device of other organization"):
582
+ r = self.client.get(
583
+ reverse("config_api:download_device_config", args=[device2.pk])
584
+ )
585
+ self.assertEqual(r.status_code, 404)
586
+
587
+ with self.subTest("Template of managed organization"):
588
+ r = self.client.get(
589
+ reverse("config_api:download_template_config", args=[template1.pk])
590
+ )
591
+ self.assertEqual(r.status_code, 200)
592
+
593
+ with self.subTest("Template of other organization"):
594
+ r = self.client.get(
595
+ reverse("config_api:download_template_config", args=[template2.pk])
596
+ )
597
+ self.assertEqual(r.status_code, 404)
598
+
599
+ with self.subTest("VPN of managed organization"):
600
+ r = self.client.get(
601
+ reverse("config_api:download_vpn_config", args=[vpn1.pk])
602
+ )
603
+ self.assertEqual(r.status_code, 200)
604
+
605
+ with self.subTest("VPN of other organization"):
606
+ r = self.client.get(
607
+ reverse("config_api:download_vpn_config", args=[vpn2.pk])
608
+ )
609
+ self.assertEqual(r.status_code, 404)
610
+
611
+ vpn2.get_cached_configuration()
612
+ with self.subTest("Cached VPN of other organization"):
613
+ r = self.client.get(
614
+ reverse("config_api:download_vpn_config", args=[vpn2.pk])
615
+ )
616
+ self.assertEqual(r.status_code, 404)
617
+
618
+ with self.subTest("Shared VPN"):
619
+ r = self.client.get(
620
+ reverse("config_api:download_vpn_config", args=[shared_vpn.pk])
621
+ )
622
+ self.assertEqual(r.status_code, 200)
623
+
562
624
  def test_update_deactivated_device(self):
563
625
  device = self._create_device(_is_deactivated=True)
564
626
  path = reverse("config_api:device_detail", args=[device.pk])
@@ -1,4 +1,5 @@
1
1
  import logging
2
+ from shlex import quote
2
3
 
3
4
  from packaging import version
4
5
 
@@ -47,7 +48,8 @@ class OpenWrt(Ssh):
47
48
 
48
49
  def change_password(self, password, confirm_password, user="root"):
49
50
  return self.exec_command(
50
- f'echo -e "{password}\n{confirm_password}" | passwd {user}'
51
+ f"printf '%s\\n%s\\n' {quote(password)} {quote(confirm_password)} "
52
+ f"| passwd {quote(user)}"
51
53
  )
52
54
 
53
55
 
@@ -782,7 +782,7 @@ HZAAAAgAhZz8ve4sK9Wbopq43Cu2kQDgX4NoA6W+FCmxCKf5AhYIzYQxIqyCazd7MrjCwS""",
782
782
  connect_mocked.assert_called_once()
783
783
  mocked_exec_command.assert_called_once()
784
784
  mocked_exec_command.assert_called_with(
785
- 'echo -e "Newpasswd@123\nNewpasswd@123" | passwd root',
785
+ "printf '%s\\n%s\\n' Newpasswd@123 Newpasswd@123 | passwd root",
786
786
  timeout=app_settings.SSH_COMMAND_TIMEOUT,
787
787
  )
788
788
  command.refresh_from_db()
@@ -790,6 +790,49 @@ HZAAAAgAhZz8ve4sK9Wbopq43Cu2kQDgX4NoA6W+FCmxCKf5AhYIzYQxIqyCazd7MrjCwS""",
790
790
  self.assertEqual(command.output, "Changed password for user root.\n")
791
791
  self.assertEqual(list(command.arguments), ["********"])
792
792
 
793
+ @mock.patch(_connect_path)
794
+ def test_execute_change_password_shell_metacharacters(self, connect_mocked):
795
+ dc = self._create_device_connection()
796
+
797
+ def _assert_quoted(password, expected):
798
+ command = Command(
799
+ device=dc.device,
800
+ connection=dc,
801
+ type="change_password",
802
+ input={"password": password, "confirm_password": password},
803
+ )
804
+ command.full_clean()
805
+ with mock.patch(_exec_command_path) as mocked_exec_command:
806
+ mocked_exec_command.return_value = self._exec_command_return_value(
807
+ stdout="Changed password for user root."
808
+ )
809
+ command.save()
810
+ command.execute()
811
+ mocked_exec_command.assert_called_once_with(
812
+ f"printf '%s\\n%s\\n' {expected} {expected} | passwd root",
813
+ timeout=app_settings.SSH_COMMAND_TIMEOUT,
814
+ )
815
+ command.refresh_from_db()
816
+ self.assertEqual(command.status, "success")
817
+
818
+ with self.subTest("safe password left unquoted"):
819
+ _assert_quoted("N3w-p@ss.word", "N3w-p@ss.word")
820
+
821
+ with self.subTest("double quote breakout"):
822
+ _assert_quoted(
823
+ 'x"; touch /tmp/PWNED; echo "',
824
+ "'x\"; touch /tmp/PWNED; echo \"'",
825
+ )
826
+
827
+ with self.subTest("command substitution"):
828
+ _assert_quoted("$(touch /tmp/PWNED)", "'$(touch /tmp/PWNED)'")
829
+
830
+ with self.subTest("single quote breakout"):
831
+ _assert_quoted("x'; touch /tmp/PWNED", "'x'\"'\"'; touch /tmp/PWNED'")
832
+
833
+ with self.subTest("backslash kept literal"):
834
+ _assert_quoted("New\\pass123", "'New\\pass123'")
835
+
793
836
  @mock.patch(_connect_path)
794
837
  @mock.patch.dict(
795
838
  ORGANIZATION_ENABLED_COMMANDS, {"__all__": ("callable_ping", "path_ping")}
@@ -1,5 +1,4 @@
1
1
  from django.http import HttpResponse
2
- from django.shortcuts import get_object_or_404
3
2
  from rest_framework import serializers
4
3
  from rest_framework.generics import (
5
4
  GenericAPIView,
@@ -53,10 +52,10 @@ class CaRenewView(ProtectedAPIMixin, GenericAPIView):
53
52
 
54
53
  class CrlDownloadView(ProtectedAPIMixin, RetrieveAPIView):
55
54
  serializer_class = CaDetailSerializer
56
- queryset = Ca.objects.none()
55
+ queryset = Ca.objects.all()
57
56
 
58
57
  def retrieve(self, request, *args, **kwargs):
59
- instance = get_object_or_404(Ca, pk=kwargs["pk"])
58
+ instance = self.get_object()
60
59
  return HttpResponse(
61
60
  instance.crl, status=200, content_type="application/x-pem-file"
62
61
  )
@@ -149,6 +149,27 @@ class TestPkiApi(
149
149
  r = self.client.get(path)
150
150
  self.assertEqual(r.status_code, 200)
151
151
 
152
+ def test_crl_download_api_multitenancy(self):
153
+ org1 = self._create_org(name="org1")
154
+ org2 = self._create_org(name="org2")
155
+ ca1 = self._create_ca(name="ca1", organization=org1)
156
+ ca2 = self._create_ca(name="ca2", organization=org2)
157
+ shared_ca = self._create_ca(name="shared", organization=None)
158
+ operator = self._create_operator(organizations=[org1])
159
+ self.client.force_login(operator)
160
+
161
+ with self.subTest("CA of managed organization"):
162
+ r = self.client.get(reverse("pki_api:crl_download", args=[ca1.pk]))
163
+ self.assertEqual(r.status_code, 200)
164
+
165
+ with self.subTest("CA of other organization"):
166
+ r = self.client.get(reverse("pki_api:crl_download", args=[ca2.pk]))
167
+ self.assertEqual(r.status_code, 404)
168
+
169
+ with self.subTest("shared CA"):
170
+ r = self.client.get(reverse("pki_api:crl_download", args=[shared_ca.pk]))
171
+ self.assertEqual(r.status_code, 200)
172
+
152
173
  def test_ca_delete_api(self):
153
174
  ca1 = self._create_ca(name="ca1", organization=self._get_org())
154
175
  path = reverse("pki_api:ca_detail", args=[ca1.pk])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openwisp-controller
3
- Version: 1.3.1
3
+ Version: 1.3.2
4
4
  Summary: OpenWISP Controller
5
5
  Home-page: http://openwisp.org
6
6
  Download-URL: https://github.com/openwisp/openwisp-controller/releases