Implement company provisioning codes and session tweaks
This commit is contained in:
parent
0fb9bf59b2
commit
2cba553efa
28 changed files with 1407 additions and 534 deletions
|
|
@ -5,15 +5,13 @@ import { api } from "@/convex/_generated/api"
|
|||
import type { Id } from "@/convex/_generated/dataModel"
|
||||
import { env } from "@/lib/env"
|
||||
import { DEFAULT_TENANT_ID } from "@/lib/constants"
|
||||
import { ensureMachineAccount } from "@/server/machines-auth"
|
||||
import { ensureCollaboratorAccount, ensureMachineAccount } from "@/server/machines-auth"
|
||||
import { createCorsPreflight, jsonWithCors } from "@/server/cors"
|
||||
import { normalizeSlug } from "@/lib/slug"
|
||||
import { prisma } from "@/lib/prisma"
|
||||
|
||||
const registerSchema = z
|
||||
.object({
|
||||
provisioningSecret: z.string().min(1),
|
||||
tenantId: z.string().optional(),
|
||||
companySlug: z.string().optional(),
|
||||
provisioningCode: z.string().min(32),
|
||||
hostname: z.string().min(1),
|
||||
os: z.object({
|
||||
name: z.string().min(1),
|
||||
|
|
@ -67,13 +65,25 @@ export async function POST(request: Request) {
|
|||
}
|
||||
|
||||
const client = new ConvexHttpClient(convexUrl)
|
||||
let normalizedCompanySlug: string | undefined
|
||||
|
||||
try {
|
||||
const tenantId = payload.tenantId ?? DEFAULT_TENANT_ID
|
||||
const provisioningCode = payload.provisioningCode.trim().toLowerCase()
|
||||
const companyRecord = await prisma.company.findFirst({
|
||||
where: { provisioningCode },
|
||||
select: { id: true, tenantId: true, name: true, slug: true, provisioningCode: true },
|
||||
})
|
||||
|
||||
if (!companyRecord) {
|
||||
return jsonWithCors(
|
||||
{ error: "Código de provisionamento inválido" },
|
||||
404,
|
||||
request.headers.get("origin"),
|
||||
CORS_METHODS
|
||||
)
|
||||
}
|
||||
|
||||
const tenantId = companyRecord.tenantId ?? DEFAULT_TENANT_ID
|
||||
const persona = payload.accessRole ?? undefined
|
||||
const collaborator = payload.collaborator ?? null
|
||||
normalizedCompanySlug = normalizeSlug(payload.companySlug)
|
||||
|
||||
if (persona && !collaborator) {
|
||||
return jsonWithCors(
|
||||
|
|
@ -99,10 +109,15 @@ export async function POST(request: Request) {
|
|||
}
|
||||
}
|
||||
|
||||
const registration = await client.mutation(api.machines.register, {
|
||||
provisioningSecret: payload.provisioningSecret,
|
||||
await client.mutation(api.companies.ensureProvisioned, {
|
||||
tenantId,
|
||||
companySlug: normalizedCompanySlug,
|
||||
slug: companyRecord.slug,
|
||||
name: companyRecord.name,
|
||||
provisioningCode: companyRecord.provisioningCode,
|
||||
})
|
||||
|
||||
const registration = await client.mutation(api.machines.register, {
|
||||
provisioningCode,
|
||||
hostname: payload.hostname,
|
||||
os: payload.os,
|
||||
macAddresses: payload.macAddresses,
|
||||
|
|
@ -126,26 +141,39 @@ export async function POST(request: Request) {
|
|||
})
|
||||
|
||||
let assignedUserId: Id<"users"> | undefined
|
||||
if (persona && collaborator) {
|
||||
if (collaborator) {
|
||||
const ensuredUser = (await client.mutation(api.users.ensureUser, {
|
||||
tenantId,
|
||||
email: collaborator.email,
|
||||
name: collaborator.name ?? collaborator.email,
|
||||
avatarUrl: undefined,
|
||||
role: persona.toUpperCase(),
|
||||
role: persona?.toUpperCase(),
|
||||
companyId: registration.companyId ? (registration.companyId as Id<"companies">) : undefined,
|
||||
})) as { _id?: Id<"users"> } | null
|
||||
|
||||
assignedUserId = ensuredUser?._id
|
||||
|
||||
await client.mutation(api.machines.updatePersona, {
|
||||
machineId: registration.machineId as Id<"machines">,
|
||||
persona,
|
||||
...(assignedUserId ? { assignedUserId } : {}),
|
||||
assignedUserEmail: collaborator.email,
|
||||
assignedUserName: collaborator.name ?? undefined,
|
||||
assignedUserRole: persona === "manager" ? "MANAGER" : "COLLABORATOR",
|
||||
await ensureCollaboratorAccount({
|
||||
email: collaborator.email,
|
||||
name: collaborator.name ?? collaborator.email,
|
||||
tenantId,
|
||||
companyId: companyRecord.id,
|
||||
})
|
||||
|
||||
if (persona) {
|
||||
assignedUserId = ensuredUser?._id
|
||||
await client.mutation(api.machines.updatePersona, {
|
||||
machineId: registration.machineId as Id<"machines">,
|
||||
persona,
|
||||
...(assignedUserId ? { assignedUserId } : {}),
|
||||
assignedUserEmail: collaborator.email,
|
||||
assignedUserName: collaborator.name ?? undefined,
|
||||
assignedUserRole: persona === "manager" ? "MANAGER" : "COLLABORATOR",
|
||||
})
|
||||
} else {
|
||||
await client.mutation(api.machines.updatePersona, {
|
||||
machineId: registration.machineId as Id<"machines">,
|
||||
persona: "",
|
||||
})
|
||||
}
|
||||
} else {
|
||||
await client.mutation(api.machines.updatePersona, {
|
||||
machineId: registration.machineId as Id<"machines">,
|
||||
|
|
@ -174,18 +202,11 @@ export async function POST(request: Request) {
|
|||
console.error("[machines.register] Falha no provisionamento", error)
|
||||
const details = error instanceof Error ? error.message : String(error)
|
||||
const msg = details.toLowerCase()
|
||||
// Mapear alguns erros "esperados" para códigos adequados
|
||||
// - empresa inválida → 404
|
||||
// - segredo inválido → 401
|
||||
// - demais ConvexError → 400
|
||||
const isInvalidCode = msg.includes("código de provisionamento inválido")
|
||||
const isCompanyNotFound = msg.includes("empresa não encontrada")
|
||||
const isInvalidSecret = msg.includes("código de provisionamento inválido")
|
||||
const isConvexError = msg.includes("convexerror")
|
||||
const status = isCompanyNotFound ? 404 : isInvalidSecret ? 401 : isConvexError ? 400 : 500
|
||||
const payload = { error: "Falha ao provisionar máquina", details } as Record<string, unknown>
|
||||
if (isCompanyNotFound && normalizedCompanySlug) {
|
||||
payload["companySlug"] = normalizedCompanySlug
|
||||
}
|
||||
const status = isInvalidCode ? 401 : isCompanyNotFound ? 404 : isConvexError ? 400 : 500
|
||||
const payload = { error: "Falha ao provisionar máquina", details }
|
||||
return jsonWithCors(payload, status, request.headers.get("origin"), CORS_METHODS)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue