feat: explorador de archivos local y autenticacion/conexion a unidad de red UNC en storage root
This commit is contained in:
@@ -1,5 +1,12 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from typing import Optional
|
||||
import os
|
||||
import string
|
||||
import uuid
|
||||
from pathlib import Path
|
||||
from pydantic import BaseModel
|
||||
|
||||
from app.core.database import get_db
|
||||
from app.api.deps import require_admin
|
||||
from app.models.models import User
|
||||
@@ -8,6 +15,11 @@ from app.services.settings_service import get_all_settings, update_settings_serv
|
||||
|
||||
router = APIRouter(prefix="/settings", tags=["System Settings"])
|
||||
|
||||
class TestShareRequest(BaseModel):
|
||||
path: str
|
||||
username: str
|
||||
password: str
|
||||
|
||||
@router.get("", response_model=SystemSettingsResponse)
|
||||
async def get_settings(
|
||||
db: AsyncSession = Depends(get_db),
|
||||
@@ -22,6 +34,13 @@ async def get_settings(
|
||||
"default_keep_daily": int(settings_dict.get("default_keep_daily", 7)),
|
||||
"default_keep_weekly": int(settings_dict.get("default_keep_weekly", 4)),
|
||||
"default_keep_monthly": int(settings_dict.get("default_keep_monthly", 12)),
|
||||
"auth_mode": settings_dict.get("auth_mode", "local"),
|
||||
"radius_host": settings_dict.get("radius_host", ""),
|
||||
"radius_port": int(settings_dict.get("radius_port", 1812)) if settings_dict.get("radius_port") else 1812,
|
||||
"radius_secret": settings_dict.get("radius_secret", ""),
|
||||
"storage_network_enabled": settings_dict.get("storage_network_enabled", "false").lower() == "true",
|
||||
"storage_network_user": settings_dict.get("storage_network_user", ""),
|
||||
"storage_network_pass": settings_dict.get("storage_network_pass", ""),
|
||||
}
|
||||
|
||||
@router.put("", response_model=SystemSettingsResponse)
|
||||
@@ -49,4 +68,95 @@ async def update_settings(
|
||||
"default_keep_daily": int(settings_dict.get("default_keep_daily", 7)),
|
||||
"default_keep_weekly": int(settings_dict.get("default_keep_weekly", 4)),
|
||||
"default_keep_monthly": int(settings_dict.get("default_keep_monthly", 12)),
|
||||
"auth_mode": settings_dict.get("auth_mode", "local"),
|
||||
"radius_host": settings_dict.get("radius_host", ""),
|
||||
"radius_port": int(settings_dict.get("radius_port", 1812)) if settings_dict.get("radius_port") else 1812,
|
||||
"radius_secret": settings_dict.get("radius_secret", ""),
|
||||
"storage_network_enabled": settings_dict.get("storage_network_enabled", "false").lower() == "true",
|
||||
"storage_network_user": settings_dict.get("storage_network_user", ""),
|
||||
"storage_network_pass": settings_dict.get("storage_network_pass", ""),
|
||||
}
|
||||
|
||||
@router.get("/explore-dir")
|
||||
async def explore_directory(
|
||||
path: Optional[str] = None,
|
||||
admin_user: User = Depends(require_admin)
|
||||
):
|
||||
"""
|
||||
Explore directories on the host filesystem.
|
||||
"""
|
||||
import platform
|
||||
|
||||
if not path or path.strip() == "":
|
||||
if platform.system().lower() == "windows":
|
||||
drives = []
|
||||
for letter in string.ascii_uppercase:
|
||||
drive_path = f"{letter}:\\"
|
||||
if os.path.exists(drive_path):
|
||||
drives.append({"name": drive_path, "path": drive_path})
|
||||
return {"current_path": "", "folders": drives}
|
||||
else:
|
||||
return {"current_path": "/", "folders": [{"name": "/", "path": "/"}]}
|
||||
|
||||
# Resolve path
|
||||
target = Path(path).resolve()
|
||||
if not target.exists() or not target.is_dir():
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"The path '{path}' does not exist or is not a directory."
|
||||
)
|
||||
|
||||
try:
|
||||
folders = []
|
||||
for entry in os.scandir(target):
|
||||
try:
|
||||
if entry.is_dir():
|
||||
folders.append({
|
||||
"name": entry.name,
|
||||
"path": str(Path(entry.path).resolve())
|
||||
})
|
||||
except Exception:
|
||||
continue # Skip inaccessible
|
||||
|
||||
folders.sort(key=lambda x: x["name"].lower())
|
||||
|
||||
return {
|
||||
"current_path": str(target),
|
||||
"parent_path": str(target.parent) if target.parent != target else None,
|
||||
"folders": folders
|
||||
}
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail=f"Failed to read directory contents: {str(e)}"
|
||||
)
|
||||
|
||||
@router.post("/test-network-share")
|
||||
async def test_network_share(
|
||||
payload: TestShareRequest,
|
||||
admin_user: User = Depends(require_admin)
|
||||
):
|
||||
"""
|
||||
Attempts to connect to a UNC network share and tests write access.
|
||||
"""
|
||||
from app.services.settings_service import connect_network_share
|
||||
|
||||
ok = connect_network_share(payload.path, payload.username, payload.password)
|
||||
if not ok:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Failed to connect to the network share. Check the server path, username, and password."
|
||||
)
|
||||
|
||||
try:
|
||||
target_path = Path(payload.path)
|
||||
os.makedirs(target_path, exist_ok=True)
|
||||
test_file = target_path / f".write_test_{uuid.uuid4().hex[:6]}"
|
||||
test_file.touch()
|
||||
test_file.unlink()
|
||||
return {"message": "Network share connected and write access verified successfully!"}
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail=f"Network share connected, but write access test failed: {str(e)}"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user