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.
This commit is contained in:
parent
18c3a49404
commit
87d6395ed2
@ -1,4 +1,5 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
import AppKit
|
||||||
|
|
||||||
/// Service für Mac-DNS-Profile-Download + Installation.
|
/// Service für Mac-DNS-Profile-Download + Installation.
|
||||||
enum MacProfileInstaller {
|
enum MacProfileInstaller {
|
||||||
@ -20,8 +21,12 @@ enum MacProfileInstaller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lädt Mac-DNS-Profile von Backend und installiert via `profiles install`.
|
/// Lädt Mac-DNS-Profile von Backend und öffnet es in System Settings → Profiles.
|
||||||
/// Profile-File wird nach Installation gelöscht (enthält sensiblen Token).
|
/// 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 {
|
static func downloadAndInstall(registration: MagicRegistration) async throws {
|
||||||
// 1. Download profile
|
// 1. Download profile
|
||||||
let profileURL: URL
|
let profileURL: URL
|
||||||
@ -31,19 +36,20 @@ enum MacProfileInstaller {
|
|||||||
throw InstallerError.downloadFailed(error.localizedDescription)
|
throw InstallerError.downloadFailed(error.localizedDescription)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Install via `profiles` command (macOS-only)
|
// 2. Open in System Settings → Profiles (user must confirm in UI)
|
||||||
let result = try await ProcessRunner.run(
|
let opened = await MainActor.run {
|
||||||
"/usr/bin/profiles",
|
NSWorkspace.shared.open(profileURL)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.
|
/// Prüft ob ReBreak-DNS-Profile bereits installiert ist.
|
||||||
|
|||||||
@ -196,13 +196,10 @@ struct MacRegistrationView: View {
|
|||||||
try await model.registerMac()
|
try await model.registerMac()
|
||||||
|
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
successMessage = "Mac erfolgreich registriert ✓"
|
|
||||||
isRegistering = false
|
isRegistering = false
|
||||||
}
|
}
|
||||||
|
// KEIN Auto-Profile-Install mehr — DNS-Schutz ist optional.
|
||||||
// Auto-trigger profile install
|
// User entscheidet selbst via Button.
|
||||||
try await Task.sleep(nanoseconds: 500_000_000) // 0.5s delay
|
|
||||||
await handleProfileInstall()
|
|
||||||
|
|
||||||
} catch {
|
} catch {
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
@ -226,14 +223,15 @@ struct MacRegistrationView: View {
|
|||||||
do {
|
do {
|
||||||
try await MacProfileInstaller.downloadAndInstall(registration: registration)
|
try await MacProfileInstaller.downloadAndInstall(registration: registration)
|
||||||
|
|
||||||
// Re-check profile status
|
|
||||||
await checkProfileStatus()
|
|
||||||
|
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
isInstallingProfile = false
|
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 {
|
} catch {
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
isInstallingProfile = false
|
isInstallingProfile = false
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user