def test_should_persist_notification(notify_api, sample_template, sample_email_template, template_type, fake_uuid, mocker): with notify_api.test_request_context(), notify_api.test_client() as client: mocked = mocker.patch('app.celery.provider_tasks.deliver_{}.apply_async'.format(template_type)) mocker.patch('app.dao.notifications_dao.create_uuid', return_value=fake_uuid) template = sample_template if template_type == 'sms' else sample_email_template to = sample_template.service.created_by.mobile_number if template_type == 'sms' \ else sample_email_template.service.created_by.email_address data = { 'to': to, 'template': template.id } api_key = ApiKey( service=template.service, name='team_key', created_by=template.created_by, key_type=KEY_TYPE_TEAM) save_model_api_key(api_key) auth_header = create_jwt_token(secret=api_key.unsigned_secret, client_id=str(api_key.service_id)) response = client.post( path='/notifications/{}'.format(template_type), data=json.dumps(data), headers=[('Content-Type', 'application/json'), ('Authorization', 'Bearer {}'.format(auth_header))]) mocked.assert_called_once_with([fake_uuid], queue='send-{}'.format(template_type)) assert response.status_code == 201 notification = notifications_dao.get_notification_by_id(fake_uuid) assert notification.to == to assert notification.template_id == template.id assert notification.notification_type == template_type
def test_should_send_sms_if_team_api_key_and_a_service_user( client, sample_template, fake_uuid, mocker): mocker.patch('app.celery.provider_tasks.deliver_sms.apply_async') mocker.patch('app.notifications.process_notifications.uuid.uuid4', return_value=fake_uuid) data = { 'to': sample_template.service.created_by.mobile_number, 'template': sample_template.id } api_key = ApiKey(service=sample_template.service, name='team_key', created_by=sample_template.created_by, key_type=KEY_TYPE_TEAM) save_model_api_key(api_key) auth_header = create_jwt_token(secret=api_key.secret, client_id=str(api_key.service_id)) response = client.post(path='/notifications/sms', data=json.dumps(data), headers=[('Content-Type', 'application/json'), ('Authorization', 'Bearer {}'.format(auth_header))]) app.celery.provider_tasks.deliver_sms.apply_async.assert_called_once_with( [fake_uuid], queue='send-sms-tasks') assert response.status_code == 201
def test_should_send_email_to_anyone_with_test_key( notify_api, sample_email_template, mocker, restricted, limit, fake_uuid ): with notify_api.test_request_context(), notify_api.test_client() as client: mocker.patch('app.celery.provider_tasks.deliver_email.apply_async') mocker.patch('app.dao.notifications_dao.create_uuid', return_value=fake_uuid) data = { 'to': '*****@*****.**', 'template': sample_email_template.id } sample_email_template.service.restricted = restricted sample_email_template.service.message_limit = limit api_key = ApiKey( service=sample_email_template.service, name='test_key', created_by=sample_email_template.created_by, key_type=KEY_TYPE_TEST ) save_model_api_key(api_key) auth_header = create_jwt_token(secret=api_key.unsigned_secret, client_id=str(api_key.service_id)) response = client.post( path='/notifications/email', data=json.dumps(data), headers=[('Content-Type', 'application/json'), ('Authorization', 'Bearer {}'.format(auth_header))] ) app.celery.provider_tasks.deliver_email.apply_async.assert_called_once_with([fake_uuid], queue='research-mode') assert response.status_code == 201
def test_authentication_passes_when_service_has_multiple_keys_some_expired( notify_api, notify_db, notify_db_session, sample_api_key): with notify_api.test_request_context(): with notify_api.test_client() as client: exprired_key = { 'service_id': sample_api_key.service_id, 'name': 'expired_key', 'expiry_date': datetime.now() } expired_api_key = ApiKey(**exprired_key) save_model_api_key(expired_api_key) another_key = { 'service_id': sample_api_key.service_id, 'name': 'another_key' } api_key = ApiKey(**another_key) save_model_api_key(api_key) token = create_jwt_token( request_method="GET", request_path=url_for('service.get_service'), secret=get_unsigned_secret(api_key.id), client_id=sample_api_key.service_id) response = client.get( url_for('service.get_service'), headers={'Authorization': 'Bearer {}'.format(token)}) assert response.status_code == 200
def test_should_delete_notification_and_return_error_if_sqs_fails( client, sample_email_template, sample_template, fake_uuid, mocker, template_type, queue_name): mocked = mocker.patch( 'app.celery.provider_tasks.deliver_{}.apply_async'.format( template_type), side_effect=Exception("failed to talk to SQS")) mocker.patch('app.notifications.process_notifications.uuid.uuid4', return_value=fake_uuid) template = sample_template if template_type == SMS_TYPE else sample_email_template to = sample_template.service.created_by.mobile_number if template_type == SMS_TYPE \ else sample_email_template.service.created_by.email_address data = {'to': to, 'template': template.id} api_key = ApiKey(service=template.service, name='team_key', created_by=template.created_by, key_type=KEY_TYPE_TEAM) save_model_api_key(api_key) auth_header = create_jwt_token(secret=api_key.secret, client_id=str(api_key.service_id)) with pytest.raises(Exception) as e: client.post(path='/notifications/{}'.format(template_type), data=json.dumps(data), headers=[('Content-Type', 'application/json'), ('Authorization', 'Bearer {}'.format(auth_header)) ]) assert str(e.value) == 'failed to talk to SQS' mocked.assert_called_once_with([fake_uuid], queue=queue_name) assert not notifications_dao.get_notification_by_id(fake_uuid) assert not NotificationHistory.query.get(fake_uuid)
def test_get_api_keys_should_return_all_keys_for_service(notify_api, notify_db, notify_db_session, sample_api_key): with notify_api.test_request_context(): with notify_api.test_client() as client: another_user = create_user(notify_db, notify_db_session, email='*****@*****.**') another_service = create_sample_service(notify_db, notify_db_session, service_name='another', user=another_user) create_sample_api_key(notify_db, notify_db_session, service=another_service) api_key2 = ApiKey(**{'service_id': sample_api_key.service_id, 'name': 'second_api_key'}) api_key3 = ApiKey(**{'service_id': sample_api_key.service_id, 'name': 'third_api_key', 'expiry_date': datetime.utcnow() + timedelta(hours=-1)}) save_model_api_key(api_key2) save_model_api_key(api_key3) assert ApiKey.query.count() == 4 auth_header = create_authorization_header(path=url_for('service.get_api_keys', service_id=sample_api_key.service_id), method='GET') response = client.get(url_for('service.get_api_keys', service_id=sample_api_key.service_id), headers=[('Content-Type', 'application/json'), auth_header]) assert response.status_code == 200 json_resp = json.loads(response.get_data(as_text=True)) assert len(json_resp['apiKeys']) == 3
def test_save_api_key_should_create_new_api_key(notify_api, notify_db, notify_db_session, sample_service): api_key = ApiKey(**{'service_id': sample_service.id, 'name': sample_service.name}) save_model_api_key(api_key) all_api_keys = get_model_api_keys(service_id=sample_service.id) assert len(all_api_keys) == 1 assert all_api_keys[0] == api_key
def create_authorization_header(service_id=None, key_type=KEY_TYPE_NORMAL): if service_id: client_id = str(service_id) secrets = ApiKey.query.filter_by(service_id=service_id, key_type=key_type).all() if secrets: secret = secrets[0].secret else: service = dao_fetch_service_by_id(service_id) data = { "service": service, "name": uuid.uuid4(), "created_by": service.created_by, "key_type": key_type, } api_key = ApiKey(**data) save_model_api_key(api_key) secret = api_key.secret else: client_id = current_app.config["ADMIN_CLIENT_USER_NAME"] secret = current_app.config["ADMIN_CLIENT_SECRET"] token = create_jwt_token(secret=secret, client_id=client_id) return "Authorization", "Bearer {}".format(token)
def test_get_notification_from_different_api_key_of_same_type_succeeds(notify_api, sample_notification, key_type): with notify_api.test_request_context(), notify_api.test_client() as client: creation_api_key = ApiKey(service=sample_notification.service, name='creation_api_key', created_by=sample_notification.service.created_by, key_type=key_type) save_model_api_key(creation_api_key) querying_api_key = ApiKey(service=sample_notification.service, name='querying_api_key', created_by=sample_notification.service.created_by, key_type=key_type) save_model_api_key(querying_api_key) sample_notification.api_key = creation_api_key sample_notification.key_type = key_type dao_update_notification(sample_notification) response = client.get( path='/notifications/{}'.format(sample_notification.id), headers=_create_auth_header_from_key(querying_api_key)) assert response.status_code == 200 notification = json.loads(response.get_data(as_text=True))['data']['notification'] assert sample_notification.api_key_id != querying_api_key.id assert notification['id'] == str(sample_notification.id)
def sample_admin_service_id(notify_db, notify_db_session): admin_user = sample_user(notify_db, notify_db_session, email="*****@*****.**") admin_service = sample_service(notify_db, notify_db_session, service_name="Sample Admin Service", user=admin_user) data = {'service': admin_service, 'name': 'sample admin key'} api_key = ApiKey(**data) save_model_api_key(api_key) return admin_service.id
def test_authentication_returns_token_expired_when_service_uses_expired_key_and_has_multiple_keys( client, sample_api_key): expired_key = { "service": sample_api_key.service, "name": "expired_key", "created_by": sample_api_key.created_by, "key_type": KEY_TYPE_NORMAL, } expired_api_key = ApiKey(**expired_key) save_model_api_key(expired_api_key) another_key = { "service": sample_api_key.service, "name": "another_key", "created_by": sample_api_key.created_by, "key_type": KEY_TYPE_NORMAL, } api_key = ApiKey(**another_key) save_model_api_key(api_key) token = create_jwt_token( secret=get_unsigned_secret(expired_api_key.id), client_id=str(sample_api_key.service_id), ) expire_api_key(service_id=sample_api_key.service_id, api_key_id=expired_api_key.id) request.headers = {"Authorization": "Bearer {}".format(token)} with pytest.raises(AuthError) as exc: requires_auth() assert exc.value.short_message == "Invalid token: API key revoked" assert exc.value.service_id == expired_api_key.service_id assert exc.value.api_key_id == expired_api_key.id
def test_authentication_returns_token_expired_when_service_uses_expired_key_and_has_multiple_keys( client, sample_api_key): expired_key = { 'service': sample_api_key.service, 'name': 'expired_key', 'created_by': sample_api_key.created_by, 'key_type': KEY_TYPE_NORMAL } expired_api_key = ApiKey(**expired_key) save_model_api_key(expired_api_key) another_key = { 'service': sample_api_key.service, 'name': 'another_key', 'created_by': sample_api_key.created_by, 'key_type': KEY_TYPE_NORMAL } api_key = ApiKey(**another_key) save_model_api_key(api_key) token = create_jwt_token(secret=get_unsigned_secret(expired_api_key.id), client_id=str(sample_api_key.service_id)) expire_api_key(service_id=sample_api_key.service_id, api_key_id=expired_api_key.id) request.headers = {'Authorization': 'Bearer {}'.format(token)} with pytest.raises(AuthError) as exc: validate_service_api_key_auth() assert exc.value.short_message == 'Invalid token: API key revoked' assert exc.value.service_id == expired_api_key.service_id assert exc.value.api_key_id == expired_api_key.id
def create_api_key(service_id=None): fetched_service = dao_fetch_service_by_id(service_id=service_id) valid_api_key = api_key_schema.load(request.get_json()).data valid_api_key.service = fetched_service save_model_api_key(valid_api_key) unsigned_api_key = get_unsigned_secret(valid_api_key.id) return jsonify(data=unsigned_api_key), 201
def test_get_notification_from_different_api_key_of_same_type_succeeds(client, sample_notification, key_type): creation_api_key = ApiKey(service=sample_notification.service, name='creation_api_key', created_by=sample_notification.service.created_by, key_type=key_type) save_model_api_key(creation_api_key) querying_api_key = ApiKey(service=sample_notification.service, name='querying_api_key', created_by=sample_notification.service.created_by, key_type=key_type) save_model_api_key(querying_api_key) sample_notification.api_key = creation_api_key sample_notification.key_type = key_type dao_update_notification(sample_notification) response = client.get( path='/notifications/{}'.format(sample_notification.id), headers=_create_auth_header_from_key(querying_api_key)) assert response.status_code == 200 notification = json.loads(response.get_data(as_text=True))['data']['notification'] assert sample_notification.api_key_id != querying_api_key.id assert notification['id'] == str(sample_notification.id)
def test_should_persist_notification(client, sample_template, sample_email_template, fake_uuid, mocker, template_type, queue_name): mocked = mocker.patch( 'app.celery.provider_tasks.deliver_{}.apply_async'.format( template_type)) mocker.patch('app.notifications.process_notifications.uuid.uuid4', return_value=fake_uuid) template = sample_template if template_type == SMS_TYPE else sample_email_template to = sample_template.service.created_by.mobile_number if template_type == SMS_TYPE \ else sample_email_template.service.created_by.email_address data = {'to': to, 'template': template.id} api_key = ApiKey(service=template.service, name='team_key', created_by=template.created_by, key_type=KEY_TYPE_TEAM) save_model_api_key(api_key) auth_header = create_jwt_token(secret=api_key.secret, client_id=str(api_key.service_id)) response = client.post(path='/notifications/{}'.format(template_type), data=json.dumps(data), headers=[('Content-Type', 'application/json'), ('Authorization', 'Bearer {}'.format(auth_header))]) mocked.assert_called_once_with([fake_uuid], queue=queue_name) assert response.status_code == 201 notification = notifications_dao.get_notification_by_id(fake_uuid) assert notification.to == to assert notification.template_id == template.id assert notification.notification_type == template_type
def create_authorization_header(service_id=None, key_type=KEY_TYPE_NORMAL): if service_id: client_id = str(service_id) secrets = ApiKey.query.filter_by(service_id=service_id, key_type=key_type).all() if secrets: secret = secrets[0].secret else: service = dao_fetch_service_by_id(service_id) data = { 'service': service, 'name': uuid.uuid4(), 'created_by': service.created_by, 'key_type': key_type } api_key = ApiKey(**data) save_model_api_key(api_key) secret = api_key.secret else: client_id = current_app.config['ADMIN_CLIENT_USER_NAME'] secret = current_app.config['ADMIN_CLIENT_SECRET'] token = create_jwt_token(secret=secret, client_id=client_id) return 'Authorization', 'Bearer {}'.format(token)
def test_should_send_email_to_anyone_with_test_key(client, sample_email_template, mocker, restricted, limit, fake_uuid): mocker.patch('app.celery.provider_tasks.deliver_email.apply_async') mocker.patch('app.notifications.process_notifications.uuid.uuid4', return_value=fake_uuid) data = { 'to': '*****@*****.**', 'template': sample_email_template.id } sample_email_template.service.restricted = restricted sample_email_template.service.message_limit = limit api_key = ApiKey(service=sample_email_template.service, name='test_key', created_by=sample_email_template.created_by, key_type=KEY_TYPE_TEST) save_model_api_key(api_key) auth_header = create_jwt_token(secret=api_key.secret, client_id=str(api_key.service_id)) response = client.post(path='/notifications/email', data=json.dumps(data), headers=[('Content-Type', 'application/json'), ('Authorization', 'Bearer {}'.format(auth_header))]) app.celery.provider_tasks.deliver_email.apply_async.assert_called_once_with( [fake_uuid], queue='research-mode-tasks') assert response.status_code == 201
def test_authentication_passes_when_service_has_multiple_keys_some_expired( client, sample_api_key): expired_key_data = {'service': sample_api_key.service, 'name': 'expired_key', 'expiry_date': datetime.utcnow(), 'created_by': sample_api_key.created_by, 'key_type': KEY_TYPE_NORMAL } expired_key = ApiKey(**expired_key_data) save_model_api_key(expired_key) another_key = {'service': sample_api_key.service, 'name': 'another_key', 'created_by': sample_api_key.created_by, 'key_type': KEY_TYPE_NORMAL } api_key = ApiKey(**another_key) save_model_api_key(api_key) token = create_jwt_token( secret=get_unsigned_secret(api_key.id), client_id=str(sample_api_key.service_id)) response = client.get( '/notifications', headers={'Authorization': 'Bearer {}'.format(token)}) assert response.status_code == 200
def test_should_not_allow_duplicate_key_names_per_service(sample_api_key, fake_uuid): api_key = ApiKey(**{'id': fake_uuid, 'service': sample_api_key.service, 'name': sample_api_key.name, 'created_by': sample_api_key.created_by, 'key_type': KEY_TYPE_NORMAL}) with pytest.raises(IntegrityError): save_model_api_key(api_key)
def _get_notification(client, notification, url): save_model_api_key( ApiKey(service=notification.service, name='api_key', created_by=notification.service.created_by, key_type=KEY_TYPE_NORMAL)) auth_header = create_authorization_header( service_id=notification.service_id) return client.get(url, headers=[auth_header])
def sample_api_key(notify_db, notify_db_session, service=None): if service is None: service = sample_service(notify_db, notify_db_session) data = {'service_id': service.id, 'name': uuid.uuid4()} api_key = ApiKey(**data) save_model_api_key(api_key) return api_key
def _get_notification(client, notification, url): save_model_api_key(ApiKey( service=notification.service, name='api_key', created_by=notification.service.created_by, key_type=KEY_TYPE_NORMAL )) auth_header = create_authorization_header(service_id=notification.service_id) return client.get(url, headers=[auth_header])
def revoke_api_key(service_id, api_key_id): try: service_api_key = get_model_api_keys(service_id=service_id, id=api_key_id) except DataError: return jsonify(result="error", message="Invalid api key for service"), 400 except NoResultFound: return jsonify(result="error", message="Api key not found for service"), 404 save_model_api_key(service_api_key, update_dict={'id': service_api_key.id, 'expiry_date': datetime.utcnow()}) return jsonify(), 202
def test_save_api_key_should_update_the_api_key(notify_api, notify_db, notify_db_session, sample_api_key): now = datetime.utcnow() saved_api_key = get_model_api_keys(service_id=sample_api_key.service_id, id=sample_api_key.id) save_model_api_key(saved_api_key, update_dict={'id': saved_api_key.id, 'expiry_date': now}) all_api_keys = get_model_api_keys(service_id=sample_api_key.service_id) assert len(all_api_keys) == 1 assert all_api_keys[0].expiry_date == now assert all_api_keys[0].secret == saved_api_key.secret assert all_api_keys[0].id == saved_api_key.id assert all_api_keys[0].service_id == saved_api_key.service_id
def sample_api_key(notify_db, notify_db_session, service=None, key_type=KEY_TYPE_NORMAL, name=None): if service is None: service = sample_service(notify_db, notify_db_session) data = {'service': service, 'name': name or uuid.uuid4(), 'created_by': service.created_by, 'key_type': key_type} api_key = ApiKey(**data) save_model_api_key(api_key) return api_key
def test_should_not_allow_duplicate_key_names_per_service(notify_api, notify_db, notify_db_session, sample_api_key): api_key = ApiKey( **{'id': sample_api_key.id + 1, 'service_id': sample_api_key.service_id, 'name': sample_api_key.name}) try: save_model_api_key(api_key) fail("should throw IntegrityError") except: pass
def sample_api_key(notify_db_session): service = create_service(check_if_service_exists=True) data = { 'service': service, 'name': uuid.uuid4(), 'created_by': service.created_by, 'key_type': KEY_TYPE_NORMAL } api_key = ApiKey(**data) save_model_api_key(api_key) return api_key
def sample_api_key(notify_db, notify_db_session, service=None, key_type=KEY_TYPE_NORMAL, name=None): if service is None: service = create_service(check_if_service_exists=True) data = { "service": service, "name": name or uuid.uuid4(), "created_by": service.created_by, "key_type": key_type, } api_key = ApiKey(**data) save_model_api_key(api_key) return api_key
def test_should_not_allow_duplicate_key_names_per_service( sample_api_key, fake_uuid): api_key = ApiKey( **{ "id": fake_uuid, "service": sample_api_key.service, "name": sample_api_key.name, "created_by": sample_api_key.created_by, "key_type": KEY_TYPE_NORMAL, }) with pytest.raises(IntegrityError): save_model_api_key(api_key)
def test_should_not_allow_duplicate_key_names_per_service( sample_api_key, fake_uuid): api_key = ApiKey( **{ 'id': fake_uuid, 'service': sample_api_key.service, 'name': sample_api_key.name, 'created_by': sample_api_key.created_by, 'key_type': KEY_TYPE_NORMAL }) with pytest.raises(IntegrityError): save_model_api_key(api_key)
def test_should_allow_valid_token_when_service_has_multiple_keys(client, sample_api_key): data = {'service': sample_api_key.service, 'name': 'some key name', 'created_by': sample_api_key.created_by, 'key_type': KEY_TYPE_NORMAL } api_key = ApiKey(**data) save_model_api_key(api_key) token = __create_token(sample_api_key.service_id) response = client.get( '/notifications', headers={'Authorization': 'Bearer {}'.format(token)}) assert response.status_code == 200
def test_save_api_key_should_not_create_new_service_history(sample_service): from app.models import Service assert Service.query.count() == 1 assert Service.get_history_model().query.count() == 1 api_key = ApiKey(**{'service': sample_service, 'name': sample_service.name, 'created_by': sample_service.created_by, 'key_type': KEY_TYPE_NORMAL}) save_model_api_key(api_key) assert Service.get_history_model().query.count() == 1
def test_should_allow_valid_token_when_service_has_multiple_keys( notify_api, notify_db, notify_db_session, sample_api_key ): with notify_api.test_request_context(): with notify_api.test_client() as client: data = {"service_id": sample_api_key.service_id, "name": "some key name"} api_key = ApiKey(**data) save_model_api_key(api_key) token = __create_get_token(sample_api_key.service_id) response = client.get( url_for("service.get_service", service_id=sample_api_key.service_id), headers={"Authorization": "Bearer {}".format(token)}, ) assert response.status_code == 200
def test_should_allow_valid_token_when_service_has_multiple_keys( client, sample_api_key): data = { "service": sample_api_key.service, "name": "some key name", "created_by": sample_api_key.created_by, "key_type": KEY_TYPE_NORMAL, } api_key = ApiKey(**data) save_model_api_key(api_key) token = __create_token(sample_api_key.service_id) response = client.get("/notifications", headers={"Authorization": "Bearer {}".format(token)}) assert response.status_code == 200
def test_should_not_return_revoked_api_keys_older_than_7_days( sample_service, days_old, expected_length): expired_api_key = ApiKey( **{ 'service': sample_service, 'name': sample_service.name, 'created_by': sample_service.created_by, 'key_type': KEY_TYPE_NORMAL, 'expiry_date': datetime.utcnow() - timedelta(days=days_old) }) save_model_api_key(expired_api_key) all_api_keys = get_model_api_keys(service_id=sample_service.id) assert len(all_api_keys) == expected_length
def test_get_notification_from_different_api_key_works(client, sample_notification, api_key_type, notification_key_type): sample_notification.key_type = notification_key_type api_key = ApiKey(service=sample_notification.service, name='api_key', created_by=sample_notification.service.created_by, key_type=api_key_type) save_model_api_key(api_key) response = client.get(path='/notifications/{}'.format( sample_notification.id), headers=_create_auth_header_from_key(api_key)) assert response.status_code == 200
def test_save_api_key_should_not_create_new_service_history(sample_service): from app.models import Service assert Service.query.count() == 1 assert Service.get_history_model().query.count() == 1 api_key = ApiKey( **{ 'service': sample_service, 'name': sample_service.name, 'created_by': sample_service.created_by, 'key_type': KEY_TYPE_NORMAL }) save_model_api_key(api_key) assert Service.get_history_model().query.count() == 1
def test_save_api_key_should_create_new_api_key_and_history(sample_service): api_key = ApiKey(**{'service': sample_service, 'name': sample_service.name, 'created_by': sample_service.created_by, 'key_type': KEY_TYPE_NORMAL}) save_model_api_key(api_key) all_api_keys = get_model_api_keys(service_id=sample_service.id) assert len(all_api_keys) == 1 assert all_api_keys[0] == api_key assert api_key.version == 1 all_history = api_key.get_history_model().query.all() assert len(all_history) == 1 assert all_history[0].id == api_key.id assert all_history[0].version == api_key.version
def test_should_allow_valid_token_when_service_has_multiple_keys( notify_api, notify_db, notify_db_session, sample_api_key): with notify_api.test_request_context(): with notify_api.test_client() as client: data = { 'service_id': sample_api_key.service_id, 'name': 'some key name' } api_key = ApiKey(**data) save_model_api_key(api_key) token = __create_get_token(sample_api_key.service_id) response = client.get( url_for('service.get_service', service_id=sample_api_key.service_id), headers={'Authorization': 'Bearer {}'.format(token)}) assert response.status_code == 200
def renew_api_key(service_id=None): try: service = get_model_services(service_id=service_id) except DataError: return jsonify(result="error", message="Invalid service id"), 400 except NoResultFound: return jsonify(result="error", message="Service not found"), 404 try: # create a new one # TODO: what validation should be done here? secret_name = request.get_json()['name'] key = ApiKey(service=service, name=secret_name) save_model_api_key(key) except DAOException as e: return jsonify(result='error', message=str(e)), 400 unsigned_api_key = get_unsigned_secret(key.id) return jsonify(data=unsigned_api_key), 201
def test_get_notification_from_different_api_key_works( notify_api, sample_notification, api_key_type, notification_key_type ): with notify_api.test_request_context(), notify_api.test_client() as client: sample_notification.key_type = notification_key_type api_key = ApiKey(service=sample_notification.service, name='api_key', created_by=sample_notification.service.created_by, key_type=api_key_type) save_model_api_key(api_key) response = client.get( path='/notifications/{}'.format(sample_notification.id), headers=_create_auth_header_from_key(api_key)) assert response.status_code == 200
def test_authentication_returns_token_expired_when_service_uses_expired_key_and_has_multiple_keys( notify_api, notify_db, notify_db_session, sample_api_key ): with notify_api.test_request_context(): with notify_api.test_client() as client: expired_key = {"service_id": sample_api_key.service_id, "name": "expired_key"} expired_api_key = ApiKey(**expired_key) save_model_api_key(expired_api_key) another_key = {"service_id": sample_api_key.service_id, "name": "another_key"} api_key = ApiKey(**another_key) save_model_api_key(api_key) token = create_jwt_token( request_method="GET", request_path=url_for("service.get_service"), secret=get_unsigned_secret(expired_api_key.id), client_id=sample_api_key.service_id, ) # expire the key expire_the_key = { "id": expired_api_key.id, "service_id": sample_api_key.service_id, "name": "expired_key", "expiry_date": datetime.now() + timedelta(hours=-2), } save_model_api_key(expired_api_key, expire_the_key) response = client.get(url_for("service.get_service"), headers={"Authorization": "Bearer {}".format(token)}) assert response.status_code == 403 data = json.loads(response.get_data()) assert data["error"] == "Invalid token: signature"
def test_get_all_notifications_only_returns_notifications_of_matching_type( notify_api, notify_db, notify_db_session, sample_service, key_type ): with notify_api.test_request_context(), notify_api.test_client() as client: team_api_key = ApiKey(service=sample_service, name='team_api_key', created_by=sample_service.created_by, key_type=KEY_TYPE_TEAM) save_model_api_key(team_api_key) normal_api_key = ApiKey(service=sample_service, name='normal_api_key', created_by=sample_service.created_by, key_type=KEY_TYPE_NORMAL) save_model_api_key(normal_api_key) test_api_key = ApiKey(service=sample_service, name='test_api_key', created_by=sample_service.created_by, key_type=KEY_TYPE_TEST) save_model_api_key(test_api_key) normal_notification = create_sample_notification( notify_db, notify_db_session, api_key_id=normal_api_key.id, key_type=KEY_TYPE_NORMAL ) team_notification = create_sample_notification( notify_db, notify_db_session, api_key_id=team_api_key.id, key_type=KEY_TYPE_TEAM ) test_notification = create_sample_notification( notify_db, notify_db_session, api_key_id=test_api_key.id, key_type=KEY_TYPE_TEST ) notification_objs = { KEY_TYPE_NORMAL: normal_notification, KEY_TYPE_TEAM: team_notification, KEY_TYPE_TEST: test_notification } response = client.get( path='/notifications', headers=_create_auth_header_from_key(notification_objs[key_type].api_key)) assert response.status_code == 200 notifications = json.loads(response.get_data(as_text=True))['notifications'] assert len(notifications) == 1 assert notifications[0]['id'] == str(notification_objs[key_type].id)
def test_authentication_passes_when_service_has_multiple_keys_some_expired( notify_api, notify_db, notify_db_session, sample_api_key ): with notify_api.test_request_context(): with notify_api.test_client() as client: exprired_key = { "service_id": sample_api_key.service_id, "name": "expired_key", "expiry_date": datetime.now(), } expired_api_key = ApiKey(**exprired_key) save_model_api_key(expired_api_key) another_key = {"service_id": sample_api_key.service_id, "name": "another_key"} api_key = ApiKey(**another_key) save_model_api_key(api_key) token = create_jwt_token( request_method="GET", request_path=url_for("service.get_service"), secret=get_unsigned_secret(api_key.id), client_id=sample_api_key.service_id, ) response = client.get(url_for("service.get_service"), headers={"Authorization": "Bearer {}".format(token)}) assert response.status_code == 200
def test_should_send_sms_if_team_api_key_and_a_service_user(notify_api, sample_template, fake_uuid, mocker): with notify_api.test_request_context(), notify_api.test_client() as client: mocker.patch('app.celery.provider_tasks.deliver_sms.apply_async') mocker.patch('app.dao.notifications_dao.create_uuid', return_value=fake_uuid) data = { 'to': sample_template.service.created_by.mobile_number, 'template': sample_template.id } api_key = ApiKey(service=sample_template.service, name='team_key', created_by=sample_template.created_by, key_type=KEY_TYPE_TEAM) save_model_api_key(api_key) auth_header = create_jwt_token(secret=api_key.unsigned_secret, client_id=str(api_key.service_id)) response = client.post( path='/notifications/sms', data=json.dumps(data), headers=[('Content-Type', 'application/json'), ('Authorization', 'Bearer {}'.format(auth_header))]) app.celery.provider_tasks.deliver_sms.apply_async.assert_called_once_with([fake_uuid], queue='send-sms') assert response.status_code == 201
def create_authorization_header(service_id=None, key_type=KEY_TYPE_NORMAL): if service_id: client_id = str(service_id) secrets = ApiKey.query.filter_by(service_id=service_id, key_type=key_type).all() if secrets: secret = secrets[0].unsigned_secret else: service = dao_fetch_service_by_id(service_id) data = { 'service': service, 'name': uuid.uuid4(), 'created_by': service.created_by, 'key_type': key_type } api_key = ApiKey(**data) save_model_api_key(api_key) secret = api_key.unsigned_secret else: client_id = current_app.config.get('ADMIN_CLIENT_USER_NAME') secret = current_app.config.get('ADMIN_CLIENT_SECRET') token = create_jwt_token(secret=secret, client_id=client_id) return 'Authorization', 'Bearer {}'.format(token)