Created
May 8, 2017 20:46
-
-
Save MarksCode/988483ba9f373e913d060837259572d1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// SignInVC.swift | |
// Dog_Log | |
// | |
// Created by Ron Marks on 1/6/17. | |
// Copyright © 2017 Ron Marks. All rights reserved. | |
// | |
import UIKit | |
import Firebase | |
import GoogleSignIn | |
import CoreData | |
import FBSDKLoginKit | |
class LoginVC: UIViewController, GIDSignInUIDelegate, GIDSignInDelegate { | |
var managedObjectContext: NSManagedObjectContext! | |
@IBOutlet weak var googleButton: UIButton! | |
@IBOutlet weak var fbButton: UIButton! | |
var ref: FIRDatabaseReference! | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
GIDSignIn.sharedInstance().uiDelegate = self | |
GIDSignIn.sharedInstance().delegate = self | |
ref = FIRDatabase.database().reference() | |
FBSDKLoginManager().logOut() // clear current token | |
} | |
// google sign in | |
@IBAction func googleTouch(_ sender: UIButton) { | |
disableGoogleButton() | |
GIDSignIn.sharedInstance().signIn() | |
} | |
// fb sign in | |
@IBAction func fbTouch(_ sender: Any) { | |
disableFacebookButton() | |
let login = FBSDKLoginManager() | |
login.logIn(withReadPermissions: ["public_profile", "email"], from: self, handler: { (result, error) in | |
if error == nil { | |
if !(result?.isCancelled)! { | |
self.getFBUserData() | |
} else { | |
self.enableFacebookButton() | |
} | |
} else { | |
print(error?.localizedDescription) | |
self.enableFacebookButton() | |
} | |
}) | |
} | |
// attempt to sign in user with fb | |
// cases: | |
// 1) user's facebook does have email. This is common case | |
// - in this case, sign them into Firebase | |
// - could be that they previously didn't have email but now they do, so update Firebase user's email | |
// - could be that a firebase account with their email already exists, throw error | |
// - otherwise everything went fine, segue to home page | |
// 2) user's facebook account could have no email associated (or disabled email permissions). This is a rare case | |
// - in this case, take user to manual email input page | |
// - or user could've already done above step, in which case just log them in normally | |
func getFBUserData(){ | |
if((FBSDKAccessToken.current()) != nil){ | |
FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "name, email"]).start(completionHandler: { (connection, result, error) -> Void in | |
if error == nil, let res = result as? [String: String]{ | |
let credential = FIRFacebookAuthProvider.credential(withAccessToken: FBSDKAccessToken.current().tokenString) | |
if res["email"] != nil { // facebook account has email | |
// CASE 1 | |
print("user has email") | |
FIRAuth.auth()?.signIn(with: credential, completion: { (user, error) in // sign user into Firebase | |
if error == nil && user != nil { | |
if user!.email == nil { // Firebase user has no email | |
user!.updateEmail(res["email"]!, completion: { error in // user has no email, set email | |
if error != nil { | |
if let errCode = FIRAuthErrorCode(rawValue: error!._code) { | |
switch errCode { | |
case .errorCodeEmailAlreadyInUse: // email is already in use by another account | |
self.showEmailTakenAlert() | |
default: | |
self.showRegistrationErrorAlert() | |
} | |
} | |
self.enableFacebookButton() | |
} else { // user previously had no email but now does | |
print("email set") | |
self.setUserInfoAndSegue() | |
} | |
}) | |
} else { // user has email, everything went fine | |
print("signed into Firebase with facebook successfully") | |
self.setUserInfoAndSegue() | |
} | |
} else { // some error happened | |
if let errCode = FIRAuthErrorCode(rawValue: error!._code) { | |
switch errCode { | |
case .errorCodeEmailAlreadyInUse: // email is already in use by another account | |
self.showEmailTakenAlert() | |
default: | |
self.showRegistrationErrorAlert() | |
} | |
self.enableFacebookButton() | |
} | |
} | |
}) | |
} else { // no email associated with facebook account | |
// CASE 2 | |
print("user has no email") | |
FIRAuth.auth()?.signIn(with: credential, completion: { (user, error) in | |
if let user = user { | |
if user.email != nil { // user has already typed in email manually | |
self.setUserInfoAndSegue() | |
} else { // make user type in email manually | |
print("user has no email") | |
let storyboard = UIStoryboard(name: "Main", bundle: nil) | |
let controller = storyboard.instantiateViewController(withIdentifier: "EmailTyper") as? EmailTyperVC | |
controller?.managedObjectContext = self.managedObjectContext | |
self.present(controller!, animated: true, completion: nil) | |
} | |
} else { | |
self.enableFacebookButton() | |
} | |
}) | |
} | |
} else { | |
self.enableFacebookButton() | |
} | |
}) | |
} else { | |
self.enableFacebookButton() | |
} | |
} | |
/// Handle Google Sign in | |
/// | |
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) { | |
if error != nil { | |
self.showRegistrationErrorAlert() | |
self.enableGoogleButton() | |
return | |
} | |
guard let idToken = user.authentication.idToken else { | |
self.enableGoogleButton() | |
return | |
} | |
guard let accessToken = user.authentication.accessToken else { return } | |
let credentials = FIRGoogleAuthProvider.credential(withIDToken: idToken, accessToken: accessToken) | |
// check if account with email already exists | |
FIRAuth.auth()?.fetchProviders(forEmail: user.profile.email, completion: { result, error in | |
if let error = error { | |
self.showRegistrationErrorAlert() | |
return | |
} | |
if let result = result { | |
if result.count > 0 { | |
if result[0] == "facebook.com" { // facebook account already exists with email | |
self.showEmailTakenAlert() | |
self.enableGoogleButton() | |
return | |
} | |
} | |
} | |
FIRAuth.auth()?.signIn(with: credentials, completion: { (user, error) in | |
if error != nil { | |
self.showRegistrationErrorAlert() | |
self.enableGoogleButton() | |
return | |
} | |
print("Successfully logged into firebase with google") | |
self.setUserInfoAndSegue() | |
}) | |
}) | |
} | |
/// See if user is already in database, if not then set data. Then segue to home screen | |
/// | |
func setUserInfoAndSegue(){ | |
if let user = FIRAuth.auth()?.currentUser { | |
UserDefaults.standard.setValue(user.uid, forKey: "CurrentUser") | |
if let email = user.email, let name = user.displayName { | |
// See if user is already in database | |
let userRef = FIRDatabase.database().reference().child("users").child(user.uid) | |
userRef.observeSingleEvent(of: .value, with: { snapshot in | |
// User not in db yet, add data then segue to home view | |
if !snapshot.exists() { | |
let nameRef = FIRDatabase.database().reference().child("allUsers").child(email.cleanString()) | |
nameRef.setValue(["name": name.lowercased(), "uid": user.uid]) | |
userRef.setValue(["name": name, "pets": false, "invites": false, "email": email]) { (error, ref) -> Void in | |
if (error != nil){ | |
print(error!) | |
} else { | |
self.dismiss(animated: true, completion: nil) | |
} | |
} | |
} else { // User is already in db, segue to home view | |
self.dismiss(animated: true, completion: nil) | |
} | |
}) | |
} | |
} | |
} | |
// account with email already exists alert | |
func showEmailTakenAlert(){ | |
let alert = UIAlertController(title: "Registration Error", message: "Your email is already registered with another account", preferredStyle: UIAlertControllerStyle.alert) | |
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil)) | |
self.present(alert, animated: true, completion: nil) | |
} | |
// some errror occurred alert | |
func showRegistrationErrorAlert(){ | |
let alert = UIAlertController(title: "Registration Error", message: "Something went wrong, please try again later", preferredStyle: UIAlertControllerStyle.alert) | |
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil)) | |
self.present(alert, animated: true, completion: nil) | |
} | |
// for when user presses facebook button | |
func disableFacebookButton(){ | |
self.fbButton.isEnabled = false | |
self.googleButton.isUserInteractionEnabled = false | |
} | |
func enableFacebookButton(){ | |
self.fbButton.isEnabled = true | |
self.googleButton.isUserInteractionEnabled = true | |
} | |
// for when user pressed google button | |
func disableGoogleButton(){ | |
self.googleButton.isEnabled = false | |
self.fbButton.isUserInteractionEnabled = false | |
} | |
func enableGoogleButton(){ | |
self.googleButton.isEnabled = true | |
self.fbButton.isUserInteractionEnabled = true | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment