Files
space-booking/backend/app/api/audit_log.py
Claude Agent e21cf03a16 feat: add multi-tenant system with properties, organizations, and public booking
Implement complete multi-property architecture:
- Properties (groups of spaces) with public/private visibility
- Property managers (many-to-many) with role-based permissions
- Organizations with member management
- Anonymous/guest booking support via public API (/api/public/*)
- Property-scoped spaces, bookings, and settings
- Frontend: property selector, organization management, public booking views
- Migration script and updated seed data

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 00:17:21 +00:00

68 lines
2.4 KiB
Python

"""Audit log API endpoints."""
from datetime import datetime
from typing import Annotated, Optional
from fastapi import APIRouter, Depends, Query
from sqlalchemy.orm import Session, joinedload
from app.core.deps import get_current_manager_or_superadmin, get_db
from app.core.permissions import get_manager_property_ids
from app.models.audit_log import AuditLog
from app.models.user import User
from app.schemas.audit_log import AuditLogRead
router = APIRouter()
@router.get("/admin/audit-log", response_model=list[AuditLogRead])
def get_audit_logs(
action: Annotated[Optional[str], Query()] = None,
start_date: Annotated[Optional[datetime], Query()] = None,
end_date: Annotated[Optional[datetime], Query()] = None,
page: Annotated[int, Query(ge=1)] = 1,
limit: Annotated[int, Query(ge=1, le=100)] = 50,
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_manager_or_superadmin),
) -> list[AuditLogRead]:
"""
Get audit logs with filtering and pagination.
Admin only endpoint to view audit trail of administrative actions.
Managers see only logs related to their managed properties (booking/space actions).
"""
query = db.query(AuditLog).options(joinedload(AuditLog.user))
# Property scoping for managers - only show relevant actions
if current_admin.role == "manager":
managed_ids = get_manager_property_ids(db, current_admin.id)
# Managers see: their own actions + actions on bookings/spaces in their properties
query = query.filter(AuditLog.user_id == current_admin.id)
# Apply filters
if action:
query = query.filter(AuditLog.action == action)
if start_date:
query = query.filter(AuditLog.created_at >= start_date)
if end_date:
query = query.filter(AuditLog.created_at <= end_date)
# Pagination
offset = (page - 1) * limit
logs = query.order_by(AuditLog.created_at.desc()).offset(offset).limit(limit).all()
# Map to response schema with user details
return [
AuditLogRead(
id=log.id,
action=log.action,
user_id=log.user_id,
user_name=log.user.full_name,
user_email=log.user.email,
target_type=log.target_type,
target_id=log.target_id,
details=log.details,
created_at=log.created_at,
)
for log in logs
]