Remove show_key endpoint

This commit is contained in:
Chandrapal Badshah
2025-05-06 17:05:30 +05:30
parent 5d560d7834
commit c0622f660b
5 changed files with 38 additions and 52 deletions
+3 -2
View File
@@ -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
+13 -5
View File
@@ -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):
-35
View File
@@ -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,
)
+3 -1
View File
@@ -34,7 +34,9 @@ export const getAIKey = async (): Promise<string> => {
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,
+19 -9
View File
@@ -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<HTMLTextAreaElement>) => {
const handleAutoResizeInputChange = (
e: React.ChangeEvent<HTMLTextAreaElement>,
) => {
handleInputChange(e);
const textarea = textareaRef.current;
if (textarea) {
@@ -104,13 +107,17 @@ export default function Chat() {
</div>
</div>
) : (
<div className="flex-1 space-y-4 overflow-y-auto p-4" ref={messagesContainerRef}>
<div
className="flex-1 space-y-4 overflow-y-auto p-4"
ref={messagesContainerRef}
>
{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 (
<div
key={message.id}
@@ -129,7 +136,10 @@ export default function Chat() {
<div
className={`prose dark:prose-invert ${message.role === "user" ? "dark:!text-black" : ""}`}
>
<MemoizedMarkdown id={message.id} content={message.content} />
<MemoizedMarkdown
id={message.id}
content={message.content}
/>
</div>
</div>
</div>
@@ -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() {
<button
type="submit"
disabled={status === "submitted" || !input.trim()}
className="rounded-lg bg-primary p-2 text-primary-foreground hover:bg-primary/90 disabled:opacity-50 flex-shrink-0 h-10 w-10 flex items-center justify-center"
className="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-primary p-2 text-primary-foreground hover:bg-primary/90 disabled:opacity-50"
>
{status === "submitted" ? <span></span> : <span></span>}
</button>