""" File Sharing endpoints (Samba/NFS) – like cockpit-file-sharing """ from fastapi import APIRouter, Depends, HTTPException, status from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials from pydantic import BaseModel from typing import Optional from services.shares import share_manager from services.auth import auth_service router = APIRouter(prefix="/api/shares", tags=["shares"]) security = HTTPBearer() def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(security)): """Verify JWT token and return username""" username = auth_service.verify_token(credentials.credentials) if not username: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token" ) return username class CreateSambaShareRequest(BaseModel): name: str path: str comment: Optional[str] = None class CreateNFSShareRequest(BaseModel): path: str clients: str options: Optional[str] = None class SambaConfigRequest(BaseModel): parameters: dict[str, str] class SambaImportRequest(BaseModel): config_file: str # ============== SAMBA ============== @router.get("/samba") async def list_samba_shares(current_user: str = Depends(get_current_user)): """List all Samba shares""" try: shares = share_manager.list_samba_shares() return {"shares": shares} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.post("/samba") async def create_samba_share( request: CreateSambaShareRequest, current_user: str = Depends(get_current_user) ): """Create new Samba share""" if not request.name.strip() or not request.path.strip(): raise HTTPException(status_code=400, detail="Name and path are required") try: success = share_manager.create_samba_share( request.name, request.path, request.comment ) if not success: raise HTTPException(status_code=400, detail="Failed to create Samba share") return {"status": "created", "name": request.name} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.put("/samba/{name}") async def update_samba_share( name: str, request: CreateSambaShareRequest, current_user: str = Depends(get_current_user) ): """Update Samba share""" if not request.name.strip() or not request.path.strip(): raise HTTPException(status_code=400, detail="Name and path are required") try: success = share_manager.update_samba_share( name, request.name, request.path, request.comment ) if not success: raise HTTPException(status_code=404, detail=f"Samba share '{name}' not found") return {"status": "updated", "name": request.name} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.delete("/samba/{name}") async def delete_samba_share( name: str, current_user: str = Depends(get_current_user) ): """Delete Samba share""" try: success = share_manager.delete_samba_share(name) if not success: raise HTTPException(status_code=404, detail=f"Samba share '{name}' not found") return {"status": "deleted", "name": name} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.get("/samba/config") async def get_samba_config(current_user: str = Depends(get_current_user)): """Get Samba global configuration""" try: config = share_manager.get_samba_global_config() return config except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.put("/samba/config") async def set_samba_config( request: SambaConfigRequest, current_user: str = Depends(get_current_user) ): """Update Samba global configuration parameters""" try: success = share_manager.set_samba_global_config(request.parameters) if not success: raise HTTPException(status_code=400, detail="Failed to update Samba configuration") return {"status": "updated"} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.post("/samba/config/import") async def import_samba_config( request: SambaImportRequest, current_user: str = Depends(get_current_user) ): """Import Samba configuration using net conf import""" try: success = share_manager.import_samba_config(request.config_file) if not success: raise HTTPException(status_code=400, detail="Failed to import Samba configuration") return {"status": "imported", "config_file": request.config_file} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) # ============== NFS ============== @router.get("/nfs") async def list_nfs_shares(current_user: str = Depends(get_current_user)): """List all NFS shares""" try: shares = share_manager.list_nfs_shares() return {"shares": shares} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.post("/nfs") async def create_nfs_share( request: CreateNFSShareRequest, current_user: str = Depends(get_current_user) ): """Create new NFS share""" if not request.path.strip() or not request.clients.strip(): raise HTTPException(status_code=400, detail="Path and clients are required") try: success = share_manager.create_nfs_share( request.path, request.clients, request.options ) if not success: raise HTTPException(status_code=400, detail="Failed to create NFS share") return {"status": "created", "path": request.path} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.delete("/nfs") async def delete_nfs_share( path: str = None, current_user: str = Depends(get_current_user) ): """Delete NFS share""" try: if not path: raise HTTPException(status_code=400, detail="path parameter required") success = share_manager.delete_nfs_share(path) if not success: raise HTTPException(status_code=404, detail=f"NFS share '{path}' not found") return {"status": "deleted", "path": path} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.get("/nfs/config") async def get_nfs_config(current_user: str = Depends(get_current_user)): """Get NFS global configuration (/etc/exports)""" try: config = share_manager.get_nfs_config() return config except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.put("/nfs/config") async def set_nfs_config( request: SambaConfigRequest, current_user: str = Depends(get_current_user) ): """Update NFS global configuration (/etc/exports)""" try: success = share_manager.set_nfs_config(request.config) if not success: raise HTTPException(status_code=400, detail="Failed to update NFS configuration") return {"status": "updated"} except Exception as e: raise HTTPException(status_code=500, detail=str(e))