Swift - get field from randomly created document ID (Firestore) - ios

in my application the user can sign up and by doing that I also save the firstname, lastname and uid.
This is how Firestore-Database looks like:
I would like to access the users lastname but I do not know how, as the Document-ID gets created randomly in the sign-up process.
Auth.auth().createUser(withEmail: email, password: password) { (result, err) in
//check for errors
if let err = err {
self.view.endEditing(true)
self.showError(err.localizedDescription)
}else {
//user was created successfully; store first and last name
let db = Firestore.firestore()
db.collection("users").addDocument(data: ["firstname":firstName, "lastname": lastName, "uid": result!.user.uid]) { (error) in
if error != nil {
self.showError("Error saving user data")
}
}
//transition to home
self.transitionToHome()
}

You need to know one of two things in order to get a document in Firestore:
The full path of the document, including the name of the collection and ID of the document (and any nested subcollections and document IDs)
Something about the data in that document, for example, a value of one of its fields.
If you don't know either of these things, then all you can do is fetch all the documents in a collection and try to figure out what you want by looking at everything in the collection.
The bottom line is that if you don't know which document belongs with which user, you are kind of stuck. You should store the ID of the user in the document, or as the ID of the document itself, so that you can use it to find that document later.
I suggest using the Firebase Auth user ID as the ID of the document. This is extremely common. Don't use addDocument to write it with a random ID, use setData with the ID you know.
Firestore cannot just know which document you want at any time, unless you provide a way for it to locate the document.

Related

firebase real time dB retrieving of specific data from multiple users in swift

so I'm working these days on a new project and I have a problem I can't solve, I hope someone can help me.
I'm working on an iOS app, I'm storing all user data on Firebase Real time dB.
My main goal is to get specific data from all users from particular positions,
For example:
Inside users, I have different UIDs of all the users in the dB.
In each one of them, there is a username, I would like to retrieve the username of each user.
In the future, I would like to store the location for each user under "Location". and then I would like to get all users that their location is "New-York".
I'll be glad to get some ideas on how to figure it out!
Thanks!
users
XLS37UqjasdfkKiB
username: "Donald"
ei8d4eYDafjQXyZ
username: "Barak"
etcj0lbSX5Oasfj
username: "Abdul"
rglmlG6Rasdgk5j
username: "Ron"
You can:
Load all JSON from /Users.
Loop over snapshot.children.
Then get the value of each child's username property.
These are also the most common navigation tactics when it comes to Firebase Realtime Database, so you'll apply these to pretty much any read operation.
Something like this:
Database.database().reference().child("isers").observe(.value, with: { (snapshot) in
if !snapshot.exists() {
print("No users found")
} else {
for case let userSnapshot as DataSnapshot in snapshot.children {
guard let dict = userSnapshot.value as? [String:Any] else {
print("Error")
return
}
let username = dict["username"] as? String
print(username)
}
}
})
Also see:
the documentation on reading data.
the documentation on listening for lists of data with a value event.
How to properly use queryOrderedByValue
Get Children of Children in Firebase Using Swift
And more from searching on [firebase-realtime-database][swift] children.

Firebase Storage Denying Image Delete Request: Error Domain=FIRStorageErrorDomain Code=-13021 "User does not have permission to access"

I have an iOS app where users can add annotations to a MapView (the annotations contain data like a title, images, Firebase uid, image fullpath etc.), and the data is uploaded to Firestore as a document, while the image associated with the annotation is uploaded to Firebase Storage. I access the image using its fullPath, which is stored in the corresponding document in Firestore. The problem I'm having is that my Firestore and Storage security rules only permit the creator of a document / image to delete it, and while Firestore is permitting the delete request, Storage is continuing to deny it, despite the same circumstances seemingly working in the test environment. Here are my Storage security rules:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /images/{userId}/{image} {
allow read;
allow create: if request.auth != null;
allow delete: if request.auth != null && request.auth.uid == userId;
}
}
}
Here is how the fullPath string of the image that I upload to Firestore is created (the constant 'fileURL' is simply the stored string of the local URL of the image in the user's phone):
let imagesFilesRef = storageRef.child("images/\(Auth.auth().currentUser!.uid)/\(fileURL.absoluteString.replacingOccurrences(of: "/", with: "."))")
And here is how I call the deletion of the image (tappedAnnotation is the annotation I am deleting, and I am accessing the fullPath stored in Firestore, which exactly matches the file path of how it's stored in Storage):
// Create a reference to the file to delete
let imageRef = storageRef.child("\(tappedAnnotation.fullPath)")
// Delete the file
imageRef.delete { error in
if let error = error {
print(error)
} else {
print("Image successfully deleted!")
}
}
When the creator of this annotation, with the correct uid, is signed in, my delete request is still being denied. Here's an exact example of something I have tried: I created an annotation with an image associated with it, signed in with a Firebase uid (just a test user) of "6CiLpg9gmsOUNC4NJgoz7RHjBeU2". Upon creation of the annotation, the fullPath was uploaded to Firestore with this exact value:
"images/6CiLpg9gmsOUNC4NJgoz7RHjBeU2/file:...Users.Derek.Library.Developer.CoreSimulator.Devices.DA2742F3-DE68-4488-A5DF-20F10EEC8199.data.Containers.Data.Application.DDD1FC6A-EC8C-4070-A4F4-6F6645640B30.tmp.34C8EF1A-6130-4650-A684-7C0ED46690B5.jpeg"
Yet upon delete request, access was denied, although the {userId} section of my security rules exactly matches the uid of the user making the request. Any idea why this is not working? Thanks for any help.

Firesbase authentication iOS login get user detail

I have just followed and correctly added the following tutorial to my app. But I’m struggling on how to get the ‘logged in’ users details from the Firestore database?
The Tutorial:
https://youtu.be/1HN7usMROt8
Once the user registers through my app the ‘First name’, ‘last name’ and ‘UID’ are saved by the Firestore database. But once the user logs in how do I GET the users first name to copy to a label on a welcome screen inside the app?
Thanks
I suppose that you know how Firestore works. If you don't you can get all informations in this documentation or watch videos about Firestore on YouTube.
So let's say you have your users saved in collection named users. When the user sign in you can get current user like this:
let currentSignInUser = Auth.auth().currentUser!
If you will force unwrap it make sure that user will be signed in.
When you have current user you can get his uid by calling uid property of current user:
let currentUserID = currentSignInUser.uid
Now you can query this uid to get documents from Firestore users collection that have same UID field value as your current signed in user:
let query = Firestore.firestore().collection("users").whereField("UID", isEqualTo: currentUserID)
Make sure that the first parameter of whereField() function is same as your field name in documents. Because you mention that UID is saved to database I name it UID.
This is all for getting informations of your current user and making query out of it. Now you can GET documents from Firestore:
query.getDocuments() { [weak self] (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
if let userInfo = querySnapshot?.documents.first {
DispatchQueue.main.async {
// Set label text to first name
self?.youLabel.text = userInfo["firstName"]
}
}
}
}
Change userInfo key to whatever name have you used for storing first name in Firestore. For example if you named your document field firstName then userInfo dictionary key must be firstName.

Get data from unknown website using Webview

I'm currently creating an app where people can book online from a specific website. (The website is NOT owned by me) but is there any way I can get the user input from the website?
My idea is to let a user book from the webpage and their information like name, phone and last name will be saved into my app.
So if a user enter their first and last name on the webpage, I wanna retrieve the input as a string so I can later on create a notification when it's time to attend the booked event. Is there any way to do this?
webview.evaluateJavaScript("document.getElementById('first_3').value") { (data, err) in
if let err = err {
print(err.localizedDescription)
} else {
print("test", data)
}
}
I've added this one to the app, and I found the id "first_3" by viewing the elements.
So, how can I get the user input from a web view into my app?

Removing a specific value off of firebase database

I am setting up a social media app and currently working on a way to create authentic usernames(no duplicates) for the user to enter, similar to that of Instagram.
The problem that I'm facing is that I can't find a way to delete the users previous username(in case anyone else wants to use it). The way that my database is setup for usernames is like:
Usernames
- username:"testUsername"
I have attempted to delete the code using this
let usernameRef = FIRDatabase.database().reference().child("Usernames").child("username").child(usersCurrentUsername)
usernameRef.removeValue(completionBlock: {(error, ref) in
if error != nil {
print("There was an error in removing the current username\(error?.localizedDescription)")
} else {
print(ref)
print("The child was removed")
}
})
I capture the users current username via snapshot in the viewdidload and store it in usersCurrentUsername.
Any help would be appreciated
let usernameRef = FIRDatabase.database().reference().child("Usernames").child("username");
usernameRef.removeValue();
Note that if the child of Usernames is only the username, the Usernames node will also be deleted.

Resources