Spaces:
Sleeping
Sleeping
fix: fix cookie issue
Browse files
frontend/app/admin/page.tsx
CHANGED
|
@@ -17,7 +17,8 @@ export default function AdminPage() {
|
|
| 17 |
useEffect(() => {
|
| 18 |
(async () => {
|
| 19 |
const r = await fetch("/api/admin/me", { credentials: "same-origin" });
|
| 20 |
-
|
|
|
|
| 21 |
else setChecking(false);
|
| 22 |
})();
|
| 23 |
}, [router]);
|
|
|
|
| 17 |
useEffect(() => {
|
| 18 |
(async () => {
|
| 19 |
const r = await fetch("/api/admin/me", { credentials: "same-origin" });
|
| 20 |
+
const session = r.ok ? await r.json().catch(() => null) : null;
|
| 21 |
+
if (!session?.authenticated) router.replace("/admin/login");
|
| 22 |
else setChecking(false);
|
| 23 |
})();
|
| 24 |
}, [router]);
|
frontend/app/api/admin/login/route.ts
CHANGED
|
@@ -4,6 +4,16 @@ import { backendUrl } from "@/lib/backend-url";
|
|
| 4 |
export const dynamic = "force-dynamic";
|
| 5 |
export const runtime = "nodejs";
|
| 6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
export async function POST(request: NextRequest) {
|
| 8 |
let response: Response;
|
| 9 |
try {
|
|
@@ -21,14 +31,24 @@ export async function POST(request: NextRequest) {
|
|
| 21 |
);
|
| 22 |
}
|
| 23 |
|
| 24 |
-
const
|
| 25 |
-
|
| 26 |
-
const cookie = response.headers.get("set-cookie");
|
| 27 |
-
if (cookie) headers.set("set-cookie", cookie);
|
| 28 |
-
|
| 29 |
-
return new NextResponse(await response.text(), {
|
| 30 |
status: response.status,
|
| 31 |
-
headers
|
|
|
|
|
|
|
| 32 |
});
|
| 33 |
-
}
|
| 34 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
export const dynamic = "force-dynamic";
|
| 5 |
export const runtime = "nodejs";
|
| 6 |
|
| 7 |
+
const ADMIN_COOKIE = "admin_session";
|
| 8 |
+
const SESSION_MAX_AGE = 60 * 60 * 12;
|
| 9 |
+
|
| 10 |
+
function sessionValue(setCookie: string | null) {
|
| 11 |
+
const pair = setCookie?.split(";")[0] ?? "";
|
| 12 |
+
const [name, ...valueParts] = pair.split("=");
|
| 13 |
+
if (name !== ADMIN_COOKIE || valueParts.length === 0) return null;
|
| 14 |
+
return valueParts.join("=");
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
export async function POST(request: NextRequest) {
|
| 18 |
let response: Response;
|
| 19 |
try {
|
|
|
|
| 31 |
);
|
| 32 |
}
|
| 33 |
|
| 34 |
+
const body = response.ok ? JSON.stringify({ ok: true }) : await response.text();
|
| 35 |
+
const nextResponse = new NextResponse(body, {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
status: response.status,
|
| 37 |
+
headers: {
|
| 38 |
+
"content-type": response.headers.get("content-type") ?? "application/json",
|
| 39 |
+
},
|
| 40 |
});
|
|
|
|
| 41 |
|
| 42 |
+
const value = sessionValue(response.headers.get("set-cookie"));
|
| 43 |
+
if (response.ok && value) {
|
| 44 |
+
nextResponse.cookies.set(ADMIN_COOKIE, value, {
|
| 45 |
+
httpOnly: true,
|
| 46 |
+
sameSite: "lax",
|
| 47 |
+
secure: request.nextUrl.protocol === "https:",
|
| 48 |
+
maxAge: SESSION_MAX_AGE,
|
| 49 |
+
path: "/",
|
| 50 |
+
});
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
return nextResponse;
|
| 54 |
+
}
|
frontend/app/api/admin/logout/route.ts
CHANGED
|
@@ -4,6 +4,8 @@ import { backendUrl } from "@/lib/backend-url";
|
|
| 4 |
export const dynamic = "force-dynamic";
|
| 5 |
export const runtime = "nodejs";
|
| 6 |
|
|
|
|
|
|
|
| 7 |
export async function POST(request: NextRequest) {
|
| 8 |
let response: Response;
|
| 9 |
try {
|
|
@@ -20,14 +22,19 @@ export async function POST(request: NextRequest) {
|
|
| 20 |
);
|
| 21 |
}
|
| 22 |
|
| 23 |
-
const
|
| 24 |
-
headers.set("content-type", response.headers.get("content-type") ?? "application/json");
|
| 25 |
-
const cookie = response.headers.get("set-cookie");
|
| 26 |
-
if (cookie) headers.set("set-cookie", cookie);
|
| 27 |
-
|
| 28 |
-
return new NextResponse(await response.text(), {
|
| 29 |
status: response.status,
|
| 30 |
-
headers
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
});
|
| 32 |
-
}
|
| 33 |
|
|
|
|
|
|
|
|
|
| 4 |
export const dynamic = "force-dynamic";
|
| 5 |
export const runtime = "nodejs";
|
| 6 |
|
| 7 |
+
const ADMIN_COOKIE = "admin_session";
|
| 8 |
+
|
| 9 |
export async function POST(request: NextRequest) {
|
| 10 |
let response: Response;
|
| 11 |
try {
|
|
|
|
| 22 |
);
|
| 23 |
}
|
| 24 |
|
| 25 |
+
const nextResponse = new NextResponse(await response.text(), {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
status: response.status,
|
| 27 |
+
headers: {
|
| 28 |
+
"content-type": response.headers.get("content-type") ?? "application/json",
|
| 29 |
+
},
|
| 30 |
+
});
|
| 31 |
+
nextResponse.cookies.set(ADMIN_COOKIE, "", {
|
| 32 |
+
httpOnly: true,
|
| 33 |
+
sameSite: "lax",
|
| 34 |
+
secure: request.nextUrl.protocol === "https:",
|
| 35 |
+
maxAge: 0,
|
| 36 |
+
path: "/",
|
| 37 |
});
|
|
|
|
| 38 |
|
| 39 |
+
return nextResponse;
|
| 40 |
+
}
|
frontend/app/api/admin/me/route.ts
CHANGED
|
@@ -20,6 +20,13 @@ export async function GET(request: NextRequest) {
|
|
| 20 |
);
|
| 21 |
}
|
| 22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
return new NextResponse(await response.text(), {
|
| 24 |
status: response.status,
|
| 25 |
headers: {
|
|
@@ -28,4 +35,3 @@ export async function GET(request: NextRequest) {
|
|
| 28 |
},
|
| 29 |
});
|
| 30 |
}
|
| 31 |
-
|
|
|
|
| 20 |
);
|
| 21 |
}
|
| 22 |
|
| 23 |
+
if (response.status === 401 || response.status === 403) {
|
| 24 |
+
return NextResponse.json(
|
| 25 |
+
{ authenticated: false },
|
| 26 |
+
{ status: 200, headers: { "cache-control": "no-store" } }
|
| 27 |
+
);
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
return new NextResponse(await response.text(), {
|
| 31 |
status: response.status,
|
| 32 |
headers: {
|
|
|
|
| 35 |
},
|
| 36 |
});
|
| 37 |
}
|
|
|