Adding a very rudimentary admin page that displays a table of users and their basic information

This commit is contained in:
Keith Stevens
2023-01-07 19:13:26 +09:00
parent d59a75a0be
commit b70c638f7c
3 changed files with 144 additions and 0 deletions
+46
View File
@@ -0,0 +1,46 @@
import { Table, TableCaption, TableContainer, Tbody, Td, Th, Thead, Tr } from "@chakra-ui/react";
import { useState } from "react";
import fetcher from "src/lib/fetcher";
import useSWR from "swr";
/**
* Fetches users from the users api route and then presents them in a simple Chakra table.
*/
const UsersCell = () => {
// Fetch and save the users.
const [users, setUsers] = useState([]);
const { isLoading } = useSWR("/api/admin/users", fetcher, {
onSuccess: (data) => {
setUsers(data);
},
});
// Present users in a naive table.
return (
<TableContainer>
<Table variant="simple">
<TableCaption>Users</TableCaption>
<Thead>
<Tr>
<Th>Id</Th>
<Th>Email</Th>
<Th>Name</Th>
<Th>Role</Th>
</Tr>
</Thead>
<Tbody>
{users.map((user, index) => (
<Tr key={index}>
<Td>{user.id}</Td>
<Td>{user.email}</Td>
<Td>{user.name}</Td>
<Td>{user.role}</Td>
</Tr>
))}
</Tbody>
</Table>
</TableContainer>
);
};
export default UsersCell;
+67
View File
@@ -0,0 +1,67 @@
import Head from "next/head";
import { useRouter } from "next/router";
import { useSession } from "next-auth/react";
import { useEffect } from "react";
import { getTransparentHeaderLayout } from "src/components/Layout";
import UsersCell from "src/components/UsersCell";
/**
* Provides the admin index page that will display a list of users and give
* admins the ability to manage their access rights.
*/
const AdminIndex = () => {
const router = useRouter();
const { data: session, status } = useSession();
// Check when the user session is loaded and re-route if the user is not an
// admin. This follows the suggestion by NextJS for handling private pages:
// https://nextjs.org/docs/api-reference/next/router#usage
//
// All admin pages should use the same check and routing steps.
useEffect(() => {
if (status === "loading") {
return;
}
if (session?.user?.role === "admin") {
return;
}
router.push("/");
}, [session, status]);
// While loading, just show something.
if (status === "loading") {
return (
<>
<Head>
<title>Open Assistant</title>
<meta
name="description"
content="Conversational AI for everyone. An open source project to create a chat enabled GPT LLM run by LAION and contributors around the world."
/>
</Head>
<main className="oa-basic-theme">loading...</main>
</>
);
}
// Show the final page.
// TODO(#237): Display a component that fetches actual user data.
return (
<>
<Head>
<title>Open Assistant</title>
<meta
name="description"
content="Conversational AI for everyone. An open source project to create a chat enabled GPT LLM run by LAION and contributors around the world."
/>
</Head>
<main className="oa-basic-theme">
<UsersCell />
</main>
</>
);
};
AdminIndex.getLayout = getTransparentHeaderLayout;
export default AdminIndex;
+31
View File
@@ -0,0 +1,31 @@
import { getToken } from "next-auth/jwt";
import client from "src/lib/prismadb";
/**
* Returns a list of user results from the database when the requesting user is
* a logged in admin.
*/
const handler = async (req, res) => {
const token = await getToken({ req });
// Return nothing if the user isn't registered or if the user isn't an admin.
if (!token || token.role !== "admin") {
res.status(403).end();
return;
}
// Fetch 20 users.
const users = await client.user.findMany({
select: {
id: true,
role: true,
name: true,
email: true,
},
take: 20,
});
res.status(200).json(users);
};
export default handler;