def _prepare_tiny_shield_models(): models = customize_pagination_with_sort_columns(list(SORTABLE_COLUMNS.keys()), DEFAULT_SORT_COLUMN) models.extend([ get_internal_or_generated_award_id_model(), {'key': 'piid', 'name': 'piid', 'optional': True, 'type': 'text', 'text_type': 'search'} ]) return models
def _prepare_tiny_shield_models(): models = customize_pagination_with_sort_columns(list(SORTABLE_COLUMNS.keys()), DEFAULT_SORT_COLUMN) models.extend( [ get_internal_or_generated_award_id_model(), {"key": "piid", "name": "piid", "optional": True, "type": "text", "text_type": "search"}, ] ) return models
def __init__(self): models = customize_pagination_with_sort_columns( list(TransactionViewSet.transaction_lookup.keys()), 'action_date' ) models.extend([ get_internal_or_generated_award_id_model(), {'key': 'idv', 'name': 'idv', 'type': 'boolean', 'default': True, 'optional': True} ]) self._tiny_shield_models = models super(TransactionViewSet, self).__init__()
def __init__(self): models = customize_pagination_with_sort_columns( list(TransactionViewSet.transaction_lookup.keys()), "action_date" ) models.extend( [ get_internal_or_generated_award_id_model(), {"key": "idv", "name": "idv", "type": "boolean", "default": True, "optional": True}, ] ) self._tiny_shield_models = models super(TransactionViewSet, self).__init__()
def _prepare_tiny_shield_models(): # This endpoint has a fixed sort. No need for "sort" or "order". models = [copy(p) for p in PAGINATION if p["name"] in ("page", "limit")] models.extend([get_internal_or_generated_award_id_model()]) models.extend([{ "key": "hide_edge_cases", "name": "hide_edge_cases", "type": "boolean", "optional": True, "default": False }]) return models
def _prepare_tiny_shield_models(): # This endpoint has a fixed sort. No need for "sort" or "order". models = [copy(p) for p in PAGINATION if p["name"] in ("page", "limit")] models.extend([get_internal_or_generated_award_id_model()]) models.extend([{ 'key': 'hide_edge_cases', 'name': 'hide_edge_cases', 'type': 'boolean', 'optional': True, 'default': False }]) return models
def _prepare_tiny_shield_models(): models = customize_pagination_with_sort_columns(SORTABLE_COLUMNS, DEFAULT_SORT_COLUMN) models.extend([ get_internal_or_generated_award_id_model(), { 'key': 'idv', 'name': 'idv', 'type': 'boolean', 'default': True, 'optional': True } ]) return models
def __init__(self): models = customize_pagination_with_sort_columns( list(TransactionViewSet.transaction_lookup.keys()), 'action_date') models.extend([ get_internal_or_generated_award_id_model(), { 'key': 'idv', 'name': 'idv', 'type': 'boolean', 'default': True, 'optional': True } ]) self._tiny_shield_models = models super(TransactionViewSet, self).__init__()
def _prepare_tiny_shield_models(): models = customize_pagination_with_sort_columns(SORTABLE_COLUMNS, DEFAULT_SORT_COLUMN) models.extend([ get_internal_or_generated_award_id_model(), { 'key': 'type', 'name': 'type', 'type': 'enum', 'enum_values': tuple(TYPE_TO_SQL_MAPPING), 'default': 'child_idvs', 'optional': True } ]) return models
def _parse_and_validate_request(requested_award: str, request_data: dict) -> dict: piid = request_data.get("piid") data = {"award_id": requested_award, "piid": piid} models = [ get_internal_or_generated_award_id_model(), { "key": "piid", "name": "piid", "allow_nulls": True, "optional": True, "type": "text", "text_type": "search", }, ] return TinyShield(models).block(data)
def _prepare_tiny_shield_models(): models = customize_pagination_with_sort_columns(SORTABLE_COLUMNS, DEFAULT_SORT_COLUMN) models.extend( [ get_internal_or_generated_award_id_model(), { "key": "type", "name": "type", "type": "enum", "enum_values": tuple(TYPE_TO_SQL_MAPPING), "default": "child_idvs", "optional": True, }, ] ) return models
def test_get_internal_or_generated_award_id_rule_bad(): # Rule violations. ts = TinyShield([get_internal_or_generated_award_id_model()]) with pytest.raises(UnprocessableEntityException): ts.block({}) with pytest.raises(UnprocessableEntityException): ts.block({"award_id": "B" * (MAX_ITEMS + 1)}) with pytest.raises(UnprocessableEntityException): ts.block({"award_id": MAX_INT + 1}) with pytest.raises(UnprocessableEntityException): ts.block({"award_id": MIN_INT - 1}) with pytest.raises(UnprocessableEntityException): ts.block({"award_id": 1.1}) with pytest.raises(UnprocessableEntityException): ts.block({"award_id": [1, 2]}) with pytest.raises(UnprocessableEntityException): ts.block({"id": "abcde"})
def test_get_internal_or_generated_award_id_rule_bad(): # Rule violations. ts = TinyShield([get_internal_or_generated_award_id_model()]) with pytest.raises(UnprocessableEntityException): ts.block({}) with pytest.raises(UnprocessableEntityException): ts.block({'award_id': 'B' * (MAX_ITEMS + 1)}) with pytest.raises(UnprocessableEntityException): ts.block({'award_id': MAX_INT + 1}) with pytest.raises(UnprocessableEntityException): ts.block({'award_id': MIN_INT - 1}) with pytest.raises(UnprocessableEntityException): ts.block({'award_id': 1.1}) with pytest.raises(UnprocessableEntityException): ts.block({'award_id': [1, 2]}) with pytest.raises(UnprocessableEntityException): ts.block({'id': 'abcde'})
# By this point, our award_id has been validated and cleaned up by # TinyShield. We will either have an internal award id that is an # integer or a generated award id that is a string. award_id = request_data['award_id'] award_id_column = 'award_id' if type(award_id) is int else 'generated_unique_award_id' sql = FUNDING_TREEMAP_SQL.format( columns=SQL(columns), award_id_column=Identifier(award_id_column), award_id=Literal(award_id), group_by=SQL(group_by), ) return execute_sql_to_ordered_dictionary(sql) @validate_post_request([get_internal_or_generated_award_id_model()]) class IDVFundingRollupViewSet(IDVFundingBaseViewSet): """ endpoint_doc: /awards/idvs/funding_rollup.md """ @cache_response() def post(self, request: Request) -> Response: columns = """coalesce(sum(nullif(faba.transaction_obligated_amount, 'NaN')), 0.0) total_transaction_obligated_amount, count(distinct ca.awarding_agency_id) awarding_agency_count, count(distinct taa.agency_id || '-' || taa.main_account_code) federal_account_count""" group_by = "" results = self._business_logic(request.data, columns, group_by) return Response(results[0])
from rest_framework.exceptions import NotFound from rest_framework.request import Request from rest_framework.response import Response from usaspending_api.awards.models import ParentAward from usaspending_api.common.cache_decorator import cache_response from usaspending_api.common.views import APIDocumentationView from usaspending_api.common.validator.award import get_internal_or_generated_award_id_model from usaspending_api.common.validator.tinyshield import TinyShield logger = logging.getLogger('console') TINY_SHIELD_MODELS = [get_internal_or_generated_award_id_model()] class IDVAmountsViewSet(APIDocumentationView): """Returns counts and dollar figures for a specific IDV. endpoint_doc: /awards/idvs/amounts.md """ @staticmethod def _parse_and_validate_request(requested_award: str) -> dict: return TinyShield(deepcopy(TINY_SHIELD_MODELS)).block({'award_id': requested_award}) @staticmethod def _business_logic(request_data: dict) -> OrderedDict: # By this point, our award_id has been validated and cleaned up by # TinyShield. We will either have an internal award id that is an
select coalesce(sum(gfaba.transaction_obligated_amount), 0.0) total_transaction_obligated_amount, count(distinct aa.toptier_agency_id) awarding_agency_count, count(distinct af.toptier_agency_id) funding_agency_count, count(distinct taa.agency_id || '-' || taa.main_account_code) federal_account_count from gather_financial_accounts_by_awards gfaba left outer join treasury_appropriation_account taa on taa.treasury_account_identifier = gfaba.treasury_account_id left outer join agency aa on aa.id = gfaba.awarding_agency_id left outer join agency af on af.id = gfaba.funding_agency_id """ ) @validate_post_request([get_internal_or_generated_award_id_model()]) class AwardFundingRollupViewSet(APIView): """ Returns File C funding totals associated with an award. """ endpoint_doc = "usaspending_api/api_contracts/contracts/v2/awards/funding_rollup.md" @staticmethod def _business_logic(request_data: dict) -> OrderedDict: # By this point, our award_id has been validated and cleaned up by # TinyShield. We will either have an internal award id that is an # integer or a generated award id that is a string. award_id = request_data["award_id"] award_id_column = "award_id" if type(award_id) is int else "generated_unique_award_id"
def _parse_and_validate_request(self, provided_award_id: str) -> dict: request_dict = {"award_id": provided_award_id} models = get_internal_or_generated_award_id_model() return TinyShield([models]).block(request_dict)
def _get_award_id(filters): models = get_internal_or_generated_award_id_model() TinyShield([models]).block(filters) award_id = filters["award_id"] return award_id
def _prepare_tiny_shield_models(): # This endpoint has a fixed sort. No need for "sort" or "order". models = [copy(p) for p in PAGINATION if p["name"] in ("page", "limit")] models.extend([get_internal_or_generated_award_id_model()]) return models
def test_get_internal_or_generated_award_id_rule(): models = [get_internal_or_generated_award_id_model()] r = TinyShield(models).block({"award_id": "abcd"}) assert r == {"award_id": "abcd"} models = [get_internal_or_generated_award_id_model()] r = TinyShield(models).block({"award_id": "A" * MAX_ITEMS}) assert r == {"award_id": "A" * MAX_ITEMS} models = [get_internal_or_generated_award_id_model(key="my_award_id")] r = TinyShield(models).block({"my_award_id": "abcd"}) assert r == {"my_award_id": "abcd"} models = [ get_internal_or_generated_award_id_model(key="my_award_id", name="your_award_id") ] r = TinyShield(models).block({"my_award_id": "abcd"}) assert r == {"my_award_id": "abcd"} models = [ get_internal_or_generated_award_id_model(key="my_award_id", name="your_award_id", optional=True) ] r = TinyShield(models).block({"my_award_id": "abcd"}) assert r == {"my_award_id": "abcd"} models = [get_internal_or_generated_award_id_model()] r = TinyShield(models).block({"award_id": 12345}) assert r == {"award_id": 12345} models = [get_internal_or_generated_award_id_model()] r = TinyShield(models).block({"award_id": "12345"}) assert r == {"award_id": 12345} models = [get_internal_or_generated_award_id_model()] r = TinyShield(models).block({"award_id": MAX_INT}) assert r == {"award_id": MAX_INT} models = [get_internal_or_generated_award_id_model()] r = TinyShield(models).block({"award_id": MIN_INT}) assert r == {"award_id": MIN_INT} models = [get_internal_or_generated_award_id_model(key="my_award_id")] r = TinyShield(models).block({"my_award_id": 12345}) assert r == {"my_award_id": 12345} models = [ get_internal_or_generated_award_id_model(key="my_award_id", name="your_award_id") ] r = TinyShield(models).block({"my_award_id": 12345}) assert r == {"my_award_id": 12345} models = [ get_internal_or_generated_award_id_model(key="my_award_id", name="your_award_id", optional=True) ] r = TinyShield(models).block({"my_award_id": 12345}) assert r == {"my_award_id": 12345} models = [ get_internal_or_generated_award_id_model(key="my_award_id", name="your_award_id", optional=True) ] r = TinyShield(models).block({}) assert r == {}
# TinyShield. We will either have an internal award id that is an # integer or a generated award id that is a string. award_id = request_data['award_id'] award_id_column = 'award_id' if type(award_id) is int else 'generated_unique_award_id' sql = FUNDING_TREEMAP_SQL.format( columns=columns, award_id_column=Identifier(award_id_column), award_id=Literal(award_id), group_by=group_by, order_by=order_by, ) return execute_sql_to_ordered_dictionary(sql) @validate_post_request([get_internal_or_generated_award_id_model(), ]) class IDVFundingRollupViewSet(IDVFundingBaseViewSet): """ endpoint_doc: /awards/idvs/funding_rollup.md """ @cache_response() def post(self, request: Request) -> Response: order_by = SQL("") columns = SQL("""coalesce(sum(nullif(faba.transaction_obligated_amount, 'NaN')), 0.0) total_transaction_obligated_amount, count(distinct ca.awarding_agency_id) awarding_agency_count, count(distinct taa.agency_id || '-' || taa.main_account_code) federal_account_count""") group_by = SQL("") results = self._business_logic(request.data, columns, group_by, order_by) return Response(results[0])
taa.treasury_account_identifier = gfaba.treasury_account_id left outer join federal_account fa on fa.agency_identifier = taa.agency_id and fa.main_account_code = taa.main_account_code left outer join agency_id_to_agency_id_for_toptier_mapping afmap on afmap.agency_id = gfaba.funding_agency_id group by federal_account, fa.account_title, funding_agency_abbreviation, funding_agency_name, afmap.agency_id_for_toptier order by {order_by} {order_direction} """) TINYSHIELD_MODELS = customize_pagination_with_sort_columns( list(SORTABLE_COLUMNS.keys()), DEFAULT_SORT_COLUMN) TINYSHIELD_MODELS.append(get_internal_or_generated_award_id_model()) @validate_post_request(TINYSHIELD_MODELS) class IDVAccountsViewSet(APIView): """ These endpoints are used to power USAspending.gov's IDV Summary Funding Accounts component. """ endpoint_doc = "usaspending_api/api_contracts/contracts/v2/idvs/accounts.md" @staticmethod def _business_logic(request_data: dict) -> list: # By this point, our award_id has been validated and cleaned up by # TinyShield. We will either have an internal award id that is an # integer or a generated award id that is a string.
from collections import OrderedDict from copy import deepcopy from rest_framework.exceptions import NotFound from rest_framework.request import Request from rest_framework.response import Response from usaspending_api.awards.models import ParentAward from usaspending_api.common.cache_decorator import cache_response from usaspending_api.common.views import APIDocumentationView from usaspending_api.common.validator.award import get_internal_or_generated_award_id_model from usaspending_api.common.validator.tinyshield import TinyShield logger = logging.getLogger('console') TINY_SHIELD_MODELS = [get_internal_or_generated_award_id_model()] class IDVAmountsViewSet(APIDocumentationView): """Returns counts and dollar figures for a specific IDV. endpoint_doc: /awards/idvs/amounts.md """ @staticmethod def _parse_and_validate_request(requested_award: str) -> dict: return TinyShield(deepcopy(TINY_SHIELD_MODELS)).block( {'award_id': requested_award}) @staticmethod def _business_logic(request_data: dict) -> OrderedDict: # By this point, our award_id has been validated and cleaned up by # TinyShield. We will either have an internal award id that is an
def test_get_internal_or_generated_award_id_rule(): models = [get_internal_or_generated_award_id_model()] r = TinyShield(models).block({'award_id': 'abcd'}) assert r == {'award_id': 'abcd'} models = [get_internal_or_generated_award_id_model()] r = TinyShield(models).block({'award_id': 'A' * MAX_ITEMS}) assert r == {'award_id': 'A' * MAX_ITEMS} models = [get_internal_or_generated_award_id_model(key='my_award_id')] r = TinyShield(models).block({'my_award_id': 'abcd'}) assert r == {'my_award_id': 'abcd'} models = [get_internal_or_generated_award_id_model(key='my_award_id', name='your_award_id')] r = TinyShield(models).block({'my_award_id': 'abcd'}) assert r == {'my_award_id': 'abcd'} models = [get_internal_or_generated_award_id_model(key='my_award_id', name='your_award_id', optional=True)] r = TinyShield(models).block({'my_award_id': 'abcd'}) assert r == {'my_award_id': 'abcd'} models = [get_internal_or_generated_award_id_model()] r = TinyShield(models).block({'award_id': 12345}) assert r == {'award_id': 12345} models = [get_internal_or_generated_award_id_model()] r = TinyShield(models).block({'award_id': '12345'}) assert r == {'award_id': 12345} models = [get_internal_or_generated_award_id_model()] r = TinyShield(models).block({'award_id': MAX_INT}) assert r == {'award_id': MAX_INT} models = [get_internal_or_generated_award_id_model()] r = TinyShield(models).block({'award_id': MIN_INT}) assert r == {'award_id': MIN_INT} models = [get_internal_or_generated_award_id_model(key='my_award_id')] r = TinyShield(models).block({'my_award_id': 12345}) assert r == {'my_award_id': 12345} models = [get_internal_or_generated_award_id_model(key='my_award_id', name='your_award_id')] r = TinyShield(models).block({'my_award_id': 12345}) assert r == {'my_award_id': 12345} models = [get_internal_or_generated_award_id_model(key='my_award_id', name='your_award_id', optional=True)] r = TinyShield(models).block({'my_award_id': 12345}) assert r == {'my_award_id': 12345} models = [get_internal_or_generated_award_id_model(key='my_award_id', name='your_award_id', optional=True)] r = TinyShield(models).block({}) assert r == {}
def _parse_and_validate_request(requested_award: str) -> dict: return TinyShield([get_internal_or_generated_award_id_model()]).block({"award_id": requested_award})