111 lines
3.8 KiB
Python
111 lines
3.8 KiB
Python
"""
|
|
FTP Server module for FactsDB service
|
|
Provides secure FTP access to onboarded directories
|
|
"""
|
|
|
|
import os
|
|
import threading
|
|
from pyftpdlib.authorizers import DummyAuthorizer
|
|
from pyftpdlib.handlers import FTPHandler
|
|
from pyftpdlib.servers import FTPServer
|
|
from typing import Dict, List, Set
|
|
from .config import Config
|
|
from .database import DatabaseManager
|
|
|
|
class FTPServerManager:
|
|
"""Manages the FTP server for FactsDB service"""
|
|
|
|
def __init__(self, config):
|
|
self.config = config
|
|
# Fix: Remove database initialization from FTP server - it doesn't need database access for basic FTP
|
|
self.db_manager = None # Don't initialize database for FTP server
|
|
self.server = None
|
|
self.is_running = False
|
|
self.onboarded_directories: Set[str] = set()
|
|
|
|
def start(self):
|
|
"""Start the FTP server"""
|
|
if self.is_running:
|
|
print("FTP server is already running")
|
|
return
|
|
|
|
try:
|
|
# Create authorizer
|
|
authorizer = DummyAuthorizer()
|
|
|
|
# Add user with read/write permissions
|
|
authorizer.add_user(
|
|
self.config.ftp_server.username,
|
|
self.config.ftp_server.password,
|
|
homedir="/",
|
|
perm="elradfmw"
|
|
)
|
|
|
|
# Create handler
|
|
handler = FTPHandler
|
|
handler.authorizer = authorizer
|
|
|
|
# Create server
|
|
self.server = FTPServer(
|
|
(self.config.ftp_server.host, self.config.ftp_server.port),
|
|
handler
|
|
)
|
|
|
|
# Set server options
|
|
self.server.max_cons = 256
|
|
self.server.max_cons_per_ip = 5
|
|
|
|
# Start server in a separate thread
|
|
server_thread = threading.Thread(target=self._run_server, daemon=True)
|
|
server_thread.start()
|
|
|
|
self.is_running = True
|
|
print(f"FTP server started on {self.config.ftp_server.host}:{self.config.ftp_server.port}")
|
|
|
|
except Exception as e:
|
|
print(f"Failed to start FTP server: {str(e)}")
|
|
self.is_running = False
|
|
|
|
def _run_server(self):
|
|
"""Run the FTP server"""
|
|
if self.server:
|
|
self.server.serve_forever()
|
|
|
|
def stop(self):
|
|
"""Stop the FTP server"""
|
|
if self.server and self.is_running:
|
|
self.server.close_all()
|
|
self.is_running = False
|
|
print("FTP server stopped")
|
|
|
|
def add_onboarded_directory(self, directory_path: str):
|
|
"""Add an onboarded directory to the FTP server access control"""
|
|
if os.path.exists(directory_path):
|
|
self.onboarded_directories.add(os.path.abspath(directory_path))
|
|
print(f"Added onboarded directory: {directory_path}")
|
|
|
|
def is_directory_allowed(self, directory_path: str) -> bool:
|
|
"""Check if a directory is allowed (onboarded)"""
|
|
abs_path = os.path.abspath(directory_path)
|
|
for onboarded_dir in self.onboarded_directories:
|
|
if abs_path.startswith(onboarded_dir):
|
|
return True
|
|
return False
|
|
|
|
def get_onboarded_directories(self) -> List[str]:
|
|
"""Get list of all onboarded directories"""
|
|
return list(self.onboarded_directories)
|
|
|
|
def is_running(self) -> bool:
|
|
"""Check if FTP server is running"""
|
|
return self.is_running
|
|
|
|
# Global FTP server instance
|
|
_ftp_server_manager = None
|
|
|
|
def get_ftp_server_manager(config: Config) -> FTPServerManager:
|
|
"""Get the global FTP server manager instance"""
|
|
global _ftp_server_manager
|
|
if _ftp_server_manager is None:
|
|
_ftp_server_manager = FTPServerManager(config)
|
|
return _ftp_server_manager |