update: new settings connection tab

This commit is contained in:
JOhn 2026-07-26 19:01:07 -04:00
parent 2e026c5287
commit 97f09ec42e
4 changed files with 216 additions and 49 deletions

0
gui/__main__.py Normal file → Executable file
View file

View file

@ -5,7 +5,6 @@ from core.Constants import Constants
from core.controllers.ConfigurationController import ConfigurationController
from core.controllers.PolicyController import PolicyController
from core.controllers.ProfileController import ProfileController
from core.services.networking.systemwide.systemwide_utils import get_firewall_setting
from gui.v2.actions.config import load_gui_config
from gui.v2.actions.profile_order import normalize_profile_order
@ -13,15 +12,28 @@ from gui.v2.actions.ticket_failure import get_ticket_verification_failure
def read_firewall_setting():
def read_connection_setting(gui_config_file, key):
try:
firewall_setting = get_firewall_setting()
return firewall_setting
config = load_gui_config(gui_config_file)
if config and "connection_settings" in config:
return bool(config["connection_settings"].get(key, False))
except Exception:
pass
return False
def read_firewall_setting(gui_config_file=None):
if gui_config_file is None:
return False
return read_connection_setting(gui_config_file, "firewall_enabled")
def read_managed_dns_setting(gui_config_file=None):
if gui_config_file is None:
return False
return read_connection_setting(gui_config_file, "managed_dns_enabled")
def read_systemwide_enabled():
try:
privilege_policy = PolicyController.get('privilege')
@ -56,7 +68,8 @@ def prepare(gui_config_file):
"endpoint_verification_enabled": endpoint_verification_enabled,
"systemwide_enabled": read_systemwide_enabled(),
"bwrap_enabled": read_bwrap_enabled(),
"firewall_setting": read_firewall_setting(),
"firewall_setting": read_firewall_setting(gui_config_file),
"managed_dns_setting": read_managed_dns_setting(gui_config_file),
"gui_config": load_gui_config(gui_config_file),
"ticket_failure": get_ticket_verification_failure(gui_config_file),
}
@ -71,6 +84,7 @@ def empty_payload():
"systemwide_enabled": False,
"bwrap_enabled": False,
"firewall_setting": False,
"managed_dns_setting": False,
"gui_config": None,
"ticket_failure": None,
}

View file

