I'm attempting to allow each user read and write their own data using firestore, but I'm getting an insufficient permissions error. I'm not sure why.
I have these rules in place for my firestore...
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{uid} {
allow create: if request.auth != null;
allow read, write, update, delete: if request.auth != null && request.auth.uid == uid;
}
}
}
In my project, I have my service that uses the following function to push the data to angular firebase (yes, it's pretty lengthy)...
constructor(private afs: AngularFirestore){}
addToOrders(artist: string, formInput: AlbumInput) {
const currentUser = this.authService.currentUser; // uses a getter function to obtain the current user
const trackingUrl = 'https://tools.usps.com/go/TrackConfirmAction_input?strOrigTrackNum=';
const newOrder: Order = {
artistName: artist,
album: formInput.selectedAlbum.name,
image: formInput.selectedAlbum.images[0].url,
orderType: formInput.orderType,
trackingUrl: trackingUrl,
variant: formInput.variant
}
if (formInput.orderType === "shipped") {
newOrder.trackingNum = formInput.trackingNum;
return of(this.afs.doc(`users/${currentUser.uid}`).collection('shipped').add(newOrder))
.subscribe({
next: (() => {
this.albumAdded$.next(true);
}),
error: (() => {
this.albumAdded$.next(false);
})
});
} else {
newOrder.date = formInput.date;
return of(this.afs.doc(`users/${currentUser.uid}`).collection('preordered').add(newOrder))
.subscribe({
next: (() => {
this.albumAdded$.next(true);
}),
error: (() => {
this.albumAdded$.next(false);
})
});
}
}
Is there anything I'm missing in this pattern that would cause such an error?
If I change the rules to users/${user=**}, it does successfully store the data into the users subcollections, but now I can't sign in normally (for some reason, I can sign up despite the methods being nearly identical). Here is my sign in...
signIn(signInForm: SignInForm) {
return this.afAuth.signInWithEmailAndPassword(signInForm.email, signInForm.password)
.then((result) => {
this.isUserData.next(true);
this.setUserData(result.user!)
.then(() => {
this.router.navigateByUrl("/home");
});
}).catch(error => {
this.errorModal(error); // Modal Generic launches to inform the user
});
}
set user data...
setUserData(user: User) {
const userRef: AngularFirestoreDocument<any> = this.afs.doc(`users/${user.uid}`);
const userData: User = {
uid: user.uid,
email: user.email,
displayName: user.displayName
}
return userRef.set(userData, {
merge: true
});
}
This rule:
match /users/{uid} {
Allows a user to read their own profile document. It does not allow them to read subcollections under there, which is what you do in this code:
of(this.afs.doc(`users/${currentUser.uid}`).collection('shipped').add(newOrder))
to allow a user to also read all subcollections of their profile document, use a recursive wildcard (**
):
match /users/{uid=**} {