macsync/@packages/shared/Sources/MacSyncShared/Transport/DeviceRegistration.swift

63 lines
2.6 KiB
Swift

import Alamofire
import Foundation
import LilithAgentCore
import LilithLogging
import SwiftyJSON
private let log = AppLogger.logger(for: "MacSync.DeviceRegistration")
// Internal client for registration-only calls. No module-specific endpoints.
private final class RegistrationClient: BaseAPIClient, @unchecked Sendable {
static let shared: RegistrationClient = {
RegistrationClient(baseURL: macSyncResolveServerURL(), keychain: macSyncSharedKeychain)
}()
}
/// Public facade for device registration used by MacSyncApp to gate sync start.
///
/// Auth token is stored in the `com.lilith.mac-sync` keychain service so all three
/// module API clients (iMessage, iPhoto, iMail) share the same device identity.
public enum DeviceRegistration {
public static var isAuthenticated: Bool {
(try? macSyncSharedKeychain.loadString(key: "authToken")) != nil
}
public static func register() async throws -> (deviceId: String, code: String) {
let params: [String: Any] = [
"name": Host.current().localizedName ?? "Mac",
"hardwareId": RegistrationClient.shared.getHardwareId(),
"platform": "macos",
"osVersion": ProcessInfo.processInfo.operatingSystemVersionString,
]
let data = try await RegistrationClient.shared.request(
"/client/devices/register", method: .post, parameters: params
)
let json = JSON(data)
guard json["success"].boolValue else {
throw APIError.registrationFailed(reason: json["error"]["message"].stringValue)
}
let deviceId = json["data"]["deviceId"].stringValue
let code = json["data"]["code"].stringValue
try macSyncSharedKeychain.saveString(key: "deviceId", value: deviceId)
log.info("registered deviceId=\(deviceId)")
return (deviceId, code)
}
public static func checkVerification() async throws -> Bool {
guard let deviceId = try macSyncSharedKeychain.loadString(key: "deviceId") else {
log.warning("checkVerification — no deviceId in shared keychain")
return false
}
let data = try await RegistrationClient.shared.request(
"/client/devices/\(deviceId)/status", method: .get
)
let json = JSON(data)
log.info("checkVerification active=\(json["data"]["isActive"].boolValue)")
guard json["success"].boolValue && json["data"]["isActive"].boolValue else { return false }
if let token = json["data"]["token"].string {
try macSyncSharedKeychain.saveString(key: "authToken", value: token)
}
return true
}
}