- backend: /api/magic/{register,devices,profile,release} + AdGuard provisioning + 24h cooldown
- prisma: magic_binding_fields migration (additive on UserDevice)
- mac-app: Phase 2 - Login + MacRegistration + Profile install
- marketing: landing section + /download/rebreakmagic + DMG
- lyra: forbidden phrases + RebreakMagic coach guidance
83 lines
2.5 KiB
Swift
83 lines
2.5 KiB
Swift
import Foundation
|
|
import IOKit
|
|
|
|
/// Device-Info für den aktuellen Mac.
|
|
/// Wird für /api/magic/register benötigt.
|
|
struct MacDeviceInfo {
|
|
let deviceId: String // IOPlatformUUID
|
|
let hostname: String // Host.current().localizedName
|
|
let model: String // hw.model via sysctl
|
|
let osVersion: String // ProductVersion
|
|
}
|
|
|
|
enum MacDeviceDetectorError: Error, LocalizedError {
|
|
case platformUUIDNotFound
|
|
case sysctlFailed(String)
|
|
|
|
var errorDescription: String? {
|
|
switch self {
|
|
case .platformUUIDNotFound:
|
|
return "IOPlatformUUID nicht gefunden"
|
|
case .sysctlFailed(let msg):
|
|
return "sysctl fehlgeschlagen: \(msg)"
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Erkennt Mac-Hardware-Infos via IOKit + sysctl.
|
|
enum MacDeviceDetector {
|
|
|
|
/// Liest IOPlatformUUID — eindeutige Hardware-ID des Mac.
|
|
static func platformUUID() throws -> String {
|
|
let service = IOServiceGetMatchingService(
|
|
kIOMainPortDefault,
|
|
IOServiceMatching("IOPlatformExpertDevice")
|
|
)
|
|
|
|
guard service != 0 else {
|
|
throw MacDeviceDetectorError.platformUUIDNotFound
|
|
}
|
|
|
|
defer { IOObjectRelease(service) }
|
|
|
|
guard let uuidCF = IORegistryEntryCreateCFProperty(
|
|
service,
|
|
"IOPlatformUUID" as CFString,
|
|
kCFAllocatorDefault,
|
|
0
|
|
)?.takeRetainedValue() as? String else {
|
|
throw MacDeviceDetectorError.platformUUIDNotFound
|
|
}
|
|
|
|
return uuidCF
|
|
}
|
|
|
|
/// Liest hw.model via sysctl (z.B. "MacBookPro18,3").
|
|
static func hwModel() throws -> String {
|
|
var size: size_t = 0
|
|
sysctlbyname("hw.model", nil, &size, nil, 0)
|
|
|
|
var model = [CChar](repeating: 0, count: size)
|
|
guard sysctlbyname("hw.model", &model, &size, nil, 0) == 0 else {
|
|
throw MacDeviceDetectorError.sysctlFailed("hw.model read failed")
|
|
}
|
|
|
|
return String(cString: model)
|
|
}
|
|
|
|
/// Sammelt alle Infos für /api/magic/register.
|
|
static func detect() throws -> MacDeviceInfo {
|
|
let deviceId = try platformUUID()
|
|
let hostname = Host.current().localizedName ?? "Unknown Mac"
|
|
let model = try hwModel()
|
|
let osVersion = ProcessInfo.processInfo.operatingSystemVersionString
|
|
|
|
return MacDeviceInfo(
|
|
deviceId: deviceId,
|
|
hostname: hostname,
|
|
model: model,
|
|
osVersion: osVersion
|
|
)
|
|
}
|
|
}
|