feat(lighthouse): update NextJS logic to work with latest APIs (#8033)

Co-authored-by: Chandrapal Badshah <12944530+Chan9390@users.noreply.github.com>
This commit is contained in:
Chandrapal Badshah
2025-06-17 13:55:37 +05:30
committed by GitHub
parent 84c30af6f8
commit 05d2b86ba8
5 changed files with 98 additions and 63 deletions
+62 -36
View File
@@ -2,11 +2,12 @@
import { apiBaseUrl, getAuthHeaders } from "@/lib/helper";
const getLighthouseConfigId = async (): Promise<string> => {
export const getAIKey = async (): Promise<string> => {
const headers = await getAuthHeaders({ contentType: false });
const url = new URL(
`${apiBaseUrl}/lighthouse-configurations?filter[name]=OpenAI`,
`${apiBaseUrl}/lighthouse-configurations?fields[lighthouse-config]=api_key`,
);
try {
const response = await fetch(url.toString(), {
method: "GET",
@@ -17,35 +18,35 @@ const getLighthouseConfigId = async (): Promise<string> => {
// Check if data array exists and has at least one item
if (data?.data && data.data.length > 0) {
return data.data[0].id;
return data.data[0].attributes.api_key || "";
}
// Return empty string if no configuration found
return "";
} catch (error) {
console.error("[Server] Error in getOpenAIConfigurationId:", error);
console.error("[Server] Error in getAIKey:", error);
return "";
}
};
export const getAIKey = async (): Promise<string> => {
export const checkLighthouseConnection = async (configId: string) => {
const headers = await getAuthHeaders({ contentType: false });
const configId = await getLighthouseConfigId();
if (!configId) {
return "";
}
const url = new URL(
`${apiBaseUrl}/lighthouse-configurations/${configId}?fields[lighthouse-config]=api_key`,
`${apiBaseUrl}/lighthouse-configurations/${configId}/connection`,
);
const response = await fetch(url.toString(), {
method: "GET",
headers,
});
const data = await response.json();
return data.data.attributes.api_key;
try {
const response = await fetch(url.toString(), {
method: "POST",
headers,
});
const data = await response.json();
return data;
} catch (error) {
console.error("[Server] Error in checkLighthouseConnection:", error);
return undefined;
}
};
export const createLighthouseConfig = async (config: {
@@ -74,29 +75,36 @@ export const createLighthouseConfig = async (config: {
body: JSON.stringify(payload),
});
const data = await response.json();
// Trigger connection check in background
if (data?.data?.id) {
checkLighthouseConnection(data.data.id);
}
return data;
} catch (error) {
console.error("[Server] Error in createAIConfiguration:", error);
console.error("[Server] Error in createLighthouseConfig:", error);
return undefined;
}
};
export const getLighthouseConfig = async () => {
const headers = await getAuthHeaders({ contentType: false });
const configId = await getLighthouseConfigId();
const url = new URL(`${apiBaseUrl}/lighthouse-configurations`);
if (!configId) {
return undefined;
}
const url = new URL(`${apiBaseUrl}/lighthouse-configurations/${configId}`);
try {
const response = await fetch(url.toString(), {
method: "GET",
headers,
});
const data = await response.json();
return data;
// Check if data array exists and has at least one item
if (data?.data && data.data.length > 0) {
return data.data[0];
}
return undefined;
} catch (error) {
console.error("[Server] Error in getLighthouseConfig:", error);
return undefined;
@@ -109,14 +117,26 @@ export const updateLighthouseConfig = async (config: {
businessContext: string;
}) => {
const headers = await getAuthHeaders({ contentType: true });
const configId = await getLighthouseConfigId();
if (!configId) {
return undefined;
}
// Get the config ID from the list endpoint
const url = new URL(`${apiBaseUrl}/lighthouse-configurations`);
try {
const url = new URL(`${apiBaseUrl}/lighthouse-configurations/${configId}`);
const response = await fetch(url.toString(), {
method: "GET",
headers: await getAuthHeaders({ contentType: false }),
});
const data = await response.json();
// Check if data array exists and has at least one item
if (!data?.data || data.data.length === 0) {
return undefined;
}
const configId = data.data[0].id;
const updateUrl = new URL(
`${apiBaseUrl}/lighthouse-configurations/${configId}`,
);
// Prepare the request payload following the JSONAPI format
const payload = {
@@ -131,16 +151,22 @@ export const updateLighthouseConfig = async (config: {
},
};
const response = await fetch(url.toString(), {
const updateResponse = await fetch(updateUrl.toString(), {
method: "PATCH",
headers,
body: JSON.stringify(payload),
});
const data = await response.json();
return data;
const updateData = await updateResponse.json();
// Trigger connection check in background
if (updateData?.data?.id || configId) {
checkLighthouseConnection(configId);
}
return updateData;
} catch (error) {
console.error("[Server] Error in updateAIConfiguration:", error);
console.error("[Server] Error in updateLighthouseConfig:", error);
return undefined;
}
};
+4 -5
View File
@@ -6,12 +6,11 @@ export const dynamic = "force-dynamic";
export default async function ChatbotConfigPage() {
const response = await getLighthouseConfig();
const initialValues = response?.data?.attributes
const initialValues = response?.attributes
? {
model: response.data.attributes.model,
apiKey: response.data.attributes.api_key || "",
businessContext: response.data.attributes.business_context || "",
model: response.attributes.model,
apiKey: response.attributes.api_key || "",
businessContext: response.attributes.business_context || "",
}
: {
model: "gpt-4o",
+6 -3
View File
@@ -1,13 +1,16 @@
import { getAIKey } from "@/actions/lighthouse/lighthouse";
import { getLighthouseConfig } from "@/actions/lighthouse/lighthouse";
import { Chat } from "@/components/lighthouse";
import { ContentLayout } from "@/components/ui";
export default async function AIChatbot() {
const apiKey = await getAIKey();
const config = await getLighthouseConfig();
const hasConfig = !!config;
const isActive = config?.attributes?.is_active ?? false;
return (
<ContentLayout title="Cloud Security Analyst" icon="lucide:bot">
<Chat hasApiKey={!!apiKey} />
<Chat hasConfig={hasConfig} isActive={isActive} />
</ContentLayout>
);
}
+13 -6
View File
@@ -16,14 +16,15 @@ interface SuggestedAction {
}
interface ChatProps {
hasApiKey: boolean;
hasConfig: boolean;
isActive: boolean;
}
interface ChatFormData {
message: string;
}
export const Chat = ({ hasApiKey }: ChatProps) => {
export const Chat = ({ hasConfig, isActive }: ChatProps) => {
const { messages, handleSubmit, handleInputChange, append, status } = useChat(
{
api: "/api/lighthouse/analyst",
@@ -119,17 +120,23 @@ export const Chat = ({ hasApiKey }: ChatProps) => {
},
];
// Determine if chat should be disabled
const shouldDisableChat = !hasConfig || !isActive;
return (
<div className="relative flex h-[calc(100vh-theme(spacing.16))] min-w-0 flex-col bg-background">
{!hasApiKey && (
{shouldDisableChat && (
<div className="absolute inset-0 z-50 flex items-center justify-center bg-background/80 backdrop-blur-sm">
<div className="bg-card max-w-md rounded-lg p-6 text-center shadow-lg">
<h3 className="mb-2 text-lg font-semibold">
OpenAI API Key Required
{!hasConfig
? "OpenAI API Key Required"
: "OpenAI API Key Invalid"}
</h3>
<p className="text-muted-foreground mb-4">
Please configure your OpenAI API key to use the Lighthouse Cloud
Security Analyst.
{!hasConfig
? "Please configure your OpenAI API key to use the Lighthouse Cloud Security Analyst."
: "OpenAI API key is invalid. Please update your key to use Lighthouse Cloud Security Analyst."}
</p>
<Link
href="/lighthouse/config"
+13 -13
View File
@@ -3,9 +3,9 @@
import {
AlertCircle,
Bookmark,
// Bot,
Bot,
CloudCog,
// Cog,
Cog,
Group,
LayoutGrid,
Mail,
@@ -135,7 +135,7 @@ export const getMenuList = (pathname: string): GroupProps[] => {
{ href: "/manage-groups", label: "Provider Groups", icon: Group },
{ href: "/scans", label: "Scan Jobs", icon: Timer },
{ href: "/roles", label: "Roles", icon: UserCog },
// { href: "/lighthouse/config", label: "Lighthouse", icon: Cog },
{ href: "/lighthouse/config", label: "Lighthouse", icon: Cog },
],
defaultOpen: true,
},
@@ -156,16 +156,16 @@ export const getMenuList = (pathname: string): GroupProps[] => {
},
],
},
// {
// groupLabel: "Prowler Lighthouse",
// menus: [
// {
// href: "/lighthouse",
// label: "Lighthouse",
// icon: Bot,
// },
// ],
// },
{
groupLabel: "Prowler Lighthouse",
menus: [
{
href: "/lighthouse",
label: "Lighthouse",
icon: Bot,
},
],
},
{
groupLabel: "",
menus: [