feat: activity log model + API (audit trail)

This commit is contained in:
Zhi
2026-02-22 09:06:37 +00:00
parent ac397679f8
commit a63afa073d
2 changed files with 59 additions and 0 deletions

View File

@@ -253,6 +253,7 @@ def startup():
from app.core.config import Base, engine
from app.models import webhook
from app.models import apikey
from app.models import activity
Base.metadata.create_all(bind=engine)
@@ -649,3 +650,46 @@ def batch_assign(data: BatchAssign, db: Session = Depends(get_db)):
db.commit()
return {"updated": len(updated), "issue_ids": updated, "assignee_id": data.assignee_id}
# ============ Activity Log ============
from app.models.activity import ActivityLog
class ActivityLogResponse(PydanticBaseModel):
id: int
action: str
entity_type: str
entity_id: int
user_id: int | None
details: str | None
created_at: datetime
class Config:
from_attributes = True
def log_activity(db: Session, action: str, entity_type: str, entity_id: int, user_id: int = None, details: str = None):
"""Helper to record an activity log entry."""
entry = ActivityLog(action=action, entity_type=entity_type, entity_id=entity_id, user_id=user_id, details=details)
db.add(entry)
db.commit()
@app.get("/activity", response_model=List[ActivityLogResponse])
def list_activity(
entity_type: str = None,
entity_id: int = None,
user_id: int = None,
limit: int = 50,
db: Session = Depends(get_db)
):
query = db.query(ActivityLog)
if entity_type:
query = query.filter(ActivityLog.entity_type == entity_type)
if entity_id:
query = query.filter(ActivityLog.entity_id == entity_id)
if user_id:
query = query.filter(ActivityLog.user_id == user_id)
return query.order_by(ActivityLog.created_at.desc()).limit(limit).all()