Firestore Database Rules for Authenticated User Email - java

Objective: The document of the user who is signed in should be accessible by the user.
Collection Structure :
> root(collection_name)
> user1#gmail.com(document_name)
> "name" : "User One"(field key and value)
> user2#gmail.com
> "name" : "User TWO"
Android Code I Used
db.collection("/root/")
.get()
.addOnCompleteListener(task -> {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : Objects.requireNonNull(task.getResult())) {
System.out.println(document.getId() + " => " + document.getData());
}
} else {
System.out.println(task.getException());
}
});
Database Rules I tried :
service cloud.firestore {
match /databases/{database}/documents {
match /root/{email} {
allow read, update, delete: if request.auth.token['email'] == email;
allow create: if request.auth != null;
}
}
}
Error I Get :
com.google.firebase.firestore.FirebaseFirestoreException: PERMISSION_DENIED: Missing or insufficient permissions.
Listen for Query(target=Query(root order by name);limitType=LIMIT_TO_FIRST) failed: Status{code=PERMISSION_DENIED, description=Missing or insufficient permissions., cause=null}
I also tried using
service cloud.firestore {
match /databases/{database}/documents {
match /root/{email} {
allow read, update, delete: if request.auth!=null;
allow create: if request.auth != null;
}
}
}
The above rule returns me all the documents in the collection but I only want it to return the document of the specific user who is signed in. So I know that the issue is in checking the email of the user.

