feat: Sync/Clone-Modus, Rotation, --setup Deployment, Scheduler-Fix, Dashboard-Updates, README
This commit is contained in:
+94
-4
@@ -251,9 +251,9 @@ def test_connection(target: TargetConnection) -> tuple[bool, str]:
|
||||
|
||||
if protocol == "LOCAL":
|
||||
check_path = Path(target.subpath)
|
||||
if check_path.exists() and check_path.is_dir():
|
||||
if check_path.exists() and (check_path.is_dir() or check_path.is_file()):
|
||||
return True, "Lokaler Pfad erreichbar."
|
||||
return False, "Lokaler Pfad ist nicht erreichbar oder kein Verzeichnis."
|
||||
return False, "Lokaler Pfad nicht gefunden oder nicht zugänglich."
|
||||
|
||||
if protocol == "SMB":
|
||||
if not target.share:
|
||||
@@ -271,7 +271,13 @@ def test_connection(target: TargetConnection) -> tuple[bool, str]:
|
||||
try:
|
||||
ftp.connect(target.host, target.port or 21, timeout=8)
|
||||
ftp.login(target.username, target.password)
|
||||
ftp.cwd(target.subpath or "/")
|
||||
subpath = target.subpath or "/"
|
||||
try:
|
||||
ftp.cwd(subpath)
|
||||
except Exception: # noqa: BLE001
|
||||
# subpath may be a file — try parent directory
|
||||
parent = "/".join(subpath.rstrip("/").split("/")[:-1]) or "/"
|
||||
ftp.cwd(parent)
|
||||
return True, "FTP-Verbindung und Pfad sind erreichbar."
|
||||
except Exception as exc: # noqa: BLE001
|
||||
return False, f"FTP-Test fehlgeschlagen: {exc}"
|
||||
@@ -288,7 +294,13 @@ def test_connection(target: TargetConnection) -> tuple[bool, str]:
|
||||
transport = paramiko.Transport((target.host, target.port or 22))
|
||||
transport.connect(username=target.username, password=target.password)
|
||||
sftp = paramiko.SFTPClient.from_transport(transport)
|
||||
sftp.listdir(target.subpath or "/")
|
||||
subpath = target.subpath or "/"
|
||||
try:
|
||||
sftp.listdir(subpath)
|
||||
except Exception: # noqa: BLE001
|
||||
# subpath may be a file — try parent directory
|
||||
parent = "/".join(subpath.rstrip("/").split("/")[:-1]) or "/"
|
||||
sftp.listdir(parent)
|
||||
return True, "SFTP-Verbindung und Pfad sind erreichbar."
|
||||
except Exception as exc: # noqa: BLE001
|
||||
return False, f"SFTP-Test fehlgeschlagen: {exc}"
|
||||
@@ -301,6 +313,84 @@ def test_connection(target: TargetConnection) -> tuple[bool, str]:
|
||||
return False, "Unbekanntes Protokoll."
|
||||
|
||||
|
||||
def browse_ftp_directories(target: TargetConnection) -> tuple[bool, str, list[dict[str, str]]]:
|
||||
ftp = FTP()
|
||||
try:
|
||||
ftp.connect(target.host, target.port or 21, timeout=8)
|
||||
ftp.login(target.username, target.password)
|
||||
current_path = normalize_subpath(target.subpath or "/")
|
||||
try:
|
||||
ftp.cwd(current_path)
|
||||
except Exception:
|
||||
current_path = "/"
|
||||
ftp.cwd("/")
|
||||
|
||||
entries: list[dict[str, str]] = []
|
||||
if current_path != "/":
|
||||
parent = "/".join(current_path.rstrip("/").split("/")[:-1]) or "/"
|
||||
entries.append({"name": "..", "path": parent, "entry_type": "up"})
|
||||
|
||||
raw_lines: list[str] = []
|
||||
try:
|
||||
ftp.retrlines("LIST", raw_lines.append)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
items: list[dict[str, str]] = []
|
||||
for line in raw_lines:
|
||||
parts = line.split(None, 8)
|
||||
if len(parts) < 9:
|
||||
continue
|
||||
name = parts[8].strip()
|
||||
if name in (".", ".."):
|
||||
continue
|
||||
is_dir = parts[0].startswith("d")
|
||||
sub_path = _build_child_path(current_path, name)
|
||||
items.append({"name": name, "path": sub_path, "entry_type": "directory" if is_dir else "file"})
|
||||
|
||||
entries.extend(_sort_entries(items))
|
||||
return True, current_path, entries
|
||||
except Exception as exc: # noqa: BLE001
|
||||
return False, f"FTP-Fehler: {exc}", []
|
||||
finally:
|
||||
try:
|
||||
ftp.quit()
|
||||
except Exception: # noqa: BLE001
|
||||
pass
|
||||
|
||||
|
||||
def browse_sftp_directories(target: TargetConnection) -> tuple[bool, str, list[dict[str, str]]]:
|
||||
import stat as stat_module
|
||||
transport = None
|
||||
sftp_client = None
|
||||
try:
|
||||
transport = paramiko.Transport((target.host, target.port or 22))
|
||||
transport.connect(username=target.username, password=target.password)
|
||||
sftp_client = paramiko.SFTPClient.from_transport(transport)
|
||||
current_path = normalize_subpath(target.subpath or "/")
|
||||
|
||||
entries: list[dict[str, str]] = []
|
||||
if current_path != "/":
|
||||
parent = "/".join(current_path.rstrip("/").split("/")[:-1]) or "/"
|
||||
entries.append({"name": "..", "path": parent, "entry_type": "up"})
|
||||
|
||||
items: list[dict[str, str]] = []
|
||||
for attr in sftp_client.listdir_attr(current_path):
|
||||
is_dir = stat_module.S_ISDIR(attr.st_mode or 0)
|
||||
sub_path = _build_child_path(current_path, attr.filename)
|
||||
items.append({"name": attr.filename, "path": sub_path, "entry_type": "directory" if is_dir else "file"})
|
||||
|
||||
entries.extend(_sort_entries(items))
|
||||
return True, current_path, entries
|
||||
except Exception as exc: # noqa: BLE001
|
||||
return False, f"SFTP-Fehler: {exc}", []
|
||||
finally:
|
||||
if sftp_client is not None:
|
||||
sftp_client.close()
|
||||
if transport is not None:
|
||||
transport.close()
|
||||
|
||||
|
||||
def browse_smb_directories(target: TargetConnection) -> tuple[bool, str, list[dict[str, str]]]:
|
||||
if target.protocol.upper() != "SMB":
|
||||
return False, "SMB-Browser ist nur fuer SMB verfuegbar.", []
|
||||
|
||||
Reference in New Issue
Block a user