2015-12-10 10:56:59 +00:00
|
|
|
import os
|
2017-04-12 17:56:55 +01:00
|
|
|
import random
|
|
|
|
|
import string
|
2016-11-10 13:22:38 +00:00
|
|
|
import uuid
|
2016-05-13 17:15:39 +01:00
|
|
|
|
2017-11-28 10:35:16 +00:00
|
|
|
from flask import _request_ctx_stack, request, g, jsonify
|
2017-08-18 15:39:39 +01:00
|
|
|
from flask_sqlalchemy import SQLAlchemy
|
2016-01-11 15:07:13 +00:00
|
|
|
from flask_marshmallow import Marshmallow
|
2017-11-06 12:34:29 +00:00
|
|
|
from flask_migrate import Migrate
|
2016-05-12 13:56:27 +01:00
|
|
|
from monotonic import monotonic
|
2018-01-17 14:36:02 +00:00
|
|
|
from notifications_utils.clients import DeskproClient
|
2016-12-01 17:20:05 +00:00
|
|
|
from notifications_utils.clients.statsd.statsd_client import StatsdClient
|
|
|
|
|
from notifications_utils.clients.redis.redis_client import RedisClient
|
2017-11-14 14:26:00 +00:00
|
|
|
from notifications_utils import logging, request_helper
|
2016-11-10 13:22:38 +00:00
|
|
|
from werkzeug.local import LocalProxy
|
|
|
|
|
|
2017-07-12 17:17:02 +01:00
|
|
|
from app.celery.celery import NotifyCelery
|
2016-05-06 09:47:06 +01:00
|
|
|
from app.clients import Clients
|
2016-11-10 13:22:38 +00:00
|
|
|
from app.clients.email.aws_ses import AwsSesClient
|
2016-02-17 12:57:51 +00:00
|
|
|
from app.clients.sms.firetext import FiretextClient
|
2016-05-11 11:34:46 +01:00
|
|
|
from app.clients.sms.loadtesting import LoadtestingClient
|
2016-11-10 13:22:38 +00:00
|
|
|
from app.clients.sms.mmg import MMGClient
|
2017-01-27 12:21:08 +00:00
|
|
|
from app.clients.performance_platform.performance_platform_client import PerformancePlatformClient
|
2016-02-16 15:28:30 +00:00
|
|
|
from app.encryption import Encryption
|
2016-07-05 15:38:20 +01:00
|
|
|
|
2016-11-21 15:16:21 +00:00
|
|
|
DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%fZ"
|
2016-03-09 11:06:37 +00:00
|
|
|
DATE_FORMAT = "%Y-%m-%d"
|
2016-03-08 17:45:37 +00:00
|
|
|
|
2016-01-07 17:31:17 +00:00
|
|
|
db = SQLAlchemy()
|
2017-11-06 12:34:29 +00:00
|
|
|
migrate = Migrate()
|
2016-01-11 15:07:13 +00:00
|
|
|
ma = Marshmallow()
|
2016-02-16 14:06:56 +00:00
|
|
|
notify_celery = NotifyCelery()
|
2016-02-17 12:57:51 +00:00
|
|
|
firetext_client = FiretextClient()
|
2016-05-11 11:34:46 +01:00
|
|
|
loadtest_client = LoadtestingClient()
|
2016-04-01 16:42:31 +01:00
|
|
|
mmg_client = MMGClient()
|
2016-02-17 17:48:23 +00:00
|
|
|
aws_ses_client = AwsSesClient()
|
2016-02-16 15:28:30 +00:00
|
|
|
encryption = Encryption()
|
2018-01-17 14:36:02 +00:00
|
|
|
deskpro_client = DeskproClient()
|
2016-05-13 17:15:39 +01:00
|
|
|
statsd_client = StatsdClient()
|
2016-11-10 11:50:49 +00:00
|
|
|
redis_store = RedisClient()
|
2017-01-27 12:21:08 +00:00
|
|
|
performance_platform_client = PerformancePlatformClient()
|
2016-01-07 17:31:17 +00:00
|
|
|
|
2016-05-06 09:47:06 +01:00
|
|
|
clients = Clients()
|
2016-05-06 09:09:47 +01:00
|
|
|
|
2015-12-15 10:47:20 +00:00
|
|
|
api_user = LocalProxy(lambda: _request_ctx_stack.top.api_user)
|
2017-05-05 15:20:23 +01:00
|
|
|
authenticated_service = LocalProxy(lambda: _request_ctx_stack.top.authenticated_service)
|
2015-12-15 10:47:20 +00:00
|
|
|
|
2015-12-10 10:56:59 +00:00
|
|
|
|
2017-11-06 12:34:29 +00:00
|
|
|
def create_app(application):
|
2016-12-08 12:12:45 +00:00
|
|
|
from app.config import configs
|
|
|
|
|
|
|
|
|
|
notify_environment = os.environ['NOTIFY_ENVIRONMENT']
|
2017-07-19 13:50:29 +01:00
|
|
|
|
2016-12-08 12:12:45 +00:00
|
|
|
application.config.from_object(configs[notify_environment])
|
|
|
|
|
|
2017-11-06 12:34:29 +00:00
|
|
|
application.config['NOTIFY_APP_NAME'] = application.name
|
2015-12-10 10:56:59 +00:00
|
|
|
|
2016-02-17 09:14:37 +00:00
|
|
|
init_app(application)
|
2017-11-14 14:26:00 +00:00
|
|
|
request_helper.init_app(application)
|
2016-01-07 17:31:17 +00:00
|
|
|
db.init_app(application)
|
2017-11-06 12:34:29 +00:00
|
|
|
migrate.init_app(application, db=db)
|
2016-01-11 15:07:13 +00:00
|
|
|
ma.init_app(application)
|
2018-01-17 14:36:02 +00:00
|
|
|
deskpro_client.init_app(application)
|
2016-05-13 17:15:39 +01:00
|
|
|
statsd_client.init_app(application)
|
2016-08-05 10:44:43 +01:00
|
|
|
logging.init_app(application, statsd_client)
|
2016-05-13 17:15:39 +01:00
|
|
|
firetext_client.init_app(application, statsd_client=statsd_client)
|
|
|
|
|
loadtest_client.init_app(application, statsd_client=statsd_client)
|
2016-06-01 15:24:19 +01:00
|
|
|
mmg_client.init_app(application, statsd_client=statsd_client)
|
2016-05-13 17:15:39 +01:00
|
|
|
aws_ses_client.init_app(application.config['AWS_REGION'], statsd_client=statsd_client)
|
2016-02-16 14:06:56 +00:00
|
|
|
notify_celery.init_app(application)
|
2016-02-16 15:28:30 +00:00
|
|
|
encryption.init_app(application)
|
2016-11-10 11:27:57 +00:00
|
|
|
redis_store.init_app(application)
|
2017-01-30 18:24:06 +00:00
|
|
|
performance_platform_client.init_app(application)
|
2016-05-11 11:34:46 +01:00
|
|
|
clients.init_app(sms_clients=[firetext_client, mmg_client, loadtest_client], email_clients=[aws_ses_client])
|
2016-02-09 13:31:45 +00:00
|
|
|
|
2016-10-27 11:46:37 +01:00
|
|
|
register_blueprint(application)
|
|
|
|
|
register_v2_blueprints(application)
|
|
|
|
|
|
2018-02-05 14:58:02 +00:00
|
|
|
# avoid circular imports by importing this file later
|
2017-11-06 12:34:29 +00:00
|
|
|
from app.commands import setup_commands
|
|
|
|
|
setup_commands(application)
|
|
|
|
|
|
2016-10-27 11:46:37 +01:00
|
|
|
return application
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def register_blueprint(application):
|
2016-08-19 17:30:25 +01:00
|
|
|
from app.service.rest import service_blueprint
|
2017-11-29 16:28:01 +00:00
|
|
|
from app.service.callback_rest import service_callback_blueprint
|
2017-03-16 18:15:49 +00:00
|
|
|
from app.user.rest import user_blueprint
|
|
|
|
|
from app.template.rest import template_blueprint
|
2016-01-14 16:13:27 +00:00
|
|
|
from app.status.healthcheck import status as status_blueprint
|
2017-03-16 18:15:49 +00:00
|
|
|
from app.job.rest import job_blueprint
|
2016-01-19 11:23:09 +00:00
|
|
|
from app.notifications.rest import notifications as notifications_blueprint
|
2016-02-24 14:01:19 +00:00
|
|
|
from app.invite.rest import invite as invite_blueprint
|
2016-02-29 17:38:02 +00:00
|
|
|
from app.accept_invite.rest import accept_invite
|
2016-04-04 12:21:38 +01:00
|
|
|
from app.template_statistics.rest import template_statistics as template_statistics_blueprint
|
2016-04-27 10:27:05 +01:00
|
|
|
from app.events.rest import events as events_blueprint
|
2016-05-10 09:04:22 +01:00
|
|
|
from app.provider_details.rest import provider_details as provider_details_blueprint
|
2016-08-05 15:48:06 +01:00
|
|
|
from app.organisation.rest import organisation_blueprint
|
2017-04-21 12:39:42 +01:00
|
|
|
from app.dvla_organisation.rest import dvla_organisation_blueprint
|
2016-09-22 14:01:25 +01:00
|
|
|
from app.delivery.rest import delivery_blueprint
|
2017-08-04 19:26:51 +01:00
|
|
|
from app.inbound_number.rest import inbound_number_blueprint
|
2017-05-31 14:49:14 +01:00
|
|
|
from app.inbound_sms.rest import inbound_sms as inbound_sms_blueprint
|
2017-03-16 18:15:49 +00:00
|
|
|
from app.notifications.receive_notifications import receive_notifications_blueprint
|
|
|
|
|
from app.notifications.notifications_sms_callback import sms_callback_blueprint
|
2017-04-25 14:56:16 +01:00
|
|
|
from app.notifications.notifications_letter_callback import letter_callback_blueprint
|
2017-11-28 10:35:16 +00:00
|
|
|
from app.authentication.auth import requires_admin_auth, requires_auth, requires_no_auth
|
2017-08-21 14:33:08 +01:00
|
|
|
from app.letters.rest import letter_job
|
2017-08-15 17:26:10 +01:00
|
|
|
from app.billing.rest import billing_blueprint
|
2016-01-15 15:48:05 +00:00
|
|
|
|
2017-03-16 18:15:49 +00:00
|
|
|
service_blueprint.before_request(requires_admin_auth)
|
2016-01-08 17:51:46 +00:00
|
|
|
application.register_blueprint(service_blueprint, url_prefix='/service')
|
2017-03-16 18:15:49 +00:00
|
|
|
|
|
|
|
|
user_blueprint.before_request(requires_admin_auth)
|
2016-01-08 17:51:46 +00:00
|
|
|
application.register_blueprint(user_blueprint, url_prefix='/user')
|
2017-03-16 18:15:49 +00:00
|
|
|
|
|
|
|
|
template_blueprint.before_request(requires_admin_auth)
|
2016-02-22 12:55:18 +00:00
|
|
|
application.register_blueprint(template_blueprint)
|
2017-03-16 18:15:49 +00:00
|
|
|
|
|
|
|
|
status_blueprint.before_request(requires_no_auth)
|
2016-03-03 15:18:12 +00:00
|
|
|
application.register_blueprint(status_blueprint)
|
2017-03-16 18:15:49 +00:00
|
|
|
|
2017-10-16 13:23:19 +01:00
|
|
|
# delivery receipts
|
|
|
|
|
# TODO: make sure research mode can still trigger sms callbacks, then re-enable this
|
|
|
|
|
sms_callback_blueprint.before_request(requires_no_auth)
|
2017-03-16 18:15:49 +00:00
|
|
|
application.register_blueprint(sms_callback_blueprint)
|
|
|
|
|
|
2017-10-16 13:23:19 +01:00
|
|
|
# inbound sms
|
2017-11-10 12:05:06 +00:00
|
|
|
receive_notifications_blueprint.before_request(requires_no_auth)
|
2017-03-16 18:15:49 +00:00
|
|
|
application.register_blueprint(receive_notifications_blueprint)
|
|
|
|
|
|
|
|
|
|
notifications_blueprint.before_request(requires_auth)
|
2016-02-24 17:12:30 +00:00
|
|
|
application.register_blueprint(notifications_blueprint)
|
2017-03-16 18:15:49 +00:00
|
|
|
|
|
|
|
|
job_blueprint.before_request(requires_admin_auth)
|
2016-01-18 09:57:04 +00:00
|
|
|
application.register_blueprint(job_blueprint)
|
2017-03-16 18:15:49 +00:00
|
|
|
|
|
|
|
|
invite_blueprint.before_request(requires_admin_auth)
|
2016-02-24 14:01:19 +00:00
|
|
|
application.register_blueprint(invite_blueprint)
|
2017-03-16 18:15:49 +00:00
|
|
|
|
|
|
|
|
delivery_blueprint.before_request(requires_admin_auth)
|
2016-09-22 14:01:25 +01:00
|
|
|
application.register_blueprint(delivery_blueprint)
|
2017-03-16 18:15:49 +00:00
|
|
|
|
2017-08-04 19:26:51 +01:00
|
|
|
inbound_number_blueprint.before_request(requires_admin_auth)
|
2017-08-14 12:46:04 +01:00
|
|
|
application.register_blueprint(inbound_number_blueprint)
|
2017-08-04 19:26:51 +01:00
|
|
|
|
2017-05-31 14:49:14 +01:00
|
|
|
inbound_sms_blueprint.before_request(requires_admin_auth)
|
|
|
|
|
application.register_blueprint(inbound_sms_blueprint)
|
|
|
|
|
|
2017-03-16 18:15:49 +00:00
|
|
|
accept_invite.before_request(requires_admin_auth)
|
2016-02-29 17:38:02 +00:00
|
|
|
application.register_blueprint(accept_invite, url_prefix='/invite')
|
2017-03-16 18:15:49 +00:00
|
|
|
|
|
|
|
|
template_statistics_blueprint.before_request(requires_admin_auth)
|
2016-04-04 12:21:38 +01:00
|
|
|
application.register_blueprint(template_statistics_blueprint)
|
2017-03-16 18:15:49 +00:00
|
|
|
|
|
|
|
|
events_blueprint.before_request(requires_admin_auth)
|
2016-04-27 10:27:05 +01:00
|
|
|
application.register_blueprint(events_blueprint)
|
2017-03-16 18:15:49 +00:00
|
|
|
|
|
|
|
|
provider_details_blueprint.before_request(requires_admin_auth)
|
2016-05-10 09:04:22 +01:00
|
|
|
application.register_blueprint(provider_details_blueprint, url_prefix='/provider-details')
|
2017-03-16 18:15:49 +00:00
|
|
|
|
|
|
|
|
organisation_blueprint.before_request(requires_admin_auth)
|
2016-08-05 15:48:06 +01:00
|
|
|
application.register_blueprint(organisation_blueprint, url_prefix='/organisation')
|
2015-12-15 17:14:13 +00:00
|
|
|
|
2017-04-21 12:39:42 +01:00
|
|
|
dvla_organisation_blueprint.before_request(requires_admin_auth)
|
|
|
|
|
application.register_blueprint(dvla_organisation_blueprint, url_prefix='/dvla_organisations')
|
|
|
|
|
|
2017-04-06 12:14:17 +01:00
|
|
|
letter_job.before_request(requires_admin_auth)
|
|
|
|
|
application.register_blueprint(letter_job)
|
|
|
|
|
|
2017-04-25 14:56:16 +01:00
|
|
|
letter_callback_blueprint.before_request(requires_no_auth)
|
|
|
|
|
application.register_blueprint(letter_callback_blueprint)
|
|
|
|
|
|
2017-08-15 17:26:10 +01:00
|
|
|
billing_blueprint.before_request(requires_admin_auth)
|
|
|
|
|
application.register_blueprint(billing_blueprint)
|
2017-11-29 16:28:01 +00:00
|
|
|
|
|
|
|
|
service_callback_blueprint.before_request(requires_admin_auth)
|
|
|
|
|
application.register_blueprint(service_callback_blueprint)
|
2017-08-15 17:26:10 +01:00
|
|
|
|
2016-10-27 11:46:37 +01:00
|
|
|
|
|
|
|
|
def register_v2_blueprints(application):
|
2017-11-03 16:35:22 +00:00
|
|
|
from app.v2.inbound_sms.get_inbound_sms import v2_inbound_sms_blueprint as get_inbound_sms
|
2017-03-22 10:54:15 +00:00
|
|
|
from app.v2.notifications.post_notifications import v2_notification_blueprint as post_notifications
|
|
|
|
|
from app.v2.notifications.get_notifications import v2_notification_blueprint as get_notifications
|
|
|
|
|
from app.v2.template.get_template import v2_template_blueprint as get_template
|
2017-03-28 10:41:25 +01:00
|
|
|
from app.v2.templates.get_templates import v2_templates_blueprint as get_templates
|
2017-03-22 10:54:15 +00:00
|
|
|
from app.v2.template.post_template import v2_template_blueprint as post_template
|
|
|
|
|
from app.authentication.auth import requires_auth
|
2016-11-18 17:36:11 +00:00
|
|
|
|
2017-03-16 18:15:49 +00:00
|
|
|
post_notifications.before_request(requires_auth)
|
2016-11-18 17:36:11 +00:00
|
|
|
application.register_blueprint(post_notifications)
|
2017-03-16 18:15:49 +00:00
|
|
|
|
|
|
|
|
get_notifications.before_request(requires_auth)
|
2016-11-18 17:36:11 +00:00
|
|
|
application.register_blueprint(get_notifications)
|
2017-03-22 10:54:15 +00:00
|
|
|
|
2017-03-28 10:41:25 +01:00
|
|
|
get_templates.before_request(requires_auth)
|
|
|
|
|
application.register_blueprint(get_templates)
|
|
|
|
|
|
2017-03-22 10:54:15 +00:00
|
|
|
get_template.before_request(requires_auth)
|
2017-03-22 10:09:14 +00:00
|
|
|
application.register_blueprint(get_template)
|
2017-03-22 10:54:15 +00:00
|
|
|
|
|
|
|
|
post_template.before_request(requires_auth)
|
2017-03-22 10:09:14 +00:00
|
|
|
application.register_blueprint(post_template)
|
2015-12-10 10:56:59 +00:00
|
|
|
|
2017-11-03 16:35:22 +00:00
|
|
|
get_inbound_sms.before_request(requires_auth)
|
|
|
|
|
application.register_blueprint(get_inbound_sms)
|
|
|
|
|
|
2016-01-14 17:45:30 +00:00
|
|
|
|
2017-03-17 16:21:41 +00:00
|
|
|
def init_app(app):
|
2016-11-25 13:27:36 +00:00
|
|
|
@app.before_request
|
|
|
|
|
def record_user_agent():
|
|
|
|
|
statsd_client.incr("user-agent.{}".format(process_user_agent(request.headers.get('User-Agent', None))))
|
|
|
|
|
|
2017-11-14 14:26:00 +00:00
|
|
|
app.before_request(request_helper.check_proxy_header_before_request)
|
|
|
|
|
|
2016-05-12 13:56:27 +01:00
|
|
|
@app.before_request
|
2016-08-05 10:44:43 +01:00
|
|
|
def record_request_details():
|
2016-05-12 13:56:27 +01:00
|
|
|
g.start = monotonic()
|
2016-08-05 10:44:43 +01:00
|
|
|
g.endpoint = request.endpoint
|
2016-05-12 13:56:27 +01:00
|
|
|
|
2016-01-20 15:28:39 +00:00
|
|
|
@app.after_request
|
|
|
|
|
def after_request(response):
|
2016-01-20 15:51:13 +00:00
|
|
|
response.headers.add('Access-Control-Allow-Origin', '*')
|
|
|
|
|
response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')
|
|
|
|
|
response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE')
|
|
|
|
|
return response
|
2016-01-20 15:28:39 +00:00
|
|
|
|
2016-11-24 17:09:56 +00:00
|
|
|
@app.errorhandler(Exception)
|
|
|
|
|
def exception(error):
|
|
|
|
|
app.logger.exception(error)
|
|
|
|
|
# error.code is set for our exception types.
|
|
|
|
|
return jsonify(result='error', message=error.message), error.code or 500
|
|
|
|
|
|
2016-10-27 11:46:37 +01:00
|
|
|
@app.errorhandler(404)
|
|
|
|
|
def page_not_found(e):
|
|
|
|
|
msg = e.description or "Not found"
|
|
|
|
|
app.logger.exception(msg)
|
|
|
|
|
return jsonify(result='error', message=msg), 404
|
|
|
|
|
|
2015-12-10 10:56:59 +00:00
|
|
|
|
2016-02-24 17:12:30 +00:00
|
|
|
def create_uuid():
|
|
|
|
|
return str(uuid.uuid4())
|
2016-11-25 13:27:36 +00:00
|
|
|
|
|
|
|
|
|
2017-04-12 17:56:55 +01:00
|
|
|
def create_random_identifier():
|
2017-04-20 10:55:53 +01:00
|
|
|
return ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(16))
|
2017-04-12 17:56:55 +01:00
|
|
|
|
|
|
|
|
|
2016-11-25 13:27:36 +00:00
|
|
|
def process_user_agent(user_agent_string):
|
|
|
|
|
if user_agent_string and user_agent_string.lower().startswith("notify"):
|
|
|
|
|
components = user_agent_string.split("/")
|
|
|
|
|
client_name = components[0].lower()
|
|
|
|
|
client_version = components[1].replace(".", "-")
|
|
|
|
|
return "{}.{}".format(client_name, client_version)
|
|
|
|
|
elif user_agent_string and not user_agent_string.lower().startswith("notify"):
|
|
|
|
|
return "non-notify-user-agent"
|
|
|
|
|
else:
|
|
|
|
|
return "unknown"
|