Insert instead of update in firebase - ios

I'm trying to insert new values into Firebase Realtime Database. But every time I "register" a new user, my database data is getting replaced by the new one. I'm totally confused on how I can do this different.
This is my code..
//Create a new user with txtfield email & password
Auth.auth().createUser(withEmail: email, password: password) { authResult, error in
//Printing error if any
if error != nil
{
print(error as Any)
return
}
//Getting database reference
let ref = Database.database().reference()
//Values to insert into database
let values = ["Username": self.username, "Email": self.email, "Name1": self.name1, "Name2": self.name2, "Name3": self.name3, "Name4": self.name4, "Name5": self.name5, "Name6": self.name6, "Dog1": dog1, "Dog2": dog2, "Dog3": dog3]
//Updating the child values
ref.updateChildValues(values, withCompletionBlock: { (err, ref) in
//Printing error if any
if err != nil
{
print(err as Any)
return
}
//Succeded if no errors
print("Saved user successfully in Firebase database!")
})
And I assume the problem is at
ref.updateChildValues(values, withCompletionBlock: { (err, ref) in
But I've no idea how I can replace this. So to make it short.
Every time I create a new user, the database data is getting replaced. And I basically want it to create a new "row" for each user.

You need to insert the items under a child like users/userID
guard let firUser = authResult.user else { return }
let userID = firUser.uid
let ref = Database.database().reference()
let user = ref.child("users/\(userID)")
user.updateChildValues////
Database
> users
> njfjnjnf889489489 // some user uid
> name
> mail
> 322jnjnf889489483 // some user uid
> name
> mail

Related

SwiftUI Edit User Account using data from Firestore

I'm very new to SwiftUI and I'm trying to create a very basic login/logout system in SwiftUI on IOS with the ability to edit the users profile. I have two main functions in the signup process, function register and function AddInfo which then actually adds the user to the db.
both in AuthenticationView.swift
func register(){
if self.email != ""{
if self.pass == self.repass{
//Creating the user
Auth.auth().createUser(withEmail: self.email, password: self.pass) { (res, err) in
if err != nil{
self.error = err!.localizedDescription
self.alert.toggle()
return
}
//Add user info to database
AddInfo(username: self.username, email: self.email)
print("success")
UserDefaults.standard.set(true, forKey: "status")
NotificationCenter.default.post(name: NSNotification.Name("status"), object: nil)
}
}
else{
self.error = "Password mismatch"
self.alert.toggle()
}
}
else{
self.error = "Please fill all the contents properly"
self.alert.toggle()
}
}
Then i have an addinfo function which adds the user to a database. The document ID of the db is the users UID and then it creates a username, email and uid automatically and i've made it create a blank entry for Firstname and Lastname.
func AddInfo(username: String, email: String) {
let db = Firestore.firestore()
let user = Auth.auth().currentUser
if let user = user {
// The user's ID, unique to the Firebase project.
// Do NOT use this value to authenticate with your backend server,
// if you have one. Use getTokenWithCompletion:completion: instead.
let uid = user.uid
//let email = user.email
//let photoURL = user.photoURL
db.collection("users").document(uid).setData([
"UID": uid,
"Username": username,
"Email": email,
"First Name": "",
"Last Name": ""])
}
This is what the DB looks like when a user registers
database look when user registers
So with all of this in mine, i'm struggling with creating a Edit user profile view. How would I go about doing this? All i need is a page that shows the users registered email, username and then they can add their first and last name (first and last name isn't included on the registration form, that's something i'd like to add after they've registered)
I've tried reading the Firestore view my profile document but i'm struggling to get my head around it

why do i get two user ids when creating a user in firebase using swift?

when i sign up a user in my ios app it generates a user id and adds that to the data base with the users name and surname and username but it is generating a user id and another random number/id and i dont know what that is for:
i dont know what the Roy... is and dont know where its coming from.
so when i try and access the users uid to access the information such as the name and surname i keep getting the following error because its using the wc7... number and not the other one:
Listener at /Users/wc7VyejKlDNfcAhFu3AkIX9Y9on1/Username failed: permission_denied
this is my code that i use to try and access the users information:
func fetchUsersData() {
guard let currentUser = Auth.auth().currentUser?.uid else { return }
print("Current user id is \(currentUser)")
Database.database().reference().child("Users").child(currentUser).child(USER_NAME).observeSingleEvent(of: .value) { (snapshot) in
guard let username = snapshot.value as? String else {return}
self.navigationItem.title = username
}
}
how do i fix this?
That code is for the Firebase Real Time Database and the screen shot is for Cloud Firestore. They are totally different and unrelated.
If you want to read the data shown in your screenshot you need to use the Cloud Firestore documentation.
The documentID 'Roy...' happens when you don't assign a document an ID... it will generate one automatically.
Also, change your Firestore structure to use the users uid as the documentID. So it would look like this
users //the collection
uid_0 //the document with documentID = a users uid
first_name: "Hank"
last_name: "Jones"
user_name: "Hankster"
uid_1
first_name: "Leroy"
last_name: "Jenkins"
user_name: "Leeeerrroooyyy"
and then the code to read a specific user name based on a uid is this
func readUserName() {
let users = self.db.collection("users")
let thisUser = users.document(the users uid)
thisUser.getDocument(completion: { documentSnapshot, error in
if let error = error {
print(error.localizedDescription)
return
}
guard let snap = documentSnapshot else { return }
let docId = snap.documentID
let userName = snap.get("user_name") as? String ?? "No Name"
print(userName)
})
}
Also note that you will need to be authenticated to Firestore to read any data or adjust the Security Rules to allow anyone to read. That's not generally a good idea but when you're just getting started it's ok.

Firebase Realtime Database doesn't save data from sign up page

I am working on sign up page of application in Swift. The part of authentication in Firebase works well, but the database doesn't save any information I request. Can anyone help?
My code:
Auth.auth().createUser(withEmail: userEmail,password: userPassword, completion: {(User, error) in
if error != nil {
print(error as Any)
return
}
guard let uid = User?.user.uid else {return}
let ref = Database.database().reference(fromURL:"Database-URL")
let userReference = ref.child("users").child(uid)
let values = ["Firstname": userFirstName,"email": userEmail]
userReference.updateChildValues(values, withCompletionBlock: { (error, reference) in
if error != nil {
print(error as Any)
return
}
})
})
The console prints an error
Optional(Error Domain=com.firebase Code=1 "Permission denied"
UserInfo={NSLocalizedDescription=Permission denied})
By default the database in a project in the new Firebase Console is only readable/writeable by authenticated users:
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
See the quickstart for the Firebase Database security rules.
Since you're not signing the user in from your code, the database denies you access to the data. To solve that you will either need to allow unauthenticated access to your database, or sign in the user before accessing the database.
Allow unauthenticated access to your database
The simplest workaround for the moment (until the tutorial gets updated) is to go into the Database panel in the console for you project, select the Rules tab and replace the contents with these rules:
{
"rules": {
".read": true,
".write": true
}
}
This makes your new database readable and writeable by everyone. Be certain to secure your database again before you go into production, otherwise somebody is likely to start abusing it.
I may not be sure but the completion for createUser doesnot give you User and error rather AuthResult and Error. So you have to get the user from result as below
Auth.auth().createUser(withEmail: email, password: password) { (authData, error) in
if let error = error {
debugPrint("FIREBASE ERROR : \(error.localizedDescription)")
} else {
if let authData = authData {
let user = authData.user //here get the user from result
self.saveToDB(user: user) . //save the user to database
}
}
}
This is the new code for firebase from may 2019. just change false to true like this:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}

How to add a username to Firebase database upon registration?

Upon logging in I want my app to make a new field in the Firebase database with the child named after the username.
if let email = emailField.text, let pass = passwordField.text {
// Check if it's sign in or register
if isLogin {
// Sign in the user with Firebase
Auth.auth().signIn(withEmail: email, password: pass, completion: { (user, error) in
// Check that user isn't nil
if let u = user {
// User is found, go to home screen
self.ref?.child(email).childByAutoId().setValue("1")
self.performSegue(withIdentifier: "goHome", sender: self)
print("yes")
}
When I try to do this, it gives me an error called SIGABART which I believe is associated with not having segues connected properly.
Yet if I delete this line:
self.ref?.child(email).childByAutoId().setValue("1")
or change the email field to a random string like "test", it works fine and appears in Firebase.
If I remember correctly, you can't use symbol # in nodes names. It's first problem. You can do it another, I think better, way:
You need to create user to ref like:
/users/uid from created FIRUser.
You can do it with next steps:
For example, your registration page will have 3 UITextFields: userEmail, userLogin and userPassword.
// *1* Create user
FIRAuth.auth()!.createUser(withEmail: userEmail.text!,
password: userPassword.text!)
{ user, error in
if error == nil {
// *2* Then log him in
FIRAuth.auth()!.signIn(withEmail: self.userEmail.text!,
password: self.userPassword.text!)
{ result in
// *3* Create new user in database, not in FIRAuth
let uid = (FIRAuth.auth()?.currentUser?.uid)!
let ref = FIRDatabase.database().reference(withPath: "someStartPart/users").child(uid)
ref.setValue(["uid": uid, "email": userEmail.text!, "login": userLogin.text!, "creationDate": String(describing: Date())])
self.performSegue(withIdentifier: "fromRegistrationToMainPage", sender: self)
}
} else {
print("\(String(describing: error?.localizedDescription))")
}
}
Like this. Hope it helps.
Firebase Auth will not allow you to store such a value. You will need to save this into Firebase Database or another service. e.g. In the Firebase Database:
userRef.setValue("username123")
You should save the username value in the database. Something like this:
FIRdatabase.database().reference().child("yourchildname").updateChild(u)
(Im on my phone, so the call might not be EXACTLY like that, but should be very close)
Cheers.
Swift 4:
//***** for realTime database
let ref = Database.database().reference(fromURL: "https://add your project URL")
let userRef = ref.child("users").child(user.user.uid)
let values = ["Email": email, "UserName": userName] //userName is the name of textField

PFUser not unwrapped - swift

I'm beginning to learn swift with parse and i've run into this error:
"Value of optional type 'PFUser?' not unwrapped; did you mean to use '!' or '?'
I can't seem to get it to work...
PFFacebookUtils.logInWithPermissions(["public_profile",
"user_about_me", "user_birthday"], block: {
user, error in
if user == nil {
println("the user canceled fb login")
//add uialert
return
}
//new user
else if user.isNew {
println("user singed up through FB")
//get information from fb then save to parse
FBRequestConnection.startWithGraphPath("/me?fields=picture,first_name,birthday,gender", completionHandler: {
connection, result, error in
//print results
println(result)
//result dictionary about user
var r = result as NSDictionary
//prnt dictionary
println(NSDictionary)
//match parse column with what fb sends
user["firstName"] = r["first_name"]
user["gender"] = r["gender"]
//r = result, then key into using picture. Then key into url using the data
let pictureURL = ((r["picture"] as NSDictionary)["data"] as NSDictionary) ["url"] as String
Instead of using if user == nil {... you should really use
if let user = user {
// Login succeeded...
}
else {
// Login failed
}
The variable user will then be unwrapped inside the if let and you can continue using user the same way you are.
Here is explanation: What is an "unwrapped value" in Swift?
PFFacebookUtils.logInWithPermissions(["public_profile",
"user_about_me", "user_birthday"], block: {
user, error in
if user == nil {
println("the user canceled fb login")
//add uialert
return
}
//new user
else if user!.isNew {
println("user singed up through FB")
//get information from fb then save to parse
FBRequestConnection.startWithGraphPath("/me?fields=picture,first_name,birthday,gender", completionHandler: {
connection, result, error in
//print results
println(result)
//result dictionary about user
var r = result as NSDictionary
//prnt dictionary
println(NSDictionary)
//match parse column with what fb sends
user["firstName"] = r["first_name"]
user["gender"] = r["gender"]
//r = result, then key into using picture. Then key into url using the data
let pictureURL = ((r["picture"] as NSDictionary)["data"] as NSDictionary) ["url"] as String

Resources