From c6e254c3906111827a5bc6aa257bf9f41614c005 Mon Sep 17 00:00:00 2001 From: ske087 Date: Sat, 22 Nov 2025 22:26:23 +0200 Subject: [PATCH] updated aplications database --- .gitignore | 3 ++ py_app/app/daily_mirror_db_setup.py | 57 +++++++++++++++++++++--- py_app/app/database_backup.py | 69 +++++++++++++++++++++-------- 3 files changed, 105 insertions(+), 24 deletions(-) diff --git a/.gitignore b/.gitignore index d22190d..46d05c3 100755 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,6 @@ instance/external_server.conf *.backup2 /logs /backups +/config +/data + diff --git a/py_app/app/daily_mirror_db_setup.py b/py_app/app/daily_mirror_db_setup.py index b04c06d..4c0cb93 100644 --- a/py_app/app/daily_mirror_db_setup.py +++ b/py_app/app/daily_mirror_db_setup.py @@ -17,12 +17,57 @@ logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) class DailyMirrorDatabase: - def __init__(self, host='localhost', user='trasabilitate', password='Initial01!', database='trasabilitate'): - self.host = host - self.user = user - self.password = password - self.database = database + def __init__(self, host=None, user=None, password=None, database=None): + """Initialize database connection parameters. + If not provided, will read from external_server.conf""" + # If parameters not provided, read from config file + if host is None or user is None or password is None or database is None: + config = self._read_db_config() + self.host = config.get('host', 'db') + self.user = config.get('user', 'trasabilitate') + self.password = config.get('password', 'Initial01!') + self.database = config.get('database', 'trasabilitate') + else: + self.host = host + self.user = user + self.password = password + self.database = database self.connection = None + + def _read_db_config(self): + """Read database configuration from external_server.conf""" + try: + from flask import current_app + settings_file = os.path.join(current_app.instance_path, 'external_server.conf') + + if os.path.exists(settings_file): + settings = {} + with open(settings_file, 'r') as f: + for line in f: + line = line.strip() + # Skip empty lines and comments + if not line or line.startswith('#'): + continue + if '=' in line: + key, value = line.split('=', 1) + settings[key] = value + + return { + 'host': settings.get('server_domain', 'db'), + 'user': settings.get('username', 'trasabilitate'), + 'password': settings.get('password', 'Initial01!'), + 'database': settings.get('database_name', 'trasabilitate') + } + except Exception as e: + logger.warning(f"Could not read config file, using defaults: {e}") + + # Fallback defaults for Docker environment + return { + 'host': 'db', + 'user': 'trasabilitate', + 'password': 'Initial01!', + 'database': 'trasabilitate' + } def connect(self): """Establish database connection""" @@ -33,7 +78,7 @@ class DailyMirrorDatabase: password=self.password, database=self.database ) - logger.info("Database connection established") + logger.info(f"Database connection established to {self.host}") return True except Exception as e: logger.error(f"Database connection failed: {e}") diff --git a/py_app/app/database_backup.py b/py_app/app/database_backup.py index 3d8883d..976507d 100644 --- a/py_app/app/database_backup.py +++ b/py_app/app/database_backup.py @@ -439,16 +439,36 @@ class DatabaseBackupManager: 'message': 'Backup file not found' } - # Use mariadb command to restore (more reliable than Python parsing) - # First, read the file and skip problematic first line if needed + # Read the SQL file with open(file_path, 'r') as f: sql_content = f.read() + # Clean up SQL content to avoid DEFINER issues + import re + # Remove problematic MariaDB sandbox mode comment from first line lines = sql_content.split('\n') if lines and lines[0].startswith('/*M!999999'): sql_content = '\n'.join(lines[1:]) + # Remove DEFINER clauses that cause permission errors + # This regex matches DEFINER=`user`@`host` in various contexts + sql_content = re.sub( + r'/\*!50017 DEFINER=`[^`]+`@`[^`]+`\*/', + '', + sql_content + ) + sql_content = re.sub( + r'/\*!50013 DEFINER=`[^`]+`@`[^`]+`\*/', + '', + sql_content + ) + sql_content = re.sub( + r'DEFINER=`[^`]+`@`[^`]+`', + '', + sql_content + ) + # Build mariadb restore command cmd = [ 'mariadb', @@ -520,6 +540,28 @@ class DatabaseBackupManager: 'message': 'Backup file not found' } + # Read SQL content + with open(file_path, 'r') as f: + sql_content = f.read() + + # Clean up SQL content to avoid DEFINER issues (in case data-only backup has them) + import re + sql_content = re.sub( + r'/\*!50017 DEFINER=`[^`]+`@`[^`]+`\*/', + '', + sql_content + ) + sql_content = re.sub( + r'/\*!50013 DEFINER=`[^`]+`@`[^`]+`\*/', + '', + sql_content + ) + sql_content = re.sub( + r'DEFINER=`[^`]+`@`[^`]+`', + '', + sql_content + ) + # First, disable foreign key checks and truncate all tables # This ensures clean data import without constraint violations try: @@ -557,10 +599,7 @@ class DatabaseBackupManager: print(f"Warning during table truncation: {e}") # Continue anyway - the restore might still work - # Read and execute SQL file using Python mariadb library - with open(file_path, 'r') as f: - sql_content = f.read() - + # Execute SQL using Python mariadb library conn = mariadb.connect( user=self.config['user'], password=self.config['password'], @@ -583,8 +622,8 @@ class DatabaseBackupManager: print(f"Warning executing statement: {stmt_error}") conn.commit() - result_success = True - result_returncode = 0 + cursor.close() + conn.close() # Re-enable foreign key checks try: @@ -603,16 +642,10 @@ class DatabaseBackupManager: except Exception as e: print(f"Warning: Could not re-enable foreign key checks: {e}") - if result_success: - return { - 'success': True, - 'message': f'Data restored successfully from {filename}' - } - else: - return { - 'success': False, - 'message': f'Data restore failed' - } + return { + 'success': True, + 'message': f'Data restored successfully from {filename} ({executed} statements executed)' + } except Exception as e: print(f"Exception during data restore: {e}")