diff --git a/CyberCP/settings.py b/CyberCP/settings.py index 926960ea8..60d9f4725 100644 --- a/CyberCP/settings.py +++ b/CyberCP/settings.py @@ -207,4 +207,8 @@ MEDIA_ROOT = MEDIA_URL DATA_UPLOAD_MAX_MEMORY_SIZE = 2147483648 # Security settings -X_FRAME_OPTIONS = 'SAMEORIGIN' \ No newline at end of file +X_FRAME_OPTIONS = 'SAMEORIGIN' + +# Default primary key field type +# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' \ No newline at end of file diff --git a/baseTemplate/migrations/0001_initial.py b/baseTemplate/migrations/0001_initial.py new file mode 100644 index 000000000..0f07939c2 --- /dev/null +++ b/baseTemplate/migrations/0001_initial.py @@ -0,0 +1,43 @@ +# Generated by Django 3.2.25 on 2024-01-01 00:00 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='CyberPanelCosmetic', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('MainDashboardCSS', models.TextField(default='')), + ], + ), + migrations.CreateModel( + name='UserNotificationPreferences', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('backup_notification_dismissed', models.BooleanField(default=False, help_text='Whether user has dismissed the backup notification')), + ('ai_scanner_notification_dismissed', models.BooleanField(default=False, help_text='Whether user has dismissed the AI scanner notification')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ], + options={ + 'verbose_name': 'User Notification Preferences', + 'verbose_name_plural': 'User Notification Preferences', + }, + ), + migrations.CreateModel( + name='version', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('version', models.CharField(max_length=10)), + ('build', models.IntegerField()), + ], + ), + ] diff --git a/baseTemplate/migrations/0002_usernotificationpreferences.py b/baseTemplate/migrations/0002_usernotificationpreferences.py new file mode 100644 index 000000000..956c8e3f6 --- /dev/null +++ b/baseTemplate/migrations/0002_usernotificationpreferences.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.25 on 2024-01-01 00:01 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('baseTemplate', '0001_initial'), + ('loginSystem', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='usernotificationpreferences', + name='user', + field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='notification_preferences', to='loginSystem.administrator'), + ), + ] diff --git a/install/install.py b/install/install.py index d48f602a2..2db012a60 100644 --- a/install/install.py +++ b/install/install.py @@ -708,6 +708,10 @@ password="%s" command = "find /usr/local/CyberCP -path '*/migrations/__pycache__' -type d -exec rm -rf {} + 2>/dev/null || true" preFlightsChecks.call(command, self.distro, command, command, 1, 0, os.EX_OSERR) + # Fix baseTemplate migrations - ensure required migration files exist + logging.InstallLog.writeToFile("Fixing baseTemplate migrations...") + self.fixBaseTemplateMigrations() + # Create all migrations at once - Django will handle dependencies logging.InstallLog.writeToFile("Creating fresh migrations for all apps...") command = "/usr/local/CyberPanel-venv/bin/python manage.py makemigrations --noinput" @@ -740,6 +744,117 @@ password="%s" except: pass + def fixBaseTemplateMigrations(self): + """ + Fix baseTemplate migrations to prevent NodeNotFoundError on AlmaLinux 9 and Ubuntu 24 + """ + try: + # Ensure baseTemplate migrations directory exists + migrations_dir = "/usr/local/CyberCP/baseTemplate/migrations" + if not os.path.exists(migrations_dir): + os.makedirs(migrations_dir) + logging.InstallLog.writeToFile("Created baseTemplate migrations directory") + + # Create __init__.py if it doesn't exist + init_file = os.path.join(migrations_dir, "__init__.py") + if not os.path.exists(init_file): + with open(init_file, 'w') as f: + f.write("") + logging.InstallLog.writeToFile("Created baseTemplate migrations __init__.py") + + # Create 0001_initial.py if it doesn't exist + initial_migration = os.path.join(migrations_dir, "0001_initial.py") + if not os.path.exists(initial_migration): + initial_content = '''# Generated by Django 3.2.25 on 2024-01-01 00:00 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='CyberPanelCosmetic', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('MainDashboardCSS', models.TextField(default='')), + ], + ), + migrations.CreateModel( + name='UserNotificationPreferences', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('backup_notification_dismissed', models.BooleanField(default=False, help_text='Whether user has dismissed the backup notification')), + ('ai_scanner_notification_dismissed', models.BooleanField(default=False, help_text='Whether user has dismissed the AI scanner notification')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ], + options={ + 'verbose_name': 'User Notification Preferences', + 'verbose_name_plural': 'User Notification Preferences', + }, + ), + migrations.CreateModel( + name='version', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('version', models.CharField(max_length=10)), + ('build', models.IntegerField()), + ], + ), + ] +''' + with open(initial_migration, 'w') as f: + f.write(initial_content) + logging.InstallLog.writeToFile("Created baseTemplate 0001_initial.py migration") + + # Create 0002_usernotificationpreferences.py if it doesn't exist + notification_migration = os.path.join(migrations_dir, "0002_usernotificationpreferences.py") + if not os.path.exists(notification_migration): + notification_content = '''# Generated by Django 3.2.25 on 2024-01-01 00:01 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('baseTemplate', '0001_initial'), + ('loginSystem', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='usernotificationpreferences', + name='user', + field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='notification_preferences', to='loginSystem.administrator'), + ), + ] +''' + with open(notification_migration, 'w') as f: + f.write(notification_content) + logging.InstallLog.writeToFile("Created baseTemplate 0002_usernotificationpreferences.py migration") + + # Set proper permissions + command = "chown -R root:root " + migrations_dir + preFlightsChecks.call(command, self.distro, command, command, 1, 0, os.EX_OSERR) + + command = "chmod -R 755 " + migrations_dir + preFlightsChecks.call(command, self.distro, command, command, 1, 0, os.EX_OSERR) + + logging.InstallLog.writeToFile("baseTemplate migrations fixed successfully") + preFlightsChecks.stdOut("baseTemplate migrations fixed successfully") + + except Exception as e: + logging.InstallLog.writeToFile("Error fixing baseTemplate migrations: " + str(e)) + preFlightsChecks.stdOut("Warning: Could not fix baseTemplate migrations: " + str(e)) + def fixCyberPanelPermissions(self): ###### fix Core CyberPanel permissions diff --git a/plogical/upgrade.py b/plogical/upgrade.py index f2aee4613..8ad910ba5 100644 --- a/plogical/upgrade.py +++ b/plogical/upgrade.py @@ -2461,6 +2461,131 @@ CREATE TABLE `websiteFunctions_backupsv2` (`id` integer AUTO_INCREMENT NOT NULL except: pass + @staticmethod + def fixBaseTemplateMigrations(): + """ + Fix baseTemplate migrations to prevent NodeNotFoundError on AlmaLinux 9 and Ubuntu 24 + """ + try: + Upgrade.stdOut("Fixing baseTemplate migrations for AlmaLinux 9 and Ubuntu 24 compatibility...") + + # Ensure baseTemplate migrations directory exists + migrations_dir = "/usr/local/CyberCP/baseTemplate/migrations" + if not os.path.exists(migrations_dir): + os.makedirs(migrations_dir) + Upgrade.stdOut("Created baseTemplate migrations directory") + + # Create __init__.py if it doesn't exist + init_file = os.path.join(migrations_dir, "__init__.py") + if not os.path.exists(init_file): + with open(init_file, 'w') as f: + f.write("") + Upgrade.stdOut("Created baseTemplate migrations __init__.py") + + # Create 0001_initial.py if it doesn't exist + initial_migration = os.path.join(migrations_dir, "0001_initial.py") + if not os.path.exists(initial_migration): + initial_content = '''# Generated by Django 3.2.25 on 2024-01-01 00:00 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='CyberPanelCosmetic', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('MainDashboardCSS', models.TextField(default='')), + ], + ), + migrations.CreateModel( + name='UserNotificationPreferences', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('backup_notification_dismissed', models.BooleanField(default=False, help_text='Whether user has dismissed the backup notification')), + ('ai_scanner_notification_dismissed', models.BooleanField(default=False, help_text='Whether user has dismissed the AI scanner notification')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ], + options={ + 'verbose_name': 'User Notification Preferences', + 'verbose_name_plural': 'User Notification Preferences', + }, + ), + migrations.CreateModel( + name='version', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('version', models.CharField(max_length=10)), + ('build', models.IntegerField()), + ], + ), + ] +''' + with open(initial_migration, 'w') as f: + f.write(initial_content) + Upgrade.stdOut("Created baseTemplate 0001_initial.py migration") + + # Create 0002_usernotificationpreferences.py if it doesn't exist + notification_migration = os.path.join(migrations_dir, "0002_usernotificationpreferences.py") + if not os.path.exists(notification_migration): + notification_content = '''# Generated by Django 3.2.25 on 2024-01-01 00:01 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('baseTemplate', '0001_initial'), + ('loginSystem', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='usernotificationpreferences', + name='user', + field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='notification_preferences', to='loginSystem.administrator'), + ), + ] +''' + with open(notification_migration, 'w') as f: + f.write(notification_content) + Upgrade.stdOut("Created baseTemplate 0002_usernotificationpreferences.py migration") + + # Set proper permissions + command = "chown -R root:root " + migrations_dir + Upgrade.executioner(command, 0) + + command = "chmod -R 755 " + migrations_dir + Upgrade.executioner(command, 0) + + # Update Django settings to include DEFAULT_AUTO_FIELD if not present + settings_file = "/usr/local/CyberCP/CyberCP/settings.py" + if os.path.exists(settings_file): + with open(settings_file, 'r') as f: + settings_content = f.read() + + if "DEFAULT_AUTO_FIELD" not in settings_content: + with open(settings_file, 'a') as f: + f.write("\n# Default primary key field type\n") + f.write("# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field\n") + f.write("DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'\n") + Upgrade.stdOut("Added DEFAULT_AUTO_FIELD to Django settings") + + Upgrade.stdOut("baseTemplate migrations fixed successfully") + + except Exception as e: + Upgrade.stdOut("Error fixing baseTemplate migrations: " + str(e)) + @staticmethod def IncBackupMigrations(): try: @@ -4445,6 +4570,9 @@ slowlog = /var/log/php{version}-fpm-slow.log ### General migrations are not needed any more # Upgrade.GeneralMigrations() + + # Fix baseTemplate migrations for AlmaLinux 9 and Ubuntu 24 compatibility + Upgrade.fixBaseTemplateMigrations() # Upgrade.p3() diff --git a/run_migration.py b/run_migration.py deleted file mode 100644 index 913a3473f..000000000 --- a/run_migration.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -Migration script for UserNotificationPreferences model -Run this script to apply the database migration for notification preferences -""" - -import os -import sys -import django - -# Add the project directory to Python path -sys.path.append('/usr/local/CyberCP') - -# Set up Django environment -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'CyberCP.settings') -django.setup() - -from django.core.management import execute_from_command_line - -if __name__ == '__main__': - print("Running migration for UserNotificationPreferences...") - try: - execute_from_command_line(['manage.py', 'migrate', 'baseTemplate']) - print("Migration completed successfully!") - except Exception as e: - print(f"Migration failed: {e}") - sys.exit(1) diff --git a/version.txt b/version.txt index eb3ab87c9..07695fa13 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -{"version":"2.4","build":3} \ No newline at end of file +{"version":"2.4","build":4} \ No newline at end of file