208 lines
7.8 KiB
Python
208 lines
7.8 KiB
Python
"""Server records operations."""
|
|
|
|
|
|
from database_service import database_connection, dict_from_row
|
|
import json
|
|
from runtime_config import (
|
|
logger,
|
|
)
|
|
from typing import Dict, List, Optional, Tuple
|
|
from user_service import get_user_by_id
|
|
import uuid
|
|
|
|
__all__ = ['create_server_record', 'delete_server_record', 'get_all_servers', 'get_server_access_and_namespace', 'get_server_by_id', 'get_user_servers', 'update_server_status']
|
|
|
|
|
|
|
|
def create_server_record(server_data: Dict) -> Optional[Dict]:
|
|
"""Create server record"""
|
|
try:
|
|
with database_connection() as conn:
|
|
cursor = conn.cursor()
|
|
is_demo = server_data.get('is_demo', False)
|
|
demo_expires_at = server_data.get('demo_expires_at')
|
|
|
|
cursor.execute('''
|
|
INSERT INTO servers (id, name, type, image, version, status, cpu, ram, storage, ip, ports, owner_id, namespace, k8s_name, is_demo, demo_expires_at, java_version, loader, sftp_username, sftp_password, sftp_port)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
''', (
|
|
server_data['id'],
|
|
server_data['name'],
|
|
server_data['type'],
|
|
server_data['image'],
|
|
server_data['version'],
|
|
server_data.get('status', 'Creating'),
|
|
server_data['cpu'],
|
|
server_data['ram'],
|
|
server_data['storage'],
|
|
server_data['ip'],
|
|
json.dumps(server_data['ports']),
|
|
server_data['ownerId'], # This should match the key in server_data
|
|
server_data.get('namespace', f"user-{server_data['ownerId']}".lower()),
|
|
server_data.get('k8s_name', server_data['id']),
|
|
is_demo,
|
|
demo_expires_at,
|
|
server_data.get('java_version'),
|
|
server_data.get('loader'),
|
|
server_data.get('sftp_username'),
|
|
server_data.get('sftp_password'),
|
|
server_data.get('sftp_port')
|
|
))
|
|
conn.commit()
|
|
|
|
# Return the server with owner_id field
|
|
cursor.execute('SELECT * FROM servers WHERE id = ?', (server_data['id'],))
|
|
server = dict_from_row(cursor.fetchone())
|
|
if server and 'ports' in server:
|
|
server['ports'] = json.loads(server['ports'])
|
|
|
|
return server
|
|
except Exception as e:
|
|
logger.error(f"Error creating server record: {e}")
|
|
return None
|
|
|
|
def get_server_by_id(server_id: str) -> Optional[Dict]:
|
|
"""Get server by ID"""
|
|
try:
|
|
# Ensure server_id is a string
|
|
server_id = str(server_id)
|
|
with database_connection() as conn:
|
|
cursor = conn.cursor()
|
|
cursor.execute('SELECT * FROM servers WHERE id = ?', (server_id,))
|
|
server = dict_from_row(cursor.fetchone())
|
|
if server and 'ports' in server:
|
|
server['ports'] = json.loads(server['ports'])
|
|
|
|
# Add backward compatibility for ownerId field
|
|
if server and 'owner_id' in server:
|
|
server['ownerId'] = server['owner_id']
|
|
|
|
return server
|
|
except Exception as e:
|
|
return None
|
|
|
|
def get_server_access_and_namespace(server_id: str, requester_id: str) -> Tuple[str, Dict]:
|
|
"""
|
|
Check if a user has access to a server and return the namespace and server record.
|
|
Access is granted if user is the owner OR an admin.
|
|
Returns (namespace, server_record)
|
|
"""
|
|
server = get_server_by_id(server_id)
|
|
if not server:
|
|
raise Exception("Server not found")
|
|
|
|
requester = get_user_by_id(requester_id)
|
|
if not requester:
|
|
raise Exception("User not found")
|
|
|
|
# Check access (ensure string comparison for IDs)
|
|
# Handle both 'owner_id' and 'ownerId' keys for compatibility
|
|
server_owner_id = str(server.get('owner_id') or server.get('ownerId', ''))
|
|
req_id = str(requester_id)
|
|
|
|
is_owner = server_owner_id == req_id
|
|
is_admin = requester.get('role') == 'admin'
|
|
|
|
if not is_owner and not is_admin:
|
|
logger.warning(f"Access denied for user {requester_id} to server {server_id}. Owner: {server_owner_id}, Role: {requester.get('role')}")
|
|
raise Exception("Access denied")
|
|
|
|
# Get owner to determine namespace
|
|
if is_owner:
|
|
owner = requester
|
|
else:
|
|
owner = get_user_by_id(server_owner_id)
|
|
|
|
if not owner:
|
|
raise Exception("Server owner not found")
|
|
|
|
namespace = f"user-{owner['username']}".lower()
|
|
return namespace, server
|
|
|
|
def get_user_servers(user_id: str) -> List[Dict]:
|
|
"""Get all servers for a user"""
|
|
try:
|
|
with database_connection() as conn:
|
|
cursor = conn.cursor()
|
|
cursor.execute('SELECT * FROM servers WHERE owner_id = ? ORDER BY created_at DESC', (user_id,))
|
|
servers = [dict_from_row(row) for row in cursor.fetchall()]
|
|
|
|
for server in servers:
|
|
if server and 'ports' in server:
|
|
server['ports'] = json.loads(server['ports'])
|
|
|
|
# Get database configuration for database servers
|
|
if server and server['type'] == 'database':
|
|
cursor.execute('SELECT * FROM database_configs WHERE server_id = ?', (server['id'],))
|
|
db_config = dict_from_row(cursor.fetchone())
|
|
if db_config:
|
|
server['databaseConfig'] = db_config
|
|
|
|
return servers
|
|
except Exception as e:
|
|
return []
|
|
|
|
def get_all_servers() -> List[Dict]:
|
|
"""Get all servers (admin only)"""
|
|
try:
|
|
with database_connection() as conn:
|
|
cursor = conn.cursor()
|
|
cursor.execute('SELECT * FROM servers ORDER BY created_at DESC')
|
|
servers = [dict_from_row(row) for row in cursor.fetchall()]
|
|
|
|
for server in servers:
|
|
if server and 'ports' in server:
|
|
try:
|
|
if isinstance(server['ports'], str):
|
|
server['ports'] = json.loads(server['ports'])
|
|
except:
|
|
server['ports'] = []
|
|
|
|
# Get database configuration for database servers
|
|
if server and server['type'] == 'database':
|
|
cursor.execute('SELECT * FROM database_configs WHERE server_id = ?', (server['id'],))
|
|
db_config = dict_from_row(cursor.fetchone())
|
|
if db_config:
|
|
server['databaseConfig'] = db_config
|
|
|
|
return servers
|
|
except Exception as e:
|
|
logger.error(f"Error getting all servers: {e}")
|
|
return []
|
|
|
|
def update_server_status(server_id: str, status: str, message: str = "") -> bool:
|
|
"""Update server status"""
|
|
try:
|
|
with database_connection() as conn:
|
|
cursor = conn.cursor()
|
|
|
|
cursor.execute(
|
|
'UPDATE servers SET status = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?',
|
|
(status, server_id)
|
|
)
|
|
|
|
status_id = f"status-{str(uuid.uuid4())[:8]}"
|
|
cursor.execute('''
|
|
INSERT INTO server_status_history (id, server_id, status, message)
|
|
VALUES (?, ?, ?, ?)
|
|
''', (status_id, server_id, status, message))
|
|
|
|
conn.commit()
|
|
return cursor.rowcount > 0
|
|
except Exception as e:
|
|
return False
|
|
|
|
def delete_server_record(server_id: str) -> bool:
|
|
"""Delete server record"""
|
|
try:
|
|
with database_connection() as conn:
|
|
cursor = conn.cursor()
|
|
# Delete database configuration first
|
|
cursor.execute('DELETE FROM database_configs WHERE server_id = ?', (server_id,))
|
|
# Then delete server
|
|
cursor.execute('DELETE FROM servers WHERE id = ?', (server_id,))
|
|
conn.commit()
|
|
return cursor.rowcount > 0
|
|
except Exception as e:
|
|
return False
|