admin.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. """
  2. Admin service for handling administrative operations.
  3. """
  4. import logging
  5. from typing import Optional, List
  6. from fastapi import Request
  7. from core.config import get_settings
  8. logger = logging.getLogger(__name__)
  9. class AdminService:
  10. """Service for managing administrative operations."""
  11. def __init__(self, versions_fetcher=None):
  12. """
  13. Initialize the admin service.
  14. Args:
  15. versions_fetcher: VersionsFetcher instance for managing remotes
  16. """
  17. self.versions_fetcher = versions_fetcher
  18. self.settings = get_settings()
  19. def get_auth_token(self) -> Optional[str]:
  20. """
  21. Retrieve the authorization token from file or environment.
  22. Returns:
  23. The authorization token if found, None otherwise
  24. """
  25. try:
  26. # Try to read the secret token from the file
  27. token_file_path = self.settings.admin_token_file_path
  28. with open(token_file_path, 'r') as file:
  29. token = file.read().strip()
  30. return token
  31. except (FileNotFoundError, PermissionError) as e:
  32. logger.error(
  33. f"Couldn't open token file at "
  34. f"{self.settings.admin_token_file_path}: {e}. "
  35. "Checking environment for token."
  36. )
  37. # If the file does not exist or no permission, check environment
  38. return self.settings.admin_token_env
  39. except Exception as e:
  40. logger.error(
  41. f"Unexpected error reading token file at "
  42. f"{self.settings.admin_token_file_path}: {e}. "
  43. "Checking environment for token."
  44. )
  45. # For any other error, fall back to environment variable
  46. return self.settings.admin_token_env
  47. async def verify_token(self, token: str) -> bool:
  48. """
  49. Verify that the provided token matches the expected admin token.
  50. Args:
  51. token: The token to verify
  52. Returns:
  53. True if token is valid, False otherwise
  54. Raises:
  55. RuntimeError: If admin token is not configured on server
  56. """
  57. expected_token = self.get_auth_token()
  58. if expected_token is None:
  59. logger.error("No admin token configured")
  60. raise RuntimeError("Admin token not configured on server")
  61. return token == expected_token
  62. async def refresh_remotes(self) -> List[str]:
  63. """
  64. Trigger a refresh of remote metadata.
  65. Returns:
  66. List of remote names that were refreshed
  67. Raises:
  68. Exception: If refresh operation fails
  69. """
  70. logger.info("Triggering remote metadata refresh")
  71. # Reload remotes.json
  72. self.versions_fetcher.reload_remotes_json()
  73. # Get list of remotes that are now available
  74. remotes_info = self.versions_fetcher.get_all_remotes_info()
  75. remotes_refreshed = [remote.name for remote in remotes_info]
  76. logger.info(
  77. f"Successfully refreshed {len(remotes_refreshed)} remotes: "
  78. f"{remotes_refreshed}"
  79. )
  80. return remotes_refreshed
  81. def get_admin_service(request: Request) -> AdminService:
  82. """
  83. Get AdminService instance with dependencies from app state.
  84. Args:
  85. request: FastAPI Request object
  86. Returns:
  87. AdminService instance initialized with app state dependencies
  88. """
  89. return AdminService(versions_fetcher=request.app.state.versions_fetcher)