fix(jira,tests): send real datetime to RT/BT date fields, resolve assignee usernames for operators
Aegis CI / lint-and-test (push) Has been cancelled
Snyk Security Scan / Python vulnerabilities (backend) (push) Has been cancelled
Snyk Security Scan / npm vulnerabilities (frontend) (push) Has been cancelled
Snyk Security Scan / Docker image vulnerabilities (backend) (push) Has been cancelled
Aegis CI / lint-and-test (push) Has been cancelled
Snyk Security Scan / Python vulnerabilities (backend) (push) Has been cancelled
Snyk Security Scan / npm vulnerabilities (frontend) (push) Has been cancelled
Snyk Security Scan / Docker image vulnerabilities (backend) (push) Has been cancelled
- RT/BT Start/End Date are genuine Jira "datetime" custom fields (confirmed via issue_editmeta), not plain dates. Pushing a bare "YYYY-MM-DD" string made Jira default the time-of-day to midnight, so RT Start Date and RT End Date ended up showing the same meaningless midnight timestamp instead of the actual execution window. Now sends a full ISO datetime. - The test detail page showed "RT: Unassigned" for the operator who WAS correctly assigned, because GET /users/operators (the only source AssigneeControl used to resolve an assignee ID into a username) is restricted to leads/managers — a plain operator has no other way to resolve their own ID. TestOut now resolves and includes the assignee's username directly (red/blue tech + reviewer), so the badge no longer depends on a permission-gated list the viewer might not have access to.
This commit is contained in:
@@ -397,8 +397,8 @@ def test_push_rt_submitted_uses_execution_times_not_click_time(mock_get_client,
|
||||
jira_service.push_rt_submitted(db, test)
|
||||
|
||||
fields = mock_jira.update_issue_field.call_args[1]["fields"]
|
||||
assert fields[jira_service.JIRA_FIELD_RT_START_DATE] == "2026-03-01"
|
||||
assert fields[jira_service.JIRA_FIELD_RT_END_DATE] == "2026-03-01"
|
||||
assert fields[jira_service.JIRA_FIELD_RT_START_DATE] == "2026-03-01T09:00:00.000+0000"
|
||||
assert fields[jira_service.JIRA_FIELD_RT_END_DATE] == "2026-03-01T11:00:00.000+0000"
|
||||
|
||||
|
||||
@patch("app.services.jira_service.has_admin_jira_configured", return_value=True)
|
||||
@@ -439,8 +439,8 @@ def test_push_rt_submitted_rt_start_date_survives_reopen(mock_get_client, mock_c
|
||||
jira_service.push_rt_submitted(db, test)
|
||||
|
||||
fields = mock_jira.update_issue_field.call_args[1]["fields"]
|
||||
assert fields[jira_service.JIRA_FIELD_RT_START_DATE] == "2026-03-01"
|
||||
assert fields[jira_service.JIRA_FIELD_RT_END_DATE] == "2026-03-05"
|
||||
assert fields[jira_service.JIRA_FIELD_RT_START_DATE] == "2026-03-01T09:00:00.000+0000"
|
||||
assert fields[jira_service.JIRA_FIELD_RT_END_DATE] == "2026-03-05T10:00:00.000+0000"
|
||||
|
||||
|
||||
@patch("app.services.jira_service.has_admin_jira_configured", return_value=True)
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
"""GET /tests/{id} must resolve assignee IDs into usernames directly, since
|
||||
GET /users/operators (the only other source of that mapping) is restricted
|
||||
to leads/managers — a plain operator viewing their own assigned test has no
|
||||
other way to find out who they're looking at. Regression: the detail page
|
||||
badge showed "RT: Unassigned" for the assigned operator themselves."""
|
||||
|
||||
from app.models.test import Test
|
||||
from app.models.technique import Technique
|
||||
|
||||
|
||||
def _seed_technique(db) -> Technique:
|
||||
technique = Technique(
|
||||
mitre_id="T9996", name="Assignee Username Test Technique",
|
||||
tactic="execution", platforms=["linux"],
|
||||
)
|
||||
db.add(technique)
|
||||
db.commit()
|
||||
db.refresh(technique)
|
||||
return technique
|
||||
|
||||
|
||||
def _seed_test(db, technique, created_by, **overrides) -> Test:
|
||||
test = Test(technique_id=technique.id, name="Assignee username test", created_by=created_by, **overrides)
|
||||
db.add(test)
|
||||
db.commit()
|
||||
db.refresh(test)
|
||||
return test
|
||||
|
||||
|
||||
def test_red_tech_assignee_username_resolved_for_the_assigned_operator(
|
||||
client, db, red_tech_headers, red_tech_user, red_lead_user,
|
||||
):
|
||||
technique = _seed_technique(db)
|
||||
test = _seed_test(db, technique, red_lead_user.id, red_tech_assignee=red_tech_user.id)
|
||||
|
||||
resp = client.get(f"/api/v1/tests/{test.id}", headers=red_tech_headers)
|
||||
|
||||
assert resp.status_code == 200, resp.text
|
||||
body = resp.json()
|
||||
assert body["red_tech_assignee"] == str(red_tech_user.id)
|
||||
assert body["red_tech_assignee_username"] == red_tech_user.username
|
||||
|
||||
|
||||
def test_blue_tech_assignee_username_resolved(client, db, red_lead_headers, red_lead_user, blue_tech_user):
|
||||
technique = _seed_technique(db)
|
||||
test = _seed_test(db, technique, red_lead_user.id, blue_tech_assignee=blue_tech_user.id)
|
||||
|
||||
resp = client.get(f"/api/v1/tests/{test.id}", headers=red_lead_headers)
|
||||
|
||||
assert resp.status_code == 200, resp.text
|
||||
assert resp.json()["blue_tech_assignee_username"] == blue_tech_user.username
|
||||
|
||||
|
||||
def test_assignee_username_is_none_when_unassigned(client, db, red_lead_headers, red_lead_user):
|
||||
technique = _seed_technique(db)
|
||||
test = _seed_test(db, technique, red_lead_user.id)
|
||||
|
||||
resp = client.get(f"/api/v1/tests/{test.id}", headers=red_lead_headers)
|
||||
|
||||
assert resp.status_code == 200, resp.text
|
||||
body = resp.json()
|
||||
assert body["red_tech_assignee"] is None
|
||||
assert body["red_tech_assignee_username"] is None
|
||||
Reference in New Issue
Block a user