| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  | import subprocess, shlex | 
					
						
							|  |  |  | import install | 
					
						
							|  |  |  | import time | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class mysqlUtilities: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @staticmethod | 
					
						
							|  |  |  |     def createDatabase(dbname, dbuser, dbpassword, publicip): | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |         """
 | 
					
						
							|  |  |  |         Create database and user with improved error handling and validation | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         import logging | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Validate input parameters | 
					
						
							|  |  |  |         if not dbname or not dbuser or not dbpassword: | 
					
						
							|  |  |  |             logging.InstallLog.writeToFile(f"ERROR: Missing required parameters - dbname: {dbname}, dbuser: {dbuser}, password: {'SET' if dbpassword else 'EMPTY'}") | 
					
						
							|  |  |  |             return 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         logging.InstallLog.writeToFile(f"Creating database '{dbname}' and user '{dbuser}' with password length: {len(dbpassword)}") | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |             # Step 1: Create database | 
					
						
							|  |  |  |             createDB = "CREATE DATABASE IF NOT EXISTS " + dbname | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 from json import loads | 
					
						
							|  |  |  |                 mysqlData = loads(open("/etc/cyberpanel/mysqlPassword", 'r').read()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 initCommand = 'mariadb -h %s --port %s -u %s -p%s -e "' % (mysqlData['mysqlhost'], mysqlData['mysqlport'], mysqlData['mysqluser'], mysqlData['mysqlpassword']) | 
					
						
							|  |  |  |                 remote = 1 | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |                 logging.InstallLog.writeToFile("Using remote MySQL configuration") | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  |             except: | 
					
						
							|  |  |  |                 passFile = "/etc/cyberpanel/mysqlPassword" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 f = open(passFile) | 
					
						
							|  |  |  |                 data = f.read() | 
					
						
							|  |  |  |                 password = data.split('\n', 1)[0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 initCommand = 'mariadb -u root -p' + password + ' -e "' | 
					
						
							|  |  |  |                 remote = 0 | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |                 logging.InstallLog.writeToFile("Using local MySQL configuration") | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             command = initCommand + createDB + '"' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |             logging.InstallLog.writeToFile(f"Executing database creation: CREATE DATABASE IF NOT EXISTS {dbname}") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  |             if install.preFlightsChecks.debug: | 
					
						
							|  |  |  |                 print(command) | 
					
						
							|  |  |  |                 time.sleep(10) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             cmd = shlex.split(command) | 
					
						
							|  |  |  |             res = subprocess.call(cmd) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |             if res != 0: | 
					
						
							|  |  |  |                 logging.InstallLog.writeToFile(f"ERROR: Database creation failed with return code: {res}") | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  |                 return 0 | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 logging.InstallLog.writeToFile(f"✓ Database '{dbname}' created successfully") | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |             # Step 2: Create user (drop first if exists to avoid conflicts) | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  |             if remote: | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |                 dropUser = f"DROP USER IF EXISTS '{dbuser}'@'{publicip}'" | 
					
						
							|  |  |  |                 createUser = f"CREATE USER '{dbuser}'@'{publicip}' IDENTIFIED BY '{dbpassword}'" | 
					
						
							|  |  |  |                 host = publicip | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  |             else: | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |                 dropUser = f"DROP USER IF EXISTS '{dbuser}'@'localhost'" | 
					
						
							|  |  |  |                 createUser = f"CREATE USER '{dbuser}'@'localhost' IDENTIFIED BY '{dbpassword}'" | 
					
						
							|  |  |  |                 host = 'localhost' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # Drop user if exists | 
					
						
							|  |  |  |             command = initCommand + dropUser + '"' | 
					
						
							|  |  |  |             logging.InstallLog.writeToFile(f"Dropping existing user '{dbuser}'@'{host}' if exists") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if install.preFlightsChecks.debug: | 
					
						
							|  |  |  |                 print(command) | 
					
						
							|  |  |  |                 time.sleep(10) | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |             cmd = shlex.split(command) | 
					
						
							|  |  |  |             subprocess.call(cmd)  # Ignore return code for DROP USER IF EXISTS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # Create user | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  |             command = initCommand + createUser + '"' | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |             logging.InstallLog.writeToFile(f"Creating user '{dbuser}'@'{host}' with password") | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if install.preFlightsChecks.debug: | 
					
						
							|  |  |  |                 print(command) | 
					
						
							|  |  |  |                 time.sleep(10) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             cmd = shlex.split(command) | 
					
						
							|  |  |  |             res = subprocess.call(cmd) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |             if res != 0: | 
					
						
							|  |  |  |                 logging.InstallLog.writeToFile(f"ERROR: User creation failed with return code: {res}") | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  |                 return 0 | 
					
						
							|  |  |  |             else: | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |                 logging.InstallLog.writeToFile(f"✓ User '{dbuser}'@'{host}' created successfully") | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |                 # Step 3: Handle special cases and grant privileges | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  |                 if remote: | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |                     ### DigitalOcean MySQL compatibility | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  |                     if mysqlData['mysqlhost'].find('ondigitalocean') > -1: | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |                         alterUserPassword = f"ALTER USER '{dbuser}'@'{publicip}' IDENTIFIED WITH mysql_native_password BY '{dbpassword}'" | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  |                         command = initCommand + alterUserPassword + '"' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |                         logging.InstallLog.writeToFile(f"Applying DigitalOcean MySQL compatibility for '{dbuser}'@'{publicip}'") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  |                         if install.preFlightsChecks.debug: | 
					
						
							|  |  |  |                             print(command) | 
					
						
							|  |  |  |                             time.sleep(10) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         cmd = shlex.split(command) | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |                         res = subprocess.call(cmd) | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |                         if res != 0: | 
					
						
							|  |  |  |                             logging.InstallLog.writeToFile(f"WARNING: DigitalOcean ALTER USER failed with return code: {res}") | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |                     ## RDS vs Standard MySQL permissions | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  |                     if mysqlData['mysqlhost'].find('rds.amazon') == -1: | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |                         grantPrivileges = f"GRANT ALL PRIVILEGES ON {dbname}.* TO '{dbuser}'@'{publicip}'" | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  |                     else: | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |                         grantPrivileges = f"GRANT INDEX, DROP, UPDATE, ALTER, CREATE, SELECT, INSERT, DELETE ON {dbname}.* TO '{dbuser}'@'{publicip}'" | 
					
						
							|  |  |  |                     host = publicip | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  |                 else: | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |                     grantPrivileges = f"GRANT ALL PRIVILEGES ON {dbname}.* TO '{dbuser}'@'localhost'" | 
					
						
							|  |  |  |                     host = 'localhost' | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |                 # Grant privileges | 
					
						
							|  |  |  |                 command = initCommand + grantPrivileges + '"' | 
					
						
							|  |  |  |                 logging.InstallLog.writeToFile(f"Granting privileges on database '{dbname}' to user '{dbuser}'@'{host}'") | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 if install.preFlightsChecks.debug: | 
					
						
							|  |  |  |                     print(command) | 
					
						
							|  |  |  |                     time.sleep(10) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 cmd = shlex.split(command) | 
					
						
							|  |  |  |                 res = subprocess.call(cmd) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |                 if res != 0: | 
					
						
							|  |  |  |                     logging.InstallLog.writeToFile(f"ERROR: Grant privileges failed with return code: {res}") | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  |                     return 0 | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |                 else: | 
					
						
							|  |  |  |                     logging.InstallLog.writeToFile(f"✓ Privileges granted successfully") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 # Step 4: Flush privileges | 
					
						
							|  |  |  |                 flushCommand = initCommand + "FLUSH PRIVILEGES" + '"' | 
					
						
							|  |  |  |                 logging.InstallLog.writeToFile("Flushing MySQL privileges") | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |                 cmd = shlex.split(flushCommand) | 
					
						
							|  |  |  |                 res = subprocess.call(cmd) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if res != 0: | 
					
						
							|  |  |  |                     logging.InstallLog.writeToFile(f"WARNING: FLUSH PRIVILEGES failed with return code: {res}") | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     logging.InstallLog.writeToFile("✓ Privileges flushed successfully") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             logging.InstallLog.writeToFile(f"✅ Database '{dbname}' and user '{dbuser}' created successfully!") | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  |             return 1 | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  |         except BaseException as msg: | 
					
						
							| 
									
										
										
										
											2025-09-28 02:00:25 +05:00
										 |  |  |             logging.InstallLog.writeToFile(f"❌ CRITICAL ERROR in createDatabase: {str(msg)}") | 
					
						
							|  |  |  |             import traceback | 
					
						
							|  |  |  |             logging.InstallLog.writeToFile(f"Full traceback: {traceback.format_exc()}") | 
					
						
							| 
									
										
										
										
											2025-08-01 14:56:30 +05:00
										 |  |  |             return 0 |