continue dispatch-server

This commit is contained in:
PxlLoewe
2025-03-14 00:18:06 -07:00
parent ec335ce489
commit 05b7d0fd39
14 changed files with 179 additions and 22 deletions

8
apps/dispatch-server/.d.ts vendored Normal file
View File

@@ -0,0 +1,8 @@
declare module "next-auth/jwt" {
interface JWT {
uid: string;
firstname: string;
lastname: string;
email: string;
}
}

View File

@@ -1,3 +1,4 @@
PORT=3002
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PORT=6379
DISPATCH_APP_TOKEN=

View File

@@ -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}`);
});

View File

@@ -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");
});

View File

@@ -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"));
}
};

View File

@@ -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",

View File

@@ -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}`);
});
};

View File

@@ -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 (
<div className="navbar bg-base-100 shadow-sm">
<div className="flex-1">

View File

@@ -1,6 +1,5 @@
import type { Metadata } from "next";
import Navbar from "./_components/Navbar";
import { useSession } from "next-auth/react";
import { redirect } from "next/navigation";
import { getServerSession } from "../api/auth/[...nextauth]/auth";

View File

@@ -0,0 +1,7 @@
import { io } from "socket.io-client";
export const socket = io(process.env.NEXT_PUBLIC_DISPATCH_SERVER_URL, {
auth: (cb) => {
cb({ token: "jwt" });
},
});

View File

@@ -0,0 +1,16 @@
import { create } from "zustand";
import { socket } from "../(dispatch)/socket";
console.log("connectionStore");
export const connectionStore = create((set) => ({
isConnected: false,
connect: async (jwt: string) => {
socket.auth = { token: "jwt" };
socket.connect();
},
}));
socket.on("connect", () => {
connectionStore.setState({ isConnected: true });
});

View File

@@ -0,0 +1,9 @@
import { create } from "zustand";
import { socket } from "../(dispatch)/socket";
export const stationStore = create((set) => {
return {
stations: [],
setStations: (stations: any) => set({ stations }),
};
});

View File

@@ -20,6 +20,7 @@
"postcss": "^8.5.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"socket.io-client": "^4.8.1",
"tailwindcss": "^4.0.2",
"zustand": "^5.0.3"
},

72
package-lock.json generated
View File

@@ -30,6 +30,7 @@
"postcss": "^8.5.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"socket.io-client": "^4.8.1",
"tailwindcss": "^4.0.2",
"zustand": "^5.0.3"
},
@@ -52,6 +53,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",
@@ -5879,6 +5881,36 @@
"node": ">=10.2.0"
}
},
"node_modules/engine.io-client": {
"version": "6.6.3",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz",
"integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==",
"license": "MIT",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1",
"engine.io-parser": "~5.2.1",
"ws": "~8.17.1",
"xmlhttprequest-ssl": "~2.1.1"
}
},
"node_modules/engine.io-client/node_modules/debug": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/engine.io-parser": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz",
@@ -16067,6 +16099,38 @@
}
}
},
"node_modules/socket.io-client": {
"version": "4.8.1",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz",
"integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==",
"license": "MIT",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.2",
"engine.io-client": "~6.6.1",
"socket.io-parser": "~4.2.4"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/socket.io-client/node_modules/debug": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/socket.io-parser": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
@@ -17786,6 +17850,14 @@
}
}
},
"node_modules/xmlhttprequest-ssl": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz",
"integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",