import { Elysia, t } from "elysia"; import { authMiddleware } from "../middlewares/auth"; import { eq } from "drizzle-orm"; import db from "../db"; import { apps } from "../db/schema/apps"; import { serverSessionService } from "../services/serverSession"; export const sessionController = new Elysia({ prefix: "/sessions" }) // Все роуты требуют авторизации .use(authMiddleware) // GET /sessions - получить список сессий пользователя .get("/", async ({ currentUser, query }) => { const { status, mode } = query as { status?: "starting" | "started" | "ending" | "ended"; mode?: "stream" | "local"; }; const sessions = await serverSessionService.findByUserId(currentUser.id, { status, mode, }); return { sessions }; }) // GET /sessions/:id - получить информацию о конкретной сессии .get("/:id", async ({ params, currentUser, status }) => { const { id } = params; const session = await serverSessionService.findByIdForUser( id, currentUser.id ); if (!session) { return status(404, "Session not found"); } return { session }; }) // POST /sessions - создать новую сессию .post( "/", async ({ body, currentUser, status }) => { const { appId, mode, serverId } = body as { appId: string; mode: "stream" | "local"; serverId?: string; }; // Проверить, что приложение существует const app = await db.query.apps.findFirst({ where: eq(apps.id, appId), }); if (!app) { return status(404, "App not found"); } // Проверить, что пользователь не имеет активных сессий этого приложения const hasActive = await serverSessionService.hasActiveSession( currentUser.id, appId ); if (hasActive) { return status(409, "User already has an active session for this app"); } // Создать сессию try { const newSession = await serverSessionService.create({ appId, userId: currentUser.id, mode, serverId, }); return { session: newSession }; } catch (error) { if (error instanceof Error) { return status(503, error.message); } return status(500, "Failed to create session"); } }, { body: t.Object({ appId: t.String({ format: "uuid" }), mode: t.Union([t.Literal("stream"), t.Literal("local")]), serverId: t.Optional(t.String({ format: "uuid" })), }), } ) // PATCH /sessions/:id - обновить статус сессии .patch( "/:id", async ({ params, body, currentUser, status }) => { const { id } = params; const { status: sessionStatus, appPid, cirrusPid, endAt, } = body as { status?: "starting" | "started" | "ending" | "ended"; appPid?: number; cirrusPid?: number; endAt?: string; }; // Проверить, что сессия существует и принадлежит пользователю const session = await serverSessionService.findByIdForUser( id, currentUser.id ); if (!session) { return status(404, "Session not found"); } // Обновить сессию const updatedSession = await serverSessionService.update(id, { status: sessionStatus, appPid, cirrusPid, endAt: endAt ? new Date(endAt) : undefined, }); return { session: updatedSession }; }, { body: t.Object({ status: t.Optional( t.Union([ t.Literal("starting"), t.Literal("started"), t.Literal("ending"), t.Literal("ended"), ]) ), appPid: t.Optional(t.Number()), cirrusPid: t.Optional(t.Number()), endAt: t.Optional(t.String({ format: "date-time" })), }), } ) // DELETE /sessions/:id - удалить (завершить) сессию .delete("/:id", async ({ params, currentUser, status }) => { const { id } = params; // Проверить, что сессия существует и принадлежит пользователю const session = await serverSessionService.findByIdForUser( id, currentUser.id ); if (!session) { return status(404, "Session not found"); } // Если сессия активна, изменить статус на "ending" if (session.status === "started" || session.status === "starting") { await serverSessionService.end(id); return { message: "Session is ending" }; } // Если сессия уже завершена или завершается return { message: "Session already ended or ending" }; }) // POST /sessions/:id/extend - продлить сессию .post( "/:id/extend", async ({ params, body, currentUser, status }) => { const { id } = params; const { minutes } = body as { minutes: number }; // Проверить, что сессия существует и принадлежит пользователю const session = await serverSessionService.findByIdForUser( id, currentUser.id ); if (!session) { return status(404, "Session not found"); } // Проверить, что сессия активна if (session.status !== "started") { return status(400, "Can only extend active sessions"); } // Продлить сессию try { const updatedSession = await serverSessionService.extend(id, minutes); return { session: updatedSession }; } catch (error) { if (error instanceof Error) { return status(400, error.message); } return status(500, "Failed to extend session"); } }, { body: t.Object({ minutes: t.Number({ minimum: 1, maximum: 120 }), }), } );