154 lines
5.1 KiB
Swift

import Foundation
import Observation
enum DebugSupervisionMode: String, CaseIterable, Identifiable {
case none
case forceSupervised
case forceUnsupervised
var id: String { rawValue }
var title: String {
switch self {
case .none: return "Aus"
case .forceSupervised: return "Force Supervised"
case .forceUnsupervised: return "Force Unsupervised"
}
}
}
@MainActor
@Observable
final class WizardModel {
var step: WizardStep = .welcome
var device: DeviceState?
var supervisionLog: [String] = []
var supervisionRunning: Bool = false
var supervisionError: String?
var enrollmentLog: [String] = []
var enrollmentRunning: Bool = false
var enrollmentError: String?
var configureLog: [String] = []
var configureRunning: Bool = false
var configureError: String?
var showAdvancedLogs: Bool = false
var cooldownEndsAt: Date?
// Debug-Reset State
var supervisionMode: DebugSupervisionMode = .none
var resetRunning: Bool = false
var resetStatus: String?
var resetAll: Bool = true
var resetEnrollmentProfile: Bool = true
var resetLockProfile: Bool = true
var resetApp: Bool = true
func advance() {
if let next = WizardStep(rawValue: step.rawValue + 1) {
step = next
}
}
func goTo(_ s: WizardStep) {
step = s
}
func reset() {
step = .welcome
device = nil
supervisionLog = []
enrollmentLog = []
configureLog = []
supervisionError = nil
enrollmentError = nil
configureError = nil
showAdvancedLogs = false
cooldownEndsAt = nil
resetStatus = nil
}
func startDebugReset() {
guard device != nil else {
resetStatus = "Kein iPhone erkannt."
return
}
resetRunning = true
resetStatus = "Führe Debug-Reset aus …"
Task {
do {
var changes: [String] = []
let removeEnrollment = resetAll || resetEnrollmentProfile
let removeLock = resetAll || resetLockProfile
let removeApp = resetAll || resetApp
let installedProfileIDs = await DeviceDetector.installedProfileIDs()
var profileIDs: [String] = []
if removeEnrollment, installedProfileIDs.contains(DeviceState.enrollmentProfileID) {
profileIDs.append(DeviceState.enrollmentProfileID)
}
if removeLock, installedProfileIDs.contains(DeviceState.lockProfileID) {
profileIDs.append(DeviceState.lockProfileID)
}
if !profileIDs.isEmpty {
try await DeviceDetector.removeProfiles(identifiers: profileIDs)
changes.append("Profile gelöscht: \(profileIDs.joined(separator: ", "))")
}
if removeApp {
try await DeviceDetector.removeApp(bundleID: "org.rebreak.app")
changes.append("App gelöscht: org.rebreak.app")
}
switch supervisionMode {
case .forceSupervised:
_ = try await SuperviseRunner.supervise(verbose: false) { _ in }
changes.append("Mode gesetzt: supervised")
case .forceUnsupervised:
_ = try await SuperviseRunner.unsupervise { _ in }
changes.append("Mode gesetzt: unsupervised")
case .none:
break
}
let nowInstalledProfiles = await DeviceDetector.installedProfileIDs()
let nowApps = await DeviceDetector.installedAppBundleIDs()
let status = await DeviceDetector.readSupervisionStatus()
await MainActor.run {
if changes.isEmpty {
resetStatus = "Keine Aktion gewählt."
} else {
resetStatus = "\(changes.joined(separator: " · "))"
}
if var device = self.device {
device.installedProfileIDs = nowInstalledProfiles
device.installedAppBundleIDs = nowApps
device.isSupervised = status.isSupervised
device.supervisorOrgName = status.organizationName
device.isFmiOn = status.findMyEnabled
device.isEnrolled = nowInstalledProfiles.contains(DeviceState.enrollmentProfileID)
if !nowApps.contains("org.rebreak.app") { device.isManaged = false }
if !nowInstalledProfiles.contains(DeviceState.lockProfileID) { device.isFilterActive = false }
self.device = device
}
resetRunning = false
}
} catch {
await MainActor.run {
resetStatus = "✗ Reset fehlgeschlagen: \(error.localizedDescription)"
resetRunning = false
}
}
}
}
}