Best practice for Admin dashboard?

I want to make an admin special page, but on the client side, I didn't know how to check if the user is admin, how can I do it? Should I check if the id from ctx is admin with getServerSideProps or should I check with trpc query? I want to do something like layout
25 Replies
robotkutya
robotkutya2y ago
In the create-t3-app starting template there is this part:
getSecretMessage: protectedProcedure.query(() => {
return "you can now see this secret message!";
}),
getSecretMessage: protectedProcedure.query(() => {
return "you can now see this secret message!";
}),
I recommend you go over that and follow that to the front end. If you have more questions lemme know 🖖
Çağlar
Çağlar2y ago
@robotkutya thank you very much, I would like to ask about handling on the client side like do I need some kind of provider layout or idk And it would be amazing if you could give me an example template
barry
barry2y ago
You don't check on the client side.
Çağlar
Çağlar2y ago
then what should I do? do you have any sample?
c
c2y ago
not sure that this is best practice, but it's a middleware implementation w/ jwt: https://discord.com/channels/966627436387266600/1067624837507457034/1068639470896824320
Çağlar
Çağlar2y ago
how did u assign role to token? where did you take it from? I couldn't add a role or isAdmin (boolean type) to session.user object in callbacks. isAdmin or role is constantly returning undefined. It exists in the schema and I define 'user' by default, but it returns undefined no matter what I do btw Im using credentials provider
barry
barry2y ago
did you make the user before adding role
Çağlar
Çağlar2y ago
Yes I did
barry
barry17mo ago
there you have the reason its undefined lol
Çağlar
Çağlar17mo ago
Nope, it shouldnt have be undefined. I set User as the default value.
barry
barry17mo ago
if a user exists without a role column, and you add role to the table it goes undefined not default
Çağlar
Çağlar17mo ago
No, I mean there is a role column and its default value is User.
barry
barry17mo ago
and you said the user was there before you added the role column
Çağlar
Çağlar17mo ago
I wasnt mean that I'm sorry if I expressed it wrong
c
c17mo ago
hard to help much without code to look at. i actually had trouble doing this just based off of docs but you can try doing what i did and just reading through all the nextauth/trpc example reps and searching through past issues for other code examples.
Çağlar
Çağlar17mo ago
@kivish Hey again, I just found how to handle it
callbacks: {
jwt: ({ token, user }) => {
user && (token.user = user);
return token;
},
redirect({ url, baseUrl }) {
// Allows relative callback URLs
if (url.startsWith("/")) return `${baseUrl}${url}`;
// Allows callback URLs on the same origin
else if (new URL(url).origin === baseUrl) return url;
return baseUrl;
},
session: ({ session, token }) => {
session.user = {
id: token.user.id,
isAdmin: token.user.isAdmin as boolean,
role: token.user.role,
};

return session;
},
},
callbacks: {
jwt: ({ token, user }) => {
user && (token.user = user);
return token;
},
redirect({ url, baseUrl }) {
// Allows relative callback URLs
if (url.startsWith("/")) return `${baseUrl}${url}`;
// Allows callback URLs on the same origin
else if (new URL(url).origin === baseUrl) return url;
return baseUrl;
},
session: ({ session, token }) => {
session.user = {
id: token.user.id,
isAdmin: token.user.isAdmin as boolean,
role: token.user.role,
};

return session;
},
},
Çağlar
Çağlar17mo ago
Çağlar
Çağlar17mo ago
In jwt we get user and return it inside token and then session takes user from token.user This method allows us to put exactly what we want inside the JWT
Lopen
Lopen17mo ago
Depending on your database structure Arr you using role based Or you have a different table for admin This is how i guard my page when i do role based adim
import { prisma } from '@/server/db/client';
import type { GetServerSideProps, GetServerSidePropsContext } from "next";
import { unstable_getServerSession } from "next-auth";
import { authOptions } from "./auth/[...nextauth]";

export const requireAdmin =
(func: GetServerSideProps) => async (ctx: GetServerSidePropsContext) => {
const session = await unstable_getServerSession(
ctx.req,
ctx.res,
authOptions
);

if (!session) {
return {
redirect: {
destination: "/login", // login path
permanent: false,
},
};
}
const result = await prisma.user.findUnique({
where: { id: session.user.userId},
select: {role:true}
});
if (result?.role !== "ADMIN") {
return {
redirect: {
destination: "/account", // login path
permanent: false,
},
};
}


return await func(ctx);
};
import { prisma } from '@/server/db/client';
import type { GetServerSideProps, GetServerSidePropsContext } from "next";
import { unstable_getServerSession } from "next-auth";
import { authOptions } from "./auth/[...nextauth]";

export const requireAdmin =
(func: GetServerSideProps) => async (ctx: GetServerSidePropsContext) => {
const session = await unstable_getServerSession(
ctx.req,
ctx.res,
authOptions
);

if (!session) {
return {
redirect: {
destination: "/login", // login path
permanent: false,
},
};
}
const result = await prisma.user.findUnique({
where: { id: session.user.userId},
select: {role:true}
});
if (result?.role !== "ADMIN") {
return {
redirect: {
destination: "/account", // login path
permanent: false,
},
};
}


return await func(ctx);
};
First i check if the user is signed in Second check if user has role admin Also i modified my session object and included role in my next auth types and session
Çağlar
Çağlar17mo ago
I totally agree, our problem here was to extend the user in the session
Lopen
Lopen17mo ago
So have you solved it?
Çağlar
Çağlar17mo ago
yes, I did, thank you for different approach
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Lopen
Lopen16mo ago
import React from "react"

export const getServerSideProps = requireAdmin(async () => {
return { props: {} };
});

function Home () {
return ( <div>hello</div>)
}
export default Home;
import React from "react"

export const getServerSideProps = requireAdmin(async () => {
return { props: {} };
});

function Home () {
return ( <div>hello</div>)
}
export default Home;
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View