Skip to content

Commit

Permalink
fix(manager): fix total_items and advisory filter bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrii authored and jdobes committed Nov 26, 2020
1 parent 6ebf7d8 commit 47e4a1a
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 51 deletions.
21 changes: 21 additions & 0 deletions manager/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -564,3 +564,24 @@ def cyndi_query(query):
if CYNDI_ENABLED:
query = query.join(InventoryHosts, JOIN.INNER, on=(SystemPlatform.inventory_id.cast("UUID") == InventoryHosts.id))
return query


def get_advisories_per_cve_from_db(synopsis: str):
"""Get advisories per CVE from DB"""
try:
data = (CveMetadata.select(CveMetadata.advisories_list)
.where(CveMetadata.cve == synopsis)).dicts()[0]['advisories_list']
except IndexError:
data = []
return data


def filter_by_advisory(advisory_name, data):
"""Filter data by advisory name"""
filtered = {}
for key, advisories in data.items():
for advisory in advisories:
if advisory_name.lower() in advisory.lower():
filtered[key] = advisories
break
return filtered
32 changes: 11 additions & 21 deletions manager/cve_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
Status, SystemPlatform, SystemVulnerabilities, CveImpact, InsightsRule, InventoryHosts
from .base import ApplicationException, DEFAULT_BUSINESS_RISK, DEFAULT_STATUS, get_or_create_account, \
GetRequest, parse_int_list, PatchRequest, get_rules_for_cves, reporter, unique_bool_list, bool_or_rules_list, \
CYNDI_ENABLED, parse_tags, cyndi_query, PATCH_HOST, PATCH_ID_QUERY_FILTER, PATCH_FILTER_PREFIX, WORKER_THREADS, ServiceAccess
CYNDI_ENABLED, parse_tags, cyndi_query, PATCH_HOST, PATCH_ID_QUERY_FILTER, PATCH_FILTER_PREFIX, WORKER_THREADS, ServiceAccess, \
get_advisories_per_cve_from_db, filter_by_advisory
from .filters import apply_filters, filter_types
from .list_view import ListView

Expand Down Expand Up @@ -282,13 +283,6 @@ def _cve_exists(synopsis):
except DoesNotExist:
raise ApplicationException('No such CVE ID', 404)

@staticmethod
def _get_advisories_per_cve_from_db(synopsis):
"""Get advisories per CVE from DB"""
query = (CveMetadata.select(CveMetadata.advisories_list)
.where(CveMetadata.cve == synopsis))
return query

@classmethod
def _get_advisories_per_system(cls, advisories_list, inv_ids):
"""Get advisories per system by a specific CVE"""
Expand Down Expand Up @@ -369,32 +363,28 @@ def handle_get(cls, **kwargs):
response = {}
result = []
patch_access = None
total_items = None
if cls._ids_only:
result = inv_ids
else:
system_advisories = {}
system_advisories_filtered = {}
if 'show_advisories' in args and args['show_advisories'] is True:
query = cls._get_advisories_per_cve_from_db(synopsis)
query = apply_filters(query, args, [filter_types.ADVISORY])
try:
advisories_list = query.dicts()[0]['advisories_list']
except IndexError:
advisories_list = []
system_advisories, patch_access = cls._get_advisories_per_system(advisories_list, inv_ids)
advisories_list = get_advisories_per_cve_from_db(synopsis)
data, patch_access = cls._get_advisories_per_system(advisories_list, inv_ids)
system_advisories = data
if 'advisory' in args and args['advisory']:
system_advisories_filtered = {sys: advisories for sys, advisories in system_advisories.items() if args['advisory'] in advisories}

system_advisories = filter_by_advisory(args['advisory'], data)
total_items = len(system_advisories)
for sys in systems:
if 'advisory' in args and args['advisory']:
if sys['inventory_id'] in system_advisories_filtered:
record = cls._build_attributes(sys, system_advisories_filtered)
if sys['inventory_id'] in system_advisories:
record = cls._build_attributes(sys, system_advisories)
result.append({'type': 'system', 'id': sys['inventory_id'], 'attributes': record})
else:
record = cls._build_attributes(sys, system_advisories)
result.append({'type': 'system', 'id': sys['inventory_id'], 'attributes': record})

response['meta'] = asys_view.get_metadata()
response['meta'] = asys_view.get_metadata(total_items)
response['meta']['patch_access'] = patch_access.status if patch_access else None
response['links'] = asys_view.get_pagination_links()
response['data'] = cls._format_data(list_arguments["data_format"], result)
Expand Down
8 changes: 0 additions & 8 deletions manager/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,13 +418,6 @@ def _filter_system_by_sap_sids(query, args):
return query


def _filter_by_advisory(query, args):
"""Filters advisory list if contains specific advisory id"""
if 'advisory' in args and args['advisory'] is not None:
query = query.where(CveMetadata.advisories_list.contains(args['advisory']))
return query


class filter_types(Enum): # pylint: disable=invalid-name
"""definition of filter types"""

Expand All @@ -448,7 +441,6 @@ class filter_types(Enum): # pylint: disable=invalid-name
SYSTEM_TAGS = _filter_system_by_tags
SYSTEM_SAP = _filter_system_by_sap
SYSTEM_SAP_SIDS = _filter_system_by_sap_sids
ADVISORY = _filter_by_advisory


