64 lines
1.8 KiB
TypeScript
Raw Normal View History

import { Socket } from "socket.io"
import { z } from "zod"
import { User } from "./types"
// Middleware for socket authentication
export const socketAuth = async (socket: Socket, next: Function) => {
// Define the schema for handshake query validation
const handshakeSchema = z.object({
userId: z.string(),
sandboxId: z.string(),
EIO: z.string(),
transport: z.string(),
})
const q = socket.handshake.query
const parseQuery = handshakeSchema.safeParse(q)
// Check if the query is valid according to the schema
if (!parseQuery.success) {
next(new Error("Invalid request."))
return
}
const { sandboxId, userId } = parseQuery.data
// Fetch user data from the database
const dbUser = await fetch(
`${process.env.DATABASE_WORKER_URL}/api/user?id=${userId}`,
{
headers: {
Authorization: `${process.env.WORKERS_KEY}`,
},
}
)
const dbUserJSON = (await dbUser.json()) as User
// Check if user data was retrieved successfully
if (!dbUserJSON) {
next(new Error("DB error."))
return
}
// Check if the user owns the sandbox or has shared access
const sandbox = dbUserJSON.sandbox.find((s) => s.id === sandboxId)
const sharedSandboxes = dbUserJSON.usersToSandboxes.find(
(uts) => uts.sandboxId === sandboxId
)
// If user doesn't own or have shared access to the sandbox, deny access
if (!sandbox && !sharedSandboxes) {
next(new Error("Invalid credentials."))
return
}
// Set socket data with user information
socket.data = {
userId,
sandboxId: sandboxId,
isOwner: sandbox !== undefined,
}
// Allow the connection
next()
}