import Link from "next/link";
import { AlertTriangle, Database, LockKeyhole, Plus, Search, Shield, UsersRound } from "lucide-react";
import { redirect } from "next/navigation";
import { AppShell } from "@/components/app-shell";
import { Avatar } from "@/components/avatar";
import { StatusBadge } from "@/components/status-badge";
import { SYSTEM_PERMISSIONS } from "@/lib/access";
import { prisma } from "@/lib/prisma";
import { getShellContext } from "@/lib/shell";
import { requireCurrentUser, userIsAdmin } from "@/lib/session";
import { requireInitialSetup } from "@/lib/setup";
import { DataTable, EmptyState, MetricTile, PageHeader, Panel, StatusDot, Tabs } from "@/components/ui";
import { getAppSettings, type AppSettings } from "@/lib/settings";
import { updateInstanceSettings, updateSecuritySettings } from "@/lib/settings-actions";
import { banUser, createInstanceInvite, disableUser, enableUser, expireStaleInvites, grantAdminRole, removeUserFriendships, revokeAdminRole, revokeInvite } from "@/lib/admin-actions";
import { deleteRoom } from "@/lib/room-actions";
import { isInviteExpired } from "@/lib/invites";
export const dynamic = "force-dynamic";
const adminTabs = ["Users", "Rooms", "Roles", "Invites", "Instance", "Security"];
export default async function AdminPage({ searchParams }: { searchParams: Promise<{ tab?: string; q?: string; saved?: string }> }) {
await requireInitialSetup();
const user = await requireCurrentUser();
if (!userIsAdmin(user)) {
redirect("/dashboard");
}
const { tab = "Users", q = "", saved } = await searchParams;
const activeTab = adminTabs.includes(tab) ? tab : "Users";
const query = q.trim().toLowerCase();
const shell = await getShellContext(user);
const [users, rooms, roles, pendingRequests, appSettings, invites, auditEvents] = await Promise.all([
prisma.user.findMany({
include: {
roles: { include: { role: true } },
_count: { select: { ownedRooms: true, roomMembers: true, sentFriends: true, gotFriends: true } }
},
orderBy: { createdAt: "asc" }
}),
prisma.room.findMany({
include: { owner: true, _count: { select: { members: true, mediaSources: true } } },
orderBy: { updatedAt: "desc" }
}),
prisma.role.findMany({
include: { _count: { select: { users: true, permissions: true } } },
orderBy: { name: "asc" }
}),
prisma.friendship.count({ where: { status: "PENDING" } }),
getAppSettings(),
prisma.invite.findMany({ include: { room: true, creator: true }, orderBy: { createdAt: "desc" }, take: 50 }),
prisma.auditEvent.findMany({ include: { actor: true, room: true }, orderBy: { createdAt: "desc" }, take: 20 })
]);
const filteredUsers = query
? users.filter((account) =>
[account.username, account.displayName || "", ...account.roles.map((role) => role.role.name)].join(" ").toLowerCase().includes(query)
)
: users;
const filteredRooms = query
? rooms.filter((room) =>
[room.name, room.slug, room.visibility, room.owner?.username || "", room.owner?.displayName || ""].join(" ").toLowerCase().includes(query)
)
: rooms;
const filteredRoles = query
? roles.filter((role) => [role.name, role.description || "", role.scope].join(" ").toLowerCase().includes(query))
: roles;
return (
{users.map((account) => (
User
Roles
Rooms
Friends
Created
Actions
))}
{account._count.ownedRooms + account._count.roomMembers}
{account._count.sentFriends + account._count.gotFriends}
{account.disabledAt ?
{rooms.map((room) => (
Room
Owner
Access
State
Updated
))}
{room.owner?.displayName || room.owner?.username || "Unassigned"}
{room._count.members + 1} users / {room._count.mediaSources} media
{formatDate(room.updatedAt)}
Instance settings saved.
: null}Security settings saved.
: null}