from core.errors.logger import logger from core.models.manage.session_management import init_session, get_session, close_session, create_ALL_tables, create_ONLY_db_version_table, get_path, does_it_exist, does_db_version_table_exist from core.models.manage.version_check import check_database_compatibility, insert_new_version, get_custom_message from core.services.helpers.manage_assets import assets_folder_setup from core.Constants import Constants from core.models.DatabaseOperation import DatabaseOperation, DBErrorType from core.models.manage.migrations import migrate_sql # generic import os import sys # ============================================================================ # DISPLAY CHOICES AND RECOVERY UI # ============================================================================ def recovery_dialog(custom_error, db_version_you_have): """This ends the app by forcing them to delete the database, move it, or just quit.""" from gui.v2.ui.popups.Database_version import show_recovery_dialog choice = show_recovery_dialog({"message": custom_error, "db_version": db_version_you_have, "status": "version_mismatch"}) logger.info(f"[DB MANAGEMENT] From the database error options, the user picked {choice}") if choice == 1: if os.path.exists(database_path): os.remove(database_path) logger.info(f"[DB MANAGEMENT] Deleted the DB file at {database_path}") logger.info(f"[DB MANAGEMENT] Closing the app gracefully, for them to reboot..") sys.exit() elif choice == 2: logger.info(f"[DB MANAGEMENT] User opted to move the DB file.") from gui.v2.ui.popups.pick_folder_to_move import launch_file_picker launch_file_picker(database_path) sys.exit() else: logger.error(f"[DB MANAGEMENT] User opted to close the app WITHOUT wiping the database, even though they need to.") sys.exit() # ============================================================================ # ASSETS FOLDER # ============================================================================ logger.info("Welcome, checking assets..") if not assets_folder_setup(): from gui.v2.ui.popups.generic_error_popup import show_error custom_error = "Unable to Setup your Assets Folder. Please create an assets directory at ~/.local/share/hydra-veil/assets" show_error(custom_error, "Critical Error") # ============================================================================ # INITIALIZE DATABASE # ============================================================================ logger.info("[DB MANAGEMENT] Starting DB init..") try: # Does the database exist? system_path = get_path() database_path = system_path / "storage.db" main_db_exists = does_it_exist(database_path) # Setup operations on the main DB which create it init_session() # (engine, Session, _session all initialized from session_management) session = get_session() # does the version checker table exist? version_table_exists = does_db_version_table_exist() except: logger.error("Critical Error with database initialization!") sys.exit() # are they upgrading from a legacy version? # that would mean the table existed, but not the version table, if not version_table_exists and main_db_exists: logger.info(f"[DB MANAGEMENT] We are dealing with a legacy database, we need to transition the user.") # shut down db connection close_session() # THEN DISPLAY CHOICES AND RECOVERY UI custom_error = "Upgrade Time! We transitioned to a new Database format for new features! Please delete the old version and fetch the new public data (what locations, browsers, ect) This will NOT affect your profiles or browser sessions." db_version_you_have = "Old System" recovery_dialog(custom_error, db_version_you_have) sys.exit() # If they're still here, then if it's NOT a legacy version, # and the new version table doesn't exist, then create it: if not version_table_exists: create_ONLY_db_version_table() # ============================================================================ # COMPARE DB VERISONS # ============================================================================ compatability_dict = check_database_compatibility(session) reason = compatability_dict.get("reason", "error") is_compatable = compatability_dict.get("result", False) logger.info(f"[DB MANAGEMENT] The result of the check is {is_compatable} and the reason is {reason}") # ============================================================================ # IF THE VERSIONS MATCH # ============================================================================ if is_compatable: try: made_tables = create_ALL_tables() # SCREEN FAILED TABLES if not made_tables: custom_error = "Critical Failure with starting the models of the database." logger.error(f"[DB MANAGEMENT] {custom_error}") close_session() from gui.v2.ui.popups.Database_version import show_recovery_dialog choice = show_recovery_dialog({"message": custom_error, "db_version": 0, "status": "cant_make"}) logger.info(f"[DB MANAGEMENT] From the database error options, the user picked {choice}") sys.exit() except: logger.info(f"[DB MANAGEMENT] create ALL tables failed. Running migrations...") made_tables = migrate_sql() logger.info(f"[DB MANAGEMENT] Results of migration is {made_tables.valid}") if not made_tables.valid: close_session() custom_error = "Could not Migrate the Database version, please delete the database. You will NOT lose profiles, this is the public data." from gui.v2.ui.popups.Database_version import show_recovery_dialog choice = show_recovery_dialog({"message": custom_error, "db_version": 0, "status": "cant_make"}) sys.exit() # ASSUME TABLES CREATED logger.info("[DB MANAGEMENT] Tables successfully made or initialized if pre-existing") # UPDATE DATA did_it_insert = insert_new_version(session, Constants.DB_VERSION_THIS_APP_WANTS) if not did_it_insert: logger.error(f"[DB MANAGEMENT] Critical Failure with updating/inserting the new DB version into the database.") # Load GUI either way: from gui.main_ui import start_ui # If the user lacks a database, we want to force them to sync the new data, to avoid NoneType errors when enabling existing profiles, if reason == "no_database": logger.info(f"[DB MANAGEMENT] User had no database to begin with, so now we're entering GUI with sync on..") force_sync = True else: logger.info(f"[DB MANAGEMENT] Launcher is now passing it off to launch the main GUI window WITHOUT force sync..") force_sync = False # Start GUI either way: start_ui(force_sync) # ============================================================================ # but IF the versions do NOT match # ============================================================================ else: logger.error(f"[DB MANAGEMENT] The App is expecting a different DB version than the real database. The reason is {reason}") db_version_you_have = compatability_dict.get("old_db_version", "Error getting the Version") # WHAT IS THE REASON? custom_error = get_custom_message(reason, compatability_dict) # shut down db connection close_session() # THEN DISPLAY CHOICES AND RECOVERY UI recovery_dialog(custom_error, db_version_you_have)