From b14a4bf47c26da7330ae14b98f5dbdea2c379edb Mon Sep 17 00:00:00 2001 From: jnMars <563438383@qq.com> Date: Wed, 1 Mar 2023 16:06:48 +0800 Subject: [PATCH] Feat - debug mode - subEvent api pubEvent api --- Authing/Authing.xcodeproj/project.pbxproj | 4 + Authing/Authing/Authing.swift | 20 +++++ Authing/Authing/Network/AuthClient.swift | 62 ++++++++++---- .../Network/AuthingWebsocketClient.swift | 85 +++++++++++++++++++ Authing/Authing/Util/ALog.swift | 16 +++- Authing/Authing/Util/Util.swift | 2 +- 6 files changed, 168 insertions(+), 21 deletions(-) create mode 100644 Authing/Authing/Network/AuthingWebsocketClient.swift diff --git a/Authing/Authing.xcodeproj/project.pbxproj b/Authing/Authing.xcodeproj/project.pbxproj index 561af33..7769552 100644 --- a/Authing/Authing.xcodeproj/project.pbxproj +++ b/Authing/Authing.xcodeproj/project.pbxproj @@ -50,6 +50,7 @@ A828C1B328DB3902001E78D0 /* Authing.h in Headers */ = {isa = PBXBuildFile; fileRef = A828C1A728DB3902001E78D0 /* Authing.h */; settings = {ATTRIBUTES = (Public, ); }; }; A8416AAE28DD91D600480FE4 /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8416AAD28DD91D600480FE4 /* Client.swift */; }; A8416AB128DDB73700480FE4 /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8416AB028DDB73700480FE4 /* Response.swift */; }; + A8796AFA29AF380C007033E5 /* AuthingWebsocketClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8796AF929AF380C007033E5 /* AuthingWebsocketClient.swift */; }; A89FCE8528E1BE8300B2F347 /* AuthOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A89FCE8428E1BE8300B2F347 /* AuthOptions.swift */; }; A8AB048028DC63B300530C86 /* Authing.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8AB047F28DC63B300530C86 /* Authing.swift */; }; A8AB048228DC63C400530C86 /* AuthClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8AB048128DC63C400530C86 /* AuthClient.swift */; }; @@ -106,6 +107,7 @@ A828C1B128DB3902001E78D0 /* AuthingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthingTests.swift; sourceTree = ""; }; A8416AAD28DD91D600480FE4 /* Client.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = ""; }; A8416AB028DDB73700480FE4 /* Response.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Response.swift; sourceTree = ""; }; + A8796AF929AF380C007033E5 /* AuthingWebsocketClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthingWebsocketClient.swift; sourceTree = ""; }; A89FCE8428E1BE8300B2F347 /* AuthOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthOptions.swift; sourceTree = ""; }; A8AB047F28DC63B300530C86 /* Authing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Authing.swift; sourceTree = ""; }; A8AB048128DC63C400530C86 /* AuthClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthClient.swift; sourceTree = ""; }; @@ -261,6 +263,7 @@ A8416AAD28DD91D600480FE4 /* Client.swift */, A8AB048128DC63C400530C86 /* AuthClient.swift */, A89FCE8428E1BE8300B2F347 /* AuthOptions.swift */, + A8796AF929AF380C007033E5 /* AuthingWebsocketClient.swift */, A8416AB028DDB73700480FE4 /* Response.swift */, ); path = Network; @@ -455,6 +458,7 @@ A8416AAE28DD91D600480FE4 /* Client.swift in Sources */, A8AB048D28DC668A00530C86 /* Config.swift in Sources */, A8AB048B28DC668A00530C86 /* UserManager.swift in Sources */, + A8796AFA29AF380C007033E5 /* AuthingWebsocketClient.swift in Sources */, A8AB049628DC672200530C86 /* config.swift in Sources */, A8AB049B28DC675900530C86 /* Util.swift in Sources */, A8AB048C28DC668A00530C86 /* CacheManager.swift in Sources */, diff --git a/Authing/Authing/Authing.swift b/Authing/Authing/Authing.swift index 049b3f7..9b0cd48 100644 --- a/Authing/Authing/Authing.swift +++ b/Authing/Authing/Authing.swift @@ -30,8 +30,10 @@ public class Authing: NSObject { case notify_lark_receive = "LarkReceiveNotificationName" } + private static var debugMode: Bool = false private static var sSchema = "https" private static var sHost = "authing.cn" + private static var sWebsocketHost = "wss://events.authing.com" private static var sAppId = "" private static var isOnPremises = false private static var sRSAPublicKey = DEFAULT_RSA_PUBLIC_KEY @@ -88,6 +90,15 @@ public class Authing: NSObject { } } + @objc public static func setWebsocketHost(websocketHost: String) { + sWebsocketHost = websocketHost + } + + @objc public static func getWebsocketHost() -> String { + return sWebsocketHost + } + + @objc public static func getConfig(completion: @escaping(Config?)->Void) { if let c = sConfig { c.getConfig(completion: completion) @@ -121,4 +132,13 @@ public class Authing: NSObject { // TODO save to user defaults then Core Data UserManager.saveUser(sCurrentUser) } + + @objc public static func setDebugMode(open: Bool) { + debugMode = open + } + + @objc public static func getDebugMode() -> Bool { + return debugMode + } + } diff --git a/Authing/Authing/Network/AuthClient.swift b/Authing/Authing/Network/AuthClient.swift index 7cd23dc..9fbb70f 100644 --- a/Authing/Authing/Network/AuthClient.swift +++ b/Authing/Authing/Network/AuthClient.swift @@ -703,7 +703,7 @@ public class AuthClient: Client { let urlString: String = "\(Authing.getSchema())://\(Util.getHost(config!))/api/v2/upload?folder=photos"; self._uploadImage(urlString, image, completion: completion) } else { - print("Cannot get config. app id:\(Authing.getAppId())") + ALog.d(AuthClient.self, "Cannot get config. app id:\(Authing.getAppId())") completion(ErrorCode.config.rawValue, ErrorCode.config.errorMessage()) } } @@ -715,7 +715,7 @@ public class AuthClient: Client { let urlString: String = "\(Authing.getSchema())://\(Util.getHost(config!))/api/v2/upload?folder=photos&private=\(isPrivate)"; self._uploadImage(urlString, image, true, completion: completion) } else { - print("Cannot get config. app id:\(Authing.getAppId())") + ALog.d(AuthClient.self, "Cannot get config. app id:\(Authing.getAppId())") completion(ErrorCode.config.rawValue, ErrorCode.config.errorMessage()) } } @@ -739,33 +739,33 @@ public class AuthClient: Client { session.uploadTask(with: urlRequest, from: data, completionHandler: { responseData, response, error in guard error == nil else { - print("network error \(url!)") + ALog.d(AuthClient.self, "network error \(url!)") completion(ErrorCode.netWork.rawValue, ErrorCode.netWork.errorMessage()) return } let jsonData = try? JSONSerialization.jsonObject(with: responseData!, options: .allowFragments) guard jsonData != nil else { - print("response not json \(url!)") + ALog.d(AuthClient.self, "response not json \(url!)") completion(ErrorCode.jsonParse.rawValue, ErrorCode.jsonParse.errorMessage()) return } guard let json = jsonData as? [String: Any] else { - print("illegal json \(url!)") + ALog.d(AuthClient.self, "illegal json \(url!)") completion(ErrorCode.jsonParse.rawValue, ErrorCode.jsonParse.errorMessage()) return } guard let code = json["code"] as? Int else { - print("no response code \(url!)") + ALog.d(AuthClient.self, "no response code \(url!)") completion(ErrorCode.jsonParse.rawValue, ErrorCode.jsonParse.errorMessage()) return } if isFaceImage == true{ guard let data = json["data"] as? NSDictionary else { - print("no response code \(url!)") + ALog.d(AuthClient.self, "no data \(url!)") completion(ErrorCode.jsonParse.rawValue, ErrorCode.jsonParse.errorMessage()) return } @@ -773,7 +773,7 @@ public class AuthClient: Client { if let u = data["key"] as? String { completion(200, u) } else { - print("response data has no url field \(url!)") + ALog.d(AuthClient.self, "response data has no key field \(url!)") completion(ErrorCode.jsonParse.rawValue, ErrorCode.jsonParse.errorMessage()) return } @@ -784,7 +784,7 @@ public class AuthClient: Client { } guard let data = json["data"] as? NSDictionary else { - print("no response data \(url!)") + ALog.d(AuthClient.self, "no response data \(url!)") completion(ErrorCode.jsonParse.rawValue, ErrorCode.jsonParse.errorMessage()) return } @@ -792,7 +792,7 @@ public class AuthClient: Client { if let u = data["url"] as? String { completion(200, u) } else { - print("response data has no url field \(url!)") + ALog.d(AuthClient.self, "response data has no url field \(url!)") completion(ErrorCode.jsonParse.rawValue, ErrorCode.jsonParse.errorMessage()) return } @@ -810,6 +810,35 @@ public class AuthClient: Client { get("/api/v3/system", completion: completion) } + //MARK: ---------- subEvent ---------- + public func subEvent(eventCode: String, completion: @escaping (String?) -> Void) { + if let currentUser = Authing.getCurrentUser(), + let token = currentUser.accessToken { + let eventUri = "\(Authing.getWebsocketHost())/events/v1/authentication/sub?code=\(eventCode)&token=\(token)" + if #available(iOS 13.0, *) { + AuthingWebsocketClient().initWebSocket(urlString: eventUri, completion: completion) + } + } + } + + //MARK: ---------- pubEvent ---------- + public func pubEvent(eventType: String, eventData: NSDictionary, completion: @escaping(Response) -> Void) { + + guard let data = try? JSONSerialization.data(withJSONObject: eventData, options: []) else { + ALog.d(AuthClient.self, "eventData is not json when requesting pubEvent") + completion(Response(ErrorCode.jsonParse.rawValue, nil, ErrorCode.jsonParse.errorMessage(), nil)) + return + } + + guard let str = String(data: data, encoding: .utf8) else { + ALog.d(AuthClient.self, "eventData is not json when requesting pubEvent") + completion(Response(ErrorCode.jsonParse.rawValue, nil, ErrorCode.jsonParse.errorMessage(), nil)) + return + } + + post("/api/v3/pub-userEvent", ["eventType": eventType, "eventData": str], completion: completion) + } + //MARK: ---------- Request ---------- public func get(_ endPoint: String, completion: @escaping (Response) -> Void) { request(endPoint: endPoint, method: "GET", body: nil, completion: completion) @@ -871,13 +900,13 @@ public class AuthClient: Client { URLSession.shared.dataTask(with: request) { (data, response, error) in guard error == nil else { - print("Guardian request network error:\(error!.localizedDescription)") + ALog.d(AuthClient.self, "Guardian request network error:\(error!.localizedDescription)") completion(Response((error as? NSError)?.code ?? 500, nil, error!.localizedDescription, nil)) return } guard data != nil else { - print("data is null when requesting \(urlString)") + ALog.d(AuthClient.self, "data is null when requesting \(urlString)") completion(Response(500, nil, "no data from server", nil)) return } @@ -896,13 +925,13 @@ public class AuthClient: Client { } guard let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary else { - print("data is not json when requesting \(urlString)") + ALog.d(AuthClient.self, "data is not json when requesting \(urlString)") completion(Response(500, nil, "only accept json data", nil)) return } guard statusCode == 200 || statusCode == 201 else { - print("Guardian request network error. Status code:\(statusCode.description). url:\(urlString)") + ALog.d(AuthClient.self, "Guardian request network error. Status code:\(statusCode.description). url:\(urlString)") let message: String? = json["message"] as? String completion(Response(statusCode, nil, message ?? "Network Error", json)) return @@ -918,7 +947,7 @@ public class AuthClient: Client { } } } catch { - print("parsing json error when requesting \(urlString)") + ALog.d(AuthClient.self, "parsing json error when requesting \(urlString)") completion(Response(500, nil, urlString, nil)) } }.resume() @@ -950,7 +979,8 @@ public class AuthClient: Client { URLSession.shared.dataTask(with: request) { (data, response, error) in guard error == nil else { - print("network error \(url!) \n\(error!)") + ALog.d(AuthClient.self, "network error \(url!) \n\(error!)") + completion(Response(ErrorCode.netWork.rawValue, nil, ErrorCode.netWork.errorMessage(), nil)) return } diff --git a/Authing/Authing/Network/AuthingWebsocketClient.swift b/Authing/Authing/Network/AuthingWebsocketClient.swift new file mode 100644 index 0000000..78b7cd4 --- /dev/null +++ b/Authing/Authing/Network/AuthingWebsocketClient.swift @@ -0,0 +1,85 @@ +// +// AuthingWebsocketClient.swift +// Guard +// +// Created by JnMars on 2023/2/27. +// + +import Foundation + +@available(iOS 13.0, *) + +public class AuthingWebsocketClient: NSObject { + private var webSocketTask: URLSessionWebSocketTask! + private var urlString: String = "" + private var retryCount: Int = 3 + private var retryTimes: Int = 0 + + public func setRetryCount(_ count: Int) { + retryCount = count + } + + public func initWebSocket(urlString: String, completion: @escaping (String?) -> Void) { + self.urlString = urlString + guard let url = URL(string: urlString) else { + ALog.e(AuthingWebsocketClient.self, "Error: can not create URL") + return + } + let urlSession = URLSession(configuration: .default, delegate: self, delegateQueue: .main) + let request = URLRequest(url: url) + webSocketTask = urlSession.webSocketTask(with: request) + webSocketTask.resume() + + webSocketTask.receive { result in + switch result { + case .success(let message): + switch message { + case .string(let text): + ALog.d(AuthingWebsocketClient.self, text) + completion(text) + case .data(let data): + ALog.d(AuthingWebsocketClient.self, "\(data)") + @unknown default: + fatalError() + } + case .failure(let error): + ALog.e(AuthingWebsocketClient.self, error) + completion(error.localizedDescription) + self.retryTimes += 1 + self.reconnect(url: self.urlString, retryTimes: self.retryTimes) + } + } + } + + public func reconnect(url: String, retryTimes: Int) { + if retryTimes == retryCount { + return + } + + DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2) { + self.initWebSocket(urlString: url) { message in + } + } + } +} + +@available(iOS 13.0, *) +extension AuthingWebsocketClient: URLSessionWebSocketDelegate { + public func urlSession(_ session: URLSession, + webSocketTask: URLSessionWebSocketTask, + didOpenWithProtocol protocol: String?) { + ALog.d(AuthingWebsocketClient.self, "URLSessionWebSocketTask is connected") + } + public func urlSession(_ session: URLSession, + webSocketTask: URLSessionWebSocketTask, + didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, + reason: Data?) { + let reasonString: String + if let reason = reason, let string = String(data: reason, encoding: .utf8) { + reasonString = string + } else { + reasonString = "" + } + ALog.e(AuthingWebsocketClient.self, "URLSessionWebSocketTask is closed: code=\(closeCode), reason=\(reasonString)") + } +} diff --git a/Authing/Authing/Util/ALog.swift b/Authing/Authing/Util/ALog.swift index 77bd10b..7298da6 100644 --- a/Authing/Authing/Util/ALog.swift +++ b/Authing/Authing/Util/ALog.swift @@ -7,19 +7,27 @@ open class ALog { public static func d(_ type: AnyClass, _ msg: Any...) { - print("📘 \(getTimestamp()):\(getTag(type)):\(msg)") + if Authing.getDebugMode() == true { + print("📘 \(getTimestamp()):\(getTag(type)):\(msg)") + } } public static func i(_ type: AnyClass, _ msg: Any...) { - print("📗 \(getTimestamp()):\(getTag(type)):\(msg)") + if Authing.getDebugMode() == true { + print("📗 \(getTimestamp()):\(getTag(type)):\(msg)") + } } public static func w(_ type: AnyClass, _ msg: Any...) { - print("⚠️ \(getTimestamp()):\(getTag(type)):\(msg)") + if Authing.getDebugMode() == true { + print("⚠️ \(getTimestamp()):\(getTag(type)):\(msg)") + } } public static func e(_ type: AnyClass, _ msg: Any...) { - print("❌ \(getTimestamp()):\(getTag(type)):\(msg)") + if Authing.getDebugMode() == true { + print("❌ \(getTimestamp()):\(getTag(type)):\(msg)") + } } private static func getTimestamp() -> String { diff --git a/Authing/Authing/Util/Util.swift b/Authing/Authing/Util/Util.swift index af0337f..40a50d5 100644 --- a/Authing/Authing/Util/Util.swift +++ b/Authing/Authing/Util/Util.swift @@ -81,7 +81,7 @@ public class Util { var result: AnyObject? let status = SecItemCopyMatching(query, &result) if (status != 0) { - print("Try get uuid from keychain operation finished with status: \(status)") + ALog.d(AuthClient.self, "Try get uuid from keychain operation finished with status: \(status)") } if (result == nil) { return nil