Firestore Sharing data with other users - firebase

I'm creating a travel app in flutter for people to create trips and share with other users that can modify its contents. I'm currently using firebase authentication so each user has an unique id. I'm having trouble understanding what concept I should use to share trip1 with user2. I found out documentReferences allow you to share the specific path of the trip with other users but it doesn't necessarily add the trip to user2 so they can see it on their dashboard. Is documentReferences the correct way to share data with other users?

The best way to do this is to create another collection with the name trips or something you want. It is better to separate the user's data and the trip's data since you are going to share it from one user to another. You can create a unique document for trip 1 and add the location's name as trip 1's value. This way you can filter out where each specific trip is by using .where(). Inside trip1 you can store the reviews of each user inside it. Watch these two videos so that you will be able to understand how to implement it:
https://www.youtube.com/watch?v=Ofux_4c94FI and https://www.youtube.com/watch?v=haMOUb3KVSo. Good Luck!

Related

Firestore model for fetching a list of friends of an user

I have been using Firestore for a very long time. I am building an app now where scalability and keeping low costs is important. (I am using flutter)
My app has users, which have user profiles, also they can add friends and talk to them (like instagram or facebook).
I have a problem building this friends system.
My model for this friends system currently looks like this:
Users collection. Each document id = user id from auth, those docs contain data like name, username, profile picture, etc.
Friends collection. Each document id = user id from auth. For each user, those docs contain a field called: friends, which is an array with each of his friends user ids.
The model looks like:
Friends collection:
- uid:
- friends_list: [friend_uid1, friend_uid2, ...]
This is how my "backend" looks.
Now I want to show my user a list of his friends. How do I do that?
I want a list that looks like instagram, with a nice UI showing each of my user friend profile pic, name, last message, etc.
I can not find a straight forward way to do this with Firestore and queries.
Let's say I do it like this:
Get all my friends user ids in an array.
Get all their user documents using .get() for each document.
This is not doable in firestore cause it would eliminate all the querying power I have (such being able to query only for users with name "x"), I would have to fetch all users and do the query on my front-end (or in a cloud function, same thing, not scalable).
If I do this like:
Get all document using a query for all users in the Friends collection, where friends_list contains my user id.
Save from those documents only the documentID and fetch all the friends user data manually.
This comes with another problem. In Firestore there is no way of fetching a document without fetching all of its fields, so the first query which I use to get the ids only of my friends would actually give me their id + their friend list instead (cause when I query, it also gets the document id + the data), which is not good.
If I do it like:
When you add a friend, instead of just saving its uid, save its uid + data.
Now I can easily show my user his friends list nicely and do some querying on front-end.
The problem here is that now if one of my friends updates his profile photo, I need to update it in every document of all of his friends, which is very write expensive for just a little profile update.
There is also the problem of watching for more data, maybe I have another collection with Chats, and I want to show the last message of my chat with a friend, now I have to fetch the chat rooms too, which is more hard to query data that comes with all the problems that I mentioned before.
In conclusion: I don't see a good scalable way to do this kind of system within Firestore. It seems a simple system which any basic app should have, but I do not see how I can do it in a way that does not make lots of reads or read more data (or sensitive data) than it should.
What kind of model would you do for a friends system like this?
You're decribing a quintessential drawback of NoSQL Databases.
A similar example is actually given in the Get to Know Cloud Firestore series.
Like others have commented, the answer really depends on your application. And this is the assessment you'll have to do. Like which of the options is cheaper depending on the use case of the app.
For example, if you go with your third option and store the friend's user data that you'll need to populate the list. This means you'll have to implement measures to keep the integrity of the copied data whenever the user updates their information.
You can then look at the usage of your app and determine how often users change their information vs how often you would need to retrieve full users if you don't copy the data to find the cheapest method for your application.

Firebase authorisation and registration

