"""Application Handlers. Requests are redirected to handlers, which are responsible for getting information from the URL and passing it down to the logic layer. The way each layer talks to each other is through Response objects which defines the type status of the data and the data itself. Please note: the Orchard uses the term handlers over views as convention for clarity See: oto.response for more details. """ from flask import g from flask import jsonify from flask import request from oto import response from oto.adaptors.flask import flaskify from feature_fm import config from feature_fm.api import app from feature_fm.constants import error from feature_fm.constants.header import CUSTOM_ACCOUNT_TYPES from feature_fm.logic import ows_services from feature_fm.utils import handler_utils @app.route('///artists') def get_artists(account_type, account_id): """Get a paginated list of artists for a label/subaccount. Args: account_type (str): the account type (label or subaccount) account_id (int): The account id (e.g. 7123) Returns: flask.Response: with the artists payload """ account_type = CUSTOM_ACCOUNT_TYPES.get(account_type) timestamp = request.args.get('timestamp') token = request.args.get('token') page_limit = request.args.get('page_limit') page_offset = request.args.get('page_offset') updated_since = request.args.get('updated_since') access_validation = handler_utils.access_validation( request, account_type, account_id) if not access_validation: return flaskify(access_validation) is_token_verified = handler_utils.validate_token(request, timestamp, token) if not is_token_verified: return flaskify(response.create_error_response( code=error.ERROR_CODE_AUTHORIZATION, message=error.ERROR_MESSAGE_INVALID_TOKEN, status=400)) return flaskify( ows_services.get_artists( account_type, account_id, page_limit, page_offset, updated_since)) @app.route('///artists', methods=['POST']) def get_artists_bulk(account_type, account_id): """Get a list of artists for a specified list of artist ids. Args: account_type (str): the account type (label or subaccount) account_id (int): The account id (e.g. 7123) Returns: flask.Response: with the artists payload """ account_type = CUSTOM_ACCOUNT_TYPES.get(account_type) timestamp = request.args.get('timestamp') token = request.args.get('token') access_validation = handler_utils.access_validation( request, account_type, account_id) if not access_validation: return flaskify(access_validation) is_token_verified = handler_utils.validate_token(request, timestamp, token) if not is_token_verified: return flaskify(response.create_error_response( code=error.ERROR_CODE_AUTHORIZATION, message=error.ERROR_MESSAGE_INVALID_TOKEN, status=400)) data = request.get_json(silent=True, force=True) or {} artist_ids = data.get('artist_ids') if not artist_ids: return flaskify(response.create_error_response( code=error.ERROR_CODE_BAD_REQUEST, message=error.ERROR_MESSAGE_MISSING_PARAMETERS, status=400)) return flaskify( ows_services.get_artists_bulk(account_type, account_id, artist_ids)) @app.route('///artist/') def get_artist_by_id(account_type, account_id, artist_id): """Get artist information by id. Args: account_type (str): the account type (label or subaccount) account_id (int): The account id (e.g. 7123) artist_id (int): The artist id (e.g. 111) Returns: flask.Response: with the artist payload """ account_type = CUSTOM_ACCOUNT_TYPES.get(account_type) timestamp = request.args.get('timestamp') token = request.args.get('token') access_validation = handler_utils.access_validation( request, account_type, account_id) if not access_validation: return flaskify(access_validation) is_token_verified = handler_utils.validate_token(request, timestamp, token) if not is_token_verified: return flaskify(response.create_error_response( code=error.ERROR_CODE_AUTHORIZATION, message=error.ERROR_MESSAGE_INVALID_TOKEN, status=400)) return flaskify( ows_services.get_artist_by_id(account_type, account_id, artist_id)) @app.route( '///artists//releases') def get_artist_releases(account_type, account_id, artist_id): """Get a paginated list of releases for an artist. Args: account_type (str): the account type (label or subaccount) account_id (int): The account id (e.g. 7123) artist_id (int): the artist id. Returns: flask.Response: with the releases payload """ account_type = CUSTOM_ACCOUNT_TYPES.get(account_type) timestamp = request.args.get('timestamp') token = request.args.get('token') search_term = request.args.get('search_term') page_limit = request.args.get('page_limit') access_validation = handler_utils.access_validation( request, account_type, account_id) if not access_validation: return flaskify(access_validation) is_token_verified = handler_utils.validate_token(request, timestamp, token) if not is_token_verified: return flaskify(response.create_error_response( code=error.ERROR_CODE_AUTHORIZATION, message=error.ERROR_MESSAGE_INVALID_TOKEN, status=400)) return flaskify( ows_services.get_artist_releases( account_type, account_id, artist_id, search_term, page_limit)) @app.route( '///releases') def get_label_releases(account_type, account_id): """Get a paginated list of releases for a label. Args: account_type (str): the account type (label or subaccount) account_id (int): The account id (e.g. 7123) Returns: flask.Response: with the releases payload """ account_type = CUSTOM_ACCOUNT_TYPES.get(account_type) timestamp = request.args.get('timestamp') token = request.args.get('token') search_term = request.args.get('search_term') page_limit = request.args.get('page_limit') access_validation = handler_utils.access_validation( request, account_type, account_id) if not access_validation: return flaskify(access_validation) is_token_verified = handler_utils.validate_token(request, timestamp, token) if not is_token_verified: return flaskify(response.create_error_response( code=error.ERROR_CODE_AUTHORIZATION, message=error.ERROR_MESSAGE_INVALID_TOKEN, status=400)) return flaskify( ows_services.get_label_releases( account_type, account_id, search_term, page_limit)) @app.route('///users/') def get_user_info(account_type, account_id, user_id): """Get a user's info. Args: account_type (str): the account type (label or subaccount) account_id (int): the account id (e.g. 7123) user_id (str): the user id Returns: flask.Response: with the user's info """ account_type = CUSTOM_ACCOUNT_TYPES.get(account_type) timestamp = request.args.get('timestamp') token = request.args.get('token') fetch_artists = request.args.get('fetch_artists') access_validation = handler_utils.access_validation( request, account_type, account_id) if not access_validation: return flaskify(access_validation) is_token_verified = handler_utils.validate_token(request, timestamp, token) if fetch_artists: if fetch_artists == 'false': fetch_artists = False elif fetch_artists == 'true': fetch_artists = True else: fetch_artists = None if is_token_verified: correlation_id = g.correlation_id return flaskify(ows_services.get_user_info( account_type, account_id, user_id, fetch_artists, correlation_id)) return flaskify(response.create_error_response( code=error.ERROR_CODE_AUTHORIZATION, message=error.ERROR_MESSAGE_INVALID_TOKEN, status=400)) @app.route('///campaign-budget') def get_campaign_budget(account_type, account_id): """Get the monthly campaign budget for a label or subaccount. Args: account_type (str): The account type (label or subaccount). account_id (int): The account id (e.g. 7123). Returns: flask.Response: Containing the monthly campaign budget. """ account_type = CUSTOM_ACCOUNT_TYPES.get(account_type) timestamp = request.args.get('timestamp') token = request.args.get('token') access_validation = handler_utils.access_validation( request, account_type, account_id) if not access_validation: return flaskify(access_validation) is_token_verified = handler_utils.validate_token(request, timestamp, token) if not is_token_verified: return flaskify(response.create_error_response( code=error.ERROR_CODE_AUTHORIZATION, message=error.ERROR_MESSAGE_INVALID_TOKEN, status=400)) return flaskify(ows_services.get_campaign_budget( account_type, account_id)) @app.route('/budget-caps', methods=['GET']) def get_budget_caps(): """Get budget caps for all the labels. Returns: flask.Response: Containing the budget caps. """ timestamp = request.args.get('timestamp') token = request.args.get('token') is_token_verified = handler_utils.validate_token(request, timestamp, token) if not is_token_verified: return flaskify(response.create_error_response( code=error.ERROR_CODE_AUTHORIZATION, message=error.ERROR_MESSAGE_INVALID_TOKEN, status=400)) return flaskify(ows_services.get_budget_caps()) @app.route(config.HEALTH_CHECK, methods=['GET']) def health(): """Check the health of the application.""" return jsonify({'status': 'ok'}) @app.errorhandler(500) def exception_handler(error): """Handle error when uncaught exception is raised. Default exception handler. Note: Exception will also be sent to Sentry if config.SENTRY is set. Returns: flask.Response: A 500 response with JSON 'code' & 'message' payload. """ message = ( 'The server encountered an internal error ' 'and was unable to complete your request.') g.log.exception(error) return flaskify(response.create_fatal_response(message))