feat: unified api.js auth + Pydantic models + JWT security hardening
- All Alpine.js pages now use shared api.js for JWT auto-refresh (9 pages) - Dashboard uses /servers/stats endpoint instead of fetching all servers - Replaced all raw dict params with Pydantic models (agent, settings, presets) - Added AgentHeartbeat, AgentExec, SettingUpdatePayload, DbCredentialCreate schemas - JWT decode now requires exp+sub claims; better error logging - ServerService.push_to_servers delegates to SyncService.batch_push - SyncService handles None audit_repo/retry_repo gracefully - Branding: web/app.js + web/style.css MultiSync→Nexus Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -88,29 +88,29 @@ class ServerService:
|
||||
source_path: str,
|
||||
sync_mode: str = "incremental",
|
||||
operator: str = "admin",
|
||||
batch_size: int = 50,
|
||||
concurrency: int = 10,
|
||||
) -> Dict[int, SyncLog]:
|
||||
"""Push files to multiple servers in batches"""
|
||||
results = {}
|
||||
servers = []
|
||||
for id in server_ids:
|
||||
server = await self.server_repo.get_by_id(id)
|
||||
if server:
|
||||
servers.append(server)
|
||||
"""Push files to multiple servers — delegates to SyncService.batch_push.
|
||||
|
||||
# TODO: Implement batch push with asyncio.Semaphore(10)
|
||||
# batch_size=50, interval=30s
|
||||
for server in servers:
|
||||
target_path = server.target_path or f"/www/wwwroot/"
|
||||
log = SyncLog(
|
||||
server_id=server.id,
|
||||
source_path=source_path,
|
||||
target_path=target_path,
|
||||
trigger_type="batch",
|
||||
operator=operator,
|
||||
status="pending",
|
||||
sync_mode=sync_mode,
|
||||
)
|
||||
log = await self.sync_log_repo.create(log)
|
||||
results[server.id] = log
|
||||
Note: API routes should use SyncService directly via Depends(get_sync_service).
|
||||
This method exists for internal callers (e.g. schedule_runner) that already
|
||||
have a ServerService instance.
|
||||
"""
|
||||
from server.application.services.sync_service import SyncService
|
||||
|
||||
return results
|
||||
# Build a SyncService sharing our existing repos + the extra ones it needs
|
||||
sync_service = SyncService(
|
||||
server_repo=self.server_repo,
|
||||
sync_log_repo=self.sync_log_repo,
|
||||
audit_repo=None, # audit handled by caller if needed
|
||||
retry_repo=None, # retry handled by caller if needed
|
||||
)
|
||||
return await sync_service.batch_push(
|
||||
server_ids=server_ids,
|
||||
source_path=source_path,
|
||||
sync_mode=sync_mode,
|
||||
operator=operator,
|
||||
batch_size=batch_size,
|
||||
concurrency=concurrency,
|
||||
)
|
||||
Reference in New Issue
Block a user