Added basic user roles

This commit is contained in:
Tom 2024-01-04 08:56:24 +00:00
parent ca9d84a25a
commit d8a72dcac0
7 changed files with 108 additions and 14 deletions

39
auth.ts
View File

@ -1,8 +1,32 @@
import NextAuth from "next-auth"
import NextAuth, { DefaultSession } from "next-auth"
import { JWT } from "@auth/core/jwt"
import { PrismaAdapter } from "@auth/prisma-adapter"
import { db } from "@/lib/db"
import authConfig from "@/auth.config"
import { getUserById } from "./data/user"
import { UserRole } from "@prisma/client"
declare module "@auth/core/types" {
/**
* Returned by `useSession`, `getSession` and received as a prop on the `SessionProvider` React Context
*/
interface Session {
user: {
role: UserRole
// By default, TypeScript merges new interface properties and overwrite existing ones. In this case, the default session user properties will be overwritten, with the new one defined above. To keep the default session user properties, you need to add them back into the newly declared interface
} & DefaultSession["user"] // To keep the default types
}
}
declare module "@auth/core/jwt" {
/** Returned by the `jwt` callback and `auth`, when using JWT sessions */
interface JWT {
role: UserRole
}
}
export const {
handlers: { GET, POST },
@ -23,9 +47,22 @@ export const {
if (token.sub && session.user) {
session.user.id = token.sub
}
if (token.role && session.user) {
session.user.role = token.role
}
return session
},
async jwt({ token, user, account, profile, isNewUser }) {
if (!token.sub) return token
const existingUser = await getUserById(token.sub)
if (!existingUser) return token
token.role = existingUser.role
return token
}
},

View File

@ -0,0 +1,30 @@
"use client"
import { UserRole } from "@prisma/client";
import { useSession } from "next-auth/react";
import React from "react";
interface RoleGateProps {
children: React.ReactNode
roles: UserRole[]
}
export const RoleGate = ({
children,
roles,
}: RoleGateProps) => {
const session = useSession()
const role = session?.data?.user.role as UserRole
if (roles.includes(role)) {
return (
<div>
{ children }
</div>
);
}
return <div />
}
export default RoleGate

View File

@ -0,0 +1,22 @@
"use client"
import axios from "axios";
import * as React from 'react';
import { useEffect, useState } from "react";
import { useSession } from "next-auth/react";
import { cn } from "@/lib/utils";
const AdminProfile = () => {
const session = useSession();
const [user, setUser] = useState<{ id: string, username: string }>()
return (
<div className={"px-10 py-6 rounded-md bg-red-300 overflow-hidden wrap m-[10px]"}>
<p className="text-xs text-gray-400">Role:</p>
<p>{session?.data?.user?.role}</p>
</div>
);
}
export default AdminProfile;

View File

@ -1,6 +1,8 @@
import Link from "next/link";
import { Button } from "../ui/button";
import UserProfile from "./userprofile";
import AdminProfile from "./adminprofile";
import RoleGate from "../auth/role-gate";
const SettingsNavigation = async () => {
return (
@ -8,7 +10,12 @@ const SettingsNavigation = async () => {
<div className="text-4xl flex pl-[15px] pb-[33px]">Hermes</div>
<div className="w-full pl-[30px] pr-[30px] pb-[50px]">
<UserProfile />
<div className="gap-5">
<UserProfile />
<RoleGate roles={["ADMIN"]}>
<AdminProfile />
</RoleGate>
</div>
</div>
<div className="flex h-full z-20 inset-y-1/3 w-full">

View File

@ -20,14 +20,13 @@ const UserProfile = () => {
previousUsername = session.user?.name || ""
if (session.user) {
const fetchData = async () => {
if (user) return
var userData = (await axios.get("/api/account")).data
setUser(userData)
console.log(userData)
}
fetchData().catch(console.error)
// TODO: check session if impersonation is in use.
}
}, [session])

View File

@ -1,16 +1,9 @@
import { db } from "@/lib/db"
import { useSession } from "next-auth/react"
export const currentUser = async() => {
const { data: session, status } = useSession()
if (status !== "authenticated") {
return null;
}
export const currentUser = async(id: string) => {
const user = await db.user.findUnique({
where: {
id: session?.user?.name as string
id
}
});

View File

@ -8,11 +8,17 @@ datasource db {
relationMode = "prisma"
}
enum UserRole {
USER
ADMIN
}
model User {
id String @id @default(cuid())
name String?
email String? @unique
emailVerified DateTime?
role UserRole @default(USER)
image String?
ttsDefaultVoice Int @default(1)
ttsEnabledVoice Int @default(1048575)