MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / ApiKeysPage

Function ApiKeysPage

packages/react/src/pages/api-keys.tsx:225–338  ·  view source on GitHub ↗
(props: { readonly orgKeysSection?: ReactNode })

Source from the content-addressed store, hash-verified

223}
224
225export function ApiKeysPage(props: { readonly orgKeysSection?: ReactNode }) {
226 useExecutorDocumentTitle("API keys");
227 const result = useAtomValue(apiKeysAtom);
228 const refreshApiKeys = useAtomRefresh(apiKeysAtom);
229 const doCreate = useAtomSet(createApiKey, { mode: "promiseExit" });
230 const doRevoke = useAtomSet(revokeApiKey, { mode: "promiseExit" });
231 const [createOpen, setCreateOpen] = useState(false);
232 // Bumped per open so the dialog body remounts with fresh state; the shell
233 // stays mounted for Radix's exit animation (see CreateKeyDialogBody).
234 const [openCount, setOpenCount] = useState(0);
235 const [revokingId, setRevokingId] = useState<string | null>(null);
236
237 const handleCreate = async (name: string): Promise<CreatedKey | null> => {
238 const exit = await doCreate({ payload: { name }, reactivityKeys: apiKeyWriteKeys });
239 trackEvent("api_key_created", { success: Exit.isSuccess(exit) });
240 if (Exit.isSuccess(exit)) {
241 toast.success("API key created");
242 return exit.value;
243 }
244 toast.error("Failed to create API key");
245 return null;
246 };
247
248 const handleRevoke = async (key: ApiKeySummary) => {
249 setRevokingId(key.id);
250 const exit = await doRevoke({ params: { apiKeyId: key.id }, reactivityKeys: apiKeyWriteKeys });
251 setRevokingId(null);
252 trackEvent("api_key_revoked", { success: Exit.isSuccess(exit) });
253 if (Exit.isSuccess(exit)) {
254 toast.success(`Revoked ${key.name}`);
255 return;
256 }
257 toast.error("Failed to revoke API key");
258 };
259
260 return (
261 <PageContainer>
262 <PageHeader
263 title="API keys"
264 description="Keys for accessing the Executor API and MCP endpoint from scripts and tools."
265 actions={
266 <Button
267 onClick={() => {
268 setOpenCount((count) => count + 1);
269 setCreateOpen(true);
270 }}
271 >
272 <span aria-hidden="true">+</span>
273 New key
274 </Button>
275 }
276 >
277 <div className="mt-4 flex max-w-2xl items-center gap-2 rounded-md border border-border bg-card px-3 py-2">
278 <code className="min-w-0 flex-1 truncate font-mono text-xs text-foreground">
279 Authorization: Bearer &lt;api-key&gt;
280 </code>
281 <CopyButton value="Authorization: Bearer <api-key>" />
282 </div>

Callers

nothing calls this directly

Calls 4

useExecutorDocumentTitleFunction · 0.90
isAsyncResultLoadingFunction · 0.90
trackEventFunction · 0.90
defaultKeyNameFunction · 0.85

Tested by

no test coverage detected