From 87d6395ed28b7a94f1d41f57022f250b57866125 Mon Sep 17 00:00:00 2001 From: chahinebrini Date: Wed, 3 Jun 2026 10:29:30 +0200 Subject: [PATCH] fix(magic-mac): macOS 26 profile install via NSWorkspace + de-dup register card Zwei Bugs: 1) 'profiles install -path' wurde mit macOS 15+ entfernt ('profiles tool no longer supports installs. Use System Settings Profiles to add configuration profiles.'). Auf macOS 26 (Tahoe) ist das Hard-Removal. -> Switch zu NSWorkspace.shared.open(profileURL): \u00f6ffnet die .mobileconfig in System Settings -> Profile-Pane. User best\u00e4tigt manuell + gibt Admin-PW. Einziger Weg ohne MDM-Enrollment. -> success-Text passt: 'Bitte in System Settings Installieren klicken'. 2) Doppelte 'Mac registriert'-Karte: successMessage-Card UND strukturierte Registration-Status-Card beide sichtbar nach register. Auto-Profile-Install nach Register war eh totes Verhalten (DNS jetzt optional). -> successMessage wird nicht mehr in handleRegistration gesetzt, nur noch in handleProfileInstall. Eine Karte. --- .../Services/MacProfileInstaller.swift | 34 +++++++++++-------- .../Sources/Views/MacRegistrationView.swift | 16 ++++----- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/apps/rebreak-magic-mac/Sources/Services/MacProfileInstaller.swift b/apps/rebreak-magic-mac/Sources/Services/MacProfileInstaller.swift index 9e7e61c..f07c10c 100644 --- a/apps/rebreak-magic-mac/Sources/Services/MacProfileInstaller.swift +++ b/apps/rebreak-magic-mac/Sources/Services/MacProfileInstaller.swift @@ -1,4 +1,5 @@ import Foundation +import AppKit /// Service für Mac-DNS-Profile-Download + Installation. enum MacProfileInstaller { @@ -20,8 +21,12 @@ enum MacProfileInstaller { } } - /// Lädt Mac-DNS-Profile von Backend und installiert via `profiles install`. - /// Profile-File wird nach Installation gelöscht (enthält sensiblen Token). + /// Lädt Mac-DNS-Profile von Backend und öffnet es in System Settings → Profiles. + /// Ab macOS 15+ ist `profiles install` für Configuration Profiles entfernt + /// ("profiles tool no longer supports installs. Use System Settings + /// Profiles to add configuration profiles."). Einzig zulässiger Weg ohne + /// MDM-Enrollment: NSWorkspace öffnet die .mobileconfig → Profiles-Pane + /// erscheint → User muss manuell „Installieren" klicken + Admin-PW geben. static func downloadAndInstall(registration: MagicRegistration) async throws { // 1. Download profile let profileURL: URL @@ -31,19 +36,20 @@ enum MacProfileInstaller { throw InstallerError.downloadFailed(error.localizedDescription) } - // 2. Install via `profiles` command (macOS-only) - let result = try await ProcessRunner.run( - "/usr/bin/profiles", - arguments: ["install", "-path", profileURL.path] - ) - - // 3. Clean up downloaded file - try? FileManager.default.removeItem(at: profileURL) - - if result.exitCode != 0 { - let errorMsg = result.stderr.isEmpty ? result.stdout : result.stderr - throw InstallerError.installFailed(errorMsg) + // 2. Open in System Settings → Profiles (user must confirm in UI) + let opened = await MainActor.run { + NSWorkspace.shared.open(profileURL) } + + if !opened { + try? FileManager.default.removeItem(at: profileURL) + throw InstallerError.installFailed( + "System Settings konnte das Profil nicht öffnen. Datei liegt unter: \(profileURL.path)" + ) + } + + // NICHT löschen — System Settings braucht die Datei evtl. noch. + // OS räumt /tmp selbst auf. } /// Prüft ob ReBreak-DNS-Profile bereits installiert ist. diff --git a/apps/rebreak-magic-mac/Sources/Views/MacRegistrationView.swift b/apps/rebreak-magic-mac/Sources/Views/MacRegistrationView.swift index bc81657..d876601 100644 --- a/apps/rebreak-magic-mac/Sources/Views/MacRegistrationView.swift +++ b/apps/rebreak-magic-mac/Sources/Views/MacRegistrationView.swift @@ -196,13 +196,10 @@ struct MacRegistrationView: View { try await model.registerMac() await MainActor.run { - successMessage = "Mac erfolgreich registriert ✓" isRegistering = false } - - // Auto-trigger profile install - try await Task.sleep(nanoseconds: 500_000_000) // 0.5s delay - await handleProfileInstall() + // KEIN Auto-Profile-Install mehr — DNS-Schutz ist optional. + // User entscheidet selbst via Button. } catch { await MainActor.run { @@ -226,14 +223,15 @@ struct MacRegistrationView: View { do { try await MacProfileInstaller.downloadAndInstall(registration: registration) - // Re-check profile status - await checkProfileStatus() - await MainActor.run { isInstallingProfile = false - successMessage = "DNS-Filter-Profil installiert ✓" + successMessage = "System Settings → Profile geöffnet. Bitte dort „Installieren" klicken und Admin-Passwort eingeben." } + // Re-check profile status nach kurzer Wartezeit (User muss in UI bestätigen) + try? await Task.sleep(nanoseconds: 3_000_000_000) + await checkProfileStatus() + } catch { await MainActor.run { isInstallingProfile = false