2
votes

In my React app, I've main three functionality which is connected to firebase. firebase auth, real-time chat, and this third one require firebase storage. I want to upload images with chat messages. when I try to upload images, the console gives me this error when I try to console.log(url)
I want to get that downloaded image url and store it in my firestore database and then use that url inside my Message.js component. console shows me this error


My Chat.js component

  const [messages, setMessages] = useState([]);
  const [assets, setAssets] = useState(null);

  useEffect(() => {
    if (channelId) {
      db.collection("channels")
        .doc(channelId)
        .collection("messages")
        .orderBy("timestamp", "desc")
        .onSnapshot((snapshot) => {
          setMessages(snapshot.docs.map((doc) => doc.data()));
        });
    }
  }, [channelId]);

  const sendMessage = (e) => {
    e.preventDefault();
    const uploadTask = storage.ref(`assets_discord/${assets.name}`).put(assets);
    uploadTask.on("state_changed", () => { 
      storage
        .ref("assetsdiscord")
        .child(assets.name)
        .getDownloadURL()
        .then((url) => {
          db.collection("assetUrl").add({
            imgUrl: url,
          });
          console.log(url);
          setAssets(null);
        });
      });
      db.collection("channels").doc(channelId).collection("messages").add({
        user: user,
        message: input,
        timestamp: firebase.firestore.FieldValue.serverTimestamp(),
      });
      
    setInput("");
  };

  const hideInput = (e) => {
    e.preventDefault();
    setShowInput(!showInput);
  };

  return (
    <div className="chat">
      {channelId ? (
        <>
          <ChatHeader channelName={channelName} />
          <div className="chat__messages">
            {messages.map((message) => (
              <Message
                user={message.user}
                message={message.message}
                timestamp={message.timestamp}
                assetUrl={message.imgUrl}
              />
            ))}
          </div>
          <div className="chat__input">
            {showInput ? (
              <>
                <form action="#">
                  <label htmlFor="imgFiles" className="upload__img">
                    <AddCircle fontSize="large" />
                  </label>
                  <input
                    type="file"
                    id="imgFiles"
                    className="hidden"
                    accept="image/*"
                    onChange={(e) => {
                      if (e.target.files[0]) {
                        setAssets(e.target.files[0]);
                      }
                    }}
                  />
                  <input
                    disabled={!channelId}
                    value={input}
                    onChange={(e) => setInput(e.target.value)}
                    type="text"
                    placeholder={`Send Message to #${channelName}`}
                  />
                  <button
                    onClick={sendMessage}
                    className="chat__inputButton"
                    type="Submit"
                  >
                    Send Message
                  </button>
                  <button onClick={hideInput}>Hide</button>
                </form>
              </>
            ) : (
              <p
                onClick={() => setShowInput(!showInput)}
                className="show__input"
              >
                Show
              </p>
            )}
          </div>
        </>
      ) : (
        <>
          <div className="chat__selectRoom">
            <ArrowLeftIcon
              style={{ fontSize: "30px" }}
              className="arrow__left"
            />
            <h3>Select Any Room to get Started</h3>
          </div>
        </>
      )}
    </div>
  );

Message Component

const Message = ({ user, timestamp, message, assetUrl }) => {
  // console.log(assetUrl);
  return (
    <div className="message">
      <Avatar src={user.photo} />
      <div className="message__info">
        <h4>
          {user.displayName}
          <span className="message__timestamp">
            {new Date(timestamp?.toDate()).toUTCString()}
          </span>
        </h4>
        <p>{message}</p>
        {/*
         <ImageUpload assetUrl={assetUrl} /> 
       */}
        <img src={assetUrl} alt="dummy" />
      </div>
    </div>
  );
};

firebase sequrity rules

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write;
    }
  }
}
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if true;
    }
  }
}

Link to live website

1
Check the address for the file if it is wrong. It is for sure that the file does not exist, check what url you are fetching from the api.Vijay
Yes it's saying file doesn't exist when I click on the firebase api URL, the url that I'm fetching api is also hosted on firebase but I am using netlify link for production. You are saying I should check my firebase url?Jeet Viramgama
Yes, check the url you are getting and download the file manually. At least you can know where is the problem, in firebase rules or in your code.Vijay
I visited the console error url but it shows me object this object: { "error": { "code": 403, "message": "Permission denied. Could not perform this operation" } } I don't understand what's wrong?Jeet Viramgama
We got it, the problem is in the firebase rules. Google provides security rules by which we can control people to access our firebase storage. I am posting an answer, please check it.Vijay

1 Answers

3
votes

Go to the firebase console then select the project you are working on then go to storage then rules.

enter image description here

If you are using firestore or database then check the rules. Another problem can be that you have not added the SHA of your project. We are allowing everyone to change the storage means public access.

In your case, as you commented, the problem can be security access. Here is a link to google documenations

I would suggest you read documentation before using any platforms like Amazon AWS, firebase, or any type of API.

Another CHeck - Check the address of the files, I rechecked the error. Your security rules are correct, I think you should use some samples from documentations.