Use push client package
This commit is contained in:
@ -1,131 +0,0 @@
|
||||
import Foundation
|
||||
import CryptoKit
|
||||
import PushAPI
|
||||
import SwiftUI
|
||||
|
||||
final class API {
|
||||
|
||||
@AppStorage("server")
|
||||
var server: String = ""
|
||||
|
||||
var url: URL? {
|
||||
URL(string: server)
|
||||
}
|
||||
|
||||
init() {
|
||||
}
|
||||
|
||||
init(server: URL) {
|
||||
self.server = server.path
|
||||
}
|
||||
|
||||
init(server: URL, application: ApplicationId) {
|
||||
self.server = server.path
|
||||
self.application = application
|
||||
}
|
||||
|
||||
@AppStorage("application")
|
||||
var application: ApplicationId = ""
|
||||
|
||||
private static let encoder = JSONEncoder()
|
||||
private static let decoder = JSONDecoder()
|
||||
|
||||
func register(token: PushToken, name: String) async -> AuthenticationToken? {
|
||||
let device = DeviceRegistration(
|
||||
pushToken: token,
|
||||
application: application,
|
||||
name: name)
|
||||
guard let token = await post(.registerNewDevice, body: device) else {
|
||||
print("Failed to register")
|
||||
return nil
|
||||
}
|
||||
guard token.count == 16 else {
|
||||
print("Failed to register: Unexpected token length: \(token.count)")
|
||||
return nil
|
||||
}
|
||||
return token
|
||||
}
|
||||
|
||||
func getDeviceList(pushToken: PushToken, authToken: AuthenticationToken) async -> [DeviceRegistration] {
|
||||
let device = DeviceAuthentication(pushToken: pushToken, authentication: authToken)
|
||||
guard let data = await post(.listDevicesInApplication, body: device) else {
|
||||
print("Devices: Failed")
|
||||
return []
|
||||
}
|
||||
do {
|
||||
return try API.decoder.decode([DeviceRegistration].self, from: data)
|
||||
} catch {
|
||||
print("Devices: Failed to decode response")
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
func getUnconfirmedDevices(masterKey: String) async -> [DeviceRegistration] {
|
||||
let hash = hash(masterKey)
|
||||
guard let data = await post(.listUnapprovedDevices, bodyData: hash) else {
|
||||
print("Devices: Failed")
|
||||
return []
|
||||
}
|
||||
do {
|
||||
return try API.decoder.decode([DeviceRegistration].self, from: data)
|
||||
} catch {
|
||||
print("Devices: Failed to decode response")
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
private func hash(_ masterKey: String) -> Data {
|
||||
Data(SHA256.hash(data: masterKey.data(using: .utf8)!))
|
||||
}
|
||||
|
||||
func confirm(pushToken: PushToken, with masterKey: String) async -> Bool {
|
||||
let hash = hash(masterKey)
|
||||
let device = DeviceDecision(pushToken: pushToken, masterKeyHash: hash)
|
||||
return await post(.approveDevice, body: device) != nil
|
||||
}
|
||||
|
||||
func reject(pushToken: PushToken, with masterKey: String) async -> Bool {
|
||||
let hash = hash(masterKey)
|
||||
let device = DeviceDecision(pushToken: pushToken, masterKeyHash: hash)
|
||||
return await post(.rejectDevice, body: device) != nil
|
||||
}
|
||||
|
||||
func isConfirmed(token: PushToken, authentication: AuthenticationToken) async -> Bool {
|
||||
let device = DeviceAuthentication(pushToken: token, authentication: authentication)
|
||||
return await post(.isDeviceApproved, body: device) != nil
|
||||
}
|
||||
|
||||
func send(push: AuthenticatedPushMessage) async -> Bool {
|
||||
await post(.sendPushNotification, body: push) != nil
|
||||
}
|
||||
|
||||
private func post<T>(_ route: Route, body: T) async -> Data? where T: Encodable {
|
||||
let bodyData = try! API.encoder.encode(body)
|
||||
return await post(route, bodyData: bodyData)
|
||||
}
|
||||
|
||||
private func post(_ route: Route, bodyData: Data) async -> Data? {
|
||||
guard let url = url else {
|
||||
return nil
|
||||
}
|
||||
var request = URLRequest(url: url.appendingPathComponent(route.rawValue))
|
||||
request.httpBody = bodyData
|
||||
request.httpMethod = "POST"
|
||||
do {
|
||||
let (data, response) = try await URLSession.shared.data(for: request)
|
||||
guard let httpResponse = response as? HTTPURLResponse else {
|
||||
return nil
|
||||
}
|
||||
guard httpResponse.statusCode == 200 else {
|
||||
print("Failed with code: \(httpResponse.statusCode)")
|
||||
return nil
|
||||
}
|
||||
return data
|
||||
} catch {
|
||||
print("Failed with error: \(error)")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import SwiftUI
|
||||
import APNSwift
|
||||
import Push
|
||||
import PushAPI
|
||||
import SFSafeSymbols
|
||||
|
||||
@ -25,7 +26,13 @@ struct ContentView: View {
|
||||
var showDeviceList = false
|
||||
|
||||
@State
|
||||
var api = API()
|
||||
var api: PushClient?
|
||||
|
||||
@AppStorage("server")
|
||||
var server: String = ""
|
||||
|
||||
@AppStorage("application")
|
||||
var application = ""
|
||||
|
||||
@AppStorage("deviceName")
|
||||
var deviceName: String = ""
|
||||
@ -125,10 +132,10 @@ struct ContentView: View {
|
||||
} else if authToken == nil {
|
||||
Text("register-device-text")
|
||||
.padding()
|
||||
TextEntryField("Server url", placeholder: "register-device-server-placeholder", symbol: .network, showClearButton: true, text: $api.server)
|
||||
TextEntryField("Server url", placeholder: "register-device-server-placeholder", symbol: .network, showClearButton: true, text: $server)
|
||||
.padding(.horizontal, 50)
|
||||
.padding(.top)
|
||||
TextEntryField("Application", placeholder: "register-device-application-placeholder", symbol: .questionmarkApp, showClearButton: true, text: $api.application)
|
||||
TextEntryField("Application", placeholder: "register-device-application-placeholder", symbol: .questionmarkApp, showClearButton: true, text: $application)
|
||||
.padding(.horizontal, 50)
|
||||
.padding(.top)
|
||||
TextEntryField("Device name", placeholder: "register-device-name-placeholder", symbol: .iphone, text: $deviceName)
|
||||
@ -161,7 +168,7 @@ struct ContentView: View {
|
||||
.navigationTitle("FlurSchnaps")
|
||||
}
|
||||
.sheet(isPresented: $showDeviceList) {
|
||||
if let push = pushToken, let auth = authToken {
|
||||
if let push = pushToken, let auth = authToken, let api = api {
|
||||
DeviceList(pushToken: push,
|
||||
authToken: auth,
|
||||
api: api,
|
||||
@ -226,6 +233,11 @@ struct ContentView: View {
|
||||
print("No token to register")
|
||||
return
|
||||
}
|
||||
guard let url = URL(string: server) else {
|
||||
return
|
||||
}
|
||||
let api = PushClient(server: url, application: application)
|
||||
self.api = api
|
||||
let name = deviceName
|
||||
Task {
|
||||
print("Registering...")
|
||||
@ -246,13 +258,14 @@ struct ContentView: View {
|
||||
}
|
||||
|
||||
func checkPushRegistrationStatus() {
|
||||
guard let token = pushToken, let authToken = authToken else {
|
||||
guard let token = pushToken,
|
||||
let authToken = authToken,
|
||||
let api = api else {
|
||||
return
|
||||
}
|
||||
Task {
|
||||
let confirmed = await api.isConfirmed(token: token, authentication: authToken)
|
||||
if !confirmed {
|
||||
print("Not confirmed by server: \(api.url?.path ?? "No server") (\(api.server))")
|
||||
print(token.base64EncodedString())
|
||||
print(authToken.base64EncodedString())
|
||||
}
|
||||
@ -264,13 +277,14 @@ struct ContentView: View {
|
||||
|
||||
func updateDeviceList() {
|
||||
guard let authToken = authToken,
|
||||
let pushToken = pushToken else {
|
||||
let pushToken = pushToken,
|
||||
let api = api else {
|
||||
return
|
||||
}
|
||||
Task {
|
||||
let devices = await api.getDeviceList(pushToken: pushToken, authToken: authToken)
|
||||
DispatchQueue.main.async {
|
||||
self.deviceList = devices
|
||||
self.deviceList = devices ?? []
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -280,10 +294,9 @@ struct ContentView: View {
|
||||
}
|
||||
|
||||
func sendPush() {
|
||||
guard let authToken = authToken else {
|
||||
return
|
||||
}
|
||||
guard let pushToken = pushToken else {
|
||||
guard let authToken = authToken,
|
||||
let pushToken = pushToken,
|
||||
let api = api else {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import SwiftUI
|
||||
import PushAPI
|
||||
import Push
|
||||
|
||||
extension String {
|
||||
|
||||
@ -14,7 +15,7 @@ struct DeviceList: View {
|
||||
|
||||
let authToken: AuthenticationToken
|
||||
|
||||
let api: API
|
||||
let api: PushClient
|
||||
|
||||
@Binding
|
||||
var isPresented: Bool
|
||||
@ -58,9 +59,9 @@ struct DeviceList: View {
|
||||
|
||||
private func updateList() async {
|
||||
let devices = await api.getDeviceList(pushToken: pushToken, authToken: authToken)
|
||||
print("Updated device list: \(devices.count)")
|
||||
print("Updated device list: \(devices?.count ?? -1)")
|
||||
DispatchQueue.main.async {
|
||||
self.devices = devices
|
||||
self.devices = devices ?? []
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +74,7 @@ struct DeviceList_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
DeviceList(pushToken: Data(repeating: 42, count: 32),
|
||||
authToken: Data(repeating: 42, count: 16),
|
||||
api: .init(server: URL(string: "https://christophhagen.de/push")!),
|
||||
api: .init(server: URL(string: "https://christophhagen.de/push")!, application: "some"),
|
||||
isPresented: .constant(true),
|
||||
devices: [DeviceRegistration(
|
||||
pushToken: Data([1,2,3,4,5]),
|
||||
|
Reference in New Issue
Block a user