New table to store the inbound api information for a service. The table is versioned.

There is a new endpoint to create the inbound api and one to update it.
This commit is contained in:
Rebecca Law
2017-06-15 11:32:51 +01:00
parent 3fdd180515
commit 828d5cd493
12 changed files with 384 additions and 70 deletions

View File

@@ -1,36 +0,0 @@
import uuid
import pytest
from sqlalchemy.exc import SQLAlchemyError
from app.dao.service_inbound_api_dao import save_service_inbound_api
from app.models import ServiceInboundApi
def test_save_service_inbound_api(sample_service):
service_inbound_api = ServiceInboundApi(
service_id=sample_service.id,
url="https::/some_service/inbound_messages",
bearer_token="some_unique_string"
)
save_service_inbound_api(service_inbound_api)
results = ServiceInboundApi.query.all()
assert len(results) == 1
assert results[0].id
assert results[0].service_id == sample_service.id
assert results[0].url == "https::/some_service/inbound_messages"
assert results[0].unsigned_bearer_token == "some_unique_string"
assert results[0].bearer_token != "some_unique_string"
def test_save_service_inbound_api_fails_if_service_doesnot_exist(notify_db, notify_db_session):
service_inbound_api = ServiceInboundApi(
service_id=uuid.uuid4(),
url="https::/some_service/inbound_messages",
bearer_token="some_unique_string"
)
with pytest.raises(SQLAlchemyError):
save_service_inbound_api(service_inbound_api)

View File

@@ -0,0 +1,116 @@
import uuid
import pytest
from sqlalchemy.exc import SQLAlchemyError
from app.authentication.utils import get_secret
from app.dao.service_inbound_api_dao import save_service_inbound_api, reset_service_inbound_api, \
get_service_inbound_api
from app.models import ServiceInboundApi
def test_save_service_inbound_api(sample_service):
service_inbound_api = ServiceInboundApi(
service_id=sample_service.id,
url="https::/some_service/inbound_messages",
bearer_token="some_unique_string",
updated_by_id=sample_service.users[0].id
)
save_service_inbound_api(service_inbound_api)
results = ServiceInboundApi.query.all()
assert len(results) == 1
inbound_api = results[0]
assert inbound_api.id
assert inbound_api.service_id == sample_service.id
assert inbound_api.updated_by_id == sample_service.users[0].id
assert inbound_api.url == "https::/some_service/inbound_messages"
assert inbound_api.unsigned_bearer_token == "some_unique_string"
assert inbound_api.bearer_token != "some_unique_string"
assert not inbound_api.updated_at
versioned = ServiceInboundApi.get_history_model().query.filter_by(id=inbound_api.id).one()
assert versioned.id == inbound_api.id
assert versioned.service_id == sample_service.id
assert versioned.updated_by_id == sample_service.users[0].id
assert versioned.url == "https::/some_service/inbound_messages"
assert versioned.bearer_token != "some_unique_string"
assert not versioned.updated_at
assert versioned.version == 1
def test_save_service_inbound_api_fails_if_service_does_not_exist(notify_db, notify_db_session):
service_inbound_api = ServiceInboundApi(
service_id=uuid.uuid4(),
url="https::/some_service/inbound_messages",
bearer_token="some_unique_string",
updated_by_id=uuid.uuid4()
)
with pytest.raises(SQLAlchemyError):
save_service_inbound_api(service_inbound_api)
def test_update_service_inbound_api(sample_service):
service_inbound_api = ServiceInboundApi(
service_id=sample_service.id,
url="https::/some_service/inbound_messages",
bearer_token="some_unique_string",
updated_by_id=sample_service.users[0].id
)
save_service_inbound_api(service_inbound_api)
results = ServiceInboundApi.query.all()
assert len(results) == 1
saved_inbound_api = results[0]
updated_inbound_api = saved_inbound_api
updated_inbound_api.url = "https::/some_service/changed_url"
reset_service_inbound_api(updated_inbound_api)
updated_results = ServiceInboundApi.query.all()
assert len(updated_results) == 1
updated = updated_results[0]
assert updated.id
assert updated.service_id == sample_service.id
assert updated.updated_by_id == sample_service.users[0].id
assert updated.url == "https::/some_service/changed_url"
assert updated.unsigned_bearer_token == "some_unique_string"
assert updated.bearer_token != "some_unique_string"
assert updated.updated_at
versioned_results = ServiceInboundApi.get_history_model().query.filter_by(id=saved_inbound_api.id).all()
assert len(versioned_results) == 2
for x in versioned_results:
if x.version == 1:
assert x.url == "https::/some_service/inbound_messages"
assert not x.updated_at
elif x.version == 2:
assert x.url == "https::/some_service/changed_url"
assert x.updated_at
else:
pytest.fail("version should not exist")
assert x.id
assert x.service_id == sample_service.id
assert x.updated_by_id == sample_service.users[0].id
assert get_secret(x.bearer_token) == "some_unique_string"
def test_get_service_inbound_api(sample_service):
service_inbound_api = ServiceInboundApi(
service_id=sample_service.id,
url="https::/some_service/inbound_messages",
bearer_token="some_unique_string",
updated_by_id=sample_service.users[0].id
)
save_service_inbound_api(service_inbound_api)
inbound_api = get_service_inbound_api(service_inbound_api.id, sample_service.id)
assert inbound_api.id
assert inbound_api.service_id == sample_service.id
assert inbound_api.updated_by_id == sample_service.users[0].id
assert inbound_api.url == "https::/some_service/inbound_messages"
assert inbound_api.unsigned_bearer_token == "some_unique_string"
assert inbound_api.bearer_token != "some_unique_string"
assert not inbound_api.updated_at