@ -19,23 +19,30 @@ class NetworkingSetupPage(Page):
self.btn_path = main_window.btn_path
self.update_status = main_window
self.manual_scripts_ready = False
self.setStyleSheet("font-family: Arial;")
self.button_next.clicked.disconnect(self.gestionar_next)
self.button_next.setVisible(True)
self.button_next.clicked.connect(self.go_to_install)
self._setup_ui()
def showEvent(self, event):
super().showEvent(event)
self.button_next.setVisible(True)
self.button_next.raise_()
def _setup_ui(self):
header_icon = self._icon_label("networking_shield.png", 48, self)
header_icon.setGeometry(74, 66, 48, 48)
title = QLabel("Firewall & Managed-DNS Setup", self)
title.setGeometry(138, 68, 590, 44)
title.setStyleSheet("font-size: 26px; font-weight: bold; color: cyan;")
title.setStyleSheet("font-family: Arial; font-size: 26px; font-weight: bold; color: cyan;")
subtitle = QLabel(
"Optional privileged networking helpers",
self)
subtitle.setGeometry(140, 108, 560, 24)
subtitle.setStyleSheet("font-size: 14px; color: #d8ffff;")
subtitle.setStyleSheet("font-family: Arial; font-size: 14px; color: #d8ffff;")
description = QLabel(
"These firewall and managed-DNS helpers are separate bash scripts. "
@ -44,7 +51,7 @@ class NetworkingSetupPage(Page):
self)
description.setGeometry(80, 152, 640, 72)
description.setWordWrap(True)
description.setStyleSheet("font-size: 15px; color: cyan;")
description.setStyleSheet("font-family: Arial; font-size: 15px; color: cyan;")
manual_panel = self._option_panel(74, 248, "Option 1", "Manual review")
manual_text = QLabel(
@ -52,7 +59,7 @@ class NetworkingSetupPage(Page):
manual_panel)
manual_text.setGeometry(24, 76, 252, 48)
manual_text.setWordWrap(True)
manual_text.setStyleSheet("font-size: 13px; color: #d8ffff;")
manual_text.setStyleSheet("font-family: Arial; font-size: 13px; color: #d8ffff;")
self.manual_button = QPushButton("Get scripts", manual_panel)
self.manual_button.setGeometry(24, 132, 252, 38)
@ -63,9 +70,9 @@ class NetworkingSetupPage(Page):
auto_text = QLabel(
"Let HydraVeil run the installer, then test that the scripts reached the sudo folder.",
auto_panel)
auto_text.setGeometry(24, 76, 252, 48)
auto_text.setGeometry(24, 76, 265, 48)
auto_text.setWordWrap(True)
auto_text.setStyleSheet("font-size: 13px; color: #d8ffff;")
auto_text.setStyleSheet("font-family: Arial; font-size: 13px; color: #d8ffff;")
self.auto_button = QPushButton("Automated installer", auto_panel)
self.auto_button.setGeometry(24, 132, 252, 38)
@ -75,7 +82,7 @@ class NetworkingSetupPage(Page):
self.status_label = QLabel("Choose manual or automated setup, or press Next to skip and continue.", self)
self.status_label.setGeometry(82, 462, 636, 38)
self.status_label.setWordWrap(True)
self.status_label.setStyleSheet("font-size: 13px; color: #d8ffff;")
self.status_label.setStyleSheet("font-family: Arial; font-size: 13px; color: #d8ffff;")
def _option_panel(self, x, y, label, title):
@ -92,11 +99,11 @@ class NetworkingSetupPage(Page):
option_label = QLabel(label, panel)
option_label.setGeometry(24, 20, 120, 20)
option_label.setStyleSheet("font-size: 11px; font-weight: bold; color: #8de9ff; border: none;")
option_label.setStyleSheet("font-family: Arial; font-size: 11px; font-weight: bold; color: #8de9ff; border: none;")
title_label = QLabel(title, panel)
title_label.setGeometry(24, 42, 240, 28)
title_label.setStyleSheet("font-size: 18px; font-weight: bold; color: cyan; border: none;")
title_label.setStyleSheet("font-family: Arial; font-size: 18px; font-weight: bold; color: cyan; border: none;")
return panel
@ -116,6 +123,7 @@ class NetworkingSetupPage(Page):
color: #f4ffff;
border: none;
border-radius: 4px;
font-family: Arial;
font-size: 12px;
font-weight: bold;
padding: 4px 8px;
@ -131,7 +139,7 @@ class NetworkingSetupPage(Page):
def _set_status(self, message, color="#d8ffff"):
self.status_label.setText(message)
self.status_label.setStyleSheet(f"font-size: 13px; color: {color};")
self.status_label.setStyleSheet(f"font-family: Arial; font-size: 13px; color: {color};")
self.update_status.update_status(message)
def _result_is_valid(self, result: Result):

View file

