简体   繁体   中英

Why is my firebase security rules not working as expected?

I want to allow users to edit their post on my app. They can edit their post if their uid matches the name of the folder in the storage.

Here is my security rules for my firebase storage:

在此处输入图像描述

it says I can delete the image if I want to (users/gafspL9sdVSOXVkxYNlqzxyDbvG2/listingPhotos/lXOxKS1N8dFefzai5H2B/R158bed9819e4fccf7e18a5eeeaf79c6b.png)

Then, when I try to edit said listing:

在此处输入图像描述

I get a 403 error. User it not authorized, in fact it throws this error at the GET function, not even the delete part.

As you can see above, I am currently logged in and my uid is correct.

Error: (xhrio_network.ts:70 GET mydomainname?prefix=users%2FgafspL9sdVSOXVkxYNlqzxyDbvG2%2FlistingPhotos%2FlXOxKS1N8dFefzai5H2B%2F&delimiter=%2F 403)

This is the folder I am trying to access:

在此处输入图像描述

My folder setup: mybucket/users/{userUID}/listingPhotos/{listingID}/picture.jpg

Any ideas what may be going wrong here guys? I may have an incorrect line of code, but the simulation says there's no problem, so I'm a bit confused.

Thank you!

EDIT

When a user wants to edit their listing, I update the listing details stored in firestore, then I delete all the photos stored in the firebase storage folder and then upload the new batch of photos.

Here is where I update listing details and delete the existing photos:

 function editListingData() {
    setLoading("loading");
    db.collection("listings")
      .doc(listingID)
      .set(
        {
          title: title,
          category: category,
          condition: condition,
          description: description,
          price: price,
          sellingFormat: sellingDetails,
          shippingPrice: shippingPrice,
          listingPhotos: [],
        },
        { merge: true }
      )
      .then(() => {
        const storageRef = firebase
          .storage()
          .ref()
          .child(
            `users/` +
            auth.currentUser.uid +
            `/listingPhotos/` +
            listingID +
            `/`
          );
        storageRef.listAll().then((listResults) => {
          const promises = listResults.items.map((item) => {
            console.log("deleting item: ", item.name)
            return item.delete();
          })
          Promise.all(promises).then(
            onUploadSubmission()
          ).catch((error => console.log("error deleteing files", error)));
        });
      })
      .then(() => {
        setLoading("complete");
        setTimeout(() => {
          history.push("/l/" + listingID)
        }, 2000);
      })
      .catch((error) => {
        console.log("firebase error: " + error);
        setLoading("error");
      });
  }

Here is where I upload the new photos and then put their downloadURL's into the firestore document, so I can get them easily later:

  function onUploadSubmission() {
    if (photos != []) {
      const promises = [];
      var listingREF = db.collection("listings").doc(listingID);
      photos.forEach((photo, index) => {
        if (photo.fileType.includes('image')) {
          console.log("current photo to upload: ", photo, "index: ", index)
          const uploadTask = firebase
            .storage()
            .ref()
            .child(
              `users/` +
              auth.currentUser.uid +
              `/listingPhotos/` +
              listingID +
              `/${"photo" + index}`
            )
            .put(photo.file);
          promises.push(uploadTask);
          uploadTask.on(
            firebase.storage.TaskEvent.STATE_CHANGED,
            (snapshot) => {
              const progress =
                (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
              if (snapshot.state === firebase.storage.TaskState.RUNNING) {
                console.log(`Progress: ${progress}%`);
              }
            },
            (error) => console.log(error.code),
            async () => {
              const downloadURL = await uploadTask.snapshot.ref.getDownloadURL();
              listingREF.update({
                listingPhotos: firebase.firestore.FieldValue.arrayUnion(
                  {
                    url: downloadURL,
                    index: index
                  }
                ),
              });
            }
          );
        }
      });
      Promise.all(promises)
        .then(() => setCreatedListing(false))
        .catch((err) => console.log(err.code));
    } else {

    }
  }

EDIT 2

So what I am trying to achieve is:

User can edit their own photos (listing photos and profile picture)

To do this, they will:

  1. Choose their new photo/s.
  2. When they click submit, firebase will delete the photos currently stored in firebase storage.
  3. It will then upload the new photo's the user selected earlier.
  4. The download URL's are then copied to the listing document in firestore so we can view them easily later

Security rules for storage are:

  • Anybody can read user photos (similar to eBay, you can see the listing photos whether you are logged in or not)
  • Users can write (delete, update, create) to their own folders only. Each folder is named after the user UID. They can only access those folders if the current logged in users UID matches the name of the folder in storage.

The error you are receiving on the get() method is due to the rules in that location lacking any permission to read in that directory. Rules cascade from top to bottom, while you have a read above, this only applies to the specified path users/{userUID}

Once that is solved, we can proceed to debug further.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM