from typing import Any, List, Optional from datetime import datetime from fastapi import APIRouter, Depends, HTTPException, Query, UploadFile, File from fastapi.responses import FileResponse from sqlalchemy.orm import Session from sqlalchemy import desc, asc from app.api.v1 import deps from app.schemas.backup import ( BackupRecord, BackupSettings, BackupSettingsUpdate, BackupRecordList, RestorePreviewResponse, RestoreRequest, SendSmsRequest ) from app.models.backup import BackupRecord as BackupRecordModel from app.services.backup_service import BackupService from app.models.user import User, UserRole router = APIRouter() @router.post("/create", response_model=BackupRecord) def create_backup( db: Session = Depends(deps.get_db), current_user: User = Depends(deps.get_current_active_user), ) -> Any: """ Manually create a backup. """ if current_user.role != UserRole.SUPER_ADMIN: raise HTTPException(status_code=403, detail="Not enough permissions") return BackupService.create_backup(db) @router.post("/upload", response_model=BackupRecord) def upload_backup( file: UploadFile = File(...), db: Session = Depends(deps.get_db), current_user: User = Depends(deps.get_current_active_user), ) -> Any: if current_user.role != UserRole.SUPER_ADMIN: raise HTTPException(status_code=403, detail="Not enough permissions") content = file.file.read() return BackupService.save_uploaded_backup(db, content, file.filename) @router.get("/", response_model=BackupRecordList) def read_backups( skip: int = 0, limit: int = 20, start_date: Optional[str] = None, # YYYY-MM-DD end_date: Optional[str] = None, # YYYY-MM-DD sort_order: str = "desc", # "desc" or "asc" db: Session = Depends(deps.get_db), current_user: User = Depends(deps.get_current_active_user), ) -> Any: """ Retrieve backup records with pagination, filtering and sorting. """ if current_user.role != UserRole.SUPER_ADMIN: raise HTTPException(status_code=403, detail="Not enough permissions") query = db.query(BackupRecordModel) if start_date: try: start_dt = datetime.strptime(start_date, "%Y-%m-%d") query = query.filter(BackupRecordModel.created_at >= start_dt) except ValueError: pass # Ignore invalid date format if end_date: try: end_dt = datetime.strptime(end_date, "%Y-%m-%d") end_dt = end_dt.replace(hour=23, minute=59, second=59) query = query.filter(BackupRecordModel.created_at <= end_dt) except ValueError: pass total = query.count() if sort_order == "asc": query = query.order_by(asc(BackupRecordModel.created_at)) else: query = query.order_by(desc(BackupRecordModel.created_at)) items = query.offset(skip).limit(limit).all() return {"total": total, "items": items} @router.get("/settings", response_model=BackupSettings) def read_backup_settings( db: Session = Depends(deps.get_db), current_user: User = Depends(deps.get_current_active_user), ) -> Any: if current_user.role != UserRole.SUPER_ADMIN: raise HTTPException(status_code=403, detail="Not enough permissions") return BackupService.get_settings(db) @router.put("/settings", response_model=BackupSettings) def update_backup_settings( settings_in: BackupSettingsUpdate, db: Session = Depends(deps.get_db), current_user: User = Depends(deps.get_current_active_user), ) -> Any: if current_user.role != UserRole.SUPER_ADMIN: raise HTTPException(status_code=403, detail="Not enough permissions") return BackupService.update_settings(db, settings_in.auto_backup_enabled, settings_in.backup_time) @router.get("/download/{id}") def download_backup( id: int, db: Session = Depends(deps.get_db), current_user: User = Depends(deps.get_current_active_user), ): if current_user.role != UserRole.SUPER_ADMIN: raise HTTPException(status_code=403, detail="Not enough permissions") backup = db.query(BackupRecordModel).filter(BackupRecordModel.id == id).first() if not backup: raise HTTPException(status_code=404, detail="Backup not found") return FileResponse(backup.file_path, filename=backup.filename, media_type='application/zip') @router.get("/{id}/restore/preview", response_model=RestorePreviewResponse) def preview_restore( id: int, type: str, # APPLICATIONS, USERS, MAPPINGS db: Session = Depends(deps.get_db), current_user: User = Depends(deps.get_current_active_user), ): if current_user.role != UserRole.SUPER_ADMIN: raise HTTPException(status_code=403, detail="Not enough permissions") return BackupService.preview_restore(db, id, type) @router.post("/send-sms") def send_restore_sms( req: SendSmsRequest, db: Session = Depends(deps.get_db), current_user: User = Depends(deps.get_current_active_user), ): if current_user.role != UserRole.SUPER_ADMIN: raise HTTPException(status_code=403, detail="Not enough permissions") BackupService.send_restore_sms(req.captcha_id, req.captcha_code, current_user) return {"message": "短信验证码已发送"} @router.post("/{id}/restore") def restore_backup( id: int, request: RestoreRequest, db: Session = Depends(deps.get_db), current_user: User = Depends(deps.get_current_active_user), ): if current_user.role != UserRole.SUPER_ADMIN: raise HTTPException(status_code=403, detail="Not enough permissions") return BackupService.restore_data( db, current_user, id, request.restore_type, request.field_mapping, request.password, request.sms_code, request.selected_files )