Login with email instead of username. Adding some code for Apple sign in

This commit is contained in:
Selim Mustafaev 2020-09-08 16:31:27 +03:00
parent de6c6a7ac5
commit f7bcaa96a2
10 changed files with 204 additions and 109 deletions

View File

@ -75,6 +75,7 @@
7A7547DD2403180A004E8406 /* SectionHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A7547DB2403180A004E8406 /* SectionHeader.swift */; };
7A7547DE2403180A004E8406 /* SectionHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7A7547DC2403180A004E8406 /* SectionHeader.xib */; };
7A7547E024032CB6004E8406 /* VehiclePhotoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A7547DF24032CB6004E8406 /* VehiclePhotoCell.swift */; };
7A813DBE2506A57100CC93B9 /* AuthenticationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A813DBD2506A57100CC93B9 /* AuthenticationServices.framework */; };
7A8A2209248D10EC0073DFD9 /* ResizeImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8A2208248D10EC0073DFD9 /* ResizeImage.swift */; };
7A8A220B248D67B60073DFD9 /* VehicleReportImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8A220A248D67B60073DFD9 /* VehicleReportImage.swift */; };
7A96AE2A246AFD6200297C33 /* Eureka in Frameworks */ = {isa = PBXBuildFile; productRef = 7A96AE29246AFD6200297C33 /* Eureka */; };
@ -157,6 +158,7 @@
7A7547DB2403180A004E8406 /* SectionHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionHeader.swift; sourceTree = "<group>"; };
7A7547DC2403180A004E8406 /* SectionHeader.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SectionHeader.xib; sourceTree = "<group>"; };
7A7547DF24032CB6004E8406 /* VehiclePhotoCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehiclePhotoCell.swift; sourceTree = "<group>"; };
7A813DBD2506A57100CC93B9 /* AuthenticationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AuthenticationServices.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/AuthenticationServices.framework; sourceTree = DEVELOPER_DIR; };
7A8A2208248D10EC0073DFD9 /* ResizeImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResizeImage.swift; sourceTree = "<group>"; };
7A8A220A248D67B60073DFD9 /* VehicleReportImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleReportImage.swift; sourceTree = "<group>"; };
7A92D0AB240425B100EF3B77 /* ATGMediaBrowser.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ATGMediaBrowser.framework; path = Carthage/Build/iOS/ATGMediaBrowser.framework; sourceTree = "<group>"; };
@ -180,6 +182,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
7A813DBE2506A57100CC93B9 /* AuthenticationServices.framework in Frameworks */,
7AF58D342402A91C00CE01A0 /* Kingfisher in Frameworks */,
7A0516162414EC1200FC55AC /* Differentiator in Frameworks */,
7A96AE2F246B2BCD00297C33 /* WebKit.framework in Frameworks */,
@ -305,6 +308,7 @@
7A11474C23FFEE8700B424AF /* Frameworks */ = {
isa = PBXGroup;
children = (
7A813DBD2506A57100CC93B9 /* AuthenticationServices.framework */,
7A96AE2E246B2BCD00297C33 /* WebKit.framework */,
7A92D0AB240425B100EF3B77 /* ATGMediaBrowser.framework */,
7A11474D23FFEE8800B424AF /* SVProgressHUD.framework */,
@ -707,7 +711,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 25;
CURRENT_PROJECT_VERSION = 26;
DEVELOPMENT_TEAM = 46DTTB8X4S;
INFOPLIST_FILE = AutoCat/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
@ -729,7 +733,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 25;
CURRENT_PROJECT_VERSION = 26;
DEVELOPMENT_TEAM = 46DTTB8X4S;
INFOPLIST_FILE = AutoCat/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;

View File

@ -2,6 +2,10 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.applesignin</key>
<array>
<string>Default</string>
</array>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.device.audio-input</key>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16097.2" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="pme-aR-UNJ">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16097.3" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="pme-aR-UNJ">
<device id="retina4_7" orientation="portrait" appearance="dark"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
@ -261,14 +261,14 @@
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="VehicleCell" id="VEP-QD-i6y" customClass="VehicleCell" customModule="AutoCat" customModuleProvider="target">
<rect key="frame" x="0.0" y="28" width="375" height="85"/>
<rect key="frame" x="0.0" y="28" width="375" height="85.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="VEP-QD-i6y" id="8hH-8I-XLB">
<rect key="frame" x="0.0" y="0.0" width="375" height="85"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="85.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Kia (JF) Optima" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="AQY-7N-q8D">
<rect key="frame" x="8" y="8" width="124" height="21"/>
<rect key="frame" x="8" y="8" width="124" height="21.5"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
@ -280,7 +280,7 @@
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cvf-vM-QnT" customClass="PlateView" customModule="AutoCat" customModuleProvider="target">
<rect key="frame" x="8" y="37" width="317" height="40"/>
<rect key="frame" x="8" y="37.5" width="317" height="40"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="Xoz-Iw-PCU"/>
@ -716,13 +716,13 @@
<stackView opaque="NO" contentMode="scaleToFill" horizontalCompressionResistancePriority="1000" axis="vertical" spacing="16" translatesAutoresizingMaskIntoConstraints="NO" id="TMc-av-b0b">
<rect key="frame" x="56.5" y="235.5" width="262.5" height="196"/>
<subviews>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Login" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Uey-88-eZL" customClass="CustomTextField" customModule="AutoCat" customModuleProvider="target">
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Email" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Uey-88-eZL" customClass="CustomTextField" customModule="AutoCat" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="262.5" height="34"/>
<constraints>
<constraint firstAttribute="height" constant="34" id="5fP-sM-e5U"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits"/>
<textInputTraits key="textInputTraits" keyboardType="emailAddress" textContentType="email"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="borderWidth">
<real key="value" value="1"/>
@ -775,6 +775,19 @@
<action selector="signupTapped:" destination="pme-aR-UNJ" eventType="touchUpInside" id="upt-yE-Xro"/>
</connections>
</button>
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="or" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="SXb-1Q-TxY">
<rect key="frame" x="0.0" y="196" width="262.5" height="0.0"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="nId-Ov-fVe" customClass="ASAuthorizationAppleIDButton">
<rect key="frame" x="0.0" y="196" width="262.5" height="0.0"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<connections>
<action selector="appleSignInTapped:" destination="pme-aR-UNJ" eventType="touchUpInside" id="LrP-Rx-JeO"/>
</connections>
</view>
</subviews>
</stackView>
</subviews>
@ -787,6 +800,7 @@
<viewLayoutGuide key="safeArea" id="CSC-sQ-Tm5"/>
</view>
<connections>
<outlet property="appleSignIn" destination="nId-Ov-fVe" id="ifS-g1-O3I"/>
<outlet property="login" destination="ltG-B1-UBj" id="Fc0-Cd-BKA"/>
<outlet property="password" destination="G1p-Hz-8yn" id="8VI-cA-YrJ"/>
<outlet property="signup" destination="hRD-Ha-MrP" id="VCG-25-bHL"/>

View File

@ -2,19 +2,23 @@ import UIKit
import RxSwift
import RxCocoa
import RealmSwift
import AuthenticationServices
class AuthController: UIViewController {
class AuthController: UIViewController, ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding {
@IBOutlet weak var username: UITextField!
@IBOutlet weak var password: UITextField!
@IBOutlet weak var login: UIButton!
@IBOutlet weak var signup: UIButton!
@IBOutlet weak var appleSignIn: ASAuthorizationAppleIDButton!
let bag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
self.appleSignIn.cornerRadius = 6
let authValid = Observable.combineLatest(self.username.rx.text, self.password.rx.text) { name, pass -> Bool in
guard let name = name, let pass = pass else { return false }
return name.count >= 4 && pass.count >= 5
@ -23,44 +27,55 @@ class AuthController: UIViewController {
authValid.bind(to: self.login.rx.isEnabled).disposed(by: self.bag)
authValid.bind(to: self.signup.rx.isEnabled).disposed(by: self.bag)
if Settings.shared.user.login.count > 0 {
self.username.text = Settings.shared.user.login
if Settings.shared.user.email.count > 0 {
self.username.text = Settings.shared.user.email
}
}
@IBAction func loginTapped(_ sender: UIButton) {
guard let name = self.username.text, let pass = self.password.text else { return }
guard let email = self.username.text, let pass = self.password.text else { return }
IHProgressHUD.show()
Api.login(username: name, password: pass)
Api.login(email: email, password: pass)
.observeOn(MainScheduler.instance)
.subscribe(onSuccess: self.goToMainScreen(user:), onError: self.displayError(error:))
.disposed(by: self.bag)
}
@IBAction func signupTapped(_ sender: UIButton) {
guard let name = self.username.text, let pass = self.password.text else { return }
guard let email = self.username.text, let pass = self.password.text else { return }
IHProgressHUD.show()
Api.signup(username: name, password: pass)
Api.signUp(email: email, password: pass)
.observeOn(MainScheduler.instance)
.subscribe(onSuccess: self.goToMainScreen(user:), onError: self.displayError(error:))
.disposed(by: self.bag)
}
@IBAction func appleSignInTapped(_ sender: ASAuthorizationAppleIDButton) {
let appleIDProvider = ASAuthorizationAppleIDProvider()
let request = appleIDProvider.createRequest()
request.requestedScopes = [.email]
let authorizationController = ASAuthorizationController(authorizationRequests: [request])
authorizationController.delegate = self
authorizationController.presentationContextProvider = self
authorizationController.performRequests()
}
func goToMainScreen(user: User) {
guard let realm = try? Realm() else {
IHProgressHUD.showError(withStatus: "Database error")
return
}
// guard let realm = try? Realm() else {
// IHProgressHUD.showError(withStatus: "Database error")
// return
// }
IHProgressHUD.dismiss()
if user.login != Settings.shared.user.login {
try? realm.write {
realm.deleteAll()
}
}
// if user.email != Settings.shared.user.email {
// try? realm.write {
// realm.deleteAll()
// }
// }
Settings.shared.user = user
let storyboard = UIStoryboard(name: "Main", bundle: nil)
@ -71,4 +86,38 @@ class AuthController: UIViewController {
IHProgressHUD.showError(withStatus: error.localizedDescription)
print(error)
}
// MARK: - Apple SignIn
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
return self.view.window!
}
func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
switch authorization.credential {
case let appleIDCredential as ASAuthorizationAppleIDCredential:
guard let email = appleIDCredential.email else {
IHProgressHUD.showError(withStatus: "Cannot get email")
return
}
IHProgressHUD.show()
Api.signIn(email: email, password: appleIDCredential.user)
.observeOn(MainScheduler.instance)
.subscribe(onSuccess: self.goToMainScreen(user:), onError: self.displayError(error:))
.disposed(by: self.bag)
if let tokenData = appleIDCredential.identityToken {
let token = String(data: tokenData, encoding: .utf8) ?? ""
_ = Api.fbVerifyAssertion(provider: "apple.com", idToken: token).subscribe(onSuccess: { _ in
print("")
}, onError: { error in
print(error)
})
}
default:
IHProgressHUD.showError(withStatus: "Unsupported authorization credential")
break
}
}
}

View File

@ -53,9 +53,9 @@ class GoogleSignInController: UIViewController, WKNavigationDelegate {
if let code = queryItems.first(where: { $0.name == "code" })?.value {
decisionHandler(.cancel)
self.getToken(code: code)
.flatMap(fbVerifyAssertion)
.flatMap { Api.fbVerifyAssertion(provider: "google.com", idToken: $0.id_token, accessToken: $0.access_token) }
.observeOn(MainScheduler.instance)
.subscribe(onNext: { _ in
.subscribe(onSuccess: { _ in
self.dismiss(animated: true, completion: self.completion)
}, onError: { error in
IHProgressHUD.showError(withStatus: error.localizedDescription)
@ -85,7 +85,7 @@ class GoogleSignInController: UIViewController, WKNavigationDelegate {
return String(data: Data(Base64FS.encode(data: hash)), encoding: .utf8)?.trimmingCharacters(in: CharacterSet(charactersIn: "="))
}
func getToken(code: String) -> Observable<TokenResponse> {
func getToken(code: String) -> Single<TokenResponse> {
let tokenUrlString = Constants.googleTokenURL
+ "?grant_type=authorization_code"
+ "&code=" + code
@ -96,54 +96,12 @@ class GoogleSignInController: UIViewController, WKNavigationDelegate {
if let url = URL(string: tokenUrlString) {
var request = URLRequest(url: url)
request.httpMethod = "POST"
return URLSession.shared.rx.data(request: request).map { data in
return URLSession.shared.rx.data(request: request).asSingle().map { data in
return try JSONDecoder().decode(TokenResponse.self, from: data)
}
} else {
let error = NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Bad URL"])
return Observable.error(error)
return Single.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(())
}
}
}

View File

@ -1,5 +1,6 @@
import UIKit
import Eureka
import AuthenticationServices
class SettingsController: FormViewController {
@ -9,11 +10,11 @@ class SettingsController: FormViewController {
form +++ Section("Profile")
<<< LabelRow("AutoCatAccount") { row in
row.title = "AutoCat Account"
row.value = Settings.shared.user.login
row.value = Settings.shared.user.email
}
<<< LabelRow("GoogleAccount") { row in
row.title = "Google"
if let jwtString = Settings.shared.user.googleIdToken, let jwt = JWT(string: jwtString) {
if let jwtString = Settings.shared.user.firebaseIdToken, let jwt = JWT(string: jwtString) {
row.value = jwt.payload.email
} else {
row.value = "Log In"
@ -22,8 +23,8 @@ class SettingsController: FormViewController {
cell.accessoryType = .disclosureIndicator
}
}.onCellSelection { cell, row in
if Settings.shared.user.googleIdToken != nil {
self.displayLogoutSheet()
if Settings.shared.user.firebaseIdToken != nil {
self.displayLogoutSheet(for: "GoogleAccount")
} else {
self.loginToGoogle()
}
@ -90,18 +91,18 @@ class SettingsController: FormViewController {
self.view.window?.rootViewController = storyboard.instantiateViewController(identifier: "AuthController")
}
func displayLogoutSheet() {
guard let jwtString = Settings.shared.user.googleIdToken, let jwt = JWT(string: jwtString) else { return }
func displayLogoutSheet(for row: String) {
guard let jwtString = Settings.shared.user.firebaseIdToken, 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 will help to gather 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
Settings.shared.user.googleIdToken = nil
Settings.shared.user.googleRefreshToken = nil
if let googleRow = self.form.rowBy(tag: "GoogleAccount") as? LabelRow {
googleRow.value = "Log In"
googleRow.reload()
Settings.shared.user.firebaseIdToken = nil
Settings.shared.user.firebaseRefreshToken = nil
if let row = self.form.rowBy(tag: row) as? LabelRow {
row.value = "Log In"
row.reload()
}
}
@ -115,7 +116,7 @@ class SettingsController: FormViewController {
if let vc = storyboard.instantiateViewController(identifier: "GoogleSignInController") as? GoogleSignInController {
vc.completion = {
guard let googleRow = self.form.rowBy(tag: "GoogleAccount") as? LabelRow else { return }
if let jwtString = Settings.shared.user.googleIdToken, let jwt = JWT(string: jwtString) {
if let jwtString = Settings.shared.user.firebaseIdToken, let jwt = JWT(string: jwtString) {
googleRow.value = jwt.payload.email
} else {
googleRow.value = "Log In"
@ -125,4 +126,8 @@ class SettingsController: FormViewController {
self.present(vc, animated: true)
}
}
func loginToApple() {
}
}

View File

@ -1,13 +1,13 @@
import Foundation
struct User: Codable {
let login: String
let email: String
var token: String
var googleIdToken: String?
var googleRefreshToken: String?
var firebaseIdToken: String?
var firebaseRefreshToken: String?
init() {
self.login = ""
self.email = ""
self.token = ""
}
}

View File

@ -1,7 +1,11 @@
import Foundation
import RxSwift
import RxCocoa
class Api {
// MARK: - Private wrappres
private static func genError(_ msg: String, suggestion: String, code: Int = 0) -> Error {
return NSError(domain: "", code: code, userInfo: [NSLocalizedDescriptionKey: msg, NSLocalizedRecoverySuggestionErrorKey: suggestion])
}
@ -36,14 +40,14 @@ class Api {
}
return URLSession.shared.rx.data(request: request).asSingle().map { data in
// let str = String(data: data, encoding: .utf8)
// print("================================")
// if let string = str?.replacingOccurrences(of: "\\\"", with: "\"")
// .replacingOccurrences(of: "\\'", with: "'")
// .replacingOccurrences(of: "\\n", with: "") {
// print(string)
// }
// print("================================")
let str = String(data: data, encoding: .utf8)
print("================================")
if let string = str?.replacingOccurrences(of: "\\\"", with: "\"")
.replacingOccurrences(of: "\\'", with: "'")
.replacingOccurrences(of: "\\n", with: "") {
print(string)
}
print("================================")
let resp = try JSONDecoder().decode(Response<T>.self, from: data)
if resp.success {
return resp.data!
@ -73,8 +77,10 @@ class Api {
return self.makeRequest(api: api, method: method, body: body, params: nil as [String:Int]?)
}
// MARK: - Firebase API
public static func refreshFbToken() -> Single<Void> {
guard let token = Settings.shared.user.googleIdToken, let refreshToken = Settings.shared.user.googleRefreshToken, let jwt = JWT(string: token), jwt.expired else {
guard let token = Settings.shared.user.firebaseIdToken, let refreshToken = Settings.shared.user.firebaseRefreshToken, let jwt = JWT(string: token), jwt.expired else {
return .just(())
}
@ -91,16 +97,16 @@ class Api {
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.secondProviderBundleId, forHTTPHeaderField: "X-Ios-Bundle-Identifier")
request.addValue(Constants.fbUserAgent, forHTTPHeaderField: "User-Agent")
return URLSession.shared.rx.json(request: request).asSingle().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
Settings.shared.user.firebaseIdToken = newToken
print("Token was successfully refresh to: \(newToken)")
}
if let newRefreshToken = json["refresh_token"] as? String {
Settings.shared.user.googleRefreshToken = newRefreshToken
Settings.shared.user.firebaseRefreshToken = newRefreshToken
}
}.catchError { error in
print(error)
@ -111,17 +117,72 @@ class Api {
}
}
public static func login(username: String, password: String) -> Single<User> {
public static func fbVerifyAssertion(provider: String, idToken: String, accessToken: String? = nil) -> Single<Void> {
let signupUrl = Constants.fbVerifyAssertion + "?key=" + (Constants.fbApiKey.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? Constants.fbApiKey)
if let url = URL(string: signupUrl) {
var innerBody = "providerId=" + provider
+ "&id_token=" + idToken
if let accessToken = accessToken {
innerBody += "&access_token=" + accessToken
}
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.secondProviderBundleId, forHTTPHeaderField: "X-Ios-Bundle-Identifier")
request.addValue(Constants.fbUserAgent, forHTTPHeaderField: "User-Agent")
return URLSession.shared.rx.json(request: request).asSingle().map { response in
guard let json = response as? [String: Any] else { return }
if let newToken = json["idToken"] as? String {
Settings.shared.user.firebaseIdToken = newToken
print("Token: \(newToken)")
}
if let newRefreshToken = json["refreshToken"] as? String {
Settings.shared.user.firebaseRefreshToken = newRefreshToken
print("Refresh token: \(newRefreshToken)")
}
}.catchError { err in
print(err)
return .just(())
}
} else {
return .just(())
}
}
// MARK: - AutoCat public API
public static func login(email: String, password: String) -> Single<User> {
let body = [
"login": username,
"email": email,
"password": password
]
return self.makeBodyRequest(api: "user/login", body: body)
}
public static func signup(username: String, password: String) -> Single<User> {
public static func signIn(email: String, password: String) -> Single<User> {
let body = [
"login": username,
"email": email,
"password": password
]
return self.makeBodyRequest(api: "user/signIn", body: body)
}
public static func signUp(email: String, password: String) -> Single<User> {
let body = [
"email": email,
"password": password
]
return self.makeBodyRequest(api: "user/signup", body: body)
@ -137,7 +198,7 @@ class Api {
"number": number,
"forceUpdate": String(force)
]
if let token = Settings.shared.user.googleIdToken {
if let token = Settings.shared.user.firebaseIdToken {
body["googleIdToken"] = token
}
return self.makeBodyRequest(api: "vehicles/check", body: body).map { (vehicle: Vehicle) -> Vehicle in

View File

@ -23,7 +23,7 @@ enum Constants {
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"
static let secondProviderBundleId = "ru.Vin01"
static let reportLinkTokenSecret = "#TheTruthIsOutThere"
static let reportLinkBaseURL = "https://auto.aliencat.pro/report.html"

View File

@ -87,6 +87,9 @@ class Recorder {
}
do {
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default, options: [])
try AVAudioSession.sharedInstance().setActive(true)
let inFormat = self.engine.inputNode.outputFormat(forBus: 0)
ExtAudioFileSetProperty(fileRef, kExtAudioFileProperty_ClientDataFormat, UInt32(MemoryLayout<AudioStreamBasicDescription>.size), inFormat.streamDescription)
@ -113,9 +116,6 @@ class Recorder {
self.engine.prepare()
try self.engine.start()
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default, options: [])
try AVAudioSession.sharedInstance().setActive(true)
} catch {
observer(.error(error))
}