Upgrade models to full NetboxModel to allow UI/API interaction:
modified: netbox_dns_bridge/models.py deleted: netbox_dns_bridge/migrations/0003_catalogzone_and_per_zone_identifier.py new file: netbox_dns_bridge/migrations/0003_full_netbox_models.py Adjust model access and function calls to match new models: modified: netbox_dns_bridge/signals/netbox_dns_zones.py modified: netbox_dns_bridge/management/commands/dns_transfer_endpoint/catalog_zone_manager.py modified: netbox_dns_bridge/management/commands/dns_transfer_endpoint/request_handler.py Update UI elements and permission interactions: modified: netbox_dns_bridge/filtersets.py modified: netbox_dns_bridge/forms.py modified: netbox_dns_bridge/jobs/notify.py modified: netbox_dns_bridge/navigation.py modified: netbox_dns_bridge/tables.py deleted: netbox_dns_bridge/templates/netbox_dns_bridge/catalog_zone_members.html new file: netbox_dns_bridge/templates/netbox_dns_bridge/catalogzone.html new file: netbox_dns_bridge/templates/netbox_dns_bridge/catalogzonemember.html deleted: netbox_dns_bridge/templates/netbox_dns_bridge/notify_overview.html new file: netbox_dns_bridge/templates/netbox_dns_bridge/seentransferclient.html modified: netbox_dns_bridge/urls.py modified: netbox_dns_bridge/views.py AI/LLM updated tests (Not verified): modified: netbox_dns_bridge/tests/conftest.py modified: netbox_dns_bridge/tests/test_catalog_zone_manager.py modified: netbox_dns_bridge/tests/test_models.py modified: netbox_dns_bridge/tests/test_notify.py modified: netbox_dns_bridge/tests/test_request_handler_integration.py modified: netbox_dns_bridge/tests/test_signals.py modified: netbox_dns_bridge/tests/test_smoke.py modified: netbox_dns_bridge/tests/test_views.py
This commit is contained in:
1 parent
14805ed32b
commit
1c51206196
26 files changed
+813
-451
No files matched your search
@@ -182,7 +182,7 @@ def catz_serial(db):
|
||||
"""Initial SOA serial value (1) for freshly created catalog zones.
|
||||
|
||||
A ``CatalogZone`` is auto-created with ``soa_serial=1`` by the zone
|
||||
post_save signal (via ``update_member_identifier``) whenever a zone is
|
||||
post_save signal (via ``update_member``) whenever a zone is
|
||||
created. Tests compare against this initial value.
|
||||
"""
|
||||
return 1
|
||||
|
||||
@@ -9,7 +9,7 @@ from netbox_dns_bridge.management.commands.dns_transfer_endpoint import (
|
||||
)
|
||||
from netbox_dns_bridge.models import (
|
||||
CatalogZone,
|
||||
CatalogZoneMemberIdentifier,
|
||||
CatalogZoneMember,
|
||||
)
|
||||
|
||||
|
||||
@@ -72,50 +72,50 @@ class TestIncrementSoaSerial:
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestGenerateMemberIdentifier:
|
||||
class TestGenerateMemberName:
|
||||
def test_returns_26_char_string(self):
|
||||
name = catzm._generate_member_identifier()
|
||||
name = catzm._generate_member_name()
|
||||
assert len(name) == 26
|
||||
|
||||
def test_is_lowercase(self):
|
||||
name = catzm._generate_member_identifier()
|
||||
name = catzm._generate_member_name()
|
||||
assert name == name.lower()
|
||||
|
||||
def test_is_base32(self):
|
||||
import string
|
||||
|
||||
name = catzm._generate_member_identifier()
|
||||
name = catzm._generate_member_name()
|
||||
valid_chars = set(string.ascii_lowercase + "234567")
|
||||
assert set(name).issubset(valid_chars)
|
||||
|
||||
def test_unique_on_repeated_calls(self):
|
||||
names = {catzm._generate_member_identifier() for _ in range(100)}
|
||||
names = {catzm._generate_member_name() for _ in range(100)}
|
||||
assert len(names) == 100
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestUpdateMemberIdentifier:
|
||||
class TestUpdateMember:
|
||||
def test_creates_identifier_for_new_zone(self, make_zone):
|
||||
zone = make_zone(name="ident-new.test")
|
||||
# Signal already creates one; delete it to test creation
|
||||
CatalogZoneMemberIdentifier.objects.filter(zone=zone).delete()
|
||||
assert not CatalogZoneMemberIdentifier.objects.filter(zone=zone).exists()
|
||||
catzm.update_member_identifier(zone)
|
||||
assert CatalogZoneMemberIdentifier.objects.filter(zone=zone).exists()
|
||||
CatalogZoneMember.objects.filter(zone=zone).delete()
|
||||
assert not CatalogZoneMember.objects.filter(zone=zone).exists()
|
||||
catzm.update_member(zone)
|
||||
assert CatalogZoneMember.objects.filter(zone=zone).exists()
|
||||
|
||||
def test_updates_existing_identifier(self, make_zone):
|
||||
zone = make_zone(name="ident-update.test")
|
||||
catzm.update_member_identifier(zone)
|
||||
old = CatalogZoneMemberIdentifier.objects.get(zone=zone)
|
||||
catzm.update_member_identifier(zone)
|
||||
new = CatalogZoneMemberIdentifier.objects.get(zone=zone)
|
||||
catzm.update_member(zone)
|
||||
old = CatalogZoneMember.objects.get(zone=zone)
|
||||
catzm.update_member(zone)
|
||||
new = CatalogZoneMember.objects.get(zone=zone)
|
||||
assert old.name != new.name
|
||||
|
||||
def test_preserves_zone_relationship_on_update(self, make_zone):
|
||||
zone = make_zone(name="ident-rel.test")
|
||||
catzm.update_member_identifier(zone)
|
||||
catzm.update_member_identifier(zone)
|
||||
assert CatalogZoneMemberIdentifier.objects.filter(zone=zone).count() == 1
|
||||
catzm.update_member(zone)
|
||||
catzm.update_member(zone)
|
||||
assert CatalogZoneMember.objects.filter(zone=zone).count() == 1
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -195,11 +195,11 @@ class TestCreateZone:
|
||||
view = make_view(name="cz-ident-view")
|
||||
zone_obj = make_zone(name="no-ident.test", view=view)
|
||||
# Remove the auto-created identifier to test on-the-fly creation
|
||||
CatalogZoneMemberIdentifier.objects.filter(zone=zone_obj).delete()
|
||||
assert not CatalogZoneMemberIdentifier.objects.filter(zone=zone_obj).exists()
|
||||
CatalogZoneMember.objects.filter(zone=zone_obj).delete()
|
||||
assert not CatalogZoneMember.objects.filter(zone=zone_obj).exists()
|
||||
zone = catzm.create_zone("catz", "cz-ident-view")
|
||||
assert zone is not None
|
||||
assert CatalogZoneMemberIdentifier.objects.filter(zone=zone_obj).exists()
|
||||
assert CatalogZoneMember.objects.filter(zone=zone_obj).exists()
|
||||
|
||||
def test_rdclass_is_in(self, make_zone, make_view):
|
||||
view = make_view(name="cz-class-view")
|
||||
|
||||
@@ -3,8 +3,8 @@ import pytest
|
||||
|
||||
from netbox_dns_bridge.models import (
|
||||
CatalogZone,
|
||||
CatalogZoneMemberIdentifier,
|
||||
SeenTransferClients,
|
||||
CatalogZoneMember,
|
||||
SeenTransferClient,
|
||||
)
|
||||
|
||||
|
||||
@@ -42,6 +42,15 @@ class TestCatalogZone:
|
||||
assert cz.soa_expire == 86400
|
||||
assert cz.soa_minimum == 3600
|
||||
|
||||
def test_is_full_netbox_model(self, make_view):
|
||||
view = make_view(name="cz-netbox-model-view")
|
||||
cz = CatalogZone.objects.create(view=view)
|
||||
assert cz.created is not None
|
||||
assert cz.last_updated is not None
|
||||
assert cz.custom_field_data == {}
|
||||
assert hasattr(cz, "tags")
|
||||
assert cz.get_absolute_url() == f"/plugins/dns-bridge/catalog-zones/{cz.pk}/"
|
||||
|
||||
def test_one_to_one_relationship(self, make_view):
|
||||
view = make_view(name="cz-oto-view")
|
||||
cz = CatalogZone.objects.create(view=view, soa_serial=7)
|
||||
@@ -67,10 +76,10 @@ class TestCatalogZone:
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestCatalogZoneMemberIdentifier:
|
||||
class TestCatalogZoneMember:
|
||||
def test_str_representation(self, make_zone):
|
||||
zone = make_zone(name="str.test")
|
||||
m = CatalogZoneMemberIdentifier.objects.get(zone=zone)
|
||||
m = CatalogZoneMember.objects.get(zone=zone)
|
||||
assert str(m) == m.name
|
||||
|
||||
def test_unique_name_per_catalog_zone(self, make_zone, make_view):
|
||||
@@ -78,11 +87,11 @@ class TestCatalogZoneMemberIdentifier:
|
||||
zone1 = make_zone(name="uniq1.test", view=view)
|
||||
zone2 = make_zone(name="uniq2.test", view=view)
|
||||
|
||||
ident1 = CatalogZoneMemberIdentifier.objects.get(zone=zone1)
|
||||
ident1 = CatalogZoneMember.objects.get(zone=zone1)
|
||||
ident1.name = "shared-name"
|
||||
ident1.save()
|
||||
|
||||
ident2 = CatalogZoneMemberIdentifier.objects.get(zone=zone2)
|
||||
ident2 = CatalogZoneMember.objects.get(zone=zone2)
|
||||
from django.db import IntegrityError
|
||||
|
||||
with pytest.raises(IntegrityError):
|
||||
@@ -95,36 +104,36 @@ class TestCatalogZoneMemberIdentifier:
|
||||
zone1 = make_zone(name="diff1.test", view=view1)
|
||||
zone2 = make_zone(name="diff2.test", view=view2)
|
||||
|
||||
ident1 = CatalogZoneMemberIdentifier.objects.get(zone=zone1)
|
||||
ident1 = CatalogZoneMember.objects.get(zone=zone1)
|
||||
ident1.name = "shared-name"
|
||||
ident1.save()
|
||||
|
||||
ident2 = CatalogZoneMemberIdentifier.objects.get(zone=zone2)
|
||||
ident2 = CatalogZoneMember.objects.get(zone=zone2)
|
||||
ident2.name = "shared-name"
|
||||
ident2.save()
|
||||
|
||||
def test_cascade_delete_when_zone_deleted(self, make_zone):
|
||||
zone = make_zone(name="cascade.test")
|
||||
m = CatalogZoneMemberIdentifier.objects.get(zone=zone)
|
||||
assert CatalogZoneMemberIdentifier.objects.filter(pk=m.pk).exists()
|
||||
m = CatalogZoneMember.objects.get(zone=zone)
|
||||
assert CatalogZoneMember.objects.filter(pk=m.pk).exists()
|
||||
zone.delete()
|
||||
assert not CatalogZoneMemberIdentifier.objects.filter(pk=m.pk).exists()
|
||||
assert not CatalogZoneMember.objects.filter(pk=m.pk).exists()
|
||||
|
||||
def test_one_to_one_relationship(self, make_zone):
|
||||
zone = make_zone(name="oto.test")
|
||||
m = CatalogZoneMemberIdentifier.objects.get(zone=zone)
|
||||
assert zone.catz_identifier == m
|
||||
m = CatalogZoneMember.objects.get(zone=zone)
|
||||
assert zone.catalog_zone_member == m
|
||||
|
||||
def test_ordering_by_name(self, make_zone, make_view):
|
||||
view = make_view(name="ord-view")
|
||||
z1 = make_zone(name="z1.test", view=view)
|
||||
z2 = make_zone(name="z2.test", view=view)
|
||||
z3 = make_zone(name="z3.test", view=view)
|
||||
CatalogZoneMemberIdentifier.objects.filter(zone=z3).update(name="gamma")
|
||||
CatalogZoneMemberIdentifier.objects.filter(zone=z1).update(name="alpha")
|
||||
CatalogZoneMemberIdentifier.objects.filter(zone=z2).update(name="beta")
|
||||
CatalogZoneMember.objects.filter(zone=z3).update(name="gamma")
|
||||
CatalogZoneMember.objects.filter(zone=z1).update(name="alpha")
|
||||
CatalogZoneMember.objects.filter(zone=z2).update(name="beta")
|
||||
names = list(
|
||||
CatalogZoneMemberIdentifier.objects.filter(
|
||||
CatalogZoneMember.objects.filter(
|
||||
zone__in=[z1, z2, z3]
|
||||
).values_list("name", flat=True)
|
||||
)
|
||||
@@ -132,10 +141,10 @@ class TestCatalogZoneMemberIdentifier:
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestSeenTransferClients:
|
||||
class TestSeenTransferClient:
|
||||
def test_str_representation(self, make_view):
|
||||
view = make_view(name="str-view")
|
||||
client = SeenTransferClients.objects.create(
|
||||
client = SeenTransferClient.objects.create(
|
||||
source_ip="192.0.2.1",
|
||||
view=view,
|
||||
last_seen="2026-01-01T00:00:00Z",
|
||||
@@ -146,13 +155,13 @@ class TestSeenTransferClients:
|
||||
from django.db import IntegrityError
|
||||
|
||||
view = make_view(name="uniq-view")
|
||||
SeenTransferClients.objects.create(
|
||||
SeenTransferClient.objects.create(
|
||||
source_ip="10.0.0.1",
|
||||
view=view,
|
||||
last_seen="2026-01-01T00:00:00Z",
|
||||
)
|
||||
with pytest.raises(IntegrityError):
|
||||
SeenTransferClients.objects.create(
|
||||
SeenTransferClient.objects.create(
|
||||
source_ip="10.0.0.1",
|
||||
view=view,
|
||||
last_seen="2026-01-02T00:00:00Z",
|
||||
@@ -161,19 +170,19 @@ class TestSeenTransferClients:
|
||||
def test_same_ip_different_views_allowed(self, make_view):
|
||||
v1 = make_view(name="v1")
|
||||
v2 = make_view(name="v2")
|
||||
SeenTransferClients.objects.create(
|
||||
SeenTransferClient.objects.create(
|
||||
source_ip="10.0.0.5", view=v1, last_seen="2026-01-01T00:00:00Z"
|
||||
)
|
||||
SeenTransferClients.objects.create(
|
||||
SeenTransferClient.objects.create(
|
||||
source_ip="10.0.0.5", view=v2, last_seen="2026-01-01T00:00:00Z"
|
||||
)
|
||||
assert SeenTransferClients.objects.filter(source_ip="10.0.0.5").count() == 2
|
||||
assert SeenTransferClient.objects.filter(source_ip="10.0.0.5").count() == 2
|
||||
|
||||
def test_protect_on_view_delete(self, make_view):
|
||||
from django.db.models import ProtectedError
|
||||
|
||||
view = make_view(name="protected-view")
|
||||
SeenTransferClients.objects.create(
|
||||
SeenTransferClient.objects.create(
|
||||
source_ip="10.0.0.9",
|
||||
view=view,
|
||||
last_seen="2026-01-01T00:00:00Z",
|
||||
@@ -187,6 +196,19 @@ class TestSeenTransferClients:
|
||||
v = make_view(name="ord-view")
|
||||
now = timezone.now()
|
||||
for ip in ["10.0.0.3", "10.0.0.1", "10.0.0.2"]:
|
||||
SeenTransferClients.objects.create(source_ip=ip, view=v, last_seen=now)
|
||||
ips = list(SeenTransferClients.objects.values_list("source_ip", flat=True))
|
||||
SeenTransferClient.objects.create(source_ip=ip, view=v, last_seen=now)
|
||||
ips = list(SeenTransferClient.objects.values_list("source_ip", flat=True))
|
||||
assert ips == ["10.0.0.1", "10.0.0.2", "10.0.0.3"]
|
||||
|
||||
def test_is_full_netbox_model(self, make_view):
|
||||
from django.utils import timezone
|
||||
|
||||
view = make_view(name="stc-netbox-model-view")
|
||||
c = SeenTransferClient.objects.create(
|
||||
source_ip="192.0.2.1", view=view, last_seen=timezone.now()
|
||||
)
|
||||
assert c.created is not None
|
||||
assert c.last_updated is not None
|
||||
assert c.custom_field_data == {}
|
||||
assert hasattr(c, "tags")
|
||||
assert c.get_absolute_url() == f"/plugins/dns-bridge/seen-transfer-clients/{c.pk}/"
|
||||
@@ -269,11 +269,11 @@ class TestScheduleCatalogZoneNotify:
|
||||
class TestSendClientNotifyRun:
|
||||
def test_sends_single_notify_to_seen_clients(self, make_zone, make_view, monkeypatch):
|
||||
import netbox_dns_bridge.jobs.notify as nh
|
||||
from netbox_dns_bridge.models import SeenTransferClients
|
||||
from netbox_dns_bridge.models import SeenTransferClient
|
||||
from django.utils import timezone
|
||||
|
||||
view = make_view(name="notify-run-view")
|
||||
SeenTransferClients.objects.create(
|
||||
SeenTransferClient.objects.create(
|
||||
source_ip="192.0.2.99", view=view, last_seen=timezone.now()
|
||||
)
|
||||
|
||||
@@ -297,11 +297,11 @@ class TestSendClientNotifyRun:
|
||||
assert mock_udp.call_count == 1
|
||||
|
||||
def test_sends_notify_without_catalog_zone(self, monkeypatch, make_view):
|
||||
from netbox_dns_bridge.models import SeenTransferClients
|
||||
from netbox_dns_bridge.models import SeenTransferClient
|
||||
from django.utils import timezone
|
||||
|
||||
view = make_view(name="no-catz-view")
|
||||
SeenTransferClients.objects.create(
|
||||
SeenTransferClient.objects.create(
|
||||
source_ip="192.0.2.1", view=view, last_seen=timezone.now()
|
||||
)
|
||||
|
||||
|
||||
@@ -148,14 +148,14 @@ class TestCatzIntegration:
|
||||
|
||||
class TestSeenClientTracking:
|
||||
def _wait_for_seen_client(self, view, timeout=3.0):
|
||||
"""Poll for SeenTransferClients record (race: response is sent before
|
||||
"""Poll for SeenTransferClient record (race: response is sent before
|
||||
_track_seen_client completes in the handler thread)."""
|
||||
import time
|
||||
from netbox_dns_bridge.models import SeenTransferClients
|
||||
from netbox_dns_bridge.models import SeenTransferClient
|
||||
|
||||
deadline = time.monotonic() + timeout
|
||||
while time.monotonic() < deadline:
|
||||
if SeenTransferClients.objects.filter(
|
||||
if SeenTransferClient.objects.filter(
|
||||
source_ip="127.0.0.1", view=view
|
||||
).exists():
|
||||
return True
|
||||
@@ -186,5 +186,5 @@ class TestSeenClientTracking:
|
||||
|
||||
import time
|
||||
time.sleep(0.3)
|
||||
from netbox_dns_bridge.models import SeenTransferClients
|
||||
assert not SeenTransferClients.objects.filter(view=view).exists()
|
||||
from netbox_dns_bridge.models import SeenTransferClient
|
||||
assert not SeenTransferClient.objects.filter(view=view).exists()
|
||||
@@ -13,7 +13,7 @@ captureOnCommitCallbacks = _DjangoTestCase.captureOnCommitCallbacks
|
||||
|
||||
from netbox_dns_bridge.models import (
|
||||
CatalogZone,
|
||||
CatalogZoneMemberIdentifier,
|
||||
CatalogZoneMember,
|
||||
)
|
||||
|
||||
|
||||
@@ -35,9 +35,9 @@ class TestZonePreSave:
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestZonePostSaveCreate:
|
||||
def test_creates_catz_member_identifier_on_new_zone(self, make_zone):
|
||||
def test_creates_catalog_zone_member_on_new_zone(self, make_zone):
|
||||
zone = make_zone(name="postcreate.test")
|
||||
assert CatalogZoneMemberIdentifier.objects.filter(zone=zone).exists()
|
||||
assert CatalogZoneMember.objects.filter(zone=zone).exists()
|
||||
|
||||
def test_increments_soa_serial_on_commit(self, make_zone, catz_serial):
|
||||
with captureOnCommitCallbacks(execute=True):
|
||||
@@ -103,19 +103,19 @@ class TestZonePostSaveCreate:
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestZonePostSaveUpdate:
|
||||
def test_updates_catz_identifier_on_name_change(self, make_zone):
|
||||
def test_updates_member_on_name_change(self, make_zone):
|
||||
zone = make_zone(name="rename-old.test")
|
||||
old_name = CatalogZoneMemberIdentifier.objects.get(zone=zone).name
|
||||
old_name = CatalogZoneMember.objects.get(zone=zone).name
|
||||
|
||||
zone.name = "rename-new.test"
|
||||
zone.save()
|
||||
|
||||
new_name = CatalogZoneMemberIdentifier.objects.get(zone=zone).name
|
||||
new_name = CatalogZoneMember.objects.get(zone=zone).name
|
||||
assert old_name != new_name
|
||||
|
||||
def test_no_identifier_update_when_name_unchanged(self, make_zone):
|
||||
zone = make_zone(name="nochange.test")
|
||||
ident = CatalogZoneMemberIdentifier.objects.get(zone=zone)
|
||||
ident = CatalogZoneMember.objects.get(zone=zone)
|
||||
original_name = ident.name
|
||||
|
||||
zone.soa_serial = zone.soa_serial + 1
|
||||
@@ -177,7 +177,7 @@ class TestZoneViewChange:
|
||||
view_b = make_view(name="fk-view-b")
|
||||
zone = make_zone(name="fk-move.test", view=view_a)
|
||||
|
||||
ident = CatalogZoneMemberIdentifier.objects.get(zone=zone)
|
||||
ident = CatalogZoneMember.objects.get(zone=zone)
|
||||
assert ident.catalog_zone == CatalogZone.objects.get(view=view_a)
|
||||
|
||||
zone.view = view_b
|
||||
|
||||
@@ -14,12 +14,12 @@ def test_plugin_importable():
|
||||
def test_models_importable():
|
||||
from netbox_dns_bridge.models import (
|
||||
CatalogZone,
|
||||
CatalogZoneMemberIdentifier,
|
||||
SeenTransferClients,
|
||||
CatalogZoneMember,
|
||||
SeenTransferClient,
|
||||
)
|
||||
assert CatalogZone._meta.model_name
|
||||
assert CatalogZoneMemberIdentifier._meta.model_name
|
||||
assert SeenTransferClients._meta.model_name
|
||||
assert CatalogZoneMember._meta.model_name
|
||||
assert SeenTransferClient._meta.model_name
|
||||
|
||||
|
||||
def test_request_handler_importable():
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""Tests for views: CatalogZoneMembersView, CatalogZoneListView, CatalogZoneEditView, NotifyOverviewView — auth gate and context."""
|
||||
"""Tests for views: CatalogZone list/detail/edit, CatalogZoneMember list/detail, SeenTransferClient list/detail — auth gate and context."""
|
||||
import pytest
|
||||
from django.test import Client
|
||||
from django.contrib.auth import get_user_model
|
||||
@@ -28,7 +28,7 @@ def regular_user(db):
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestCatalogZoneMembersView:
|
||||
class TestCatalogZoneMemberListView:
|
||||
def test_unauthenticated_redirects_to_login(self, client):
|
||||
resp = client.get("/plugins/dns-bridge/catalog-zone-members/")
|
||||
assert resp.status_code in (302, 403)
|
||||
@@ -38,11 +38,48 @@ class TestCatalogZoneMembersView:
|
||||
resp = client.get("/plugins/dns-bridge/catalog-zone-members/")
|
||||
assert resp.status_code in (302, 403)
|
||||
|
||||
def test_superuser_can_access(self, client, superuser):
|
||||
def test_superuser_can_access(self, client, superuser, make_zone):
|
||||
make_zone(name="member-list.test")
|
||||
client.login(username="admin", password="testpass")
|
||||
resp = client.get("/plugins/dns-bridge/catalog-zone-members/")
|
||||
assert resp.status_code == 200
|
||||
|
||||
def test_list_contains_members(self, client, superuser, make_zone):
|
||||
zone = make_zone(name="member-row.test")
|
||||
client.login(username="admin", password="testpass")
|
||||
resp = client.get("/plugins/dns-bridge/catalog-zone-members/")
|
||||
member_list = list(resp.context["table"].data)
|
||||
assert len(member_list) >= 1
|
||||
m = next(m for m in member_list if m.zone_id == zone.id)
|
||||
assert m.name
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestCatalogZoneMemberDetailView:
|
||||
def test_unauthenticated_redirects_to_login(self, client, make_zone):
|
||||
zone = make_zone(name="member-detail.test")
|
||||
from netbox_dns_bridge.models import CatalogZoneMember
|
||||
m = CatalogZoneMember.objects.get(zone=zone)
|
||||
resp = client.get(f"/plugins/dns-bridge/catalog-zone-members/{m.pk}/")
|
||||
assert resp.status_code in (302, 403)
|
||||
|
||||
def test_regular_user_forbidden(self, client, regular_user, make_zone):
|
||||
zone = make_zone(name="member-detail-forbidden.test")
|
||||
from netbox_dns_bridge.models import CatalogZoneMember
|
||||
m = CatalogZoneMember.objects.get(zone=zone)
|
||||
client.login(username="regular", password="testpass")
|
||||
resp = client.get(f"/plugins/dns-bridge/catalog-zone-members/{m.pk}/")
|
||||
assert resp.status_code in (302, 403)
|
||||
|
||||
def test_superuser_can_access_detail(self, client, superuser, make_zone):
|
||||
zone = make_zone(name="member-detail-get.test")
|
||||
from netbox_dns_bridge.models import CatalogZoneMember
|
||||
m = CatalogZoneMember.objects.get(zone=zone)
|
||||
client.login(username="admin", password="testpass")
|
||||
resp = client.get(f"/plugins/dns-bridge/catalog-zone-members/{m.pk}/")
|
||||
assert resp.status_code == 200
|
||||
assert resp.context["object"].name == m.name
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestCatalogZoneListView:
|
||||
@@ -138,45 +175,104 @@ class TestCatalogZoneEditView:
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestNotifyOverviewView:
|
||||
class TestCatalogZoneDetailView:
|
||||
def test_unauthenticated_redirects_to_login(self, client, make_view):
|
||||
view = make_view(name="detail-cz-view")
|
||||
from netbox_dns_bridge.models import CatalogZone
|
||||
cz = CatalogZone.objects.create(view=view)
|
||||
resp = client.get(f"/plugins/dns-bridge/catalog-zones/{cz.pk}/")
|
||||
assert resp.status_code in (302, 403)
|
||||
|
||||
def test_regular_user_forbidden(self, client, regular_user, make_view):
|
||||
view = make_view(name="detail-cz-view-forbidden")
|
||||
from netbox_dns_bridge.models import CatalogZone
|
||||
cz = CatalogZone.objects.create(view=view)
|
||||
client.login(username="regular", password="testpass")
|
||||
resp = client.get(f"/plugins/dns-bridge/catalog-zones/{cz.pk}/")
|
||||
assert resp.status_code in (302, 403)
|
||||
|
||||
def test_superuser_can_access_detail(self, client, superuser, make_view):
|
||||
view = make_view(name="detail-cz-view-get")
|
||||
from netbox_dns_bridge.models import CatalogZone
|
||||
cz = CatalogZone.objects.create(view=view, soa_serial=42)
|
||||
client.login(username="admin", password="testpass")
|
||||
resp = client.get(f"/plugins/dns-bridge/catalog-zones/{cz.pk}/")
|
||||
assert resp.status_code == 200
|
||||
assert resp.context["object"].soa_serial == 42
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestSeenTransferClientListView:
|
||||
def test_unauthenticated_redirects_to_login(self, client):
|
||||
resp = client.get("/plugins/dns-bridge/notify/")
|
||||
resp = client.get("/plugins/dns-bridge/seen-transfer-clients/")
|
||||
assert resp.status_code in (302, 403)
|
||||
|
||||
def test_regular_user_forbidden(self, client, regular_user):
|
||||
client.login(username="regular", password="testpass")
|
||||
resp = client.get("/plugins/dns-bridge/notify/")
|
||||
resp = client.get("/plugins/dns-bridge/seen-transfer-clients/")
|
||||
assert resp.status_code in (302, 403)
|
||||
|
||||
def test_superuser_can_access(self, client, superuser):
|
||||
client.login(username="admin", password="testpass")
|
||||
resp = client.get("/plugins/dns-bridge/notify/")
|
||||
assert resp.status_code == 200
|
||||
|
||||
def test_context_contains_seen_clients(self, client, superuser, make_view):
|
||||
from netbox_dns_bridge.models import SeenTransferClients
|
||||
def test_superuser_can_access(self, client, superuser, make_view):
|
||||
from netbox_dns_bridge.models import SeenTransferClient
|
||||
from django.utils import timezone
|
||||
|
||||
view = make_view(name="notify-view")
|
||||
SeenTransferClients.objects.create(
|
||||
view = make_view(name="stc-list-view")
|
||||
SeenTransferClient.objects.create(
|
||||
source_ip="192.0.2.1", view=view, last_seen=timezone.now()
|
||||
)
|
||||
client.login(username="admin", password="testpass")
|
||||
resp = client.get("/plugins/dns-bridge/notify/")
|
||||
assert "seen_clients" in resp.context
|
||||
clients = list(resp.context["seen_clients"])
|
||||
assert len(clients) == 1
|
||||
assert clients[0].source_ip == "192.0.2.1"
|
||||
resp = client.get("/plugins/dns-bridge/seen-transfer-clients/")
|
||||
assert resp.status_code == 200
|
||||
|
||||
def test_seen_clients_ordered_by_ip(self, client, superuser, make_view):
|
||||
from netbox_dns_bridge.models import SeenTransferClients
|
||||
def test_list_contains_clients(self, client, superuser, make_view):
|
||||
from netbox_dns_bridge.models import SeenTransferClient
|
||||
from django.utils import timezone
|
||||
|
||||
view = make_view(name="ord-notify-view")
|
||||
now = timezone.now()
|
||||
for ip in ["10.0.0.3", "10.0.0.1", "10.0.0.2"]:
|
||||
SeenTransferClients.objects.create(source_ip=ip, view=view, last_seen=now)
|
||||
view = make_view(name="stc-list-row-view")
|
||||
SeenTransferClient.objects.create(
|
||||
source_ip="192.0.2.1", view=view, last_seen=timezone.now()
|
||||
)
|
||||
client.login(username="admin", password="testpass")
|
||||
resp = client.get("/plugins/dns-bridge/notify/")
|
||||
ips = [c.source_ip for c in resp.context["seen_clients"]]
|
||||
assert ips == ["10.0.0.1", "10.0.0.2", "10.0.0.3"]
|
||||
resp = client.get("/plugins/dns-bridge/seen-transfer-clients/")
|
||||
client_list = list(resp.context["table"].data)
|
||||
assert len(client_list) >= 1
|
||||
assert client_list[0].source_ip == "192.0.2.1"
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestSeenTransferClientDetailView:
|
||||
def test_unauthenticated_redirects_to_login(self, client, make_view):
|
||||
from netbox_dns_bridge.models import SeenTransferClient
|
||||
from django.utils import timezone
|
||||
|
||||
view = make_view(name="stc-detail-view")
|
||||
c = SeenTransferClient.objects.create(
|
||||
source_ip="192.0.2.1", view=view, last_seen=timezone.now()
|
||||
)
|
||||
resp = client.get(f"/plugins/dns-bridge/seen-transfer-clients/{c.pk}/")
|
||||
assert resp.status_code in (302, 403)
|
||||
|
||||
def test_regular_user_forbidden(self, client, regular_user, make_view):
|
||||
from netbox_dns_bridge.models import SeenTransferClient
|
||||
from django.utils import timezone
|
||||
|
||||
view = make_view(name="stc-detail-forbidden-view")
|
||||
c = SeenTransferClient.objects.create(
|
||||
source_ip="192.0.2.1", view=view, last_seen=timezone.now()
|
||||
)
|
||||
client.login(username="regular", password="testpass")
|
||||
resp = client.get(f"/plugins/dns-bridge/seen-transfer-clients/{c.pk}/")
|
||||
assert resp.status_code in (302, 403)
|
||||
|
||||
def test_superuser_can_access_detail(self, client, superuser, make_view):
|
||||
from netbox_dns_bridge.models import SeenTransferClient
|
||||
from django.utils import timezone
|
||||
|
||||
view = make_view(name="stc-detail-get-view")
|
||||
c = SeenTransferClient.objects.create(
|
||||
source_ip="192.0.2.42", view=view, last_seen=timezone.now()
|
||||
)
|
||||
client.login(username="admin", password="testpass")
|
||||
resp = client.get(f"/plugins/dns-bridge/seen-transfer-clients/{c.pk}/")
|
||||
assert resp.status_code == 200
|
||||
assert resp.context["object"].source_ip == "192.0.2.42"
|
||||
Reference in new issue
Block a user