123 lines
3.9 KiB
TypeScript
123 lines
3.9 KiB
TypeScript
|
|
import { auth } from "@/auth";
|
||
|
|
import { prisma } from "@/lib/prisma";
|
||
|
|
import { redirect } from "next/navigation";
|
||
|
|
import {
|
||
|
|
Container,
|
||
|
|
Typography,
|
||
|
|
Paper,
|
||
|
|
Table,
|
||
|
|
TableBody,
|
||
|
|
TableCell,
|
||
|
|
TableHead,
|
||
|
|
TableRow,
|
||
|
|
Box,
|
||
|
|
Alert,
|
||
|
|
Breadcrumbs
|
||
|
|
} from "@mui/material";
|
||
|
|
import Link from "next/link";
|
||
|
|
import UserRow from "./user-row";
|
||
|
|
import SettingsIcon from '@mui/icons-material/Settings';
|
||
|
|
import NavigateNextIcon from '@mui/icons-material/NavigateNext';
|
||
|
|
|
||
|
|
export default async function SettingsPage() {
|
||
|
|
const session = await auth();
|
||
|
|
const userEmail = session?.user?.email || "";
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 1. Access Control
|
||
|
|
* Check if the logged-in user is the Bootstrap Admin from .env
|
||
|
|
* or has the ADMIN role assigned in the database.
|
||
|
|
*/
|
||
|
|
const isBootstrap = userEmail === process.env.INITIAL_ADMIN_EMAIL;
|
||
|
|
const dbUser = await prisma.user.findUnique({
|
||
|
|
where: { email: userEmail },
|
||
|
|
select: { id: true, role: true }
|
||
|
|
});
|
||
|
|
|
||
|
|
const isAdmin = isBootstrap || dbUser?.role === "ADMIN";
|
||
|
|
|
||
|
|
if (!isAdmin) {
|
||
|
|
redirect("/dashboard"); // Unauthorized users are sent back to Dashboard
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 2. Data Fetching
|
||
|
|
* Get all users to display in the management table.
|
||
|
|
*/
|
||
|
|
const allUsers = await prisma.user.findMany({
|
||
|
|
orderBy: { email: 'asc' }
|
||
|
|
});
|
||
|
|
|
||
|
|
return (
|
||
|
|
<Container maxWidth="md" sx={{ py: 6 }}>
|
||
|
|
{/* Breadcrumbs for easier navigation */}
|
||
|
|
<Breadcrumbs
|
||
|
|
separator={<NavigateNextIcon fontSize="small" />}
|
||
|
|
aria-label="breadcrumb"
|
||
|
|
sx={{ mb: 3 }}
|
||
|
|
>
|
||
|
|
<Link href="/dashboard" style={{ textDecoration: 'none', color: 'inherit' }}>
|
||
|
|
Dashboard
|
||
|
|
</Link>
|
||
|
|
<Typography color="text.primary">Settings</Typography>
|
||
|
|
</Breadcrumbs>
|
||
|
|
|
||
|
|
<Box mb={4} sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
|
||
|
|
<SettingsIcon color="primary" sx={{ fontSize: 40 }} />
|
||
|
|
<Box>
|
||
|
|
<Typography variant="h4" fontWeight={800} color="text.primary">
|
||
|
|
User Management
|
||
|
|
</Typography>
|
||
|
|
<Typography variant="body1" color="text.secondary">
|
||
|
|
Assign Administrative privileges and manage user access.
|
||
|
|
</Typography>
|
||
|
|
</Box>
|
||
|
|
</Box>
|
||
|
|
|
||
|
|
{/* 3. Bootstrap Warning Box */}
|
||
|
|
{isBootstrap && (
|
||
|
|
<Alert severity="info" variant="outlined" sx={{ mb: 4, borderRadius: 2 }}>
|
||
|
|
You are authenticated via <strong>INITIAL_ADMIN_EMAIL</strong>.
|
||
|
|
This provides permanent access to this page regardless of database settings.
|
||
|
|
</Alert>
|
||
|
|
)}
|
||
|
|
|
||
|
|
{/* 4. User Management Table */}
|
||
|
|
<Paper elevation={0} sx={{ border: '1px solid #e0e0e0', borderRadius: 3, overflow: 'hidden' }}>
|
||
|
|
<Table>
|
||
|
|
<TableHead sx={{ bgcolor: '#f8f9fa' }}>
|
||
|
|
<TableRow>
|
||
|
|
<TableCell sx={{ fontWeight: 700 }}>User Identity</TableCell>
|
||
|
|
<TableCell sx={{ fontWeight: 700 }}>Current Role</TableCell>
|
||
|
|
<TableCell align="right" sx={{ fontWeight: 700 }}>Actions</TableCell>
|
||
|
|
</TableRow>
|
||
|
|
</TableHead>
|
||
|
|
<TableBody>
|
||
|
|
{allUsers.length > 0 ? (
|
||
|
|
allUsers.map((user) => (
|
||
|
|
<UserRow
|
||
|
|
key={user.id}
|
||
|
|
user={user}
|
||
|
|
currentUserId={dbUser?.id || ""}
|
||
|
|
isBootstrapAdmin={isBootstrap}
|
||
|
|
/>
|
||
|
|
))
|
||
|
|
) : (
|
||
|
|
<TableRow>
|
||
|
|
<TableCell colSpan={3} align="center" sx={{ py: 4 }}>
|
||
|
|
<Typography color="text.secondary">No users found in database.</Typography>
|
||
|
|
</TableCell>
|
||
|
|
</TableRow>
|
||
|
|
)}
|
||
|
|
</TableBody>
|
||
|
|
</Table>
|
||
|
|
</Paper>
|
||
|
|
|
||
|
|
<Box mt={3}>
|
||
|
|
<Typography variant="caption" color="text.secondary">
|
||
|
|
Note: Users must log out and log back in for role changes to take effect in their active session.
|
||
|
|
</Typography>
|
||
|
|
</Box>
|
||
|
|
</Container>
|
||
|
|
);
|
||
|
|
}
|