From 0995cd2e3c02b298cbda2a32b3a6286451b328cc Mon Sep 17 00:00:00 2001 From: Adam Shimali Date: Fri, 29 Jan 2016 10:27:23 +0000 Subject: [PATCH] Uploading csv creates job via api --- app/__init__.py | 3 +++ app/main/views/sms.py | 23 ++++++++++++++--------- app/notify_client/job_api_client.py | 29 +++++++++++++++++++++++++++++ app/templates/views/check-sms.html | 1 + tests/app/main/views/test_sms.py | 28 +++++++++++++++++++--------- tests/conftest.py | 25 ++++++++++++++++++++++--- 6 files changed, 88 insertions(+), 21 deletions(-) create mode 100644 app/notify_client/job_api_client.py diff --git a/app/__init__.py b/app/__init__.py index cf2b6b3a9..cde6f7e22 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -11,6 +11,7 @@ from werkzeug.exceptions import abort from app.notify_client.api_client import NotificationsAdminAPIClient from app.notify_client.api_key_api_client import ApiKeyApiClient from app.notify_client.user_api_client import UserApiClient +from app.notify_client.job_api_client import JobApiClient from app.its_dangerous_session import ItsdangerousSessionInterface import app.proxy_fix from config import configs @@ -22,6 +23,7 @@ csrf = CsrfProtect() notifications_api_client = NotificationsAdminAPIClient() user_api_client = UserApiClient() api_key_api_client = ApiKeyApiClient() +job_api_client = JobApiClient() def create_app(config_name, config_overrides=None): @@ -36,6 +38,7 @@ def create_app(config_name, config_overrides=None): notifications_api_client.init_app(application) user_api_client.init_app(application) api_key_api_client.init_app(application) + job_api_client.init_app(application) login_manager.init_app(application) login_manager.login_view = 'main.sign_in' diff --git a/app/main/views/sms.py b/app/main/views/sms.py index 65f0c6fe3..b10bf0905 100644 --- a/app/main/views/sms.py +++ b/app/main/views/sms.py @@ -1,6 +1,5 @@ import csv import re -import os from datetime import date @@ -9,14 +8,13 @@ from flask import ( render_template, redirect, url_for, - session, flash, - current_app, abort ) from flask_login import login_required from werkzeug import secure_filename +from client.errors import HTTPError from app.main import main from app.main.forms import CsvUploadForm @@ -25,6 +23,7 @@ from app.main.uploader import ( s3download ) from app.main.dao import templates_dao +from app import job_api_client @main.route("/services//sms/send", methods=['GET', 'POST']) @@ -38,7 +37,8 @@ def send_sms(service_id): upload_id = s3upload(service_id, filedata) return redirect(url_for('.check_sms', service_id=service_id, - upload_id=upload_id)) + upload_id=upload_id, + file_name=filedata['file_name'])) except ValueError as e: message = 'There was a problem uploading: {}'.format( csv_file.filename) @@ -67,18 +67,23 @@ def check_sms(service_id, upload_id): if request.method == 'GET': contents = s3download(service_id, upload_id) upload_result = _get_numbers(contents) - # TODO get original file name + file_name = request.args.get('file_name') return render_template( 'views/check-sms.html', upload_result=upload_result, - filename='someupload_file_name.csv', + file_name=file_name, message_template=''' ((name)), we’ve received your ((thing)). We’ll contact you again within 1 week. ''', service_id=service_id ) elif request.method == 'POST': - # TODO create the job with template, file location etc. + file_name = request.form['original_file_name'] + + # TODO need a real template id picked from form + template_id = 1 + + job_api_client.create_job(service_id, template_id, file_name) return redirect(url_for('main.view_job', service_id=service_id, job_id=upload_id)) @@ -89,7 +94,7 @@ def _get_filedata(file): if len(lines) < 2: # must be at least header and one line message = 'The file {} contained no data'.format(file.filename) raise ValueError(message) - return {'filename': file.filename, 'data': lines} + return {'file_name': file.filename, 'data': lines} def _format_filename(filename): @@ -100,7 +105,7 @@ def _format_filename(filename): def _get_numbers(contents): - pattern = re.compile(r'^\+44\s?\d{4}\s?\d{6}$') # need better validation + pattern = re.compile(r'^\+44\s?\d{4}\s?\d{6}$') # TODO need better validation reader = csv.DictReader( contents.split('\n'), lineterminator='\n', diff --git a/app/notify_client/job_api_client.py b/app/notify_client/job_api_client.py new file mode 100644 index 000000000..7c938cb70 --- /dev/null +++ b/app/notify_client/job_api_client.py @@ -0,0 +1,29 @@ +import uuid + +from client.base import BaseAPIClient + + +class JobApiClient(BaseAPIClient): + def __init__(self, base_url=None, client_id=None, secret=None): + super(self.__class__, self).__init__(base_url=base_url or 'base_url', + client_id=client_id or 'client_id', + secret=secret or 'secret') + + def init_app(self, app): + self.base_url = app.config['API_HOST_NAME'] + self.client_id = app.config['ADMIN_CLIENT_USER_NAME'] + self.secret = app.config['ADMIN_CLIENT_SECRET'] + + def create_job(self, service_id, template_id, file_name): + job_id = str(uuid.uuid4()) + data = { + "id": job_id, + "service": service_id, + "template": template_id, + "original_file_name": file_name, + "bucket_name": "service-{}-notify".format(service_id), + "file_name": "{}.csv".format(job_id) + } + + resp = self.post(url='/service/{}/job'.format(service_id), data=data) + return resp['data'] diff --git a/app/templates/views/check-sms.html b/app/templates/views/check-sms.html index 89726050e..80a216ca4 100644 --- a/app/templates/views/check-sms.html +++ b/app/templates/views/check-sms.html @@ -59,6 +59,7 @@ back_link = url_for(".send_sms", service_id=service_id) )}} + {% endif %} {% endblock %} diff --git a/tests/app/main/views/test_sms.py b/tests/app/main/views/test_sms.py index ef90289bf..401fffcba 100644 --- a/tests/app/main/views/test_sms.py +++ b/tests/app/main/views/test_sms.py @@ -117,15 +117,25 @@ def test_upload_csvfile_with_valid_phone_shows_all_if_6_or_less_numbers(app_, @moto.mock_s3 -def test_should_redirect_to_job(app_, - api_user_active, - mock_get_user, - mock_get_user_by_email, - mock_login): +def test_create_job_should_call_api(app_, + service_one, + api_user_active, + mock_get_user, + mock_get_user_by_email, + mock_login, + job_data, + mock_create_job): + + service_id = job_data['service'] + template_id = job_data['template'] + upload_id = job_data['id'] + file_name = job_data['original_file_name'] + with app_.test_request_context(): with app_.test_client() as client: client.login(api_user_active) - response = client.post(url_for('main.check_sms', - service_id=123, - upload_id='someid')) - assert response.status_code == 302 + url = url_for('main.check_sms', service_id=service_id, upload_id=upload_id, file_name=file_name) + response = client.post(url, data=job_data, follow_redirects=True) + + assert response.status_code == 200 + mock_create_job.assert_called_with(service_id, template_id, file_name) diff --git a/tests/conftest.py b/tests/conftest.py index f036a6585..87492a6a6 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -422,6 +422,25 @@ def mock_check_verify_code_code_expired(mocker): @pytest.fixture(scope='function') -def mock_send_email(mocker): - return mocker.patch( - 'app.notifications_api_client.send_email', return_value=None) +def job_data(mocker): + import uuid + job_id = uuid.uuid4() + original_file_name = 'thisisatest.csv' + bucket_name = 'service-2-notify' + file_name = '{}.csv'.format(job_id) + data = { + 'id': str(job_id), + 'service': 1, + 'template': 1, + 'original_file_name': original_file_name, + 'bucket_name': bucket_name, + 'file_name': file_name, + } + return data + + +@pytest.fixture(scope='function') +def mock_create_job(mocker, job_data): + def _create(service_id, template_id, file_name): + return job_data + return mocker.patch('app.job_api_client.create_job', side_effect=_create)