From c0622f660be314cfccbe83f0675489d7293cc7c2 Mon Sep 17 00:00:00 2001 From: Chandrapal Badshah <12944530+Chan9390@users.noreply.github.com> Date: Tue, 6 May 2025 17:05:30 +0530 Subject: [PATCH] Remove show_key endpoint --- api/src/backend/api/tests/test_views.py | 5 ++-- api/src/backend/api/v1/serializers.py | 18 +++++++++---- api/src/backend/api/v1/views.py | 35 ------------------------- ui/actions/lighthouse/lighthouse.ts | 4 ++- ui/app/(prowler)/lighthouse/chat.tsx | 28 +++++++++++++------- 5 files changed, 38 insertions(+), 52 deletions(-) diff --git a/api/src/backend/api/tests/test_views.py b/api/src/backend/api/tests/test_views.py index a7743f0560..f27152f3a4 100644 --- a/api/src/backend/api/tests/test_views.py +++ b/api/src/backend/api/tests/test_views.py @@ -5584,13 +5584,14 @@ class TestLighthouseConfigViewSet: assert "gpt-4o" in response.json()["data"]["available_models"] assert "gpt-4o-mini" in response.json()["data"]["available_models"] - def test_lighthouse_config_show_key( + def test_lighthouse_config_get_key( self, authenticated_client, lighthouse_config_fixture, valid_config_payload ): config_id = lighthouse_config_fixture.id expected_api_key = valid_config_payload["data"]["attributes"]["api_key"] response = authenticated_client.get( - reverse("lighthouseconfig-show-key", kwargs={"pk": config_id}) + reverse("lighthouseconfig-detail", kwargs={"pk": config_id}) + + "?fields[lighthouse-config]=api_key" ) assert response.status_code == status.HTTP_200_OK assert response.json()["data"]["attributes"]["api_key"] == expected_api_key diff --git a/api/src/backend/api/v1/serializers.py b/api/src/backend/api/v1/serializers.py index 7d3febf8a7..92eb82dbe7 100644 --- a/api/src/backend/api/v1/serializers.py +++ b/api/src/backend/api/v1/serializers.py @@ -2135,7 +2135,7 @@ class LighthouseConfigSerializer(RLSSerializer): Serializer for the LighthouseConfig model. """ - api_key = serializers.CharField(write_only=True, required=False) + api_key = serializers.CharField(required=False) class Meta: model = LighthouseConfig @@ -2159,10 +2159,18 @@ class LighthouseConfigSerializer(RLSSerializer): } def to_representation(self, instance): - ret = super().to_representation(instance) - # Add back the masked API key for display - ret["api_key"] = "*" * len(instance.api_key) if instance.api_key else None - return ret + data = super().to_representation(instance) + # Check if api_key is specifically requested in fields param + fields_param = self.context.get("request", None) and self.context[ + "request" + ].query_params.get("fields[lighthouse-config]", "") + if fields_param == "api_key": + # Return decrypted key if specifically requested + data["api_key"] = instance.api_key_decoded if instance.api_key else None + else: + # Return masked key for general requests + data["api_key"] = "*" * len(instance.api_key) if instance.api_key else None + return data class LighthouseConfigCreateSerializer(RLSSerializer, BaseWriteSerializer): diff --git a/api/src/backend/api/v1/views.py b/api/src/backend/api/v1/views.py index c6bc3d576a..6e7a9ccaf7 100644 --- a/api/src/backend/api/v1/views.py +++ b/api/src/backend/api/v1/views.py @@ -2848,38 +2848,3 @@ class LighthouseConfigViewSet(BaseRLSViewSet): status=status.HTTP_201_CREATED, headers=headers, ) - - @action(detail=True, methods=["get"], url_path="show_key") - def show_key(self, request, pk=None): - """ - Return the decrypted API key for the specified Lighthouse configuration. - """ - instance = self.get_object() - - if not instance.api_key: - return Response( - {"detail": "API key is missing."}, - status=status.HTTP_400_BAD_REQUEST, - ) - - try: - decrypted_key = instance.api_key_decoded - if decrypted_key is None: - return Response( - {"detail": "API key is invalid or missing."}, - status=status.HTTP_400_BAD_REQUEST, - ) - return Response( - data={ - "type": "lighthouse-config", - "attributes": {"api_key": decrypted_key}, - }, - status=status.HTTP_200_OK, - ) - except Exception as e: - return Response( - { - "detail": f"An unexpected error occurred while retrieving the API key. {str(e)}" - }, - status=status.HTTP_500_INTERNAL_SERVER_ERROR, - ) diff --git a/ui/actions/lighthouse/lighthouse.ts b/ui/actions/lighthouse/lighthouse.ts index 00ccaf182f..ca59fe9b77 100644 --- a/ui/actions/lighthouse/lighthouse.ts +++ b/ui/actions/lighthouse/lighthouse.ts @@ -34,7 +34,9 @@ export const getAIKey = async (): Promise => { return ""; } - const url = new URL(`${apiBaseUrl}/lighthouse-config/${configId}/show_key`); + const url = new URL( + `${apiBaseUrl}/lighthouse-config/${configId}?fields[lighthouse-config]=api_key`, + ); const response = await fetch(url.toString(), { method: "GET", headers, diff --git a/ui/app/(prowler)/lighthouse/chat.tsx b/ui/app/(prowler)/lighthouse/chat.tsx index 5912b738e1..201f49c038 100644 --- a/ui/app/(prowler)/lighthouse/chat.tsx +++ b/ui/app/(prowler)/lighthouse/chat.tsx @@ -1,7 +1,7 @@ "use client"; import { useChat } from "@ai-sdk/react"; -import { useRef, useEffect } from "react"; +import { useEffect, useRef } from "react"; import { MemoizedMarkdown } from "@/components/memoized-markdown"; @@ -60,11 +60,14 @@ export default function Chat() { const container = messagesContainerRef.current; const userMsg = latestUserMsgRef.current; const containerPadding = 16; // p-4 in Tailwind = 16px - container.scrollTop = userMsg.offsetTop - container.offsetTop - containerPadding; + container.scrollTop = + userMsg.offsetTop - container.offsetTop - containerPadding; } }, [messages]); - const handleAutoResizeInputChange = (e: React.ChangeEvent) => { + const handleAutoResizeInputChange = ( + e: React.ChangeEvent, + ) => { handleInputChange(e); const textarea = textareaRef.current; if (textarea) { @@ -104,13 +107,17 @@ export default function Chat() { ) : ( -
+
{messages.map((message, idx) => { const lastUserIdx = messages .map((m, i) => (m.role === "user" ? i : -1)) - .filter(i => i !== -1) + .filter((i) => i !== -1) .pop(); - const isLatestUserMsg = message.role === "user" && lastUserIdx === idx; + const isLatestUserMsg = + message.role === "user" && lastUserIdx === idx; return (
- +
@@ -156,7 +166,7 @@ export default function Chat() { onChange={handleAutoResizeInputChange} placeholder="Type your message..." rows={1} - className="w-full flex-1 px-3 py-2 focus:outline-none resize-none overflow-hidden rounded-lg border bg-background" + className="w-full flex-1 resize-none overflow-hidden rounded-lg border bg-background px-3 py-2 focus:outline-none" style={{ minHeight: "40px", maxHeight: "160px" }} onKeyDown={(e) => { if ((e.metaKey || e.ctrlKey) && e.key === "Enter") { @@ -168,7 +178,7 @@ export default function Chat() {