Websocket and auth fixes

This commit is contained in:
2025-10-15 15:14:27 +02:00
parent 8b562a37b2
commit cf32a2b778
7 changed files with 54 additions and 41 deletions
+24 -21
View File
@@ -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=<relayToken>?key=<serverKey>
* 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();
SERVER_AUTH_TOKENS.set(relayToken, {
const { data: relayToken, error: errorRelay } = await supabase
.from("server_auth")
.insert({
user_id: user.id,
server_id,
});
})
.select()
.maybeSingle();
return NextResponse.json({ message: "ok", token: relayToken });
if (!relayToken || errorRelay)
return NextResponse.json(
{ message: "Failed to create relay token" },
{ status: StatusCodes.INTERNAL_SERVER_ERROR }
);
return NextResponse.json({ message: "ok", token: relayToken.key });
}
+14 -2
View File
@@ -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 });
}
+1 -1
View File
@@ -38,7 +38,7 @@ function MessageContainer({
[message.from]: res.data as UserProfile,
}))
)
.catch(console.error);
.catch(() => {});
}, [message.from, setUserList]);
return (
+1 -3
View File
@@ -338,7 +338,5 @@ function getUser(
get(`/api/profile/?id=${id}`, onResponse)
?.then(onResponse)
.catch((e) => {
console.error(e);
});
.catch((e) => {});
}
+3 -1
View File
@@ -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}`);
}
}
+3 -5
View File
@@ -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);
}
+7 -7
View File
@@ -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;
}