fix(resource/api-keys): 编辑后复制当前凭证并清空旧显示状态
This commit is contained in:
parent
47ff656083
commit
6d512fb0ad
21
src/components/dashboard/ApiKeysPanel.test.ts
Normal file
21
src/components/dashboard/ApiKeysPanel.test.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { copyCurrentApiKey } from "./ApiKeysPanel";
|
||||
|
||||
describe("copyCurrentApiKey", () => {
|
||||
it("reads the current credential instead of reusing a previously revealed value", async () => {
|
||||
let current = "synthetic-old-key";
|
||||
let copied = "";
|
||||
const reveal = async (id: string) => {
|
||||
expect(id).toBe("k1");
|
||||
return current;
|
||||
};
|
||||
const write = async (value: string) => { copied = value; };
|
||||
|
||||
await copyCurrentApiKey("k1", reveal, write);
|
||||
expect(copied).toBe("synthetic-old-key");
|
||||
|
||||
current = "synthetic-new-key";
|
||||
await copyCurrentApiKey("k1", reveal, write);
|
||||
expect(copied).toBe("synthetic-new-key");
|
||||
});
|
||||
});
|
||||
@ -18,6 +18,14 @@ const PROVIDERS = [
|
||||
{ value: "custom", label: "自定义", color: "bg-gray-100 text-gray-600 border-gray-200" },
|
||||
];
|
||||
|
||||
export async function copyCurrentApiKey(
|
||||
id: string,
|
||||
reveal: (id: string) => Promise<string>,
|
||||
write: (value: string) => Promise<void>,
|
||||
): Promise<void> {
|
||||
await write(await reveal(id));
|
||||
}
|
||||
|
||||
function getProviderStyle(provider: string) {
|
||||
return PROVIDERS.find((p) => p.value === provider)?.color ?? PROVIDERS[PROVIDERS.length - 1].color;
|
||||
}
|
||||
@ -144,7 +152,7 @@ function ApiKeyCard({ item, onEdit, onDelete }: {
|
||||
};
|
||||
const copy = async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(secret ?? await revealApiKey(item.id));
|
||||
await copyCurrentApiKey(item.id, revealApiKey, (value) => navigator.clipboard.writeText(value));
|
||||
setError(undefined);
|
||||
} catch (cause) {
|
||||
setError(String(cause));
|
||||
@ -249,6 +257,7 @@ export function ApiKeysPanel() {
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const [editingItem, setEditingItem] = useState<(ApiKey & { api_key: string }) | null>(null);
|
||||
const [editError, setEditError] = useState<string>();
|
||||
const [keyRevision, setKeyRevision] = useState(0);
|
||||
|
||||
const { data: keys = [] } = useQuery({
|
||||
queryKey: ["api-keys"],
|
||||
@ -262,7 +271,7 @@ export function ApiKeysPanel() {
|
||||
|
||||
const editMut = useMutation({
|
||||
mutationFn: ({ id, input }: { id: string; input: SaveApiKeyInput }) => editApiKey(id, input),
|
||||
onSuccess: () => { qc.invalidateQueries({ queryKey: ["api-keys"] }); setEditingItem(null); },
|
||||
onSuccess: () => { setKeyRevision((revision) => revision + 1); qc.invalidateQueries({ queryKey: ["api-keys"] }); setEditingItem(null); },
|
||||
});
|
||||
|
||||
const deleteMut = useMutation({
|
||||
@ -299,7 +308,7 @@ export function ApiKeysPanel() {
|
||||
|
||||
{keys.map((k) => (
|
||||
<ApiKeyCard
|
||||
key={k.id}
|
||||
key={`${k.id}:${keyRevision}`}
|
||||
item={k}
|
||||
onEdit={() => { void (async () => {
|
||||
try {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user