diff --git a/.env.sample b/.env.sample index 0e692b0d..a5796351 100644 --- a/.env.sample +++ b/.env.sample @@ -22,6 +22,7 @@ BROWSER_TIMEOUT= IGNORE_UNAUTHORIZED_CA= IGNORE_HTTPS_ERRORS= IGNORE_URL_SIZE_LIMIT= +ADMINISTRATOR= # AWS S3 Settings SPACES_KEY= diff --git a/lib/api/controllers/users/getUsers.ts b/lib/api/controllers/users/getUsers.ts new file mode 100644 index 00000000..dd2b1686 --- /dev/null +++ b/lib/api/controllers/users/getUsers.ts @@ -0,0 +1,22 @@ +import { prisma } from "@/lib/api/db"; + +export default async function getUsers() { + // Get all users + const users = await prisma.user.findMany({ + select: { + id: true, + username: true, + email: true, + emailVerified: true, + subscriptions: { + select: { + active: true, + }, + }, + createdAt: true, + updatedAt: true, + }, + }); + + return { response: users, status: 200 }; +} diff --git a/pages/admin.tsx b/pages/admin.tsx new file mode 100644 index 00000000..6624fe33 --- /dev/null +++ b/pages/admin.tsx @@ -0,0 +1,77 @@ +import { User as U } from "@prisma/client"; +import Link from "next/link"; +import { useEffect, useState } from "react"; + +interface User extends U { + subscriptions: { + active: boolean; + }; +} + +export default function Admin() { + const [users, setUsers] = useState(); + + useEffect(() => { + // fetch users + fetch("/api/v1/users") + .then((res) => res.json()) + .then((data) => setUsers(data.response)); + }, []); + + return ( +
+
+ + + +

+ User Administration +

+
+ +
+ + {users && users.length > 0 ? ( +
+ + + + + + {process.env.NEXT_PUBLIC_EMAIL_PROVIDER === "true" && ( + + )} + {process.env.NEXT_PUBLIC_STRIPE === "true" && ( + + )} + + + + + + {users.map((user, index) => ( + + + + {process.env.NEXT_PUBLIC_EMAIL_PROVIDER === "true" && ( + + )} + {process.env.NEXT_PUBLIC_STRIPE === "true" && ( + + )} + + + + ))} + +
UsernameEmailSubscribedCreated AtUpdated At
{index + 1}{user.username}{user.email}{user.subscriptions.active ? "Yes" : "No"}{new Date(user.createdAt).toLocaleString()}{new Date(user.updatedAt).toLocaleString()}
+
+ ) : ( +

No users found.

+ )} +
+ ); +} diff --git a/pages/api/v1/users/index.ts b/pages/api/v1/users/index.ts index 3af7bf8e..cce6b4ea 100644 --- a/pages/api/v1/users/index.ts +++ b/pages/api/v1/users/index.ts @@ -1,9 +1,17 @@ import type { NextApiRequest, NextApiResponse } from "next"; import postUser from "@/lib/api/controllers/users/postUser"; +import getUsers from "@/lib/api/controllers/users/getUsers"; +import verifyUser from "@/lib/api/verifyUser"; export default async function users(req: NextApiRequest, res: NextApiResponse) { if (req.method === "POST") { const response = await postUser(req, res); return response; + } else if (req.method === "GET") { + const user = await verifyUser({ req, res }); + if (!user || process.env.ADMINISTRATOR !== user.username) return; + + const response = await getUsers(); + return res.status(response.status).json({ response: response.response }); } } diff --git a/types/enviornment.d.ts b/types/enviornment.d.ts index e8c5a7c6..5a94472f 100644 --- a/types/enviornment.d.ts +++ b/types/enviornment.d.ts @@ -14,6 +14,7 @@ declare global { ARCHIVE_TAKE_COUNT?: string; IGNORE_UNAUTHORIZED_CA?: string; IGNORE_URL_SIZE_LIMIT?: string; + ADMINISTRATOR?: string; SPACES_KEY?: string; SPACES_SECRET?: string; @@ -418,4 +419,4 @@ declare global { } } -export { }; +export {};