diff --git a/AutoCat.xcodeproj/project.pbxproj b/AutoCat.xcodeproj/project.pbxproj index cad3904..d7fa03b 100644 --- a/AutoCat.xcodeproj/project.pbxproj +++ b/AutoCat.xcodeproj/project.pbxproj @@ -33,6 +33,7 @@ 7A3F07AB24360DC800E59687 /* Dated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3F07AA24360DC800E59687 /* Dated.swift */; }; 7A3F07AD2436350B00E59687 /* SearchController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3F07AC2436350B00E59687 /* SearchController.swift */; }; 7A3F07AF24366DF900E59687 /* Filter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3F07AE24366DF900E59687 /* Filter.swift */; }; + 7A43F9F8246C8A6200BA5B49 /* JWT.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A43F9F7246C8A6200BA5B49 /* JWT.swift */; }; 7A530B78240010D900CBFE6E /* InputMask in Frameworks */ = {isa = PBXBuildFile; productRef = 7A530B77240010D900CBFE6E /* InputMask */; }; 7A530B7A24001D3300CBFE6E /* CheckController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7924001D3300CBFE6E /* CheckController.swift */; }; 7A530B7E24017FEE00CBFE6E /* VehicleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7D24017FEE00CBFE6E /* VehicleCell.swift */; }; @@ -48,7 +49,6 @@ 7A64AE812469E16100ABE48E /* ProgressAnimatedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A64AE7B2469E16100ABE48E /* ProgressAnimatedView.swift */; }; 7A64AE822469E16100ABE48E /* IHProgressHUD.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A64AE7C2469E16100ABE48E /* IHProgressHUD.swift */; }; 7A64AE832469E16100ABE48E /* IHProgressHUD.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 7A64AE7D2469E16100ABE48E /* IHProgressHUD.bundle */; }; - 7A64AE85246AD12E00ABE48E /* GoogleAuth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A64AE84246AD12E00ABE48E /* GoogleAuth.swift */; }; 7A6DD903242BF4A5009DE740 /* PlateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6DD902242BF4A5009DE740 /* PlateView.swift */; }; 7A6DD90824329144009DE740 /* CenterTextLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6DD90724329144009DE740 /* CenterTextLayer.swift */; }; 7A6DD90A24329541009DE740 /* RoadNumbers2.0.otf in Resources */ = {isa = PBXBuildFile; fileRef = 7A6DD90924329541009DE740 /* RoadNumbers2.0.otf */; }; @@ -91,6 +91,7 @@ 7A3F07AA24360DC800E59687 /* Dated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dated.swift; sourceTree = ""; }; 7A3F07AC2436350B00E59687 /* SearchController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchController.swift; sourceTree = ""; }; 7A3F07AE24366DF900E59687 /* Filter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Filter.swift; sourceTree = ""; }; + 7A43F9F7246C8A6200BA5B49 /* JWT.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JWT.swift; sourceTree = ""; }; 7A530B7924001D3300CBFE6E /* CheckController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckController.swift; sourceTree = ""; }; 7A530B7D24017FEE00CBFE6E /* VehicleCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleCell.swift; sourceTree = ""; }; 7A530B7F2401803A00CBFE6E /* Vehicle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Vehicle.swift; sourceTree = ""; }; @@ -105,7 +106,6 @@ 7A64AE7B2469E16100ABE48E /* ProgressAnimatedView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProgressAnimatedView.swift; sourceTree = ""; }; 7A64AE7C2469E16100ABE48E /* IHProgressHUD.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IHProgressHUD.swift; sourceTree = ""; }; 7A64AE7D2469E16100ABE48E /* IHProgressHUD.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = IHProgressHUD.bundle; sourceTree = ""; }; - 7A64AE84246AD12E00ABE48E /* GoogleAuth.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GoogleAuth.swift; sourceTree = ""; }; 7A6DD902242BF4A5009DE740 /* PlateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlateView.swift; sourceTree = ""; }; 7A6DD90724329144009DE740 /* CenterTextLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CenterTextLayer.swift; sourceTree = ""; }; 7A6DD90924329541009DE740 /* RoadNumbers2.0.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = RoadNumbers2.0.otf; sourceTree = ""; }; @@ -213,6 +213,7 @@ 7A64AE6E2469DFB600ABE48E /* ATGMediaBrowser */, 7A6DD90724329144009DE740 /* CenterTextLayer.swift */, 7A96AE32246C095700297C33 /* Base64FS.swift */, + 7A11474323FF06CA00B424AF /* Api.swift */, ); path = ThirdParty; sourceTree = ""; @@ -220,9 +221,8 @@ 7A11474223FF06B600B424AF /* Utils */ = { isa = PBXGroup; children = ( - 7A11474323FF06CA00B424AF /* Api.swift */, - 7A64AE84246AD12E00ABE48E /* GoogleAuth.swift */, 7A96AE30246B2FE400297C33 /* Constants.swift */, + 7A43F9F7246C8A6200BA5B49 /* JWT.swift */, ); path = Utils; sourceTree = ""; @@ -435,7 +435,6 @@ 7A64AE762469DFB600ABE48E /* ContentTransformers.swift in Sources */, 7A11471823FDEBFA00B424AF /* ReportController.swift in Sources */, 7A64AE7E2469E16100ABE48E /* RadialGradientLayer.swift in Sources */, - 7A64AE85246AD12E00ABE48E /* GoogleAuth.swift in Sources */, 7A64AE7F2469E16100ABE48E /* IndefiniteAnimatedView.swift in Sources */, 7A11471A23FE839000B424AF /* AuthController.swift in Sources */, 7A530B7A24001D3300CBFE6E /* CheckController.swift in Sources */, @@ -446,6 +445,7 @@ 7A11474723FF2AA500B424AF /* User.swift in Sources */, 7A11471623FDEB2A00B424AF /* MainSplitController.swift in Sources */, 7AF58D3124029E1000CE01A0 /* VehicleHeaderCell.swift in Sources */, + 7A43F9F8246C8A6200BA5B49 /* JWT.swift in Sources */, 7A6DD903242BF4A5009DE740 /* PlateView.swift in Sources */, 7A11470323FDE7E500B424AF /* SceneDelegate.swift in Sources */, 7A530B7E24017FEE00CBFE6E /* VehicleCell.swift in Sources */, diff --git a/AutoCat.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/AutoCat.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index d19adf4..7f46c2f 100644 --- a/AutoCat.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/AutoCat.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -33,8 +33,8 @@ "repositoryURL": "https://github.com/onevcat/Kingfisher", "state": { "branch": null, - "revision": "349ed06467a6f8a4939bcb83db301542bc84eac9", - "version": "5.13.4" + "revision": "910d808ade2a576e1a292ceb458a6fa43f67f594", + "version": "5.14.0" } }, { diff --git a/AutoCat.xcodeproj/xcuserdata/selim.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/AutoCat.xcodeproj/xcuserdata/selim.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index af111e5..07e3a91 100644 --- a/AutoCat.xcodeproj/xcuserdata/selim.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/AutoCat.xcodeproj/xcuserdata/selim.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -24,69 +24,5 @@ stopOnStyle = "0"> - - - - - - - - - - - - - - - - diff --git a/AutoCat/Controllers/GoogleSignInController.swift b/AutoCat/Controllers/GoogleSignInController.swift index 87fbf25..3607130 100644 --- a/AutoCat/Controllers/GoogleSignInController.swift +++ b/AutoCat/Controllers/GoogleSignInController.swift @@ -2,6 +2,15 @@ import UIKit import WebKit import CommonCrypto +private struct TokenResponse: Codable { + var id_token: String + var refresh_token: String + var access_token: String + var expires_in: Int + var token_type: String + var scope: String +} + class GoogleSignInController: UIViewController, WKNavigationDelegate { @IBOutlet weak var webView: WKWebView! @@ -19,9 +28,6 @@ class GoogleSignInController: UIViewController, WKNavigationDelegate { self.codeVerifier = UUID().uuidString let codeChallenge = self.sha256(string: self.codeVerifier) ?? "" - print("++++++++++++++++++") - print(codeVerifier) - print(codeChallenge) let authUrlString = Constants.googleAuthURL + "?response_type=code" @@ -43,8 +49,20 @@ class GoogleSignInController: UIViewController, WKNavigationDelegate { if let queryItems = components.queryItems { if let code = queryItems.first(where: { $0.name == "code" })?.value { decisionHandler(.cancel) - self.getToken(code: code) { error, idToken in - print("ID Token: \(idToken)") + self.getToken(code: code) { error, idToken, refreshToken in + if let err = error { + DispatchQueue.main.async { + self.dismiss(animated: true) { + IHProgressHUD.showError(withStatus: err.localizedDescription) + } + } + } else { + Settings.shared.user.googleIdToken = idToken + Settings.shared.user.googleRefreshToken = refreshToken + DispatchQueue.main.async { + self.dismiss(animated: true, completion: nil) + } + } } return } @@ -70,7 +88,7 @@ class GoogleSignInController: UIViewController, WKNavigationDelegate { return String(data: Data(Base64FS.encode(data: hash)), encoding: .utf8)?.trimmingCharacters(in: CharacterSet(charactersIn: "=")) } - func getToken(code: String, completion: @escaping (Error?, String?) -> Void) { + func getToken(code: String, completion: @escaping (Error?, String?, String?) -> Void) { let tokenUrlString = Constants.googleTokenURL + "?grant_type=authorization_code" + "&code=" + code @@ -81,18 +99,22 @@ class GoogleSignInController: UIViewController, WKNavigationDelegate { if let url = URL(string: tokenUrlString) { var request = URLRequest(url: url) request.httpMethod = "POST" - URLSession.shared.dataTask(with: request) { data, response, error in + let task = URLSession.shared.dataTask(with: request) { data, response, error in if let data = data { - if let str = String(data: data, encoding: .utf8) { - print(str) - } + if let resp = try? JSONDecoder().decode(TokenResponse.self, from: data) { + completion(nil, resp.id_token, resp.refresh_token) + } else { + let error = NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Response parsing error"]) + completion(error, nil, nil) + } } else { - completion(error, nil) + completion(error, nil, nil) } } + task.resume() } else { let error = NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Bad URL"]) - completion(error, nil) + completion(error, nil, nil) } } } diff --git a/AutoCat/Controllers/SettingsController.swift b/AutoCat/Controllers/SettingsController.swift index 9cfddaa..95d0689 100644 --- a/AutoCat/Controllers/SettingsController.swift +++ b/AutoCat/Controllers/SettingsController.swift @@ -12,8 +12,12 @@ class SettingsController: FormViewController { row.value = Settings.shared.user.login } <<< LabelRow("GoogleAccount") { row in - row.title = "Google Account" - row.value = "Log In" + row.title = "Google" + if let jwtString = Settings.shared.user.googleIdToken, let jwt = JWT(string: jwtString) { + row.value = jwt.payload.email + } else { + row.value = "Log In" + } row.cellUpdate { cell, _ in cell.accessoryType = .disclosureIndicator } @@ -37,7 +41,9 @@ class SettingsController: FormViewController { } func displayLogoutSheet() { - let sheet = UIAlertController(title: "Google Account", message: "You are currently signed in with email example@gmail.com. It allows us to find more data about vehicles.", preferredStyle: .actionSheet) + guard let jwtString = Settings.shared.user.googleIdToken, let jwt = JWT(string: jwtString) else { return } + + let sheet = UIAlertController(title: jwt.payload.name, message: "You are currently signed in with email \(jwt.payload.email). It allows us to find more data about vehicles.", preferredStyle: .actionSheet) let cancel = UIAlertAction(title: "Cancel", style: .cancel) { _ in sheet.dismiss(animated: true, completion: nil) } let logout = UIAlertAction(title: "Sign Out", style: .destructive) { _ in diff --git a/AutoCat/Models/User.swift b/AutoCat/Models/User.swift index ef6c6eb..368c304 100644 --- a/AutoCat/Models/User.swift +++ b/AutoCat/Models/User.swift @@ -4,10 +4,10 @@ struct User: Codable { let login: String var token: String var googleIdToken: String? + var googleRefreshToken: String? init() { self.login = "" self.token = "" - self.googleIdToken = "" } } diff --git a/AutoCat/Utils/Api.swift b/AutoCat/ThirdParty/Api.swift similarity index 100% rename from AutoCat/Utils/Api.swift rename to AutoCat/ThirdParty/Api.swift diff --git a/AutoCat/Utils/GoogleAuth.swift b/AutoCat/Utils/GoogleAuth.swift deleted file mode 100644 index fbf2875..0000000 --- a/AutoCat/Utils/GoogleAuth.swift +++ /dev/null @@ -1,2 +0,0 @@ -import Foundation - diff --git a/AutoCat/Utils/JWT.swift b/AutoCat/Utils/JWT.swift new file mode 100644 index 0000000..3c4f046 --- /dev/null +++ b/AutoCat/Utils/JWT.swift @@ -0,0 +1,38 @@ +import Foundation + +struct JwtPayload: Codable { + var email: String + var name: String + var exp: Int +} + +class JWT { + private var jwt: String + public let payload: JwtPayload + public var expired: Bool { + return TimeInterval(self.payload.exp) < Date().timeIntervalSince1970 + } + + init?(string: String) { + self.jwt = string + + let parts = string.split(separator: ".") + if parts.count == 3 { + var payloadStr = String(parts[1]) + if (payloadStr.count % 2 != 0) { + payloadStr += String(repeating: "=", count: (payloadStr.count % 2)) + } + if let json = Data(base64Encoded: payloadStr, options: [.ignoreUnknownCharacters]) { + if let resp = try? JSONDecoder().decode(JwtPayload.self, from: json) { + self.payload = resp + } else { + return nil + } + } else { + return nil + } + } else { + return nil + } + } +}