LinkDesk/backend/routers/activities.py

240 lines
8.2 KiB
Python

from fastapi import APIRouter, Depends, Query
from sqlalchemy.orm import Session
from sqlalchemy import desc
from typing import List, Optional
from datetime import datetime, timedelta
from database import get_db
from models.user import User
from models.activity import Activity, ActivityType
from models.project import ProjectMember
from schemas.activity import ActivityResponse
from utils.auth import get_current_user
from utils.activity import ActivityService
router = APIRouter(prefix="/activities", tags=["activities"])
@router.get("/project/{project_id}", response_model=List[ActivityResponse])
def get_project_activities(
project_id: int,
skip: int = Query(0, ge=0),
limit: int = Query(50, ge=1, le=100),
type_filter: Optional[ActivityType] = None,
days: Optional[int] = Query(None, ge=1, le=90),
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""Get activity feed for a specific project (excludes activities for deleted records)."""
# Verify user has access to the project
member = db.query(ProjectMember).filter(
ProjectMember.project_id == project_id,
ProjectMember.user_id == current_user.id
).first()
if not member and not current_user.is_admin:
from fastapi import HTTPException
raise HTTPException(status_code=403, detail="Access denied to this project")
# Use ActivityService to get activities excluding deleted records
activities = ActivityService.get_activities_excluding_deleted(
db=db,
project_id=project_id,
skip=skip,
limit=limit,
type_filter=type_filter,
days=days
)
return activities
@router.get("/task/{task_id}", response_model=List[ActivityResponse])
def get_task_activities(
task_id: int,
skip: int = Query(0, ge=0),
limit: int = Query(50, ge=1, le=100),
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""Get activity timeline for a specific task (excludes activities for deleted records)."""
from models.task import Task
# Verify user has access to the task and it's not deleted
task = db.query(Task).filter(Task.id == task_id, Task.deleted_at.is_(None)).first()
if not task:
from fastapi import HTTPException
raise HTTPException(status_code=404, detail="Task not found")
# Check if user is a member of the project
member = db.query(ProjectMember).filter(
ProjectMember.project_id == task.project_id,
ProjectMember.user_id == current_user.id
).first()
if not member and not current_user.is_admin:
from fastapi import HTTPException
raise HTTPException(status_code=403, detail="Access denied to this task")
# Use ActivityService to get activities excluding deleted records
activities = ActivityService.get_activities_excluding_deleted(
db=db,
task_id=task_id,
skip=skip,
limit=limit
)
return activities
@router.get("/user/{user_id}", response_model=List[ActivityResponse])
def get_user_activities(
user_id: int,
skip: int = Query(0, ge=0),
limit: int = Query(50, ge=1, le=100),
days: Optional[int] = Query(None, ge=1, le=90),
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""Get activity history for a specific user (excludes activities for deleted records)."""
# Users can only view their own activity unless they're admin
if user_id != current_user.id and not current_user.is_admin:
from fastapi import HTTPException
raise HTTPException(status_code=403, detail="Access denied")
# Use ActivityService to get activities excluding deleted records
activities = ActivityService.get_activities_excluding_deleted(
db=db,
user_id=user_id,
skip=skip,
limit=limit,
days=days
)
return activities
@router.get("/recent", response_model=List[ActivityResponse])
def get_recent_activities(
skip: int = Query(0, ge=0),
limit: int = Query(20, ge=1, le=50),
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""Get recent activities from all projects the user has access to (excludes activities for deleted records)."""
# Get all projects the user is a member of
project_ids = db.query(ProjectMember.project_id).filter(
ProjectMember.user_id == current_user.id
).all()
project_ids = [pid[0] for pid in project_ids]
if not project_ids and not current_user.is_admin:
return []
# For non-admin users, filter by their project access
if not current_user.is_admin:
# Get activities from user's projects, excluding deleted records
all_activities = []
for project_id in project_ids:
activities = ActivityService.get_activities_excluding_deleted(
db=db,
project_id=project_id,
skip=0,
limit=limit * 2 # Get more to account for filtering
)
all_activities.extend(activities)
# Sort by created_at and apply pagination
all_activities.sort(key=lambda x: x.created_at, reverse=True)
return all_activities[skip:skip + limit]
else:
# Admin gets all activities excluding deleted records
activities = ActivityService.get_activities_excluding_deleted(
db=db,
skip=skip,
limit=limit
)
return activities
# Admin-only endpoints that include activities for deleted records
@router.get("/admin/project/{project_id}/all", response_model=List[ActivityResponse])
def get_project_activities_including_deleted(
project_id: int,
skip: int = Query(0, ge=0),
limit: int = Query(50, ge=1, le=100),
type_filter: Optional[ActivityType] = None,
days: Optional[int] = Query(None, ge=1, le=90),
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""Get all activity feed for a specific project including deleted records (admin only)."""
if not current_user.is_admin:
from fastapi import HTTPException
raise HTTPException(status_code=403, detail="Admin access required")
# Use ActivityService to get all activities including deleted records
activities = ActivityService.get_activities_including_deleted(
db=db,
project_id=project_id,
skip=skip,
limit=limit,
type_filter=type_filter,
days=days
)
return activities
@router.get("/admin/user/{user_id}/all", response_model=List[ActivityResponse])
def get_user_activities_including_deleted(
user_id: int,
skip: int = Query(0, ge=0),
limit: int = Query(50, ge=1, le=100),
days: Optional[int] = Query(None, ge=1, le=90),
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""Get all activity history for a specific user including deleted records (admin only)."""
if not current_user.is_admin:
from fastapi import HTTPException
raise HTTPException(status_code=403, detail="Admin access required")
# Use ActivityService to get all activities including deleted records
activities = ActivityService.get_activities_including_deleted(
db=db,
user_id=user_id,
skip=skip,
limit=limit,
days=days
)
return activities
@router.get("/admin/all", response_model=List[ActivityResponse])
def get_all_activities_including_deleted(
skip: int = Query(0, ge=0),
limit: int = Query(50, ge=1, le=100),
type_filter: Optional[ActivityType] = None,
days: Optional[int] = Query(None, ge=1, le=90),
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""Get all activities including deleted records (admin only)."""
if not current_user.is_admin:
from fastapi import HTTPException
raise HTTPException(status_code=403, detail="Admin access required")
# Use ActivityService to get all activities including deleted records
activities = ActivityService.get_activities_including_deleted(
db=db,
skip=skip,
limit=limit,
type_filter=type_filter,
days=days
)
return activities