continue dispatch-server
This commit is contained in:
8
apps/dispatch-server/.d.ts
vendored
Normal file
8
apps/dispatch-server/.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
declare module "next-auth/jwt" {
|
||||
interface JWT {
|
||||
uid: string;
|
||||
firstname: string;
|
||||
lastname: string;
|
||||
email: string;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
PORT=3002
|
||||
REDIS_HOST=localhost
|
||||
REDIS_PORT=6379
|
||||
REDIS_PORT=6379
|
||||
DISPATCH_APP_TOKEN=
|
||||
@@ -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}`);
|
||||
});
|
||||
|
||||
8
apps/dispatch-server/modules/redis.ts
Normal file
8
apps/dispatch-server/modules/redis.ts
Normal 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");
|
||||
});
|
||||
28
apps/dispatch-server/modules/socketJWT.ts
Normal file
28
apps/dispatch-server/modules/socketJWT.ts
Normal 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"));
|
||||
}
|
||||
};
|
||||
@@ -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",
|
||||
|
||||
@@ -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}`);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
7
apps/dispatch/app/(dispatch)/socket.ts
Normal file
7
apps/dispatch/app/(dispatch)/socket.ts
Normal 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" });
|
||||
},
|
||||
});
|
||||
16
apps/dispatch/app/_store/connectionStore.ts
Normal file
16
apps/dispatch/app/_store/connectionStore.ts
Normal 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 });
|
||||
});
|
||||
9
apps/dispatch/app/_store/stationsStore.ts
Normal file
9
apps/dispatch/app/_store/stationsStore.ts
Normal 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 }),
|
||||
};
|
||||
});
|
||||
@@ -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
72
package-lock.json
generated
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user