PinataCloud / pinata

The new Pinata SDK
https://docs.pinata.cloud/sdk
MIT License
8 stars 4 forks source link

Authentication failed: {"error":"not authenticated"} #42

Closed Boby900 closed 1 month ago

Boby900 commented 1 month ago

when I am trying to get the group details, I am getting an error that not authenticated

"use client";

import { useState } from "react";
import { pinata } from "../../utils/config";
import Image from "next/image";

export default function Home() {
  const [file, setFile] = useState<File>();
  const [url, setUrl] = useState("");
  const [uploading, setUploading] = useState(false);

  const uploadFile = async () => {
    if (!file) {
      alert("No file selected");
      return;
    }

    try {
      setUploading(true);
      try {
        const groups = await pinata.groups.get({
          groupId: "019284a8-2202-7e10-b799-6e74ace4b3da",
        });
        console.log("Groups fetched successfully:", groups);
      } catch (e) {
        console.error("Error fetching groups:", e);
      }
      const keyRequest = await fetch("/api/key");
      const keyData = await keyRequest.json();

      const upload = await pinata.upload.file(file).key(keyData.JWT);
      const urlRequest = await fetch("/api/sign", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ cid: upload.cid }),
      });
      const url = await urlRequest.json();
      console.log("Raw url from /api/sign:", url);

      setUrl(url);

      setUploading(false);
    } catch (e) {
      console.log(e);
      setUploading(false);
      alert("Trouble uploading file");
    }
  };

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setFile(e.target?.files?.[0]);
  };

  return (
    <main className="w-full text-lg min-h-screen m-auto flex flex-col justify-center items-center">
      <input type="file" onChange={handleChange} />
      <button disabled={uploading} onClick={uploadFile}>
        {uploading ? "Uploading..." : "Upload"}
      </button>
      {url ? (
        <Image height={700} width={500} src={url} alt="Image" />
      ) : (
        <p>Loading image...</p>
      )}
    </main>
  );
}

Screenshot (652)

stevedylandev commented 1 month ago

Hey Boby! This is likely due to your PINATA_JWT not being a NEXT_PUBLIC variables, which prevents it from being processed client side. The upload works because you are using the .key() method with the upload and passing in the temporary key.

One solution would be to move the group creation to a new API endpoint and return the group info to be used in the upload.

Another option which hasn't been fully documented yet is running pinata.setNewJwt() with a temporary key passed in, but I think that will cause more problems then less.

We could also look into extending the key method into other classes like groups. Would love to hear your use case for it!

Boby900 commented 1 month ago

@stevedylandev thanks Will try out these work arounds

Boby900 commented 1 month ago

thanks, @stevedylandev , it worked. I have created an API endpoint for getting the group details, using the GET function, and then fetched it in another components.

stevedylandev commented 1 month ago

Excellent! I'll go ahead and close this out for now but will look into some of the other possibilities I mentioned earlier.

Boby900 commented 1 month ago

hey, @stevedylandev , I am now able to get the group info but how will I be able to make my images as a publicly available/ when I upload images using the upload button it should be stored in that group. and then how will I fetch the images from that group?

"use client";

import { useState } from "react";
import { pinata } from "../../utils/config";
import Image from "next/image";

export default function Home() {
  const [file, setFile] = useState<File>();
  const [url, setUrl] = useState("");
  const [uploading, setUploading] = useState(false);

  const uploadFile = async () => {
    if (!file) {
      alert("No file selected");
      return;
    }

    try {
      setUploading(true);
      const groupData = await fetch("/api/group")
      const groupJson = await groupData.json(); // Await the Promise
      console.log(groupJson.id);
      const keyRequest = await fetch("/api/key");
      const keyData = await keyRequest.json();

      const upload = await pinata.upload.file(file).key(keyData.JWT);
      const urlRequest = await fetch("/api/sign", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ cid: upload.cid }),
      });
      const url = await urlRequest.json();

      setUrl(url);

      setUploading(false);
    } catch (e) {
      console.log(e);
      setUploading(false);
      alert("Trouble uploading file");
    }
  };

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setFile(e.target?.files?.[0]);
  };

  return (
    <main className="w-full text-lg min-h-screen m-auto flex flex-col justify-center items-center">
      <input type="file" onChange={handleChange} />
      <button disabled={uploading} onClick={uploadFile}>
        {uploading ? "Uploading..." : "Upload"}
      </button>
      {url ? (
        <Image height={700} width={500} src={url} alt="Image" />
      ) : (
        <p>Loading image...</p>
      )}
    </main>
  );
}
stevedylandev commented 1 month ago

If you want to list the files in a group you can use the group filter method on the SDK: https://docs.pinata.cloud/sdk/files/list#group

Or use the query param on the API: https://docs.pinata.cloud/api-reference/endpoint/list-files

Once you have the cid of a file you want to retrieve, and it is indeed public by being in a public group, you can retrieve it through the gateway like so:

https://example.mypinata.cloud/files/{cid}
Boby900 commented 1 month ago

thanks @stevedylandev for your help, but I was trying to ask, how I would make sure that if I am uploading any file using the upload button it should be directly stored in the group, whose details I am fetching using an API.

   const groupData = await fetch("/api/group")

my group doesn't have any images yet

Screenshot (654)

Screenshot (653)

Boby900 commented 1 month ago

I got this working, by adding

 const groupData = await fetch("/api/group")
      const groupJson = await groupData.json(); // Await the Promise
      console.log(groupJson.id);
      const keyRequest = await fetch("/api/key");
      const keyData = await keyRequest.json() 

      const upload = await pinata.upload.file(file).group(groupJson.id).key(keyData.JWT);