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.core.config import Base, engine
from app.models import webhook from app.models import webhook
from app.models import apikey from app.models import apikey
from app.models import activity
Base.metadata.create_all(bind=engine) Base.metadata.create_all(bind=engine)
@@ -649,3 +650,46 @@ def batch_assign(data: BatchAssign, db: Session = Depends(get_db)):
db.commit() db.commit()
return {"updated": len(updated), "issue_ids": updated, "assignee_id": data.assignee_id} 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()

15
app/models/activity.py Normal file
View File

@@ -0,0 +1,15 @@
from sqlalchemy import Column, Integer, String, Text, DateTime, ForeignKey
from sqlalchemy.sql import func
from app.core.config import Base
class ActivityLog(Base):
__tablename__ = "activity_logs"
id = Column(Integer, primary_key=True, index=True)
action = Column(String(50), nullable=False) # e.g. "issue.created", "comment.added"
entity_type = Column(String(50), nullable=False) # "issue", "project", "comment"
entity_id = Column(Integer, nullable=False)
user_id = Column(Integer, ForeignKey("users.id"), nullable=True)
details = Column(Text, nullable=True) # JSON string
created_at = Column(DateTime(timezone=True), server_default=func.now())