def test_should_process_email_job_into_research_mode_queue_if_research_mode_service( notify_db, notify_db_session, mocker ): mocker.patch('app.celery.tasks.s3.get_job_from_s3', return_value=load_example_csv('sms')) mocker.patch('app.celery.tasks.send_email.apply_async') mocker.patch('app.encryption.encrypt', return_value="something_encrypted") mocker.patch('app.celery.tasks.create_uuid', return_value="uuid") service = sample_service(notify_db, notify_db_session) service.research_mode = True services_dao.dao_update_service(service) template = sample_email_template(notify_db, notify_db_session, service=service) job = sample_job(notify_db, notify_db_session, template=template, service=service) process_job(job.id) s3.get_job_from_s3.assert_called_once_with( str(job.service.id), str(job.id) ) tasks.send_email.apply_async.assert_called_once_with( (str(job.service_id), "uuid", "something_encrypted", "2016-01-01T11:09:00.061258Z"), queue="research-mode" )
def test_should_not_send_notification_if_restricted_and_not_a_service_user(notify_api, sample_template, sample_email_template, mocker, template_type, to): with notify_api.test_request_context(): with notify_api.test_client() as client: mocked = mocker.patch('app.celery.provider_tasks.deliver_{}.apply_async'.format(template_type)) template = sample_template if template_type == 'sms' else sample_email_template template.service.restricted = True dao_update_service(template.service) data = { 'to': to, 'template': template.id } auth_header = create_authorization_header(service_id=template.service_id) response = client.post( path='/notifications/{}'.format(template_type), data=json.dumps(data), headers=[('Content-Type', 'application/json'), auth_header]) json_resp = json.loads(response.get_data(as_text=True)) mocked.assert_not_called() assert response.status_code == 400 assert [( 'Can’t send to this recipient when service is in trial mode ' '– see https://www.notifications.service.gov.uk/trial-mode' )] == json_resp['message']['to']
def test_should_send_notification_if_restricted_and_a_service_user( notify_api, sample_template, sample_email_template, template_type, mocker): with notify_api.test_request_context(): with notify_api.test_client() as client: mocked = mocker.patch( 'app.celery.provider_tasks.deliver_{}.apply_async'.format( template_type)) template = sample_template if template_type == SMS_TYPE else sample_email_template to = template.service.created_by.mobile_number if template_type == SMS_TYPE \ else template.service.created_by.email_address template.service.restricted = True dao_update_service(template.service) data = {'to': to, 'template': template.id} auth_header = create_authorization_header( service_id=template.service_id) response = client.post( path='/notifications/{}'.format(template_type), data=json.dumps(data), headers=[('Content-Type', 'application/json'), auth_header]) assert mocked.called == 1 assert response.status_code == 201
def populate_go_live(file_name): # 0 - count, 1- Link, 2- Service ID, 3- DEPT, 4- Service Name, 5- Main contact, # 6- Contact detail, 7-MOU, 8- LIVE date, 9- SMS, 10 - Email, 11 - Letters, 12 -CRM, 13 - Blue badge import csv print("Populate go live user and date") with open(file_name, 'r') as f: rows = csv.reader( f, quoting=csv.QUOTE_MINIMAL, skipinitialspace=True, ) print(next(rows)) # ignore header row for index, row in enumerate(rows): print(index, row) service_id = row[2] go_live_email = row[6] go_live_date = datetime.strptime(row[8], '%d/%m/%Y') + timedelta(hours=12) print(service_id, go_live_email, go_live_date) try: if go_live_email: go_live_user = get_user_by_email(go_live_email) else: go_live_user = None except NoResultFound: print("No user found for email address: ", go_live_email) continue try: service = dao_fetch_service_by_id(service_id) except NoResultFound: print("No service found for: ", service_id) continue service.go_live_user = go_live_user service.go_live_at = go_live_date dao_update_service(service)
def test_should_not_send_notification_if_restricted_and_not_a_service_user( notify_api, sample_template, sample_email_template, mocker, template_type, to): with notify_api.test_request_context(): with notify_api.test_client() as client: mocked = mocker.patch( 'app.celery.provider_tasks.deliver_{}.apply_async'.format( template_type)) template = sample_template if template_type == SMS_TYPE else sample_email_template template.service.restricted = True dao_update_service(template.service) data = {'to': to, 'template': template.id} auth_header = create_authorization_header( service_id=template.service_id) response = client.post( path='/notifications/{}'.format(template_type), data=json.dumps(data), headers=[('Content-Type', 'application/json'), auth_header]) json_resp = json.loads(response.get_data(as_text=True)) mocked.assert_not_called() assert response.status_code == 400 assert [ ('Can’t send to this recipient when service is in trial mode ' '– see https://www.notifications.service.gov.uk/trial-mode') ] == json_resp['message']['to']
def test_dao_fetch_service_creator(notify_db_session): active_user_1 = create_user(email="*****@*****.**", state="active") active_user_2 = create_user(email="*****@*****.**", state="active") service = Service( name="service_name", email_from="email_from", message_limit=1000, restricted=False, created_by=active_user_1, ) dao_create_service( service, active_user_1, service_permissions=[ SMS_TYPE, EMAIL_TYPE, INTERNATIONAL_SMS_TYPE, ], ) service.created_by_id = active_user_2.id service.name = "New Name" dao_update_service(service) assert Service.query.count() == 1 history_model = Service.get_history_model() entries = history_model.query.all() assert len(entries) == 2 assert entries[1].created_by_id == active_user_2.id assert active_user_1 == dao_fetch_service_creator(service.id)
def test_update_service_creates_a_history_record_with_current_data(notify_db_session): user = create_user() assert Service.query.count() == 0 assert Service.get_history_model().query.count() == 0 service = Service(name="service_name", email_from="email_from", message_limit=1000, restricted=False, created_by=user) dao_create_service(service, user) assert Service.query.count() == 1 assert Service.query.first().version == 1 assert Service.get_history_model().query.count() == 1 service.name = 'updated_service_name' dao_update_service(service) assert Service.query.count() == 1 assert Service.get_history_model().query.count() == 2 service_from_db = Service.query.first() assert service_from_db.version == 2 assert Service.get_history_model().query.filter_by(name='service_name').one().version == 1 assert Service.get_history_model().query.filter_by(name='updated_service_name').one().version == 2
def update_service(service_id): req_json = request.get_json() fetched_service = dao_fetch_service_by_id(service_id) # Capture the status change here as Marshmallow changes this later service_going_live = fetched_service.restricted and not req_json.get( 'restricted', True) current_data = dict(service_schema.dump(fetched_service).data.items()) current_data.update(request.get_json()) service = service_schema.load(current_data).data if 'email_branding' in req_json: email_branding_id = req_json['email_branding'] service.email_branding = None if not email_branding_id else EmailBranding.query.get( email_branding_id) if 'letter_branding' in req_json: letter_branding_id = req_json['letter_branding'] service.letter_branding = None if not letter_branding_id else LetterBranding.query.get( letter_branding_id) dao_update_service(service) if service_going_live: send_notification_to_service_users( service_id=service_id, template_id=current_app.config['SERVICE_NOW_LIVE_TEMPLATE_ID'], personalisation={ 'service_name': current_data['name'], 'message_limit': '{:,}'.format(current_data['message_limit']) }, include_user_fields=['name']) return jsonify(data=service_schema.dump(fetched_service).data), 200
def test_should_send_notification_if_restricted_and_a_service_user(notify_api, sample_template, sample_email_template, template_type, mocker): with notify_api.test_request_context(): with notify_api.test_client() as client: mocked = mocker.patch('app.celery.provider_tasks.deliver_{}.apply_async'.format(template_type)) template = sample_template if template_type == 'sms' else sample_email_template to = template.service.created_by.mobile_number if template_type == 'sms' \ else template.service.created_by.email_address template.service.restricted = True dao_update_service(template.service) data = { 'to': to, 'template': template.id } auth_header = create_authorization_header(service_id=template.service_id) response = client.post( path='/notifications/{}'.format(template_type), data=json.dumps(data), headers=[('Content-Type', 'application/json'), auth_header]) assert mocked.called == 1 assert response.status_code == 201
def test_should_put_send_email_task_in_research_mode_queue_if_research_mode_service( notify_db, notify_db_session, mocker ): service = sample_service(notify_db, notify_db_session) service.research_mode = True services_dao.dao_update_service(service) template = sample_email_template(notify_db, notify_db_session, service=service) notification = _notification_json(template, to="*****@*****.**") mocker.patch('app.celery.provider_tasks.deliver_email.apply_async') notification_id = uuid.uuid4() send_email( template.service_id, notification_id, encryption.encrypt(notification), datetime.utcnow().strftime(DATETIME_FORMAT) ) persisted_notification = Notification.query.one() provider_tasks.deliver_email.apply_async.assert_called_once_with( [str(persisted_notification.id)], queue="research-mode" )
def delete_smtp_relay(service_id): service = dao_fetch_service_by_id(service_id) if service.smtp_user is not None: smtp_remove(service.smtp_user) service.smtp_user = None dao_update_service(service) return jsonify(True), 201 else: raise InvalidRequest(message="SMTP user does not exist", status_code=500)
def test_update_service_permission_creates_a_history_record_with_current_data( notify_db_session, ): user = create_user() assert Service.query.count() == 0 assert Service.get_history_model().query.count() == 0 service = Service( name="service_name", email_from="email_from", message_limit=1000, restricted=False, created_by=user, ) dao_create_service( service, user, service_permissions=[ SMS_TYPE, EMAIL_TYPE, INTERNATIONAL_SMS_TYPE, ], ) service.permissions.append( ServicePermission(service_id=service.id, permission="letter")) dao_update_service(service) assert Service.query.count() == 1 assert Service.get_history_model().query.count() == 2 service_from_db = Service.query.first() assert service_from_db.version == 2 _assert_service_permissions( service.permissions, (SMS_TYPE, EMAIL_TYPE, INTERNATIONAL_SMS_TYPE, LETTER_TYPE)) permission = [p for p in service.permissions if p.permission == "sms"][0] service.permissions.remove(permission) dao_update_service(service) assert Service.query.count() == 1 assert Service.get_history_model().query.count() == 3 service_from_db = Service.query.first() assert service_from_db.version == 3 _assert_service_permissions( service.permissions, (EMAIL_TYPE, INTERNATIONAL_SMS_TYPE, LETTER_TYPE)) assert len(Service.get_history_model().query.filter_by( name="service_name").all()) == 3 assert Service.get_history_model().query.filter_by( name="service_name").all()[2].version == 3
def update_service(service_id): req_json = request.get_json() fetched_service = dao_fetch_service_by_id(service_id) # Capture the status change here as Marshmallow changes this later service_going_live = fetched_service.restricted and not req_json.get( "restricted", True) message_limit_changed = fetched_service.message_limit != req_json.get( "message_limit", fetched_service.message_limit) current_data = dict(service_schema.dump(fetched_service).data.items()) current_data.update(request.get_json()) service = service_schema.load(current_data).data if "email_branding" in req_json: email_branding_id = req_json["email_branding"] service.email_branding = None if not email_branding_id else EmailBranding.query.get( email_branding_id) if "letter_branding" in req_json: letter_branding_id = req_json["letter_branding"] service.letter_branding = None if not letter_branding_id else LetterBranding.query.get( letter_branding_id) dao_update_service(service) if message_limit_changed: redis_store.delete(daily_limit_cache_key(service_id)) redis_store.delete(near_daily_limit_cache_key(service_id)) redis_store.delete(over_daily_limit_cache_key(service_id)) if not fetched_service.restricted: _warn_service_users_about_message_limit_changed( service_id, current_data) if service_going_live: _warn_services_users_about_going_live(service_id, current_data) try: # Two scenarios, if there is a user that has requested to go live, we will use that user # to create a user-service/contact-deal pair between notify and zendesk sell # If by any chance there is no tracked request to a user, notify will try to identify the user # that created the service and then create a user-service/contact-deal relationship if service.go_live_user_id: user = get_user_by_id(service.go_live_user_id) else: user = dao_fetch_service_creator(service.id) ZenDeskSell().send_go_live_service(service, user) except Exception as e: current_app.logger.exception(e) return jsonify(data=service_schema.dump(fetched_service).data), 200
def update_service(service_id): req_json = request.get_json() fetched_service = dao_fetch_service_by_id(service_id) # Capture the status change here as Marshmallow changes this later service_going_live = fetched_service.restricted and not req_json.get('restricted', True) service_go_live_requested = 'go_live_user' in req_json current_data = dict(service_schema.dump(fetched_service).data.items()) current_data.update(request.get_json()) service = service_schema.load(current_data).data if 'email_branding' in req_json: email_branding_id = req_json['email_branding'] service.email_branding = None if not email_branding_id else EmailBranding.query.get(email_branding_id) if 'letter_branding' in req_json: letter_branding_id = req_json['letter_branding'] service.letter_branding = None if not letter_branding_id else LetterBranding.query.get(letter_branding_id) dao_update_service(service) if service_go_live_requested: template = dao_get_template_by_id(current_app.config['NOTIFY_ADMIN_OF_GO_LIVE_REQUEST_TEMPLATE_ID']) service_url = "{}/services/{}".format(current_app.config['ADMIN_BASE_URL'], str(service.id)) saved_notification = persist_notification( template_id=template.id, template_version=template.version, recipient=get_or_build_support_email_address(), service=template.service, personalisation={ 'service_name': service.name, 'service_dashboard_url': service_url }, notification_type=EMAIL_TYPE, api_key_id=None, key_type=KEY_TYPE_NORMAL, reply_to_text=get_or_build_support_email_address() ) send_notification_to_queue(saved_notification, research_mode=False, queue=QueueNames.NOTIFY) if service_going_live: send_notification_to_service_users( service_id=service_id, template_id=current_app.config['SERVICE_NOW_LIVE_TEMPLATE_ID'], personalisation={ 'service_name': current_data['name'], 'message_limit': '{:,}'.format(current_data['message_limit']) }, include_user_fields=['name'] ) return jsonify(data=service_schema.dump(fetched_service).data), 200
def create_smtp_relay(service_id): service = dao_fetch_service_by_id(service_id) alphabet = "1234567890abcdefghijklmnopqrstuvwxyz" if service.smtp_user is None: user_id = generate(alphabet, size=7) credentials = smtp_add(user_id) service.smtp_user = credentials["iam"] dao_update_service(service) return jsonify(credentials), 201 else: raise InvalidRequest(message="SMTP user already exists", status_code=500)
def test_should_remove_provider_from_service(notify_db_session, ses_provider): user = create_user() service = Service(name="service_name", email_from="email_from", message_limit=1000, restricted=False, created_by=user, email_provider_id=ses_provider.id) dao_create_service(service, user) stored_service = dao_fetch_service_by_id(service.id) stored_service.email_provider_id = None dao_update_service(service) updated_service = dao_fetch_service_by_id(service.id) assert not updated_service.email_provider_id
def populate_service_volume_intentions(file_name): # [0] service_id # [1] SMS:: volume intentions for service # [2] Email:: volume intentions for service # [3] Letters:: volume intentions for service with open(file_name, 'r') as f: for line in itertools.islice(f, 1, None): columns = line.split(',') print(columns) service = dao_fetch_service_by_id(columns[0]) service.volume_sms = columns[1] service.volume_email = columns[2] service.volume_letter = columns[3] dao_update_service(service) print("populate-service-volume-intentions complete")
def test_send_user_sms_code(notify_api, sample_user, sms_code_template, mocker, research_mode): """ Tests POST endpoint /user/<user_id>/sms-code """ with notify_api.test_request_context(): with notify_api.test_client() as client: if research_mode: notify_service = dao_fetch_service_by_id(current_app.config['NOTIFY_SERVICE_ID']) notify_service.research_mode = True dao_update_service(notify_service) data = json.dumps({}) auth_header = create_authorization_header() mocked = mocker.patch('app.user.rest.create_secret_code', return_value='11111') mocker.patch('app.celery.provider_tasks.deliver_sms.apply_async') resp = client.post( url_for('user.send_user_sms_code', user_id=sample_user.id), data=data, headers=[('Content-Type', 'application/json'), auth_header]) assert resp.status_code == 204 assert mocked.call_count == 1 assert VerifyCode.query.count() == 1 assert VerifyCode.query.first().check_code('11111') assert Notification.query.count() == 1 notification = Notification.query.first() assert notification.personalisation == {'verify_code': '11111'} assert notification.to == sample_user.mobile_number assert str(notification.service_id) == current_app.config['NOTIFY_SERVICE_ID'] app.celery.provider_tasks.deliver_sms.apply_async.assert_called_once_with( ([str(notification.id)]), queue="notify" )
def test_send_user_sms_code(client, sample_user, sms_code_template, mocker, research_mode): """ Tests POST endpoint /user/<user_id>/sms-code """ notify_service = dao_fetch_service_by_id( current_app.config["NOTIFY_SERVICE_ID"]) if research_mode: notify_service.research_mode = True dao_update_service(notify_service) auth_header = create_authorization_header() mocked = mocker.patch("app.user.rest.create_secret_code", return_value="11111") mocker.patch("app.celery.provider_tasks.deliver_sms.apply_async") resp = client.post( url_for("user.send_user_2fa_code", code_type="sms", user_id=sample_user.id), data=json.dumps({}), headers=[("Content-Type", "application/json"), auth_header], ) assert resp.status_code == 204 assert mocked.call_count == 1 assert VerifyCode.query.one().check_code("11111") notification = Notification.query.one() assert notification.personalisation == {"verify_code": "11111"} assert notification.to == sample_user.mobile_number assert str( notification.service_id) == current_app.config["NOTIFY_SERVICE_ID"] assert notification.reply_to_text == notify_service.get_default_sms_sender( ) app.celery.provider_tasks.deliver_sms.apply_async.assert_called_once_with( ([str(notification.id)]), queue="notify-internal-tasks")
def test_update_service_creates_a_history_record_with_current_data(sample_user): assert Service.query.count() == 0 assert Service.get_history_model().query.count() == 0 service = Service( name="service_name", email_from="email_from", message_limit=1000, restricted=False, created_by=sample_user ) dao_create_service(service, sample_user) assert Service.query.count() == 1 assert Service.query.first().version == 1 assert Service.get_history_model().query.count() == 1 service.name = "updated_service_name" dao_update_service(service) assert Service.query.count() == 1 assert Service.get_history_model().query.count() == 2 service_from_db = Service.query.first() assert service_from_db.version == 2 assert Service.get_history_model().query.filter_by(name="service_name").one().version == 1 assert Service.get_history_model().query.filter_by(name="updated_service_name").one().version == 2