feat: cadastro manual de acesso remoto e ajustes de horas

This commit is contained in:
Esdras Renan 2025-10-24 23:52:58 -03:00
parent 8e3cbc7a9a
commit f3a7045691
16 changed files with 1549 additions and 207 deletions

View file

@ -0,0 +1,89 @@
import { NextResponse } from "next/server"
import { z } from "zod"
import { ConvexHttpClient } from "convex/browser"
import { assertStaffSession } from "@/lib/auth-server"
import type { Id } from "@/convex/_generated/dataModel"
export const runtime = "nodejs"
const schema = z.object({
machineId: z.string().min(1),
provider: z.string().optional(),
identifier: z.string().optional(),
url: z.string().optional(),
notes: z.string().optional(),
action: z.enum(["save", "clear"]).optional(),
})
export async function POST(request: Request) {
const session = await assertStaffSession()
if (!session) {
return NextResponse.json({ error: "Não autorizado" }, { status: 401 })
}
if (!session.user.id) {
return NextResponse.json({ error: "Sessão inválida" }, { status: 400 })
}
let parsed: z.infer<typeof schema>
try {
const body = await request.json()
parsed = schema.parse(body)
} catch {
return NextResponse.json({ error: "Payload inválido" }, { status: 400 })
}
const convexUrl = process.env.NEXT_PUBLIC_CONVEX_URL
if (!convexUrl) {
return NextResponse.json({ error: "Convex não configurado" }, { status: 500 })
}
const client = new ConvexHttpClient(convexUrl)
try {
const action = parsed.action ?? "save"
if (action === "clear") {
const result = (await (client as unknown as { mutation: (name: string, args: Record<string, unknown>) => Promise<unknown> }).mutation("machines:updateRemoteAccess", {
machineId: parsed.machineId as Id<"machines">,
actorId: session.user.id as Id<"users">,
clear: true,
})) as { remoteAccess?: unknown } | null
return NextResponse.json({ ok: true, remoteAccess: result?.remoteAccess ?? null })
}
const provider = (parsed.provider ?? "").trim()
const identifier = (parsed.identifier ?? "").trim()
if (!provider || !identifier) {
return NextResponse.json({ error: "Informe o provedor e o identificador do acesso remoto." }, { status: 400 })
}
let normalizedUrl: string | undefined
const rawUrl = (parsed.url ?? "").trim()
if (rawUrl.length > 0) {
const candidate = /^https?:\/\//i.test(rawUrl) ? rawUrl : `https://${rawUrl}`
try {
new URL(candidate)
normalizedUrl = candidate
} catch {
return NextResponse.json({ error: "URL inválida. Informe um endereço iniciado com http:// ou https://." }, { status: 422 })
}
}
const notes = (parsed.notes ?? "").trim()
const result = (await (client as unknown as { mutation: (name: string, args: Record<string, unknown>) => Promise<unknown> }).mutation("machines:updateRemoteAccess", {
machineId: parsed.machineId as Id<"machines">,
actorId: session.user.id as Id<"users">,
provider,
identifier,
url: normalizedUrl,
notes: notes.length ? notes : undefined,
})) as { remoteAccess?: unknown } | null
return NextResponse.json({ ok: true, remoteAccess: result?.remoteAccess ?? null })
} catch (error) {
console.error("[machines.remote-access]", error)
return NextResponse.json({ error: "Falha ao atualizar acesso remoto" }, { status: 500 })
}
}