Fix form template labels and guard admin auth tables
This commit is contained in:
parent
003d068c56
commit
7fb6c65d9a
2 changed files with 113 additions and 65 deletions
|
|
@ -1,3 +1,5 @@
|
|||
import { Prisma } from "@prisma/client"
|
||||
|
||||
import { AdminUsersManager } from "@/components/admin/admin-users-manager"
|
||||
import { AppShell } from "@/components/app-shell"
|
||||
import { SiteHeader } from "@/components/site-header"
|
||||
|
|
@ -10,80 +12,111 @@ import { getServerSession } from "@/lib/auth-server"
|
|||
export const runtime = "nodejs"
|
||||
export const dynamic = "force-dynamic"
|
||||
|
||||
async function loadUsers() {
|
||||
const users = await prisma.authUser.findMany({
|
||||
orderBy: { createdAt: "desc" },
|
||||
select: {
|
||||
id: true,
|
||||
email: true,
|
||||
name: true,
|
||||
role: true,
|
||||
tenantId: true,
|
||||
machinePersona: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
},
|
||||
})
|
||||
function isMissingAuthTableError(error: unknown, table: string): boolean {
|
||||
if (!(error instanceof Prisma.PrismaClientKnownRequestError)) {
|
||||
return false
|
||||
}
|
||||
if (error.code !== "P2021" && error.code !== "P2023") {
|
||||
return false
|
||||
}
|
||||
const target = typeof error.meta?.table === "string" ? error.meta.table.toLowerCase() : ""
|
||||
return target.includes(table.toLowerCase())
|
||||
}
|
||||
|
||||
const domainUsers = await prisma.user.findMany({
|
||||
select: {
|
||||
email: true,
|
||||
companyId: true,
|
||||
company: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
async function loadUsers() {
|
||||
try {
|
||||
const users = await prisma.authUser.findMany({
|
||||
orderBy: { createdAt: "desc" },
|
||||
select: {
|
||||
id: true,
|
||||
email: true,
|
||||
name: true,
|
||||
role: true,
|
||||
tenantId: true,
|
||||
machinePersona: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
},
|
||||
})
|
||||
|
||||
if (users.length === 0) {
|
||||
return []
|
||||
}
|
||||
|
||||
const domainUsers = await prisma.user.findMany({
|
||||
select: {
|
||||
email: true,
|
||||
companyId: true,
|
||||
company: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
const domainByEmail = new Map<string, (typeof domainUsers)[number]>(
|
||||
domainUsers.map(
|
||||
(user: (typeof domainUsers)[number]): [string, (typeof domainUsers)[number]] => [
|
||||
user.email.toLowerCase(),
|
||||
user,
|
||||
]
|
||||
const domainByEmail = new Map<string, (typeof domainUsers)[number]>(
|
||||
domainUsers.map(
|
||||
(user: (typeof domainUsers)[number]): [string, (typeof domainUsers)[number]] => [
|
||||
user.email.toLowerCase(),
|
||||
user,
|
||||
]
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
return users.map((user: (typeof users)[number]) => {
|
||||
const domain = domainByEmail.get(user.email.toLowerCase())
|
||||
const normalizedRole = (normalizeRole(user.role) ?? "agent") as RoleOption
|
||||
return {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
name: user.name ?? "",
|
||||
role: normalizedRole,
|
||||
tenantId: user.tenantId ?? DEFAULT_TENANT_ID,
|
||||
createdAt: user.createdAt.toISOString(),
|
||||
updatedAt: user.updatedAt?.toISOString() ?? null,
|
||||
companyId: domain?.companyId ?? null,
|
||||
companyName: domain?.company?.name ?? null,
|
||||
machinePersona: user.machinePersona ?? null,
|
||||
return users.map((user: (typeof users)[number]) => {
|
||||
const domain = domainByEmail.get(user.email.toLowerCase())
|
||||
const normalizedRole = (normalizeRole(user.role) ?? "agent") as RoleOption
|
||||
return {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
name: user.name ?? "",
|
||||
role: normalizedRole,
|
||||
tenantId: user.tenantId ?? DEFAULT_TENANT_ID,
|
||||
createdAt: user.createdAt.toISOString(),
|
||||
updatedAt: user.updatedAt?.toISOString() ?? null,
|
||||
companyId: domain?.companyId ?? null,
|
||||
companyName: domain?.company?.name ?? null,
|
||||
machinePersona: user.machinePersona ?? null,
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
if (isMissingAuthTableError(error, "AuthUser")) {
|
||||
console.warn("[admin] auth tables missing; returning empty user list")
|
||||
return []
|
||||
}
|
||||
})
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async function loadInvites(): Promise<NormalizedInvite[]> {
|
||||
const invites = await prisma.authInvite.findMany({
|
||||
orderBy: { createdAt: "desc" },
|
||||
include: {
|
||||
events: {
|
||||
orderBy: { createdAt: "asc" },
|
||||
try {
|
||||
const invites = await prisma.authInvite.findMany({
|
||||
orderBy: { createdAt: "desc" },
|
||||
include: {
|
||||
events: {
|
||||
orderBy: { createdAt: "asc" },
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const now = new Date()
|
||||
const cutoff = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000)
|
||||
return invites
|
||||
.map((invite: (typeof invites)[number]) => normalizeInvite(invite, now))
|
||||
.filter((invite: NormalizedInvite) => {
|
||||
if (invite.status !== "revoked") return true
|
||||
if (!invite.revokedAt) return true
|
||||
return new Date(invite.revokedAt) > cutoff
|
||||
})
|
||||
|
||||
const now = new Date()
|
||||
const cutoff = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000)
|
||||
return invites
|
||||
.map((invite) => normalizeInvite(invite, now))
|
||||
.filter((invite: NormalizedInvite) => {
|
||||
if (invite.status !== "revoked") return true
|
||||
if (!invite.revokedAt) return true
|
||||
return new Date(invite.revokedAt) > cutoff
|
||||
})
|
||||
} catch (error) {
|
||||
if (isMissingAuthTableError(error, "AuthInvite")) {
|
||||
console.warn("[admin] auth invite tables missing; returning empty invite list")
|
||||
return []
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
export default async function AdminPage() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue