Skip to content

Commit 17410e2

Browse files
sebinbashSn0wfreezeDev
authored andcommitted
Create a SetttingsView to manually enter Search Party Token, add error handling for expired token
1 parent 3ef4280 commit 17410e2

File tree

8 files changed

+128
-23
lines changed

8 files changed

+128
-23
lines changed

OpenHaystack/OpenHaystack.xcodeproj/project.pbxproj

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
archiveVersion = 1;
44
classes = {
55
};
6-
objectVersion = 52;
6+
objectVersion = 54;
77
objects = {
88

99
/* Begin PBXBuildFile section */
@@ -58,6 +58,7 @@
5858
78EC227225DBC8CE0042B775 /* Accessory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78EC227125DBC8CE0042B775 /* Accessory.swift */; };
5959
78EC227725DBDB7E0042B775 /* KeychainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78EC227625DBDB7E0042B775 /* KeychainController.swift */; };
6060
78F8BB4C261C50EB00D9F37F /* LargeButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78F8BB4B261C50EB00D9F37F /* LargeButtonStyle.swift */; };
61+
9ED440A02C1605EF002574D1 /* OpenHaystackSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ED4409F2C1605EF002574D1 /* OpenHaystackSettingsView.swift */; };
6162
F126102F2600D1D80066A859 /* Slider+LogScale.swift in Sources */ = {isa = PBXBuildFile; fileRef = F126102E2600D1D80066A859 /* Slider+LogScale.swift */; };
6263
F12D5A5A25FA4F3500CBBA09 /* BluetoothAccessoryScanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = F12D5A5925FA4F3500CBBA09 /* BluetoothAccessoryScanner.swift */; };
6364
F12D5A6025FA79FA00CBBA09 /* Advertisement.swift in Sources */ = {isa = PBXBuildFile; fileRef = F12D5A5F25FA79FA00CBBA09 /* Advertisement.swift */; };
@@ -169,6 +170,7 @@
169170
78EC227125DBC8CE0042B775 /* Accessory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Accessory.swift; sourceTree = "<group>"; };
170171
78EC227625DBDB7E0042B775 /* KeychainController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainController.swift; sourceTree = "<group>"; };
171172
78F8BB4B261C50EB00D9F37F /* LargeButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LargeButtonStyle.swift; sourceTree = "<group>"; };
173+
9ED4409F2C1605EF002574D1 /* OpenHaystackSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenHaystackSettingsView.swift; sourceTree = "<group>"; };
172174
F126102E2600D1D80066A859 /* Slider+LogScale.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Slider+LogScale.swift"; sourceTree = "<group>"; };
173175
F12D5A5925FA4F3500CBBA09 /* BluetoothAccessoryScanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BluetoothAccessoryScanner.swift; sourceTree = "<group>"; };
174176
F12D5A5F25FA79FA00CBBA09 /* Advertisement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Advertisement.swift; sourceTree = "<group>"; };
@@ -380,6 +382,7 @@
380382
isa = PBXGroup;
381383
children = (
382384
78F8BB4A261C50D500D9F37F /* Styles */,
385+
9ED4409F2C1605EF002574D1 /* OpenHaystackSettingsView.swift */,
383386
78286D7625E5114600F65511 /* ActivityIndicator.swift */,
384387
78EC226B25DBC2E40042B775 /* OpenHaystackMainView.swift */,
385388
78486BEE25DD711E0007ED87 /* PopUpAlertView.swift */,
@@ -644,6 +647,7 @@
644647
7821DAD325F7C39A0054DC33 /* ESP32InstallSheet.swift in Sources */,
645648
781EB3F125DAD7EA00FEAA19 /* FindMyKeyDecoder.swift in Sources */,
646649
787D8AC125DECD3C00148766 /* AccessoryController.swift in Sources */,
650+
9ED440A02C1605EF002574D1 /* OpenHaystackSettingsView.swift in Sources */,
647651
78023CAB25F7767000B083EF /* ESP32Controller.swift in Sources */,
648652
F12D5A6025FA79FA00CBBA09 /* Advertisement.swift in Sources */,
649653
781EB3F225DAD7EA00FEAA19 /* OpenHaystackApp.swift in Sources */,

OpenHaystack/OpenHaystack.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 33 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

OpenHaystack/OpenHaystack/AnisetteDataManager.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,6 @@ public class AnisetteDataManager: NSObject {
118118

119119
guard let anisetteData = AOSUtilities.retrieveOTPHeadersForDSID("-2") else { throw AnisetteDataError.aosKitFailure }
120120

121-
let dateFormatter = ISO8601DateFormatter()
122-
123121
guard let machineID = anisetteData["X-Apple-MD-M"] as? String,
124122
let otp = anisetteData["X-Apple-MD"] as? String,
125123
let deviceId = AOSUtilities.machineUDID,

OpenHaystack/OpenHaystack/FindMy/FindMyController.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@ class FindMyController: ObservableObject {
148148

149149
} catch {
150150
print("Failed with error \(error)")
151+
if jsonData.isEmpty {
152+
print("Empty response, consider updating your Search Party Token")
153+
completion(FindMyErrors.invalidSearchPartyToken)
154+
}
151155
devices[deviceIndex].reports = []
152156
}
153157
fetchReportGroup.leave()
@@ -241,4 +245,5 @@ class FindMyController: ObservableObject {
241245
enum FindMyErrors: Error {
242246
case decodingPlistFailed(message: String)
243247
case objectReleased
248+
case invalidSearchPartyToken
244249
}

OpenHaystack/OpenHaystack/HaystackApp/AccessoryController.swift

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import OSLog
1313
import SwiftUI
1414

1515
class AccessoryController: ObservableObject {
16+
@AppStorage("searchPartyToken") private var searchPartyToken: String = ""
1617
@Published var accessories: [Accessory]
1718
var selfObserver: AnyCancellable?
1819
var listElementsObserver = [AnyCancellable]()
@@ -244,10 +245,8 @@ class AccessoryController: ObservableObject {
244245
case .failure(_):
245246
completion(.failure(.activatePlugin))
246247
case .success(let accountData):
247-
248-
guard let token = accountData.searchPartyToken,
249-
token.isEmpty == false
250-
else {
248+
let token = accountData.searchPartyToken ?? self.searchPartyToken.data(using: .utf8) ?? Data()
249+
if token.isEmpty {
251250
completion(.failure(.searchPartyToken))
252251
return
253252
}
@@ -256,7 +255,12 @@ class AccessoryController: ObservableObject {
256255
switch result {
257256
case .failure(let error):
258257
os_log(.error, "Downloading reports failed %@", error.localizedDescription)
259-
completion(.failure(.downloadingReportsFailed))
258+
switch error {
259+
case FindMyErrors.invalidSearchPartyToken:
260+
completion(.failure(.invalidSearchPartyToken))
261+
default:
262+
completion(.failure(.downloadingReportsFailed))
263+
}
260264
case .success(let devices):
261265
let reports = devices.compactMap({ $0.reports }).flatMap({ $0 })
262266
if reports.isEmpty {

OpenHaystack/OpenHaystack/HaystackApp/Views/OpenHaystackMainView.swift

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ struct OpenHaystackMainView: View {
3838

3939
@State var showESP32DeploySheet = false
4040

41+
@AppStorage("searchPartyToken") private var settingsSPToken: String?
42+
@AppStorage("useMailPlugin") private var settingsUseMailPlugin: Bool = false
43+
4144
var body: some View {
4245

4346
NavigationView {
@@ -135,7 +138,7 @@ struct OpenHaystackMainView: View {
135138

136139
Button(
137140
action: {
138-
if !self.mailPluginIsActive {
141+
if self.settingsUseMailPlugin && !self.mailPluginIsActive {
139142
self.showMailPlugInPopover.toggle()
140143
self.checkPluginIsRunning(silent: true, nil)
141144
} else {
@@ -174,17 +177,26 @@ struct OpenHaystackMainView: View {
174177
return
175178
}
176179

177-
let pluginManager = MailPluginManager()
180+
/// Checks if the search party token was set in the settings. If true the plugin is also not needed
181+
if let tokenString = self.settingsSPToken {
182+
self.searchPartyToken = tokenString
183+
return
184+
}
178185

179-
// Check if the plugin is installed
180-
if pluginManager.isMailPluginInstalled == false {
181-
// Install the mail plugin
182-
self.alertType = .activatePlugin
183-
self.checkPluginIsRunning(silent: true, nil)
184-
} else {
185-
self.checkPluginIsRunning(nil)
186+
/// Uses mail plugin if enabled in settings
187+
if self.settingsUseMailPlugin {
188+
let pluginManager = MailPluginManager()
189+
// Check if the plugin is installed
190+
if pluginManager.isMailPluginInstalled == false {
191+
// Install the mail plugin
192+
self.alertType = .activatePlugin
193+
self.checkPluginIsRunning(silent: true, nil)
194+
} else {
195+
self.checkPluginIsRunning(nil)
196+
}
186197
}
187198

199+
188200
}
189201

190202
/// Download the location reports for all current accessories. Shows an error if something fails, like plug-in is missing
@@ -308,7 +320,19 @@ struct OpenHaystackMainView: View {
308320
title: Text("Add the search party token"),
309321
message: Text(
310322
"""
311-
Please paste the search party token below after copying itfrom the macOS Keychain.
323+
Please paste the search party token in the settings after copying it from the macOS Keychain.
324+
The item that contains the key can be found by searching for:
325+
com.apple.account.DeviceLocator.search-party-token
326+
"""
327+
),
328+
dismissButton: Alert.Button.okay())
329+
case .invalidSearchPartyToken:
330+
return Alert(
331+
title: Text("Invalid search party token"),
332+
message: Text(
333+
"""
334+
The request returned an empty result, this is probably due to an invalid search party token.
335+
Please consider updating your search party token in the settings after copying it from the macOS Keychain.
312336
The item that contains the key can be found by searching for:
313337
com.apple.account.DeviceLocator.search-party-token
314338
"""
@@ -388,6 +412,7 @@ struct OpenHaystackMainView: View {
388412

389413
case keyError
390414
case searchPartyToken
415+
case invalidSearchPartyToken
391416
case deployFailed
392417
case nrfDeployFailed
393418
case deployedSuccessfully
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//
2+
// OpenHaystack – Tracking personal Bluetooth devices via Apple's Find My network
3+
//
4+
// Copyright © 2024 Secure Mobile Networking Lab (SEEMOO)
5+
// Copyright © 2024 The Open Wireless Link Project
6+
//
7+
// SPDX-License-Identifier: AGPL-3.0-only
8+
//
9+
10+
import Foundation
11+
import SwiftUI
12+
13+
struct OpenHaystackSettingsView: View {
14+
var body: some View {
15+
TabView {
16+
GeneralSettingsView()
17+
.tabItem {
18+
Label("General", systemImage: "gear")
19+
}
20+
}
21+
}
22+
}
23+
24+
struct GeneralSettingsView: View {
25+
@AppStorage("useMailPlugin") private var useMailPlugin = false
26+
@AppStorage("searchPartyToken") private var searchPartyToken = ""
27+
28+
var body: some View {
29+
Form {
30+
Toggle("Use Apple Mail Plugin (only works on macOS 13 and lower)", isOn: $useMailPlugin)
31+
TextField("Search Party Token", text: $searchPartyToken)
32+
}
33+
.padding(20)
34+
.frame(width: 600, height: 200)
35+
}
36+
}

OpenHaystack/OpenHaystack/OpenHaystackApp.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ struct OpenHaystackApp: App {
4444
.commands {
4545
SidebarCommands()
4646
}
47+
#if os(macOS)
48+
Settings {
49+
OpenHaystackSettingsView()
50+
}
51+
#endif
4752
}
4853

4954
func checkForUpdates() {

0 commit comments

Comments
 (0)