From 05937d539e76e1f5158e31448745ae08d96585d4 Mon Sep 17 00:00:00 2001
From: Benjamin Bertrand <benjamin.bertrand@esss.se>
Date: Mon, 13 Nov 2017 16:41:25 +0100
Subject: [PATCH] Catch DataError from database

Use full exception error as message (error messages from psycopg2 can
be quite long but that makes it much more explicit)
---
 app/api/main.py              | 20 ++++++++++----------
 tests/functional/test_api.py | 14 +++++++-------
 2 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/app/api/main.py b/app/api/main.py
index aaae913..398afd8 100644
--- a/app/api/main.py
+++ b/app/api/main.py
@@ -21,6 +21,14 @@ from ..decorators import jwt_groups_accepted
 bp = Blueprint('api', __name__)
 
 
+def commit():
+    try:
+        db.session.commit()
+    except (sa.exc.IntegrityError, sa.exc.DataError) as e:
+        db.session.rollback()
+        raise utils.CSEntryError(str(e), status_code=422)
+
+
 def get_item_by_id_or_ics_id(id_):
     """Retrieve item by id or ICS id"""
     try:
@@ -64,11 +72,7 @@ def create_generic_model(model, mandatory_fields=('name',)):
     except ValueError as e:
         raise utils.CSEntryError(str(e), status_code=422)
     db.session.add(instance)
-    try:
-        db.session.commit()
-    except sa.exc.IntegrityError as e:
-        db.session.rollback()
-        raise utils.CSEntryError('IntegrityError', status_code=409)
+    commit()
     return jsonify(instance.to_dict()), 201
 
 
@@ -173,11 +177,7 @@ def patch_item(id_):
     for child in item.children:
         child.location = item.location
         child.status = item.status
-    try:
-        db.session.commit()
-    except sa.exc.IntegrityError as e:
-        db.session.rollback()
-        raise utils.CSEntryError('IntegrityError', status_code=409)
+    commit()
     return jsonify(item.to_dict())
 
 
diff --git a/tests/functional/test_api.py b/tests/functional/test_api.py
index 59b4d1a..ce1b072 100644
--- a/tests/functional/test_api.py
+++ b/tests/functional/test_api.py
@@ -99,7 +99,7 @@ def check_response_message(response, msg, status_code=400):
         # flask-jwt-extended is using "msg" instead of "message"
         # in its default callbacks
         message = data['msg']
-    assert message == msg
+    assert message.startswith(msg)
 
 
 def check_names(response, names):
@@ -171,11 +171,11 @@ def test_create_generic_model(endpoint, client, user_token):
     assert {'id', 'name'} <= set(response.json.keys())
     assert response.json['name'] == 'Foo'
     response = post(client, f'/api/{endpoint}', data=data, token=user_token)
-    check_response_message(response, 'IntegrityError', 409)
+    check_response_message(response, '(psycopg2.IntegrityError) duplicate key value violates unique constraint', 422)
     response = post(client, f'/api/{endpoint}', data={'name': 'foo'}, token=user_token)
-    check_response_message(response, 'IntegrityError', 409)
+    check_response_message(response, '(psycopg2.IntegrityError) duplicate key value violates unique constraint', 422)
     response = post(client, f'/api/{endpoint}', data={'name': 'FOO'}, token=user_token)
-    check_response_message(response, 'IntegrityError', 409)
+    check_response_message(response, '(psycopg2.IntegrityError) duplicate key value violates unique constraint', 422)
     data = {'name': 'Bar'}
     response = post(client, f'/api/{endpoint}', data=data, token=user_token)
     assert response.status_code == 201
@@ -207,7 +207,7 @@ def test_create_item(client, user_token):
     response = post(client, '/api/items', data=data2, token=user_token)
     assert response.status_code == 201
     response = post(client, '/api/items', data=data2, token=user_token)
-    check_response_message(response, 'IntegrityError', 409)
+    check_response_message(response, '(psycopg2.IntegrityError) duplicate key value violates unique constraint', 422)
 
     # check all items that were created
     assert models.Item.query.count() == 3
@@ -323,7 +323,7 @@ def test_patch_item_integrity_error(client, session, user_token):
     session.commit()
     data = {'ics_id': 'AAA001'}
     response = patch(client, f'/api/items/{item2.id}', data=data, token=user_token)
-    check_response_message(response, 'IntegrityError', 409)
+    check_response_message(response, '(psycopg2.IntegrityError) duplicate key value violates unique constraint', 422)
 
 
 def test_patch_item_parent(client, session, user_token):
@@ -492,7 +492,7 @@ def test_create_network(client, session, admin_token):
 
     # Check that prefix shall be unique
     response = post(client, '/api/networks', data=data, token=admin_token)
-    check_response_message(response, 'IntegrityError', 409)
+    check_response_message(response, '(psycopg2.IntegrityError) duplicate key value violates unique constraint', 422)
 
     # Check that all parameters can be passed
     data2 = {'prefix': '172.16.5.0/24',
-- 
GitLab