feat: add auth to gatekeeper
All checks were successful
Monorepo Pipeline / 🧪 Quality Assurance (push) Successful in 5m0s
Monorepo Pipeline / 🚀 Release (push) Successful in 3m43s
Monorepo Pipeline / 🐳 Build & Push Images (push) Successful in 5m16s

This commit is contained in:
2026-02-07 14:48:39 +01:00
parent 61e78ea672
commit a594affdfa
3 changed files with 132 additions and 18 deletions

View File

@@ -17,16 +17,69 @@ export default async function LoginPage({ searchParams }: LoginPageProps) {
async function login(formData: FormData) {
"use server";
const password = formData.get("password");
const expectedPassword = process.env.GATEKEEPER_PASSWORD || "mintel";
const email = formData.get("email") as string;
const password = formData.get("password") as string;
const expectedCode = process.env.GATEKEEPER_PASSWORD || "mintel";
const adminEmail = process.env.DIRECTUS_ADMIN_EMAIL;
const adminPassword = process.env.DIRECTUS_ADMIN_PASSWORD;
const authCookieName =
process.env.AUTH_COOKIE_NAME || "mintel_gatekeeper_session";
const targetRedirect = formData.get("redirect") as string;
const cookieDomain = process.env.COOKIE_DOMAIN;
if (password === expectedPassword) {
let userIdentity = "";
// 1. Check Global Admin (from ENV)
if (
adminEmail &&
adminPassword &&
email === adminEmail &&
password === adminPassword
) {
userIdentity = "Admin";
}
// 2. Check Generic Code (Guest)
else if (!email && password === expectedCode) {
userIdentity = "Guest";
}
// 3. Check Directus if email is provided
if (email && password && process.env.DIRECTUS_URL) {
try {
const loginRes = await fetch(`${process.env.DIRECTUS_URL}/auth/login`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, password }),
});
if (loginRes.ok) {
const { data } = await loginRes.json();
const accessToken = data.access_token;
// Fetch user info to get a nice display name
const userRes = await fetch(`${process.env.DIRECTUS_URL}/users/me`, {
headers: { Authorization: `Bearer ${accessToken}` },
});
if (userRes.ok) {
const { data: user } = await userRes.json();
userIdentity = user.first_name || user.email;
}
}
} catch (e) {
console.error("Directus Auth Error:", e);
}
}
if (userIdentity) {
const cookieStore = await cookies();
cookieStore.set(authCookieName, expectedPassword, {
// Store identity in the cookie (simplified for now, ideally signed)
const sessionValue = JSON.stringify({
identity: userIdentity,
timestamp: Date.now(),
});
cookieStore.set(authCookieName, sessionValue, {
httpOnly: true,
secure: true,
path: "/",
@@ -85,24 +138,35 @@ export default async function LoginPage({ searchParams }: LoginPageProps) {
</div>
)}
<form action={login} className="space-y-6">
<form action={login} className="space-y-4">
<input type="hidden" name="redirect" value={redirectUrl} />
<div className="relative group">
<input
type="password"
name="password"
required
autoFocus
autoComplete="current-password"
placeholder="GATEKEEPER CODE"
className="w-full bg-slate-50/50 border border-slate-200 rounded-2xl px-6 py-4 focus:outline-none focus:border-slate-900 focus:bg-white transition-all text-sm font-sans font-bold tracking-[0.3em] uppercase placeholder:text-slate-300 placeholder:tracking-widest shadow-sm shadow-slate-50"
/>
<div className="space-y-2">
<div className="relative group">
<input
type="email"
name="email"
placeholder="EMAIL (OPTIONAL)"
className="w-full bg-slate-50/50 border border-slate-200 rounded-2xl px-6 py-4 focus:outline-none focus:border-slate-900 focus:bg-white transition-all text-[10px] font-sans font-bold tracking-[0.2em] uppercase placeholder:text-slate-300 shadow-sm shadow-slate-50"
/>
</div>
<div className="relative group">
<input
type="password"
name="password"
required
autoFocus
autoComplete="current-password"
placeholder="ACCESS CODE"
className="w-full bg-slate-50/50 border border-slate-200 rounded-2xl px-6 py-4 focus:outline-none focus:border-slate-900 focus:bg-white transition-all text-sm font-sans font-bold tracking-[0.3em] uppercase placeholder:text-slate-300 placeholder:tracking-widest shadow-sm shadow-slate-50"
/>
</div>
</div>
<button
type="submit"
className="btn btn-primary w-full py-5 rounded-2xl text-[10px] shadow-lg shadow-slate-100"
className="btn btn-primary w-full py-5 rounded-2xl text-[10px] shadow-lg shadow-slate-100 flex items-center justify-center"
>
Unlock Access
<ArrowRight className="ml-3 w-3 h-3 group-hover:translate-x-1 transition-transform" />