@ -17,6 +17,7 @@ from core.Constants import Constants
from core.controllers.ConfigurationController import ConfigurationController
from core.controllers.PolicyController import PolicyController
from core.controllers.ProfileController import ProfileController
from core.controllers.SystemStateController import SystemStateController
from core.controllers.tickets.UseTicketController import (
do_we_use_a_random_ticket,
get_unused_tickets,
@ -31,7 +32,7 @@ from core.Errors import (
PolicyRevocationError,
)
from core.errors.logger import logger as core_logger
from core.services.networking.systemwide.systemwide_utils import get_firewall_setting
from core.services.helpers.setup_sudo_scripts import test_if_in_sudo_folder
from gui.v2.actions import settings_data
from gui.v2.actions.key_interpretation import interpret_key_results
@ -1521,8 +1522,12 @@ class Settings(Page):
def show_connection_page(self):
core_logger.info("User navigated to Settings -> Connection")
if hasattr(self, "connection_gate_status"):
self.load_firewall_settings()
self.load_managed_dns_settings()
self.refresh_connection_settings_gate()
self.content_layout.setCurrentWidget(self.connection_page)
self._select_menu_button("Connection Page")
self._select_menu_button("Connections")
def show_logs_page(self):
core_logger.info("User navigated to Settings -> Error Logs")
@ -2114,7 +2119,7 @@ class Settings(Page):
def load_firewall_settings(self, enabled=None):
if enabled is None:
enabled = settings_data.load(read_firewall_setting)
enabled = self.read_gui_connection_setting("firewall_enabled")
self.firewall_toggle.setChecked(enabled)
if enabled:
self.firewall_status_value.setText("Enabled")
@ -2126,6 +2131,20 @@ class Settings(Page):
f"color: #e67e22; font-size: 14px; {self.font_style}")
def load_managed_dns_settings(self, enabled=None):
if enabled is None:
enabled = self.read_gui_connection_setting("managed_dns_enabled")
self.managed_dns_toggle.setChecked(enabled)
if enabled:
self.managed_dns_status_value.setText("Enabled")
self.managed_dns_status_value.setStyleSheet(
f"color: #2ecc71; font-size: 14px; {self.font_style}")
else:
self.managed_dns_status_value.setText("Disabled")
self.managed_dns_status_value.setStyleSheet(
f"color: #e67e22; font-size: 14px; {self.font_style}")
def save_bwrap_settings(self):
enable = self.bwrap_toggle.isChecked()
try:
@ -2153,28 +2172,108 @@ class Settings(Page):
f"color: red; font-size: 14px; {self.font_style}")
def save_firewall_settings(self):
enable = self.firewall_toggle.isChecked()
def save_connection_settings(self):
can_modify, message, _ = self.connection_settings_gate()
if not can_modify:
self.connection_gate_status.setText(message)
self.connection_gate_status.setStyleSheet(
f"color: #ff6b6b; font-size: 12px; {self.font_style}")
self.set_connection_controls_enabled(False)
self.update_status.update_status(message)
return
firewall_enabled = self.firewall_toggle.isChecked()
managed_dns_enabled = self.managed_dns_toggle.isChecked()
try:
if enable:
ConfigurationController.change_firewall(True)
self.firewall_status_value.setText("Enabled")
else:
ConfigurationController.change_firewall(False)
self.firewall_status_value.setText("Disabled")
self.save_gui_connection_settings(firewall_enabled, managed_dns_enabled)
self.load_firewall_settings(firewall_enabled)
self.load_managed_dns_settings(managed_dns_enabled)
self.update_status.update_status(
"Firewall settings updated")
"Connection settings updated")
except CommandNotFoundError as e:
self.firewall_status_value.setText(str(e))
self.firewall_status_value.setStyleSheet(
f"color: red; font-size: 14px; {self.font_style}")
except Exception as e:
print(e)
self.firewall_status_value.setText(f"Failed to update firewall setting {e}")
self.firewall_status_value.setText(f"Failed to update connection settings {e}")
self.firewall_status_value.setStyleSheet(
f"color: red; font-size: 14px; {self.font_style}")
def save_firewall_settings(self):
self.save_connection_settings()
def read_gui_connection_setting(self, key):
try:
config = self.update_status._load_gui_config()
if config and "connection_settings" in config:
return bool(config["connection_settings"].get(key, False))
except Exception:
pass
return False
def save_gui_connection_settings(self, firewall_enabled, managed_dns_enabled):
config = self.update_status._load_gui_config()
if config is None:
config = {}
if "connection_settings" not in config:
config["connection_settings"] = {}
config["connection_settings"]["firewall_enabled"] = firewall_enabled
config["connection_settings"]["managed_dns_enabled"] = managed_dns_enabled
self.update_status._save_gui_config(config)
self._prepared["firewall_setting"] = firewall_enabled
self._prepared["managed_dns_setting"] = managed_dns_enabled
def connection_settings_gate(self):
installed, install_message = self.networking_scripts_installed()
if not installed:
return False, f"Firewall and managed-DNS helpers are not installed. {install_message}", True
if self.has_active_systemwide_profile():
return False, "Disable the active systemwide profile before changing firewall or managed-DNS settings.", False
return True, "Firewall and managed-DNS helpers are installed. No active systemwide profile detected.", False
def networking_scripts_installed(self):
try:
result = test_if_in_sudo_folder()
if result.valid:
return True, "Installed."
return False, result.message
except Exception as e:
return False, str(e)
def has_active_systemwide_profile(self):
try:
return SystemStateController.get() is not None
except Exception:
return True
def set_connection_controls_enabled(self, enabled):
for widget_name in ("firewall_toggle", "managed_dns_toggle", "connection_save_button"):
widget = getattr(self, widget_name, None)
if widget is not None:
widget.setEnabled(enabled)
def refresh_connection_settings_gate(self):
can_modify, message, show_install = self.connection_settings_gate()
self.connection_gate_status.setText(message)
color = "#2ecc71" if can_modify else "#ff6b6b"
self.connection_gate_status.setStyleSheet(
f"color: {color}; font-size: 12px; {self.font_style}")
self.set_connection_controls_enabled(can_modify)
self.connection_install_button.setVisible(show_install)
def open_networking_installer(self):
self.custom_window.navigator.navigate("networking_setup")
def load_registrations_settings(self) -> None:
try:
config = self._prepared_value(
@ -2242,7 +2341,7 @@ class Settings(Page):
def create_connection_page(self):
page = QWidget()
layout = QVBoxLayout(page)
layout.setSpacing(20)
layout.setSpacing(16)
layout.setContentsMargins(20, 20, 20, 20)
title = QLabel("CONNECTION PAGE")
@ -2251,43 +2350,89 @@ class Settings(Page):
layout.addWidget(title)
description = QLabel(
"Control connection settings such as the firewall.")
"Control firewall and managed-DNS behavior for systemwide profiles.")
description.setWordWrap(True)
description.setStyleSheet(
f"color: white; font-size: 14px; {self.font_style}")
layout.addWidget(description)
status_layout = QHBoxLayout()
status_label = QLabel("Current status:")
status_label.setStyleSheet(
self.connection_gate_status = QLabel("")
self.connection_gate_status.setWordWrap(True)
self.connection_gate_status.setStyleSheet(
f"color: #e67e22; font-size: 12px; {self.font_style}")
layout.addWidget(self.connection_gate_status)
self.connection_install_button = QPushButton("Install networking helpers")
self.connection_install_button.setFixedSize(190, 38)
self.connection_install_button.setStyleSheet(f"""
QPushButton {{
background: #007AFF;
color: white;
border: none;
border-radius: 5px;
font-weight: bold;
{self.font_style}
}}
QPushButton:hover {{
background: #0056CC;
}}
""")
self.connection_install_button.clicked.connect(self.open_networking_installer)
layout.addWidget(self.connection_install_button)
firewall_status_layout = QHBoxLayout()
firewall_status_label = QLabel("Firewall status:")
firewall_status_label.setStyleSheet(
f"color: white; font-size: 14px; {self.font_style}")
self.firewall_status_value = QLabel("")
self.firewall_status_value.setStyleSheet(
f"color: #e67e22; font-size: 14px; {self.font_style}")
status_layout.addWidget(status_label)
status_layout.addWidget(self.firewall_status_value)
status_layout.addStretch()
layout.addLayout(status_layout)
firewall_status_layout.addWidget(firewall_status_label)
firewall_status_layout.addWidget(self.firewall_status_value)
firewall_status_layout.addStretch()
layout.addLayout(firewall_status_layout)
toggle_layout = QHBoxLayout()
dns_status_layout = QHBoxLayout()
dns_status_label = QLabel("Managed-DNS status:")
dns_status_label.setStyleSheet(
f"color: white; font-size: 14px; {self.font_style}")
self.managed_dns_status_value = QLabel("")
self.managed_dns_status_value.setStyleSheet(
f"color: #e67e22; font-size: 14px; {self.font_style}")
dns_status_layout.addWidget(dns_status_label)
dns_status_layout.addWidget(self.managed_dns_status_value)
dns_status_layout.addStretch()
layout.addLayout(dns_status_layout)
firewall_toggle_layout = QHBoxLayout()
self.firewall_toggle = QCheckBox("Enable Firewall Automatically when Systemwide Profiles are Activated")
self.firewall_toggle.setStyleSheet(self.get_checkbox_style())
toggle_layout.addWidget(self.firewall_toggle)
toggle_layout.addStretch()
layout.addLayout(toggle_layout)
firewall_toggle_layout.addWidget(self.firewall_toggle)
firewall_toggle_layout.addStretch()
layout.addLayout(firewall_toggle_layout)
save_button = QPushButton()
save_button.setFixedSize(75, 46)
save_button.setIcon(QIcon(os.path.join(self.btn_path, "save.png")))
save_button.setIconSize(QSize(75, 46))
save_button.clicked.connect(self.save_firewall_settings)
dns_toggle_layout = QHBoxLayout()
self.managed_dns_toggle = QCheckBox("Enable Managed-DNS Automatically when Systemwide Profiles are Activated")
self.managed_dns_toggle.setStyleSheet(self.get_checkbox_style())
dns_toggle_layout.addWidget(self.managed_dns_toggle)
dns_toggle_layout.addStretch()
layout.addLayout(dns_toggle_layout)
self.connection_save_button = QPushButton()
self.connection_save_button.setFixedSize(75, 46)
self.connection_save_button.setIcon(QIcon(os.path.join(self.btn_path, "save.png")))
self.connection_save_button.setIconSize(QSize(75, 46))
self.connection_save_button.clicked.connect(self.save_connection_settings)
button_layout = QHBoxLayout()
button_layout.addWidget(save_button)
button_layout.addWidget(self.connection_save_button)
button_layout.addStretch()
layout.addLayout(button_layout)
layout.addStretch()
self.load_firewall_settings(
self._prepared_value("firewall_setting", settings_data.read_firewall_setting))
self._prepared_value("firewall_setting", lambda: self.read_gui_connection_setting("firewall_enabled")))
self.load_managed_dns_settings(
self._prepared_value("managed_dns_setting", lambda: self.read_gui_connection_setting("managed_dns_enabled")))
self.refresh_connection_settings_gate()
return page