Firebase query with simple login - firebase

I am trying to query firebase where I have used simple login to differentiate between users. As such firebase looks like this:
users/simplelogin:*/favouritecolour
favouritecolour looks like {0: blue, 1: red, 2: green}
I want to be able to query for all users with the same favouritecolour and send their profile information back to be displayed on the web page.
users/simplelogin:*/profileinformation
The problem I have is that simple login uses authData.uid for "simplelogin:*" and as such it is different for each user. I want to look through all users. I am not sure how to reference the path to just the favouritecolour for each user, as when querying I don't want to have to search the entire database. I have looked for a wildcard token to use in the path name. I have also looked at relative path definitions, where one may be able to skip over branches in a path. No luck. What code do I need to write to return profileinformation as a snapshot for all profiles matching favouritecolour red?
Thanks for your help.

You need to organize data according to how they are going to be accessed, not according to how "it makes sense" in traditional relational DB. This also includes data duplication and non-normalization.
Take a look at this.
So, you also need to keep something like this:
/favouritecolor/{color}/ --> { user1, user2, user3 }

Related

Request.auth.metadata in security rules?

I have a Firebase project where I'd like for users to be able to see when other users created their profiles. My initial hope was that I could use "user.metadata.creationTime" on the frontend to pass the date into the user's extra info document and verify that it is correct by having "request.resource.data.datecreated == request.auth.metadata.creationTime" as a Database Rule, but it looks like it is not possible according to the documentation.
Is there any way I can verify that the creation date is correct on the backend?
More info edit: Below is the code that is being triggered when a user creates a new account on my profile. The three values are displayed publicly. I'm creating a niche gear for sale page so being able to see when a user first created their account could be helpful when deciding if a seller is sketchy. I don't want someone to be able to make it seem like they have been around for longer than they have been.
db.collection('users').doc(user.uid).set({
username: "Username-156135",
bio: "Add a bio",
created: user.metadata.creationTime
});
Firestore rules:
match /users/{id} {
allow get;
allow create, update: if request.resource.data.username is string &&
request.resource.data.bio is string &&
request.resource.data.created == request.auth.metadata.creationTime;
}
user.metadata.creationTime, according to the API documentation is a string with no documented format. I suggest not using it. In fact, what you're trying to do seems impossible since that value isn't available in the API documentation for request.auth.
What I suggest you do instead is use a Firebase Auth onCreate trigger with Cloud Functions to automatically create that document with the current time as a proper timestamp. Then, in security rules, I wouldn't even give the user the ability to change that field, so you can be sure it was only ever set accurately by the trigger. You might be interested in this solution overall.

Firebase/Google Cloud Storage how to store the image

I have a Firestore that has a User Document. When a User uploads a profile image to the bucket I resize it in the Cloud Function and then save the smaller thumbnail of it. Now I am not sure what the best practice is to receive the Download URL for it, there are 2 possibilities:
In the Cloud Function get a Signed URL and store it in the Users Document or
Get the download url on the frontend with the .getDownloadUrl() method.
The problems I have with either solution is
1: The URL is really big, getting multiple Users on a Page this adds up in more size than the actual rest of the User Document
2: In terms of speed im not sure if its the best to loop through a list of Users to get each's thumbnail download URL, but the advantage is I do not have to deal with normalizing the new Profile Pic URL one every occurrence in the database.
The URL is not that that big. Before trying to optimize, first collect some clear benchmarks that suggest the size of the URL is seriously impacting the performance of the page. Don't optimize this if it doesn't need it. I've never heard of anyone complaining that a download URL is bad for performance.
You don't need to loop over all users. You should arrange to have the UID of the user available at the time of the resize, so you can update the correct user. You can put the UID in the path of the file upload and parse it out, or you can put the UID in object metadata at the time of the upload.
Either approach is valid, though. Pick the one that suits you the best. Generating it on the backend is probably more resilient to errors.
As Doug Stevenson mentioned in his answer, I also think you are trying to optimize something that's not even a performance or storage problem. However, if you still want to optimize the size of your URL, I have two solutions for you.
As we already know, the URL of a picture looks similar to this:
https://firebasestorage.googleapis.com/v0/b/project-id/o/images_folder%2vvTMvCsCRsckpR3R5Qg2s.jpg?alt=media&token=2277f575-8ff7-2211-8262-a28ef679d703
So the first solution would be to shorten the links using a service like tiny.cc. There are also other examples but I think you get the idea. So in case of the URL above, after you shorten it, will look like this:
http:// tiny.cc /2r4ucz
The second solution requires the saving two things in your database. It is not about shorten the link, it's about storing less data. So as you can see, the URL above is combined from a "BASE_URL":
https://firebasestorage.googleapis.com/v0/b/project-id/o/images_folder
Which includes the name of your project and the name of the folder where you store the images. It also contains the name of the image, which in my case is an id that is generated by Firestore and it's by definion unique. And the last part is the token id:
2277f575-8ff7-2211-8262-a28ef679d703
So the second solution would be to store in your database only the id of the image and the token and then reconstruct the entire URL client side. So in the example above the only things that you should store are:
Firestore-root
|
--- users (collection)
|
--- uid (document)
|
--- id: vvTMvCsCRsckpR3R5Qg2s
|
--- token: 2277f575-8ff7-2211-8262-a28ef679d703
|
--- //Other user details
If your user will always have a single picture then you can use instead of that random id, the uid that is coming from the authentication processs:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();

Firebase Storage : Get the token of the URL

I currently have an application that works with Firebase.
I repeatedly load profile pictures. However the link is quite long, it consumes a certain amount of data. To reduce this load, I would like to put the link in raw and only load the token that is added to the link.
To explain, a link looks like this: “https://firebasestorage.googleapis.com/v0/b/fir-development.appspot.com/o/9pGveKDGphYVNTzRE5U3KTpSdpl2?alt=media&token=f408c3be-07d2-4ec2-bad7-acafedf59708”
So I would like to put in gross: https://firebasestorage.googleapis.com/v0/b/fir-developpement.appspot.com/o/
In continuation: “9pGveKDGphYVNTzRE5U3KTpSdpl2” which is the UID of the user that I recover already and the or my problem this poses: “alt = media & token = f408c3be-07d2-4ec2-bad7-acafedf59708” which adds randomly for each photo .
I would like to get back only this last random piece …
Is it possible ?
Thank you
UP : 01/11 Still no solution
It's not supported to break apart and reassemble download URLs. You should be treating these strings as if their implementation details might change without warning.

Meteor: Single-Document Subscription

Whenever I encounter code snippets on the web, I see something like
Meteor.subscribe('posts', 'bob-smith');
The client can then display all posts of "bob-smith".
The subscription returns several documents.
What I need, in contrast, is a single-document subscription in order to show an article's body field. I would like to filter by (article) id:
Meteor.subscribe('articles', articleId);
But I got suspicious when I searched the web for similar examples: I cannot find even one single-document subscription example.
What is the reason for that? Why does nobody use single-document subscriptions?
Oh but people do!
This is not against any best practice that I know of.
For example, here is a code sample from the github repository of Telescope where you can see a publication for retrieving a single user based on his or her id.
Here is another one for retrieving a single post, and here is the subscription for it.
It is actually sane to subscribe only to the data that you need at a given moment in your app. If you are writing a single post page, you should make a single post publication/subscription for it, such as:
Meteor.publish('singleArticle', function (articleId) {
return Articles.find({_id: articleId});
});
// Then, from an iron-router route for example:
Meteor.subscribe('singleArticle', this.params.articleId);
A common pattern that uses a single document subscription is a parameterized route, ex: /posts/:_id - you'll see these in many iron:router answers here.

Firebase auto generated UID changed?

I am using firebase for login and auth, and was using $createUser. For the first couple weeks working on my app the users I created were being generated with an UID like 'simplelogin:83'. Today, I am working on my app and users are being created with an UID that looks more like a GUID. Did something change on firebases' end? Can I control how that gets generated?
The format has indeed changed from <provider>:<id> into a single opaque UUID. For more information see this post where the change was announced.
There is no way for you to control the format of the user ids for your app. If you're having trouble adapting your code to the new format, reach out to support#firebase.com.

Resources