When you are using the following rules:
match /root/{email} {
allow read, update, delete: if request.auth.token['email'] == email;
allow create: if request.auth != null;
}
It means that you allow only the authenticated user to read, update or delete data at the location you are pointing to, which is the user's document. However, in your code, you request data from the entire "root" collection:
db.collection("/root/").get()
Hence that error message. To solve this, you either change the query in your code, or you change the rules. But most likely you should change the way you are getting the data by using the following reference:
db.collection("root").document(userEmail).get().addOnCompleteListener(/* ... /*);

Related

How to check a phonenumber that already added to the firestore database?

Here in the Firestore databases is a collection called "Users", In that collection, there are 29 documents(States) and in each of that documents there are many collections(Districts). This collection includes many documents these documents include the user's data along with numbers).
so how do we check the phone number that has already been added to the database?
I write something like this
FirebaseFirestore firestore = FirebaseFirestore.getInstance();
CollectionReference usersRef = firestore.collection("Users");
String phoneNumber = "1234567890";
usersRef.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
Map<String, Object> data = document.getData();
for (String key : data.keySet()) {
Object value = data.get(key);
if (value instanceof String && ((String) value).equals(phoneNumber)) {
isRealAvailable = true;
Toast.makeText(OtpActivity.this, "Number found", Toast.LENGTH_SHORT).show();
// Phone number found
break;
}
}
}
} else {
isRealAvailable = false;
Toast.makeText(OtpActivity.this, "No number found, create an account!", Toast.LENGTH_LONG).show();
}
// Handle error
}
});
(the number is not a String value)
I don't know how to retrieve these details from different document names.
How do we get the Phone Number from the document? if it exists.
What I wanted is, I'm building a blood donors app, where people can register using their phone numbers. From different countries. So when a user sign-up with proper details, he can go to the main screen. Whenever he logout and login, he doesn't need to update the details again. As we know phone number login and signup are the same. Also, I want to separate the states and places in different documents and collections. I added the location permission and perspective codes so the country and states are chosen automatically. (will get the users location)
When you're calling get() on the following collection reference:
CollectionReference usersRef = firestore.collection("Users");
It means that you're trying to get all user documents that exist in the Users collection. As soon as you get all users, you then check the phoneNumber against the one that you find in the database, which is bad since you'll need to pay for a document read even for the users that do not have that particular phone number. What you have to do instead is to create a query that should only return the documents that you are interested in.
On the other hand, your actual database schema isn't quite helping you to achieve that. In the NoSQL world, we are usually structuring a database according to the queries that we want to perform. So if you need to get all users from Brooklyn / New York that have a particular phone number, I would recommend you have a schema that looks like this:
db
|
--- users (collection)
|
--- $uid (document)
|
--- city: "New York"
|
--- borough: "Brooklyn"
|
--- mobNumber: 720555
And in code, it should look like this:
FirebaseFirestore db = FirebaseFirestore.getInstance();
CollectionReference usersRef = db.collection("users");
Query queryByMobNumber = usersRef.whereEqualTo("city", "New York")
.whereEqualTo("borough", "Brooklyn")
.whereEqualTo("mobNumber", 720555);
queryByMobNumber.get().addOnCompleteListener(/* ... /*);
So in Firestore, chaining multiple whereEqualTo calls will work perfectly fine.
Besides that, I see that you are changing a boolean value inside the callback, which will not be seen outside the callback because Firebase API is asynchronous. If you want to learn more about that, I recommend you check this resource. Here is the corresponding repo.

I am trying to access the values of a particular key from the Firebase database.I want to update those values and update it

[This is my json dataThis is my code ][1]
I am trying to change the value of the key-value pair in the Firebase database.
Lets suppose I have a key value like this:"chemistry":"20".I want to extract the value of the key chemistry and want to update it after adding some number like I add 10 to it so my final key value pair will become "chemistry":"30" .But I am unable to access the key can someone help me with this.
My code goes here:
mAuth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
// Sign in success, update UI with the signed-in user's information
Log.d("TAG", "signInWithEmail:success");
//extracting the current user from the databse
FirebaseUser user = mAuth.getCurrentUser();
//getting the uid of the user
String Uid=user.getUid();
//getting the databse instance for the particular user
FirebaseDatabase database = FirebaseDatabase.getInstance();
//setting the path to the Users/Uid to read the key values
DatabaseReference myRef = database.getReference("Users/"+Uid);
//textView.setText(myRef);
String key=myRef.child("chemistry").getKey();
textView.setText(key);
// myRef.setValue("Hello, World!");
} else {
// If sign in fails, display a message to the user.
Log.w("TAG", "signInWithEmail:failure", task.getException());
Toast.makeText(TestActivity.this, "Authentication failed.",
Toast.LENGTH_SHORT).show();
//updateUI(null);
}
// ...
}
});
my json is here:
{
"Users" : {
"LMn5GeZixNQNpdQhGzdKNbTgIw53" : {
"chemistry" : "20",
"email" : "umairnsr87#gmail.com",
"lastScore" : "0",
"maths" : "0",
"name" : "umair",
"phone" : "123456789",
"physics" : "0"
}
}
}
In general, you should add some attempt code of what you are trying to achieve, so that others can better guide you to fix your problems. People is not supposed to write code for you.
Anyway, if your collection is called users. then you would retrieve a specific ID in this way:
db.collection("users").doc(THEID).get()
.then( data => {
console.log(data)
})
use .add(jsondata) and .set(jsondata) for ading and updating
here's the documentation:
https://firebase.google.com/docs/firestore/?gclid=CjwKCAjwm4rqBRBUEiwAwaWjjK7_CnO37twhvxrw2-WUxep6ykpTEaJiGnmojoBz74TNylodfkL7DxoCE9gQAvD_BwE
I am trying to change the value of the key-value pair in the firebase database.
In general when you want to update a value of a property, you should use DatabaseReference's updateChildren(Map update):
Update the specific child keys to the specified values.
Regarding the second issue:
Lets suppose I have a key value like this:"chemistry":"20".I want to extract the value of the key chemistry and want to update it after adding some number like I add 10 to it so my final key value pair will become "chemistry":"30"
Above, I showed you how you can simply update the value of a property, however, if you want to increment the value of your chemistry field in a multiuser environment, to have consistent data, I recommend you see my answer from this post, where I have explained how to update a score field using Firebase Transactions.

check nested key existence in video object in youtube-api to avoid NULLPOINTEREXCEPTION

I want to check the existence of nested key in Video object returned as a Json response from youtube video search by using below code:-
YouTube.Videos.List searchvideostats = youtube.videos().list("snippet,statistics");
searchvideostats.setKey(apiKey);
Video v = searchvideostats.execute().getItems().get(0);
System.out.println(v.toPrettyString());
I got output like this:-
{
"etag" : "\"m2yskBQFythfE4irbTIeOgYYfBU/-TONXAYMx_10Caihcoac4XCyb4I\"",
"id" : "4Aa9GwWaRv0",
"kind" : "youtube#video",
"snippet" : {
"categoryId" : "10",
...................
.........
MY goal is:- how to check whether categoryId key is present in this response or not. coz if do v.getSnippet().getCategoryId() it gives NullPointerException if categotyId is not present in Json.
Tried:-
if (v.containsKey("id")) {
System.out.println("contains");
} else {
System.out.println("doesnt contains");
}
this returns contains as expected.
if (v.containsKey("categoryId")) {
System.out.println("contains");
} else {
System.out.println("doesnt contains");
}
This returns doesnt contains.. which is not expected. How would I check if this nested key is available?
P.S. -> I have to check many nested such keys.
Thanks for help.
You don't need String manipulations. Just use Youtube library.
if(video.getSnippet()!=null && video.getSnippet().getCategoryId()!=null)
will do the stuff.
note: checking for zero length categoryid might be necessary also.

Get related data from pointer

I have simple data structure:
"Issue" has poiter to other class "Status" in field "status"
From doc we know include - take key name and pointed data should be avalible in result without any action. But then I try to access pointed data I get null.
ParseQuery<Issue> query = ParseQuery.getQuery("Issues");
query.include("status");
query.whereEqualTo("owner", user);
query.findInBackground(new FindCallback<Issue>() {
public void done(List<Issue> issueList, ParseException e) {
if (e == null) {
Log.d(TAG, "Retrieved " + issueList.size() + " issues");
ParseObject status = issueList.get(0).getParseObject("status"); //NULL!
} else {
Log.d(TAG, "Error: " + e.getMessage());
}
}
});
Manualy form console I can see valid data and jump from Issue to Status by pointer (I have only one record in both)
Parse lib version - 1.11
What I'm doing wrong?
I think it should work.. Check your security and ACL settings in Parse Status class (if you don't have the rights to get the status you won't get it), make sure issueList.get(0) is not null and make sure that the Status object you are pointing to really exist in Parse Status table.

How to get if a code exist in parse.com?

I have a problem, I have this structure in parse.com in "VerificationCode" db:
When someone inserts a code in my app, it automatically adds in the "attachedUser" column the id of the user who is stored locally and I call it "ParseInstallObject.codigo2" and I get the id of the user for example to see it in a textview, etc.
The problem is that I want to check if the user id exists in parse or not; and if it exists do something or if not exist do another thing.
I used a code that I see in the documentation of parse.com but it always shows that the code exists. This is my code:
ParseQuery<ParseObject> query2 = ParseQuery.getQuery("VerificationCode");
query2.whereEqualTo("attachedUser", ParseInstallObject.codigo2);
query2.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> scoreList, ParseException e) {
if (e == null) {
comprobar.setText("exist");
comprobar2.setText("exist");
} else {
comprobar.setText("no exist");
comprobar2.setText("no exist");
}
}
});
How can I see if the user has a valid code or not?
e==null means that the call was successfully completed by the server. It does not imply that the user exists or not.
if(e==null){
if(scoreList == null || scoreList.isEmpty()){
// The user does not exist.
}else{
// the user exists.
}
}else {
// You have an exception (like HTTPTimeout, etc). Handle it as per requirement.
}

Categories