Skip to content

Commit

Permalink
APP-4383 - [API] Updated TC API module for changes in the V3 API
Browse files Browse the repository at this point in the history
APP-4401 - [API] Fixed issue with Assignee model not calculating appropriate model type
  • Loading branch information
bsummers-tc committed Feb 27, 2024
1 parent fb8da75 commit 094581e
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 74 deletions.
21 changes: 21 additions & 0 deletions tcex/api/tc/v3/_gen/_gen_filter_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,25 @@ def _gen_code_has_tag_method(self) -> list:
'',
]

def _gen_code_has_all_tags_method(self) -> list:
"""Return code for has_tag TQL filter methods."""
self._add_tql_imports()
return [
f'{self.i1}@property',
f'{self.i1}def has_all_tags(self):',
f'{self.i2}"""Return **TagFilter** for further filtering."""',
f'{self.i2}# first-party',
f'{self.i2}from tcex.api.tc.v3.tags.tag_filter import TagFilter',
'',
f'{self.i2}tags = TagFilter(Tql())',
(
f'''{self.i2}self._tql.add_filter('hasAllTags', '''
'''TqlOperator.EQ, tags, TqlType.SUB_QUERY)'''
),
f'{self.i2}return tags',
'',
]

def _gen_code_has_task_method(self) -> list:
"""Return code for has_task TQL filter methods."""
self._add_tql_imports()
Expand Down Expand Up @@ -495,6 +514,8 @@ def gen_class_methods(self):
_filter_class.extend(self._gen_code_has_note_method())
elif f.keyword.snake_case() == 'has_tag':
_filter_class.extend(self._gen_code_has_tag_method())
elif f.keyword.snake_case() == 'has_all_tags':
_filter_class.extend(self._gen_code_has_all_tags_method())
elif f.keyword.snake_case() == 'has_task':
_filter_class.extend(self._gen_code_has_task_method())
elif f.keyword.snake_case() == 'has_attribute':
Expand Down
22 changes: 8 additions & 14 deletions tcex/api/tc/v3/cases/case_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,21 +267,15 @@ def description(self, operator: Enum, description: list | str):

self._tql.add_filter('description', operator, description, TqlType.STRING)

def has_all_tags(self, operator: Enum, has_all_tags: int | list):
"""Filter All Tags based on **hasAllTags** keyword.
Args:
operator: The operator enum for the filter.
has_all_tags: Filters data tagged with all provided Tag IDs. Query must only contain
'id=x' or 'id IN (x,y,z)'.
"""
if isinstance(has_all_tags, list) and operator not in self.list_types:
raise RuntimeError(
'Operator must be CONTAINS, NOT_CONTAINS, IN'
'or NOT_IN when filtering on a list of values.'
)
@property
def has_all_tags(self):
"""Return **TagFilter** for further filtering."""
# first-party
from tcex.api.tc.v3.tags.tag_filter import TagFilter

self._tql.add_filter('hasAllTags', operator, has_all_tags, TqlType.INTEGER)
tags = TagFilter(Tql())
self._tql.add_filter('hasAllTags', TqlOperator.EQ, tags, TqlType.SUB_QUERY)
return tags

@property
def has_artifact(self):
Expand Down
22 changes: 8 additions & 14 deletions tcex/api/tc/v3/groups/group_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,21 +321,15 @@ def generated_report(self, operator: Enum, generated_report: bool):
"""
self._tql.add_filter('generatedReport', operator, generated_report, TqlType.BOOLEAN)

def has_all_tags(self, operator: Enum, has_all_tags: int | list):
"""Filter All Tags based on **hasAllTags** keyword.
Args:
operator: The operator enum for the filter.
has_all_tags: Filters data tagged with all provided Tag IDs. Query must only contain
'id=x' or 'id IN (x,y,z)'.
"""
if isinstance(has_all_tags, list) and operator not in self.list_types:
raise RuntimeError(
'Operator must be CONTAINS, NOT_CONTAINS, IN'
'or NOT_IN when filtering on a list of values.'
)
@property
def has_all_tags(self):
"""Return **TagFilter** for further filtering."""
# first-party
from tcex.api.tc.v3.tags.tag_filter import TagFilter

self._tql.add_filter('hasAllTags', operator, has_all_tags, TqlType.INTEGER)
tags = TagFilter(Tql())
self._tql.add_filter('hasAllTags', TqlOperator.EQ, tags, TqlType.SUB_QUERY)
return tags

@property
def has_artifact(self):
Expand Down
22 changes: 8 additions & 14 deletions tcex/api/tc/v3/indicators/indicator_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -411,21 +411,15 @@ def first_seen(self, operator: Enum, first_seen: Arrow | datetime | int | str):
first_seen = self.util.any_to_datetime(first_seen).strftime('%Y-%m-%d %H:%M:%S')
self._tql.add_filter('firstSeen', operator, first_seen, TqlType.STRING)

def has_all_tags(self, operator: Enum, has_all_tags: int | list):
"""Filter All Tags based on **hasAllTags** keyword.
Args:
operator: The operator enum for the filter.
has_all_tags: Filters data tagged with all provided Tag IDs. Query must only contain
'id=x' or 'id IN (x,y,z)'.
"""
if isinstance(has_all_tags, list) and operator not in self.list_types:
raise RuntimeError(
'Operator must be CONTAINS, NOT_CONTAINS, IN'
'or NOT_IN when filtering on a list of values.'
)
@property
def has_all_tags(self):
"""Return **TagFilter** for further filtering."""
# first-party
from tcex.api.tc.v3.tags.tag_filter import TagFilter

self._tql.add_filter('hasAllTags', operator, has_all_tags, TqlType.INTEGER)
tags = TagFilter(Tql())
self._tql.add_filter('hasAllTags', TqlOperator.EQ, tags, TqlType.SUB_QUERY)
return tags

@property
def has_artifact(self):
Expand Down
22 changes: 8 additions & 14 deletions tcex/api/tc/v3/intel_requirements/intel_requirement_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,21 +321,15 @@ def generated_report(self, operator: Enum, generated_report: bool):
"""
self._tql.add_filter('generatedReport', operator, generated_report, TqlType.BOOLEAN)

