mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-13 23:11:40 +00:00
fix: key-detail not-found state, bound SPA fallback probe, drop stale deprecation
Addresses Greptile review: KeyDetailPage now renders an explicit 'Key not found' page (with a back button) when the id in the URL resolves to no key, instead of leaning on KeyInfoView's internal fallback. SPAStaticFiles._spa_shell now resolves each candidate shell and rejects anything outside the static directory before probing it with os.path.isfile, so a '..'-bearing URL can't make the existence check escape the served directory. The @deprecated notice on templates/key_info_view.tsx is removed: it pointed at a successor file that does not exist and the component is the sole implementation used across the dashboard
This commit is contained in:
parent
115694dc0e
commit
b3b2ec5d58
3 changed files with 26 additions and 20 deletions
|
|
@ -620,6 +620,13 @@ class SPAStaticFiles(StaticFiles):
|
|||
last_segment = path.rstrip("/").rsplit("/", 1)[-1]
|
||||
return "." not in last_segment
|
||||
|
||||
def _bounded_shell(self, relative: str) -> Optional[str]:
|
||||
base = os.path.realpath(str(self.directory))
|
||||
candidate = os.path.realpath(os.path.join(base, relative))
|
||||
if candidate != base and not candidate.startswith(base + os.sep):
|
||||
return None
|
||||
return relative if os.path.isfile(candidate) else None
|
||||
|
||||
def _spa_shell(self, path: str) -> Optional[str]:
|
||||
trimmed = path.strip("/")
|
||||
segments = trimmed.split("/") if trimmed else []
|
||||
|
|
@ -630,11 +637,10 @@ class SPAStaticFiles(StaticFiles):
|
|||
if parent
|
||||
else f"{_SPA_SHELL_PLACEHOLDER_SEGMENT}/index.html"
|
||||
)
|
||||
if os.path.isfile(os.path.join(str(self.directory), placeholder)):
|
||||
return placeholder
|
||||
if os.path.isfile(os.path.join(str(self.directory), "index.html")):
|
||||
return "index.html"
|
||||
return None
|
||||
shell = self._bounded_shell(placeholder)
|
||||
if shell is not None:
|
||||
return shell
|
||||
return self._bounded_shell("index.html")
|
||||
|
||||
async def _try_original(self, path: str, scope: StarletteScope) -> Optional[StarletteResponse]:
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
|||
import LoadingScreen from "@/components/common_components/LoadingScreen";
|
||||
import KeyInfoView from "@/components/templates/key_info_view";
|
||||
import { migratedHref } from "@/utils/migratedPages";
|
||||
import { ArrowLeftOutlined } from "@ant-design/icons";
|
||||
import { Button } from "antd";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
|
||||
|
|
@ -22,19 +24,24 @@ export default function KeyDetailPage() {
|
|||
const { data: keyData, isPending } = useKeyInfo(keyId);
|
||||
const { data: teams } = useAllTeams();
|
||||
|
||||
const backToKeys = () => router.push(migratedHref("api-keys"));
|
||||
|
||||
if (authLoading || !isAuthorized) {
|
||||
return <LoadingScreen />;
|
||||
}
|
||||
if (!keyId || isPending) {
|
||||
return <LoadingScreen />;
|
||||
}
|
||||
if (!keyData) {
|
||||
return (
|
||||
<div className="p-4">
|
||||
<Button type="text" icon={<ArrowLeftOutlined />} onClick={backToKeys} className="mb-4">
|
||||
Back to Keys
|
||||
</Button>
|
||||
<p className="text-sm text-gray-700">Key not found</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<KeyInfoView
|
||||
keyId={keyId}
|
||||
keyData={keyData ?? undefined}
|
||||
teams={teams ?? []}
|
||||
onClose={() => router.push(migratedHref("api-keys"))}
|
||||
/>
|
||||
);
|
||||
return <KeyInfoView keyId={keyId} keyData={keyData} teams={teams ?? []} onClose={backToKeys} />;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,13 +50,6 @@ const PREMIUM_METADATA_FIELDS = ["policies", "guardrails", "prompts", "tags", "a
|
|||
const isEmptyValue = (v: unknown): boolean =>
|
||||
v == null || (Array.isArray(v) && v.length === 0) || (typeof v === "string" && v.trim() === "");
|
||||
|
||||
/**
|
||||
* ─────────────────────────────────────────────────────────────────────────
|
||||
* @deprecated
|
||||
* This component is being DEPRECATED in favor of src/app/(dashboard)/virtual-keys/components/KeyInfoView.tsx
|
||||
* Please contribute to the new refactor.
|
||||
* ─────────────────────────────────────────────────────────────────────────
|
||||
*/
|
||||
export default function KeyInfoView({
|
||||
onClose,
|
||||
keyData,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue