Skip to content

Commit 4954f8e

Browse files
Merge pull request #140 from code42/INTEG-2844/timestamp-bugfix
when querying sessions, properly use timestamp in milliseconds
2 parents c44731e + 0ab859e commit 4954f8e

File tree

3 files changed

+111
-6
lines changed

3 files changed

+111
-6
lines changed

src/_incydr_sdk/queries/utils.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,13 @@ def parse_ts_to_posix_ts(timestamp: Union[str, datetime]):
4141
return dt.timestamp()
4242

4343

44+
def parse_ts_to_ms_ts(timestamp: Union[str, datetime]):
45+
"""
46+
Parse epoch ms timestamp from DATE/DATETIME str or datetime obj.
47+
"""
48+
return parse_ts_to_posix_ts(timestamp) * 1000
49+
50+
4451
def parse_str_to_dt(timestamp: str):
4552
try:
4653
dt = parser.parse(timestamp)

src/_incydr_sdk/sessions/client.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from _incydr_sdk.enums.sessions import ContentInspectionStatuses
99
from _incydr_sdk.enums.sessions import SessionStates
1010
from _incydr_sdk.enums.sessions import SortKeys
11-
from _incydr_sdk.queries.utils import parse_ts_to_posix_ts
11+
from _incydr_sdk.queries.utils import parse_ts_to_ms_ts
1212
from _incydr_sdk.sessions.models.models import SessionsChangeStateRequest
1313
from _incydr_sdk.sessions.models.models import SessionsCriteriaRequest
1414
from _incydr_sdk.sessions.models.models import SessionsQueryRequest
@@ -76,9 +76,9 @@ def get_page(
7676

7777
# Parse timestamps
7878
if start_time and not isinstance(start_time, (int, float)):
79-
start_time = parse_ts_to_posix_ts(start_time)
79+
start_time = parse_ts_to_ms_ts(start_time)
8080
if end_time and not isinstance(end_time, (int, float)):
81-
end_time = parse_ts_to_posix_ts(end_time)
81+
end_time = parse_ts_to_ms_ts(end_time)
8282

8383
if states and not isinstance(states, List):
8484
states = [states]
@@ -253,9 +253,9 @@ def update_state_by_criteria(
253253

254254
# Parse timestamps
255255
if start_time and not isinstance(start_time, (int, float)):
256-
start_time = parse_ts_to_posix_ts(start_time)
256+
start_time = parse_ts_to_ms_ts(start_time)
257257
if end_time and not isinstance(end_time, (int, float)):
258-
end_time = parse_ts_to_posix_ts(end_time)
258+
end_time = parse_ts_to_ms_ts(end_time)
259259

260260
if states and not isinstance(states, List):
261261
states = [states]

tests/test_sessions.py

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@
2222

2323
TEST_SESSION_ID = "123-session-1"
2424
DATETIME_INSTANT = datetime(2024, 1, 1, tzinfo=timezone.utc)
25-
POSIX_TS = int(DATETIME_INSTANT.timestamp())
25+
POSIX_TS = int(DATETIME_INSTANT.timestamp()) * 1000
26+
START_DATE = "2024-12-19"
27+
START_TIMESTAMP = 1734566400000 # in ms
28+
END_DATE = "2024-12-20"
29+
END_TIMESTAMP = 1734652800000 # in ms
2630

2731
TEST_SESSION = {
2832
"actorId": TEST_SESSION_ID,
@@ -158,6 +162,50 @@ def test_get_page_when_custom_params_returns_expected_data(httpserver_auth: HTTP
158162
assert len(page.items) == 1 == page.total_count
159163

160164

165+
def test_get_page_when_given_date_uses_correct_timestamp(httpserver_auth: HTTPServer):
166+
query = {
167+
"actor_id": "actor-id",
168+
"on_or_after": START_TIMESTAMP,
169+
"before": END_TIMESTAMP,
170+
"has_alerts": "false",
171+
"risk_indicators": ["risk-indicator"],
172+
"state": ["OPEN"],
173+
"severity": [3],
174+
"rule_id": ["rule-id"],
175+
"watchlist_id": ["watchlist-id"],
176+
"content_inspection_status": "PENDING",
177+
"order_by": "score",
178+
"sort_direction": "desc",
179+
"page_number": 2,
180+
"page_size": 10,
181+
}
182+
sessions_page = {"items": [TEST_SESSION], "totalCount": 1}
183+
httpserver_auth.expect_request(
184+
"/v1/sessions", method="GET", query_string=urlencode(query, doseq=True)
185+
).respond_with_json(sessions_page)
186+
187+
client = Client()
188+
page = client.sessions.v1.get_page(
189+
actor_id="actor-id",
190+
start_time=START_DATE,
191+
end_time=END_DATE,
192+
has_alerts=False,
193+
sort_key=SortKeys.SCORE,
194+
risk_indicators=["risk-indicator"],
195+
sort_dir=SortDirection.DESC,
196+
states=SessionStates.OPEN,
197+
severities=3,
198+
rule_ids="rule-id",
199+
watchlist_ids="watchlist-id",
200+
page_num=2,
201+
page_size=10,
202+
content_inspection_status=ContentInspectionStatuses.PENDING,
203+
)
204+
assert isinstance(page, SessionsPage)
205+
assert page.items[0].json() == json.dumps(TEST_SESSION)
206+
assert len(page.items) == 1 == page.total_count
207+
208+
161209
def test_iter_all_when_default_params_returns_expected_data(
162210
httpserver_auth: HTTPServer,
163211
):
@@ -357,6 +405,56 @@ def test_update_state_by_criteria_makes_expected_calls(httpserver_auth: HTTPServ
357405
assert response.status_code == 200
358406

359407

408+
def test_update_state_by_criteria_when_given_date_uses_correct_timestamp(
409+
httpserver_auth: HTTPServer,
410+
):
411+
query = {
412+
"actor_id": "actor-id",
413+
"on_or_after": START_TIMESTAMP,
414+
"before": END_TIMESTAMP,
415+
"has_alerts": "false",
416+
"risk_indicators": ["risk-indicator"],
417+
"state": ["OPEN"],
418+
"severity": [3],
419+
"rule_id": ["rule-id"],
420+
"watchlist_id": ["watchlist-id"],
421+
"content_inspection_status": "PENDING",
422+
}
423+
424+
token = "123-token"
425+
httpserver_auth.expect_request(
426+
"/v1/sessions/change-states",
427+
query_string=urlencode(query, doseq=True),
428+
method="POST",
429+
json={"continuationToken": None, "newState": "CLOSED"},
430+
).respond_with_json({"continuationToken": token})
431+
httpserver_auth.expect_request(
432+
"/v1/sessions/change-states",
433+
query_string=urlencode(query, doseq=True),
434+
method="POST",
435+
json={"continuationToken": token, "newState": "CLOSED"},
436+
).respond_with_json({"continuationToken": None})
437+
438+
client = Client()
439+
responses = client.sessions.v1.update_state_by_criteria(
440+
new_state=SessionStates.CLOSED,
441+
actor_id="actor-id",
442+
start_time=START_DATE,
443+
end_time=END_DATE,
444+
has_alerts=False,
445+
risk_indicators=["risk-indicator"],
446+
states=SessionStates.OPEN,
447+
severities=3,
448+
rule_ids="rule-id",
449+
watchlist_ids="watchlist-id",
450+
content_inspection_status=ContentInspectionStatuses.PENDING,
451+
)
452+
assert responses[0].json()["continuationToken"] == token
453+
assert responses[1].json()["continuationToken"] is None
454+
for response in responses:
455+
assert response.status_code == 200
456+
457+
360458
# ************************************************ CLI ************************************************
361459

362460

0 commit comments

Comments
 (0)