"""Application. The API application is a `flask` application. It provides simple features such as registering a url for a specific handlers. """ from abacus_common_logic.connectors.database import db from abacus_common_logic.marshalling.custom_fields import ma from abacus_common_logic.utils.users import set_flask_user_details_from_headers from flask import Flask from owslogger import flask_logger from owsrequest import flask_request from owsresponse import response from owsresponse.adaptors.flask import flaskify from werkzeug.exceptions import HTTPException, InternalServerError def create_app(config): """Create an app.""" app = Flask(config.SERVICE_NAME) app.config.from_object(config) app.url_map.strict_slashes = False setup_application_log(app, config) setup_owsrequest(app, config) setup_db(app, config) setup_marshmallow(app) register_blueprints(app) register_error_handlers(app) register_request_handler(app) return app def setup_owsrequest(app, config): """Set up request framework.""" try: import uwsgi # noqa uwsgiRunning = True except ImportError: uwsgiRunning = False flask_request.set_rules_validator(app, 'abacus_contract/access_rules.yml') flask_request.setup( app, config.ENVIRONMENT, add_request_context=True, label_profile=True, verify_access=False, rules_file=None, access_log_only=config.ONLY_LOG_ACCESS_ERRORS, exclude_paths=[config.HEALTH_CHECK], uwsgi_cache_enabled=uwsgiRunning ) def setup_application_log(app, config): """Set up the application log.""" flask_logger.setup( app, config.ENVIRONMENT, config.LOGGER_NAME, config.LOGGER_LEVEL, config.SERVICE_NAME, config.SERVICE_VERSION, exclude_paths=[config.HEALTH_CHECK]) def setup_db(app, config): """Set up the database.""" app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.config['SQLALCHEMY_DATABASE_URI'] = \ 'mysql+pymysql://{}:{}@{}:{}/{}?charset=UTF8MB4'.format( config.MYSQL_DB_USER, config.MYSQL_DB_PASS, config.MYSQL_DB_HOST, config.MYSQL_DB_PORT, config.MYSQL_DB_NAME) db.init_app(app) def setup_marshmallow(app): """Set up marshmallow.""" ma.init_app(app) def register_blueprints(app): """Register blueprints.""" from abacus_contract.blueprints.base import base_api from abacus_contract.blueprints.contract import contract_api from abacus_contract.blueprints.contract_advance import contract_advance_api from abacus_contract.blueprints.contract_flowthrough import contract_flowthrough_api from abacus_contract.blueprints.contract_lifecycle_schedule_detail \ import contract_lifecycle_schedule_detail_api from abacus_contract.blueprints.contract_lifecycle_schedule \ import contract_lifecycle_schedule_api from abacus_contract.blueprints.contract_lifecycle import contract_lifecycle_api from abacus_contract.blueprints.contract_mechanical_deduction import \ contract_mechanical_deduction_api from abacus_contract.blueprints.contract_party import contract_party_api from abacus_contract.blueprints.contract_reserve import contract_reserve_api from abacus_contract.blueprints.contract_template import contract_template_api from abacus_contract.blueprints.contract_term import contract_term_api from abacus_contract.blueprints.contract_term_condition import contract_term_condition_api # noqa: E501 from abacus_contract.blueprints.contract_term_schedule import contract_term_schedule_api # noqa: E501 from abacus_contract.blueprints.contract_exclusion import contract_exclusion_api from abacus_contract.blueprints.legacy_contract import legacy_contract_api from abacus_contract.blueprints.reference_flowthrough_calculation \ import reference_flowthrough_calculation_api from abacus_contract.blueprints.reference_mechanical_rate \ import reference_mechanical_rate_api from abacus_contract.blueprints.reference_payment_entity \ import reference_payment_entity_api from abacus_contract.blueprints.reference_payment_type \ import reference_payment_type_api from abacus_contract.blueprints.reference_sap_profit_center \ import reference_sap_profit_center_api from abacus_contract.blueprints.reference_signing_entity \ import reference_signing_entity_api from abacus_contract.blueprints.reference_transaction_type \ import reference_transaction_type_api from abacus_contract.blueprints.reference_transaction_type_group \ import reference_transaction_type_group_api app.register_blueprint(base_api) app.register_blueprint(contract_api) app.register_blueprint(contract_advance_api) app.register_blueprint(contract_flowthrough_api) app.register_blueprint(contract_lifecycle_schedule_detail_api) app.register_blueprint(contract_lifecycle_schedule_api) app.register_blueprint(contract_lifecycle_api) app.register_blueprint(contract_mechanical_deduction_api) app.register_blueprint(contract_party_api) app.register_blueprint(contract_reserve_api) app.register_blueprint(contract_template_api) app.register_blueprint(contract_term_api) app.register_blueprint(contract_term_condition_api) app.register_blueprint(contract_term_schedule_api) app.register_blueprint(contract_exclusion_api) app.register_blueprint(legacy_contract_api) app.register_blueprint(reference_flowthrough_calculation_api) app.register_blueprint(reference_mechanical_rate_api) app.register_blueprint(reference_payment_entity_api) app.register_blueprint(reference_payment_type_api) app.register_blueprint(reference_sap_profit_center_api) app.register_blueprint(reference_signing_entity_api) app.register_blueprint(reference_transaction_type_api) app.register_blueprint(reference_transaction_type_group_api) def register_error_handlers(app): """Register error handlers.""" def http_error_handler(error): """Handle http errors.""" return flaskify(response.create_error_response( message=error.description, status=error.code, code='error')) app.register_error_handler(HTTPException, http_error_handler) def exception_handler(_): """Handle exceptions.""" message = ( 'The server encountered an internal error ' 'and was unable to complete your request.') return flaskify(response.create_fatal_response(message)) app.register_error_handler(InternalServerError, exception_handler) def register_request_handler(app): """Register function to preprocess request data.""" @app.before_request def before_request_start(): set_flask_user_details_from_headers()