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
|
PORT=3002
|
||||||
REDIS_HOST=localhost
|
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 { createServer } from "http";
|
||||||
import { handle } from "socket-events/connect-dispatch";
|
import { handle } from "socket-events/connect-dispatch";
|
||||||
import { Server } from "socket.io";
|
import { Server } from "socket.io";
|
||||||
import { createClient } from "redis";
|
|
||||||
import { createAdapter } from "@socket.io/redis-adapter";
|
import { createAdapter } from "@socket.io/redis-adapter";
|
||||||
|
import { jwtMiddleware } from "modules/socketJWT";
|
||||||
const pubClient = createClient();
|
import { pubClient, subClient } from "modules/redis";
|
||||||
const subClient = pubClient.duplicate();
|
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
const server = createServer(app);
|
const server = createServer(app);
|
||||||
|
|
||||||
const initApp = async () => {
|
const io = new Server(server, {
|
||||||
await Promise.all([pubClient.connect(), subClient.connect()]);
|
adapter: createAdapter(pubClient, subClient),
|
||||||
const io = new Server(server, {
|
cors: {},
|
||||||
adapter: createAdapter(pubClient, subClient),
|
});
|
||||||
});
|
|
||||||
|
|
||||||
io.on("connection", (socket) => {
|
io.use(jwtMiddleware);
|
||||||
socket.on("connect-dispatch", handle);
|
|
||||||
});
|
|
||||||
server.listen(process.env.PORT, () => {
|
|
||||||
console.log(`Server running on port ${process.env.PORT}`);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
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",
|
"cron": "^4.1.0",
|
||||||
"dotenv": "^16.4.7",
|
"dotenv": "^16.4.7",
|
||||||
"express": "^4.21.2",
|
"express": "^4.21.2",
|
||||||
|
"jsonwebtoken": "^9.0.2",
|
||||||
"nodemailer": "^6.10.0",
|
"nodemailer": "^6.10.0",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"redis": "^4.7.0",
|
"redis": "^4.7.0",
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
|
import { pubClient } from "modules/redis";
|
||||||
import { Server, Socket } from "socket.io";
|
import { Server, Socket } from "socket.io";
|
||||||
|
|
||||||
export const handle = async (socket: Socket, io: Server) => {
|
export const handle = (socket: Socket, io: Server) => async (jwt: string) => {
|
||||||
console.log("Connected to dispatch server");
|
const userId = socket.data.user.id; // User ID aus dem JWT-Token
|
||||||
socket.on("disconnect", () => {
|
await pubClient.set(`dispatchers:${socket.id}`, userId);
|
||||||
|
|
||||||
|
socket.join("dispatchers"); // Dem Dispatcher-Raum beitreten
|
||||||
|
|
||||||
|
socket.on("disconnect", async () => {
|
||||||
console.log("Disconnected from dispatch server");
|
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 { ChangeRufgruppe } from "../_components/ChangeRufgruppe";
|
||||||
import { Notifications } from "../_components/Notifications";
|
import { Notifications } from "../_components/Notifications";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { connectionStore } from "../../_store/connectionStore";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
import { socket } from "../socket";
|
||||||
|
|
||||||
export default function Navbar() {
|
export default function Navbar() {
|
||||||
|
const connected = connectionStore((state) => state);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="navbar bg-base-100 shadow-sm">
|
<div className="navbar bg-base-100 shadow-sm">
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import Navbar from "./_components/Navbar";
|
import Navbar from "./_components/Navbar";
|
||||||
import { useSession } from "next-auth/react";
|
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
import { getServerSession } from "../api/auth/[...nextauth]/auth";
|
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",
|
"postcss": "^8.5.1",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
|
"socket.io-client": "^4.8.1",
|
||||||
"tailwindcss": "^4.0.2",
|
"tailwindcss": "^4.0.2",
|
||||||
"zustand": "^5.0.3"
|
"zustand": "^5.0.3"
|
||||||
},
|
},
|
||||||
|
|||||||
72
package-lock.json
generated
72
package-lock.json
generated
@@ -30,6 +30,7 @@
|
|||||||
"postcss": "^8.5.1",
|
"postcss": "^8.5.1",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
|
"socket.io-client": "^4.8.1",
|
||||||
"tailwindcss": "^4.0.2",
|
"tailwindcss": "^4.0.2",
|
||||||
"zustand": "^5.0.3"
|
"zustand": "^5.0.3"
|
||||||
},
|
},
|
||||||
@@ -52,6 +53,7 @@
|
|||||||
"cron": "^4.1.0",
|
"cron": "^4.1.0",
|
||||||
"dotenv": "^16.4.7",
|
"dotenv": "^16.4.7",
|
||||||
"express": "^4.21.2",
|
"express": "^4.21.2",
|
||||||
|
"jsonwebtoken": "^9.0.2",
|
||||||
"nodemailer": "^6.10.0",
|
"nodemailer": "^6.10.0",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"redis": "^4.7.0",
|
"redis": "^4.7.0",
|
||||||
@@ -5879,6 +5881,36 @@
|
|||||||
"node": ">=10.2.0"
|
"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": {
|
"node_modules/engine.io-parser": {
|
||||||
"version": "5.2.3",
|
"version": "5.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz",
|
"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": {
|
"node_modules/socket.io-parser": {
|
||||||
"version": "4.2.4",
|
"version": "4.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
|
"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": {
|
"node_modules/y18n": {
|
||||||
"version": "5.0.8",
|
"version": "5.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||||
|
|||||||
Reference in New Issue
Block a user