diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index df78617..d933205 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -12,7 +12,7 @@ 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, grantAdminRole, removeUserFriendships, revokeAdminRole, revokeInvite } from "@/lib/admin-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"; @@ -340,6 +340,8 @@ function InvitesPanel({ }>; rooms: Array<{ id: string; name: string; slug: string }>; }) { + const expiredInviteCount = invites.filter((invite) => invite.status === "ACTIVE" && isInviteExpired(invite.expiresAt)).length; + return (
@@ -361,6 +363,11 @@ function InvitesPanel({ + {expiredInviteCount > 0 ? ( +
+ +
+ ) : null} {invites.length === 0 ? ( ) : ( diff --git a/src/lib/admin-actions.ts b/src/lib/admin-actions.ts index 1e5cb10..6309471 100644 --- a/src/lib/admin-actions.ts +++ b/src/lib/admin-actions.ts @@ -125,6 +125,19 @@ export async function revokeInvite(formData: FormData) { revalidateAdmin(); } +export async function expireStaleInvites() { + const admin = await requireAdmin(); + const result = await prisma.invite.updateMany({ + where: { + status: "ACTIVE", + expiresAt: { lt: new Date() } + }, + data: { status: "EXPIRED" } + }); + await audit(admin.id, "admin.invites.expire", { expiredInvites: result.count }); + revalidateAdmin(); +} + async function audit(actorId: string, action: string, metadata: Prisma.InputJsonObject) { await prisma.auditEvent.create({ data: { actorId, action, metadata } }); }