Skip to content

Commit 65b0b24

Browse files
committed
View fixes for policies and web demo fixes
1 parent f36518a commit 65b0b24

File tree

6 files changed

+55
-26
lines changed

6 files changed

+55
-26
lines changed

src/switchcraft/__init__.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,10 @@
33
import sys
44
# --- WEB / PYODIDE PATCHES (run immediately on package import) ---
55
if sys.platform == "emscripten":
6-
try:
7-
# Patch requests/urllib3 to use browser fetch
8-
import pyodide_http
9-
pyodide_http.patch_all()
10-
except ImportError:
11-
pass
12-
13-
# Mock SSL to prevent import errors in libraries (like urllib3) that expect it
146
import types
157
if "ssl" not in sys.modules:
168
ssl_mock = types.ModuleType("ssl")
17-
# Add minimal ssl module attributes that might be checked
9+
# Add minimal ssl module attributes that might be checked by urllib3
1810
ssl_mock.SSLContext = type("SSLContext", (), {"__init__": lambda *a, **kw: None})
1911
ssl_mock.PROTOCOL_TLS = 2
2012
ssl_mock.PROTOCOL_TLS_CLIENT = 16
@@ -23,8 +15,16 @@
2315
ssl_mock.CERT_NONE = 0
2416
ssl_mock.CERT_OPTIONAL = 1
2517
ssl_mock.CERT_REQUIRED = 2
18+
# Critical: urllib3 checks these version numbers
19+
ssl_mock.OPENSSL_VERSION_NUMBER = 0x101010CF # Fake version >= 3.5.4
20+
ssl_mock.OPENSSL_VERSION = "OpenSSL 3.5.4 (Pyodide Mock)"
21+
ssl_mock.OPENSSL_VERSION_INFO = (1, 1, 1, 15, 15)
22+
ssl_mock.HAS_NEVER_CHECK_COMMON_NAME = True
2623
sys.modules["ssl"] = ssl_mock
2724

28-
# Note: In Flet 0.70+, ft.run() is the correct method (ft.app is deprecated)
29-
# No patching needed for ft.run - web_entry.py should call it correctly.
30-
# The SSL mock above is still needed.
25+
try:
26+
# Patch requests/urllib3 to use browser fetch
27+
import pyodide_http
28+
pyodide_http.patch_all()
29+
except ImportError:
30+
pass

src/switchcraft/assets/lang/de.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@
6161
"settings_policies": "Richtlinien",
6262
"active_policies_title": "Aktive Richtlinien",
6363
"no_policies_found": "Keine aktiven Richtlinien gefunden.",
64+
"policies_enforced_msg": "Die folgenden Einstellungen werden von Ihrer Organisation (GPO/Intune) erzwungen und können nicht geändert werden.",
65+
"policies_no_gpo_msg": "Es sind derzeit keine GPO- oder Intune-Richtlinien aktiv. Die Einstellungen können frei angepasst werden.",
6466
"sync_desc": "Synchronisiere deine Einstellungen über Geräte hinweg.",
6567
"generate_intune_script": "Intune Skript generieren",
6668
"manual_select": "Datei auswählen",

src/switchcraft/assets/lang/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@
6161
"settings_policies": "Policies",
6262
"active_policies_title": "Active Policies",
6363
"no_policies_found": "No active policies found.",
64+
"policies_enforced_msg": "The following settings are enforced by your organization (GPO/Intune) and cannot be changed.",
65+
"policies_no_gpo_msg": "No GPO or Intune policies are currently enforced. Settings can be freely modified.",
6466
"sync_desc": "Sync your settings across devices.",
6567
"ex_dash_filters": "Filters",
6668
"ex_mail_traffic": "Mail Traffic Statistics",

src/switchcraft/gui_modern/app.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,9 @@ def build_ui(self):
980980
ft.NavigationRailDestination(
981981
icon=ft.Icons.EMAIL_OUTLINED, selected_icon=ft.Icons.EMAIL, label=i18n.get("exchange_title") or "Exchange"
982982
), # 20 Exchange
983+
ft.NavigationRailDestination(
984+
icon=ft.Icons.POLICY_OUTLINED, selected_icon=ft.Icons.POLICY, label=i18n.get("settings_policies") or "Policies"
985+
), # 21 Policies
983986
]
984987

985988

src/switchcraft/gui_modern/views/category_view.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@
3636
"Gruppen-Manager": "desc_groups",
3737
"Winget Creator": "desc_wingetcreate",
3838
"Help & Resources": "desc_help",
39-
"Hilfe & Ressourcen": "desc_help"
39+
"Hilfe & Ressourcen": "desc_help",
40+
"Policies": "desc_policies",
41+
"Richtlinien": "desc_policies"
4042
}
4143

4244
class CategoryView(ft.Container):

