172 lines
6 KiB
TypeScript
172 lines
6 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server"
|
|
import { cookies } from "next/headers"
|
|
import { ConvexHttpClient } from "convex/browser"
|
|
|
|
import { api } from "@/convex/_generated/api"
|
|
import type { Id } from "@/convex/_generated/dataModel"
|
|
import { env } from "@/lib/env"
|
|
import { assertAuthenticatedSession } from "@/lib/auth-server"
|
|
import { DEFAULT_TENANT_ID } from "@/lib/constants"
|
|
|
|
const MACHINE_CTX_COOKIE = "machine_ctx"
|
|
|
|
function decodeMachineCookie(value: string) {
|
|
try {
|
|
const json = Buffer.from(value, "base64url").toString("utf8")
|
|
return JSON.parse(json) as {
|
|
machineId: string
|
|
persona: string | null
|
|
assignedUserId: string | null
|
|
assignedUserEmail: string | null
|
|
assignedUserName: string | null
|
|
assignedUserRole: string | null
|
|
}
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
function encodeMachineCookie(payload: {
|
|
machineId: string
|
|
persona: string | null
|
|
assignedUserId: string | null
|
|
assignedUserEmail: string | null
|
|
assignedUserName: string | null
|
|
assignedUserRole: string | null
|
|
}) {
|
|
return Buffer.from(JSON.stringify(payload)).toString("base64url")
|
|
}
|
|
|
|
export async function GET(request: NextRequest) {
|
|
const session = await assertAuthenticatedSession()
|
|
if (!session || session.user?.role !== "machine") {
|
|
return NextResponse.json({ error: "Sessão de máquina não encontrada." }, { status: 403 })
|
|
}
|
|
|
|
const convexUrl = env.NEXT_PUBLIC_CONVEX_URL
|
|
if (!convexUrl) {
|
|
return NextResponse.json({ error: "Convex não configurado." }, { status: 500 })
|
|
}
|
|
|
|
const client = new ConvexHttpClient(convexUrl)
|
|
const cookieStore = await cookies()
|
|
const cookieValue = cookieStore.get(MACHINE_CTX_COOKIE)?.value ?? null
|
|
|
|
const decoded = cookieValue ? decodeMachineCookie(cookieValue) : null
|
|
let machineId: Id<"machines"> | null = decoded?.machineId ? (decoded.machineId as Id<"machines">) : null
|
|
|
|
if (!machineId) {
|
|
try {
|
|
const lookup = (await client.query(api.machines.findByAuthEmail, {
|
|
authEmail: session.user.email.toLowerCase(),
|
|
})) as { id: string } | null
|
|
|
|
if (!lookup?.id) {
|
|
return NextResponse.json({ error: "Máquina não vinculada à sessão atual." }, { status: 404 })
|
|
}
|
|
|
|
machineId = lookup.id as Id<"machines">
|
|
} catch (error) {
|
|
console.error("[machines.session] Falha ao localizar máquina por e-mail", error)
|
|
return NextResponse.json({ error: "Não foi possível localizar a máquina." }, { status: 500 })
|
|
}
|
|
}
|
|
|
|
try {
|
|
let context = (await client.query(api.machines.getContext, {
|
|
machineId,
|
|
})) as {
|
|
id: string
|
|
tenantId: string
|
|
companyId: string | null
|
|
companySlug: string | null
|
|
persona: string | null
|
|
assignedUserId: string | null
|
|
assignedUserEmail: string | null
|
|
assignedUserName: string | null
|
|
assignedUserRole: string | null
|
|
metadata: Record<string, unknown> | null
|
|
authEmail: string | null
|
|
}
|
|
|
|
let ensuredAssignedUserId = context.assignedUserId
|
|
let ensuredAssignedUserName = context.assignedUserName
|
|
let ensuredAssignedUserRole = context.assignedUserRole
|
|
|
|
if (!ensuredAssignedUserId && context.persona && context.assignedUserEmail) {
|
|
try {
|
|
const ensuredUser = (await client.mutation(api.users.ensureUser, {
|
|
tenantId: context.tenantId ?? DEFAULT_TENANT_ID,
|
|
email: context.assignedUserEmail,
|
|
name: context.assignedUserName ?? context.assignedUserEmail,
|
|
role: (context.assignedUserRole ?? context.persona ?? "collaborator").toUpperCase(),
|
|
companyId: context.companyId ? (context.companyId as Id<"companies">) : undefined,
|
|
})) as {
|
|
_id?: Id<"users">
|
|
name?: string | null
|
|
role?: string | null
|
|
} | null
|
|
|
|
if (ensuredUser?._id) {
|
|
ensuredAssignedUserId = ensuredUser._id as string
|
|
ensuredAssignedUserName = ensuredUser.name ?? context.assignedUserName
|
|
ensuredAssignedUserRole = ensuredUser.role ?? context.assignedUserRole
|
|
|
|
await client.mutation(api.machines.updatePersona, {
|
|
machineId: machineId as Id<"machines">,
|
|
persona: context.persona ?? undefined,
|
|
assignedUserId: ensuredUser._id as Id<"users">,
|
|
assignedUserEmail: context.assignedUserEmail,
|
|
assignedUserName: ensuredAssignedUserName ?? undefined,
|
|
assignedUserRole: (ensuredAssignedUserRole ?? context.persona ?? "collaborator").toUpperCase(),
|
|
})
|
|
|
|
context = (await client.query(api.machines.getContext, {
|
|
machineId,
|
|
})) as typeof context
|
|
|
|
ensuredAssignedUserId = context.assignedUserId ?? ensuredAssignedUserId
|
|
ensuredAssignedUserName = context.assignedUserName ?? ensuredAssignedUserName
|
|
ensuredAssignedUserRole = context.assignedUserRole ?? ensuredAssignedUserRole
|
|
}
|
|
} catch (error) {
|
|
console.error("[machines.session] Falha ao garantir usuário vinculado", error)
|
|
}
|
|
}
|
|
|
|
const responsePayload = {
|
|
machineId: context.id,
|
|
persona: context.persona,
|
|
assignedUserId: ensuredAssignedUserId,
|
|
assignedUserEmail: context.assignedUserEmail,
|
|
assignedUserName: ensuredAssignedUserName,
|
|
assignedUserRole: ensuredAssignedUserRole,
|
|
}
|
|
|
|
const response = NextResponse.json({
|
|
machine: {
|
|
...context,
|
|
assignedUserId: ensuredAssignedUserId ?? null,
|
|
assignedUserName: ensuredAssignedUserName ?? null,
|
|
assignedUserRole: ensuredAssignedUserRole ?? null,
|
|
},
|
|
cookie: responsePayload,
|
|
})
|
|
|
|
const isSecure = request.nextUrl.protocol === "https:"
|
|
response.cookies.set({
|
|
name: MACHINE_CTX_COOKIE,
|
|
value: encodeMachineCookie(responsePayload),
|
|
httpOnly: true,
|
|
sameSite: "lax",
|
|
secure: isSecure,
|
|
path: "/",
|
|
maxAge: 60 * 60 * 24 * 30,
|
|
})
|
|
|
|
return response
|
|
} catch (error) {
|
|
console.error("[machines.session] Falha ao obter contexto da máquina", error)
|
|
return NextResponse.json({ error: "Falha ao obter contexto da máquina." }, { status: 500 })
|
|
}
|
|
}
|