From d29f221a3b3e7393d1c7e0c52bcae227ef957795 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Mon, 13 Oct 2025 22:00:02 +0200 Subject: [PATCH] WebSocket Secure --- src/app/api/profile/route.ts | 10 +++++++--- src/app/chat/[id]/page.tsx | 11 +++++------ src/app/chat/page.tsx | 4 ++-- src/app/server/[ip]/page.tsx | 4 ++-- src/components/MessageBox.tsx | 16 +++++++++------- src/components/Sidebar.tsx | 15 +++++++-------- src/hooks/get-user.ts | 10 ++++------ src/lib/auth.ts | 6 ++++-- 8 files changed, 40 insertions(+), 36 deletions(-) diff --git a/src/app/api/profile/route.ts b/src/app/api/profile/route.ts index f40a4ff..a88cf8a 100644 --- a/src/app/api/profile/route.ts +++ b/src/app/api/profile/route.ts @@ -10,7 +10,7 @@ import { ProfileSettings } from "@/types/settings"; export async function POST(req: NextRequest) { const url = new URL(req.url); const token = req.cookies.get("token")?.value; - const { username, display_name, avatar_url } = + const { username, display_name, avatar_url, node_address } = (await req.json()) as ProfileSettings; if (!token) @@ -21,7 +21,10 @@ export async function POST(req: NextRequest) { if (!username || !display_name || !avatar_url) return NextResponse.json( - { message: "Invalid body, requires username, display_name, avatar_url" }, + { + message: + "Invalid body, requires username, display_name, avatar_url, node_address", + }, { status: StatusCodes.BAD_REQUEST } ); @@ -41,6 +44,7 @@ export async function POST(req: NextRequest) { username, display_name, avatar_url, + node_address, }) .eq("id", user.id); @@ -85,7 +89,7 @@ export async function GET(req: NextRequest) { const { data: profile } = await supabase .from("profiles") - .select("id, username, display_name, avatar_url") + .select("id, username, display_name, avatar_url, node_address") .eq("id", user_id) .maybeSingle(); diff --git a/src/app/chat/[id]/page.tsx b/src/app/chat/[id]/page.tsx index 1fc0bb8..40037ca 100644 --- a/src/app/chat/[id]/page.tsx +++ b/src/app/chat/[id]/page.tsx @@ -1,12 +1,11 @@ "use client"; -import { useEffect, useRef, useState } from "react"; +import { useRef, useState } from "react"; import MessageBox from "@/components/MessageBox"; import AppSidebar from "@/components/Sidebar"; import { Message } from "@/types/types"; -import useUser, { User } from "@/hooks/get-user"; -import { NumberMap, StringMap } from "@/types/typeUtils"; -import auth, { makeAddress } from "@/lib/auth"; +import { UserProfile } from "@/hooks/get-user"; +import { StringMap } from "@/types/typeUtils"; import { useParams } from "next/navigation"; // In this testing instance we are assuming that the target's node is localhost @@ -16,8 +15,8 @@ export default function DMs() { const { id } = useParams<{ id: string }>(); const wsRef = useRef(null); const [messages, setMessages] = useState([]); - const [userList, setUserList] = useState>({}); - const [user, setUser] = useState(); + const [userList, setUserList] = useState>({}); + const [user, setUser] = useState(); return ( (null); - const [userList, setUserList] = useState>({}); + const [userList, setUserList] = useState>({}); return ( (null); const [server, setServer] = useState(); const [messages, setMessages] = useState([]); - const [userList, setUserList] = useState>({}); + const [userList, setUserList] = useState>({}); useEffect(() => { if (!ip) return; diff --git a/src/components/MessageBox.tsx b/src/components/MessageBox.tsx index 3e61d9b..4fc8e92 100644 --- a/src/components/MessageBox.tsx +++ b/src/components/MessageBox.tsx @@ -16,9 +16,8 @@ import { format, isToday, isYesterday } from "date-fns"; import ReactMarkdown from "react-markdown"; import remarkGfm from "remark-gfm"; import { NumberMap, StringMap } from "@/types/typeUtils"; -import { User } from "@/hooks/get-user"; +import { UserProfile } from "@/hooks/get-user"; import axios from "axios"; -import { Avatar, AvatarFallback, AvatarImage } from "./ui/avatar"; import ProfilePicture from "./ProfilePicture"; function MessageContainer({ @@ -27,14 +26,17 @@ function MessageContainer({ setUserList, }: { message: Message; - userList: NumberMap; - setUserList: React.Dispatch>>; + userList: StringMap; + setUserList: React.Dispatch>>; }) { useEffect(() => { axios .get("/api/profile/", { params: { id: message.from } }) .then((res) => - setUserList((prev) => ({ ...prev, [message.from]: res.data as User })) + setUserList((prev) => ({ + ...prev, + [message.from]: res.data as UserProfile, + })) ) .catch(console.error); }, [message.from, setUserList]); @@ -144,8 +146,8 @@ export default function MessageBox({ channelName, }: { messages: Message[]; - userList: NumberMap; - setUserList: React.Dispatch>>; + userList: NumberMap; + setUserList: React.Dispatch>>; sendMessage: (m: string) => void; channelName?: string; }) { diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index 7bd011c..173911e 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -28,7 +28,7 @@ import { Card } from "./ui/card"; import { ScrollArea } from "./ui/scroll-area"; import { useRouter } from "next/navigation"; import Link from "next/link"; -import useUser, { User } from "@/hooks/get-user"; +import useUser, { UserProfile } from "@/hooks/get-user"; import ProfilePicture from "./ProfilePicture"; import auth, { makeAddress } from "@/lib/auth"; import { toast } from "sonner"; @@ -47,19 +47,18 @@ export default function AppSidebar({ wsRef: React.RefObject; setMessages: React.Dispatch>; onNewMessage?: (msg: Message) => void; - userList: StringMap; - setUserList: React.Dispatch>>; + userList: StringMap; + setUserList: React.Dispatch>>; chatWith?: string; children?: React.ReactNode; - setUser?: React.Dispatch>; + setUser?: React.Dispatch>; server?: Server | undefined; }>) { const [servers, setServers] = useState<[string, string][]>([]); const [newServer, setNewServer] = useState({ name: "", ip: "" }); const router = useRouter(); const user = useUser(); - const [userList, setUserList] = useState>({}); - const ip = "192.168.100.3"; + const [userList, setUserList] = useState>({}); useEffect(() => { const s = Cookies.get("servers")?.split(","); @@ -67,10 +66,10 @@ export default function AppSidebar({ }, []); useEffect(() => { - if (!ip || !user) return; + if (!user?.node_address) return; if (setUser) setUser(user); auth( - makeAddress(ip, 7090), + makeAddress(user?.node_address, 7090), wsRef, () => {}, setMessages, diff --git a/src/hooks/get-user.ts b/src/hooks/get-user.ts index f1fdb35..1c693f9 100644 --- a/src/hooks/get-user.ts +++ b/src/hooks/get-user.ts @@ -1,19 +1,17 @@ "use client"; +import { ProfileSettings } from "@/types/settings"; import axios from "axios"; import Cookies from "js-cookie"; import { useRouter } from "next/navigation"; import { useEffect, useState } from "react"; -export interface User { +export interface UserProfile extends ProfileSettings { id: string; - username: string; - display_name: string; - avatar_url: string; } export default function useUser() { - const [user, setUser] = useState(null); + const [user, setUser] = useState(null); const router = useRouter(); useEffect(() => { @@ -25,7 +23,7 @@ export default function useUser() { } try { - const res = (await axios.get("/api/profile")).data as User; + const res = (await axios.get("/api/profile")).data as UserProfile; setUser(res); } catch { diff --git a/src/lib/auth.ts b/src/lib/auth.ts index 1124987..d333770 100644 --- a/src/lib/auth.ts +++ b/src/lib/auth.ts @@ -3,7 +3,9 @@ import axios from "axios"; import { Dispatch, RefObject, SetStateAction } from "react"; export function makeAddress(ip: string, defaultPort = 7080) { - return ip.includes(":") ? `${ip}` : `${ip}:${defaultPort}`; + // return ip.includes(":") ? `${ip}` : `${ip}:${defaultPort}`; + // Apparently wss doesn't like ports (or maybe the tunnel I'm using) + return ip; } export default async function auth( @@ -19,7 +21,7 @@ export default async function auth( ).token; // Open the WebSocket connection - const ws = new WebSocket(`ws://${ip}`); + const ws = new WebSocket(`wss://${ip}`); wsRef.current = ws; ws.onopen = () => {