backup.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. from typing import Any, List, Optional
  2. from datetime import datetime
  3. from fastapi import APIRouter, Depends, HTTPException, Query, UploadFile, File
  4. from fastapi.responses import FileResponse
  5. from sqlalchemy.orm import Session
  6. from sqlalchemy import desc, asc
  7. from app.api.v1 import deps
  8. from app.schemas.backup import (
  9. BackupRecord,
  10. BackupSettings,
  11. BackupSettingsUpdate,
  12. BackupRecordList,
  13. RestorePreviewResponse,
  14. RestoreRequest,
  15. SendSmsRequest
  16. )
  17. from app.models.backup import BackupRecord as BackupRecordModel
  18. from app.services.backup_service import BackupService
  19. from app.models.user import User, UserRole
  20. router = APIRouter()
  21. @router.post("/create", response_model=BackupRecord)
  22. def create_backup(
  23. db: Session = Depends(deps.get_db),
  24. current_user: User = Depends(deps.get_current_active_user),
  25. ) -> Any:
  26. """
  27. Manually create a backup.
  28. """
  29. if current_user.role != UserRole.SUPER_ADMIN:
  30. raise HTTPException(status_code=403, detail="Not enough permissions")
  31. return BackupService.create_backup(db)
  32. @router.post("/upload", response_model=BackupRecord)
  33. def upload_backup(
  34. file: UploadFile = File(...),
  35. db: Session = Depends(deps.get_db),
  36. current_user: User = Depends(deps.get_current_active_user),
  37. ) -> Any:
  38. if current_user.role != UserRole.SUPER_ADMIN:
  39. raise HTTPException(status_code=403, detail="Not enough permissions")
  40. content = file.file.read()
  41. return BackupService.save_uploaded_backup(db, content, file.filename)
  42. @router.get("/", response_model=BackupRecordList)
  43. def read_backups(
  44. skip: int = 0,
  45. limit: int = 20,
  46. start_date: Optional[str] = None, # YYYY-MM-DD
  47. end_date: Optional[str] = None, # YYYY-MM-DD
  48. sort_order: str = "desc", # "desc" or "asc"
  49. db: Session = Depends(deps.get_db),
  50. current_user: User = Depends(deps.get_current_active_user),
  51. ) -> Any:
  52. """
  53. Retrieve backup records with pagination, filtering and sorting.
  54. """
  55. if current_user.role != UserRole.SUPER_ADMIN:
  56. raise HTTPException(status_code=403, detail="Not enough permissions")
  57. query = db.query(BackupRecordModel)
  58. if start_date:
  59. try:
  60. start_dt = datetime.strptime(start_date, "%Y-%m-%d")
  61. query = query.filter(BackupRecordModel.created_at >= start_dt)
  62. except ValueError:
  63. pass # Ignore invalid date format
  64. if end_date:
  65. try:
  66. end_dt = datetime.strptime(end_date, "%Y-%m-%d")
  67. end_dt = end_dt.replace(hour=23, minute=59, second=59)
  68. query = query.filter(BackupRecordModel.created_at <= end_dt)
  69. except ValueError:
  70. pass
  71. total = query.count()
  72. if sort_order == "asc":
  73. query = query.order_by(asc(BackupRecordModel.created_at))
  74. else:
  75. query = query.order_by(desc(BackupRecordModel.created_at))
  76. items = query.offset(skip).limit(limit).all()
  77. return {"total": total, "items": items}
  78. @router.get("/settings", response_model=BackupSettings)
  79. def read_backup_settings(
  80. db: Session = Depends(deps.get_db),
  81. current_user: User = Depends(deps.get_current_active_user),
  82. ) -> Any:
  83. if current_user.role != UserRole.SUPER_ADMIN:
  84. raise HTTPException(status_code=403, detail="Not enough permissions")
  85. return BackupService.get_settings(db)
  86. @router.put("/settings", response_model=BackupSettings)
  87. def update_backup_settings(
  88. settings_in: BackupSettingsUpdate,
  89. db: Session = Depends(deps.get_db),
  90. current_user: User = Depends(deps.get_current_active_user),
  91. ) -> Any:
  92. if current_user.role != UserRole.SUPER_ADMIN:
  93. raise HTTPException(status_code=403, detail="Not enough permissions")
  94. return BackupService.update_settings(db, settings_in.auto_backup_enabled, settings_in.backup_time)
  95. @router.get("/download/{id}")
  96. def download_backup(
  97. id: int,
  98. db: Session = Depends(deps.get_db),
  99. current_user: User = Depends(deps.get_current_active_user),
  100. ):
  101. if current_user.role != UserRole.SUPER_ADMIN:
  102. raise HTTPException(status_code=403, detail="Not enough permissions")
  103. backup = db.query(BackupRecordModel).filter(BackupRecordModel.id == id).first()
  104. if not backup:
  105. raise HTTPException(status_code=404, detail="Backup not found")
  106. return FileResponse(backup.file_path, filename=backup.filename, media_type='application/zip')
  107. @router.get("/{id}/restore/preview", response_model=RestorePreviewResponse)
  108. def preview_restore(
  109. id: int,
  110. type: str, # APPLICATIONS, USERS, MAPPINGS
  111. db: Session = Depends(deps.get_db),
  112. current_user: User = Depends(deps.get_current_active_user),
  113. ):
  114. if current_user.role != UserRole.SUPER_ADMIN:
  115. raise HTTPException(status_code=403, detail="Not enough permissions")
  116. return BackupService.preview_restore(db, id, type)
  117. @router.post("/send-sms")
  118. def send_restore_sms(
  119. req: SendSmsRequest,
  120. db: Session = Depends(deps.get_db),
  121. current_user: User = Depends(deps.get_current_active_user),
  122. ):
  123. if current_user.role != UserRole.SUPER_ADMIN:
  124. raise HTTPException(status_code=403, detail="Not enough permissions")
  125. BackupService.send_restore_sms(req.captcha_id, req.captcha_code, current_user)
  126. return {"message": "短信验证码已发送"}
  127. @router.post("/{id}/restore")
  128. def restore_backup(
  129. id: int,
  130. request: RestoreRequest,
  131. db: Session = Depends(deps.get_db),
  132. current_user: User = Depends(deps.get_current_active_user),
  133. ):
  134. if current_user.role != UserRole.SUPER_ADMIN:
  135. raise HTTPException(status_code=403, detail="Not enough permissions")
  136. return BackupService.restore_data(
  137. db,
  138. current_user,
  139. id,
  140. request.restore_type,
  141. request.field_mapping,
  142. request.password,
  143. request.sms_code,
  144. request.selected_files
  145. )