fix(jira): honor jira_email override in account-id lookup, not just email
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

lookup_user_jira_account_id() only ever searched by Aegis login email,
ignoring the jira_email override field that exists precisely for users
whose corporate Atlassian email differs from their Aegis login email
(the rest of jira_service.py already documents and uses this priority
order). Found via jesus-huertas, whose real Jira account uses a
different email than his Aegis account.
This commit is contained in:
kitos
2026-07-10 13:42:33 +02:00
parent a46aa157f3
commit 1535ddaa5d
2 changed files with 27 additions and 1 deletions
+4 -1
View File
@@ -295,6 +295,9 @@ def get_admin_jira_client(db: Session):
def lookup_user_jira_account_id(db: Session, user: User) -> bool: def lookup_user_jira_account_id(db: Session, user: User) -> bool:
"""Lookup *user*'s Atlassian account ID by email using the admin Jira client. """Lookup *user*'s Atlassian account ID by email using the admin Jira client.
Uses ``user.jira_email`` when set (for users whose corporate Atlassian
email differs from their Aegis login email), falling back to
``user.email`` — same resolution order as the rest of this module.
Updates ``user.jira_account_id`` in-place when found or changed. Updates ``user.jira_account_id`` in-place when found or changed.
Returns ``True`` when the value was updated, ``False`` otherwise. Returns ``True`` when the value was updated, ``False`` otherwise.
Non-fatal — all errors are logged at DEBUG level and swallowed. Non-fatal — all errors are logged at DEBUG level and swallowed.
@@ -302,7 +305,7 @@ def lookup_user_jira_account_id(db: Session, user: User) -> bool:
if not has_admin_jira_configured(db): if not has_admin_jira_configured(db):
return False return False
email = getattr(user, "email", None) email = getattr(user, "jira_email", None) or getattr(user, "email", None)
if not email: if not email:
return False return False
+23
View File
@@ -427,6 +427,7 @@ def _make_user(**overrides):
u.username = "gerardo-ruiz" u.username = "gerardo-ruiz"
u.email = "gerardo.ruiz@kaseya.com" u.email = "gerardo.ruiz@kaseya.com"
u.jira_account_id = None u.jira_account_id = None
u.jira_email = None
for k, v in overrides.items(): for k, v in overrides.items():
setattr(u, k, v) setattr(u, k, v)
return u return u
@@ -455,6 +456,28 @@ def test_lookup_user_jira_account_id_calls_with_valid_kwargs(mock_get_client, mo
assert user.jira_account_id == "abc123" assert user.jira_account_id == "abc123"
@patch("app.services.jira_service.has_admin_jira_configured", return_value=True)
@patch("app.services.jira_service.get_admin_jira_client")
def test_lookup_user_jira_account_id_prefers_jira_email_override(mock_get_client, mock_configured, db):
"""Regression: a user's real Atlassian email can differ from their Aegis
login email (e.g. jesus-huertas@kaseya.com in Aegis vs
jesus.rodenas@kaseya.com in Jira) — jira_email must take priority."""
mock_jira = MagicMock()
mock_jira.user_find_by_user_string.return_value = [
{"emailAddress": "jesus.rodenas@kaseya.com", "accountId": "jesus-account-id"}
]
mock_get_client.return_value = mock_jira
user = _make_user(email="jesus.huertas@kaseya.com", jira_email="jesus.rodenas@kaseya.com")
updated = jira_service.lookup_user_jira_account_id(db, user)
mock_jira.user_find_by_user_string.assert_called_once_with(
query="jesus.rodenas@kaseya.com", limit=10
)
assert updated is True
assert user.jira_account_id == "jesus-account-id"
@patch("app.services.jira_service.has_admin_jira_configured", return_value=True) @patch("app.services.jira_service.has_admin_jira_configured", return_value=True)
@patch("app.services.jira_service.get_admin_jira_client") @patch("app.services.jira_service.get_admin_jira_client")
def test_lookup_user_jira_account_id_no_match(mock_get_client, mock_configured, db): def test_lookup_user_jira_account_id_no_match(mock_get_client, mock_configured, db):