def has_all_tags(self, operator: Enum, has_all_tags: int | list):
"""Filter All Tags based on **hasAllTags** keyword.
Args:
operator: The operator enum for the filter.
has_all_tags: Filters data tagged with all provided Tag IDs. Query must only contain
'id=x' or 'id IN (x,y,z)'.
"""
if isinstance(has_all_tags, list) and operator not in self.list_types:
raise RuntimeError(
'Operator must be CONTAINS, NOT_CONTAINS, IN'
'or NOT_IN when filtering on a list of values.'
)
@property
def has_all_tags(self):
"""Return **TagFilter** for further filtering."""
# first-party
from tcex.api.tc.v3.tags.tag_filter import TagFilter

self._tql.add_filter('hasAllTags', operator, has_all_tags, TqlType.INTEGER)
tags = TagFilter(Tql())
self._tql.add_filter('hasAllTags', TqlOperator.EQ, tags, TqlType.SUB_QUERY)
return tags

@property
def has_artifact(self):
Expand Down
2 changes: 1 addition & 1 deletion tcex/api/tc/v3/v3_model_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def default(self, o: Any) -> str:
return o


class V3ModelABC(BaseModel, ABC):
class V3ModelABC(BaseModel, ABC, allow_population_by_field_name=True):
"""V3 Base Model"""

_associated_type = PrivateAttr(False)
Expand Down
22 changes: 8 additions & 14 deletions tcex/api/tc/v3/victims/victim_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,21 +93,15 @@ def description(self, operator: Enum, description: list | str):

self._tql.add_filter('description', operator, description, TqlType.STRING)

def has_all_tags(self, operator: Enum, has_all_tags: int | list):
"""Filter All Tags based on **hasAllTags** keyword.
Args:
operator: The operator enum for the filter.
has_all_tags: Filters data tagged with all provided Tag IDs. Query must only contain
'id=x' or 'id IN (x,y,z)'.
"""
if isinstance(has_all_tags, list) and operator not in self.list_types:
raise RuntimeError(
'Operator must be CONTAINS, NOT_CONTAINS, IN'
'or NOT_IN when filtering on a list of values.'
)
@property
def has_all_tags(self):
"""Return **TagFilter** for further filtering."""
# first-party
from tcex.api.tc.v3.tags.tag_filter import TagFilter

self._tql.add_filter('hasAllTags', operator, has_all_tags, TqlType.INTEGER)
tags = TagFilter(Tql())
self._tql.add_filter('hasAllTags', TqlOperator.EQ, tags, TqlType.SUB_QUERY)
return tags

@property
def has_attribute(self):
Expand Down
1 change: 1 addition & 0 deletions tests/api/tc/v3/cases/test_case_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ def test_case_all_filters(self, request: FixtureRequest):
case_occurrence_time = datetime.now() - timedelta(days=20)

assignee = {'type': 'User', 'data': {'user_name': os.getenv('TC_API_ACCESS_ID')}}
# assignee = {'type': 'Group', 'data': {'name': 'TcEx Testing'}}

# [Create Testing] define case data
case_data = {
Expand Down
9 changes: 6 additions & 3 deletions tests/api/tc/v3/v3_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -757,12 +757,12 @@ def obj_api_options(self):
]

if self.v3_helper.v3_object == 'indicators':
if 'associationName' in names:
# fix discrepancy between <endpoint>/fields and <endpoint>
names = ['customAssociationNames']
if 'genericCustomIndicatorValues' in names:
# fix discrepancy between <endpoint>/fields and <endpoint>
names = ['value1', 'value2', 'value3']
if 'whoIs' in names:
# fix discrepancy between <endpoint>/fields and <endpoint>
names = ['whois']
if 'threatAssess' in names:
# fix discrepancy between <endpoint>/fields and <endpoint>
names = [
Expand All @@ -772,6 +772,9 @@ def obj_api_options(self):
'threatAssessScoreFalsePositive',
'threatAssessScoreObserved',
]
if 'whoIs' in names:
# fix discrepancy between <endpoint>/fields and <endpoint>
names = ['whois']

if self.v3_helper.v3_object == 'results':
if 'intelRequirementDetails' in names:
Expand Down

0 comments on commit 094581e

Please sign in to comment.