src/switchcraft/gui_modern/views/settings_view.py

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -108,36 +108,52 @@ def _create_managed_control(self, control: ft.Control, key: str) -> ft.Control:
108108
return control
109109

110110
def _build_policies_tab(self):
111-
"""Builds a read-only view of all managed settings."""
111+
"""Builds a read-only view of managed settings (GPO/Intune only, not user preferences)."""
112112
managed_settings = []
113113
# List of known keys to check
114114
known_keys = [
115115
"CompanyName", "UpdateChannel", "EnableWinget",
116116
"GraphTenantId", "GraphClientId", "IntuneToolPath",
117117
"GitRepoPath", "CustomTemplatePath", "SignScripts",
118118
"CodeSigningCertThumbprint", "CodeSigningCertPath",
119-
"AIProvider", "DebugMode"
119+
"AIProvider", "DebugMode", "GraphClientSecret", "AIKey"
120+
]
121+
122+
# Keys that contain secrets - these should be masked
123+
secret_keys = ["GraphClientSecret", "AIKey", "IntuneClientSecret"]
124+
125+
# Sources that indicate organizational management (NOT user preferences)
126+
managed_sources = [
127+
"GPO (Local Machine)",
128+
"GPO (Current User)",
129+
"Intune OMA-URI",
130+
"System Registry (HKLM)"
120131
]
121132

122133
# Scan for managed keys
123134
for key in known_keys:
124135
res = SwitchCraftConfig.get_value_with_source(key)
125136
if res:
126-
# If managed, the source will be one of the GPO or Intune ones
127-
# But even if it's just 'System Registry', we show it if it's considered 'managed' or if we want to show all sources
128-
# The user specifically asked to show GPO, Systemregistry, Userregistry, Intune OMA URI
129-
managed_settings.append({
130-
"Setting": key,
131-
"Value": str(res["value"]),
132-
"Source": res["source"]
133-
})
137+
source = res["source"]
138+
# Only include if it's from a managed source (not user registry)
139+
if source in managed_sources:
140+
# Mask secret values
141+
value = str(res["value"])
142+
if key in secret_keys and value:
143+
value = "**** hidden ****"
144+
145+
managed_settings.append({
146+
"Setting": key,
147+
"Value": value,
148+
"Source": source
149+
})
134150

135151
if not managed_settings:
136152
return ft.Container(
137153
content=ft.Column([
138154
ft.Icon(ft.Icons.POLICY, size=50, color="GREEN"),
139155
ft.Text(i18n.get("no_policies_found") or "No active policies found.", size=20),
140-
ft.Text("Settings can be freely modified.", color="ON_SURFACE_VARIANT")
156+
ft.Text(i18n.get("policies_no_gpo_msg") or "No GPO or Intune policies are currently enforced. Settings can be freely modified.", color="ON_SURFACE_VARIANT")
141157
], alignment=ft.MainAxisAlignment.CENTER, horizontal_alignment=ft.CrossAxisAlignment.CENTER),
142158
expand=True,
143159
alignment=ft.Alignment(0, 0)
@@ -165,7 +181,7 @@ def _build_policies_tab(self):
165181

166182
return ft.ListView([
167183
ft.Text(i18n.get("active_policies_title") or "Active Policies", size=24, weight=ft.FontWeight.BOLD),
168-
ft.Text("The following settings are enforced by your organization and cannot be changed.", color="ON_SURFACE_VARIANT"),
184+
ft.Text(i18n.get("policies_enforced_msg") or "The following settings are enforced by your organization (GPO/Intune) and cannot be changed.", color="ON_SURFACE_VARIANT"),
169185
ft.Divider(),
170186
dt
171187
], padding=20)
@@ -490,7 +506,11 @@ def pick_intune_tool(e):
490506
client.on_change=lambda e: SwitchCraftConfig.set_user_preference("GraphClientId", e.control.value)
491507
client_ctrl = self._create_managed_control(client, "GraphClientId")
492508

493-
secret = ft.TextField(label=i18n.get("settings_entra_secret") or "Entra Client Secret", value=SwitchCraftConfig.get_secure_value("GraphClientSecret") or "", password=True, can_reveal_password=True)
509+
# Debug: Log what we get from secure storage
510+
secret_value = SwitchCraftConfig.get_secure_value("GraphClientSecret")
511+
logger.debug(f"Loading GraphClientSecret from config: {repr(secret_value[:4] + '***' if secret_value else None)}")
512+
513+
secret = ft.TextField(label=i18n.get("settings_entra_secret") or "Entra Client Secret", value=secret_value or "", password=True, can_reveal_password=True)
494514
secret.on_change=lambda e: SwitchCraftConfig.set_secret("GraphClientSecret", e.control.value)
495515

496516
self.raw_tenant_field = tenant

0 commit comments

Comments
 (0)