Sorry, you might have to give me an example. I literally started learning to code last week haha. Think iāve done quite well to get this far tbh haha.
what does this code return when that if is not true?
Assuming if I put this in the right place (a big assumption) returns nothing.
if (nftList.raw.total > 0) {
return {
redirect: {
permanent: false,
destination: "/videos",
},
props: {},
};
}
console.log;
}
export default Protected;
Update: I donāt know how but I think I just solved it⦠It spontaneously worked for the wallet with the NFT (redirected correctly) but returned the same error for a wallet without it.
I added an else function to redirect back to index and it now seems to be functioning perfectly.
if (nftList.raw.total > 0) {
return {
redirect: {
permanent: false,
destination: "/videos",
},
props: {},
};
} else {
return {
redirect: {
permanent: false,
destination: "/",
},
};
}
}
export default Protected;
Thanks for the assistance!
Your getserverside function still needs to return something, you can have it like so
if (nftList.raw.total > 0) {
return {
redirect: {
destination: "/videos",
permanent: false,
},
};
}
return {
props: {},
};
also, on your /videos
route you still need to do a check inside getserversideprops and redirect to a different page if the used doesnt have access
if (nftList.raw.total < 1) {
return {
redirect: {
destination: "/signin",
permanent: false,
},
};
}
return {
props: {},
};
I can see itāll take me a while to get to grips with this⦠plus itās solidity next so Iād better pull my socks up and get to work! Thanks for your help.
Hi,
Hope i can continue with this on this thread as is related to our past feed. I just realised that with my solution or redirecting through the NFT gate, of course you can navigate to that URL directly to bypass it. Therefore I need a way of returning the page contents within the NFT check function. I have tried setting the page as a component and importing it into the code but clearly not compatible with the getServerSideProps.
Do you have any suggestions how I can do this?
Thank you
on your protected page you can add the same logic to redirect the user if they doesnt have the nft
Thank you, that works great.
However the problem remains that I can simply navigate on the local host to localhost:3000/videos and I can access the page whether or not Iām connected to an NFT-carrying wallet
I think instead of a redirect, I need to inject the pages code directly into the getserversideprops (if I understand that correctly) then return the logic : if NFT exists in wallet, show content, if not send back to ā/ā. Unfortunately the moralis tutorial only shows how to return NFT details, not a protected page itself.
this code checks if the user is logged in, you can add this before checking for nfts
change the destination to /signin
Thanks, yes thatās all already there from the tutorial.
Problem is as I say, the redirect to the videos page from the protected page doesnāt protect the videos page. So what I want to do is inject the videos page code into the projected page.
The code i sent is meant to be used on your /videos
page inside getServerSideProps
Thanks, I have added this code as per your recommendation:
import Head from "next/head";
import Header from "../Components/Header";
import VideoContainer from "../Components/VideoContainer";
import { useEffect, useState } from "react";
import Data from "../Components/Data";
import RecommendedList from "../Components/RecommendedList";
export default function protectedPage() {
const [isVideo, setVideo] = useState({
name: Data[0].videoName,
videoSrc: Data[0].videoSrc,
});
async function getServerSideProps(context) {
const session = await getSession(context);
if (!session) {
return {
redirect: {
destination: "/",
permanent: false,
},
};
}
}
useEffect(() => {
const scrollContainer = (Document =
document.getElementById("scrollContainer"));
scrollContainer.addEventListener("wheel", (evt) => {
evt.preventDefault();
scrollContainer.scrollLeft += evt.deltaY;
});
}, []);
return (
<div className="bg-fieldNight bg-cover w-screen h-screen overflow-hidden flex-col ">
<Head>
<title>Premium Content</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<Header />
{/* Main Container */}
<div className="w-full h-[calc(100%-80px)] flex">
{/* Main Container */}
<div className="ml-10 sm:w-[calc(100%-60px)] md:w-[90%] h-full justify-center">
{/* Thank you */}
<div className="w-full h-[20%] flex itmes-center justify-center">
<div
className=" flex overflow-x-auto items-center scrollbar-none py-2"
id="scrollContainer"
>
<h1 className="text-textColor text-[12px] lg:text-[30px] md:text-[23px] sm:text-[16px]">
Thank you for all your support! As you have one of my Official
Proofreader NFTs, here you can find exclusive videos which log
the writing process of my books from the very first day
</h1>
</div>
</div>
{/* ------------ */}
{/* Video Section */}
<div className="w-full h-[70%] grid grid-cols-3 gap-2 p-2">
{/* Video Container */}
<div
className="bg-black
col-span-6 sm:col-span-6 md:col-span-2 rounded-lg overflow-hidden flex items-center justify-center"
>
<VideoContainer data={isVideo} />
</div>
{/* Recommended List */}
<div className="w-[100%] col-span-6 sm:col-span-6 md:col-span-1 bg-searchBg overflow-y-auto scrollbar-thin scrollbar-thumb-gray-800 rounded-lg">
<p className="text-textColor text-[18px] font-bold my-2 px-2">
Book 1 Production Videos
</p>
{Data &&
Data.map((data) => (
<div
key={data.id}
onClick={() =>
setVideo({
name: data.videoName,
videoSrc: data.videoSrc,
})
}
>
<RecommendedList
imgSrc={data.imgSrc}
videoName={data.videoName}
/>
</div>
))}
</div>
</div>
{/* ------------ */}
</div>
</div>
</div>
);
}`
However still the issue remains that the videos page content can be viewed by anyone who has an active metamask session active regardless of whether they hold the NFT or not.
This is my protected page which redirects to the videos page. Ideally what Iād like is to make this the videos page and inject the content of the vdieos page into the if(nftList.raw.total >0) condition.
I have added a note to where I believe this should go, but please do correct me and advise on how to code this in:
import { getSession } from "next-auth/react";
import Moralis from "moralis";
import { EvmChain } from "@moralisweb3/common-evm-utils";
function Protected({ message, nftList }) {
return (
<div>
<h3>Protected content</h3>
<p>{message}</p>
<pre>{JSON.stringify(nftList, null, 2)}</pre>
</div>
);
}
export async function getServerSideProps(context) {
const session = await getSession(context);
if (!session) {
return {
redirect: {
destination: "/",
permanent: false,
},
};
}
if (!Moralis.Core.isStarted) {
await Moralis.start({ apiKey: process.env.MORALIS_API_KEY });
}
const nftList = await Moralis.EvmApi.nft.getWalletNFTs({
chain: EvmChain.ETHEREUM,
address: session.user.address,
tokenAddresses: ["0x495f947276749ce646f68ac8c248420045cb7b5e"],
});
if (nftList.raw.total > 0) {
return {
// Can I add something here to show a videos component which will use the videos page code?
props: {},
};
}
if (nftList.raw.total < 1) {
return {
redirect: {
permanent: false,
destination: "/noNFT",
},
props: {},
};
}
}
export default Protected;
here you can add the check again on your page where you show the videos
async function getServerSideProps(context) {
const session = await getSession(context);
if (!session) {
return {
redirect: {
destination: "/",
permanent: false,
},
};
}
if (!Moralis.Core.isStarted) {
await Moralis.start({ apiKey: process.env.MORALIS_API_KEY });
}
const nftList = await Moralis.EvmApi.nft.getWalletNFTs({
chain: EvmChain.ETHEREUM,
address: session.user.address,
tokenAddresses: ["0x495f947276749ce646f68ac8c248420045cb7b5e"],
});
if (nftList.raw.total < 1) {
return {
redirect: {
permanent: false,
destination: "/noNFT",
},
props: {},
};
}
return {
props: {},
};
}
Thanks.
Added this to the videos page and replaced the protected page code with what you recommended above. However issue remains can still access the videos page via url with no check running. It seems the issue may be that the getServerSideProps function in the videos page is showing as ādeclared but never readā.
I am sorry I know this must be becoming a pain, especially if Iām making obvious errors! As I say this is my first dabbling in coding so it must be frustrating for you. Hugely appreciate your ongoing support.
Video page code:
import Head from "next/head";
import Header from "../Components/Header";
import VideoContainer from "../Components/VideoContainer";
import { useEffect, useState } from "react";
import Data from "../Components/Data";
import RecommendedList from "../Components/RecommendedList";
export default function protectedPage() {
const [isVideo, setVideo] = useState({
name: Data[0].videoName,
videoSrc: Data[0].videoSrc,
});
async function getServerSideProps(context) { //declared but never read
const session = await getSession(context);
if (!session) {
return {
redirect: {
destination: "/",
permanent: false,
},
};
}
if (!Moralis.Core.isStarted) {
await Moralis.start({ apiKey: process.env.MORALIS_API_KEY });
}
const nftList = await Moralis.EvmApi.nft.getWalletNFTs({
chain: EvmChain.ETHEREUM,
address: session.user.address,
tokenAddresses: ["0x495f947276749ce646f68ac8c248420045cb7b5e"],
});
if (nftList.raw.total < 1) {
return {
redirect: {
permanent: false,
destination: "/noNFT",
},
props: {},
};
}
return {
props: {},
};
}
useEffect(() => {
const scrollContainer = (Document =
document.getElementById("scrollContainer"));
scrollContainer.addEventListener("wheel", (evt) => {
evt.preventDefault();
scrollContainer.scrollLeft += evt.deltaY;
});
}, []);
return (
<div className="bg-fieldNight bg-cover w-screen h-screen overflow-hidden flex-col ">
<Head>
<title>Premium Content</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<Header />
{/* Main Container */}
<div className="w-full h-[calc(100%-80px)] flex">
{/* Main Container */}
<div className="ml-10 sm:w-[calc(100%-60px)] md:w-[90%] h-full justify-center">
{/* Thank you */}
<div className="w-full h-[20%] flex itmes-center justify-center">
<div
className=" flex overflow-x-auto items-center scrollbar-none py-2"
id="scrollContainer"
>
<h1 className="text-textColor text-[12px] lg:text-[30px] md:text-[23px] sm:text-[16px]">
Thank you for all your support! As you have one of my Official
Proofreader NFTs, here you can find exclusive videos which log
the writing process of my books from the very first day
</h1>
</div>
</div>
{/* ------------ */}
{/* Video Section */}
<div className="w-full h-[70%] grid grid-cols-3 gap-2 p-2">
{/* Video Container */}
<div
className="bg-black
col-span-6 sm:col-span-6 md:col-span-2 rounded-lg overflow-hidden flex items-center justify-center"
>
<VideoContainer data={isVideo} />
</div>
{/* Recommended List */}
<div className="w-[100%] col-span-6 sm:col-span-6 md:col-span-1 bg-searchBg overflow-y-auto scrollbar-thin scrollbar-thumb-gray-800 rounded-lg">
<p className="text-textColor text-[18px] font-bold my-2 px-2">
Book 1 Production Videos
</p>
{Data &&
Data.map((data) => (
<div
key={data.id}
onClick={() =>
setVideo({
name: data.videoName,
videoSrc: data.videoSrc,
})
}
>
<RecommendedList
imgSrc={data.imgSrc}
videoName={data.videoName}
/>
</div>
))}
</div>
</div>
{/* ------------ */}
</div>
</div>
</div>
);
}
the issues is that your have getServerSideProps
inside the component, you can move the function out, and also add export
export async function getServerSideProps
Thatās it!
Thank you so much for your ongoing support!