Changed my firebase rules, to allow user data to be stored, however it did not work. I am also working with stripe. I’ve included firebase rules, my login component and initializing firebase in my app.
Every time I press signup button, I get that error in the title.
Firebase Rules:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /customers/{uid} {
allow read, write: if request.auth.uid == uid;
match /checkout_sessions/{id} {
allow read, write: if request.auth.uid == uid;
}
match /subscriptions/{id} {
allow read: if request.auth.uid == uid;
}
match /payments/{id} {
allow read: if request.auth.uid == uid;
}
match /users/{userId} {
allow read, write: if request.auth.uid == userId;
}
}
match /products/{id} {
allow read: if true;
match /prices/{id} {
allow read: if true;
}
match /tax_rates/{id} {
allow read: if true;
}
}
}
}
Login component:
import {
closeLoginModal,
closePasswordModal,
closeSignupModal,
openLoginModal,
openPasswordModal,
openSignupModal,
} from "@/redux/modalSlice";
import { faUser, faXmark } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import Modal from "@mui/material/Modal";
import { useDispatch, useSelector } from "react-redux";
import {
browserLocalPersistence,
createUserWithEmailAndPassword,
onAuthStateChanged,
setPersistence,
signInWithEmailAndPassword,
} from "firebase/auth";
import { db } from "@/firebase";
import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { getAuth, GoogleAuthProvider, signInWithPopup } from "firebase/auth";
import { app } from "@/firebase";
import { doc, setDoc } from "firebase/firestore";
export default function LoginModal() {
// Modal
const isLoginOpen = useSelector((state) => state.modals.loginModalOpen);
const isSignupOpen = useSelector((state) => state.modals.signupModalOpen);
const isPasswordOpen = useSelector((state) => state.modals.passwordModalOpen);
// Firebase
const auth = getAuth();
const provider = new GoogleAuthProvider();
const dispatch = useDispatch();
const router = useRouter();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [loginError, setLoginError] = useState("");
const handleSignup = async (e) => {
e.preventDefault();
console.log("called");
console.log(email);
try {
console.log("success");
await setPersistence(auth, browserLocalPersistence);
const userCredentials = await createUserWithEmailAndPassword(
auth,
email,
password
);
// await createUserWithEmailAndPassword(auth, email, password);
const user = userCredentials.user;
console.log(user);
if (user) {
await setDoc(doc(db, "users", user.uid), {
email: user.email,
uid: user.uid,
});
setLoginError("");
console.log("loggedIn");
goToForYouPage();
}
} catch (error) {
setLoginError("Wrong email or password. Please try again.");
alert(error);
console.error("error", error);
}
};
const handleLogin = async (e) => {
e.preventDefault();
try {
await setPersistence(auth, browserLocalPersistence);
// await signInWithEmailAndPassword(auth, email, password);
const userCredentials = await signInWithEmailAndPassword(
auth,
email,
password
);
const user = userCredentials.user;
if (user) {
await setDoc(doc(db, "users", user.uid), {
email: user.email,
uid: user.uid,
});
setLoginError("");
console.log("loggedIn");
goToForYouPage();
}
} catch (error) {
setLoginError("Wrong email or password. Please try again.");
alert(error);
}
};
const handleGoogleLogin = async () => {
const result = await signInWithPopup(auth, provider);
const user = result.user;
if (user) {
goToForYouPage();
}
};
const handleGuestLogin = async () => {
e.preventDefault();
try {
await setPersistence(auth, browserLocalPersistence);
const userCredentials = await signInWithEmailAndPassword(
auth,
"guestuser@guest.com",
"123456"
);
const user = userCredentials.user;
if (user) {
await setDoc(doc(db, "users", user.uid), {
email: user.email,
uid: user.uid,
});
}
goToForYouPage();
} catch (error) {
setLoginError("Wrong email or password. Please try again");
alert(error);
}
};
const goToForYouPage = () => {
router.push("/for-you");
};
// useEffect(() => {
// const unsubscribe = onAuthStateChanged(auth, (currentUser) => {
// console.log(currentUser);
// });
// // Make sure to unsubscribe when the component unmounts
// return unsubscribe;
// }, []);
return (
<>
JSX
</>
);
}
Firebase setup:
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
import { getAuth } from "firebase/auth";
const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
};
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const db = getFirestore(app);
export { db, auth };
>Solution :
You have this operation to write to Firestore:
await setDoc(doc(db, "users", user.uid), {
email: user.email,
uid: user.uid,
});
So this writes a document with the current use’s UID to a top-level collection named users
.
If we look at your security rules however, the only place where you grant access to a users
collection is nested under a collection called customers
.
To allow writing to the top-level users
collection, pull up that rule or create a new top-level match /users/{userId}
rule similar to the ones you already have for customers
, products
, prices
and tax_rates
.