I am trying to create a basic app for my small educational business.
We supply English teachers to schools and I want a way for parents to access the progress reports and other data about their children.
I'm using Android Studio and Flutter as well as Firebase to store the data. I don't want parents to be able to access the data of every child, obviously, but they may have more than one child at the school.
So I need to limit their read privileges to just the records that relate to their children. I'd like to do that by giving them some sort of registration code that they could use the first time they access the app so that we can ensure that they are only being given access to the correct records. Subsequent logins would then be via email and password.
Is there a way to do this with Firebase?
Your use-case sounds feasible, but it is really broad which makes it impossible to answer it completely-yet-succinctly.
Specific on what to do with the registration code that associates a parent with their children, when you generate the registration code, you write that code and the associated children to a database. Then when the parent registers with that code, you associate their account (UID) with the code. You'll just have to ensure that the code is sufficiently long and random that it can't be reasonably guessed by another user.

Can Firebase Realtime Database effectively loop through billions of posts and retrieve them by the users that posted them?

I am developing an iOS app with Firebase Realtime Database. The app will potentially have billions of posts with a number of images and data that needs to be retrieved based on the people a specific user follows (something like Instagram).
I understand that the best practice in Firebase is to structure data as flat as possible which would mean having a "Posts" node with potentially billion of entries, which I would then filter by a kind of 'posted_by' parameter. This begs two questions:
1) Will I be able to retrieve said posts with a query that returns posts by any of the users I follow? (By passing something like an array of the users I follow)
2) Will Firebase be effective enough to loop through potentially billions of posts to find the ones that match my criteria, or is there otherwise a better way to structure data so as to make the app as optimal as possible?
Thanks in advance for the answers.
Billions of entries are no problem.
You should check if Firebase is the most cost efficient solution if you have huge volume of data.
1) Firebase can do that, but you probably don't want the user to wait for all entries (when there are a lot for a single user), but instead request them "page" by "page" and only request more pages on demand when the user scrolls up/down.
2) If you ensure you have an index on the user id, then it doesn't have to go through each one individually. Searching by index is efficient.

How can Firebase nodes be structured to restrict user access and allow admin to pull report data?

Context: I am putting together a time tracking application using Firebase as my backend. My current node structure has Time Entries and Clients at the root like so:
Time Entry
Entry ID
UserID
clientID, hours, date, description, etc
Clients
ClientID
name, projects, etc
This structure works fine if I'm just adding and pulling time entries based on the user, but I want to start putting together reports on a per client basis. Currently, this means making a separate HTTP request for each user and then filtering by the clientID to get at the data.
The rule structure for Firebase grants access to all child nodes once access is given to the parent node, so one big list doesn't work as it can't restrict users from seeing or editing each other's entries.
Question: Is there a way to structure the nodes that would allow for restricting users to only managing their own time entries, as well as allow for one query to pull all entries tied to a client?
** The only solution I could come up with was duplicating the entries into a single node used just for reporting purposes, but this doesn't seem like a sustainable option
#AL. your answer was what I went up going with after scouring the docs across the web. Duplicating the data is the best route to take.
The new Firestore beta seems to provided some workarounds to this.
The way that I would do this is with Cloud Firestore.
Create a root collection clients and a document for each client. This partitions the data into easily manageable chunks, so that a client admin can see all data for their company.
Within the client document, create a sub-collection called timeEntries. When a user writes to this, they must include a userId field (you can enforce this in the rules) which is equal to request.auth.uid
https://firebase.google.com/docs/firestore/security/rules-conditions#data_validation
You can now create read rules which allow an admin to query any document in the timeEntries sub-collection, but an individual user must query with userId = request.auth.uid in order to only return the entries that they have created.
https://firebase.google.com/docs/firestore/security/rules-conditions#security_rules_and_query_results
Within your users/{uid} collection or clients/{clientId} collection, you can easily create a flag to identify admin users and check this when reading data.
https://firebase.google.com/docs/firestore/security/rules-conditions#access_other_documents

Allow users to see each other's data in firebase

Is there a why to let two user login with their own email and password and see the same data?
(Maybe one user well login and be transferred to the other user that has all the data).
Thanks,
Zvi Karp
What you were trying to do is about Database Design, it's actually not about Firebase. (watch out: the link is about relational database design, but Firebase is not using relational database. The idea is the same though.)
There are many ways to achieve your goal. Since you didn't describe your question clearly, I'll just give a general solution:
add a key sahredData to your User entity, and the value of this key is the id of the data you want to share between users. Different users can use the same value in this field(which means they share the same data).
whenever a user needs to access the shared data, use the value of sharedData, which is the id of the shared data, to access the data.

Resources