From 5fe6f3cf713d1fccc987e82faa1eac243cd788a9 Mon Sep 17 00:00:00 2001
From: Benjamin Bertrand <benjamin.bertrand@esss.se>
Date: Mon, 13 Nov 2017 15:35:01 +0100
Subject: [PATCH] Catch ValueError when submitting invalid IP in API

TODO: we should maybe raise ValidationError in models
and catch that to raise CSEntryError in the API
---
 app/api/main.py              |  2 ++
 tests/functional/test_api.py | 38 +++++++++++++++++++++++++++++++++++-
 2 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/app/api/main.py b/app/api/main.py
index f778224..aaae913 100644
--- a/app/api/main.py
+++ b/app/api/main.py
@@ -61,6 +61,8 @@ def create_generic_model(model, mandatory_fields=('name',)):
     except TypeError as e:
         message = str(e).replace('__init__() got an ', '')
         raise utils.CSEntryError(message)
+    except ValueError as e:
+        raise utils.CSEntryError(str(e), status_code=422)
     db.session.add(instance)
     try:
         db.session.commit()
diff --git a/tests/functional/test_api.py b/tests/functional/test_api.py
index c17c6b9..59b4d1a 100644
--- a/tests/functional/test_api.py
+++ b/tests/functional/test_api.py
@@ -510,7 +510,43 @@ def test_create_network(client, session, admin_token):
     assert models.Network.query.count() == 2
 
 
-def test_create_network_constraint_fail(client, session, admin_token):
+def test_create_network_invalid_prefix(client, session, admin_token):
+    # invalid network address
+    data = {'prefix': 'foo',
+            'first': '172.16.1.10',
+            'last': '172.16.1.250'}
+    response = post(client, '/api/networks', data=data, token=admin_token)
+    check_response_message(response, "'foo' does not appear to be an IPv4 or IPv6 network", 422)
+    data = {'prefix': '172.16.1',
+            'first': '172.16.1.10',
+            'last': '172.16.1.250'}
+    response = post(client, '/api/networks', data=data, token=admin_token)
+    check_response_message(response, "'172.16.1' does not appear to be an IPv4 or IPv6 network", 422)
+    # prefix address has host bits set
+    data = {'prefix': '172.16.1.1/24',
+            'first': '172.16.1.10',
+            'last': '172.16.1.250'}
+    response = post(client, '/api/networks', data=data, token=admin_token)
+    check_response_message(response, '172.16.1.1/24 has host bits set', 422)
+
+
+@pytest.mark.parametrize('address', ('', 'foo', '192.168'))
+def test_create_network_invalid_ip(address, client, session, admin_token):
+    # invalid first IP address
+    data = {'prefix': '192.168.0.0/24',
+            'first': address,
+            'last': '192.168.0.250'}
+    response = post(client, '/api/networks', data=data, token=admin_token)
+    check_response_message(response, f"'{address}' does not appear to be an IPv4 or IPv6 address", 422)
+    # invalid last IP address
+    data = {'prefix': '192.168.0.0/24',
+            'first': '192.168.0.250',
+            'last': address}
+    response = post(client, '/api/networks', data=data, token=admin_token)
+    check_response_message(response, f"'{address}' does not appear to be an IPv4 or IPv6 address", 422)
+
+
+def test_create_network_invalid_range(client, session, admin_token):
     # first not in prefix
     data = {'prefix': '172.16.1.0/24',
             'first': '172.16.2.10',
-- 
GitLab