EN VI

Javascript - ERROR Error uploading profile picture: [FirebaseError: Missing or insufficient permissions.]?

2024-03-09 23:00:15
How to Javascript - ERROR Error uploading profile picture: [FirebaseError: Missing or insufficient permissions.]

I’m developing a React Native app using Expo and attempting to upload a profile picture to Firebase Storage using Expo’s ImagePicker. The app allows users to take a photo or choose one from their library and then upload the selected image to Firebase Storage.

However, I’m encountering a FirebaseError: Missing or insufficient permissions error when attempting to upload the image. The error occurs in the uploadImageToStorage function, specifically when calling uploadBytesResumable to upload the image to Firebase Storage.

    const handleTakePhoto = async () => {
        const { status } = await ImagePicker.requestCameraPermissionsAsync();
        if (status !== "granted") {
            alert("Sorry, we need camera roll permissions to make this work!");
            return;
        }

        const result = await ImagePicker.launchCameraAsync({
            mediaTypes: ImagePicker.MediaTypeOptions.Images,
            allowsEditing: true,
            aspect: [1, 1],
            quality: 0.2,
        });

        if (result.canceled) {
            // Handle cancellation
        } else if (result.type === 'dismissed') {
            // MainActivity was destroyed, get the pending result
            const pendingResult = await ImagePicker.getPendingResultAsync();
            if (!pendingResult.cancelled) {
                uploadImageToStorage(pendingResult.assets[0].uri);
            }
        } else {
            uploadImageToStorage(result.assets[0].uri);
        }
    };

    const handleChooseFromLibrary = async () => {
        const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
        if (status !== "granted") {
            alert("Sorry, we need camera roll permissions to make this work!");
            return;
        }

        const result = await ImagePicker.launchImageLibraryAsync({
            mediaTypes: ImagePicker.MediaTypeOptions.Images,
            allowsEditing: true,
            aspect: [1, 1],
            quality: 0.2,
        });

        if (!result.canceled) {
            uploadImageToStorage(result.assets[0].uri);
        }
    };

    const uploadImageToStorage = async (uri) => {
        const user = auth.currentUser;
        const imageName = `profile-picture-${user.uid}`;
        const response = await fetch(uri);
        const blob = await response.blob();
        const storageRef = ref(
            storage,
            `users/${user.uid}/profilePictures/${imageName}`
        );

        try {
            const snapshot = await uploadBytesResumable(storageRef, blob);
            const downloadURL = await getDownloadURL(snapshot.ref);

            // Update profile and database with the new photoURL
            await updateProfile(user, { photoURL: downloadURL });
            await updateDoc(doc(db, "users", user.uid), { photoURL: downloadURL });

            // Update the profile picture state and close the modal
            setProfilePic(downloadURL);
            addProfilePicModalRef.current.close();
        } catch (error) {
            console.error("Error uploading profile picture: ", error);
        }
    };

    const handleDeleteProfilePic = async () => {
        const user = auth.currentUser;
        const storageRef = ref(
            storage,
            `users/${user.uid}/profilePictures/profile-picture-${user.uid}`
        );
        try {
            await deleteObject(storageRef);
            await updateProfile(user, { photoURL: null });
            await updateDoc(doc(db, "users", user.uid), { photoURL: null });
            setProfilePic(null);
        } catch (error) {
            console.error("Error deleting profile picture: ", error);
        }
    };

Firebase security rules

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /profile/{userId}/profile-pic/{allPaths=**} {
      allow read: if request.auth != null;
      allow write: if request.auth != null && request.auth.uid == userId;
    }
  }
}

Solution:

Your security rules path doesn't match the path in the app code. Here is the pattern your rules allow:

match /profile/{userId}/profile-pic/{allPaths=**} {

Here is the pattern in your code:

`users/${user.uid}/profilePictures/${imageName}`

"profile" is not the same as "users", and "profile-pic" is not the same as "profilePictures", so the rule will reject the upload.

Answer

Login


Forgot Your Password?

Create Account


Lost your password? Please enter your email address. You will receive a link to create a new password.

Reset Password

Back to login