From 3cf2b1bc49e1e495d900f61661909522cfe72258 Mon Sep 17 00:00:00 2001 From: Zhi Date: Fri, 27 Feb 2026 09:39:39 +0000 Subject: [PATCH] feat: auto activity logging on issue create/delete, fix schema db.add bug --- app/api/routers/issues.py | 5 ++++- app/api/routers/projects.py | 1 + app/services/activity.py | 18 ++++++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 app/services/activity.py diff --git a/app/api/routers/issues.py b/app/api/routers/issues.py index 0162ffe..7369dd0 100644 --- a/app/api/routers/issues.py +++ b/app/api/routers/issues.py @@ -13,6 +13,7 @@ from app.services.webhook import fire_webhooks_sync from app.models.notification import Notification as NotificationModel from app.api.deps import get_current_user_or_apikey from app.api.rbac import check_project_role +from app.services.activity import log_activity router = APIRouter(tags=["Issues"]) @@ -29,7 +30,7 @@ def _notify_user(db, user_id, ntype, title, message=None, entity_type=None, enti @router.post("/issues", response_model=schemas.IssueResponse, status_code=status.HTTP_201_CREATED) def create_issue(issue: schemas.IssueCreate, bg: BackgroundTasks, db: Session = Depends(get_db), current_user: models.User = Depends(get_current_user_or_apikey)): - db.add(issue); check_project_role(db, current_user.id, issue.project_id, min_role="dev") + check_project_role(db, current_user.id, issue.project_id, min_role="dev") db_issue = models.Issue(**issue.model_dump()) db.add(db_issue) db.commit() @@ -38,6 +39,7 @@ def create_issue(issue: schemas.IssueCreate, bg: BackgroundTasks, db: Session = bg.add_task(fire_webhooks_sync, event, {"issue_id": db_issue.id, "title": db_issue.title, "type": db_issue.issue_type, "status": db_issue.status}, db_issue.project_id, db) + log_activity(db, "issue.created", "issue", db_issue.id, current_user.id, {"title": db_issue.title}) return db_issue @@ -116,6 +118,7 @@ def delete_issue(issue_id: int, db: Session = Depends(get_db), current_user: mod issue = db.query(models.Issue).filter(models.Issue.id == issue_id).first() if not issue: raise HTTPException(status_code=404, detail="Issue not found") + log_activity(db, "issue.deleted", "issue", issue.id, current_user.id, {"title": issue.title}) db.delete(issue) db.commit() return None diff --git a/app/api/routers/projects.py b/app/api/routers/projects.py index 4ca9ab1..f07af99 100644 --- a/app/api/routers/projects.py +++ b/app/api/routers/projects.py @@ -8,6 +8,7 @@ from app.models import models from app.schemas import schemas from app.api.deps import get_current_user_or_apikey from app.api.rbac import check_project_role +from app.services.activity import log_activity router = APIRouter(prefix="/projects", tags=["Projects"]) diff --git a/app/services/activity.py b/app/services/activity.py new file mode 100644 index 0000000..d924f4c --- /dev/null +++ b/app/services/activity.py @@ -0,0 +1,18 @@ +"""Activity logging helper — auto-record CRUD operations.""" +import json +from sqlalchemy.orm import Session +from app.models.activity import ActivityLog + + +def log_activity(db: Session, action: str, entity_type: str, entity_id: int, user_id: int = None, details: dict = None): + """Record an activity log entry.""" + entry = ActivityLog( + action=action, + entity_type=entity_type, + entity_id=entity_id, + user_id=user_id, + details=json.dumps(details) if details else None, + ) + db.add(entry) + db.commit() + return entry