View File

@@ -2,10 +2,9 @@ from datetime import datetime
import uuid
from app.dao.inbound_sms_dao import dao_create_inbound_sms
from app.dao.jobs_dao import dao_create_job
from app.dao.service_inbound_api_dao import save_service_inbound_api
from app.models import (
InboundSms,
Service,
User,
Template,
@@ -17,7 +16,7 @@ from app.models import (
EMAIL_TYPE,
SMS_TYPE,
KEY_TYPE_NORMAL,
)
ServiceInboundApi)
from app.dao.users_dao import save_model_user
from app.dao.notifications_dao import dao_create_notification, dao_created_scheduled_notification
from app.dao.templates_dao import dao_create_template
@@ -212,3 +211,17 @@ def create_inbound_sms(
)
dao_create_inbound_sms(inbound)
return inbound
def create_service_inbound_api(
service,
url="https://something.com",
bearer_token="some_super_secret",
):
service_inbound_api = ServiceInboundApi(service_id=service.id,
url=url,
bearer_token=bearer_token,
updated_by_id=service.users[0].id
)
save_service_inbound_api(service_inbound_api)
return service_inbound_api

View File

@@ -8,16 +8,17 @@ import pytest
from flask import url_for, current_app
from freezegun import freeze_time
from app.authentication.utils import get_secret
from app.dao.users_dao import save_model_user
from app.dao.services_dao import dao_remove_user_from_service
from app.models import (
Organisation, Rate, Service, ServicePermission, User,
KEY_TYPE_NORMAL, KEY_TYPE_TEAM, KEY_TYPE_TEST,
EMAIL_TYPE, SMS_TYPE, LETTER_TYPE, INTERNATIONAL_SMS_TYPE, INBOUND_SMS_TYPE,
DVLA_ORG_LAND_REGISTRY,
ServiceInboundApi)
DVLA_ORG_LAND_REGISTRY
)
from tests import create_authorization_header
from tests.app.db import create_template
from tests.app.db import create_template, create_service_inbound_api
from tests.app.conftest import (
sample_service as create_service,
sample_user_service_permission as create_user_service_permission,
@@ -2150,10 +2151,11 @@ def test_search_for_notification_by_to_field_returns_content(
assert notifications[0]['body'] == 'Hello Foo\nYour thing is due soon'
def test_set_service_inbound_api(client, sample_service):
def test_create_service_inbound_api(client, sample_service):
data = {
"url": "https://some_service/inbound-sms",
"bearer_token": "some-unique-string"
"bearer_token": "some-unique-string",
"updated_by_id": str(sample_service.users[0].id)
}
response = client.post(
'/service/{}/inbound-api'.format(sample_service.id),
@@ -2162,9 +2164,58 @@ def test_set_service_inbound_api(client, sample_service):
)
assert response.status_code == 201
api_data = ServiceInboundApi.query.all()
assert len(api_data) == 1
assert api_data[0].service_id == sample_service.id
assert api_data[0].url == "https://some_service/inbound-sms"
assert api_data[0].unsigned_bearer_token == "some-unique-string"
assert api_data[0].bearer_token != "some-unique-string"
resp_json = json.loads(response.get_data(as_text=True))["data"]
assert resp_json["id"]
assert resp_json["service_id"] == str(sample_service.id)
assert resp_json["url"] == "https://some_service/inbound-sms"
assert resp_json["bearer_token"] != "some-unique-string" # returned encrypted
assert resp_json["updated_by_id"] == str(sample_service.users[0].id)
assert resp_json["created_at"]
assert not resp_json["updated_at"]
def test_set_service_inbound_api_raises_500_when_service_does_not_exist(client):
data = {
"url": "https://some_service/inbound-sms",
"bearer_token": "some-unique-string",
"updated_by_id": str(uuid.uuid4())
}
response = client.post(
'/service/{}/inbound-api'.format(uuid.uuid4()),
data=json.dumps(data),
headers=[('Content-Type', 'application/json'), create_authorization_header()]
)
assert response.status_code == 500
def test_update_service_inbound_api_updates_url(client, sample_service):
service_inbound_api = create_service_inbound_api(service=sample_service,
url="https://original_url.com")
data = {
"url": "https://another_url.com",
"updated_by_id": str(sample_service.users[0].id)
}
response = client.post("/service/{}/inbound-api/{}".format(sample_service.id, service_inbound_api.id),
data=json.dumps(data),
headers=[('Content-Type', 'application/json'), create_authorization_header()])
assert response.status_code == 200
resp_json = json.loads(response.get_data(as_text=True))["data"]
assert resp_json["url"] == "https://another_url.com"
assert service_inbound_api.url == "https://another_url.com"
def test_update_service_inbound_api_updates_bearer_token(client, sample_service):
service_inbound_api = create_service_inbound_api(service=sample_service,
bearer_token="some_super_secret")
data = {
"bearer_token": "different_token",
"updated_by_id": str(sample_service.users[0].id)
}
response = client.post("/service/{}/inbound-api/{}".format(sample_service.id, service_inbound_api.id),
data=json.dumps(data),
headers=[('Content-Type', 'application/json'), create_authorization_header()])
assert response.status_code == 200
resp_json = json.loads(response.get_data(as_text=True))["data"]
assert get_secret(resp_json["bearer_token"]) == "different_token"
assert service_inbound_api.unsigned_bearer_token == "different_token"

View File

@@ -0,0 +1,45 @@
import json
import uuid
import pytest
from jsonschema import ValidationError
from app.schema_validation import validate
from app.service.service_inbound_api_schema import service_inbound_api
def test_service_inbound_api_schema_validates():
under_test = {"url": "https://some_url.for_service",
"bearer_token": "something_ten_chars",
"updated_by_id": str(uuid.uuid4())
}
validated = validate(under_test, service_inbound_api)
assert validated == under_test
@pytest.mark.parametrize("url", ["not a url", "https not a url", "http://valid.com"])
def test_service_inbound_api_schema_errors_for_url_not_valid_url(url):
under_test = {"url": url,
"bearer_token": "something_ten_chars",
"updated_by_id": str(uuid.uuid4())
}
with pytest.raises(ValidationError) as e:
validate(under_test, service_inbound_api)
errors = json.loads(str(e.value)).get('errors')
assert len(errors) == 1
assert errors[0]['message'] == "url is not a valid https url"
def test_service_inbound_api_schema_bearer_token_under_ten_char():
under_test = {"url": "https://some_url.for_service",
"bearer_token": "shorty",
"updated_by_id": str(uuid.uuid4())
}
with pytest.raises(ValidationError) as e:
validate(under_test, service_inbound_api)
errors = json.loads(str(e.value)).get('errors')
assert len(errors) == 1
assert errors[0]['message'] == "bearer_token shorty is too short"