Refactor backend and add registry build workflow
Build and publish Docker image / build-and-publish (push) Successful in 2m45s
Build and publish Docker image / build-and-publish (push) Successful in 2m45s
This commit is contained in:
commit
c177d7981d
43 files changed
+18124
No files matched your search
@@ -0,0 +1,207 @@
|
||||
"""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
|
||||
Reference in new issue
Block a user