diff --git a/src/app.ts b/src/app.ts index a985d60..cd4ac56 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1688,6 +1688,19 @@ export function createApp() { return { keys: json.data ?? [] } }) + .get('/api/admin/api-keys/:id', async ({ request, set, params }) => { + const auth = await requireDeveloper(request, set) + if (!auth) return { error: set.status === 401 ? 'Unauthorized' : 'Forbidden' } + const app = await prisma.app.findUnique({ where: { id: 'desa-plus' } }) + if (!app?.urlApi) { set.status = 503; return { error: 'desa-plus belum dikonfigurasi' } } + const res = await fetch(`${app.urlApi.replace(/\/$/, '')}/api/monitoring/api-keys/${params.id}`, { + headers: { 'x-api-key': app.apiKey ?? '' }, + }) + const json = await res.json() + set.status = res.status + return json + }) + .post('/api/admin/api-keys', async ({ request, set }) => { const auth = await requireDeveloper(request, set) if (!auth) return { error: set.status === 401 ? 'Unauthorized' : 'Forbidden' } diff --git a/src/frontend/routes/dev.tsx b/src/frontend/routes/dev.tsx index a1b0936..d5611c2 100644 --- a/src/frontend/routes/dev.tsx +++ b/src/frontend/routes/dev.tsx @@ -55,6 +55,7 @@ import { TbApps, TbBug, TbChevronRight, + TbCheck, TbCopy, TbCircleFilled, TbCode, @@ -1833,15 +1834,23 @@ function ApiKeysPanel() { const [createdKey, setCreatedKey] = useState(null) const [keyCopied, setKeyCopied] = useState(false) const [revealedOpened, { open: openRevealed, close: closeRevealed }] = useDisclosure(false) - const [visibleKeys, setVisibleKeys] = useState>(new Set()) + const [copyingId, setCopyingId] = useState(null) + const [copiedId, setCopiedId] = useState(null) - const toggleKeyVisibility = (keyId: string) => { - setVisibleKeys((prev) => { - const next = new Set(prev) - if (next.has(keyId)) next.delete(keyId) - else next.add(keyId) - return next - }) + const copyFullKey = async (id: string) => { + setCopyingId(id) + try { + const res = await fetch(`/api/admin/api-keys/${id}`, { credentials: 'include' }) + const json = await res.json() + const fullKey = json.data?.key + if (fullKey) { + await navigator.clipboard.writeText(fullKey) + setCopiedId(id) + setTimeout(() => setCopiedId(null), 2000) + } + } finally { + setCopyingId(null) + } } const { data, isLoading } = useQuery({ @@ -1947,28 +1956,20 @@ function ApiKeysPanel() { {k.name} - - {visibleKeys.has(k.id) ? k.key : '•'.repeat(32)} + + {k.key} - + toggleKeyVisibility(k.id)} + color={copiedId === k.id ? 'green' : 'gray'} + loading={copyingId === k.id} + onClick={() => copyFullKey(k.id)} > - {visibleKeys.has(k.id) ? : } + {copiedId === k.id ? : } - - {({ copy }) => ( - - - - - - )} -