From cf32a2b7785ec3fba784e611ac05d8dcd84269b4 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Wed, 15 Oct 2025 15:14:27 +0200 Subject: [PATCH 1/7] Websocket and auth fixes --- src/app/api/auth/route.ts | 47 +++++++++++++++++++---------------- src/app/api/profile/route.ts | 16 ++++++++++-- src/components/MessageBox.tsx | 2 +- src/components/Sidebar.tsx | 4 +-- src/hooks/get-user.ts | 4 ++- src/hooks/use-settings.ts | 8 +++--- src/lib/auth.ts | 14 +++++------ 7 files changed, 54 insertions(+), 41 deletions(-) diff --git a/src/app/api/auth/route.ts b/src/app/api/auth/route.ts index 96915e2..11160ea 100644 --- a/src/app/api/auth/route.ts +++ b/src/app/api/auth/route.ts @@ -1,12 +1,6 @@ import { NextRequest, NextResponse } from "next/server"; import { StatusCodes } from "http-status-codes"; import { supabase } from "../supa"; - -const SERVER_AUTH_TOKENS = new Map< - string, - { user_id: string; server_id: string } ->(); - /** * GET /api/auth?token=?key= * Called by a (DM node / Server) to verify a temporary relay token. @@ -16,31 +10,36 @@ export async function GET(req: NextRequest) { const token = url.searchParams.get("token"); const key = url.searchParams.get("key"); - if (!token || !key) { + if (!token || !key) return NextResponse.json( { message: "There should be a token and a key parameter" }, { status: StatusCodes.BAD_REQUEST } ); - } const { data: server } = await supabase .from("servers") .select("id, created_at, owner, address") .eq("key", key) .maybeSingle(); + if (!server) return NextResponse.json( { message: "Key unauthorized" }, { status: StatusCodes.UNAUTHORIZED } ); - const auth = SERVER_AUTH_TOKENS.get(token); - if (!auth) { + const { data: auth } = await supabase + .from("server_auth") + .delete() + .eq("key", token) + .select() + .maybeSingle(); + + if (!auth) return NextResponse.json( { message: "Invalid or expired token" }, { status: StatusCodes.NOT_FOUND } ); - } if (auth.server_id !== server.id) return NextResponse.json( @@ -48,8 +47,6 @@ export async function GET(req: NextRequest) { { status: StatusCodes.UNAUTHORIZED } ); - SERVER_AUTH_TOKENS.delete(token); - return NextResponse.json({ message: "ok", ...auth }); } @@ -76,12 +73,10 @@ export async function POST(req: NextRequest) { { status: StatusCodes.BAD_REQUEST } ); - const supabaseToken = authHeader.value; - const { data: { user }, error, - } = await supabase.auth.getUser(supabaseToken); + } = await supabase.auth.getUser(authHeader.value); if (error || !user) { return NextResponse.json( @@ -90,12 +85,20 @@ export async function POST(req: NextRequest) { ); } - const relayToken = crypto.randomUUID(); + const { data: relayToken, error: errorRelay } = await supabase + .from("server_auth") + .insert({ + user_id: user.id, + server_id, + }) + .select() + .maybeSingle(); - SERVER_AUTH_TOKENS.set(relayToken, { - user_id: user.id, - server_id, - }); + if (!relayToken || errorRelay) + return NextResponse.json( + { message: "Failed to create relay token" }, + { status: StatusCodes.INTERNAL_SERVER_ERROR } + ); - return NextResponse.json({ message: "ok", token: relayToken }); + return NextResponse.json({ message: "ok", token: relayToken.key }); } diff --git a/src/app/api/profile/route.ts b/src/app/api/profile/route.ts index a88cf8a..e45c823 100644 --- a/src/app/api/profile/route.ts +++ b/src/app/api/profile/route.ts @@ -84,14 +84,26 @@ export async function GET(req: NextRequest) { if (!user_id) return NextResponse.json( { message: "Invalid token" }, - { status: StatusCodes.NOT_FOUND } + { status: StatusCodes.BAD_REQUEST } ); - const { data: profile } = await supabase + const { data: profile, error } = await supabase .from("profiles") .select("id, username, display_name, avatar_url, node_address") .eq("id", user_id) .maybeSingle(); + if (error) + return NextResponse.json( + { message: error.message }, + { status: StatusCodes.INTERNAL_SERVER_ERROR } + ); + + if (!profile) + return NextResponse.json( + { message: "Profile not found" }, + { status: StatusCodes.NOT_FOUND } + ); + return NextResponse.json({ message: "ok", ...profile }); } diff --git a/src/components/MessageBox.tsx b/src/components/MessageBox.tsx index 4fc8e92..289bfb2 100644 --- a/src/components/MessageBox.tsx +++ b/src/components/MessageBox.tsx @@ -38,7 +38,7 @@ function MessageContainer({ [message.from]: res.data as UserProfile, })) ) - .catch(console.error); + .catch(() => {}); }, [message.from, setUserList]); return ( diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index 66ecfb3..d57d4c6 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -338,7 +338,5 @@ function getUser( get(`/api/profile/?id=${id}`, onResponse) ?.then(onResponse) - .catch((e) => { - console.error(e); - }); + .catch((e) => {}); } diff --git a/src/hooks/get-user.ts b/src/hooks/get-user.ts index 901c6da..9379a1e 100644 --- a/src/hooks/get-user.ts +++ b/src/hooks/get-user.ts @@ -5,6 +5,7 @@ import Cookies from "js-cookie"; import { useRouter } from "next/navigation"; import { useEffect, useState } from "react"; import { get } from "@/lib/request"; +import { toast } from "sonner"; export interface UserProfile extends ProfileSettings { id: string; @@ -24,8 +25,9 @@ export default function useUser() { try { setUser((await get("/api/profile")).data); - } catch { + } catch (e: any) { router.push("/login"); + toast.error(`Error: ${e}`); } } diff --git a/src/hooks/use-settings.ts b/src/hooks/use-settings.ts index c6b50e4..21bf861 100644 --- a/src/hooks/use-settings.ts +++ b/src/hooks/use-settings.ts @@ -2,6 +2,7 @@ import { defaultSettings, getClientSettings } from "@/lib/clientSettings"; import { ProfileSettings, ClientSettings } from "@/types/settings"; +import axios from "axios"; import { Dispatch, SetStateAction, useEffect, useState } from "react"; export function useClientSettings(): [ @@ -31,11 +32,8 @@ export function useProfileSettings(): [ useEffect(() => { async function fetchProfileSettings() { try { - const res = await fetch("/api/profile"); - if (res.ok) { - const data = (await res.json()) as ProfileSettings; - setSettings(data); - } + const res = await axios.get("/api/profile"); + setSettings(res.data as ProfileSettings); } catch (error) { console.error("Failed to fetch profile settings:", error); } diff --git a/src/lib/auth.ts b/src/lib/auth.ts index 29eaf8c..9e330bc 100644 --- a/src/lib/auth.ts +++ b/src/lib/auth.ts @@ -26,13 +26,6 @@ export default async function auth( ws.onopen = () => { console.log("Connected to WebSocket:", ip); - ws.send( - JSON.stringify({ - version: "0.0.1", - auth_token: server_auth, - last_message: lastMessage || 0, - }) - ); }; ws.onmessage = (m) => { @@ -41,6 +34,13 @@ export default async function auth( if (data.version) { setServer({ channels: [], ...data }); + ws.send( + JSON.stringify({ + version: "0.0.1", + auth_token: server_auth, + last_message: lastMessage || 0, + }) + ); return; } From e6d67a394e9b129d6be4de7995c54e241313b3e8 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Wed, 15 Oct 2025 15:31:10 +0200 Subject: [PATCH 2/7] Fixed sidebar users --- src/components/Sidebar.tsx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index d57d4c6..4b78b12 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -64,7 +64,11 @@ export default function AppSidebar({ const [userList, setUserList] = useState>({}); const dms = Array.from( - new Set(messages?.flatMap((item) => [item.from, item.channel_id]) || []) + new Set( + messages + ?.flatMap((item) => [item.from, item.channel_id]) + .filter((item) => item !== user?.id) || [] + ) ); useEffect(() => { @@ -280,12 +284,10 @@ function DMItem({ status: string; settings?: boolean; }) { - const router = useRouter(); - return (
From 04b865131341bcd74e20fe73e7ef3072d905fbaa Mon Sep 17 00:00:00 2001 From: Leo dev Date: Wed, 15 Oct 2025 17:41:36 +0200 Subject: [PATCH 3/7] Toggle-able sidebar --- src/app/chat/[id]/page.tsx | 7 ++++--- src/app/chat/page.tsx | 3 +++ src/app/server/[ip]/page.tsx | 4 ++++ src/components/MessageBox.tsx | 9 ++++++-- src/components/Sidebar.tsx | 39 ++++++++++++++++++++++++++++++++--- 5 files changed, 54 insertions(+), 8 deletions(-) diff --git a/src/app/chat/[id]/page.tsx b/src/app/chat/[id]/page.tsx index 470eb32..8af22d6 100644 --- a/src/app/chat/[id]/page.tsx +++ b/src/app/chat/[id]/page.tsx @@ -9,9 +9,6 @@ import { StringMap } from "@/types/typeUtils"; import { useParams } from "next/navigation"; import { useMessages } from "@/hooks/use-messages"; -// In this testing instance we are assuming that the target's node is localhost -// To make this functional we need to add a settings feature to the api - export default function DMs() { const { id } = useParams<{ id: string }>(); const wsRef = useRef(null); @@ -19,9 +16,12 @@ export default function DMs() { const addMessage = useMessages((s) => s.addMessage); const [userList, setUserList] = useState>({}); const [user, setUser] = useState(); + const [sidebarOpen, setSidebarOpen] = useState(false); return ( setSidebarOpen(true)} channelName={userList[id]?.display_name || id} userList={userList} setUserList={setUserList} diff --git a/src/app/chat/page.tsx b/src/app/chat/page.tsx index 67377d1..6dbca1b 100644 --- a/src/app/chat/page.tsx +++ b/src/app/chat/page.tsx @@ -14,9 +14,12 @@ export default function Chat() { const [userList, setUserList] = useState>({}); const messages = useMessages((s) => s.messages); const addMessage = useMessages((s) => s.addMessage); + const [sidebarOpen, setSidebarOpen] = useState(false); return ( >({}); const messages = useMessages((s) => s.messages); const addMessage = useMessages((s) => s.addMessage); + const [sidebarOpen, setSidebarOpen] = useState(false); useEffect(() => { if (!ip) return; @@ -26,6 +27,8 @@ export default function Server() { return ( {}} userList={userList} @@ -33,6 +36,7 @@ export default function Server() { server={server} > setSidebarOpen(true)} channelName="General" userList={userList} setUserList={setUserList} diff --git a/src/components/MessageBox.tsx b/src/components/MessageBox.tsx index 289bfb2..8cc19d5 100644 --- a/src/components/MessageBox.tsx +++ b/src/components/MessageBox.tsx @@ -10,7 +10,7 @@ import { DropdownMenuContent, DropdownMenuTrigger, } from "./ui/dropdown-menu"; -import { SmilePlusIcon } from "lucide-react"; +import { ChevronLeft, ChevronLeftIcon, SmilePlusIcon } from "lucide-react"; import { useEffect, useRef, useState } from "react"; import { format, isToday, isYesterday } from "date-fns"; import ReactMarkdown from "react-markdown"; @@ -144,12 +144,14 @@ export default function MessageBox({ setUserList, sendMessage, channelName, + toggleSidebar, }: { messages: Message[]; userList: NumberMap; setUserList: React.Dispatch>>; sendMessage: (m: string) => void; channelName?: string; + toggleSidebar: () => void; }) { const [text, setText] = useState(""); @@ -157,7 +159,10 @@ export default function MessageBox({
{channelName && (
- {channelName} + + + {channelName} +
)}
diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index 4b78b12..c3f6e8b 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -35,6 +35,7 @@ import SettingsDialog from "./settings/SettingsDialog"; import Link from "next/link"; import axios from "axios"; import { get, Response } from "@/lib/request"; +import { cn } from "@/lib/utils"; export default function AppSidebar({ children, @@ -45,6 +46,8 @@ export default function AppSidebar({ server, messages, addMessage, + open, + setOpen, }: Readonly<{ wsRef: React.RefObject; addMessage: (msg: Message) => void; @@ -56,6 +59,8 @@ export default function AppSidebar({ children?: React.ReactNode; setUser?: React.Dispatch>; server?: Server | undefined; + open: boolean; + setOpen: React.Dispatch>; }>) { const [servers, setServers] = useState<[string, string][]>([]); const [newServer, setNewServer] = useState({ name: "", ip: "" }); @@ -123,7 +128,28 @@ export default function AppSidebar({ return (
-
+ {open && ( +
setOpen(false)} + /> + )} + {/*
*/} +
- - {children} + {open ? ( +
+
+ {children} +
+
+ ) : ( + children + )}
); } From ead2fdd6e9d967d664a7286b9a3a84e26c0e12ac Mon Sep 17 00:00:00 2001 From: Leo dev Date: Wed, 15 Oct 2025 17:56:45 +0200 Subject: [PATCH 4/7] Better sidebar toggle --- src/app/chat/page.tsx | 2 +- src/components/Sidebar.tsx | 27 +++++++-------------------- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/src/app/chat/page.tsx b/src/app/chat/page.tsx index 6dbca1b..31af79b 100644 --- a/src/app/chat/page.tsx +++ b/src/app/chat/page.tsx @@ -14,7 +14,7 @@ export default function Chat() { const [userList, setUserList] = useState>({}); const messages = useMessages((s) => s.messages); const addMessage = useMessages((s) => s.addMessage); - const [sidebarOpen, setSidebarOpen] = useState(false); + const [sidebarOpen, setSidebarOpen] = useState(true); return ( - {open && ( -
setOpen(false)} - /> - )} - {/*
*/}
@@ -238,7 +222,7 @@ export default function AppSidebar({
{/* Right column */} -
+
{server ? (

{server.name}

@@ -292,7 +276,10 @@ export default function AppSidebar({
{open ? ( -
+
setOpen(false)} + >
{children}
From 8f917706c7c5ce5135afad24b57277959c1ca1c8 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Wed, 15 Oct 2025 18:01:55 +0200 Subject: [PATCH 5/7] Better sidebar toggle --- src/components/Sidebar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index 79bf2dd..07609ce 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -131,7 +131,7 @@ export default function AppSidebar({
From 8e230fc891bc7aaf13013179bb21bab63f4e5381 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Wed, 15 Oct 2025 18:16:07 +0200 Subject: [PATCH 6/7] Fixed mobile ui --- src/components/MessageBox.tsx | 8 ++++---- src/components/Sidebar.tsx | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/MessageBox.tsx b/src/components/MessageBox.tsx index 8cc19d5..20ad876 100644 --- a/src/components/MessageBox.tsx +++ b/src/components/MessageBox.tsx @@ -156,7 +156,7 @@ export default function MessageBox({ const [text, setText] = useState(""); return ( -
+
{channelName && (
@@ -165,7 +165,7 @@ export default function MessageBox({
)} -
+
{messages.map((msg) => ( ))}
-
+
-
+
); } diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index 07609ce..79f81f8 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -127,7 +127,7 @@ export default function AppSidebar({ }; return ( -
+
Date: Wed, 15 Oct 2025 18:41:04 +0200 Subject: [PATCH 7/7] Notification top right --- src/components/Sidebar.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index 79f81f8..fe90f21 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -99,6 +99,7 @@ export default function AppSidebar({ label: "View", onClick: () => router.push(`/chat/${m.from}`), }, + position: "top-right", } );