below I just typed is error showing "Cannot cover value of type '(,) -> Void' to expected argument type '(NSERROR!) -> Void!)'
on this line of code: what would be wrong?
FIREBASE_REF.createUser(email, password: password, withCompletionBlock: {(error,authData) -> Void in
#IBAction func creatAccountAction(sender: AnyObject) {
let email = self.emailTextField.text
let password = self.passwordTextField.text
if email != "" && password != ""
{
FIREBASE_REF.createUser(email, password: password, withCompletionBlock: {(error,authData) -> Void in
if error != nil {
FIREBASE_REF.authUser(email, password: password, withCompletionBlock: { (error, authData) -> Void in
if error == nil {
NSUserDefaults.standardUserDefaults().setValue(authData.uid, forKey: "uid")
}
else {
print (error)
}
})
}
else {
print (error)
}
}
)}
else
Try this:
FIREBASE_REF.createUser(email, password: password, withCompletionBlock: {(error) -> Void in
This block has probably only one parameter
There are two options for creating a user, one just creates it and returns an error if it fails (withCompletionBlock), the other also returns the authData (withValueCompletionBlock): that's the one you want.
myRootRef.createUser(email, password: pw, withValueCompletionBlock: { error, result in
if error != nil {
print("error creating user")
} else {
let uid = result["uid"] as! String
NSUserDefaults.standardUserDefaults().setValue(uid, forKey: "uid")
//pass the parameters to another function to auth the user
self.authUserWithAuthData( email, password: pw )
}
})
Related
I'm trying to add additional information to my cloud function so that way my Stripe customer has all of the data saved in the Firebase Database. However, my question is how can I implement the constants in my cloud function correctly so the information uploads correctly? Without the fullname, username, and profileImage in my cloud function and my registration function in the functions section, it creates the Stripe customer. How do I structure the constants for those three fields so they can upload as well? Or should I create an email and password registration screen, so I can create the stripeID, then create another screen for additional information to add to the reference? Thank you!
Cloud Function:
exports.createStripeCustomer = functions.https.onCall( async (data, context) => {
const email = data.email
const uid = context.auth.uid
const fullname = context.auth.uid.fullname
const username = context.auth.uid.username
const profileImage = context.auth.uid.profileImage
if (uid === null) {
console.log('Illegal access attempt due to unauthenticated attempt.')
throw new functions.https.HttpsError('internal', 'Illegal access attempt')
}
return stripe.customers.create({
email : email,
fullname : fullname,
username : username,
profileImage : profileImage
}).then( customer => {
return customer["id"]
}).then( customerId => {
admin.database().ref("customers").child(uid).set(
{
stripeId: customerId,
email: email,
fullname: fullname,
username: username,
profileImage: profileImage,
id: uid
}
)
}).catch( err => {
throw new functions.https.HttpsError('internal', 'Unable to create Stripe customer.')
})
})
AuthService Function:
static func createCustomer(credentials: CustomerCredentials, completion: #escaping(DatabaseCompletion)) {
guard let imageData = credentials.profileImage.jpegData(compressionQuality: 0.3) else { return }
let filename = NSUUID().uuidString
let storageRef = STORAGE_REF.reference(withPath: "/customer_profile_images/\(filename)")
storageRef.putData(imageData, metadata: nil) { (meta, error) in
if let error = error {
debugPrint(error.localizedDescription)
return
}
storageRef.downloadURL { (url, error) in
guard let profileImageUrl = url?.absoluteString else { return }
Auth.auth().createUser(withEmail: credentials.email, password: credentials.password) { (result, error) in
if let error = error {
debugPrint(error.localizedDescription)
return
}
guard let uid = result?.user.uid else { return }
let values = ["email" : credentials.email,
"fullname" : credentials.fullname,
"username" : credentials.username,
"uid" : uid,
"profileImageUrl" : profileImageUrl] as [String : Any]
CustomerDataService.saveCustomerData(uid: uid, fullname: credentials.fullname, email: credentials.email,
username: credentials.username, profileImagUrl: profileImageUrl)
REF_CUSTOMERS.child(uid).setValue(values, withCompletionBlock: completion)
}
}
}
}
Registration Function:
#objc func handleCreateAccount() {
guard let profileImage = profileImage else {
self.simpleAlert(title: "Error", msg: "Please select a profile image.")
return
}
guard let email = emailTextField.text?.lowercased() , email.isNotEmpty ,
let fullname = fullnameTextField.text , fullname.isNotEmpty ,
let username = usernameTextField.text?.lowercased() , username.isNotEmpty ,
let password = passwordTextField.text , password.isNotEmpty ,
let confirmPassword = confirmPasswordTextField.text , confirmPassword.isNotEmpty else {
self.simpleAlert(title: "Error", msg: "Please fill out all fields.")
return
}
if password != confirmPassword {
self.simpleAlert(title: "Error", msg: "Passwords don't match, please try again.")
return
}
showLoader(true, withText: "Registering Account")
let credentials = CustomerCredentials(email: email, fullname: fullname, username: username,
password: password, profileImage: profileImage)
AuthService.createCustomer(credentials: credentials) { (error, ref) in
if let error = error {
Auth.auth().handleFireAuthError(error: error, vc: self)
self.showLoader(false)
return
}
Functions.functions().httpsCallable("createStripeCustomer").call(["email": credentials.email,
"fullname": credentials.fullname,
"username": credentials.username,
"profileImage": credentials.profileImage]) { result, error in
if let error = error {
Auth.auth().handleFireAuthError(error: error, vc: self)
self.showLoader(false)
return
}
}
self.showLoader(false)
guard let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) else { return }
guard let tab = window.rootViewController as? MainTabController else { return }
tab.setupNavigationControllers()
self.handleDismissal()
}
}
To complete what I was trying to accomplish, I created a screen for customers to create an e-mail and password. This way the StripeID could be created, and then I created another screen to add the full name, username and profile image, and updated the database reference.
My codes error
I do not know why its saying that 'uid' has no member, also i don't know where AuthDataResult is coming from because i have never used this as an import or anything along those lines...
#IBAction func signinPressed(_ sender: Any) {
if let email = emailField.text, let password = passwordField.text {
Auth.auth().signIn(withEmail: email, password: password) { (user, error )
in
if error != nil{
//create account
} else {
KeychainWrapper.standard.set((user?.uid)!,
forKey: ("Key_UID"))
self.preformSegue(performSegue(withIdentifier: "toFeed", sender: nil))
}
}
}
}
The error you get is:
Value of type AuthDataResult has no member uid
If you look at the reference documentation for AuthDataResult, you'll see that this is correct: there is no uid in that class. The uid property exists in FIRUser, so you'll want to use:
user?.user.uid
Or to make it less confusing, give your current user variable a name that better matches what it is:
Auth.auth().signIn(withEmail: email, password: password) { (authData, error ) in
if error != nil{
//create account
} else {
KeychainWrapper.standard.set((authData?.user.uid)!,
forKey: ("Key_UID"))
self.preformSegue(performSegue(withIdentifier: "toFeed", sender: nil))
}
}
I am trying to access a user's uid in Firebase Authentication. I created a createUser completion block in my code and at the end of the block I want to check for the user in which I named firUser. When I try to add firUser.uid in my User I get the error message
"Value of type 'AuthDataResult' has no member ‘uid’"
Below is a copy of the code I wrote hopefully some one can help me.
Auth.auth().createUser(withEmail: email, password: password, completion: { (firUser, error) in
if error != nil {
// report error
} else if let firUser = firUser {
let newUser = User(uid: firUser.uid, username: username, fullName: fullName, bio: "", website: "", follows: [], followedBy: [], profileImage: self.profileImage)
newUser.save(completion: { (error) in
if error != nil {
// report
} else {
// Login User
Auth.auth().signIn(withEmail: email, password: password, completion: { (firUser, error) in
if let error = error {
// report error
print(error)
} else {
self.dismiss(animated: true, completion: nil)
}
})
}
})
}
})
According to the guide, when using .createUser,
If the new account was successfully created, the user is signed in,
and you can get the user's account data from the result object that's
passed to the callback method.
Notice in the sample, you get back authResult, not a User object. authResult contains some information, including the User. You can get to the User using authResult.user.
In addition, when calling the method, if successful, the user is already signed in, so there's no reason to sign them in again. I changed the parameter name to authResult from the sample to help eliminate some of the confusion.
Auth.auth().createUser(withEmail: email, password: password, completion: { authResult, error in
if let error = error {
// report error
return
}
guard let authResult = authResult else { return }
let firUser = authResult.user
let newUser = User(uid: firUser.uid, username: username, fullName: fullName, bio: "", website: "", follows: [], followedBy: [], profileImage: self.profileImage)
newUser.save(completion: { (error) in
if let error = error {
// report
} else {
// not sure what you need to do here anymore since the user is already signed in
}
})
})
I am not familiar with the new Firebase. How do I create new users? The code below I Signup and auth new user. If I need to create this new user under "Customers" in Firebase Database, what code do I need to add? Thanks!
FIRAuth.auth()?.createUserWithEmail(email, password: password, completion: { (user, err) in
if err != nil {
self.showAlert("Can't Register", msg: "Please enter email and password")
} else {
NSUserDefaults.standardUserDefaults().setValue(user?.uid, forKey: "uid")
FIRAuth.auth()?.signInWithEmail(email, password: password, completion: { (user, error) in
})
self.performSegueWithIdentifier("toSecondVC", sender: self)
}
})
FIRAuth.auth()?.createUserWithEmail(email, password: password, completion: { (user, err) in
if err != nil {
self.showAlert("Can't Register", msg: "Please enter email and password")
} else {
NSUserDefaults.standardUserDefaults().setValue(user?.uid, forKey: "uid")
FIRDatabase.database().reference().child("Customers").setValue([user!.uid : "true"])
//Or if you want to save the users Details too:-
/*
FIRDatabase.database().reference().child("Customers").setValue([user!.uid : ["email" : email,"password" : password]])
*/
self.performSegueWithIdentifier("toSecondVC", sender: self)
}
})
Also might i suggest reading this : Firebase iOS - Save Data
The answer above is correct, but I'd recommend doing it this way:
var values = [Any : Any] // This is a dictionary where you can store user details
values["userUID"] = // user's uid
values["usersName"] = // user's name
// etc.
let customerRef = databaseReference.child("Customers") // You could also add a child with the user's UID in order to identify each user
customerRef.updateChildValues(values, withCompletionBlock: { (error, ref) in
if error != nil {
// display error.code and error.localizedDescription to user if needed
} else if ref != [] {
// Success!
// If needed, save the user to NSUserDefaults and perfrom a segue to another ViewController
} else {
// There was an error, but not sure what happened. Let the user know how they can fix the problem (maybe add the details to the database later)
}
})
In my Swift app, when signing up a user, the user is prompted to select a username. This username will then be stored in the Firebase realtime database like this: self.ref.child("users").child(user!.uid).setValue(["username": usernameResponse]), where username response is the value entered by the user. This happens as part of the sign up method:
FIRAuth.auth()?.createUserWithEmail(email, password: passwordUltimate) { (user, error) in
// ... if error != nil {
I would like to verify if the username is available before setting its value. Is there some kind of query I could use to check that there are no duplicates?
Here is my database with some sample data (qwerty12345 is the uid):
#IBAction func enterUsername(){
let enteredUsername = usernameText!.text!
let namesRef = ref.childByAppendingPath("/usernames/\(enteredUsername)")
namesRef.observeSingleEventType(.Value, withBlock: {
snap in
if (snap.value is NSNull){
let userNameAndUUID = ["Username" : enteredUsername, "UUID" : self.appDelegate.UUID]
namesRef.setValue(userNameAndUUID)
print("first block")
}else {
print("second block")
//do some other stuff
}
})
}
Alternately:
let checkWaitingRef = Firebase(url:"https://test.firebaseio.com/users")
checkWaitingRef.queryOrderedByChild("username").queryEqualToValue("\(username!)")
.observeEventType(.Value, withBlock: { snapshot in
if ( snapshot.value is NSNull ) {
print("not found)")
} else {
print(snapshot.value)
}
}