2026-01-09 05:29:11 -05:00
|
|
|
import { NextResponse } from "next/server";
|
2026-01-19 18:31:08 -05:00
|
|
|
import { getSettings } from "@/lib/localDb";
|
2026-01-09 05:29:11 -05:00
|
|
|
import bcrypt from "bcryptjs";
|
|
|
|
|
import { cookies } from "next/headers";
|
2026-05-11 22:43:42 -04:00
|
|
|
import { setDashboardAuthCookie } from "@/lib/auth/dashboardSession";
|
|
|
|
|
import { isOidcConfigured } from "@/lib/auth/oidc";
|
2026-01-09 05:29:11 -05:00
|
|
|
|
2026-04-13 06:38:09 -04:00
|
|
|
function isTunnelRequest(request, settings) {
|
|
|
|
|
const host = (request.headers.get("host") || "").split(":")[0].toLowerCase();
|
|
|
|
|
const tunnelHost = settings.tunnelUrl ? new URL(settings.tunnelUrl).hostname.toLowerCase() : "";
|
|
|
|
|
const tailscaleHost = settings.tailscaleUrl ? new URL(settings.tailscaleUrl).hostname.toLowerCase() : "";
|
|
|
|
|
return (tunnelHost && host === tunnelHost) || (tailscaleHost && host === tailscaleHost);
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-09 05:29:11 -05:00
|
|
|
export async function POST(request) {
|
|
|
|
|
try {
|
|
|
|
|
const { password } = await request.json();
|
|
|
|
|
const settings = await getSettings();
|
|
|
|
|
|
2026-04-13 06:38:09 -04:00
|
|
|
// Block login via tunnel/tailscale if dashboard access is disabled
|
|
|
|
|
if (isTunnelRequest(request, settings) && settings.tunnelDashboardAccess !== true) {
|
|
|
|
|
return NextResponse.json({ error: "Dashboard access via tunnel is disabled" }, { status: 403 });
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-09 05:29:11 -05:00
|
|
|
// Default password is '123456' if not set
|
|
|
|
|
const storedHash = settings.password;
|
|
|
|
|
|
2026-05-11 22:43:42 -04:00
|
|
|
if (settings.authMode === "oidc" && isOidcConfigured(settings)) {
|
|
|
|
|
return NextResponse.json({ error: "Password login is disabled. Use OIDC sign in." }, { status: 403 });
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-09 05:29:11 -05:00
|
|
|
let isValid = false;
|
2026-01-19 18:31:08 -05:00
|
|
|
if (storedHash) {
|
|
|
|
|
isValid = await bcrypt.compare(password, storedHash);
|
|
|
|
|
} else {
|
2026-01-19 05:15:11 -05:00
|
|
|
// Use env var or default
|
|
|
|
|
const initialPassword = process.env.INITIAL_PASSWORD || "123456";
|
|
|
|
|
isValid = password === initialPassword;
|
2026-01-09 05:29:11 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isValid) {
|
|
|
|
|
const cookieStore = await cookies();
|
2026-05-11 22:43:42 -04:00
|
|
|
await setDashboardAuthCookie(cookieStore, request);
|
2026-01-09 05:29:11 -05:00
|
|
|
|
|
|
|
|
return NextResponse.json({ success: true });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NextResponse.json({ error: "Invalid password" }, { status: 401 });
|
|
|
|
|
} catch (error) {
|
|
|
|
|
return NextResponse.json({ error: error.message }, { status: 500 });
|
|
|
|
|
}
|
|
|
|
|
}
|