def apply_filters(query, args, filters):
Expand Down
11 changes: 8 additions & 3 deletions manager/list_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,10 @@ def _apply_sort(self):
if sort_columns:
self.query = self.query.order_by(*sort_columns)

def _get_total_items(self):
self.total_items = self.query.count()
def _get_total_items(self, total_items=None):
if total_items is None:
total_items = self.query.count()
self.total_items = total_items

pages = math.ceil(self.total_items / self.list_args["page_size"])
self.pages = pages if pages > 0 else 1
Expand Down Expand Up @@ -145,8 +147,11 @@ def get_pagination_links(self):
"last": self._get_last_link()
}

def get_metadata(self):
def get_metadata(self, total_items=None):
"""Returns pagination/filtering/sorting related metadata"""
if total_items is not None:
self._get_total_items(total_items)

meta = {
"sort": self.list_args["sort"],
"filter": self.list_args["filter"],
Expand Down
28 changes: 10 additions & 18 deletions manager/system_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from common.utils import external_service_request, FUTURE_ERR
from .base import ApplicationException, DEFAULT_BUSINESS_RISK, GetRequest, parse_int_list, PatchRequest, \
DeleteRequest, CVE_SYNOPSIS_SORT, parse_str_or_list, reporter, unique_bool_list, CYNDI_ENABLED, parse_tags, \
cyndi_query, PATCH_HOST, PATCH_ID_QUERY_FILTER, PATCH_FILTER_PREFIX, WORKER_THREADS, ServiceAccess
cyndi_query, PATCH_HOST, PATCH_ID_QUERY_FILTER, PATCH_FILTER_PREFIX, WORKER_THREADS, ServiceAccess, get_advisories_per_cve_from_db, filter_by_advisory
from .filters import apply_filters, filter_types
from .list_view import ListView

Expand Down Expand Up @@ -277,16 +277,6 @@ def _patch_request_advisories(inv_id, advisories_list, x_rh_identity, patch_acce
return list(advisories_response_json['data']) if advisories_response_json is not None else None
return None

@staticmethod
def _get_advisories_per_cve_from_db(synopsis: str):
"""Get advisories per CVE from DB"""
try:
data = (CveMetadata.select(CveMetadata.advisories_list)
.where(CveMetadata.cve == synopsis)).dicts()[0]['advisories_list']
except IndexError:
data = []
return data

@classmethod
def _get_advisories_per_cve(cls, cve_names: list, inv_id: str):
"""Get advisories per CVE by a specific system"""
Expand All @@ -296,7 +286,7 @@ def _get_advisories_per_cve(cls, cve_names: list, inv_id: str):
future_to_cve = {}
x_rh_identity = connexion.request.headers['x-rh-identity']
for cve_name in cve_names:
advisories = cls._get_advisories_per_cve_from_db(cve_name)
advisories = get_advisories_per_cve_from_db(cve_name)
future_to_cve[executor.submit(cls._patch_request_advisories, inv_id, advisories, x_rh_identity, patch_access)] = cve_name
for future in concurrent.futures.as_completed(future_to_cve):
try:
Expand Down Expand Up @@ -385,30 +375,32 @@ def handle_get(cls, **kwargs): # pylint: disable=too-many-statements

patch_access = None
cve_advisories = {}
cve_advisories_filtered = {}
total_items = None
if 'show_advisories' in args and args['show_advisories'] is True:
cve_names = []
for cve in cves_view:
cve_names.append(cve['cve_name'])
cve_advisories, patch_access = cls._get_advisories_per_cve(cve_names, inventory_id)
data, patch_access = cls._get_advisories_per_cve(cve_names, inventory_id)
cve_advisories = data
if 'advisory' in args and args['advisory']:
cve_advisories_filtered = {cve: advisories for cve, advisories in cve_advisories.items() if args['advisory'] in advisories}
cve_advisories = filter_by_advisory(args['advisory'], data)
total_items = len(cve_advisories)

response = {}
result = []
if not cls._ids_only:
for cve in cves_view:
if 'advisory' in args and args['advisory']:
if cve['cve_name'] in cve_advisories_filtered:
record = cls._build_attributes(cve, cve_advisories_filtered)
if cve['cve_name'] in cve_advisories:
record = cls._build_attributes(cve, cve_advisories)
result.append({'type': 'cve', 'id': cve['cve_name'], 'attributes': record})
else:
record = cls._build_attributes(cve, cve_advisories)
result.append({'type': 'cve', 'id': cve['cve_name'], 'attributes': record})
else:
for cve in cves_view:
result.append(cve['cve_name'])
response['meta'] = cves_view.get_metadata()
response['meta'] = cves_view.get_metadata(total_items)
response['meta']['opt_out'] = system.opt_out
response['meta']['patch_access'] = patch_access.status if patch_access else None
response['links'] = cves_view.get_pagination_links()
Expand Down
2 changes: 1 addition & 1 deletion tests/manager_tests/test_links.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def __init__(self, query, sortable_columns, default_sort_columns, filterable_col
super(NoQueryListView, self).__init__(query, sortable_columns, default_sort_columns, filterable_columns,
list_args, query_args, uri)

def _get_total_items(self):
def _get_total_items(self, total_items=None):
# Intercept so we can ignore the query
pages = math.ceil(self.total_items / self.list_args["page"])
self.pages = pages if pages > 0 else 1
Expand Down

0 comments on commit 47e4a1a

Please sign in to comment.