8f98bdd273
- ruff.toml: select E/W/F/I/N rules, line-length=120, drop legacy ignores - Auto-fix: sort 82 import blocks (isort), remove 29 unused imports, strip 6 trailing-whitespace blank lines in docstrings - main.py: move setup_logging and settings imports to top (E402) - errors.py: noqa N818 on DDD exception names (96 call sites, safe) - intel_service.py: noqa N817 for universal ET alias - atomic/elastic/sigma import services: move _MAX_UNCOMPRESSED_SIZE and _MAX_ENTRIES to module level (N806) - compliance_import_service.py: move SAMPLE_CONTROLS / CIS_CONTROLS to module level; wrap long description strings (N806 + E501) - snapshot_service.py: move STATUS_ORDER dict to module level (N806) - sigma_import_service.py: remove dead dedup_key expression (F841) - threat_actor_import_service.py: remove dead stix_to_actor expression (F841) - data_source.py, seed_demo.py, campaign_scheduler_service.py, lolbas_import_service.py: wrap lines exceeding 120 chars (E501) - d3fend_import_service.py: per-file E501 ignore (data file with long strings) All 439 unit tests pass. ruff check app/ → All checks passed!
58 lines
1.9 KiB
Python
58 lines
1.9 KiB
Python
"""Jira integration models — link Aegis entities to Jira issues."""
|
|
|
|
import enum
|
|
import uuid
|
|
|
|
from sqlalchemy import Column, DateTime, ForeignKey, Index, String, func
|
|
from sqlalchemy import Enum as SQLEnum
|
|
from sqlalchemy.dialects.postgresql import JSONB, UUID
|
|
from sqlalchemy.orm import relationship
|
|
|
|
from app.database import Base
|
|
|
|
|
|
class JiraLinkEntityType(str, enum.Enum):
|
|
test = "test"
|
|
technique = "technique"
|
|
campaign = "campaign"
|
|
evidence = "evidence"
|
|
|
|
|
|
class JiraSyncDirection(str, enum.Enum):
|
|
aegis_to_jira = "aegis_to_jira"
|
|
jira_to_aegis = "jira_to_aegis"
|
|
bidirectional = "bidirectional"
|
|
|
|
|
|
class JiraLink(Base):
|
|
"""Associates an Aegis entity with a Jira issue for bidirectional sync."""
|
|
|
|
__tablename__ = "jira_links"
|
|
|
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
entity_type = Column(SQLEnum(JiraLinkEntityType), nullable=False)
|
|
entity_id = Column(UUID(as_uuid=True), nullable=False)
|
|
jira_issue_key = Column(String(50), nullable=False)
|
|
jira_issue_id = Column(String(50))
|
|
jira_project_key = Column(String(20))
|
|
jira_status = Column(String(100))
|
|
jira_priority = Column(String(50))
|
|
jira_assignee = Column(String(255))
|
|
jira_story_points = Column(String(10))
|
|
sync_direction = Column(
|
|
SQLEnum(JiraSyncDirection), default=JiraSyncDirection.bidirectional
|
|
)
|
|
last_synced_at = Column(DateTime)
|
|
sync_metadata = Column(JSONB, default={})
|
|
created_by = Column(UUID(as_uuid=True), ForeignKey("users.id"))
|
|
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|
|
|
|
creator = relationship("User", foreign_keys=[created_by])
|
|
|
|
__table_args__ = (
|
|
Index("ix_jira_links_entity_id", "entity_id"),
|
|
Index("ix_jira_links_issue_key", "jira_issue_key"),
|
|
Index("ix_jira_links_entity_type_entity_id", "entity_type", "entity_id"),
|
|
)
|