From f1806ef4a2244ef1755cb4b67c5eba18d4b2444f Mon Sep 17 00:00:00 2001 From: Atridad Lahiji Date: Sat, 29 Jul 2023 13:05:17 -0600 Subject: [PATCH 1/4] Matt's the only one to ask for one of these so here we go... why not? --- prisma/schema.prisma | 1 + src/pages/room/[id].tsx | 9 +++++++++ src/utils/types.ts | 1 + 3 files changed, 11 insertions(+) diff --git a/prisma/schema.prisma b/prisma/schema.prisma index a53c78c..bd8df38 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1,6 +1,7 @@ enum RoleValue { USER ADMIN + MATT } generator client { diff --git a/src/pages/room/[id].tsx b/src/pages/room/[id].tsx index 98bd56a..68652a1 100644 --- a/src/pages/room/[id].tsx +++ b/src/pages/room/[id].tsx @@ -15,6 +15,7 @@ import { IoReloadOutline, IoSaveOutline, } from "react-icons/io5"; +import { GiStarFormation } from "react-icons/gi"; import { z } from "zod"; import { api } from "~/utils/api"; import { getServerAuthSession } from "../../server/auth"; @@ -310,6 +311,14 @@ const RoomBody: React.FC = ({}) => { )}{" "} + {presenceItem.data.role === "MATT" && ( +
+ +
+ )}{" "} {presenceItem.clientId === roomFromDb.userId && (
; const RoleValues = { ADMIN: "ADMIN", USER: "USER", + MATT: "MATT", } as const; export type Role = BetterEnum; From c402732f0a227fa6c66e8cc8a098bb557013cf7a Mon Sep 17 00:00:00 2001 From: Atridad Lahiji Date: Sat, 29 Jul 2023 13:18:14 -0600 Subject: [PATCH 2/4] SLIGHT change to the role... --- prisma/schema.prisma | 2 +- src/pages/admin/index.tsx | 90 ++++++++++++++++++++-------------- src/pages/dashboard/index.tsx | 30 +++++++----- src/pages/room/[id].tsx | 4 +- src/server/api/routers/user.ts | 6 ++- src/utils/types.ts | 2 +- 6 files changed, 80 insertions(+), 54 deletions(-) diff --git a/prisma/schema.prisma b/prisma/schema.prisma index bd8df38..41ff26a 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1,7 +1,7 @@ enum RoleValue { USER ADMIN - MATT + VIP } generator client { diff --git a/src/pages/admin/index.tsx b/src/pages/admin/index.tsx index d66a1cd..0a081d0 100644 --- a/src/pages/admin/index.tsx +++ b/src/pages/admin/index.tsx @@ -5,6 +5,7 @@ import { AiOutlineClear } from "react-icons/ai"; import { FaShieldAlt } from "react-icons/fa"; import { IoTrashBinOutline } from "react-icons/io5"; import { SiGithub, SiGoogle } from "react-icons/si"; +import { GiStarFormation } from "react-icons/gi"; import { api } from "~/utils/api"; import type { Role } from "~/utils/types"; import { getServerAuthSession } from "../../server/auth"; @@ -158,70 +159,70 @@ const AdminBody: React.FC = () => {
Users
- { usersCountLoading || usersCountFetching ? ( + {usersCountLoading || usersCountFetching ? ( ) : ( - <>{ usersCount ? usersCount : "0" } - ) } + <>{usersCount ? usersCount : "0"} + )}
Rooms
- { roomsCountLoading || roomsCountFetching ? ( + {roomsCountLoading || roomsCountFetching ? ( ) : ( - <>{ roomsCount ? roomsCount : "0" } - ) } + <>{roomsCount ? roomsCount : "0"} + )}
Votes
- { votesCountLoading || votesCountFetching ? ( + {votesCountLoading || votesCountFetching ? ( ) : ( - <>{ votesCount ? votesCount : "0" } - ) } + <>{votesCount ? votesCount : "0"} + )}
- { usersCountFetching || - usersFetching || - roomsCountFetching || - votesCountFetching ? ( + {usersCountFetching || + usersFetching || + roomsCountFetching || + votesCountFetching ? ( ) : (
- ) } + )}

Users:

- { usersLoading || usersFetching ? ( + {usersLoading || usersFetching ? ( ) : (
- {/* head */ } + {/* head */} @@ -233,55 +234,72 @@ const AdminBody: React.FC = () => { - { users + {users ?.sort((user1, user2) => user2.createdAt > user1.createdAt ? 1 : -1 ) .map((user) => { return ( - + ); - }) } + })}
ID
- { user.id } + {user.id} - { user.name } + {user.name} - { user.createdAt.toLocaleDateString() } + {user.createdAt.toLocaleDateString()} - { user.sessions.length } + {user.sessions.length} - { getProviders(user).includes("google") && ( + {getProviders(user).includes("google") && ( - ) } - { getProviders(user).includes("github") && ( + )} + {getProviders(user).includes("github") && ( - ) } + )} +
- ) } + )}
diff --git a/src/pages/dashboard/index.tsx b/src/pages/dashboard/index.tsx index 6ad31f0..7ed5495 100644 --- a/src/pages/dashboard/index.tsx +++ b/src/pages/dashboard/index.tsx @@ -8,6 +8,7 @@ import Link from "next/link"; import { useEffect, useState } from "react"; import { FaShieldAlt } from "react-icons/fa"; import { getServerAuthSession } from "~/server/auth"; +import { GiStarFormation } from "react-icons/gi"; export const getServerSideProps: GetServerSideProps = async (ctx) => { const session = await getServerAuthSession(ctx); @@ -57,20 +58,23 @@ const HomePageBody: React.FC = () => { return ( <>

- Hi, { sessionData?.user.name }!{ " " } - { sessionData?.user.role === "ADMIN" && ( + Hi, {sessionData?.user.name}!{" "} + {sessionData?.user.role === "ADMIN" && ( - ) } + )} + {sessionData?.user.role === "VIP" && ( + + )}

{ + onClick={() => { setTabIndex(0); localStorage.setItem("dashboardTabIndex", "0"); - } } + }} > Join a Room @@ -78,36 +82,36 @@ const HomePageBody: React.FC = () => { className={ tabIndex === 1 ? "tab no-underline tab-active" : "tab no-underline" } - onClick={ () => { + onClick={() => { setTabIndex(1); localStorage.setItem("dashboardTabIndex", "1"); - } } + }} > Room List
- { tabIndex === 0 && ( + {tabIndex === 0 && ( <> { + onChange={(event) => { console.log(event.target.value); setJoinRoomTextBox(event.target.value); - } } + }} /> 0 ? `/room/${joinRoomTextBox}` : "/" } + href={joinRoomTextBox.length > 0 ? `/room/${joinRoomTextBox}` : "/"} className="btn btn-secondary" > Join Room - ) } + )} - { tabIndex === 1 && } + {tabIndex === 1 && } ); }; diff --git a/src/pages/room/[id].tsx b/src/pages/room/[id].tsx index 68652a1..29c15d0 100644 --- a/src/pages/room/[id].tsx +++ b/src/pages/room/[id].tsx @@ -311,10 +311,10 @@ const RoomBody: React.FC = ({}) => { )}{" "} - {presenceItem.data.role === "MATT" && ( + {presenceItem.data.role === "VIP" && (
diff --git a/src/server/api/routers/user.ts b/src/server/api/routers/user.ts index d7eff4f..f5995cf 100644 --- a/src/server/api/routers/user.ts +++ b/src/server/api/routers/user.ts @@ -153,7 +153,11 @@ export const userRouter = createTRPCRouter({ .input( z.object({ userId: z.string(), - role: z.union([z.literal("ADMIN"), z.literal("USER")]), + role: z.union([ + z.literal("ADMIN"), + z.literal("USER"), + z.literal("VIP"), + ]), }) ) .mutation(async ({ ctx, input }) => { diff --git a/src/utils/types.ts b/src/utils/types.ts index f2a5477..cf71bb6 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -10,7 +10,7 @@ export type EventType = BetterEnum; const RoleValues = { ADMIN: "ADMIN", USER: "USER", - MATT: "MATT", + VIP: "VIP", } as const; export type Role = BetterEnum; From 95c9314d03ed84e93c6774daa08eaeef6c82a265 Mon Sep 17 00:00:00 2001 From: Atridad Lahiji Date: Sat, 29 Jul 2023 21:38:59 -0600 Subject: [PATCH 3/4] Role overhaul --- prisma/schema.prisma | 10 ++--- src/pages/admin/index.tsx | 42 +++++++++--------- src/pages/dashboard/index.tsx | 4 +- src/pages/profile/index.tsx | 80 ++++++++++++++++++---------------- src/pages/room/[id].tsx | 7 +-- src/server/api/routers/user.ts | 41 ++++++++++++----- src/server/auth.ts | 16 ++++--- src/utils/types.ts | 10 +---- 8 files changed, 114 insertions(+), 96 deletions(-) diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 41ff26a..edcd219 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1,9 +1,3 @@ -enum RoleValue { - USER - ADMIN - VIP -} - generator client { provider = "prisma-client-js" } @@ -47,7 +41,6 @@ model Session { model User { id String @id @default(cuid()) - role RoleValue @default(USER) createdAt DateTime @default(now()) name String? email String? @unique @@ -58,6 +51,9 @@ model User { rooms Room[] votes Vote[] logs Log[] + isAdmin Boolean @default(false) + isVIP Boolean @default(false) + } model VerificationToken { diff --git a/src/pages/admin/index.tsx b/src/pages/admin/index.tsx index 0a081d0..9d9a86f 100644 --- a/src/pages/admin/index.tsx +++ b/src/pages/admin/index.tsx @@ -7,7 +7,6 @@ import { IoTrashBinOutline } from "react-icons/io5"; import { SiGithub, SiGoogle } from "react-icons/si"; import { GiStarFormation } from "react-icons/gi"; import { api } from "~/utils/api"; -import type { Role } from "~/utils/types"; import { getServerAuthSession } from "../../server/auth"; export const getServerSideProps: GetServerSideProps = async (ctx) => { @@ -23,7 +22,7 @@ export const getServerSideProps: GetServerSideProps = async (ctx) => { }; } - if (session.user.role !== "ADMIN") { + if (!session.user.isAdmin) { ctx.res.statusCode = 403; return { redirect: { @@ -91,7 +90,8 @@ const AdminBody: React.FC = () => { id: string; }[]; id: string; - role: Role; + isAdmin: boolean; + isVIP: boolean; name: string | null; email: string | null; }) => { @@ -120,7 +120,13 @@ const AdminBody: React.FC = () => { }, }); - const setRoleMutation = api.user.setRole.useMutation({ + const setAdminMutation = api.user.setAdmin.useMutation({ + onSuccess: async () => { + await refetchData(); + }, + }); + + const setVIPMutation = api.user.setVIP.useMutation({ onSuccess: async () => { await refetchData(); }, @@ -138,8 +144,12 @@ const AdminBody: React.FC = () => { await clearSessionsMutation.mutateAsync(); }; - const setUserRoleHandler = async (userId: string, role: Role) => { - await setRoleMutation.mutateAsync({ userId, role }); + const setAdmin = async (userId: string, value: boolean) => { + await setAdminMutation.mutateAsync({ userId, value }); + }; + + const setVIP = async (userId: string, value: boolean) => { + await setVIPMutation.mutateAsync({ userId, value }); }; const refetchData = async () => { @@ -264,36 +274,28 @@ const AdminBody: React.FC = () => { diff --git a/src/pages/dashboard/index.tsx b/src/pages/dashboard/index.tsx index 7ed5495..7e20c68 100644 --- a/src/pages/dashboard/index.tsx +++ b/src/pages/dashboard/index.tsx @@ -59,10 +59,10 @@ const HomePageBody: React.FC = () => { <>

Hi, {sessionData?.user.name}!{" "} - {sessionData?.user.role === "ADMIN" && ( + {sessionData?.user.isAdmin && ( )} - {sessionData?.user.role === "VIP" && ( + {sessionData?.user.isVIP && ( )}

diff --git a/src/pages/profile/index.tsx b/src/pages/profile/index.tsx index e7196e9..27b53ac 100644 --- a/src/pages/profile/index.tsx +++ b/src/pages/profile/index.tsx @@ -9,6 +9,7 @@ import { FaShieldAlt } from "react-icons/fa"; import { SiGithub, SiGoogle } from "react-icons/si"; import { api } from "~/utils/api"; import { getServerAuthSession } from "../../server/auth"; +import { GiStarFormation } from "react-icons/gi"; export const getServerSideProps: GetServerSideProps = async (ctx) => { const session = await getServerAuthSession(ctx); @@ -103,7 +104,7 @@ const ProfileBody: React.FC = () => { @@ -114,79 +115,82 @@ const ProfileBody: React.FC = () => {

Profile:

- { sessionData.user.image && ( -
- { sessionData.user.role === "ADMIN" && ( - -
- -
-
- ) } + {sessionData.user.image && ( + Profile picture. + )} - Profile picture. -
- ) } +
+ {sessionData.user.isAdmin && ( +
+ +
+ )} + {sessionData.user.isVIP && ( +
+ +
+ )} +
- { providersLoading ? ( + {providersLoading ? (
- { " " } + {" "}
) : (
- ) } + )} - { sessionData.user.name && ( + {sessionData.user.name && ( setNameText(event.target.value) } + value={nameText} + onChange={(event) => setNameText(event.target.value)} /> - ) } + )} - { sessionData.user.email && ( + {sessionData.user.email && ( - ) } + )} - {/* */ } + {/* */}