diff --git a/scram/route_manager/tests/acceptance/environment.py b/scram/route_manager/tests/acceptance/environment.py index 0d31198b..baf6776e 100644 --- a/scram/route_manager/tests/acceptance/environment.py +++ b/scram/route_manager/tests/acceptance/environment.py @@ -1,5 +1,6 @@ """Setup the environment for tests.""" +from django.test import Client from rest_framework.test import APIClient from scram.users.tests.factories import UserFactory @@ -12,3 +13,4 @@ def django_ready(context): # Default to using the API client. context.test.client = APIClient() + context.test.web_client = Client() diff --git a/scram/route_manager/tests/acceptance/features/query.feature b/scram/route_manager/tests/acceptance/features/query.feature index 534399fb..d631bd3e 100644 --- a/scram/route_manager/tests/acceptance/features/query.feature +++ b/scram/route_manager/tests/acceptance/features/query.feature @@ -37,7 +37,8 @@ Feature: we can query the list of entries for a specific entry | 2001:DB8:950C::/48 | 2001:DB8:950C::1/128 | | 2001:DB8:950D::/48 | 2001:DB8:950D::1/64 | - Scenario Outline: we cant query larger than our prefixmin + # This is to make sure the code path for deactivating an entry works correctly + Scenario Outline: we cant query larger than our prefix min Given a client with block authorization When we're logged in And the CIDR prefix limits are 24 and 48 @@ -46,20 +47,18 @@ Feature: we can query the list of entries for a specific entry And we query for Then we get a 400 status code - Examples: IPs | ip | | 192.0.2.0/24 | | 2001:DB8::/48 | - Scenario Outline: we cant enter malformed IPs + Scenario Outline: we get the proper error when querying an invalid cidr Given a client with block authorization When we're logged in And we add the entry And we query for Then we get a ValueError - Examples: IPs | ip | | 1.2.3.256 | diff --git a/scram/route_manager/tests/acceptance/features/search.feature b/scram/route_manager/tests/acceptance/features/search.feature new file mode 100644 index 00000000..c02d5a01 --- /dev/null +++ b/scram/route_manager/tests/acceptance/features/search.feature @@ -0,0 +1,25 @@ +Feature: Test our search bar + We need to make sure search works as expected + + Scenario Outline: Searching for a valid CIDR works + Given a client with block authorization + When we're logged in + And we add the entry + And we search for + Then we get a 200 status code + + Examples: IPs + | ip | + | 192.0.2.168 | + | 2001:DB8:9508::1 | + + Scenario Outline: Searching for an invalid CIDR returns a Bad Request error + Given a client with block authorization + When we're logged in + And we search for + Then we get a 400 status code + + Examples: IPs + | ip | + | " " | + | asdf | diff --git a/scram/route_manager/tests/acceptance/steps/common.py b/scram/route_manager/tests/acceptance/steps/common.py index f6c43fc7..cb803ba6 100644 --- a/scram/route_manager/tests/acceptance/steps/common.py +++ b/scram/route_manager/tests/acceptance/steps/common.py @@ -9,7 +9,12 @@ from django import conf from django.urls import reverse -from scram.route_manager.models import ActionType, Client, WebSocketMessage, WebSocketSequenceElement +from scram.route_manager.models import ( + ActionType, + Client, + WebSocketMessage, + WebSocketSequenceElement, +) @given("a {name} actiontype is defined") @@ -54,6 +59,7 @@ def create_unauthed_client(context, name): def login(context): """Login.""" context.test.client.login(username="user", password="password") + context.test.web_client.login(username="user", password="password") @when("the CIDR prefix limits are {v4_minprefix:d} and {v6_minprefix:d}") diff --git a/scram/route_manager/tests/acceptance/steps/ip.py b/scram/route_manager/tests/acceptance/steps/ip.py index 89247f6c..b8fda111 100644 --- a/scram/route_manager/tests/acceptance/steps/ip.py +++ b/scram/route_manager/tests/acceptance/steps/ip.py @@ -48,3 +48,12 @@ def check_comment(context, value, comment): except ValueError as e: context.response = None context.queryException = e + + +@when("we search for {ip}") +def search_ip(context, ip): + """Search our main search bar for an IP.""" + client = context.test.web_client + search_url = reverse("route_manager:search") + + context.response = client.post(search_url, data={"cidr": ip}) diff --git a/scram/route_manager/views.py b/scram/route_manager/views.py index 06d20a73..50abbd7f 100644 --- a/scram/route_manager/views.py +++ b/scram/route_manager/views.py @@ -15,7 +15,7 @@ from django.contrib.auth.mixins import PermissionRequiredMixin from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator from django.db import transaction -from django.http import HttpResponse +from django.http import HttpResponse, HttpResponseBadRequest from django.shortcuts import redirect, render from django.utils import timezone from django.views.decorators.http import require_POST @@ -73,10 +73,25 @@ def home_page(request, prefilter=None): def search_entries(request): """Wrap the home page with a specified CIDR to restrict Entries to.""" - # Using ipaddress because we needed to turn off strict mode - # (which netfields uses by default with seemingly no toggle) - # This caused searches with host bits set to 500 which is bad UX see: 68854ee1ad4789a62863083d521bddbc96ab7025 - addr = ipaddress.ip_network(request.POST.get("cidr"), strict=False) + if request.method != "POST": + return redirect("route_manager:home") + + try: + # Using ipaddress because we needed to turn off strict mode + # (which netfields uses by default with seemingly no toggle) + # This caused searches with host bits set to 500 which is bad UX see: 68854ee1ad4789a62863083d521bddbc96ab7025 + addr = ipaddress.ip_network(request.POST.get("cidr"), strict=False) + except ValueError: + try: + # leading space was breaking ipaddress module + str_addr = str(request.POST.get("cidr")).strip() + addr = ipaddress.ip_network(str_addr, strict=False) + except ValueError: + messages.add_message(request, messages.ERROR, "Search query was not a valid CIDR address") + + # Send a 400, but show the home page instead of an error page + return HttpResponseBadRequest(render(request, "route_manager/home.html")) + # We call home_page because search is just a more specific case of the same view and template to return. return home_page( request,