diff --git a/backend/database/src/index.ts b/backend/database/src/index.ts
index 314c9d0..a116e01 100644
--- a/backend/database/src/index.ts
+++ b/backend/database/src/index.ts
@@ -1,4 +1,4 @@
-import type { DrizzleD1Database } from "drizzle-orm/d1";
+// import type { DrizzleD1Database } from "drizzle-orm/d1";
import { drizzle } from "drizzle-orm/d1";
import { json } from "itty-router-extras";
import { ZodError, z } from "zod";
@@ -10,6 +10,7 @@ import { and, eq, sql } from "drizzle-orm";
export interface Env {
DB: D1Database;
STORAGE: any;
+ KV: KVNamespace;
}
// https://github.com/drizzle-team/drizzle-orm/tree/main/examples/cloudflare-d1
@@ -30,7 +31,35 @@ export default {
const db = drizzle(env.DB, { schema });
- if (path === "/api/sandbox") {
+ if (path === "/api/session") {
+ if (method === "PUT") {
+ const body = await request.json();
+ const schema = z.object({
+ userId: z.string(),
+ sandboxId: z.string(),
+ });
+
+ const { userId, sandboxId } = schema.parse(body);
+
+ await env.KV.put(userId, sandboxId);
+
+ return success;
+ } else if (method === "GET") {
+ const params = url.searchParams;
+ if (params.has("id")) {
+ const id = params.get("id") as string;
+ const sandboxId = await env.KV.get(id);
+ return json({ sandboxId });
+ } else return invalidRequest;
+ } else if (method === "DELETE") {
+ const params = url.searchParams;
+ if (params.has("id")) {
+ const id = params.get("id") as string;
+ await env.KV.delete(id);
+ return success;
+ } else return invalidRequest;
+ } else return methodNotAllowed;
+ } else if (path === "/api/sandbox") {
if (method === "GET") {
const params = url.searchParams;
if (params.has("id")) {
@@ -65,14 +94,14 @@ export default {
return invalidRequest;
}
} else if (method === "POST") {
- const initSchema = z.object({
+ const postSchema = z.object({
id: z.string(),
name: z.string().optional(),
visibility: z.enum(["public", "private"]).optional(),
});
const body = await request.json();
- const { id, name, visibility } = initSchema.parse(body);
+ const { id, name, visibility } = postSchema.parse(body);
const sb = await db.update(sandbox).set({ name, visibility }).where(eq(sandbox.id, id)).returning().get();
return success;
@@ -99,9 +128,8 @@ export default {
body: JSON.stringify({ sandboxId: sb.id, type }),
headers: { "Content-Type": "application/json" },
});
- const initStorageRes = await env.STORAGE.fetch(initStorageRequest);
- // const initStorage = await initStorageRes.text();
+ await env.STORAGE.fetch(initStorageRequest);
return new Response(sb.id, { status: 200 });
} else {
diff --git a/backend/server/dockerfile b/backend/server/dockerfile
index 31f5512..cc82df0 100644
--- a/backend/server/dockerfile
+++ b/backend/server/dockerfile
@@ -2,8 +2,8 @@ FROM node:20
# Security: Drop all capabilities
USER root
-RUN apt-get update && apt-get install -y libcap2-bin && \
- setcap cap_net_bind_service=+ep /usr/local/bin/node
+RUN apt-get update && apt-get install -y libcap2-bin
+RUN setcap cap_net_bind_service=+ep /usr/local/bin/node
WORKDIR /code
@@ -15,21 +15,14 @@ COPY . .
RUN npm run build
+# Security: Create non-root user and assign ownership
RUN useradd -m sboxuser
RUN mkdir projects && chown -R sboxuser:sboxuser projects
-
-# todo user namespace mapping
-
-RUN apt-get install -y firejail
-# RUN echo "noblacklist /code/projects\nprivate-bin node\nwhitelist /code/projects\n" > /etc/firejail/sboxuser.profile
-
-# RUN echo '#!/bin/bash\nexec firejail --private=/projects --noprofile node dist/index.js' > /start.sh
-RUN echo '#!/bin/bash\nexec firejail --private=/code/projects --noprofile --net=none --whitelist=/code/projects node dist/index.js' > /start.sh
-RUN chmod +x /start.sh
-
USER sboxuser
-EXPOSE 8000
-EXPOSE 4000
+# user namespace mapping
-CMD ["/start.sh"]
+EXPOSE 8000
+EXPOSE 5173
+
+CMD [ "node", "dist/index.js" ]
\ No newline at end of file
diff --git a/frontend/components/editor/index.tsx b/frontend/components/editor/index.tsx
index 25b37fd..32426a1 100644
--- a/frontend/components/editor/index.tsx
+++ b/frontend/components/editor/index.tsx
@@ -34,50 +34,55 @@ export default function Editor({
return;
}
- startServer(sandboxData.id).then((response) => {
- if (!response.success) {
- toast.error(response.message);
- setDidFail(true);
- } else {
- setIsServiceRunning(true);
+ // startServer(sandboxData.id).then((response) => {
+ // if (!response.success) {
+ // toast.error(response.message);
+ // setDidFail(true);
+ // } else {
+ // setIsServiceRunning(true);
- checkServiceStatus(sandboxData.id)
- .then(() => {
- setIsDeploymentActive(true);
+ // checkServiceStatus(sandboxData.id)
+ // .then(() => {
+ // setIsDeploymentActive(true);
- getTaskIp(sandboxData.id)
- .then((ip) => {
- setTaskIp(ip);
- })
- .catch(() => {
- setDidFail(true);
- toast.error("An error occurred while getting your server IP.");
- });
- })
- .catch(() => {
- toast.error("An error occurred while initializing your server.");
- setDidFail(true);
- });
- }
- });
+ // getTaskIp(sandboxData.id)
+ // .then((ip) => {
+ // setTaskIp(ip);
+ // })
+ // .catch(() => {
+ // setDidFail(true);
+ // toast.error("An error occurred while getting your server IP.");
+ // });
+ // })
+ // .catch(() => {
+ // toast.error("An error occurred while initializing your server.");
+ // setDidFail(true);
+ // });
+ // }
+ // });
}, []);
- if (didFail) return ;
- if (!isServiceRunning || !isDeploymentActive || !taskIp)
- return (
-
- );
+ // if (didFail) return ;
+ // if (!isServiceRunning || !isDeploymentActive || !taskIp)
+ // return (
+ //
+ // );
return (
-
+
);
}