@kuadrant/kuadrant-backstage-plugin-frontend 0.0.2-dev-b3bc94f → 0.0.2-dev-b393fa5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/components/ApiAccessCard/ApiAccessCard.esm.js +9 -1
  2. package/dist/components/ApiAccessCard/ApiAccessCard.esm.js.map +1 -1
  3. package/dist/components/ApiKeyDetailPage/ApiKeyDetailPage.esm.js +2 -1
  4. package/dist/components/ApiKeyDetailPage/ApiKeyDetailPage.esm.js.map +1 -1
  5. package/dist/components/ApiKeyManagementTab/ApiKeyManagementTab.esm.js +7 -3
  6. package/dist/components/ApiKeyManagementTab/ApiKeyManagementTab.esm.js.map +1 -1
  7. package/dist/components/ApiProductDetailPage/ApiProductDetailPage.esm.js +15 -5
  8. package/dist/components/ApiProductDetailPage/ApiProductDetailPage.esm.js.map +1 -1
  9. package/dist/components/ApprovalQueueTable/ApprovalQueueTable.esm.js +9 -4
  10. package/dist/components/ApprovalQueueTable/ApprovalQueueTable.esm.js.map +1 -1
  11. package/dist/components/EditAPIKeyDialog/EditAPIKeyDialog.esm.js +3 -4
  12. package/dist/components/EditAPIKeyDialog/EditAPIKeyDialog.esm.js.map +1 -1
  13. package/dist/components/EntityApiApprovalTab/EntityApiApprovalTab.esm.js +7 -3
  14. package/dist/components/EntityApiApprovalTab/EntityApiApprovalTab.esm.js.map +1 -1
  15. package/dist/components/KuadrantPage/{KuadrantPage.esm.js → ApiProductsPage.esm.js} +32 -22
  16. package/dist/components/KuadrantPage/ApiProductsPage.esm.js.map +1 -0
  17. package/dist/components/KuadrantPage/index.esm.js +1 -1
  18. package/dist/components/MyApiKeysTable/MyApiKeysTable.esm.js +11 -2
  19. package/dist/components/MyApiKeysTable/MyApiKeysTable.esm.js.map +1 -1
  20. package/dist/components/RequestAccessDialog/RequestAccessDialog.esm.js +3 -4
  21. package/dist/components/RequestAccessDialog/RequestAccessDialog.esm.js.map +1 -1
  22. package/dist/plugin.esm.js +1 -1
  23. package/dist/plugin.esm.js.map +1 -1
  24. package/dist-scalprum/{internal.plugin-kuadrant.e195d879e62f0e73cc2f.js → internal.plugin-kuadrant.09545fa30927eb9a66fd.js} +2 -2
  25. package/dist-scalprum/{internal.plugin-kuadrant.e195d879e62f0e73cc2f.js.map → internal.plugin-kuadrant.09545fa30927eb9a66fd.js.map} +1 -1
  26. package/dist-scalprum/plugin-manifest.json +2 -2
  27. package/dist-scalprum/static/2821.972ae33b.chunk.js +2 -0
  28. package/dist-scalprum/static/2821.972ae33b.chunk.js.map +1 -0
  29. package/dist-scalprum/static/{2967.6a1db3ad.chunk.js → 2967.65c51af8.chunk.js} +2 -2
  30. package/dist-scalprum/static/2967.65c51af8.chunk.js.map +1 -0
  31. package/dist-scalprum/static/3650.ee76eba9.chunk.js +2 -0
  32. package/dist-scalprum/static/3650.ee76eba9.chunk.js.map +1 -0
  33. package/dist-scalprum/static/4682.51e5be13.chunk.js +2 -0
  34. package/dist-scalprum/static/4682.51e5be13.chunk.js.map +1 -0
  35. package/dist-scalprum/static/5203.b654e8e0.chunk.js +2 -0
  36. package/dist-scalprum/static/5203.b654e8e0.chunk.js.map +1 -0
  37. package/dist-scalprum/static/6800.20f46859.chunk.js +2 -0
  38. package/dist-scalprum/static/6800.20f46859.chunk.js.map +1 -0
  39. package/dist-scalprum/static/6840.1653e6b0.chunk.js +2 -0
  40. package/dist-scalprum/static/6840.1653e6b0.chunk.js.map +1 -0
  41. package/dist-scalprum/static/7791.ac1ac509.chunk.js +2 -0
  42. package/dist-scalprum/static/7791.ac1ac509.chunk.js.map +1 -0
  43. package/dist-scalprum/static/exposed-PluginRoot.55777e36.chunk.js +2 -0
  44. package/dist-scalprum/static/exposed-PluginRoot.55777e36.chunk.js.map +1 -0
  45. package/package.json +1 -1
  46. package/dist/components/KuadrantPage/KuadrantPage.esm.js.map +0 -1
  47. package/dist-scalprum/static/2967.6a1db3ad.chunk.js.map +0 -1
  48. package/dist-scalprum/static/3459.ac9b9e54.chunk.js +0 -2
  49. package/dist-scalprum/static/3459.ac9b9e54.chunk.js.map +0 -1
  50. package/dist-scalprum/static/3650.4f0dc550.chunk.js +0 -2
  51. package/dist-scalprum/static/3650.4f0dc550.chunk.js.map +0 -1
  52. package/dist-scalprum/static/4682.bd2dfccd.chunk.js +0 -2
  53. package/dist-scalprum/static/4682.bd2dfccd.chunk.js.map +0 -1
  54. package/dist-scalprum/static/5203.539ed3ec.chunk.js +0 -2
  55. package/dist-scalprum/static/5203.539ed3ec.chunk.js.map +0 -1
  56. package/dist-scalprum/static/6800.6e2a08fe.chunk.js +0 -2
  57. package/dist-scalprum/static/6800.6e2a08fe.chunk.js.map +0 -1
  58. package/dist-scalprum/static/6840.3bd67cf4.chunk.js +0 -2
  59. package/dist-scalprum/static/6840.3bd67cf4.chunk.js.map +0 -1
  60. package/dist-scalprum/static/7791.8135d440.chunk.js +0 -2
  61. package/dist-scalprum/static/7791.8135d440.chunk.js.map +0 -1
  62. package/dist-scalprum/static/exposed-PluginRoot.c3fd0cc1.chunk.js +0 -2
  63. package/dist-scalprum/static/exposed-PluginRoot.c3fd0cc1.chunk.js.map +0 -1
@@ -12,6 +12,7 @@ import { useEntity } from '@backstage/plugin-catalog-react';
12
12
  import { RequestAccessDialog } from '../RequestAccessDialog/RequestAccessDialog.esm.js';
13
13
  import { useKuadrantPermission } from '../../utils/permissions.esm.js';
14
14
  import { kuadrantApiKeyCreatePermission } from '../../permissions.esm.js';
15
+ import { handleFetchError } from '../../utils/errors.esm.js';
15
16
 
