import { getAuthenticatedUser } from "@/auth"; import { getUserEffectiveSettings } from "@/database/settings"; import { getLoginEvents, getUserSessions, getUserHas2FA } from "@/lib/keycloak"; import AccountSecurity from "@/components/account/AccountSecurity"; export default async function SecurityPage() { const user = await getAuthenticatedUser(); let loginSessions: Array<{ id: string; loginTime: string; ipAddress: string; device: string; location: string; status: "success" | "failed"; }> = []; let securityEvents: Array<{ id: string; event: string; detail: string; timestamp: string; icon: string; color: string; }> = []; let twoFactorEnabled = false; let loginNotifications = true; let activeSessionCount = 0; if (user?.keycloakId) { try { const [events, has2FA, sessions] = await Promise.all([ getLoginEvents(user.keycloakId, 20), getUserHas2FA(user.keycloakId), getUserSessions(user.keycloakId), ]); twoFactorEnabled = has2FA; activeSessionCount = sessions.length; // Map Keycloak events to login sessions loginSessions = events.map((e, i) => ({ id: String(i), loginTime: new Date(e.time).toISOString(), ipAddress: e.ipAddress || "Unknown", device: e.details?.user_agent ? parseUserAgent(e.details.user_agent) : "Unknown", location: "—", status: e.type === "LOGIN" ? "success" as const : "failed" as const, })); // Map to security events timeline securityEvents = events.slice(0, 10).map((e, i) => ({ id: String(i), event: e.type === "LOGIN" ? "Login" : "Failed Login", detail: e.type === "LOGIN" ? `Successful login from ${e.ipAddress || "unknown"}` : `Failed login attempt: ${e.error || "invalid credentials"}`, timestamp: new Date(e.time).toISOString(), icon: e.type === "LOGIN" ? "ph-sign-in" : "ph-warning", color: e.type === "LOGIN" ? "success" : "danger", })); } catch (err) { console.warn("[security page] Keycloak fetch error:", err); } } // Load loginNotifications preference from DB if (user?.gscUserId) { try { const effective = await getUserEffectiveSettings( user.gscUserId, user.tenantId, user.gscCustomerId, ["user.security"] ); const secSettings = effective["user.security"]; if (secSettings?.loginNotifications) { loginNotifications = secSettings.loginNotifications.value as boolean; } } catch { // Use default } } return ( ); } function parseUserAgent(ua: string): string { if (ua.includes("Chrome") && !ua.includes("Edge")) { if (ua.includes("Windows")) return "Chrome on Windows"; if (ua.includes("Mac")) return "Chrome on macOS"; if (ua.includes("Linux")) return "Chrome on Linux"; return "Chrome"; } if (ua.includes("Firefox")) { if (ua.includes("Windows")) return "Firefox on Windows"; if (ua.includes("Mac")) return "Firefox on macOS"; return "Firefox"; } if (ua.includes("Safari") && !ua.includes("Chrome")) { if (ua.includes("iPhone") || ua.includes("iPad")) return "Safari on iOS"; return "Safari on macOS"; } if (ua.includes("Edge")) return "Edge on Windows"; return "Unknown"; }