feat(jira): add editable jira_email field per user
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Users can now set a separate Atlassian email for Jira authentication in Settings → Profile → Jira Integration. Falls back to the Aegis account email when not set, so existing setups are unaffected. - Migration b043: adds jira_email column to users table - User model/schema: expose jira_email read/write - jira_service: _effective_jira_email() uses jira_email ?? email - Frontend: replaces read-only email display with editable input Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,10 +2,11 @@
|
||||
|
||||
Authentication model
|
||||
--------------------
|
||||
Each Aegis user authenticates to Jira with their own corporate email
|
||||
(``user.email``) and their personal Atlassian API token
|
||||
(``user.jira_api_token``). This way every Jira action is traceable to a
|
||||
real person rather than a shared service account.
|
||||
Each Aegis user authenticates to Jira with their own Atlassian email and
|
||||
personal API token. The email used is ``user.jira_email`` when set, falling
|
||||
back to ``user.email`` (the Aegis account email). This lets users specify a
|
||||
separate corporate Atlassian email without changing their Aegis login.
|
||||
The token is stored in ``user.jira_api_token``.
|
||||
|
||||
Admin configuration
|
||||
-------------------
|
||||
@@ -107,9 +108,15 @@ def upsert_jira_config(db: Session, key: str, value: str) -> None:
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _effective_jira_email(user: User) -> Optional[str]:
|
||||
"""Return the email to use for Jira auth: jira_email if set, otherwise email."""
|
||||
return getattr(user, "jira_email", None) or user.email
|
||||
|
||||
|
||||
def get_user_jira_client(user: User, db: Session):
|
||||
"""Build an Atlassian Jira client authenticated as *user*.
|
||||
|
||||
Uses ``user.jira_email`` when set, otherwise falls back to ``user.email``.
|
||||
Raises ``InvalidOperationError`` when configuration is incomplete so
|
||||
callers can surface meaningful error messages.
|
||||
"""
|
||||
@@ -120,23 +127,24 @@ def get_user_jira_client(user: User, db: Session):
|
||||
"System Settings → Jira Configuration."
|
||||
)
|
||||
|
||||
if not user.email:
|
||||
auth_email = _effective_jira_email(user)
|
||||
if not auth_email:
|
||||
raise InvalidOperationError(
|
||||
"Your account has no email address. Set one in your profile before "
|
||||
"using the Jira integration."
|
||||
"No email configured for Jira authentication. "
|
||||
"Set a Jira email in Settings → Profile → Jira Integration."
|
||||
)
|
||||
|
||||
if not user.jira_api_token:
|
||||
raise InvalidOperationError(
|
||||
"You have not configured a Jira API token. "
|
||||
"Go to Settings → Integrations and add your personal Atlassian token."
|
||||
"Go to Settings → Profile → Jira Integration and add your personal Atlassian token."
|
||||
)
|
||||
|
||||
from atlassian import Jira
|
||||
|
||||
return Jira(
|
||||
url=jira_url,
|
||||
username=user.email,
|
||||
username=auth_email,
|
||||
password=user.jira_api_token,
|
||||
cloud=True,
|
||||
)
|
||||
@@ -144,7 +152,7 @@ def get_user_jira_client(user: User, db: Session):
|
||||
|
||||
def has_jira_configured(user: User, db: Session) -> bool:
|
||||
"""Return True if *user* has everything needed to call Jira."""
|
||||
return bool(get_jira_url(db) and user.email and user.jira_api_token)
|
||||
return bool(get_jira_url(db) and _effective_jira_email(user) and user.jira_api_token)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user