16
17
  const ApiAccessCard = ({ namespace: propNamespace }) => {
17
18
  const { entity } = useEntity();
@@ -39,7 +40,8 @@ const ApiAccessCard = ({ namespace: propNamespace }) => {
39
40
  const url = `${backendUrl}/api/kuadrant/requests/my?namespace=${namespace}` ;
40
41
  const response = await fetchApi.fetch(url);
41
42
  if (!response.ok) {
42
- throw new Error("failed to fetch api key requests");
43
+ const error = await handleFetchError(response);
44
+ throw new Error(`failed to fetch api key requests ${error}`);
43
45
  }
44
46
  const data = await response.json();
45
47
  const allRequests = data.items || [];
@@ -86,6 +88,12 @@ const ApiAccessCard = ({ namespace: propNamespace }) => {
86
88
  }
87
89
  } catch (err) {
88
90
  console.error("failed to fetch api key:", err);
91
+ const errorMessage = err instanceof Error ? err.message : "unknown error occurred";
92
+ alertApi.post({
93
+ message: `Failed to fetch APIKey. ${errorMessage}`,
94
+ severity: "error",
95
+ display: "transient"
96
+ });
89
97
  } finally {
90
98
  setApiKeyLoading((prev) => {
91
99
  const next = new Set(prev);
@@ -1 +1 @@
1
- {"version":3,"file":"ApiAccessCard.esm.js","sources":["../../../src/components/ApiAccessCard/ApiAccessCard.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { useAsync } from 'react-use';\nimport {\n InfoCard,\n Progress,\n ResponseErrorPanel,\n} from '@backstage/core-components';\nimport {\n Typography,\n Box,\n Chip,\n Button,\n IconButton,\n Tooltip,\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n} from '@material-ui/core';\nimport AddIcon from '@material-ui/icons/Add';\nimport VisibilityIcon from '@material-ui/icons/Visibility';\nimport VisibilityOffIcon from '@material-ui/icons/VisibilityOff';\nimport FileCopyIcon from '@material-ui/icons/FileCopy';\nimport WarningIcon from '@material-ui/icons/Warning';\nimport { useApi, configApiRef, identityApiRef, fetchApiRef, alertApiRef } from '@backstage/core-plugin-api';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { RequestAccessDialog, Plan } from '../RequestAccessDialog';\nimport { useKuadrantPermission } from '../../utils/permissions';\nimport { kuadrantApiKeyCreatePermission } from '../../permissions';\n\ninterface APIKey {\n metadata: {\n name: string;\n namespace: string;\n };\n spec: {\n apiProductRef: {\n name: string;\n };\n planTier: string;\n };\n status?: {\n phase: 'Pending' | 'Approved' | 'Rejected';\n secretRef?: {\n name: string;\n key: string;\n };\n canReadSecret?: boolean;\n };\n}\n\ninterface APIProduct {\n metadata: {\n name: string;\n namespace: string;\n };\n status?: {\n discoveredPlans?: Plan[];\n };\n}\n\nexport interface ApiAccessCardProps {\n // deprecated: use entity annotations instead\n namespace?: string;\n}\n\nexport const ApiAccessCard = ({ namespace: propNamespace }: ApiAccessCardProps) => {\n const { entity } = useEntity();\n const config = useApi(configApiRef);\n const identityApi = useApi(identityApiRef);\n const fetchApi = useApi(fetchApiRef);\n const alertApi = useApi(alertApiRef);\n const backendUrl = config.getString('backend.baseUrl');\n const [userEmail, setUserEmail] = useState<string>('');\n const [requestDialogOpen, setRequestDialogOpen] = useState(false);\n const [refresh, setRefresh] = useState(0);\n\n // key reveal state\n const [visibleKeys, setVisibleKeys] = useState<Set<string>>(new Set());\n const [apiKeyValues, setApiKeyValues] = useState<Map<string, string>>(new Map());\n const [apiKeyLoading, setApiKeyLoading] = useState<Set<string>>(new Set());\n const [alreadyReadKeys, setAlreadyReadKeys] = useState<Set<string>>(new Set());\n const [showOnceWarningOpen, setShowOnceWarningOpen] = useState(false);\n const [pendingKeyReveal, setPendingKeyReveal] = useState<{\n namespace: string;\n name: string;\n } | null>(null);\n\n // get apiproduct name from entity annotation (set by entity provider)\n const apiProductName = entity.metadata.annotations?.['kuadrant.io/apiproduct'] || entity.metadata.name;\n const namespace = entity.metadata.annotations?.['kuadrant.io/namespace'] || propNamespace || 'default';\n\n // get current user identity\n useAsync(async () => {\n const profile = await identityApi.getProfileInfo();\n setUserEmail(profile.email || '');\n }, [identityApi]);\n\n // fetch user's approved keys\n const { value: requests, loading: keysLoading, error: keysError } = useAsync(async () => {\n const url = namespace\n ? `${backendUrl}/api/kuadrant/requests/my?namespace=${namespace}`\n : `${backendUrl}/api/kuadrant/requests/my`;\n const response = await fetchApi.fetch(url);\n if (!response.ok) {\n throw new Error('failed to fetch api key requests');\n }\n const data = await response.json();\n const allRequests = data.items || [];\n return allRequests.filter((r: APIKey) =>\n r.spec.apiProductRef?.name === apiProductName && r.status?.phase === 'Approved'\n );\n }, [namespace, apiProductName, backendUrl, fetchApi, refresh]);\n\n // fetch apiproduct to get available plans\n const { value: apiProduct, loading: productLoading } = useAsync(async () => {\n const response = await fetchApi.fetch(`${backendUrl}/api/kuadrant/apiproducts`);\n if (!response.ok) {\n return null;\n }\n const data = await response.json();\n return data.items?.find(\n (p: APIProduct) =>\n p.metadata.namespace === namespace &&\n p.metadata.name === apiProductName,\n );\n }, [namespace, apiProductName, fetchApi, backendUrl]);\n\n const resourceRef = apiProduct\n ? `apiproduct:${apiProduct.metadata.namespace}/${apiProduct.metadata.name}`\n : undefined;\n\n const { allowed: canCreateRequest, loading: permissionLoading } = useKuadrantPermission(\n kuadrantApiKeyCreatePermission,\n resourceRef,\n );\n\n const fetchApiKeyFromSecret = async (requestNamespace: string, requestName: string) => {\n const key = `${requestNamespace}/${requestName}`;\n if (apiKeyLoading.has(key)) {\n return;\n }\n\n setApiKeyLoading((prev) => new Set(prev).add(key));\n try {\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/apikeys/${requestNamespace}/${requestName}/secret`,\n );\n if (response.ok) {\n const data = await response.json();\n setApiKeyValues((prev) => new Map(prev).set(key, data.apiKey));\n setAlreadyReadKeys((prev) => new Set(prev).add(key));\n } else if (response.status === 403) {\n setAlreadyReadKeys((prev) => new Set(prev).add(key));\n alertApi.post({\n message: 'This API key has already been viewed and cannot be retrieved again.',\n severity: 'warning',\n display: 'transient',\n });\n }\n } catch (err) {\n console.error('failed to fetch api key:', err);\n } finally {\n setApiKeyLoading((prev) => {\n const next = new Set(prev);\n next.delete(key);\n return next;\n });\n }\n };\n\n const clearApiKeyValue = (requestNamespace: string, requestName: string) => {\n const key = `${requestNamespace}/${requestName}`;\n setApiKeyValues((prev) => {\n const next = new Map(prev);\n next.delete(key);\n return next;\n });\n };\n\n const toggleVisibility = (keyName: string) => {\n setVisibleKeys((prev) => {\n const newSet = new Set(prev);\n if (newSet.has(keyName)) {\n newSet.delete(keyName);\n } else {\n newSet.add(keyName);\n }\n return newSet;\n });\n };\n\n const loading = keysLoading || productLoading || permissionLoading;\n\n if (loading) {\n return <Progress />;\n }\n\n if (keysError) {\n return <ResponseErrorPanel error={keysError} />;\n }\n\n const keys = (requests as APIKey[]) || [];\n const plans = (apiProduct?.status?.discoveredPlans || []) as Plan[];\n const canRequest = canCreateRequest && plans.length > 0;\n\n const renderKeyRow = (request: APIKey) => {\n const key = `${request.metadata.namespace}/${request.metadata.name}`;\n const isVisible = visibleKeys.has(request.metadata.name);\n const isLoading = apiKeyLoading.has(key);\n const apiKeyValue = apiKeyValues.get(key);\n const hasSecretRef = request.status?.secretRef?.name;\n const canReadSecret = request.status?.canReadSecret !== false;\n const isAlreadyRead = alreadyReadKeys.has(key) || !canReadSecret;\n\n const handleRevealClick = () => {\n if (isVisible) {\n clearApiKeyValue(request.metadata.namespace, request.metadata.name);\n toggleVisibility(request.metadata.name);\n } else if (!isAlreadyRead) {\n setPendingKeyReveal({\n namespace: request.metadata.namespace,\n name: request.metadata.name,\n });\n setShowOnceWarningOpen(true);\n }\n };\n\n const handleCopy = async () => {\n if (apiKeyValue) {\n await navigator.clipboard.writeText(apiKeyValue);\n alertApi.post({\n message: 'API key copied to clipboard',\n severity: 'success',\n display: 'transient',\n });\n }\n };\n\n return (\n <Box\n key={request.metadata.name}\n mb={1}\n p={1.5}\n border={1}\n borderColor=\"grey.300\"\n borderRadius={4}\n >\n <Box display=\"flex\" justifyContent=\"space-between\" alignItems=\"center\" mb={1}>\n <Typography variant=\"body2\" style={{ fontWeight: 500 }}>\n {request.metadata.name}\n </Typography>\n <Chip label={request.spec.planTier} color=\"primary\" size=\"small\" />\n </Box>\n {hasSecretRef && (\n <Box display=\"flex\" alignItems=\"center\">\n <Typography\n variant=\"body2\"\n style={{\n fontFamily: 'monospace',\n fontSize: '0.8rem',\n flex: 1,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}\n >\n {isLoading\n ? 'Loading...'\n : isVisible && apiKeyValue\n ? apiKeyValue\n : isAlreadyRead && !apiKeyValue\n ? 'Already viewed'\n : '••••••••••••••••'}\n </Typography>\n {isVisible && apiKeyValue && (\n <Tooltip title=\"Copy to clipboard\">\n <IconButton size=\"small\" onClick={handleCopy}>\n <FileCopyIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n )}\n <Tooltip\n title={\n isAlreadyRead && !apiKeyValue\n ? 'Key already viewed'\n : isVisible\n ? 'Hide API key'\n : 'Reveal API key (one-time only)'\n }\n >\n <span>\n <IconButton\n size=\"small\"\n onClick={handleRevealClick}\n disabled={isLoading || (isAlreadyRead && !apiKeyValue)}\n >\n {isVisible ? <VisibilityOffIcon fontSize=\"small\" /> : <VisibilityIcon fontSize=\"small\" />}\n </IconButton>\n </span>\n </Tooltip>\n </Box>\n )}\n </Box>\n );\n };\n\n return (\n <>\n <InfoCard title=\"Kuadrant API Keys\">\n <Box p={2}>\n {keys.length > 0 ? (\n <>\n <Typography variant=\"body2\" color=\"textSecondary\" gutterBottom>\n {keys.length} active key{keys.length !== 1 ? 's' : ''}\n </Typography>\n {keys.map(renderKeyRow)}\n </>\n ) : (\n <Typography variant=\"body1\" gutterBottom>\n You don't have any API keys for this API yet\n </Typography>\n )}\n <Box mt={2}>\n {canRequest ? (\n <Button\n variant=\"contained\"\n color=\"primary\"\n size=\"small\"\n startIcon={<AddIcon />}\n onClick={() => setRequestDialogOpen(true)}\n >\n Request API Access\n </Button>\n ) : (\n <Typography variant=\"caption\" color=\"textSecondary\">\n Visit the API Keys tab to view and manage access\n </Typography>\n )}\n </Box>\n </Box>\n </InfoCard>\n\n <RequestAccessDialog\n open={requestDialogOpen}\n onClose={() => setRequestDialogOpen(false)}\n onSuccess={() => {\n setRequestDialogOpen(false);\n setRefresh((r) => r + 1);\n }}\n apiProductName={apiProductName}\n namespace={namespace}\n userEmail={userEmail}\n plans={plans}\n />\n\n <Dialog\n open={showOnceWarningOpen}\n onClose={() => {\n setShowOnceWarningOpen(false);\n setPendingKeyReveal(null);\n }}\n maxWidth=\"sm\"\n >\n <DialogTitle>\n <Box display=\"flex\" alignItems=\"center\">\n <WarningIcon color=\"primary\" style={{ marginRight: 8 }} />\n View API Key\n </Box>\n </DialogTitle>\n <DialogContent>\n <Typography variant=\"body1\" paragraph>\n This API key can only be viewed <strong>once</strong>. After you\n reveal it, you will not be able to retrieve it again.\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Make sure to copy and store it securely before closing this view.\n </Typography>\n </DialogContent>\n <DialogActions>\n <Button\n onClick={() => {\n setShowOnceWarningOpen(false);\n setPendingKeyReveal(null);\n }}\n >\n Cancel\n </Button>\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={() => {\n if (pendingKeyReveal) {\n fetchApiKeyFromSecret(\n pendingKeyReveal.namespace,\n pendingKeyReveal.name,\n );\n toggleVisibility(pendingKeyReveal.name);\n }\n setShowOnceWarningOpen(false);\n setPendingKeyReveal(null);\n }}\n >\n Reveal API Key\n </Button>\n </DialogActions>\n </Dialog>\n </>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;AAkEO,MAAM,aAAgB,GAAA,CAAC,EAAE,SAAA,EAAW,eAAwC,KAAA;AACjF,EAAM,MAAA,EAAE,MAAO,EAAA,GAAI,SAAU,EAAA;AAC7B,EAAM,MAAA,MAAA,GAAS,OAAO,YAAY,CAAA;AAClC,EAAM,MAAA,WAAA,GAAc,OAAO,cAAc,CAAA;AACzC,EAAM,MAAA,QAAA,GAAW,OAAO,WAAW,CAAA;AACnC,EAAM,MAAA,QAAA,GAAW,OAAO,WAAW,CAAA;AACnC,EAAM,MAAA,UAAA,GAAa,MAAO,CAAA,SAAA,CAAU,iBAAiB,CAAA;AACrD,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAiB,EAAE,CAAA;AACrD,EAAA,MAAM,CAAC,iBAAA,EAAmB,oBAAoB,CAAA,GAAI,SAAS,KAAK,CAAA;AAChE,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,CAAC,CAAA;AAGxC,EAAA,MAAM,CAAC,WAAa,EAAA,cAAc,IAAI,QAAsB,iBAAA,IAAI,KAAK,CAAA;AACrE,EAAA,MAAM,CAAC,YAAc,EAAA,eAAe,IAAI,QAA8B,iBAAA,IAAI,KAAK,CAAA;AAC/E,EAAA,MAAM,CAAC,aAAe,EAAA,gBAAgB,IAAI,QAAsB,iBAAA,IAAI,KAAK,CAAA;AACzE,EAAA,MAAM,CAAC,eAAiB,EAAA,kBAAkB,IAAI,QAAsB,iBAAA,IAAI,KAAK,CAAA;AAC7E,EAAA,MAAM,CAAC,mBAAA,EAAqB,sBAAsB,CAAA,GAAI,SAAS,KAAK,CAAA;AACpE,EAAA,MAAM,CAAC,gBAAA,EAAkB,mBAAmB,CAAA,GAAI,SAGtC,IAAI,CAAA;AAGd,EAAA,MAAM,iBAAiB,MAAO,CAAA,QAAA,CAAS,cAAc,wBAAwB,CAAA,IAAK,OAAO,QAAS,CAAA,IAAA;AAClG,EAAA,MAAM,YAAY,MAAO,CAAA,QAAA,CAAS,WAAc,GAAA,uBAAuB,KAAK,aAAiB,IAAA,SAAA;AAG7F,EAAA,QAAA,CAAS,YAAY;AACnB,IAAM,MAAA,OAAA,GAAU,MAAM,WAAA,CAAY,cAAe,EAAA;AACjD,IAAa,YAAA,CAAA,OAAA,CAAQ,SAAS,EAAE,CAAA;AAAA,GAClC,EAAG,CAAC,WAAW,CAAC,CAAA;AAGhB,EAAM,MAAA,EAAE,OAAO,QAAU,EAAA,OAAA,EAAS,aAAa,KAAO,EAAA,SAAA,EAAc,GAAA,QAAA,CAAS,YAAY;AACvF,IAAM,MAAA,GAAA,GACF,CAAG,EAAA,UAAU,uCAAuC,SAAS,CAAA,CAAA,CAChD;AACjB,IAAA,MAAM,QAAW,GAAA,MAAM,QAAS,CAAA,KAAA,CAAM,GAAG,CAAA;AACzC,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAM,MAAA,IAAI,MAAM,kCAAkC,CAAA;AAAA;AAEpD,IAAM,MAAA,IAAA,GAAO,MAAM,QAAA,CAAS,IAAK,EAAA;AACjC,IAAM,MAAA,WAAA,GAAc,IAAK,CAAA,KAAA,IAAS,EAAC;AACnC,IAAA,OAAO,WAAY,CAAA,MAAA;AAAA,MAAO,CAAC,MACzB,CAAE,CAAA,IAAA,CAAK,eAAe,IAAS,KAAA,cAAA,IAAkB,CAAE,CAAA,MAAA,EAAQ,KAAU,KAAA;AAAA,KACvE;AAAA,KACC,CAAC,SAAA,EAAW,gBAAgB,UAAY,EAAA,QAAA,EAAU,OAAO,CAAC,CAAA;AAG7D,EAAA,MAAM,EAAE,KAAO,EAAA,UAAA,EAAY,SAAS,cAAe,EAAA,GAAI,SAAS,YAAY;AAC1E,IAAA,MAAM,WAAW,MAAM,QAAA,CAAS,KAAM,CAAA,CAAA,EAAG,UAAU,CAA2B,yBAAA,CAAA,CAAA;AAC9E,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAO,OAAA,IAAA;AAAA;AAET,IAAM,MAAA,IAAA,GAAO,MAAM,QAAA,CAAS,IAAK,EAAA;AACjC,IAAA,OAAO,KAAK,KAAO,EAAA,IAAA;AAAA,MACjB,CAAC,MACC,CAAE,CAAA,QAAA,CAAS,cAAc,SACzB,IAAA,CAAA,CAAE,SAAS,IAAS,KAAA;AAAA,KACxB;AAAA,KACC,CAAC,SAAA,EAAW,cAAgB,EAAA,QAAA,EAAU,UAAU,CAAC,CAAA;AAEpD,EAAM,MAAA,WAAA,GAAc,UAChB,GAAA,CAAA,WAAA,EAAc,UAAW,CAAA,QAAA,CAAS,SAAS,CAAI,CAAA,EAAA,UAAA,CAAW,QAAS,CAAA,IAAI,CACvE,CAAA,GAAA,SAAA;AAEJ,EAAA,MAAM,EAAE,OAAA,EAAS,gBAAkB,EAAA,OAAA,EAAS,mBAAsB,GAAA,qBAAA;AAAA,IAChE,8BAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAM,MAAA,qBAAA,GAAwB,OAAO,gBAAA,EAA0B,WAAwB,KAAA;AACrF,IAAA,MAAM,GAAM,GAAA,CAAA,EAAG,gBAAgB,CAAA,CAAA,EAAI,WAAW,CAAA,CAAA;AAC9C,IAAI,IAAA,aAAA,CAAc,GAAI,CAAA,GAAG,CAAG,EAAA;AAC1B,MAAA;AAAA;AAGF,IAAiB,gBAAA,CAAA,CAAC,SAAS,IAAI,GAAA,CAAI,IAAI,CAAE,CAAA,GAAA,CAAI,GAAG,CAAC,CAAA;AACjD,IAAI,IAAA;AACF,MAAM,MAAA,QAAA,GAAW,MAAM,QAAS,CAAA,KAAA;AAAA,QAC9B,CAAG,EAAA,UAAU,CAAyB,sBAAA,EAAA,gBAAgB,IAAI,WAAW,CAAA,OAAA;AAAA,OACvE;AACA,MAAA,IAAI,SAAS,EAAI,EAAA;AACf,QAAM,MAAA,IAAA,GAAO,MAAM,QAAA,CAAS,IAAK,EAAA;AACjC,QAAgB,eAAA,CAAA,CAAC,IAAS,KAAA,IAAI,GAAI,CAAA,IAAI,EAAE,GAAI,CAAA,GAAA,EAAK,IAAK,CAAA,MAAM,CAAC,CAAA;AAC7D,QAAmB,kBAAA,CAAA,CAAC,SAAS,IAAI,GAAA,CAAI,IAAI,CAAE,CAAA,GAAA,CAAI,GAAG,CAAC,CAAA;AAAA,OACrD,MAAA,IAAW,QAAS,CAAA,MAAA,KAAW,GAAK,EAAA;AAClC,QAAmB,kBAAA,CAAA,CAAC,SAAS,IAAI,GAAA,CAAI,IAAI,CAAE,CAAA,GAAA,CAAI,GAAG,CAAC,CAAA;AACnD,QAAA,QAAA,CAAS,IAAK,CAAA;AAAA,UACZ,OAAS,EAAA,qEAAA;AAAA,UACT,QAAU,EAAA,SAAA;AAAA,UACV,OAAS,EAAA;AAAA,SACV,CAAA;AAAA;AACH,aACO,GAAK,EAAA;AACZ,MAAQ,OAAA,CAAA,KAAA,CAAM,4BAA4B,GAAG,CAAA;AAAA,KAC7C,SAAA;AACA,MAAA,gBAAA,CAAiB,CAAC,IAAS,KAAA;AACzB,QAAM,MAAA,IAAA,GAAO,IAAI,GAAA,CAAI,IAAI,CAAA;AACzB,QAAA,IAAA,CAAK,OAAO,GAAG,CAAA;AACf,QAAO,OAAA,IAAA;AAAA,OACR,CAAA;AAAA;AACH,GACF;AAEA,EAAM,MAAA,gBAAA,GAAmB,CAAC,gBAAA,EAA0B,WAAwB,KAAA;AAC1E,IAAA,MAAM,GAAM,GAAA,CAAA,EAAG,gBAAgB,CAAA,CAAA,EAAI,WAAW,CAAA,CAAA;AAC9C,IAAA,eAAA,CAAgB,CAAC,IAAS,KAAA;AACxB,MAAM,MAAA,IAAA,GAAO,IAAI,GAAA,CAAI,IAAI,CAAA;AACzB,MAAA,IAAA,CAAK,OAAO,GAAG,CAAA;AACf,MAAO,OAAA,IAAA;AAAA,KACR,CAAA;AAAA,GACH;AAEA,EAAM,MAAA,gBAAA,GAAmB,CAAC,OAAoB,KAAA;AAC5C,IAAA,cAAA,CAAe,CAAC,IAAS,KAAA;AACvB,MAAM,MAAA,MAAA,GAAS,IAAI,GAAA,CAAI,IAAI,CAAA;AAC3B,MAAI,IAAA,MAAA,CAAO,GAAI,CAAA,OAAO,CAAG,EAAA;AACvB,QAAA,MAAA,CAAO,OAAO,OAAO,CAAA;AAAA,OAChB,MAAA;AACL,QAAA,MAAA,CAAO,IAAI,OAAO,CAAA;AAAA;AAEpB,MAAO,OAAA,MAAA;AAAA,KACR,CAAA;AAAA,GACH;AAEA,EAAM,MAAA,OAAA,GAAU,eAAe,cAAkB,IAAA,iBAAA;AAEjD,EAAA,IAAI,OAAS,EAAA;AACX,IAAA,2CAAQ,QAAS,EAAA,IAAA,CAAA;AAAA;AAGnB,EAAA,IAAI,SAAW,EAAA;AACb,IAAO,uBAAA,KAAA,CAAA,aAAA,CAAC,kBAAmB,EAAA,EAAA,KAAA,EAAO,SAAW,EAAA,CAAA;AAAA;AAG/C,EAAM,MAAA,IAAA,GAAQ,YAAyB,EAAC;AACxC,EAAA,MAAM,KAAS,GAAA,UAAA,EAAY,MAAQ,EAAA,eAAA,IAAmB,EAAC;AACvD,EAAM,MAAA,UAAA,GAAa,gBAAoB,IAAA,KAAA,CAAM,MAAS,GAAA,CAAA;AAEtD,EAAM,MAAA,YAAA,GAAe,CAAC,OAAoB,KAAA;AACxC,IAAM,MAAA,GAAA,GAAM,GAAG,OAAQ,CAAA,QAAA,CAAS,SAAS,CAAI,CAAA,EAAA,OAAA,CAAQ,SAAS,IAAI,CAAA,CAAA;AAClE,IAAA,MAAM,SAAY,GAAA,WAAA,CAAY,GAAI,CAAA,OAAA,CAAQ,SAAS,IAAI,CAAA;AACvD,IAAM,MAAA,SAAA,GAAY,aAAc,CAAA,GAAA,CAAI,GAAG,CAAA;AACvC,IAAM,MAAA,WAAA,GAAc,YAAa,CAAA,GAAA,CAAI,GAAG,CAAA;AACxC,IAAM,MAAA,YAAA,GAAe,OAAQ,CAAA,MAAA,EAAQ,SAAW,EAAA,IAAA;AAChD,IAAM,MAAA,aAAA,GAAgB,OAAQ,CAAA,MAAA,EAAQ,aAAkB,KAAA,KAAA;AACxD,IAAA,MAAM,aAAgB,GAAA,eAAA,CAAgB,GAAI,CAAA,GAAG,KAAK,CAAC,aAAA;AAEnD,IAAA,MAAM,oBAAoB,MAAM;AAC9B,MAAA,IAAI,SAAW,EAAA;AACb,QAAA,gBAAA,CAAiB,OAAQ,CAAA,QAAA,CAAS,SAAW,EAAA,OAAA,CAAQ,SAAS,IAAI,CAAA;AAClE,QAAiB,gBAAA,CAAA,OAAA,CAAQ,SAAS,IAAI,CAAA;AAAA,OACxC,MAAA,IAAW,CAAC,aAAe,EAAA;AACzB,QAAoB,mBAAA,CAAA;AAAA,UAClB,SAAA,EAAW,QAAQ,QAAS,CAAA,SAAA;AAAA,UAC5B,IAAA,EAAM,QAAQ,QAAS,CAAA;AAAA,SACxB,CAAA;AACD,QAAA,sBAAA,CAAuB,IAAI,CAAA;AAAA;AAC7B,KACF;AAEA,IAAA,MAAM,aAAa,YAAY;AAC7B,MAAA,IAAI,WAAa,EAAA;AACf,QAAM,MAAA,SAAA,CAAU,SAAU,CAAA,SAAA,CAAU,WAAW,CAAA;AAC/C,QAAA,QAAA,CAAS,IAAK,CAAA;AAAA,UACZ,OAAS,EAAA,6BAAA;AAAA,UACT,QAAU,EAAA,SAAA;AAAA,UACV,OAAS,EAAA;AAAA,SACV,CAAA;AAAA;AACH,KACF;AAEA,IACE,uBAAA,KAAA,CAAA,aAAA;AAAA,MAAC,GAAA;AAAA,MAAA;AAAA,QACC,GAAA,EAAK,QAAQ,QAAS,CAAA,IAAA;AAAA,QACtB,EAAI,EAAA,CAAA;AAAA,QACJ,CAAG,EAAA,GAAA;AAAA,QACH,MAAQ,EAAA,CAAA;AAAA,QACR,WAAY,EAAA,UAAA;AAAA,QACZ,YAAc,EAAA;AAAA,OAAA;AAAA,sBAEb,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAI,OAAQ,EAAA,MAAA,EAAO,gBAAe,eAAgB,EAAA,UAAA,EAAW,QAAS,EAAA,EAAA,EAAI,CACzE,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,UAAW,EAAA,EAAA,OAAA,EAAQ,SAAQ,KAAO,EAAA,EAAE,UAAY,EAAA,GAAA,EAC9C,EAAA,EAAA,OAAA,CAAQ,QAAS,CAAA,IACpB,mBACC,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,OAAA,CAAQ,KAAK,QAAU,EAAA,KAAA,EAAM,SAAU,EAAA,IAAA,EAAK,SAAQ,CACnE,CAAA;AAAA,MACC,gCACE,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAI,OAAQ,EAAA,MAAA,EAAO,YAAW,QAC7B,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,QAAC,UAAA;AAAA,QAAA;AAAA,UACC,OAAQ,EAAA,OAAA;AAAA,UACR,KAAO,EAAA;AAAA,YACL,UAAY,EAAA,WAAA;AAAA,YACZ,QAAU,EAAA,QAAA;AAAA,YACV,IAAM,EAAA,CAAA;AAAA,YACN,QAAU,EAAA,QAAA;AAAA,YACV,YAAc,EAAA;AAAA;AAChB,SAAA;AAAA,QAEC,SAAA,GACG,eACA,SAAa,IAAA,WAAA,GACX,cACA,aAAiB,IAAA,CAAC,cAChB,gBACA,GAAA;AAAA,SAET,SAAa,IAAA,WAAA,wCACX,OAAQ,EAAA,EAAA,KAAA,EAAM,uCACZ,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,MAAK,OAAQ,EAAA,OAAA,EAAS,8BAC/B,KAAA,CAAA,aAAA,CAAA,YAAA,EAAA,EAAa,UAAS,OAAQ,EAAA,CACjC,CACF,CAEF,kBAAA,KAAA,CAAA,aAAA;AAAA,QAAC,OAAA;AAAA,QAAA;AAAA,UACC,OACE,aAAiB,IAAA,CAAC,WACd,GAAA,oBAAA,GACA,YACE,cACA,GAAA;AAAA,SAAA;AAAA,4CAGP,MACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,UAAC,UAAA;AAAA,UAAA;AAAA,YACC,IAAK,EAAA,OAAA;AAAA,YACL,OAAS,EAAA,iBAAA;AAAA,YACT,QAAA,EAAU,SAAc,IAAA,aAAA,IAAiB,CAAC;AAAA,WAAA;AAAA,UAEzC,SAAA,uCAAa,iBAAkB,EAAA,EAAA,QAAA,EAAS,SAAQ,CAAK,mBAAA,KAAA,CAAA,aAAA,CAAC,cAAe,EAAA,EAAA,QAAA,EAAS,OAAQ,EAAA;AAAA,SAE3F;AAAA,OAEJ;AAAA,KAEJ;AAAA,GAEJ;AAEA,EACE,uBAAA,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,sCACG,QAAS,EAAA,EAAA,KAAA,EAAM,uCACb,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAI,GAAG,CACL,EAAA,EAAA,IAAA,CAAK,SAAS,CACb,mBAAA,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,sCACG,UAAW,EAAA,EAAA,OAAA,EAAQ,SAAQ,KAAM,EAAA,eAAA,EAAgB,YAAY,EAAA,IAAA,EAAA,EAC3D,IAAK,CAAA,MAAA,EAAO,eAAY,IAAK,CAAA,MAAA,KAAW,IAAI,GAAM,GAAA,EACrD,GACC,IAAK,CAAA,GAAA,CAAI,YAAY,CACxB,CAEA,mBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,OAAQ,EAAA,OAAA,EAAQ,cAAY,IAAC,EAAA,EAAA,8CAEzC,mBAED,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAI,EAAI,EAAA,CAAA,EAAA,EACN,UACC,mBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,OAAQ,EAAA,WAAA;AAAA,MACR,KAAM,EAAA,SAAA;AAAA,MACN,IAAK,EAAA,OAAA;AAAA,MACL,SAAA,sCAAY,OAAQ,EAAA,IAAA,CAAA;AAAA,MACpB,OAAA,EAAS,MAAM,oBAAA,CAAqB,IAAI;AAAA,KAAA;AAAA,IACzC;AAAA,GAED,mBAEC,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,OAAQ,EAAA,SAAA,EAAU,KAAM,EAAA,eAAA,EAAA,EAAgB,kDAEpD,CAEJ,CACF,CACF,CAEA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,mBAAA;AAAA,IAAA;AAAA,MACC,IAAM,EAAA,iBAAA;AAAA,MACN,OAAA,EAAS,MAAM,oBAAA,CAAqB,KAAK,CAAA;AAAA,MACzC,WAAW,MAAM;AACf,QAAA,oBAAA,CAAqB,KAAK,CAAA;AAC1B,QAAW,UAAA,CAAA,CAAC,CAAM,KAAA,CAAA,GAAI,CAAC,CAAA;AAAA,OACzB;AAAA,MACA,cAAA;AAAA,MACA,SAAA;AAAA,MACA,SAAA;AAAA,MACA;AAAA;AAAA,GAGF,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,IAAM,EAAA,mBAAA;AAAA,MACN,SAAS,MAAM;AACb,QAAA,sBAAA,CAAuB,KAAK,CAAA;AAC5B,QAAA,mBAAA,CAAoB,IAAI,CAAA;AAAA,OAC1B;AAAA,MACA,QAAS,EAAA;AAAA,KAAA;AAAA,wCAER,WACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,OAAI,OAAQ,EAAA,MAAA,EAAO,YAAW,QAC7B,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,eAAY,KAAM,EAAA,SAAA,EAAU,OAAO,EAAE,WAAA,EAAa,GAAK,EAAA,CAAA,EAAE,cAE5D,CACF,CAAA;AAAA,oBACA,KAAA,CAAA,aAAA,CAAC,qCACE,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,SAAQ,OAAQ,EAAA,SAAA,EAAS,IAAC,EAAA,EAAA,kCAAA,kBACH,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,IAAA,EAAO,MAAI,CAAS,EAAA,mEAEvD,mBACC,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,SAAQ,OAAQ,EAAA,KAAA,EAAM,eAAgB,EAAA,EAAA,mEAElD,CACF,CAAA;AAAA,wCACC,aACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,SAAS,MAAM;AACb,UAAA,sBAAA,CAAuB,KAAK,CAAA;AAC5B,UAAA,mBAAA,CAAoB,IAAI,CAAA;AAAA;AAC1B,OAAA;AAAA,MACD;AAAA,KAGD,kBAAA,KAAA,CAAA,aAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,OAAQ,EAAA,WAAA;AAAA,QACR,KAAM,EAAA,SAAA;AAAA,QACN,SAAS,MAAM;AACb,UAAA,IAAI,gBAAkB,EAAA;AACpB,YAAA,qBAAA;AAAA,cACE,gBAAiB,CAAA,SAAA;AAAA,cACjB,gBAAiB,CAAA;AAAA,aACnB;AACA,YAAA,gBAAA,CAAiB,iBAAiB,IAAI,CAAA;AAAA;AAExC,UAAA,sBAAA,CAAuB,KAAK,CAAA;AAC5B,UAAA,mBAAA,CAAoB,IAAI,CAAA;AAAA;AAC1B,OAAA;AAAA,MACD;AAAA,KAGH;AAAA,GAEJ,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"ApiAccessCard.esm.js","sources":["../../../src/components/ApiAccessCard/ApiAccessCard.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { useAsync } from 'react-use';\nimport {\n InfoCard,\n Progress,\n ResponseErrorPanel,\n} from '@backstage/core-components';\nimport {\n Typography,\n Box,\n Chip,\n Button,\n IconButton,\n Tooltip,\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n} from '@material-ui/core';\nimport AddIcon from '@material-ui/icons/Add';\nimport VisibilityIcon from '@material-ui/icons/Visibility';\nimport VisibilityOffIcon from '@material-ui/icons/VisibilityOff';\nimport FileCopyIcon from '@material-ui/icons/FileCopy';\nimport WarningIcon from '@material-ui/icons/Warning';\nimport { useApi, configApiRef, identityApiRef, fetchApiRef, alertApiRef } from '@backstage/core-plugin-api';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { RequestAccessDialog, Plan } from '../RequestAccessDialog';\nimport { useKuadrantPermission } from '../../utils/permissions';\nimport { kuadrantApiKeyCreatePermission } from '../../permissions';\nimport {handleFetchError} from \"../../utils/errors.ts\";\n\ninterface APIKey {\n metadata: {\n name: string;\n namespace: string;\n };\n spec: {\n apiProductRef: {\n name: string;\n };\n planTier: string;\n };\n status?: {\n phase: 'Pending' | 'Approved' | 'Rejected';\n secretRef?: {\n name: string;\n key: string;\n };\n canReadSecret?: boolean;\n };\n}\n\ninterface APIProduct {\n metadata: {\n name: string;\n namespace: string;\n };\n status?: {\n discoveredPlans?: Plan[];\n };\n}\n\nexport interface ApiAccessCardProps {\n // deprecated: use entity annotations instead\n namespace?: string;\n}\n\nexport const ApiAccessCard = ({ namespace: propNamespace }: ApiAccessCardProps) => {\n const { entity } = useEntity();\n const config = useApi(configApiRef);\n const identityApi = useApi(identityApiRef);\n const fetchApi = useApi(fetchApiRef);\n const alertApi = useApi(alertApiRef);\n const backendUrl = config.getString('backend.baseUrl');\n const [userEmail, setUserEmail] = useState<string>('');\n const [requestDialogOpen, setRequestDialogOpen] = useState(false);\n const [refresh, setRefresh] = useState(0);\n\n // key reveal state\n const [visibleKeys, setVisibleKeys] = useState<Set<string>>(new Set());\n const [apiKeyValues, setApiKeyValues] = useState<Map<string, string>>(new Map());\n const [apiKeyLoading, setApiKeyLoading] = useState<Set<string>>(new Set());\n const [alreadyReadKeys, setAlreadyReadKeys] = useState<Set<string>>(new Set());\n const [showOnceWarningOpen, setShowOnceWarningOpen] = useState(false);\n const [pendingKeyReveal, setPendingKeyReveal] = useState<{\n namespace: string;\n name: string;\n } | null>(null);\n\n // get apiproduct name from entity annotation (set by entity provider)\n const apiProductName = entity.metadata.annotations?.['kuadrant.io/apiproduct'] || entity.metadata.name;\n const namespace = entity.metadata.annotations?.['kuadrant.io/namespace'] || propNamespace || 'default';\n\n // get current user identity\n useAsync(async () => {\n const profile = await identityApi.getProfileInfo();\n setUserEmail(profile.email || '');\n }, [identityApi]);\n\n // fetch user's approved keys\n const { value: requests, loading: keysLoading, error: keysError } = useAsync(async () => {\n const url = namespace\n ? `${backendUrl}/api/kuadrant/requests/my?namespace=${namespace}`\n : `${backendUrl}/api/kuadrant/requests/my`;\n const response = await fetchApi.fetch(url);\n if (!response.ok) {\n const error = await handleFetchError(response);\n throw new Error(`failed to fetch api key requests ${error}`);\n }\n const data = await response.json();\n const allRequests = data.items || [];\n return allRequests.filter((r: APIKey) =>\n r.spec.apiProductRef?.name === apiProductName && r.status?.phase === 'Approved'\n );\n }, [namespace, apiProductName, backendUrl, fetchApi, refresh]);\n\n // fetch apiproduct to get available plans\n const { value: apiProduct, loading: productLoading } = useAsync(async () => {\n const response = await fetchApi.fetch(`${backendUrl}/api/kuadrant/apiproducts`);\n if (!response.ok) {\n return null;\n }\n const data = await response.json();\n return data.items?.find(\n (p: APIProduct) =>\n p.metadata.namespace === namespace &&\n p.metadata.name === apiProductName,\n );\n }, [namespace, apiProductName, fetchApi, backendUrl]);\n\n const resourceRef = apiProduct\n ? `apiproduct:${apiProduct.metadata.namespace}/${apiProduct.metadata.name}`\n : undefined;\n\n const { allowed: canCreateRequest, loading: permissionLoading } = useKuadrantPermission(\n kuadrantApiKeyCreatePermission,\n resourceRef,\n );\n\n const fetchApiKeyFromSecret = async (requestNamespace: string, requestName: string) => {\n const key = `${requestNamespace}/${requestName}`;\n if (apiKeyLoading.has(key)) {\n return;\n }\n\n setApiKeyLoading((prev) => new Set(prev).add(key));\n try {\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/apikeys/${requestNamespace}/${requestName}/secret`,\n );\n if (response.ok) {\n const data = await response.json();\n setApiKeyValues((prev) => new Map(prev).set(key, data.apiKey));\n setAlreadyReadKeys((prev) => new Set(prev).add(key));\n } else if (response.status === 403) {\n setAlreadyReadKeys((prev) => new Set(prev).add(key));\n alertApi.post({\n message: 'This API key has already been viewed and cannot be retrieved again.',\n severity: 'warning',\n display: 'transient',\n });\n }\n } catch (err) {\n console.error('failed to fetch api key:', err);\n const errorMessage = err instanceof Error ? err.message : \"unknown error occurred\";\n alertApi.post({\n message: `Failed to fetch APIKey. ${errorMessage}`,\n severity: 'error',\n display: 'transient',\n });\n } finally {\n setApiKeyLoading((prev) => {\n const next = new Set(prev);\n next.delete(key);\n return next;\n });\n }\n };\n\n const clearApiKeyValue = (requestNamespace: string, requestName: string) => {\n const key = `${requestNamespace}/${requestName}`;\n setApiKeyValues((prev) => {\n const next = new Map(prev);\n next.delete(key);\n return next;\n });\n };\n\n const toggleVisibility = (keyName: string) => {\n setVisibleKeys((prev) => {\n const newSet = new Set(prev);\n if (newSet.has(keyName)) {\n newSet.delete(keyName);\n } else {\n newSet.add(keyName);\n }\n return newSet;\n });\n };\n\n const loading = keysLoading || productLoading || permissionLoading;\n\n if (loading) {\n return <Progress />;\n }\n\n if (keysError) {\n return <ResponseErrorPanel error={keysError} />;\n }\n\n const keys = (requests as APIKey[]) || [];\n const plans = (apiProduct?.status?.discoveredPlans || []) as Plan[];\n const canRequest = canCreateRequest && plans.length > 0;\n\n const renderKeyRow = (request: APIKey) => {\n const key = `${request.metadata.namespace}/${request.metadata.name}`;\n const isVisible = visibleKeys.has(request.metadata.name);\n const isLoading = apiKeyLoading.has(key);\n const apiKeyValue = apiKeyValues.get(key);\n const hasSecretRef = request.status?.secretRef?.name;\n const canReadSecret = request.status?.canReadSecret !== false;\n const isAlreadyRead = alreadyReadKeys.has(key) || !canReadSecret;\n\n const handleRevealClick = () => {\n if (isVisible) {\n clearApiKeyValue(request.metadata.namespace, request.metadata.name);\n toggleVisibility(request.metadata.name);\n } else if (!isAlreadyRead) {\n setPendingKeyReveal({\n namespace: request.metadata.namespace,\n name: request.metadata.name,\n });\n setShowOnceWarningOpen(true);\n }\n };\n\n const handleCopy = async () => {\n if (apiKeyValue) {\n await navigator.clipboard.writeText(apiKeyValue);\n alertApi.post({\n message: 'API key copied to clipboard',\n severity: 'success',\n display: 'transient',\n });\n }\n };\n\n return (\n <Box\n key={request.metadata.name}\n mb={1}\n p={1.5}\n border={1}\n borderColor=\"grey.300\"\n borderRadius={4}\n >\n <Box display=\"flex\" justifyContent=\"space-between\" alignItems=\"center\" mb={1}>\n <Typography variant=\"body2\" style={{ fontWeight: 500 }}>\n {request.metadata.name}\n </Typography>\n <Chip label={request.spec.planTier} color=\"primary\" size=\"small\" />\n </Box>\n {hasSecretRef && (\n <Box display=\"flex\" alignItems=\"center\">\n <Typography\n variant=\"body2\"\n style={{\n fontFamily: 'monospace',\n fontSize: '0.8rem',\n flex: 1,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}\n >\n {isLoading\n ? 'Loading...'\n : isVisible && apiKeyValue\n ? apiKeyValue\n : isAlreadyRead && !apiKeyValue\n ? 'Already viewed'\n : '••••••••••••••••'}\n </Typography>\n {isVisible && apiKeyValue && (\n <Tooltip title=\"Copy to clipboard\">\n <IconButton size=\"small\" onClick={handleCopy}>\n <FileCopyIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n )}\n <Tooltip\n title={\n isAlreadyRead && !apiKeyValue\n ? 'Key already viewed'\n : isVisible\n ? 'Hide API key'\n : 'Reveal API key (one-time only)'\n }\n >\n <span>\n <IconButton\n size=\"small\"\n onClick={handleRevealClick}\n disabled={isLoading || (isAlreadyRead && !apiKeyValue)}\n >\n {isVisible ? <VisibilityOffIcon fontSize=\"small\" /> : <VisibilityIcon fontSize=\"small\" />}\n </IconButton>\n </span>\n </Tooltip>\n </Box>\n )}\n </Box>\n );\n };\n\n return (\n <>\n <InfoCard title=\"Kuadrant API Keys\">\n <Box p={2}>\n {keys.length > 0 ? (\n <>\n <Typography variant=\"body2\" color=\"textSecondary\" gutterBottom>\n {keys.length} active key{keys.length !== 1 ? 's' : ''}\n </Typography>\n {keys.map(renderKeyRow)}\n </>\n ) : (\n <Typography variant=\"body1\" gutterBottom>\n You don't have any API keys for this API yet\n </Typography>\n )}\n <Box mt={2}>\n {canRequest ? (\n <Button\n variant=\"contained\"\n color=\"primary\"\n size=\"small\"\n startIcon={<AddIcon />}\n onClick={() => setRequestDialogOpen(true)}\n >\n Request API Access\n </Button>\n ) : (\n <Typography variant=\"caption\" color=\"textSecondary\">\n Visit the API Keys tab to view and manage access\n </Typography>\n )}\n </Box>\n </Box>\n </InfoCard>\n\n <RequestAccessDialog\n open={requestDialogOpen}\n onClose={() => setRequestDialogOpen(false)}\n onSuccess={() => {\n setRequestDialogOpen(false);\n setRefresh((r) => r + 1);\n }}\n apiProductName={apiProductName}\n namespace={namespace}\n userEmail={userEmail}\n plans={plans}\n />\n\n <Dialog\n open={showOnceWarningOpen}\n onClose={() => {\n setShowOnceWarningOpen(false);\n setPendingKeyReveal(null);\n }}\n maxWidth=\"sm\"\n >\n <DialogTitle>\n <Box display=\"flex\" alignItems=\"center\">\n <WarningIcon color=\"primary\" style={{ marginRight: 8 }} />\n View API Key\n </Box>\n </DialogTitle>\n <DialogContent>\n <Typography variant=\"body1\" paragraph>\n This API key can only be viewed <strong>once</strong>. After you\n reveal it, you will not be able to retrieve it again.\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Make sure to copy and store it securely before closing this view.\n </Typography>\n </DialogContent>\n <DialogActions>\n <Button\n onClick={() => {\n setShowOnceWarningOpen(false);\n setPendingKeyReveal(null);\n }}\n >\n Cancel\n </Button>\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={() => {\n if (pendingKeyReveal) {\n fetchApiKeyFromSecret(\n pendingKeyReveal.namespace,\n pendingKeyReveal.name,\n );\n toggleVisibility(pendingKeyReveal.name);\n }\n setShowOnceWarningOpen(false);\n setPendingKeyReveal(null);\n }}\n >\n Reveal API Key\n </Button>\n </DialogActions>\n </Dialog>\n </>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -121,8 +121,9 @@ const ApiKeyDetailPage = () => {
121
121
  }
122
122
  } catch (err) {
123
123
  console.error("Failed to fetch API key:", err);
124
+ const errorMessage = err instanceof Error ? err.message : "unknown error occurred";
124
125
  alertApi.post({
125
- message: "Failed to fetch API key",
126
+ message: `Failed to fetch APIKey. ${errorMessage}`,
126
127
  severity: "error",
127
128
  display: "transient"
128
129
  });
@@ -1 +1 @@
1
- {"version":3,"file":"ApiKeyDetailPage.esm.js","sources":["../../../src/components/ApiKeyDetailPage/ApiKeyDetailPage.tsx"],"sourcesContent":["import React, { useState } from \"react\";\nimport { useParams } from \"react-router-dom\";\nimport {\n useApi,\n configApiRef,\n fetchApiRef,\n alertApiRef,\n} from \"@backstage/core-plugin-api\";\nimport { useAsync } from \"react-use\";\nimport {\n Header,\n Page,\n Content,\n Progress,\n ResponseErrorPanel,\n InfoCard,\n Link,\n Breadcrumbs,\n} from \"@backstage/core-components\";\nimport {\n Box,\n Grid,\n Typography,\n Chip,\n IconButton,\n Tooltip,\n Tabs,\n Tab,\n Button,\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n makeStyles,\n} from \"@material-ui/core\";\nimport VisibilityIcon from \"@material-ui/icons/Visibility\";\nimport VisibilityOffIcon from \"@material-ui/icons/VisibilityOff\";\nimport FileCopyIcon from \"@material-ui/icons/FileCopy\";\nimport WarningIcon from \"@material-ui/icons/Warning\";\nimport ArrowBackIcon from \"@material-ui/icons/ArrowBack\";\nimport OpenInNewIcon from \"@material-ui/icons/OpenInNew\";\nimport EmailIcon from \"@material-ui/icons/Email\";\nimport { APIKey, APIProduct } from \"../../types/api-management\";\nimport { getStatusChipStyle } from \"../../utils/styles\";\n\nconst useStyles = makeStyles((theme) => ({\n label: {\n fontWeight: 600,\n color: theme.palette.text.secondary,\n marginBottom: theme.spacing(0.5),\n },\n value: {\n marginBottom: theme.spacing(2),\n },\n codeBlock: {\n backgroundColor: theme.palette.background.default,\n padding: theme.spacing(2),\n borderRadius: theme.shape.borderRadius,\n fontFamily: \"monospace\",\n fontSize: \"0.875rem\",\n overflow: \"auto\",\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-all\",\n },\n apiKeyContainer: {\n display: \"flex\",\n alignItems: \"center\",\n gap: theme.spacing(1),\n padding: theme.spacing(1.5),\n backgroundColor: theme.palette.background.default,\n borderRadius: theme.shape.borderRadius,\n fontFamily: \"monospace\",\n },\n tabPanel: {\n marginTop: theme.spacing(2),\n },\n}));\n\nconst CodeExample = ({\n code,\n onCopy,\n}: {\n code: string;\n onCopy: () => void;\n}) => {\n const classes = useStyles();\n\n return (\n <Box position=\"relative\">\n <Box className={classes.codeBlock}>{code}</Box>\n <Tooltip title=\"Copy code\">\n <IconButton\n size=\"small\"\n style={{ position: \"absolute\", top: 8, right: 8 }}\n onClick={onCopy}\n >\n <FileCopyIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n </Box>\n );\n};\n\nexport const ApiKeyDetailPage = () => {\n const classes = useStyles();\n const { namespace, name } = useParams<{ namespace: string; name: string }>();\n const config = useApi(configApiRef);\n const fetchApi = useApi(fetchApiRef);\n const alertApi = useApi(alertApiRef);\n const backendUrl = config.getString(\"backend.baseUrl\");\n\n const [selectedTab, setSelectedTab] = useState(0);\n const [showApiKey, setShowApiKey] = useState(false);\n const [apiKeyValue, setApiKeyValue] = useState<string | null>(null);\n const [apiKeyLoading, setApiKeyLoading] = useState(false);\n const [alreadyRead, setAlreadyRead] = useState(false);\n const [showWarning, setShowWarning] = useState(false);\n\n const {\n value: data,\n loading,\n error,\n } = useAsync(async () => {\n const [apiKeyResponse, productsResponse] = await Promise.all([\n fetchApi.fetch(`${backendUrl}/api/kuadrant/apikeys/${namespace}/${name}`),\n fetchApi.fetch(`${backendUrl}/api/kuadrant/apiproducts`),\n ]);\n\n if (!apiKeyResponse.ok) {\n throw new Error(\"Failed to fetch API key\");\n }\n const apiKeyData = await apiKeyResponse.json();\n\n // check if key has already been read\n if (apiKeyData.status?.canReadSecret === false) {\n setAlreadyRead(true);\n }\n\n // find matching api product to get contact info\n let apiProduct: APIProduct | undefined;\n if (productsResponse.ok) {\n const productsData = await productsResponse.json();\n apiProduct = (productsData.items || []).find(\n (p: APIProduct) =>\n p.metadata.name === apiKeyData.spec.apiProductRef?.name &&\n p.metadata.namespace === apiKeyData.metadata.namespace,\n );\n }\n\n return { apiKey: apiKeyData as APIKey, apiProduct };\n }, [namespace, name, backendUrl, fetchApi]);\n\n const apiKey = data?.apiKey;\n const apiProduct = data?.apiProduct;\n\n const fetchApiKeySecret = async () => {\n setApiKeyLoading(true);\n try {\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/apikeys/${namespace}/${name}/secret`,\n );\n if (response.ok) {\n const data = await response.json();\n setApiKeyValue(data.apiKey);\n setAlreadyRead(true);\n setShowApiKey(true);\n } else if (response.status === 403) {\n setAlreadyRead(true);\n alertApi.post({\n message:\n \"This API key has already been viewed and cannot be retrieved again.\",\n severity: \"warning\",\n display: \"transient\",\n });\n }\n } catch (err) {\n console.error(\"Failed to fetch API key:\", err);\n alertApi.post({\n message: \"Failed to fetch API key\",\n severity: \"error\",\n display: \"transient\",\n });\n } finally {\n setApiKeyLoading(false);\n }\n };\n\n const handleRevealClick = () => {\n if (showApiKey) {\n setShowApiKey(false);\n setApiKeyValue(null);\n } else if (!alreadyRead) {\n setShowWarning(true);\n }\n };\n\n const handleConfirmReveal = () => {\n setShowWarning(false);\n fetchApiKeySecret();\n };\n\n const handleCopy = async (text: string) => {\n await navigator.clipboard.writeText(text);\n alertApi.post({\n message: \"Copied to clipboard\",\n severity: \"success\",\n display: \"transient\",\n });\n };\n\n if (loading) {\n return <Progress />;\n }\n\n if (error || !apiKey) {\n return (\n <ResponseErrorPanel error={error || new Error(\"API key not found\")} />\n );\n }\n\n const phase = apiKey.status?.phase || \"Pending\";\n const statusLabel = phase === \"Approved\" ? \"Active\" : phase;\n const hostname = apiKey.status?.apiHostname || \"api.example.com\";\n const displayApiKey = apiKeyValue || \"<your-api-key>\";\n\n // code examples\n const curlExample = `curl -H \"Authorization: Bearer ${displayApiKey}\" \\\\\n https://${hostname}/`;\n\n const nodeExample = `const response = await fetch('https://${hostname}/', {\n headers: {\n 'Authorization': 'Bearer ${displayApiKey}'\n }\n});\nconst data = await response.json();`;\n\n const pythonExample = `import requests\n\nresponse = requests.get(\n 'https://${hostname}/',\n headers={'Authorization': 'Bearer ${displayApiKey}'}\n)\ndata = response.json()`;\n\n const goExample = `package main\n\nimport (\n \"net/http\"\n)\n\nfunc main() {\n client := &http.Client{}\n req, _ := http.NewRequest(\"GET\", \"https://${hostname}/\", nil)\n req.Header.Set(\"Authorization\", \"Bearer ${displayApiKey}\")\n resp, _ := client.Do(req)\n defer resp.Body.Close()\n}`;\n\n const codeExamples = [\n { label: \"cURL\", code: curlExample },\n { label: \"Node.js\", code: nodeExample },\n { label: \"Python\", code: pythonExample },\n { label: \"Go\", code: goExample },\n ];\n\n return (\n <Page themeId=\"tool\">\n <Header\n title={apiKey.metadata.name}\n subtitle={`API Key for ${apiKey.spec.apiProductRef?.name || \"unknown\"}`}\n >\n <Link to=\"/kuadrant/api-keys\">\n <Button startIcon={<ArrowBackIcon />}>Back to API Keys</Button>\n </Link>\n </Header>\n <Content>\n <Box mb={2}>\n <Breadcrumbs aria-label=\"breadcrumb\">\n <Link to=\"/kuadrant/api-keys\">API keys</Link>\n <Typography>{apiKey.metadata.name}</Typography>\n </Breadcrumbs>\n </Box>\n\n <Box mb={3} display=\"flex\" style={{ gap: 8 }}>\n <Link to={`/catalog/default/api/${apiKey.spec.apiProductRef?.name}`}>\n <Button\n variant=\"outlined\"\n startIcon={<OpenInNewIcon />}\n data-testid=\"view-api-button\"\n >\n View API\n </Button>\n </Link>\n {apiProduct?.spec?.contact &&\n (apiProduct.spec.contact.email ||\n apiProduct.spec.contact.url ||\n apiProduct.spec.contact.slack) && (\n <Button\n variant=\"outlined\"\n startIcon={<EmailIcon />}\n href={\n apiProduct.spec.contact.email\n ? `mailto:${apiProduct.spec.contact.email}`\n : apiProduct.spec.contact.slack\n ? apiProduct.spec.contact.slack\n : apiProduct.spec.contact.url || \"#\"\n }\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Contact Owner\n </Button>\n )}\n </Box>\n\n <Grid container spacing={3}>\n <Grid item xs={12} md={6}>\n <InfoCard title=\"API Key Details\">\n <Box>\n <Typography variant=\"caption\" className={classes.label}>\n Status\n </Typography>\n <Box className={classes.value}>\n <Chip\n label={statusLabel}\n size=\"small\"\n style={getStatusChipStyle(phase)}\n data-testid=\"api-key-status-chip\"\n />\n </Box>\n\n <Typography variant=\"caption\" className={classes.label}>\n API Product\n </Typography>\n <Typography variant=\"body1\" className={classes.value}>\n <Link\n to={`/catalog/default/api/${apiKey.spec.apiProductRef?.name}/api-keys`}\n >\n {apiKey.spec.apiProductRef?.name || \"unknown\"}\n </Link>\n </Typography>\n\n <Typography variant=\"caption\" className={classes.label}>\n Tier\n </Typography>\n <Box className={classes.value}>\n <Chip\n label={apiKey.spec.planTier}\n size=\"small\"\n variant=\"outlined\"\n />\n </Box>\n\n <Typography variant=\"caption\" className={classes.label}>\n Requester\n </Typography>\n <Typography variant=\"body1\" className={classes.value}>\n {apiKey.spec.requestedBy?.userId}\n </Typography>\n\n <Typography variant=\"caption\" className={classes.label}>\n Requested\n </Typography>\n <Typography variant=\"body1\" className={classes.value}>\n {apiKey.metadata.creationTimestamp\n ? new Date(\n apiKey.metadata.creationTimestamp,\n ).toLocaleDateString()\n : \"-\"}\n </Typography>\n\n {apiKey.status?.reviewedBy && (\n <>\n <Typography variant=\"caption\" className={classes.label}>\n Reviewed By\n </Typography>\n <Typography variant=\"body1\" className={classes.value}>\n {apiKey.status.reviewedBy.replace(/^user:default\\//, \"\")}\n {apiKey.status.reviewedAt && (\n <Typography variant=\"caption\" color=\"textSecondary\">\n {\" \"}\n on{\" \"}\n {new Date(\n apiKey.status.reviewedAt,\n ).toLocaleDateString()}\n </Typography>\n )}\n </Typography>\n </>\n )}\n </Box>\n </InfoCard>\n </Grid>\n\n <Grid item xs={12} md={6}>\n <InfoCard title=\"Use Case\">\n <Typography variant=\"body1\">\n {apiKey.spec.useCase || \"No use case provided\"}\n </Typography>\n </InfoCard>\n\n {phase === \"Approved\" && (\n <Box mt={2}>\n <InfoCard title=\"API Key\">\n {alreadyRead && !apiKeyValue ? (\n <Tooltip title=\"This API key has already been viewed and cannot be retrieved again\">\n <Box display=\"flex\" alignItems=\"center\">\n <Typography variant=\"body2\" color=\"textSecondary\">\n Already viewed - cannot be retrieved again\n </Typography>\n <VisibilityOffIcon\n fontSize=\"small\"\n color=\"disabled\"\n style={{ marginLeft: 8 }}\n />\n </Box>\n </Tooltip>\n ) : (\n <Box className={classes.apiKeyContainer}>\n <Typography\n variant=\"body2\"\n style={{ fontFamily: \"monospace\", flex: 1 }}\n >\n {apiKeyLoading\n ? \"Loading...\"\n : showApiKey && apiKeyValue\n ? apiKeyValue\n : \"•\".repeat(32)}\n </Typography>\n {showApiKey && apiKeyValue && (\n <Tooltip title=\"Copy to clipboard\">\n <IconButton\n size=\"small\"\n onClick={() => handleCopy(apiKeyValue)}\n >\n <FileCopyIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n )}\n <Tooltip\n title={\n showApiKey\n ? \"Hide API key\"\n : \"Reveal API key (one-time only)\"\n }\n >\n <span>\n <IconButton\n size=\"small\"\n onClick={handleRevealClick}\n disabled={\n apiKeyLoading || (alreadyRead && !apiKeyValue)\n }\n >\n {showApiKey ? (\n <VisibilityOffIcon fontSize=\"small\" />\n ) : (\n <VisibilityIcon fontSize=\"small\" />\n )}\n </IconButton>\n </span>\n </Tooltip>\n </Box>\n )}\n </InfoCard>\n </Box>\n )}\n </Grid>\n\n {phase === \"Approved\" && (\n <Grid item xs={12}>\n <InfoCard title=\"Code Examples\">\n <Box>\n <Tabs\n value={selectedTab}\n onChange={(_, newValue) => setSelectedTab(newValue)}\n indicatorColor=\"primary\"\n textColor=\"primary\"\n >\n {codeExamples.map((ex) => (\n <Tab key={ex.label} label={ex.label} />\n ))}\n </Tabs>\n <Box className={classes.tabPanel}>\n <CodeExample\n code={codeExamples[selectedTab].code}\n onCopy={() => handleCopy(codeExamples[selectedTab].code)}\n />\n </Box>\n </Box>\n </InfoCard>\n </Grid>\n )}\n\n {apiKey.status?.limits && (\n <Grid item xs={12}>\n <InfoCard title=\"Rate Limits\">\n <Grid container spacing={2}>\n {apiKey.status.limits.daily && (\n <Grid item>\n <Typography variant=\"caption\" className={classes.label}>\n Daily\n </Typography>\n <Typography variant=\"h6\">\n {apiKey.status.limits.daily.toLocaleString()}\n </Typography>\n </Grid>\n )}\n {apiKey.status.limits.weekly && (\n <Grid item>\n <Typography variant=\"caption\" className={classes.label}>\n Weekly\n </Typography>\n <Typography variant=\"h6\">\n {apiKey.status.limits.weekly.toLocaleString()}\n </Typography>\n </Grid>\n )}\n {apiKey.status.limits.monthly && (\n <Grid item>\n <Typography variant=\"caption\" className={classes.label}>\n Monthly\n </Typography>\n <Typography variant=\"h6\">\n {apiKey.status.limits.monthly.toLocaleString()}\n </Typography>\n </Grid>\n )}\n </Grid>\n </InfoCard>\n </Grid>\n )}\n </Grid>\n </Content>\n\n <Dialog\n open={showWarning}\n onClose={() => setShowWarning(false)}\n maxWidth=\"sm\"\n >\n <DialogTitle>\n <Box display=\"flex\" alignItems=\"center\">\n <WarningIcon color=\"primary\" style={{ marginRight: 8 }} />\n View API Key\n </Box>\n </DialogTitle>\n <DialogContent>\n <Typography variant=\"body1\" paragraph>\n This API key can only be viewed <strong>once</strong>. After you\n reveal it, you will not be able to retrieve it again.\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Make sure to copy and store it securely before closing this view.\n </Typography>\n </DialogContent>\n <DialogActions>\n <Button onClick={() => setShowWarning(false)}>Cancel</Button>\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={handleConfirmReveal}\n >\n Reveal API Key\n </Button>\n </DialogActions>\n </Dialog>\n </Page>\n );\n};\n"],"names":["apiProduct","data"],"mappings":"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"}
1
+ {"version":3,"file":"ApiKeyDetailPage.esm.js","sources":["../../../src/components/ApiKeyDetailPage/ApiKeyDetailPage.tsx"],"sourcesContent":["import React, { useState } from \"react\";\nimport { useParams } from \"react-router-dom\";\nimport {\n useApi,\n configApiRef,\n fetchApiRef,\n alertApiRef,\n} from \"@backstage/core-plugin-api\";\nimport { useAsync } from \"react-use\";\nimport {\n Header,\n Page,\n Content,\n Progress,\n ResponseErrorPanel,\n InfoCard,\n Link,\n Breadcrumbs,\n} from \"@backstage/core-components\";\nimport {\n Box,\n Grid,\n Typography,\n Chip,\n IconButton,\n Tooltip,\n Tabs,\n Tab,\n Button,\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n makeStyles,\n} from \"@material-ui/core\";\nimport VisibilityIcon from \"@material-ui/icons/Visibility\";\nimport VisibilityOffIcon from \"@material-ui/icons/VisibilityOff\";\nimport FileCopyIcon from \"@material-ui/icons/FileCopy\";\nimport WarningIcon from \"@material-ui/icons/Warning\";\nimport ArrowBackIcon from \"@material-ui/icons/ArrowBack\";\nimport OpenInNewIcon from \"@material-ui/icons/OpenInNew\";\nimport EmailIcon from \"@material-ui/icons/Email\";\nimport { APIKey, APIProduct } from \"../../types/api-management\";\nimport { getStatusChipStyle } from \"../../utils/styles\";\n\nconst useStyles = makeStyles((theme) => ({\n label: {\n fontWeight: 600,\n color: theme.palette.text.secondary,\n marginBottom: theme.spacing(0.5),\n },\n value: {\n marginBottom: theme.spacing(2),\n },\n codeBlock: {\n backgroundColor: theme.palette.background.default,\n padding: theme.spacing(2),\n borderRadius: theme.shape.borderRadius,\n fontFamily: \"monospace\",\n fontSize: \"0.875rem\",\n overflow: \"auto\",\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-all\",\n },\n apiKeyContainer: {\n display: \"flex\",\n alignItems: \"center\",\n gap: theme.spacing(1),\n padding: theme.spacing(1.5),\n backgroundColor: theme.palette.background.default,\n borderRadius: theme.shape.borderRadius,\n fontFamily: \"monospace\",\n },\n tabPanel: {\n marginTop: theme.spacing(2),\n },\n}));\n\nconst CodeExample = ({\n code,\n onCopy,\n}: {\n code: string;\n onCopy: () => void;\n}) => {\n const classes = useStyles();\n\n return (\n <Box position=\"relative\">\n <Box className={classes.codeBlock}>{code}</Box>\n <Tooltip title=\"Copy code\">\n <IconButton\n size=\"small\"\n style={{ position: \"absolute\", top: 8, right: 8 }}\n onClick={onCopy}\n >\n <FileCopyIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n </Box>\n );\n};\n\nexport const ApiKeyDetailPage = () => {\n const classes = useStyles();\n const { namespace, name } = useParams<{ namespace: string; name: string }>();\n const config = useApi(configApiRef);\n const fetchApi = useApi(fetchApiRef);\n const alertApi = useApi(alertApiRef);\n const backendUrl = config.getString(\"backend.baseUrl\");\n\n const [selectedTab, setSelectedTab] = useState(0);\n const [showApiKey, setShowApiKey] = useState(false);\n const [apiKeyValue, setApiKeyValue] = useState<string | null>(null);\n const [apiKeyLoading, setApiKeyLoading] = useState(false);\n const [alreadyRead, setAlreadyRead] = useState(false);\n const [showWarning, setShowWarning] = useState(false);\n\n const {\n value: data,\n loading,\n error,\n } = useAsync(async () => {\n const [apiKeyResponse, productsResponse] = await Promise.all([\n fetchApi.fetch(`${backendUrl}/api/kuadrant/apikeys/${namespace}/${name}`),\n fetchApi.fetch(`${backendUrl}/api/kuadrant/apiproducts`),\n ]);\n\n if (!apiKeyResponse.ok) {\n throw new Error(\"Failed to fetch API key\");\n }\n const apiKeyData = await apiKeyResponse.json();\n\n // check if key has already been read\n if (apiKeyData.status?.canReadSecret === false) {\n setAlreadyRead(true);\n }\n\n // find matching api product to get contact info\n let apiProduct: APIProduct | undefined;\n if (productsResponse.ok) {\n const productsData = await productsResponse.json();\n apiProduct = (productsData.items || []).find(\n (p: APIProduct) =>\n p.metadata.name === apiKeyData.spec.apiProductRef?.name &&\n p.metadata.namespace === apiKeyData.metadata.namespace,\n );\n }\n\n return { apiKey: apiKeyData as APIKey, apiProduct };\n }, [namespace, name, backendUrl, fetchApi]);\n\n const apiKey = data?.apiKey;\n const apiProduct = data?.apiProduct;\n\n const fetchApiKeySecret = async () => {\n setApiKeyLoading(true);\n try {\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/apikeys/${namespace}/${name}/secret`,\n );\n if (response.ok) {\n const data = await response.json();\n setApiKeyValue(data.apiKey);\n setAlreadyRead(true);\n setShowApiKey(true);\n } else if (response.status === 403) {\n setAlreadyRead(true);\n alertApi.post({\n message:\n \"This API key has already been viewed and cannot be retrieved again.\",\n severity: \"warning\",\n display: \"transient\",\n });\n }\n } catch (err) {\n console.error(\"Failed to fetch API key:\", err);\n const errorMessage = err instanceof Error ? err.message : \"unknown error occurred\";\n alertApi.post({\n message: `Failed to fetch APIKey. ${errorMessage}`,\n severity: 'error',\n display: 'transient',\n });\n } finally {\n setApiKeyLoading(false);\n }\n };\n\n const handleRevealClick = () => {\n if (showApiKey) {\n setShowApiKey(false);\n setApiKeyValue(null);\n } else if (!alreadyRead) {\n setShowWarning(true);\n }\n };\n\n const handleConfirmReveal = () => {\n setShowWarning(false);\n fetchApiKeySecret();\n };\n\n const handleCopy = async (text: string) => {\n await navigator.clipboard.writeText(text);\n alertApi.post({\n message: \"Copied to clipboard\",\n severity: \"success\",\n display: \"transient\",\n });\n };\n\n if (loading) {\n return <Progress />;\n }\n\n if (error || !apiKey) {\n return (\n <ResponseErrorPanel error={error || new Error(\"API key not found\")} />\n );\n }\n\n const phase = apiKey.status?.phase || \"Pending\";\n const statusLabel = phase === \"Approved\" ? \"Active\" : phase;\n const hostname = apiKey.status?.apiHostname || \"api.example.com\";\n const displayApiKey = apiKeyValue || \"<your-api-key>\";\n\n // code examples\n const curlExample = `curl -H \"Authorization: Bearer ${displayApiKey}\" \\\\\n https://${hostname}/`;\n\n const nodeExample = `const response = await fetch('https://${hostname}/', {\n headers: {\n 'Authorization': 'Bearer ${displayApiKey}'\n }\n});\nconst data = await response.json();`;\n\n const pythonExample = `import requests\n\nresponse = requests.get(\n 'https://${hostname}/',\n headers={'Authorization': 'Bearer ${displayApiKey}'}\n)\ndata = response.json()`;\n\n const goExample = `package main\n\nimport (\n \"net/http\"\n)\n\nfunc main() {\n client := &http.Client{}\n req, _ := http.NewRequest(\"GET\", \"https://${hostname}/\", nil)\n req.Header.Set(\"Authorization\", \"Bearer ${displayApiKey}\")\n resp, _ := client.Do(req)\n defer resp.Body.Close()\n}`;\n\n const codeExamples = [\n { label: \"cURL\", code: curlExample },\n { label: \"Node.js\", code: nodeExample },\n { label: \"Python\", code: pythonExample },\n { label: \"Go\", code: goExample },\n ];\n\n return (\n <Page themeId=\"tool\">\n <Header\n title={apiKey.metadata.name}\n subtitle={`API Key for ${apiKey.spec.apiProductRef?.name || \"unknown\"}`}\n >\n <Link to=\"/kuadrant/api-keys\">\n <Button startIcon={<ArrowBackIcon />}>Back to API Keys</Button>\n </Link>\n </Header>\n <Content>\n <Box mb={2}>\n <Breadcrumbs aria-label=\"breadcrumb\">\n <Link to=\"/kuadrant/api-keys\">API keys</Link>\n <Typography>{apiKey.metadata.name}</Typography>\n </Breadcrumbs>\n </Box>\n\n <Box mb={3} display=\"flex\" style={{ gap: 8 }}>\n <Link to={`/catalog/default/api/${apiKey.spec.apiProductRef?.name}`}>\n <Button\n variant=\"outlined\"\n startIcon={<OpenInNewIcon />}\n data-testid=\"view-api-button\"\n >\n View API\n </Button>\n </Link>\n {apiProduct?.spec?.contact &&\n (apiProduct.spec.contact.email ||\n apiProduct.spec.contact.url ||\n apiProduct.spec.contact.slack) && (\n <Button\n variant=\"outlined\"\n startIcon={<EmailIcon />}\n href={\n apiProduct.spec.contact.email\n ? `mailto:${apiProduct.spec.contact.email}`\n : apiProduct.spec.contact.slack\n ? apiProduct.spec.contact.slack\n : apiProduct.spec.contact.url || \"#\"\n }\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Contact Owner\n </Button>\n )}\n </Box>\n\n <Grid container spacing={3}>\n <Grid item xs={12} md={6}>\n <InfoCard title=\"API Key Details\">\n <Box>\n <Typography variant=\"caption\" className={classes.label}>\n Status\n </Typography>\n <Box className={classes.value}>\n <Chip\n label={statusLabel}\n size=\"small\"\n style={getStatusChipStyle(phase)}\n data-testid=\"api-key-status-chip\"\n />\n </Box>\n\n <Typography variant=\"caption\" className={classes.label}>\n API Product\n </Typography>\n <Typography variant=\"body1\" className={classes.value}>\n <Link\n to={`/catalog/default/api/${apiKey.spec.apiProductRef?.name}/api-keys`}\n >\n {apiKey.spec.apiProductRef?.name || \"unknown\"}\n </Link>\n </Typography>\n\n <Typography variant=\"caption\" className={classes.label}>\n Tier\n </Typography>\n <Box className={classes.value}>\n <Chip\n label={apiKey.spec.planTier}\n size=\"small\"\n variant=\"outlined\"\n />\n </Box>\n\n <Typography variant=\"caption\" className={classes.label}>\n Requester\n </Typography>\n <Typography variant=\"body1\" className={classes.value}>\n {apiKey.spec.requestedBy?.userId}\n </Typography>\n\n <Typography variant=\"caption\" className={classes.label}>\n Requested\n </Typography>\n <Typography variant=\"body1\" className={classes.value}>\n {apiKey.metadata.creationTimestamp\n ? new Date(\n apiKey.metadata.creationTimestamp,\n ).toLocaleDateString()\n : \"-\"}\n </Typography>\n\n {apiKey.status?.reviewedBy && (\n <>\n <Typography variant=\"caption\" className={classes.label}>\n Reviewed By\n </Typography>\n <Typography variant=\"body1\" className={classes.value}>\n {apiKey.status.reviewedBy.replace(/^user:default\\//, \"\")}\n {apiKey.status.reviewedAt && (\n <Typography variant=\"caption\" color=\"textSecondary\">\n {\" \"}\n on{\" \"}\n {new Date(\n apiKey.status.reviewedAt,\n ).toLocaleDateString()}\n </Typography>\n )}\n </Typography>\n </>\n )}\n </Box>\n </InfoCard>\n </Grid>\n\n <Grid item xs={12} md={6}>\n <InfoCard title=\"Use Case\">\n <Typography variant=\"body1\">\n {apiKey.spec.useCase || \"No use case provided\"}\n </Typography>\n </InfoCard>\n\n {phase === \"Approved\" && (\n <Box mt={2}>\n <InfoCard title=\"API Key\">\n {alreadyRead && !apiKeyValue ? (\n <Tooltip title=\"This API key has already been viewed and cannot be retrieved again\">\n <Box display=\"flex\" alignItems=\"center\">\n <Typography variant=\"body2\" color=\"textSecondary\">\n Already viewed - cannot be retrieved again\n </Typography>\n <VisibilityOffIcon\n fontSize=\"small\"\n color=\"disabled\"\n style={{ marginLeft: 8 }}\n />\n </Box>\n </Tooltip>\n ) : (\n <Box className={classes.apiKeyContainer}>\n <Typography\n variant=\"body2\"\n style={{ fontFamily: \"monospace\", flex: 1 }}\n >\n {apiKeyLoading\n ? \"Loading...\"\n : showApiKey && apiKeyValue\n ? apiKeyValue\n : \"•\".repeat(32)}\n </Typography>\n {showApiKey && apiKeyValue && (\n <Tooltip title=\"Copy to clipboard\">\n <IconButton\n size=\"small\"\n onClick={() => handleCopy(apiKeyValue)}\n >\n <FileCopyIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n )}\n <Tooltip\n title={\n showApiKey\n ? \"Hide API key\"\n : \"Reveal API key (one-time only)\"\n }\n >\n <span>\n <IconButton\n size=\"small\"\n onClick={handleRevealClick}\n disabled={\n apiKeyLoading || (alreadyRead && !apiKeyValue)\n }\n >\n {showApiKey ? (\n <VisibilityOffIcon fontSize=\"small\" />\n ) : (\n <VisibilityIcon fontSize=\"small\" />\n )}\n </IconButton>\n </span>\n </Tooltip>\n </Box>\n )}\n </InfoCard>\n </Box>\n )}\n </Grid>\n\n {phase === \"Approved\" && (\n <Grid item xs={12}>\n <InfoCard title=\"Code Examples\">\n <Box>\n <Tabs\n value={selectedTab}\n onChange={(_, newValue) => setSelectedTab(newValue)}\n indicatorColor=\"primary\"\n textColor=\"primary\"\n >\n {codeExamples.map((ex) => (\n <Tab key={ex.label} label={ex.label} />\n ))}\n </Tabs>\n <Box className={classes.tabPanel}>\n <CodeExample\n code={codeExamples[selectedTab].code}\n onCopy={() => handleCopy(codeExamples[selectedTab].code)}\n />\n </Box>\n </Box>\n </InfoCard>\n </Grid>\n )}\n\n {apiKey.status?.limits && (\n <Grid item xs={12}>\n <InfoCard title=\"Rate Limits\">\n <Grid container spacing={2}>\n {apiKey.status.limits.daily && (\n <Grid item>\n <Typography variant=\"caption\" className={classes.label}>\n Daily\n </Typography>\n <Typography variant=\"h6\">\n {apiKey.status.limits.daily.toLocaleString()}\n </Typography>\n </Grid>\n )}\n {apiKey.status.limits.weekly && (\n <Grid item>\n <Typography variant=\"caption\" className={classes.label}>\n Weekly\n </Typography>\n <Typography variant=\"h6\">\n {apiKey.status.limits.weekly.toLocaleString()}\n </Typography>\n </Grid>\n )}\n {apiKey.status.limits.monthly && (\n <Grid item>\n <Typography variant=\"caption\" className={classes.label}>\n Monthly\n </Typography>\n <Typography variant=\"h6\">\n {apiKey.status.limits.monthly.toLocaleString()}\n </Typography>\n </Grid>\n )}\n </Grid>\n </InfoCard>\n </Grid>\n )}\n </Grid>\n </Content>\n\n <Dialog\n open={showWarning}\n onClose={() => setShowWarning(false)}\n maxWidth=\"sm\"\n >\n <DialogTitle>\n <Box display=\"flex\" alignItems=\"center\">\n <WarningIcon color=\"primary\" style={{ marginRight: 8 }} />\n View API Key\n </Box>\n </DialogTitle>\n <DialogContent>\n <Typography variant=\"body1\" paragraph>\n This API key can only be viewed <strong>once</strong>. After you\n reveal it, you will not be able to retrieve it again.\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Make sure to copy and store it securely before closing this view.\n </Typography>\n </DialogContent>\n <DialogActions>\n <Button onClick={() => setShowWarning(false)}>Cancel</Button>\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={handleConfirmReveal}\n >\n Reveal API Key\n </Button>\n </DialogActions>\n </Dialog>\n </Page>\n );\n};\n"],"names":["apiProduct","data"],"mappings":"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"}
@@ -18,6 +18,7 @@ import { EditAPIKeyDialog } from '../EditAPIKeyDialog/EditAPIKeyDialog.esm.js';
18
18
  import { ConfirmDeleteDialog } from '../ConfirmDeleteDialog/ConfirmDeleteDialog.esm.js';
19
19
  import { generateAuthCodeSnippets } from '../../utils/codeSnippets.esm.js';
20
20
  import { RequestAccessDialog } from '../RequestAccessDialog/RequestAccessDialog.esm.js';
21
+ import { handleFetchError } from '../../utils/errors.esm.js';
21
22
 
22
23
  const ApiKeyManagementTab = ({
23
24
  namespace: propNamespace
@@ -66,7 +67,8 @@ const ApiKeyManagementTab = ({
66
67
  `${backendUrl}/api/kuadrant/requests/my?namespace=${namespace}`
67
68
  );
68
69
  if (!response.ok) {
69
- throw new Error("failed to fetch requests");
70
+ const error2 = await handleFetchError(response);
71
+ throw new Error(`failed to fetch requests. ${error2}`);
70
72
  }
71
73
  const data = await response.json();
72
74
  return (data.items || []).filter(
@@ -83,7 +85,8 @@ const ApiKeyManagementTab = ({
83
85
  `${backendUrl}/api/kuadrant/apiproducts`
84
86
  );
85
87
  if (!response.ok) {
86
- throw new Error("failed to fetch api products");
88
+ const error2 = await handleFetchError(response);
89
+ throw new Error(`failed to fetch api products. ${error2}`);
87
90
  }
88
91
  const data = await response.json();
89
92
  const product = data.items?.find(
@@ -121,7 +124,8 @@ const ApiKeyManagementTab = ({
121
124
  { method: "DELETE" }
122
125
  );
123
126
  if (!response.ok) {
124
- throw new Error("failed to delete request");
127
+ const error2 = await handleFetchError(response);
128
+ throw new Error(error2);
125
129
  }
126
130
  alertApi.post({
127
131
  message: "API key deleted successfully",