Angular and firestore rules - javascript

I'm really new to Firebase and Firestore database.
I have an angular project and I use the angular/fire package to communicate with firebase.
I have created a user with user/password method and the call works perfectly.
try {
const user = await signInWithEmailAndPassword(this.auth, email, password);
return user;
} catch (e) {
return null;
}
After that I would like to store some data in the firestore db and all works fine
addVideoId(storageVideoId: StorageVideoIdModel) {
const notesRef = collection(this.firestore, 'videoIds');
return setDoc( doc(notesRef, '' + storageVideoId.date), storageVideoId );
}
After that comes the problem.
I applied a rule in the firestore console:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /videoIds/{id} {
allow read, write: if request.auth != null;
}
}
}
well... if I run the addVideoId function.... IT WORKS!
The playgroud tells me that the rule is valid and no operations are permitted, but If I run the addVideoId from angular code without log in, it works anyway....
I really don't understand how to pass that auth object in the rule...
I need some help because are 2 days that I'm stuck on it and I cannot find any example or tutorial that merge authentication with database rules.
Please help
Thanks

I think you want to define where the user has permission to write to, otherwise, your users can overwrite each other's data.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{userId}/videoIds/{id} {
allow read;
allow write: if request.auth != null && request.auth.uid == userId;
}
}
}
this will allow all users to read, but only write to their own collection.

Related

I get a missing permissions error in firebase even though I allow it to read

I am working on a react firebase project.
the error I am getting is
"FirebaseError: Missing or insufficient permissions."
Here is my code to get the data
const data = await getDocs(
query(collectionGroup(db, "posts"), orderBy("upvote", "desc"), limit(5)));
Here is my firebase security rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /posts/{docId}{
allow read;
allow update: if request.auth.uid != null;
}
}
}
I have no idea what is going on I allow read in firebase rules but when I go and get the data it does not work
You should check if in the Database under the rules if read: true and write: true if not make those true.
So go to DataBase-> Rules
make
Read:true
Write:true
But for production databases allow only for authenticated users

How safely show publicly UID of firestore sub-collection

I have the following firestore db structure (image 1). I want (unauthenticated) users of my web app to be able to see each plumber public profile which contains reviews (image 2) they get from the won jobs. My question is how could i safely expose UID of each user who has made one of those reviews. Hopefully my question makes sense.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
the ui i want to archive
If you want to allow users to read/write their own user document and allow anyone to read their reviews, try these rules:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, update: if request.auth.uid == userId;
match /reviews/{reviewId} {
allow read: if true;
allow write: if request.auth.uid == resource.data.userId
}
}
}
}
Here only the poster of review and write (update/delete) it and any unauthenticated users can read them. However they cannot access the User document.
You can read more about security rules in the documentation.

How to access all data in a firestore database with admin approval?

I am currently building a vuejs web app that uses firestore from firebase. The basic structure is a user fills out an application with data and then an admin can look at that data to see if they are eligible for funding. The problem that I am encountering is that when the admin requests the information from firestore, it only ever returns an empty array.
The admin tag is assigned using this firebase cloud function:
const admin = require('firebase-admin');
admin.initializeApp();
exports.addAdminRole = functions.https.onCall((data, context) => {
//get user and add custom claim (admin)
return admin.auth().getUserByEmail(data.email).then(user => {
return admin.auth().setCustomUserClaims(user.uid, {
admin: true
});
}).then(() => {
return {
message: `Success! ${data.email} has been made an admin`
}
}).catch(err => {
return err;
});
});
My firestore structure is as follows:
users
|_user1_uid
|_info
|_user2_uid
|_info
The call I am making to get the information is this:
db.collection('users')
.get()
.then(snapshot => {
console.log(snapshot.docs)
})
As you can see, the call is supposed to get a snapshot of all of the documents I have. (example: the console.log should show that I have three users > (3) [n, n, n]). However, what is returned instead is an empty array.
My firestore rules are this:
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, write: if request.auth.token.admin == true;
}
match /users/{userId}/{document=**} {
allow create: if request.auth != null;
allow read, write: if request.auth.token.admin == true;
allow read, write: if request.auth.uid == userId;
}
}
}
Any suggestions or pointers on why my admin is unable to get the users' information would be appreciated.
Thanks!
Ok, I figured out what was happening. When I start making my documents I was using this code:
db.collection('users').doc(this.uid)
.collection('info').doc('county').set({
county: this.county
)}
What I didn't realize is that this makes the document that holds this.uid to be virtual. If I had looked a little harder I would have seen this notification on firebase:
I found a relatively simple workaround which was first creating the UID document with dummy data before adding actual info to it like so:
db.collection('users').doc(this.uid).set({
dummy: 'dummy'
})
This fixed my problem. Thanks everyone for your help! I appreciate it!

Firestore rule to read collection

Firestore rule to read collection overrides document rule to deny unauthorized access of other users data.
Here's my scenario, I'm getting the user information with the phone number associated by the Authentication and the Document in the database. I'm querying the whole /users collection with where clause and in the Firestore Rules I'm letting anyone to read /users collection, but I think this is insecure.
Javascript
const phone_number = firebase.auth().currentUser.phoneNumber // Example: "+5521988887777"
const usersRef = firebase.firestore().collection('users')
usersRef.where("phone_number", "==", phone_number).limit(1).get()
.then(snapshot => {
const doc = snapshot.docs[0]
Firestore Rules
service cloud.firestore {
match /databases/{database}/documents {
match /users {
allow read;
}
match /users/{user} {
allow read, write: if request.auth != null && request.auth.token.phone_number == resource.data.phone_number;
}
}
}
I'm trying to achieve a workaround to the issue, thanks.
To correct the security rule I have removed the first condition to allow all reads (as commented above).
Working Firestore Rules
service cloud.firestore {
match /databases/{database}/documents {
match /users/{user} {
allow read, write: if request.auth != null && request.auth.token.phone_number == resource.data.phone_number;
}
}
}

Cloud Firestore with Authentication

I have been looking for a way to use Authentication with Firebase's new Cloud Firestore. I know it's possible, but there is no good guide both in the Documentation and other places.
Could someone please explain how to provide an Authentication UID when get()ing data from Cloud Firestore?
Here are my security rules:
service cloud.firestore {
match /users/{userID} {
allow read, write: if request.auth.uid == userID;
}
}
And here is my current code:
var db = firebase.firestore();
var docRef = db.collection("users").doc(uid); //lets say "uid" var is already defined
docRef.get().then(function(doc) {
if (doc.exists) {
console.log("Document data:", doc.data());
} else {
console.log("No such document!");
}
}).catch(function(error) {
console.log("Error getting document:", error);
});
The structure of my database is just a "users" collection at root, then a document for each user (named after the UID). I want to get the document with the user's UID.
Of course, this gives the error "Missing or insufficient permissions," which is expected, because of the security rules.
This question may seem simple, but if anyone can find some good documentation on this, that would be great!
I was just confused about how UIDs work. I was under the impression that you have to supply a UID and an auth token to database operation.
You don't actually pass in a UID to database operations. The firebase object stores authentication state. You can simply sign in (check the Firebase docs to read how to do this), and after the action is completed (use a .then promise statement) you can simply do your operation.
Additionally, to have users not sign in every time they visit your app, you can have the `firebase object's authentication state persistent.
Your rule should be inside match /databases/{database}/documents
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userID} {
allow read, write: if request.auth.uid == userID;
}
}
}

Categories

Resources