From f16e356555e08c19bafca930b209ec15f2b254bf Mon Sep 17 00:00:00 2001 From: sianida26 Date: Fri, 16 Feb 2024 20:50:19 +0700 Subject: [PATCH] Added socket --- .env.development | 2 + bun.lockb | Bin 201445 -> 201445 bytes server/socket.ts | 101 ++++++++++++++++++ src/app/dashboard/(auth)/permissions/page.tsx | 2 +- .../auth/utils/cachedGetUserFromToken.ts | 6 ++ src/modules/auth/utils/getUserFromToken.ts | 4 +- .../actions/createLinkRequest.ts | 3 + 7 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 .env.development create mode 100644 server/socket.ts create mode 100644 src/modules/auth/utils/cachedGetUserFromToken.ts diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..9c36dce --- /dev/null +++ b/.env.development @@ -0,0 +1,2 @@ +WS_PORT=4001 +WS_HOST=ws://localhost:$WS_PORT \ No newline at end of file diff --git a/bun.lockb b/bun.lockb index 6a58ffd6d340df22db524ab9817ef794069a0ac9..8228dda871141b10f43894a23ad26fa284485192 100755 GIT binary patch delta 31 jcmaF5l;`PEo`x32Elirc>`V+`&~CuXwB3N0c`GXbm+c3h delta 31 ncmaF5l;`PEo`x32Elirc?2K`SdIox??FPI|+YNY`x3U5Nss0G< diff --git a/server/socket.ts b/server/socket.ts new file mode 100644 index 0000000..1269481 --- /dev/null +++ b/server/socket.ts @@ -0,0 +1,101 @@ +import getUserFromToken from "@/modules/auth/utils/getUserFromToken"; +import { User } from "@prisma/client"; +import prisma from "@/core/db"; +import Bun from "bun"; + +const intents = { + listenMyWaitingLinkRequest: "listenMyWaitingLinkRequest", +} as const; + +const waitingLinkRequestConnections: Map< + string, + Bun.ServerWebSocket<{ + channel: string; + user: User; + intent: string; + }> +> = new Map(); + +export const server = Bun.serve<{ + channel: string; + user: User; + intent: string; +}>({ + async fetch(req, server) { + const url = new URL(req.url); + req.headers.getSetCookie(); + const pathname = url.pathname; + + const cookies = req.headers.get("Cookie"); + + // Extract the Authorization header + const authHeader = req.headers.get("Authorization"); + const token = authHeader?.startsWith("Bearer ") + ? authHeader.substring(7, authHeader.length) + : null; + + const user = token ? await getUserFromToken(token) : null; + + const intent = pathname.substring(1); + + switch (intent) { + case `/${intents.listenMyWaitingLinkRequest}`: { + if (!user) { + return new Response("Unauthorized", { status: 401 }); + } + const channel = `mwrl-${user.id}`; + const success = server.upgrade(req, { + data: { user, channel, intent }, + }); + if (success) return undefined; + break; + } + default: { + return new Response(""); + } + } + }, + websocket: { + async open(ws) { + switch (ws.data.intent) { + case intents.listenMyWaitingLinkRequest: { + ws.subscribe(ws.data.channel); + + //retrieve user's link requests with status of waiting + const result = await prisma.office365LinkRequest.findMany({ + where: { + createdBy: ws.data.user.id, + status: "WAITING", + }, + select: { + id: true, + }, + }); + + server.publish(ws.data.channel, JSON.stringify(result)); + + waitingLinkRequestConnections.set(ws.data.channel, ws); + } + } + }, + + message(ws, message) { + // the server re-broadcasts incoming messages to everyone + // server.publish("the-group-chat", `: ${message}`); + }, + close(ws) { + // const msg = ` has left the chat`; + // server.publish("the-group-chat", msg); + // ws.unsubscribe("the-group-chat"); + switch (ws.data.intent) { + case intents.listenMyWaitingLinkRequest: { + ws.unsubscribe(ws.data.channel); + waitingLinkRequestConnections.delete(ws.data.channel); + } + } + }, + }, + port: 3001, +}); + +console.log(`Listening on ${server.hostname}:${server.port}`); diff --git a/src/app/dashboard/(auth)/permissions/page.tsx b/src/app/dashboard/(auth)/permissions/page.tsx index 6d7e669..83f89ae 100644 --- a/src/app/dashboard/(auth)/permissions/page.tsx +++ b/src/app/dashboard/(auth)/permissions/page.tsx @@ -26,7 +26,7 @@ export default async function RolesPage({ searchParams }: Props) { update: "permission.update", delete: "permission.delete", }); - + const res = await getAllPermissions(); if (!res.success) throw new Error("Error while fetch permission"); diff --git a/src/modules/auth/utils/cachedGetUserFromToken.ts b/src/modules/auth/utils/cachedGetUserFromToken.ts new file mode 100644 index 0000000..cb2c7cb --- /dev/null +++ b/src/modules/auth/utils/cachedGetUserFromToken.ts @@ -0,0 +1,6 @@ +import { cache } from "react"; +import getUserFromToken from "./getUserFromToken"; + +const cachedGetUserFromToken = cache(getUserFromToken); + +export default cachedGetUserFromToken; diff --git a/src/modules/auth/utils/getUserFromToken.ts b/src/modules/auth/utils/getUserFromToken.ts index a4011ff..991b649 100644 --- a/src/modules/auth/utils/getUserFromToken.ts +++ b/src/modules/auth/utils/getUserFromToken.ts @@ -12,7 +12,7 @@ import prisma from "@/core/db"; * @returns The user's data if the user exists, or null if no user is found. * Throws an error if the token is invalid or the database query fails. */ -const getUserFromToken = cache(async (token: string) => { +const getUserFromToken = async (token: string) => { // Decode the JWT token to extract the user ID const decodedToken = decodeJwtToken(token) as { id: string; iat: number }; @@ -32,6 +32,6 @@ const getUserFromToken = cache(async (token: string) => { }); return user; -}); +}; export default getUserFromToken; diff --git a/src/modules/resellerOffice365/actions/createLinkRequest.ts b/src/modules/resellerOffice365/actions/createLinkRequest.ts index 16fdd6b..c54145a 100644 --- a/src/modules/resellerOffice365/actions/createLinkRequest.ts +++ b/src/modules/resellerOffice365/actions/createLinkRequest.ts @@ -10,6 +10,7 @@ import mapObjectToFirstValue from "@/utils/mapObjectToFirstValue"; import db from "@/core/db"; import getCurrentUser from "@/modules/auth/utils/getCurrentUser"; import { revalidatePath } from "next/cache"; +import {server} from "../../../../server/socket"; export default async function createLinkRequest( formData: RequestLinkForm @@ -54,6 +55,8 @@ export default async function createLinkRequest( revalidatePath(".") + server.publish(`mwrl-${currentUser.id}`, "update") + return { success: true, message: