works
This commit is contained in:
parent
08a898a82a
commit
74bb83f3ed
@ -237,7 +237,9 @@ export default {
|
|||||||
const res = await db.query.user.findFirst({
|
const res = await db.query.user.findFirst({
|
||||||
where: (user, { eq }) => eq(user.id, id),
|
where: (user, { eq }) => eq(user.id, id),
|
||||||
with: {
|
with: {
|
||||||
sandbox: true,
|
sandbox: {
|
||||||
|
orderBy: (sandbox, { desc }) => [desc(sandbox.createdAt)],
|
||||||
|
},
|
||||||
usersToSandboxes: true,
|
usersToSandboxes: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -16,13 +16,13 @@ COPY . .
|
|||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
# Security: Create non-root user and assign ownership
|
# Security: Create non-root user and assign ownership
|
||||||
RUN useradd -m sboxuser
|
RUN useradd -m appuser
|
||||||
RUN mkdir projects && chown -R sboxuser:sboxuser projects
|
RUN mkdir projects && chown -R appuser:appuser projects
|
||||||
USER sboxuser
|
USER appuser
|
||||||
|
|
||||||
# user namespace mapping
|
# todo user namespace mapping
|
||||||
|
|
||||||
EXPOSE 8000
|
EXPOSE 3000
|
||||||
EXPOSE 5173
|
EXPOSE 4000
|
||||||
|
|
||||||
CMD [ "node", "dist/index.js" ]
|
CMD [ "node", "dist/index.js" ]
|
@ -51,19 +51,21 @@ const terminals: {
|
|||||||
|
|
||||||
const dirName = path.join(__dirname, "..");
|
const dirName = path.join(__dirname, "..");
|
||||||
|
|
||||||
const handshakeSchema = z.object({
|
|
||||||
userId: z.string(),
|
|
||||||
sandboxId: z.string(),
|
|
||||||
EIO: z.string(),
|
|
||||||
transport: z.string(),
|
|
||||||
});
|
|
||||||
|
|
||||||
io.use(async (socket, next) => {
|
io.use(async (socket, next) => {
|
||||||
|
console.log("Middleware");
|
||||||
|
|
||||||
|
const handshakeSchema = z.object({
|
||||||
|
userId: z.string(),
|
||||||
|
sandboxId: z.string(),
|
||||||
|
EIO: z.string(),
|
||||||
|
transport: z.string(),
|
||||||
|
});
|
||||||
|
|
||||||
const q = socket.handshake.query;
|
const q = socket.handshake.query;
|
||||||
const parseQuery = handshakeSchema.safeParse(q);
|
const parseQuery = handshakeSchema.safeParse(q);
|
||||||
|
|
||||||
if (!parseQuery.success) {
|
if (!parseQuery.success) {
|
||||||
("Invalid request.");
|
console.log("Invalid request.");
|
||||||
next(new Error("Invalid request."));
|
next(new Error("Invalid request."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -75,6 +77,7 @@ io.use(async (socket, next) => {
|
|||||||
const dbUserJSON = (await dbUser.json()) as User;
|
const dbUserJSON = (await dbUser.json()) as User;
|
||||||
|
|
||||||
if (!dbUserJSON) {
|
if (!dbUserJSON) {
|
||||||
|
console.log("DB error.");
|
||||||
next(new Error("DB error."));
|
next(new Error("DB error."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -85,6 +88,7 @@ io.use(async (socket, next) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!sandbox && !sharedSandboxes) {
|
if (!sandbox && !sharedSandboxes) {
|
||||||
|
console.log("Invalid credentials.");
|
||||||
next(new Error("Invalid credentials."));
|
next(new Error("Invalid credentials."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -145,6 +149,7 @@ io.on("connection", async (socket) => {
|
|||||||
|
|
||||||
// todo: send diffs + debounce for efficiency
|
// todo: send diffs + debounce for efficiency
|
||||||
socket.on("saveFile", async (fileId: string, body: string) => {
|
socket.on("saveFile", async (fileId: string, body: string) => {
|
||||||
|
console.log("save");
|
||||||
try {
|
try {
|
||||||
await saveFileRL.consume(data.userId, 1);
|
await saveFileRL.consume(data.userId, 1);
|
||||||
|
|
||||||
@ -470,5 +475,5 @@ io.on("connection", async (socket) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
httpServer.listen(port, () => {
|
httpServer.listen(port, () => {
|
||||||
console.log(`Server, running on port ${port}`);
|
console.log(`Server 123, running on port ${port}`);
|
||||||
});
|
});
|
||||||
|
@ -56,8 +56,9 @@ import react from '@vitejs/plugin-react'
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()],
|
plugins: [react()],
|
||||||
server: {
|
server: {
|
||||||
port: 8000,
|
port: 3000,
|
||||||
},
|
host: "0.0.0.0",
|
||||||
|
}
|
||||||
})
|
})
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
@ -87,10 +88,12 @@ export default defineConfig({
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
|
font-family: sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
color: #fff;
|
color: #000;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,10 +90,6 @@ export default function CodeEditor({
|
|||||||
terminal: Terminal | null;
|
terminal: Terminal | null;
|
||||||
}[]
|
}[]
|
||||||
>([]);
|
>([]);
|
||||||
const [activeTerminalId, setActiveTerminalId] = useState("");
|
|
||||||
const [creatingTerminal, setCreatingTerminal] = useState(false);
|
|
||||||
const [closingTerminal, setClosingTerminal] = useState("");
|
|
||||||
const activeTerminal = terminals.find((t) => t.id === activeTerminalId);
|
|
||||||
|
|
||||||
const isOwner = sandboxData.userId === userData.id;
|
const isOwner = sandboxData.userId === userData.id;
|
||||||
const clerk = useClerk();
|
const clerk = useClerk();
|
||||||
@ -752,14 +748,7 @@ export default function CodeEditor({
|
|||||||
<Terminals
|
<Terminals
|
||||||
terminals={terminals}
|
terminals={terminals}
|
||||||
setTerminals={setTerminals}
|
setTerminals={setTerminals}
|
||||||
activeTerminalId={activeTerminalId}
|
|
||||||
setActiveTerminalId={setActiveTerminalId}
|
|
||||||
socket={socket}
|
socket={socket}
|
||||||
activeTerminal={activeTerminal}
|
|
||||||
creatingTerminal={creatingTerminal}
|
|
||||||
setCreatingTerminal={setCreatingTerminal}
|
|
||||||
closingTerminal={closingTerminal}
|
|
||||||
setClosingTerminal={setClosingTerminal}
|
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="w-full h-full flex items-center justify-center text-lg font-medium text-muted-foreground/50 select-none">
|
<div className="w-full h-full flex items-center justify-center text-lg font-medium text-muted-foreground/50 select-none">
|
||||||
|
@ -34,55 +34,50 @@ export default function Editor({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// startServer(sandboxData.id).then((response) => {
|
startServer(sandboxData.id).then((response) => {
|
||||||
// if (!response.success) {
|
if (!response.success) {
|
||||||
// toast.error(response.message);
|
toast.error(response.message);
|
||||||
// setDidFail(true);
|
setDidFail(true);
|
||||||
// } else {
|
} else {
|
||||||
// setIsServiceRunning(true);
|
setIsServiceRunning(true);
|
||||||
|
|
||||||
// checkServiceStatus(sandboxData.id)
|
checkServiceStatus(sandboxData.id)
|
||||||
// .then(() => {
|
.then(() => {
|
||||||
// setIsDeploymentActive(true);
|
setIsDeploymentActive(true);
|
||||||
|
|
||||||
// getTaskIp(sandboxData.id)
|
getTaskIp(sandboxData.id)
|
||||||
// .then((ip) => {
|
.then((ip) => {
|
||||||
// setTaskIp(ip);
|
setTaskIp(ip);
|
||||||
// })
|
})
|
||||||
// .catch(() => {
|
.catch(() => {
|
||||||
// setDidFail(true);
|
setDidFail(true);
|
||||||
// toast.error("An error occurred while getting your server IP.");
|
toast.error("An error occurred while getting your server IP.");
|
||||||
// });
|
});
|
||||||
// })
|
})
|
||||||
// .catch(() => {
|
.catch(() => {
|
||||||
// toast.error("An error occurred while initializing your server.");
|
toast.error("An error occurred while initializing your server.");
|
||||||
// setDidFail(true);
|
setDidFail(true);
|
||||||
// });
|
});
|
||||||
// }
|
}
|
||||||
// });
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// if (didFail) return <Loading didFail={didFail} />;
|
if (didFail) return <Loading didFail={didFail} />;
|
||||||
// if (!isServiceRunning || !isDeploymentActive || !taskIp)
|
if (!isServiceRunning || !isDeploymentActive || !taskIp)
|
||||||
// return (
|
return (
|
||||||
// <Loading
|
<Loading
|
||||||
// text="Creating sandbox resources"
|
text="Creating sandbox resources"
|
||||||
// description={
|
description={
|
||||||
// isDeploymentActive
|
isDeploymentActive
|
||||||
// ? "Preparing server networking..."
|
? "Preparing server networking..."
|
||||||
// : isServiceRunning
|
: isServiceRunning
|
||||||
// ? "Initializing server, this could take a minute..."
|
? "Initializing server, this could take a minute..."
|
||||||
// : "Requesting your server creation..."
|
: "Requesting your server creation..."
|
||||||
// }
|
}
|
||||||
// />
|
/>
|
||||||
// );
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CodeEditor
|
<CodeEditor ip={taskIp} userData={userData} sandboxData={sandboxData} />
|
||||||
ip={"localhost"}
|
|
||||||
// ip={taskIp}
|
|
||||||
userData={userData}
|
|
||||||
sandboxData={sandboxData}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import {
|
|||||||
TerminalSquare,
|
TerminalSquare,
|
||||||
UnfoldVertical,
|
UnfoldVertical,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useRef } from "react";
|
import { useRef, useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
|
||||||
export default function PreviewWindow({
|
export default function PreviewWindow({
|
||||||
@ -22,6 +22,7 @@ export default function PreviewWindow({
|
|||||||
ip: string;
|
ip: string;
|
||||||
}) {
|
}) {
|
||||||
const ref = useRef<HTMLIFrameElement>(null);
|
const ref = useRef<HTMLIFrameElement>(null);
|
||||||
|
const [iframeKey, setIframeKey] = useState(0);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -33,9 +34,9 @@ export default function PreviewWindow({
|
|||||||
<div className="h-8 rounded-md px-3 bg-secondary flex items-center w-full justify-between">
|
<div className="h-8 rounded-md px-3 bg-secondary flex items-center w-full justify-between">
|
||||||
<div className="text-xs">
|
<div className="text-xs">
|
||||||
Preview
|
Preview
|
||||||
<span className="inline-block ml-2 items-center font-mono text-muted-foreground">
|
{/* <span className="inline-block ml-2 items-center font-mono text-muted-foreground">
|
||||||
localhost:8000
|
localhost:8000
|
||||||
</span>
|
</span> */}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex space-x-1 translate-x-1">
|
<div className="flex space-x-1 translate-x-1">
|
||||||
{collapsed ? (
|
{collapsed ? (
|
||||||
@ -45,13 +46,13 @@ export default function PreviewWindow({
|
|||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{/* Todo, make this open inspector */}
|
{/* Todo, make this open inspector */}
|
||||||
<PreviewButton disabled onClick={() => {}}>
|
{/* <PreviewButton disabled onClick={() => {}}>
|
||||||
<TerminalSquare className="w-4 h-4" />
|
<TerminalSquare className="w-4 h-4" />
|
||||||
</PreviewButton>
|
</PreviewButton> */}
|
||||||
|
|
||||||
<PreviewButton
|
<PreviewButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigator.clipboard.writeText(`http://${ip}:8000`);
|
navigator.clipboard.writeText(`http://${ip}:3000`);
|
||||||
toast.info("Copied preview link to clipboard");
|
toast.info("Copied preview link to clipboard");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -59,9 +60,10 @@ export default function PreviewWindow({
|
|||||||
</PreviewButton>
|
</PreviewButton>
|
||||||
<PreviewButton
|
<PreviewButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (ref.current) {
|
// if (ref.current) {
|
||||||
ref.current.contentWindow?.location.reload();
|
// ref.current.contentWindow?.location.reload();
|
||||||
}
|
// }
|
||||||
|
setIframeKey((prev) => prev + 1);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<RotateCw className="w-3 h-3" />
|
<RotateCw className="w-3 h-3" />
|
||||||
@ -74,10 +76,11 @@ export default function PreviewWindow({
|
|||||||
{collapsed ? null : (
|
{collapsed ? null : (
|
||||||
<div className="w-full grow rounded-md overflow-hidden bg-foreground">
|
<div className="w-full grow rounded-md overflow-hidden bg-foreground">
|
||||||
<iframe
|
<iframe
|
||||||
|
key={iframeKey}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
width={"100%"}
|
width={"100%"}
|
||||||
height={"100%"}
|
height={"100%"}
|
||||||
src={`http://${ip}:8000`}
|
src={`http://${ip}:3000`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -8,18 +8,12 @@ import { Loader2, Plus, SquareTerminal, TerminalSquare } from "lucide-react";
|
|||||||
import { Socket } from "socket.io-client";
|
import { Socket } from "socket.io-client";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import EditorTerminal from "./terminal";
|
import EditorTerminal from "./terminal";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
export default function Terminals({
|
export default function Terminals({
|
||||||
terminals,
|
terminals,
|
||||||
setTerminals,
|
setTerminals,
|
||||||
activeTerminalId,
|
|
||||||
setActiveTerminalId,
|
|
||||||
socket,
|
socket,
|
||||||
activeTerminal,
|
|
||||||
creatingTerminal,
|
|
||||||
setCreatingTerminal,
|
|
||||||
closingTerminal,
|
|
||||||
setClosingTerminal,
|
|
||||||
}: {
|
}: {
|
||||||
terminals: { id: string; terminal: Terminal | null }[];
|
terminals: { id: string; terminal: Terminal | null }[];
|
||||||
setTerminals: React.Dispatch<
|
setTerminals: React.Dispatch<
|
||||||
@ -30,20 +24,13 @@ export default function Terminals({
|
|||||||
}[]
|
}[]
|
||||||
>
|
>
|
||||||
>;
|
>;
|
||||||
activeTerminalId: string;
|
|
||||||
setActiveTerminalId: React.Dispatch<React.SetStateAction<string>>;
|
|
||||||
socket: Socket;
|
socket: Socket;
|
||||||
activeTerminal:
|
|
||||||
| {
|
|
||||||
id: string;
|
|
||||||
terminal: Terminal | null;
|
|
||||||
}
|
|
||||||
| undefined;
|
|
||||||
creatingTerminal: boolean;
|
|
||||||
setCreatingTerminal: React.Dispatch<React.SetStateAction<boolean>>;
|
|
||||||
closingTerminal: string;
|
|
||||||
setClosingTerminal: React.Dispatch<React.SetStateAction<string>>;
|
|
||||||
}) {
|
}) {
|
||||||
|
const [activeTerminalId, setActiveTerminalId] = useState("");
|
||||||
|
const [creatingTerminal, setCreatingTerminal] = useState(false);
|
||||||
|
const [closingTerminal, setClosingTerminal] = useState("");
|
||||||
|
const activeTerminal = terminals.find((t) => t.id === activeTerminalId);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="h-10 w-full overflow-auto flex gap-2 shrink-0 tab-scroll">
|
<div className="h-10 w-full overflow-auto flex gap-2 shrink-0 tab-scroll">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user