Firebase authorization
This commit is contained in:
parent
5fd6bf65f3
commit
523fb5d411
@ -24,5 +24,21 @@
|
|||||||
stopOnStyle = "0">
|
stopOnStyle = "0">
|
||||||
</BreakpointContent>
|
</BreakpointContent>
|
||||||
</BreakpointProxy>
|
</BreakpointProxy>
|
||||||
|
<BreakpointProxy
|
||||||
|
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||||
|
<BreakpointContent
|
||||||
|
uuid = "143FAB5A-C171-426A-A0BA-67C44E72B9D5"
|
||||||
|
shouldBeEnabled = "Yes"
|
||||||
|
ignoreCount = "0"
|
||||||
|
continueAfterRunningActions = "No"
|
||||||
|
filePath = "AutoCat/Controllers/GoogleSignInController.swift"
|
||||||
|
startingColumnNumber = "9223372036854775807"
|
||||||
|
endingColumnNumber = "9223372036854775807"
|
||||||
|
startingLineNumber = "61"
|
||||||
|
endingLineNumber = "61"
|
||||||
|
landmarkName = "webView(_:decidePolicyFor:decisionHandler:)"
|
||||||
|
landmarkType = "7">
|
||||||
|
</BreakpointContent>
|
||||||
|
</BreakpointProxy>
|
||||||
</Breakpoints>
|
</Breakpoints>
|
||||||
</Bucket>
|
</Bucket>
|
||||||
|
|||||||
@ -18,10 +18,22 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
|
|
||||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||||
|
|
||||||
let config = Realm.Configuration(
|
let config = Realm.Configuration(
|
||||||
schemaVersion: 3,
|
schemaVersion: 5,
|
||||||
migrationBlock: { migration, oldSchemaVersion in
|
migrationBlock: { migration, oldSchemaVersion in
|
||||||
})
|
if oldSchemaVersion <= 3 {
|
||||||
|
var numbers: [String] = []
|
||||||
|
migration.enumerateObjects(ofType: "Vehicle") { old, new in
|
||||||
|
if let number = old?["number"] as? String {
|
||||||
|
if numbers.contains(number) {
|
||||||
|
migration.delete(old!)
|
||||||
|
} else {
|
||||||
|
numbers.append(number)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
Realm.Configuration.defaultConfiguration = config
|
Realm.Configuration.defaultConfiguration = config
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import SwiftDate
|
|||||||
import RxRealm
|
import RxRealm
|
||||||
import RxDataSources
|
import RxDataSources
|
||||||
|
|
||||||
class CheckController: UIViewController, MaskedTextFieldDelegateListener {
|
class CheckController: UIViewController, MaskedTextFieldDelegateListener, UITableViewDelegate {
|
||||||
|
|
||||||
@IBOutlet weak var number: UITextField!
|
@IBOutlet weak var number: UITextField!
|
||||||
@IBOutlet weak var check: UIButton!
|
@IBOutlet weak var check: UIButton!
|
||||||
@ -32,7 +32,7 @@ class CheckController: UIViewController, MaskedTextFieldDelegateListener {
|
|||||||
} else {
|
} else {
|
||||||
return UITableViewCell()
|
return UITableViewCell()
|
||||||
}
|
}
|
||||||
})
|
}, canEditRowAtIndexPath: { _, _ in true })
|
||||||
|
|
||||||
ds.titleForHeaderInSection = { dataSourse, index in
|
ds.titleForHeaderInSection = { dataSourse, index in
|
||||||
return dataSourse.sectionModels[index].header
|
return dataSourse.sectionModels[index].header
|
||||||
@ -42,11 +42,14 @@ class CheckController: UIViewController, MaskedTextFieldDelegateListener {
|
|||||||
.subscribe(onNext: self.updateDetailController(with:))
|
.subscribe(onNext: self.updateDetailController(with:))
|
||||||
.disposed(by: self.bag)
|
.disposed(by: self.bag)
|
||||||
|
|
||||||
|
|
||||||
Observable.collection(from: realm.objects(Vehicle.self)
|
Observable.collection(from: realm.objects(Vehicle.self)
|
||||||
.sorted(byKeyPath: "addedDate", ascending: false))
|
.sorted(byKeyPath: "addedDate", ascending: false))
|
||||||
.map { $0.groupedByDate() }
|
.map { $0.groupedByDate() }
|
||||||
.bind(to: self.history.rx.items(dataSource: ds))
|
.bind(to: self.history.rx.items(dataSource: ds))
|
||||||
.disposed(by: self.bag)
|
.disposed(by: self.bag)
|
||||||
|
|
||||||
|
self.history.rx.setDelegate(self).disposed(by: self.bag)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewWillAppear(_ animated: Bool) {
|
override func viewWillAppear(_ animated: Bool) {
|
||||||
@ -111,7 +114,7 @@ class CheckController: UIViewController, MaskedTextFieldDelegateListener {
|
|||||||
func onReceivedVehicle(_ vehicle: Vehicle) {
|
func onReceivedVehicle(_ vehicle: Vehicle) {
|
||||||
if let realm = try? Realm() {
|
if let realm = try? Realm() {
|
||||||
try? realm.write {
|
try? realm.write {
|
||||||
realm.add(vehicle)
|
realm.add(vehicle, update: .modified)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,5 +141,21 @@ class CheckController: UIViewController, MaskedTextFieldDelegateListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
|
||||||
|
guard let vehicle: Vehicle = try? self.history.rx.model(at: indexPath) else { return nil }
|
||||||
|
|
||||||
|
let updateAction = UIContextualAction(style: .normal, title: "Update") { action, view, completion in
|
||||||
|
IHProgressHUD.show()
|
||||||
|
Api.checkVehicle(by: vehicle.number, force: true)
|
||||||
|
.observeOn(MainScheduler.instance)
|
||||||
|
.subscribe(onNext: self.onReceivedVehicle(_:), onError: { err in
|
||||||
|
IHProgressHUD.showError(withStatus: err.localizedDescription)
|
||||||
|
print(err.localizedDescription)
|
||||||
|
}).disposed(by: self.bag)
|
||||||
|
completion(true)
|
||||||
|
}
|
||||||
|
updateAction.image = UIImage(systemName: "arrow.2.circlepath")
|
||||||
|
updateAction.backgroundColor = .systemBlue
|
||||||
|
return UISwipeActionsConfiguration(actions: [updateAction])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
import UIKit
|
import UIKit
|
||||||
import WebKit
|
import WebKit
|
||||||
import CommonCrypto
|
import CommonCrypto
|
||||||
|
import RxSwift
|
||||||
|
|
||||||
private struct TokenResponse: Codable {
|
struct TokenResponse: Codable {
|
||||||
var id_token: String
|
var id_token: String
|
||||||
var refresh_token: String
|
var refresh_token: String?
|
||||||
var access_token: String
|
var access_token: String
|
||||||
var expires_in: Int
|
var expires_in: Int
|
||||||
var token_type: String
|
var token_type: String
|
||||||
@ -14,6 +15,7 @@ private struct TokenResponse: Codable {
|
|||||||
class GoogleSignInController: UIViewController, WKNavigationDelegate {
|
class GoogleSignInController: UIViewController, WKNavigationDelegate {
|
||||||
@IBOutlet weak var webView: WKWebView!
|
@IBOutlet weak var webView: WKWebView!
|
||||||
|
|
||||||
|
private var bag = DisposeBag()
|
||||||
private var codeVerifier: String = ""
|
private var codeVerifier: String = ""
|
||||||
public var completion: (() -> Void)?
|
public var completion: (() -> Void)?
|
||||||
|
|
||||||
@ -35,7 +37,7 @@ class GoogleSignInController: UIViewController, WKNavigationDelegate {
|
|||||||
+ "&code_challenge_method=S256"
|
+ "&code_challenge_method=S256"
|
||||||
+ "&scope=email%20profile"
|
+ "&scope=email%20profile"
|
||||||
+ "&redirect_uri=" + Constants.googleRedirectURL
|
+ "&redirect_uri=" + Constants.googleRedirectURL
|
||||||
+ "&client_id=" + Constants.googleClientId
|
+ "&client_id=" + Constants.fbClientId
|
||||||
+ "&code_challenge=" + codeChallenge
|
+ "&code_challenge=" + codeChallenge
|
||||||
|
|
||||||
if let url = URL(string: authUrlString) {
|
if let url = URL(string: authUrlString) {
|
||||||
@ -50,23 +52,15 @@ class GoogleSignInController: UIViewController, WKNavigationDelegate {
|
|||||||
if let queryItems = components.queryItems {
|
if let queryItems = components.queryItems {
|
||||||
if let code = queryItems.first(where: { $0.name == "code" })?.value {
|
if let code = queryItems.first(where: { $0.name == "code" })?.value {
|
||||||
decisionHandler(.cancel)
|
decisionHandler(.cancel)
|
||||||
self.getToken(code: code) { error, idToken, refreshToken in
|
self.getToken(code: code)
|
||||||
if let err = error {
|
.flatMap(fbVerifyAssertion)
|
||||||
DispatchQueue.main.async {
|
.observeOn(MainScheduler.instance)
|
||||||
self.dismiss(animated: true) {
|
.subscribe(onNext: { _ in
|
||||||
IHProgressHUD.showError(withStatus: err.localizedDescription)
|
self.dismiss(animated: true, completion: self.completion)
|
||||||
}
|
}, onError: { error in
|
||||||
}
|
IHProgressHUD.showError(withStatus: error.localizedDescription)
|
||||||
} else {
|
})
|
||||||
Settings.shared.user.googleIdToken = idToken
|
.disposed(by: self.bag)
|
||||||
Settings.shared.user.googleRefreshToken = refreshToken
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
self.dismiss(animated: true) {
|
|
||||||
self.completion?()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,33 +85,65 @@ class GoogleSignInController: UIViewController, WKNavigationDelegate {
|
|||||||
return String(data: Data(Base64FS.encode(data: hash)), encoding: .utf8)?.trimmingCharacters(in: CharacterSet(charactersIn: "="))
|
return String(data: Data(Base64FS.encode(data: hash)), encoding: .utf8)?.trimmingCharacters(in: CharacterSet(charactersIn: "="))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getToken(code: String, completion: @escaping (Error?, String?, String?) -> Void) {
|
func getToken(code: String) -> Observable<TokenResponse> {
|
||||||
let tokenUrlString = Constants.googleTokenURL
|
let tokenUrlString = Constants.googleTokenURL
|
||||||
+ "?grant_type=authorization_code"
|
+ "?grant_type=authorization_code"
|
||||||
+ "&code=" + code
|
+ "&code=" + code
|
||||||
+ "&redirect_uri=" + Constants.googleRedirectURL
|
+ "&redirect_uri=" + Constants.googleRedirectURL
|
||||||
+ "&client_id=" + Constants.googleClientId
|
+ "&client_id=" + Constants.fbClientId
|
||||||
+ "&code_verifier=" + self.codeVerifier
|
+ "&code_verifier=" + self.codeVerifier
|
||||||
|
|
||||||
if let url = URL(string: tokenUrlString) {
|
if let url = URL(string: tokenUrlString) {
|
||||||
var request = URLRequest(url: url)
|
var request = URLRequest(url: url)
|
||||||
request.httpMethod = "POST"
|
request.httpMethod = "POST"
|
||||||
let task = URLSession.shared.dataTask(with: request) { data, response, error in
|
return URLSession.shared.rx.data(request: request).map { data in
|
||||||
if let data = data {
|
return try JSONDecoder().decode(TokenResponse.self, from: data)
|
||||||
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, nil)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
task.resume()
|
|
||||||
} else {
|
} else {
|
||||||
let error = NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Bad URL"])
|
let error = NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Bad URL"])
|
||||||
completion(error, nil, nil)
|
return Observable.error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func fbVerifyAssertion(tokenResp: TokenResponse) -> Observable<Void> {
|
||||||
|
let signupUrl = Constants.fbVerifyAssertion + "?key=" + (Constants.fbApiKey.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? Constants.fbApiKey)
|
||||||
|
if let url = URL(string: signupUrl) {
|
||||||
|
let innerBody = "providerId=google.com"
|
||||||
|
+ "&id_token=" + tokenResp.id_token
|
||||||
|
+ "&access_token=" + tokenResp.access_token
|
||||||
|
|
||||||
|
let body: [String:Any] = [
|
||||||
|
"returnIdpCredential": true,
|
||||||
|
"returnSecureToken": true,
|
||||||
|
"autoCreate": true,
|
||||||
|
"requestUri": "http://localhost",
|
||||||
|
"postBody": innerBody
|
||||||
|
]
|
||||||
|
|
||||||
|
var request = URLRequest(url: url)
|
||||||
|
request.httpMethod = "POST"
|
||||||
|
request.httpBody = try? JSONSerialization.data(withJSONObject: body, options: .prettyPrinted)
|
||||||
|
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||||
|
request.addValue(Constants.fbClientVersion, forHTTPHeaderField: "X-Client-Version")
|
||||||
|
request.addValue(Constants.vin01BUndleId, forHTTPHeaderField: "X-Ios-Bundle-Identifier")
|
||||||
|
request.addValue(Constants.fbUserAgent, forHTTPHeaderField: "User-Agent")
|
||||||
|
|
||||||
|
return URLSession.shared.rx.json(request: request).map { response in
|
||||||
|
guard let json = response as? [String: Any] else { return }
|
||||||
|
if let newToken = json["idToken"] as? String {
|
||||||
|
Settings.shared.user.googleIdToken = newToken
|
||||||
|
print("Token: \(newToken)")
|
||||||
|
}
|
||||||
|
if let newRefreshToken = json["refreshToken"] as? String {
|
||||||
|
Settings.shared.user.googleRefreshToken = newRefreshToken
|
||||||
|
print("Refresh token: \(newRefreshToken)")
|
||||||
|
}
|
||||||
|
}.catchError { err in
|
||||||
|
print(err)
|
||||||
|
return .just(())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return .just(())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,6 +22,8 @@
|
|||||||
<true/>
|
<true/>
|
||||||
<key>NSAppTransportSecurity</key>
|
<key>NSAppTransportSecurity</key>
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>NSAllowsArbitraryLoads</key>
|
||||||
|
<true/>
|
||||||
<key>NSExceptionDomains</key>
|
<key>NSExceptionDomains</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>avto-nomer.ru</key>
|
<key>avto-nomer.ru</key>
|
||||||
|
|||||||
@ -41,7 +41,6 @@ class VehiclePhoto: Object, Decodable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Vehicle: Object, Decodable, IdentifiableType {
|
class Vehicle: Object, Decodable, IdentifiableType {
|
||||||
@objc dynamic var _id: String = ""
|
|
||||||
@objc dynamic var brand: VehicleBrand?
|
@objc dynamic var brand: VehicleBrand?
|
||||||
@objc dynamic var model: VehicleModel?
|
@objc dynamic var model: VehicleModel?
|
||||||
@objc dynamic var color: String?
|
@objc dynamic var color: String?
|
||||||
@ -59,10 +58,9 @@ class Vehicle: Object, Decodable, IdentifiableType {
|
|||||||
@objc dynamic var addedBy: String = ""
|
@objc dynamic var addedBy: String = ""
|
||||||
let photos = List<VehiclePhoto>()
|
let photos = List<VehiclePhoto>()
|
||||||
|
|
||||||
var identity: String { _id }
|
var identity: String { number }
|
||||||
|
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case _id
|
|
||||||
case brand
|
case brand
|
||||||
case model
|
case model
|
||||||
case color
|
case color
|
||||||
@ -83,7 +81,6 @@ class Vehicle: Object, Decodable, IdentifiableType {
|
|||||||
|
|
||||||
required init(from decoder: Decoder) throws {
|
required init(from decoder: Decoder) throws {
|
||||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
self._id = try container.decode(String.self, forKey: ._id)
|
|
||||||
self.brand = try container.decodeIfPresent(VehicleBrand.self, forKey: .brand)
|
self.brand = try container.decodeIfPresent(VehicleBrand.self, forKey: .brand)
|
||||||
self.model = try container.decodeIfPresent(VehicleModel.self, forKey: .model)
|
self.model = try container.decodeIfPresent(VehicleModel.self, forKey: .model)
|
||||||
self.color = try container.decodeIfPresent(String.self, forKey: .color)
|
self.color = try container.decodeIfPresent(String.self, forKey: .color)
|
||||||
@ -111,7 +108,10 @@ class Vehicle: Object, Decodable, IdentifiableType {
|
|||||||
|
|
||||||
init(_ number: String) {
|
init(_ number: String) {
|
||||||
self.number = number
|
self.number = number
|
||||||
self._id = UUID().uuidString
|
|
||||||
self.addedDate = Date().timeIntervalSince1970*1000
|
self.addedDate = Date().timeIntervalSince1970*1000
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override static func primaryKey() -> String? {
|
||||||
|
return "number"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
63
AutoCat/ThirdParty/Api.swift
vendored
63
AutoCat/ThirdParty/Api.swift
vendored
@ -2,7 +2,7 @@ import Foundation
|
|||||||
import RxSwift
|
import RxSwift
|
||||||
|
|
||||||
class Api {
|
class Api {
|
||||||
private static let baseUrl = "https://vps.aliencat.pro:8443/"
|
private static let baseUrl = "http://127.0.0.1:3000/" //"https://vps.aliencat.pro:8443/"
|
||||||
|
|
||||||
private static func genError(_ msg: String, suggestion: String, code: Int = 0) -> Error {
|
private static func genError(_ msg: String, suggestion: String, code: Int = 0) -> Error {
|
||||||
return NSError(domain: "", code: code, userInfo: [NSLocalizedDescriptionKey: msg, NSLocalizedRecoverySuggestionErrorKey: suggestion])
|
return NSError(domain: "", code: code, userInfo: [NSLocalizedDescriptionKey: msg, NSLocalizedRecoverySuggestionErrorKey: suggestion])
|
||||||
@ -36,7 +36,7 @@ class Api {
|
|||||||
return URLSession.shared.rx.data(request: request).map { data in
|
return URLSession.shared.rx.data(request: request).map { data in
|
||||||
// let str = String(data: data, encoding: .utf8)
|
// let str = String(data: data, encoding: .utf8)
|
||||||
// print("================================")
|
// print("================================")
|
||||||
// print(str)
|
// print(str?.replacingOccurrences(of: "\\\"", with: "\""))
|
||||||
// print("================================")
|
// print("================================")
|
||||||
let resp = try JSONDecoder().decode(Response<T>.self, from: data)
|
let resp = try JSONDecoder().decode(Response<T>.self, from: data)
|
||||||
if resp.success {
|
if resp.success {
|
||||||
@ -47,6 +47,44 @@ class Api {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static func refreshFbToken() -> Observable<Void> {
|
||||||
|
guard let token = Settings.shared.user.googleIdToken, let refreshToken = Settings.shared.user.googleRefreshToken, let jwt = JWT(string: token), jwt.expired else {
|
||||||
|
return .just(())
|
||||||
|
}
|
||||||
|
|
||||||
|
let refreshUrlString = Constants.fbRefreshToken + "?key=" + Constants.fbApiKey
|
||||||
|
|
||||||
|
let body = [
|
||||||
|
"grantType": "refresh_token",
|
||||||
|
"refreshToken": refreshToken
|
||||||
|
]
|
||||||
|
|
||||||
|
if let url = URL(string: refreshUrlString) {
|
||||||
|
var request = URLRequest(url: url)
|
||||||
|
request.httpMethod = "POST"
|
||||||
|
request.httpBody = try? JSONSerialization.data(withJSONObject: body, options: .prettyPrinted)
|
||||||
|
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||||
|
request.addValue(Constants.fbClientVersion, forHTTPHeaderField: "X-Client-Version")
|
||||||
|
request.addValue(Constants.vin01BUndleId, forHTTPHeaderField: "X-Ios-Bundle-Identifier")
|
||||||
|
request.addValue(Constants.fbUserAgent, forHTTPHeaderField: "User-Agent")
|
||||||
|
return URLSession.shared.rx.json(request: request).map { resp in
|
||||||
|
guard let json = resp as? [String: Any] else { return }
|
||||||
|
if let newToken = json["id_token"] as? String {
|
||||||
|
Settings.shared.user.googleIdToken = newToken
|
||||||
|
print("Token was successfully refresh to: \(newToken)")
|
||||||
|
}
|
||||||
|
if let newRefreshToken = json["refresh_token"] as? String {
|
||||||
|
Settings.shared.user.googleRefreshToken = newRefreshToken
|
||||||
|
}
|
||||||
|
}.catchError { error in
|
||||||
|
print(error)
|
||||||
|
return .just(())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return .just(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static func login(username: String, password: String) -> Observable<User> {
|
public static func login(username: String, password: String) -> Observable<User> {
|
||||||
let body = [
|
let body = [
|
||||||
"login": username,
|
"login": username,
|
||||||
@ -71,14 +109,19 @@ class Api {
|
|||||||
return self.makeRequest(api: "vehicles", method: "GET", body: body)
|
return self.makeRequest(api: "vehicles", method: "GET", body: body)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func checkVehicle(by number: String) -> Observable<Vehicle> {
|
public static func checkVehicle(by number: String, force: Bool = false) -> Observable<Vehicle> {
|
||||||
if let token = Settings.shared.user.googleIdToken, let jwt = JWT(string: token) {
|
return self.refreshFbToken().flatMap { () -> Observable<Vehicle> in
|
||||||
|
var body = [
|
||||||
}
|
"number": number,
|
||||||
|
"forceUpdate": String(force)
|
||||||
return self.makeRequest(api: "vehicles/check", method: "POST", body: ["number": number]).map { (vehicle: Vehicle) -> Vehicle in
|
]
|
||||||
vehicle.addedDate = Date().timeIntervalSince1970*1000
|
if let token = Settings.shared.user.googleIdToken {
|
||||||
return vehicle
|
body["googleIdToken"] = token
|
||||||
|
}
|
||||||
|
return self.makeRequest(api: "vehicles/check", method: "POST", body: body).map { (vehicle: Vehicle) -> Vehicle in
|
||||||
|
vehicle.addedDate = Date().timeIntervalSince1970*1000
|
||||||
|
return vehicle
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,13 @@ enum Constants {
|
|||||||
static let googleTokenURL = "https://oauth2.googleapis.com/token"
|
static let googleTokenURL = "https://oauth2.googleapis.com/token"
|
||||||
static let googleRedirectURL = "com.googleusercontent.apps.994679674451-k7clunkk4nicl6iuajdtc5u7hvustbdb:/oauth2callback"
|
static let googleRedirectURL = "com.googleusercontent.apps.994679674451-k7clunkk4nicl6iuajdtc5u7hvustbdb:/oauth2callback"
|
||||||
|
|
||||||
static let googleClientId = "994679674451-k7clunkk4nicl6iuajdtc5u7hvustbdb.apps.googleusercontent.com"
|
static let fbClientId = "994679674451-k7clunkk4nicl6iuajdtc5u7hvustbdb.apps.googleusercontent.com"
|
||||||
static let googleApiKey = "AIzaSyDVlrQj_05y6AeZNf8enpSWFIiHhgwfnGI"
|
static let fbApiKey = "AIzaSyDVlrQj_05y6AeZNf8enpSWFIiHhgwfnGI"
|
||||||
|
|
||||||
|
static let fbClientVersion = "iOS/FirebaseSDK/6.5.1/FirebaseCore-iOS"
|
||||||
|
static let fbVerifyAssertion = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyAssertion"
|
||||||
|
static let fbRefreshToken = "https://securetoken.googleapis.com/v1/token"
|
||||||
|
static let fbUserAgent = "FirebaseAuth.iOS/6.5.1 ru.Vin01/1.0 iPhone/13.5 hw/sim"
|
||||||
|
|
||||||
|
static let vin01BUndleId = "ru.Vin01"
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user