"""Blueprint for account payee API.""" from abacus_common_logic.utils.authorization import permissions_authorize_many_accounts from abacus_common_logic.views.create_view import CreateView from abacus_common_logic.views.item_view import ItemView from abacus_common_logic.views.list_view import ListView from flask import Blueprint from flask import g from flask import request from owsrequest import flask_request from owsresponse import response from owsresponse.adaptors.flask import flaskify from abacus_account.config import ows_client from abacus_account.constants import error from abacus_account.logic import account_payee as logic from abacus_account.logic.account_payee_dataload import ( format_payees_for_dataloader, get_payees_by_account_ids, get_payees_by_ids, ) from abacus_account.models.account_payee import AccountPayee from abacus_account.schemas.account_payee import AccountPayeeDetailSchema, \ AccountPayeePostSchema, AccountPayeePutSchema from abacus_account.utils.authorization import authorize_many_accounts from abacus_account.utils.format_error import validation_error from abacus_account.utils.request import get_optional_numeric_list_from_params account_payee_api = Blueprint('account_payee_api', __name__) class AccountPayeeByAccountIdList(ListView): """View for listing accounts payee by account ids.""" model_class = AccountPayee list_entry_schema = AccountPayeeDetailSchema() def post(self): """Get payees by account ids. NOTE: This endpoint uses a POST method to allow for a larger list of query args. """ try: account_ids = get_optional_numeric_list_from_params() if not account_ids: return flaskify(validation_error(error.ERROR_INVALID_IDS.format( object='Account'))) except ValueError: return flaskify(validation_error(error.ERROR_INVALID_IDS.format( object='Account'))) access_rule_decision = flask_request.verify_rules_access_standalone(request) if not access_rule_decision: authorized = authorize_many_accounts(account_ids) if not authorized: return flaskify(response.create_error_response( code=error.ERROR_CODE_AUTHORIZATION, message='Unauthorized', status=403, )) authorized = permissions_authorize_many_accounts( ows_client, g.request_context.profile_type, g.request_context.profile_id, account_ids ) if not authorized: return flaskify(response.create_error_response( code=error.ERROR_CODE_FORBIDDEN, message=error.ERROR_MESSAGE_FORBIDDEN_USER, status=403 )) payees = get_payees_by_account_ids(account_ids) return flaskify(format_payees_for_dataloader( input_ids=account_ids, payees_list=payees, key='account_id' )) class AccountPayeeList(ListView): """View for listing accounts payee by payee ids.""" model_class = AccountPayee list_entry_schema = AccountPayeeDetailSchema() def post(self): """Get payees by ids. NOTE: This endpoint uses a POST method to allow for a larger list of query args. """ try: account_payee_ids = get_optional_numeric_list_from_params() if not account_payee_ids: return flaskify(validation_error(error.ERROR_INVALID_IDS.format( object='AccountPayee'))) except ValueError: return flaskify(validation_error(error.ERROR_INVALID_IDS.format( object='AccountPayee'))) # Since we are authorizing accounts via PDP, we need to load the payees # along with their account IDs to authorize them. # Eventually, payees can be defined as a new resource_type and # can be authorized via hierarchy if needed. payees = get_payees_by_ids(account_payee_ids) account_ids = [payee.get('account_id') for payee in payees] access_rule_decision = flask_request.verify_rules_access_standalone(request) if not access_rule_decision: authorized = authorize_many_accounts(account_ids) if not authorized: return flaskify(response.create_error_response( code=error.ERROR_CODE_AUTHORIZATION, message='Unauthorized', status=403, )) authorized = permissions_authorize_many_accounts( ows_client, g.request_context.profile_type, g.request_context.profile_id, account_ids ) if not authorized: return flaskify(response.create_error_response( code=error.ERROR_CODE_FORBIDDEN, message=error.ERROR_MESSAGE_FORBIDDEN_USER, status=403 )) return flaskify(format_payees_for_dataloader( input_ids=account_payee_ids, payees_list=payees, key='account_payee_id' )) account_payee_api.add_url_rule( '/account-payee/dataloader/account', methods=['POST'], view_func=AccountPayeeByAccountIdList.as_view('list_payees_by_account_ids'), ) account_payee_api.add_url_rule( '/account-payee/dataloader', methods=['POST'], view_func=AccountPayeeList.as_view('list_payees') ) class AccountPayeeItemView(ItemView): """View for finding an account_payee by ID.""" model_class = AccountPayee object_detail_schema = AccountPayeeDetailSchema() put_schema = AccountPayeePutSchema() def get(self, object_id, **kwargs): """Get account payee by id.""" account_payee_response = super().get(object_id, **kwargs) account_id = account_payee_response.get_json().get('account_id') access_rule_decision = flask_request.verify_rules_access_standalone(request) if not access_rule_decision: return flaskify(response.create_error_response( code=error.ERROR_CODE_AUTHORIZATION, message='Unauthorized', status=401, )) authorized = permissions_authorize_many_accounts( ows_client, g.request_context.profile_type, g.request_context.profile_id, [account_id] ) if not authorized: return flaskify(response.create_error_response( code=error.ERROR_CODE_FORBIDDEN, message=error.ERROR_MESSAGE_FORBIDDEN_USER, status=403 )) return account_payee_response def put(self, object_id, **kwargs): """Update account_payee by id.""" access_rule_decision = flask_request.verify_rules_access_standalone(request) if not access_rule_decision: return flaskify(response.create_error_response( code=error.ERROR_CODE_AUTHORIZATION, message='Unauthorized', status=401, )) return super().put(object_id, **kwargs) def update_handler(self, obj, **params): """Update account_payee.""" return logic.update_account_payee(obj, **params) class AccountPayeeCreateView(CreateView): """Handles account creation.""" post_schema = AccountPayeePostSchema(exclude=('payoneer_program_id',)) def post(self, **kwargs): """Create an account payee.""" access_rule_decision = flask_request.verify_rules_access_standalone(request) if not access_rule_decision: return flaskify(response.create_error_response( code=error.ERROR_CODE_AUTHORIZATION, message='Unauthorized', status=401, )) return super().post(**kwargs) def create_handler(self, **params): """Create an account.""" return logic.create_account_payee(**params) account_payee_api.add_url_rule( '/account-payee/', methods=['GET', 'PUT'], view_func=AccountPayeeItemView.as_view('account_payee') ) account_payee_api.add_url_rule( '/account-payee', view_func=AccountPayeeCreateView.as_view('create_account_payee') ) @account_payee_api.route( '/account//account-payee/', methods=['GET'] ) def get_account_payee_by_account_id(object_id): """Endpoint to GET account_payee for a specified account.""" access_rule_decision = flask_request.verify_rules_access_standalone(request) if not access_rule_decision: return flaskify(response.create_error_response( code=error.ERROR_CODE_AUTHORIZATION, message='Unauthorized', status=401, )) authorized = permissions_authorize_many_accounts( ows_client, g.request_context.profile_type, g.request_context.profile_id, [object_id] ) if not authorized: return flaskify(response.create_error_response( code=error.ERROR_CODE_FORBIDDEN, message=error.ERROR_MESSAGE_FORBIDDEN_USER, status=403 )) return flaskify(logic.get_account_payee_by_account_id(object_id))