diff --git a/apps/dispatch-server/.d.ts b/apps/dispatch-server/.d.ts new file mode 100644 index 00000000..8b3f9cfb --- /dev/null +++ b/apps/dispatch-server/.d.ts @@ -0,0 +1,8 @@ +declare module "next-auth/jwt" { + interface JWT { + uid: string; + firstname: string; + lastname: string; + email: string; + } +} diff --git a/apps/dispatch-server/.env.example b/apps/dispatch-server/.env.example index 47b922aa..3ed5e2cd 100644 --- a/apps/dispatch-server/.env.example +++ b/apps/dispatch-server/.env.example @@ -1,3 +1,4 @@ PORT=3002 REDIS_HOST=localhost -REDIS_PORT=6379 \ No newline at end of file +REDIS_PORT=6379 +DISPATCH_APP_TOKEN= \ No newline at end of file diff --git a/apps/dispatch-server/index.ts b/apps/dispatch-server/index.ts index 962f3caa..995a3b38 100644 --- a/apps/dispatch-server/index.ts +++ b/apps/dispatch-server/index.ts @@ -3,27 +3,23 @@ import express from "express"; import { createServer } from "http"; import { handle } from "socket-events/connect-dispatch"; import { Server } from "socket.io"; -import { createClient } from "redis"; import { createAdapter } from "@socket.io/redis-adapter"; - -const pubClient = createClient(); -const subClient = pubClient.duplicate(); +import { jwtMiddleware } from "modules/socketJWT"; +import { pubClient, subClient } from "modules/redis"; const app = express(); const server = createServer(app); -const initApp = async () => { - await Promise.all([pubClient.connect(), subClient.connect()]); - const io = new Server(server, { - adapter: createAdapter(pubClient, subClient), - }); +const io = new Server(server, { + adapter: createAdapter(pubClient, subClient), + cors: {}, +}); - io.on("connection", (socket) => { - socket.on("connect-dispatch", handle); - }); - server.listen(process.env.PORT, () => { - console.log(`Server running on port ${process.env.PORT}`); - }); -}; +io.use(jwtMiddleware); -initApp(); +io.on("connection", (socket) => { + socket.on("connect-dispatch", () => {}); +}); +server.listen(process.env.PORT, () => { + console.log(`Server running on port ${process.env.PORT}`); +}); diff --git a/apps/dispatch-server/modules/redis.ts b/apps/dispatch-server/modules/redis.ts new file mode 100644 index 00000000..02151d4a --- /dev/null +++ b/apps/dispatch-server/modules/redis.ts @@ -0,0 +1,8 @@ +import { createClient } from "redis"; + +export const pubClient = createClient(); +export const subClient = pubClient.duplicate(); + +Promise.all([pubClient.connect(), subClient.connect()]).then(() => { + console.log("Redis connected"); +}); diff --git a/apps/dispatch-server/modules/socketJWT.ts b/apps/dispatch-server/modules/socketJWT.ts new file mode 100644 index 00000000..e88c1301 --- /dev/null +++ b/apps/dispatch-server/modules/socketJWT.ts @@ -0,0 +1,28 @@ +import { ExtendedError, Server, Socket } from "socket.io"; +import jwt from "jsonwebtoken"; +import { pubClient } from "modules/redis"; + +if (!process.env.DISPATCH_APP_TOKEN) + throw new Error("DISPATCH_APP_TOKEN is not defined"); + +export const jwtMiddleware = async ( + socket: Socket, + next: (err?: ExtendedError) => void, +) => { + try { + const token = socket.handshake.auth?.token; + console.log(socket.handshake); + if (!token) return new Error("Authentication error"); + const decoded = jwt.verify(token, process.env.DISPATCH_APP_TOKEN!); + // socket.data.userId = decoded.; // User ID lokal speichern + + // Prüfen, ob der Nutzer ein Disponent ist + const userId: any = decoded; + socket.data.user = decoded; // Lokal speichern + + // In Redis speichern: Key = 'connected_dispatchers', Feld = socket.id, Wert = JSON-String des Users + } catch (err) { + console.error(err); + next(new Error("Authentication error")); + } +}; diff --git a/apps/dispatch-server/package.json b/apps/dispatch-server/package.json index bb691558..25330a35 100644 --- a/apps/dispatch-server/package.json +++ b/apps/dispatch-server/package.json @@ -24,6 +24,7 @@ "cron": "^4.1.0", "dotenv": "^16.4.7", "express": "^4.21.2", + "jsonwebtoken": "^9.0.2", "nodemailer": "^6.10.0", "react": "^19.0.0", "redis": "^4.7.0", diff --git a/apps/dispatch-server/socket-events/connect-dispatch.ts b/apps/dispatch-server/socket-events/connect-dispatch.ts index b43c3d28..47048cb3 100644 --- a/apps/dispatch-server/socket-events/connect-dispatch.ts +++ b/apps/dispatch-server/socket-events/connect-dispatch.ts @@ -1,8 +1,14 @@ +import { pubClient } from "modules/redis"; import { Server, Socket } from "socket.io"; -export const handle = async (socket: Socket, io: Server) => { - console.log("Connected to dispatch server"); - socket.on("disconnect", () => { +export const handle = (socket: Socket, io: Server) => async (jwt: string) => { + const userId = socket.data.user.id; // User ID aus dem JWT-Token + await pubClient.set(`dispatchers:${socket.id}`, userId); + + socket.join("dispatchers"); // Dem Dispatcher-Raum beitreten + + socket.on("disconnect", async () => { console.log("Disconnected from dispatch server"); + await pubClient.del(`dispatchers:${socket.id}`); }); }; diff --git a/apps/dispatch/app/(dispatch)/_components/Navbar.tsx b/apps/dispatch/app/(dispatch)/_components/Navbar.tsx index 20b5e05d..88d5dba0 100644 --- a/apps/dispatch/app/(dispatch)/_components/Navbar.tsx +++ b/apps/dispatch/app/(dispatch)/_components/Navbar.tsx @@ -3,8 +3,13 @@ import { ToggleTalkButton } from "../_components/ToggleTalkButton"; import { ChangeRufgruppe } from "../_components/ChangeRufgruppe"; import { Notifications } from "../_components/Notifications"; import Link from "next/link"; +import { connectionStore } from "../../_store/connectionStore"; +import { useEffect } from "react"; +import { socket } from "../socket"; export default function Navbar() { + const connected = connectionStore((state) => state); + return (