mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 04:51:51 +00:00
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:
committed by
GitHub
parent
84c30af6f8
commit
05d2b86ba8
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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: [
|
||||
|
||||
Reference in New Issue
Block a user