Files
remotelink-docker/app/api/connect/route.ts
monoadmin e16a2fa978 Add Python agent, WebSocket relay, real viewer, enrollment tokens
- WebSocket relay service (FastAPI) bridges agents and viewers
- Python agent with screen capture (mss), input control (pynput),
  script execution, and auto-reconnect
- Windows service wrapper, PyInstaller spec, NSIS installer for
  silent mass deployment (RemoteLink-Setup.exe /S /SERVER= /ENROLL=)
- Enrollment token system: admin generates tokens, agents self-register
- Real WebSocket viewer replaces simulated canvas
- Linux agent binary served from /downloads/remotelink-agent-linux
- DB migration 0002: viewer_token on sessions, enrollment_tokens table
- Sign-up pages cleaned up (invite-only redirect)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 16:25:10 -07:00

72 lines
2.1 KiB
TypeScript

import { auth } from '@/auth'
import { db } from '@/lib/db'
import { sessionCodes, sessions, machines } from '@/lib/db/schema'
import { eq, and, isNull, gt } from 'drizzle-orm'
import { NextRequest, NextResponse } from 'next/server'
export async function POST(request: NextRequest) {
const session = await auth()
if (!session?.user?.id) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { code } = await request.json()
if (!code || typeof code !== 'string') {
return NextResponse.json({ error: 'Code required' }, { status: 400 })
}
const normalizedCode = code.replace(/\s/g, '').toUpperCase()
// Find valid, unused session code
const codeResult = await db
.select()
.from(sessionCodes)
.where(
and(
eq(sessionCodes.code, normalizedCode),
eq(sessionCodes.isActive, true),
gt(sessionCodes.expiresAt, new Date()),
isNull(sessionCodes.usedAt)
)
)
.limit(1)
const sessionCode = codeResult[0]
if (!sessionCode) {
return NextResponse.json({ error: 'Invalid or expired session code' }, { status: 400 })
}
// Look up machine name
const machineResult = await db
.select({ name: machines.name })
.from(machines)
.where(eq(machines.id, sessionCode.machineId))
.limit(1)
const machineName = machineResult[0]?.name ?? 'Remote Machine'
// Mark code as used
await db
.update(sessionCodes)
.set({ usedAt: new Date(), usedBy: session.user.id, isActive: false })
.where(eq(sessionCodes.id, sessionCode.id))
// Create session record (viewer_token is auto-generated by DB default)
const newSession = await db
.insert(sessions)
.values({
machineId: sessionCode.machineId,
machineName,
viewerUserId: session.user.id,
connectionType: 'session_code',
sessionCode: normalizedCode,
})
.returning({ id: sessions.id, viewerToken: sessions.viewerToken })
return NextResponse.json({
sessionId: newSession[0].id,
viewerToken: newSession[0].viewerToken,
machineId: sessionCode.machineId,
})
}