+28
-19
@@ -4,24 +4,36 @@ import { supabase } from "../supa";
|
||||
|
||||
const SERVER_AUTH_TOKENS = new Map<
|
||||
string,
|
||||
{ user_id: string; server_ip: string }
|
||||
{ user_id: string; server_id: string }
|
||||
>();
|
||||
|
||||
/**
|
||||
* GET /api/auth?token=<relayToken>
|
||||
* GET /api/auth?token=<relayToken>?key=<serverKey>
|
||||
* Called by a (DM node / Server) to verify a temporary relay token.
|
||||
*/
|
||||
export async function GET(req: NextRequest) {
|
||||
const url = new URL(req.url);
|
||||
const token = url.searchParams.get("token");
|
||||
const key = url.searchParams.get("key");
|
||||
|
||||
if (!token) {
|
||||
if (!token || !key) {
|
||||
return NextResponse.json(
|
||||
{ message: "There should be a token parameter" },
|
||||
{ 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) {
|
||||
return NextResponse.json(
|
||||
@@ -30,19 +42,11 @@ export async function GET(req: NextRequest) {
|
||||
);
|
||||
}
|
||||
|
||||
const ip =
|
||||
req.headers.get("x-real-ip") ||
|
||||
req.headers.get("x-forwarded-for")?.split(",")[0] ||
|
||||
"127.0.0.1";
|
||||
|
||||
console.log("Auth request from IP:", ip);
|
||||
|
||||
if (auth.server_ip !== ip && ip !== "::1") {
|
||||
if (auth.server_id !== server.id)
|
||||
return NextResponse.json(
|
||||
{ message: "Invalid address" },
|
||||
{ message: "Invalid id" },
|
||||
{ status: StatusCodes.UNAUTHORIZED }
|
||||
);
|
||||
}
|
||||
|
||||
SERVER_AUTH_TOKENS.delete(token);
|
||||
|
||||
@@ -53,19 +57,24 @@ export async function GET(req: NextRequest) {
|
||||
* POST /api/auth
|
||||
* Called by the client to request a temporary relay token for a DM server.
|
||||
*
|
||||
* Body: { server_ip: string }
|
||||
* Body: { server_id: string }
|
||||
* Header: Authorization: Bearer <supabase_jwt>
|
||||
*/
|
||||
export async function POST(req: NextRequest) {
|
||||
const { server_ip } = await req.json();
|
||||
const { server_id } = await req.json();
|
||||
const authHeader = req.cookies.get("token");
|
||||
|
||||
if (!authHeader) {
|
||||
if (!server_id)
|
||||
return NextResponse.json(
|
||||
{ message: "Missing server_id in the json body" },
|
||||
{ status: StatusCodes.BAD_REQUEST }
|
||||
);
|
||||
|
||||
if (!authHeader)
|
||||
return NextResponse.json(
|
||||
{ message: "Missing Supabase Authorization header" },
|
||||
{ status: StatusCodes.BAD_REQUEST }
|
||||
);
|
||||
}
|
||||
|
||||
const supabaseToken = authHeader.value;
|
||||
|
||||
@@ -85,7 +94,7 @@ export async function POST(req: NextRequest) {
|
||||
|
||||
SERVER_AUTH_TOKENS.set(relayToken, {
|
||||
user_id: user.id,
|
||||
server_ip: String(server_ip),
|
||||
server_id,
|
||||
});
|
||||
|
||||
return NextResponse.json({ message: "ok", token: relayToken });
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { supabase } from "../../supa";
|
||||
import { StatusCodes } from "http-status-codes";
|
||||
|
||||
/**
|
||||
* GET /api/server/<id>
|
||||
*/
|
||||
export async function GET(
|
||||
req: NextRequest,
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
const { id } = await params;
|
||||
|
||||
const { data: profile } = await supabase
|
||||
.from("servers")
|
||||
.select("id, created_at, owner, address")
|
||||
.eq("id", id)
|
||||
.maybeSingle();
|
||||
|
||||
if (!profile)
|
||||
return NextResponse.json(
|
||||
{ message: "not found" },
|
||||
{ status: StatusCodes.NOT_FOUND }
|
||||
);
|
||||
|
||||
return NextResponse.json({ message: "ok", ...profile });
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
MessageCircle,
|
||||
Plus,
|
||||
Search,
|
||||
SettingsIcon,
|
||||
Volume2Icon,
|
||||
} from "lucide-react";
|
||||
import { Server, Channel, Message } from "@/types/types";
|
||||
@@ -27,10 +26,9 @@ import { Button } from "./ui/button";
|
||||
import { Card } from "./ui/card";
|
||||
import { ScrollArea } from "./ui/scroll-area";
|
||||
import { useRouter } from "next/navigation";
|
||||
import Link from "next/link";
|
||||
import useUser, { UserProfile } from "@/hooks/get-user";
|
||||
import ProfilePicture from "./ProfilePicture";
|
||||
import auth, { makeAddress } from "@/lib/auth";
|
||||
import auth from "@/lib/auth";
|
||||
import { toast } from "sonner";
|
||||
import { StringMap } from "@/types/typeUtils";
|
||||
import SettingsDialog from "./settings/SettingsDialog";
|
||||
|
||||
+8
-21
@@ -2,34 +2,21 @@ import { Message, Server } from "@/types/types";
|
||||
import axios from "axios";
|
||||
import { Dispatch, RefObject, SetStateAction } from "react";
|
||||
|
||||
async function getIP(domain: string) {
|
||||
const res = await fetch(`https://dns.google/resolve?name=${domain}&type=A`);
|
||||
const data = await res.json();
|
||||
return data.Answer[0]?.data || null;
|
||||
}
|
||||
|
||||
export async function makeAddress(ip: string, defaultPort = 7080) {
|
||||
// Apparently wss doesn't like ports (or maybe the tunnel I'm using)
|
||||
// return ip.includes(":") ? `${ip}` : `${ip}:${defaultPort}`;
|
||||
if (ip.match(/^\d\.\d\.\d\.\d/)) {
|
||||
return ip;
|
||||
}
|
||||
|
||||
return await getIP(ip);
|
||||
}
|
||||
|
||||
export default async function auth(
|
||||
ip: string,
|
||||
id: string,
|
||||
wsRef: RefObject<WebSocket | null>,
|
||||
setServer: Dispatch<SetStateAction<Server | undefined>>,
|
||||
setMessages: Dispatch<SetStateAction<Message[]>>,
|
||||
onNewMessage?: (m: Message) => void
|
||||
) {
|
||||
console.log("Authenticating with server id:", id);
|
||||
|
||||
const ip = ((await axios.get(`/api/server/${id}`)).data as any)
|
||||
.address as string;
|
||||
|
||||
console.log("Authenticating with server at:", ip);
|
||||
const server_auth = (
|
||||
(await axios.post("/api/auth", { server_ip: await makeAddress(ip) }))
|
||||
.data as any
|
||||
).token;
|
||||
const server_auth = ((await axios.post("/api/auth", { server_id: id })).data as any)
|
||||
.token;
|
||||
|
||||
// Open the WebSocket connection
|
||||
const ws = new WebSocket(`wss://${ip}`);
|
||||
|
||||
Reference in New Issue
Block a user