@kuadrant/kuadrant-backstage-plugin-frontend 0.0.2-dev-0b744dd → 0.0.2-dev-9be93a3
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.
- package/dist/api.esm.js +220 -0
- package/dist/api.esm.js.map +1 -0
- package/dist/apis.esm.js +15 -0
- package/dist/apis.esm.js.map +1 -0
- package/dist/components/ApiAccessCard/ApiAccessCard.esm.js +27 -37
- package/dist/components/ApiAccessCard/ApiAccessCard.esm.js.map +1 -1
- package/dist/components/ApiKeyApprovalPage/ApiKeyApprovalPage.esm.js +10 -0
- package/dist/components/ApiKeyApprovalPage/ApiKeyApprovalPage.esm.js.map +1 -0
- package/dist/components/ApiKeyApprovalPage/index.esm.js +2 -0
- package/dist/components/ApiKeyDetailPage/ApiKeyDetailPage.esm.js +28 -40
- package/dist/components/ApiKeyDetailPage/ApiKeyDetailPage.esm.js.map +1 -1
- package/dist/components/ApiKeyManagementTab/ApiKeyManagementTab.esm.js +20 -46
- package/dist/components/ApiKeyManagementTab/ApiKeyManagementTab.esm.js.map +1 -1
- package/dist/components/ApiProductDetailPage/ApiProductDetailPage.esm.js +27 -35
- package/dist/components/ApiProductDetailPage/ApiProductDetailPage.esm.js.map +1 -1
- package/dist/components/ApiProductDetails/ApiProductDetails.esm.js +13 -3
- package/dist/components/ApiProductDetails/ApiProductDetails.esm.js.map +1 -1
- package/dist/components/ApiProductInfoCard/ApiProductInfoCard.esm.js +5 -13
- package/dist/components/ApiProductInfoCard/ApiProductInfoCard.esm.js.map +1 -1
- package/dist/components/ApiProductOpenApiAlert/ApiProductOpenApiAlert.esm.js +7 -10
- package/dist/components/ApiProductOpenApiAlert/ApiProductOpenApiAlert.esm.js.map +1 -1
- package/dist/components/ApprovalQueueTable/ApprovalQueueTable.esm.js +34 -66
- package/dist/components/ApprovalQueueTable/ApprovalQueueTable.esm.js.map +1 -1
- package/dist/components/CreateAPIProductDialog/CreateAPIProductDialog.esm.js +143 -58
- package/dist/components/CreateAPIProductDialog/CreateAPIProductDialog.esm.js.map +1 -1
- package/dist/components/EditAPIKeyDialog/EditAPIKeyDialog.esm.js +8 -18
- package/dist/components/EditAPIKeyDialog/EditAPIKeyDialog.esm.js.map +1 -1
- package/dist/components/EditAPIProductDialog/EditAPIProductDialog.esm.js +52 -30
- package/dist/components/EditAPIProductDialog/EditAPIProductDialog.esm.js.map +1 -1
- package/dist/components/EntityApiApprovalTab/EntityApiApprovalTab.esm.js +11 -27
- package/dist/components/EntityApiApprovalTab/EntityApiApprovalTab.esm.js.map +1 -1
- package/dist/components/KuadrantPage/ApiProductsPage.esm.js +71 -55
- package/dist/components/KuadrantPage/ApiProductsPage.esm.js.map +1 -1
- package/dist/components/MyApiKeysPage/MyApiKeysPage.esm.js +10 -0
- package/dist/components/MyApiKeysPage/MyApiKeysPage.esm.js.map +1 -0
- package/dist/components/MyApiKeysPage/index.esm.js +2 -0
- package/dist/components/MyApiKeysPage/index.esm.js.map +1 -0
- package/dist/components/MyApiKeysTable/MyApiKeysTable.esm.js +51 -57
- package/dist/components/MyApiKeysTable/MyApiKeysTable.esm.js.map +1 -1
- package/dist/components/RequestAccessDialog/RequestAccessDialog.esm.js +10 -25
- package/dist/components/RequestAccessDialog/RequestAccessDialog.esm.js.map +1 -1
- package/dist/components/SimpleRequestAccessDialog/SimpleRequestAccessDialog.esm.js +206 -0
- package/dist/components/SimpleRequestAccessDialog/SimpleRequestAccessDialog.esm.js.map +1 -0
- package/dist/index.d.ts +461 -2
- package/dist/index.esm.js +3 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/plugin.esm.js +11 -4
- package/dist/plugin.esm.js.map +1 -1
- package/dist/utils/styles.esm.js +44 -5
- package/dist/utils/styles.esm.js.map +1 -1
- package/dist-scalprum/internal.plugin-kuadrant.8bf02d5482a5a3ed6337.js +2 -0
- package/dist-scalprum/internal.plugin-kuadrant.8bf02d5482a5a3ed6337.js.map +1 -0
- package/dist-scalprum/plugin-manifest.json +3 -3
- package/dist-scalprum/static/2118.82433765.chunk.js +2 -0
- package/dist-scalprum/static/2118.82433765.chunk.js.map +1 -0
- package/dist-scalprum/static/2967.28e7c7f8.chunk.js +2 -0
- package/dist-scalprum/static/2967.28e7c7f8.chunk.js.map +1 -0
- package/dist-scalprum/static/369.2374941c.chunk.js +2 -0
- package/dist-scalprum/static/369.2374941c.chunk.js.map +1 -0
- package/dist-scalprum/static/3947.ff1c25cf.chunk.js +2 -0
- package/dist-scalprum/static/3947.ff1c25cf.chunk.js.map +1 -0
- package/dist-scalprum/static/3976.cf3ec7be.chunk.js +2 -0
- package/dist-scalprum/static/3976.cf3ec7be.chunk.js.map +1 -0
- package/dist-scalprum/static/4447.222bb58d.chunk.js +2 -0
- package/dist-scalprum/static/4447.222bb58d.chunk.js.map +1 -0
- package/dist-scalprum/static/5010.4ef96c87.chunk.js +3 -0
- package/dist-scalprum/static/5010.4ef96c87.chunk.js.map +1 -0
- package/dist-scalprum/static/5203.e92a3353.chunk.js +2 -0
- package/dist-scalprum/static/5203.e92a3353.chunk.js.map +1 -0
- package/dist-scalprum/static/6371.6ee1f11d.chunk.js +2 -0
- package/dist-scalprum/static/6371.6ee1f11d.chunk.js.map +1 -0
- package/dist-scalprum/static/6422.969d9b8c.chunk.js +2 -0
- package/dist-scalprum/static/6422.969d9b8c.chunk.js.map +1 -0
- package/dist-scalprum/static/6800.a7645f4c.chunk.js +2 -0
- package/dist-scalprum/static/6800.a7645f4c.chunk.js.map +1 -0
- package/dist-scalprum/static/69.1decc5e8.chunk.js +2 -0
- package/dist-scalprum/static/69.1decc5e8.chunk.js.map +1 -0
- package/dist-scalprum/static/7005.a9f73153.chunk.js +2 -0
- package/dist-scalprum/static/7005.a9f73153.chunk.js.map +1 -0
- package/dist-scalprum/static/7270.b0e185f1.chunk.js +2 -0
- package/dist-scalprum/static/7270.b0e185f1.chunk.js.map +1 -0
- package/dist-scalprum/static/7791.5c1eea8a.chunk.js +2 -0
- package/dist-scalprum/static/7791.5c1eea8a.chunk.js.map +1 -0
- package/dist-scalprum/static/{6763.d6cd937f.chunk.js → 8563.46f1a3e1.chunk.js} +3 -3
- package/dist-scalprum/static/8563.46f1a3e1.chunk.js.map +1 -0
- package/dist-scalprum/static/8789.84963cbc.chunk.js +2 -0
- package/dist-scalprum/static/8789.84963cbc.chunk.js.map +1 -0
- package/dist-scalprum/static/8804.63919453.chunk.js +2 -0
- package/dist-scalprum/static/8804.63919453.chunk.js.map +1 -0
- package/dist-scalprum/static/9051.db875198.chunk.js +2 -0
- package/dist-scalprum/static/9051.db875198.chunk.js.map +1 -0
- package/dist-scalprum/static/{2946.a35243f1.chunk.js → 9370.2e9fe34b.chunk.js} +3 -3
- package/dist-scalprum/static/9370.2e9fe34b.chunk.js.map +1 -0
- package/dist-scalprum/static/9838.5df9b1de.chunk.js +2 -0
- package/dist-scalprum/static/9838.5df9b1de.chunk.js.map +1 -0
- package/dist-scalprum/static/exposed-PluginRoot.8a8dd91f.chunk.js +2 -0
- package/dist-scalprum/static/exposed-PluginRoot.8a8dd91f.chunk.js.map +1 -0
- package/package.json +3 -1
- package/dist/components/ApiKeysPage/ApiKeysPage.esm.js +0 -43
- package/dist/components/ApiKeysPage/ApiKeysPage.esm.js.map +0 -1
- package/dist/components/ApiKeysPage/index.esm.js +0 -2
- package/dist-scalprum/internal.plugin-kuadrant.114cbbe1d3ddb939d776.js +0 -2
- package/dist-scalprum/internal.plugin-kuadrant.114cbbe1d3ddb939d776.js.map +0 -1
- package/dist-scalprum/static/2821.0829f14d.chunk.js +0 -2
- package/dist-scalprum/static/2821.0829f14d.chunk.js.map +0 -1
- package/dist-scalprum/static/2946.a35243f1.chunk.js.map +0 -1
- package/dist-scalprum/static/2967.65c51af8.chunk.js +0 -2
- package/dist-scalprum/static/2967.65c51af8.chunk.js.map +0 -1
- package/dist-scalprum/static/3650.ee76eba9.chunk.js +0 -2
- package/dist-scalprum/static/3650.ee76eba9.chunk.js.map +0 -1
- package/dist-scalprum/static/3947.7458971d.chunk.js +0 -2
- package/dist-scalprum/static/3947.7458971d.chunk.js.map +0 -1
- package/dist-scalprum/static/3984.647ef00c.chunk.js +0 -2
- package/dist-scalprum/static/3984.647ef00c.chunk.js.map +0 -1
- package/dist-scalprum/static/4651.c85cecc4.chunk.js +0 -2
- package/dist-scalprum/static/4651.c85cecc4.chunk.js.map +0 -1
- package/dist-scalprum/static/4682.75f17114.chunk.js +0 -2
- package/dist-scalprum/static/4682.75f17114.chunk.js.map +0 -1
- package/dist-scalprum/static/5010.0cd6c959.chunk.js +0 -3
- package/dist-scalprum/static/5010.0cd6c959.chunk.js.map +0 -1
- package/dist-scalprum/static/5203.b654e8e0.chunk.js +0 -2
- package/dist-scalprum/static/5203.b654e8e0.chunk.js.map +0 -1
- package/dist-scalprum/static/5453.ecdee66d.chunk.js +0 -2
- package/dist-scalprum/static/5453.ecdee66d.chunk.js.map +0 -1
- package/dist-scalprum/static/6371.d45f37cc.chunk.js +0 -2
- package/dist-scalprum/static/6371.d45f37cc.chunk.js.map +0 -1
- package/dist-scalprum/static/6763.d6cd937f.chunk.js.map +0 -1
- package/dist-scalprum/static/6800.20f46859.chunk.js +0 -2
- package/dist-scalprum/static/6800.20f46859.chunk.js.map +0 -1
- package/dist-scalprum/static/6840.1653e6b0.chunk.js +0 -2
- package/dist-scalprum/static/6840.1653e6b0.chunk.js.map +0 -1
- package/dist-scalprum/static/7236.f3886d59.chunk.js +0 -2
- package/dist-scalprum/static/7236.f3886d59.chunk.js.map +0 -1
- package/dist-scalprum/static/7791.ac1ac509.chunk.js +0 -2
- package/dist-scalprum/static/7791.ac1ac509.chunk.js.map +0 -1
- package/dist-scalprum/static/8172.cbe1f2c4.chunk.js +0 -2
- package/dist-scalprum/static/8172.cbe1f2c4.chunk.js.map +0 -1
- package/dist-scalprum/static/8799.939d14f9.chunk.js +0 -2
- package/dist-scalprum/static/8799.939d14f9.chunk.js.map +0 -1
- package/dist-scalprum/static/exposed-PluginRoot.ed95fa78.chunk.js +0 -2
- package/dist-scalprum/static/exposed-PluginRoot.ed95fa78.chunk.js.map +0 -1
- /package/dist/components/{ApiKeysPage → ApiKeyApprovalPage}/index.esm.js.map +0 -0
- /package/dist-scalprum/static/{5010.0cd6c959.chunk.js.LICENSE.txt → 5010.4ef96c87.chunk.js.LICENSE.txt} +0 -0
- /package/dist-scalprum/static/{6763.d6cd937f.chunk.js.LICENSE.txt → 8563.46f1a3e1.chunk.js.LICENSE.txt} +0 -0
- /package/dist-scalprum/static/{2946.a35243f1.chunk.js.LICENSE.txt → 9370.2e9fe34b.chunk.js.LICENSE.txt} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
2
|
import { useParams } from 'react-router-dom';
|
|
3
|
-
import { useApi,
|
|
3
|
+
import { useApi, alertApiRef } from '@backstage/core-plugin-api';
|
|
4
|
+
import { kuadrantApiRef } from '../../api.esm.js';
|
|
4
5
|
import { useAsync } from 'react-use';
|
|
5
6
|
import { Progress, ResponseErrorPanel, Page, Header, Link, Content, Breadcrumbs, InfoCard } from '@backstage/core-components';
|
|
6
7
|
import { makeStyles, Button, Box, Typography, Grid, Chip, Tooltip, IconButton, Tabs, Tab, Dialog, DialogTitle, DialogContent, DialogActions } from '@material-ui/core';
|
|
@@ -11,7 +12,7 @@ import WarningIcon from '@material-ui/icons/Warning';
|
|
|
11
12
|
import ArrowBackIcon from '@material-ui/icons/ArrowBack';
|
|
12
13
|
import OpenInNewIcon from '@material-ui/icons/OpenInNew';
|
|
13
14
|
import EmailIcon from '@material-ui/icons/Email';
|
|
14
|
-
import {
|
|
15
|
+
import { getApprovalQueueStatusChipStyle } from '../../utils/styles.esm.js';
|
|
15
16
|
|
|
16
17
|
const useStyles = makeStyles((theme) => ({
|
|
17
18
|
label: {
|
|
@@ -63,10 +64,8 @@ const CodeExample = ({
|
|
|
63
64
|
const ApiKeyDetailPage = () => {
|
|
64
65
|
const classes = useStyles();
|
|
65
66
|
const { namespace, name } = useParams();
|
|
66
|
-
const
|
|
67
|
-
const fetchApi = useApi(fetchApiRef);
|
|
67
|
+
const kuadrantApi = useApi(kuadrantApiRef);
|
|
68
68
|
const alertApi = useApi(alertApiRef);
|
|
69
|
-
const backendUrl = config.getString("backend.baseUrl");
|
|
70
69
|
const [selectedTab, setSelectedTab] = useState(0);
|
|
71
70
|
const [showApiKey, setShowApiKey] = useState(false);
|
|
72
71
|
const [apiKeyValue, setApiKeyValue] = useState(null);
|
|
@@ -78,55 +77,44 @@ const ApiKeyDetailPage = () => {
|
|
|
78
77
|
loading,
|
|
79
78
|
error
|
|
80
79
|
} = useAsync(async () => {
|
|
81
|
-
const [
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
const [apiKeyData, productsData] = await Promise.all([
|
|
81
|
+
kuadrantApi.getApiKey(namespace, name),
|
|
82
|
+
kuadrantApi.getApiProducts()
|
|
84
83
|
]);
|
|
85
|
-
if (!apiKeyResponse.ok) {
|
|
86
|
-
throw new Error("Failed to fetch API key");
|
|
87
|
-
}
|
|
88
|
-
const apiKeyData = await apiKeyResponse.json();
|
|
89
84
|
if (apiKeyData.status?.canReadSecret === false) {
|
|
90
85
|
setAlreadyRead(true);
|
|
91
86
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
apiProduct2 = (productsData.items || []).find(
|
|
96
|
-
(p) => p.metadata.name === apiKeyData.spec.apiProductRef?.name && p.metadata.namespace === apiKeyData.metadata.namespace
|
|
97
|
-
);
|
|
98
|
-
}
|
|
87
|
+
const apiProduct2 = (productsData.items || []).find(
|
|
88
|
+
(p) => p.metadata.name === apiKeyData.spec.apiProductRef?.name && p.metadata.namespace === apiKeyData.metadata.namespace
|
|
89
|
+
);
|
|
99
90
|
return { apiKey: apiKeyData, apiProduct: apiProduct2 };
|
|
100
|
-
}, [namespace, name,
|
|
91
|
+
}, [namespace, name, kuadrantApi]);
|
|
101
92
|
const apiKey = data?.apiKey;
|
|
102
93
|
const apiProduct = data?.apiProduct;
|
|
103
94
|
const fetchApiKeySecret = async () => {
|
|
104
95
|
setApiKeyLoading(true);
|
|
105
96
|
try {
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
} else if (response.status === 403) {
|
|
97
|
+
const extractedSecret = await kuadrantApi.getApiKeySecret(namespace, name);
|
|
98
|
+
setApiKeyValue(extractedSecret.apiKey);
|
|
99
|
+
setAlreadyRead(true);
|
|
100
|
+
setShowApiKey(true);
|
|
101
|
+
} catch (err) {
|
|
102
|
+
console.error("Failed to fetch API key:", err);
|
|
103
|
+
const errorMessage = err instanceof Error ? err.message : "unknown error occurred";
|
|
104
|
+
if (errorMessage.includes("403") || errorMessage.includes("already been viewed")) {
|
|
115
105
|
setAlreadyRead(true);
|
|
116
106
|
alertApi.post({
|
|
117
107
|
message: "This API key has already been viewed and cannot be retrieved again.",
|
|
118
108
|
severity: "warning",
|
|
119
109
|
display: "transient"
|
|
120
110
|
});
|
|
111
|
+
} else {
|
|
112
|
+
alertApi.post({
|
|
113
|
+
message: `Failed to fetch APIKey. ${errorMessage}`,
|
|
114
|
+
severity: "error",
|
|
115
|
+
display: "transient"
|
|
116
|
+
});
|
|
121
117
|
}
|
|
122
|
-
} catch (err) {
|
|
123
|
-
console.error("Failed to fetch API key:", err);
|
|
124
|
-
const errorMessage = err instanceof Error ? err.message : "unknown error occurred";
|
|
125
|
-
alertApi.post({
|
|
126
|
-
message: `Failed to fetch APIKey. ${errorMessage}`,
|
|
127
|
-
severity: "error",
|
|
128
|
-
display: "transient"
|
|
129
|
-
});
|
|
130
118
|
} finally {
|
|
131
119
|
setApiKeyLoading(false);
|
|
132
120
|
}
|
|
@@ -201,8 +189,8 @@ func main() {
|
|
|
201
189
|
title: apiKey.metadata.name,
|
|
202
190
|
subtitle: `API Key for ${apiKey.spec.apiProductRef?.name || "unknown"}`
|
|
203
191
|
},
|
|
204
|
-
/* @__PURE__ */ React.createElement(Link, { to: "/kuadrant/api-keys" }, /* @__PURE__ */ React.createElement(Button, { startIcon: /* @__PURE__ */ React.createElement(ArrowBackIcon, null) }, "Back to API Keys"))
|
|
205
|
-
), /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(Box, { mb: 2 }, /* @__PURE__ */ React.createElement(Breadcrumbs, { "aria-label": "breadcrumb" }, /* @__PURE__ */ React.createElement(Link, { to: "/kuadrant/api-keys" }, "API keys"), /* @__PURE__ */ React.createElement(Typography, null, apiKey.metadata.name))), /* @__PURE__ */ React.createElement(Box, { mb: 3, display: "flex", style: { gap: 8 } }, /* @__PURE__ */ React.createElement(Link, { to: `/catalog/default/api/${apiKey.spec.apiProductRef?.name}` }, /* @__PURE__ */ React.createElement(
|
|
192
|
+
/* @__PURE__ */ React.createElement(Link, { to: "/kuadrant/my-api-keys" }, /* @__PURE__ */ React.createElement(Button, { startIcon: /* @__PURE__ */ React.createElement(ArrowBackIcon, null) }, "Back to API Keys"))
|
|
193
|
+
), /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(Box, { mb: 2 }, /* @__PURE__ */ React.createElement(Breadcrumbs, { "aria-label": "breadcrumb" }, /* @__PURE__ */ React.createElement(Link, { to: "/kuadrant/my-api-keys" }, "API keys"), /* @__PURE__ */ React.createElement(Typography, null, apiKey.metadata.name))), /* @__PURE__ */ React.createElement(Box, { mb: 3, display: "flex", style: { gap: 8 } }, /* @__PURE__ */ React.createElement(Link, { to: `/catalog/default/api/${apiKey.spec.apiProductRef?.name}` }, /* @__PURE__ */ React.createElement(
|
|
206
194
|
Button,
|
|
207
195
|
{
|
|
208
196
|
variant: "outlined",
|
|
@@ -225,7 +213,7 @@ func main() {
|
|
|
225
213
|
{
|
|
226
214
|
label: statusLabel,
|
|
227
215
|
size: "small",
|
|
228
|
-
style:
|
|
216
|
+
style: getApprovalQueueStatusChipStyle(phase),
|
|
229
217
|
"data-testid": "api-key-status-chip"
|
|
230
218
|
}
|
|
231
219
|
)), /* @__PURE__ */ React.createElement(Typography, { variant: "caption", className: classes.label }, "API Product"), /* @__PURE__ */ React.createElement(Typography, { variant: "body1", className: classes.value }, /* @__PURE__ */ React.createElement(
|
|
@@ -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 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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"}
|
|
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 alertApiRef,\n} from \"@backstage/core-plugin-api\";\nimport { kuadrantApiRef } from '../../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 { getApprovalQueueStatusChipStyle } 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 kuadrantApi = useApi(kuadrantApiRef);\n const alertApi = useApi(alertApiRef);\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 [apiKeyData, productsData] = await Promise.all([\n kuadrantApi.getApiKey(namespace!, name!),\n kuadrantApi.getApiProducts(),\n ]);\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 const 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 return { apiKey: apiKeyData as APIKey, apiProduct };\n }, [namespace, name, kuadrantApi]);\n\n const apiKey = data?.apiKey;\n const apiProduct = data?.apiProduct;\n\n const fetchApiKeySecret = async () => {\n setApiKeyLoading(true);\n try {\n const extractedSecret = await kuadrantApi.getApiKeySecret(namespace!, name!);\n setApiKeyValue(extractedSecret.apiKey);\n setAlreadyRead(true);\n setShowApiKey(true);\n } catch (err) {\n console.error(\"Failed to fetch API key:\", err);\n const errorMessage = err instanceof Error ? err.message : \"unknown error occurred\";\n if (errorMessage.includes(\"403\") || errorMessage.includes(\"already been viewed\")) {\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 } else {\n alertApi.post({\n message: `Failed to fetch APIKey. ${errorMessage}`,\n severity: 'error',\n display: 'transient',\n });\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/my-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/my-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={getApprovalQueueStatusChipStyle(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"],"mappings":";;;;;;;;;;;;;;;;AA4CA,MAAM,SAAA,GAAY,UAAW,CAAA,CAAC,KAAW,MAAA;AAAA,EACvC,KAAO,EAAA;AAAA,IACL,UAAY,EAAA,GAAA;AAAA,IACZ,KAAA,EAAO,KAAM,CAAA,OAAA,CAAQ,IAAK,CAAA,SAAA;AAAA,IAC1B,YAAA,EAAc,KAAM,CAAA,OAAA,CAAQ,GAAG;AAAA,GACjC;AAAA,EACA,KAAO,EAAA;AAAA,IACL,YAAA,EAAc,KAAM,CAAA,OAAA,CAAQ,CAAC;AAAA,GAC/B;AAAA,EACA,SAAW,EAAA;AAAA,IACT,eAAA,EAAiB,KAAM,CAAA,OAAA,CAAQ,UAAW,CAAA,OAAA;AAAA,IAC1C,OAAA,EAAS,KAAM,CAAA,OAAA,CAAQ,CAAC,CAAA;AAAA,IACxB,YAAA,EAAc,MAAM,KAAM,CAAA,YAAA;AAAA,IAC1B,UAAY,EAAA,WAAA;AAAA,IACZ,QAAU,EAAA,UAAA;AAAA,IACV,QAAU,EAAA,MAAA;AAAA,IACV,UAAY,EAAA,UAAA;AAAA,IACZ,SAAW,EAAA;AAAA,GACb;AAAA,EACA,eAAiB,EAAA;AAAA,IACf,OAAS,EAAA,MAAA;AAAA,IACT,UAAY,EAAA,QAAA;AAAA,IACZ,GAAA,EAAK,KAAM,CAAA,OAAA,CAAQ,CAAC,CAAA;AAAA,IACpB,OAAA,EAAS,KAAM,CAAA,OAAA,CAAQ,GAAG,CAAA;AAAA,IAC1B,eAAA,EAAiB,KAAM,CAAA,OAAA,CAAQ,UAAW,CAAA,OAAA;AAAA,IAC1C,YAAA,EAAc,MAAM,KAAM,CAAA,YAAA;AAAA,IAC1B,UAAY,EAAA;AAAA,GACd;AAAA,EACA,QAAU,EAAA;AAAA,IACR,SAAA,EAAW,KAAM,CAAA,OAAA,CAAQ,CAAC;AAAA;AAE9B,CAAE,CAAA,CAAA;AAEF,MAAM,cAAc,CAAC;AAAA,EACnB,IAAA;AAAA,EACA;AACF,CAGM,KAAA;AACJ,EAAA,MAAM,UAAU,SAAU,EAAA;AAE1B,EAAA,uBACG,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAI,QAAS,EAAA,UAAA,EAAA,sCACX,GAAI,EAAA,EAAA,SAAA,EAAW,OAAQ,CAAA,SAAA,EAAA,EAAY,IAAK,CAAA,kBACxC,KAAA,CAAA,aAAA,CAAA,OAAA,EAAA,EAAQ,OAAM,WACb,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,IAAK,EAAA,OAAA;AAAA,MACL,OAAO,EAAE,QAAA,EAAU,YAAY,GAAK,EAAA,CAAA,EAAG,OAAO,CAAE,EAAA;AAAA,MAChD,OAAS,EAAA;AAAA,KAAA;AAAA,oBAET,KAAA,CAAA,aAAA,CAAC,YAAa,EAAA,EAAA,QAAA,EAAS,OAAQ,EAAA;AAAA,GAEnC,CACF,CAAA;AAEJ,CAAA;AAEO,MAAM,mBAAmB,MAAM;AACpC,EAAA,MAAM,UAAU,SAAU,EAAA;AAC1B,EAAA,MAAM,EAAE,SAAA,EAAW,IAAK,EAAA,GAAI,SAA+C,EAAA;AAC3E,EAAM,MAAA,WAAA,GAAc,OAAO,cAAc,CAAA;AACzC,EAAM,MAAA,QAAA,GAAW,OAAO,WAAW,CAAA;AAEnC,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAAS,CAAC,CAAA;AAChD,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,SAAS,KAAK,CAAA;AAClD,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAAwB,IAAI,CAAA;AAClE,EAAA,MAAM,CAAC,aAAA,EAAe,gBAAgB,CAAA,GAAI,SAAS,KAAK,CAAA;AACxD,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAAS,KAAK,CAAA;AACpD,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAAS,KAAK,CAAA;AAEpD,EAAM,MAAA;AAAA,IACJ,KAAO,EAAA,IAAA;AAAA,IACP,OAAA;AAAA,IACA;AAAA,GACF,GAAI,SAAS,YAAY;AACvB,IAAA,MAAM,CAAC,UAAY,EAAA,YAAY,CAAI,GAAA,MAAM,QAAQ,GAAI,CAAA;AAAA,MACnD,WAAA,CAAY,SAAU,CAAA,SAAA,EAAY,IAAK,CAAA;AAAA,MACvC,YAAY,cAAe;AAAA,KAC5B,CAAA;AAGD,IAAI,IAAA,UAAA,CAAW,MAAQ,EAAA,aAAA,KAAkB,KAAO,EAAA;AAC9C,MAAA,cAAA,CAAe,IAAI,CAAA;AAAA;AAIrB,IAAA,MAAMA,WAAc,GAAA,CAAA,YAAA,CAAa,KAAS,IAAA,EAAI,EAAA,IAAA;AAAA,MAC5C,CAAC,CAAA,KACC,CAAE,CAAA,QAAA,CAAS,IAAS,KAAA,UAAA,CAAW,IAAK,CAAA,aAAA,EAAe,IACnD,IAAA,CAAA,CAAE,QAAS,CAAA,SAAA,KAAc,WAAW,QAAS,CAAA;AAAA,KACjD;AAEA,IAAA,OAAO,EAAE,MAAA,EAAQ,UAAsB,EAAA,UAAA,EAAAA,WAAW,EAAA;AAAA,GACjD,EAAA,CAAC,SAAW,EAAA,IAAA,EAAM,WAAW,CAAC,CAAA;AAEjC,EAAA,MAAM,SAAS,IAAM,EAAA,MAAA;AACrB,EAAA,MAAM,aAAa,IAAM,EAAA,UAAA;AAEzB,EAAA,MAAM,oBAAoB,YAAY;AACpC,IAAA,gBAAA,CAAiB,IAAI,CAAA;AACrB,IAAI,IAAA;AACF,MAAA,MAAM,eAAkB,GAAA,MAAM,WAAY,CAAA,eAAA,CAAgB,WAAY,IAAK,CAAA;AAC3E,MAAA,cAAA,CAAe,gBAAgB,MAAM,CAAA;AACrC,MAAA,cAAA,CAAe,IAAI,CAAA;AACnB,MAAA,aAAA,CAAc,IAAI,CAAA;AAAA,aACX,GAAK,EAAA;AACZ,MAAQ,OAAA,CAAA,KAAA,CAAM,4BAA4B,GAAG,CAAA;AAC7C,MAAA,MAAM,YAAe,GAAA,GAAA,YAAe,KAAQ,GAAA,GAAA,CAAI,OAAU,GAAA,wBAAA;AAC1D,MAAA,IAAI,aAAa,QAAS,CAAA,KAAK,KAAK,YAAa,CAAA,QAAA,CAAS,qBAAqB,CAAG,EAAA;AAChF,QAAA,cAAA,CAAe,IAAI,CAAA;AACnB,QAAA,QAAA,CAAS,IAAK,CAAA;AAAA,UACZ,OACE,EAAA,qEAAA;AAAA,UACF,QAAU,EAAA,SAAA;AAAA,UACV,OAAS,EAAA;AAAA,SACV,CAAA;AAAA,OACI,MAAA;AACL,QAAA,QAAA,CAAS,IAAK,CAAA;AAAA,UACZ,OAAA,EAAS,2BAA2B,YAAY,CAAA,CAAA;AAAA,UAChD,QAAU,EAAA,OAAA;AAAA,UACV,OAAS,EAAA;AAAA,SACV,CAAA;AAAA;AACH,KACA,SAAA;AACA,MAAA,gBAAA,CAAiB,KAAK,CAAA;AAAA;AACxB,GACF;AAEA,EAAA,MAAM,oBAAoB,MAAM;AAC9B,IAAA,IAAI,UAAY,EAAA;AACd,MAAA,aAAA,CAAc,KAAK,CAAA;AACnB,MAAA,cAAA,CAAe,IAAI,CAAA;AAAA,KACrB,MAAA,IAAW,CAAC,WAAa,EAAA;AACvB,MAAA,cAAA,CAAe,IAAI,CAAA;AAAA;AACrB,GACF;AAEA,EAAA,MAAM,sBAAsB,MAAM;AAChC,IAAA,cAAA,CAAe,KAAK,CAAA;AACpB,IAAkB,iBAAA,EAAA;AAAA,GACpB;AAEA,EAAM,MAAA,UAAA,GAAa,OAAO,IAAiB,KAAA;AACzC,IAAM,MAAA,SAAA,CAAU,SAAU,CAAA,SAAA,CAAU,IAAI,CAAA;AACxC,IAAA,QAAA,CAAS,IAAK,CAAA;AAAA,MACZ,OAAS,EAAA,qBAAA;AAAA,MACT,QAAU,EAAA,SAAA;AAAA,MACV,OAAS,EAAA;AAAA,KACV,CAAA;AAAA,GACH;AAEA,EAAA,IAAI,OAAS,EAAA;AACX,IAAA,2CAAQ,QAAS,EAAA,IAAA,CAAA;AAAA;AAGnB,EAAI,IAAA,KAAA,IAAS,CAAC,MAAQ,EAAA;AACpB,IAAA,2CACG,kBAAmB,EAAA,EAAA,KAAA,EAAO,SAAS,IAAI,KAAA,CAAM,mBAAmB,CAAG,EAAA,CAAA;AAAA;AAIxE,EAAM,MAAA,KAAA,GAAQ,MAAO,CAAA,MAAA,EAAQ,KAAS,IAAA,SAAA;AACtC,EAAM,MAAA,WAAA,GAAc,KAAU,KAAA,UAAA,GAAa,QAAW,GAAA,KAAA;AACtD,EAAM,MAAA,QAAA,GAAW,MAAO,CAAA,MAAA,EAAQ,WAAe,IAAA,iBAAA;AAC/C,EAAA,MAAM,gBAAgB,WAAe,IAAA,gBAAA;AAGrC,EAAM,MAAA,WAAA,GAAc,kCAAkC,aAAa,CAAA;AAAA,UAAA,EACzD,QAAQ,CAAA,CAAA,CAAA;AAElB,EAAM,MAAA,WAAA,GAAc,yCAAyC,QAAQ,CAAA;AAAA;AAAA,6BAAA,EAExC,aAAa,CAAA;AAAA;AAAA;AAAA,mCAAA,CAAA;AAK1C,EAAA,MAAM,aAAgB,GAAA,CAAA;;AAAA;AAAA,aAAA,EAGT,QAAQ,CAAA;AAAA,sCAAA,EACiB,aAAa,CAAA;AAAA;AAAA,sBAAA,CAAA;AAInD,EAAA,MAAM,SAAY,GAAA,CAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,8CAAA,EAQ4B,QAAQ,CAAA;AAAA,4CAAA,EACV,aAAa,CAAA;AAAA;AAAA;AAAA,CAAA,CAAA;AAKzD,EAAA,MAAM,YAAe,GAAA;AAAA,IACnB,EAAE,KAAA,EAAO,MAAQ,EAAA,IAAA,EAAM,WAAY,EAAA;AAAA,IACnC,EAAE,KAAA,EAAO,SAAW,EAAA,IAAA,EAAM,WAAY,EAAA;AAAA,IACtC,EAAE,KAAA,EAAO,QAAU,EAAA,IAAA,EAAM,aAAc,EAAA;AAAA,IACvC,EAAE,KAAA,EAAO,IAAM,EAAA,IAAA,EAAM,SAAU;AAAA,GACjC;AAEA,EACE,uBAAA,KAAA,CAAA,aAAA,CAAC,IAAK,EAAA,EAAA,OAAA,EAAQ,MACZ,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,OAAO,QAAS,CAAA,IAAA;AAAA,MACvB,UAAU,CAAe,YAAA,EAAA,MAAA,CAAO,IAAK,CAAA,aAAA,EAAe,QAAQ,SAAS,CAAA;AAAA,KAAA;AAAA,oBAErE,KAAA,CAAA,aAAA,CAAC,IAAK,EAAA,EAAA,EAAA,EAAG,uBACP,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,MAAO,EAAA,EAAA,SAAA,kBAAY,KAAA,CAAA,aAAA,CAAA,aAAA,EAAA,IAAc,CAAI,EAAA,EAAA,kBAAgB,CACxD;AAAA,GACF,sCACC,OACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,OAAI,EAAI,EAAA,CAAA,EAAA,sCACN,WAAY,EAAA,EAAA,YAAA,EAAW,gCACrB,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,IAAG,uBAAwB,EAAA,EAAA,UAAQ,mBACxC,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,IAAA,EAAY,OAAO,QAAS,CAAA,IAAK,CACpC,CACF,CAAA,sCAEC,GAAI,EAAA,EAAA,EAAA,EAAI,GAAG,OAAQ,EAAA,MAAA,EAAO,OAAO,EAAE,GAAA,EAAK,GACvC,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,QAAK,EAAI,EAAA,CAAA,qBAAA,EAAwB,OAAO,IAAK,CAAA,aAAA,EAAe,IAAI,CAC/D,CAAA,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,OAAQ,EAAA,UAAA;AAAA,MACR,SAAA,sCAAY,aAAc,EAAA,IAAA,CAAA;AAAA,MAC1B,aAAY,EAAA;AAAA,KAAA;AAAA,IACb;AAAA,GAGH,CACC,EAAA,UAAA,EAAY,IAAM,EAAA,OAAA,KAChB,WAAW,IAAK,CAAA,OAAA,CAAQ,KACvB,IAAA,UAAA,CAAW,KAAK,OAAQ,CAAA,GAAA,IACxB,UAAW,CAAA,IAAA,CAAK,QAAQ,KACxB,CAAA,oBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,OAAQ,EAAA,UAAA;AAAA,MACR,SAAA,sCAAY,SAAU,EAAA,IAAA,CAAA;AAAA,MACtB,IAAA,EACE,WAAW,IAAK,CAAA,OAAA,CAAQ,QACpB,CAAU,OAAA,EAAA,UAAA,CAAW,IAAK,CAAA,OAAA,CAAQ,KAAK,CAAA,CAAA,GACvC,WAAW,IAAK,CAAA,OAAA,CAAQ,QACtB,UAAW,CAAA,IAAA,CAAK,QAAQ,KACxB,GAAA,UAAA,CAAW,IAAK,CAAA,OAAA,CAAQ,GAAO,IAAA,GAAA;AAAA,MAEvC,MAAO,EAAA,QAAA;AAAA,MACP,GAAI,EAAA;AAAA,KAAA;AAAA,IACL;AAAA,GAIP,CAAA,kBAEC,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,WAAS,IAAC,EAAA,OAAA,EAAS,CACvB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,QAAK,IAAI,EAAA,IAAA,EAAC,EAAI,EAAA,EAAA,EAAI,IAAI,CACrB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,QAAS,EAAA,EAAA,KAAA,EAAM,qCACb,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,IAAA,kBACE,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,SAAQ,SAAU,EAAA,SAAA,EAAW,OAAQ,CAAA,KAAA,EAAA,EAAO,QAExD,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,GAAI,EAAA,EAAA,SAAA,EAAW,QAAQ,KACtB,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACC,KAAO,EAAA,WAAA;AAAA,MACP,IAAK,EAAA,OAAA;AAAA,MACL,KAAA,EAAO,gCAAgC,KAAK,CAAA;AAAA,MAC5C,aAAY,EAAA;AAAA;AAAA,GAEhB,CAEA,kBAAA,KAAA,CAAA,aAAA,CAAC,UAAW,EAAA,EAAA,OAAA,EAAQ,WAAU,SAAW,EAAA,OAAA,CAAQ,KAAO,EAAA,EAAA,aAExD,mBACC,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,SAAQ,OAAQ,EAAA,SAAA,EAAW,QAAQ,KAC7C,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACC,EAAI,EAAA,CAAA,qBAAA,EAAwB,MAAO,CAAA,IAAA,CAAK,eAAe,IAAI,CAAA,SAAA;AAAA,KAAA;AAAA,IAE1D,MAAA,CAAO,IAAK,CAAA,aAAA,EAAe,IAAQ,IAAA;AAAA,GAExC,CAAA,kBAEC,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,SAAQ,SAAU,EAAA,SAAA,EAAW,OAAQ,CAAA,KAAA,EAAA,EAAO,MAExD,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,GAAI,EAAA,EAAA,SAAA,EAAW,QAAQ,KACtB,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,OAAO,IAAK,CAAA,QAAA;AAAA,MACnB,IAAK,EAAA,OAAA;AAAA,MACL,OAAQ,EAAA;AAAA;AAAA,GAEZ,CAEA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,OAAQ,EAAA,SAAA,EAAU,WAAW,OAAQ,CAAA,KAAA,EAAA,EAAO,WAExD,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,OAAQ,EAAA,OAAA,EAAQ,WAAW,OAAQ,CAAA,KAAA,EAAA,EAC5C,OAAO,IAAK,CAAA,WAAA,EAAa,MAC5B,CAAA,sCAEC,UAAW,EAAA,EAAA,OAAA,EAAQ,WAAU,SAAW,EAAA,OAAA,CAAQ,SAAO,WAExD,CAAA,sCACC,UAAW,EAAA,EAAA,OAAA,EAAQ,SAAQ,SAAW,EAAA,OAAA,CAAQ,SAC5C,MAAO,CAAA,QAAA,CAAS,oBACb,IAAI,IAAA;AAAA,IACF,OAAO,QAAS,CAAA;AAAA,GAClB,CAAE,oBACF,GAAA,GACN,GAEC,MAAO,CAAA,MAAA,EAAQ,8BAEZ,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,OAAQ,EAAA,SAAA,EAAU,WAAW,OAAQ,CAAA,KAAA,EAAA,EAAO,aAExD,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,OAAQ,EAAA,OAAA,EAAQ,WAAW,OAAQ,CAAA,KAAA,EAAA,EAC5C,OAAO,MAAO,CAAA,UAAA,CAAW,QAAQ,iBAAmB,EAAA,EAAE,GACtD,MAAO,CAAA,MAAA,CAAO,8BACZ,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,SAAQ,SAAU,EAAA,KAAA,EAAM,mBACjC,GAAI,EAAA,IAAA,EACF,KACF,IAAI,IAAA;AAAA,IACH,OAAO,MAAO,CAAA;AAAA,GACd,CAAA,kBAAA,EACJ,CAEJ,CACF,CAEJ,CACF,CACF,CAEA,kBAAA,KAAA,CAAA,aAAA,CAAC,IAAK,EAAA,EAAA,IAAA,EAAI,IAAC,EAAA,EAAA,EAAI,EAAI,EAAA,EAAA,EAAI,CACrB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,QAAS,EAAA,EAAA,KAAA,EAAM,UACd,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,UAAW,EAAA,EAAA,OAAA,EAAQ,OACjB,EAAA,EAAA,MAAA,CAAO,IAAK,CAAA,OAAA,IAAW,sBAC1B,CACF,CAEC,EAAA,KAAA,KAAU,UACT,oBAAA,KAAA,CAAA,aAAA,CAAC,GAAI,EAAA,EAAA,EAAA,EAAI,CACP,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,QAAS,EAAA,EAAA,KAAA,EAAM,SACb,EAAA,EAAA,WAAA,IAAe,CAAC,WAAA,mBACd,KAAA,CAAA,aAAA,CAAA,OAAA,EAAA,EAAQ,KAAM,EAAA,oEAAA,EAAA,kBACZ,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAI,OAAQ,EAAA,MAAA,EAAO,UAAW,EAAA,QAAA,EAAA,kBAC5B,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,OAAQ,EAAA,OAAA,EAAQ,KAAM,EAAA,eAAA,EAAA,EAAgB,4CAElD,CACA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,iBAAA;AAAA,IAAA;AAAA,MACC,QAAS,EAAA,OAAA;AAAA,MACT,KAAM,EAAA,UAAA;AAAA,MACN,KAAA,EAAO,EAAE,UAAA,EAAY,CAAE;AAAA;AAAA,GAE3B,CACF,CAAA,uCAEC,GAAI,EAAA,EAAA,SAAA,EAAW,QAAQ,eACtB,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,OAAQ,EAAA,OAAA;AAAA,MACR,KAAO,EAAA,EAAE,UAAY,EAAA,WAAA,EAAa,MAAM,CAAE;AAAA,KAAA;AAAA,IAEzC,gBACG,YACA,GAAA,UAAA,IAAc,cACZ,WACA,GAAA,QAAA,CAAI,OAAO,EAAE;AAAA,KAEpB,UAAc,IAAA,WAAA,oBACZ,KAAA,CAAA,aAAA,CAAA,OAAA,EAAA,EAAQ,OAAM,mBACb,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,IAAK,EAAA,OAAA;AAAA,MACL,OAAA,EAAS,MAAM,UAAA,CAAW,WAAW;AAAA,KAAA;AAAA,oBAErC,KAAA,CAAA,aAAA,CAAC,YAAa,EAAA,EAAA,QAAA,EAAS,OAAQ,EAAA;AAAA,GAEnC,CAEF,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,OAAA;AAAA,IAAA;AAAA,MACC,KAAA,EACE,aACI,cACA,GAAA;AAAA,KAAA;AAAA,wCAGL,MACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,IAAK,EAAA,OAAA;AAAA,QACL,OAAS,EAAA,iBAAA;AAAA,QACT,QAAA,EACE,aAAkB,IAAA,WAAA,IAAe,CAAC;AAAA,OAAA;AAAA,MAGnC,UAAA,uCACE,iBAAkB,EAAA,EAAA,QAAA,EAAS,SAAQ,CAEpC,mBAAA,KAAA,CAAA,aAAA,CAAC,cAAe,EAAA,EAAA,QAAA,EAAS,OAAQ,EAAA;AAAA,KAGvC;AAAA,GAEJ,CAEJ,CACF,CAEJ,CAEC,EAAA,KAAA,KAAU,8BACR,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,IAAI,EAAA,IAAA,EAAC,IAAI,EACb,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,YAAS,KAAM,EAAA,eAAA,EAAA,sCACb,GACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACC,KAAO,EAAA,WAAA;AAAA,MACP,QAAU,EAAA,CAAC,CAAG,EAAA,QAAA,KAAa,eAAe,QAAQ,CAAA;AAAA,MAClD,cAAe,EAAA,SAAA;AAAA,MACf,SAAU,EAAA;AAAA,KAAA;AAAA,IAET,YAAa,CAAA,GAAA,CAAI,CAAC,EAAA,qBAChB,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAI,GAAK,EAAA,EAAA,CAAG,KAAO,EAAA,KAAA,EAAO,EAAG,CAAA,KAAA,EAAO,CACtC;AAAA,GAEH,kBAAA,KAAA,CAAA,aAAA,CAAC,GAAI,EAAA,EAAA,SAAA,EAAW,QAAQ,QACtB,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,WAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAM,YAAa,CAAA,WAAW,CAAE,CAAA,IAAA;AAAA,MAChC,QAAQ,MAAM,UAAA,CAAW,YAAa,CAAA,WAAW,EAAE,IAAI;AAAA;AAAA,GAE3D,CACF,CACF,CACF,CAAA,EAGD,OAAO,MAAQ,EAAA,MAAA,oBACb,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,IAAI,EAAA,IAAA,EAAC,IAAI,EACb,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,QAAS,EAAA,EAAA,KAAA,EAAM,aACd,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,IAAK,EAAA,EAAA,SAAA,EAAS,IAAC,EAAA,OAAA,EAAS,CACtB,EAAA,EAAA,MAAA,CAAO,MAAO,CAAA,MAAA,CAAO,yBACnB,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,IAAI,EAAA,IAAA,EAAA,kBACP,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,OAAQ,EAAA,SAAA,EAAU,SAAW,EAAA,OAAA,CAAQ,KAAO,EAAA,EAAA,OAExD,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,OAAQ,EAAA,IAAA,EAAA,EACjB,MAAO,CAAA,MAAA,CAAO,MAAO,CAAA,KAAA,CAAM,cAAe,EAC7C,CACF,CAAA,EAED,MAAO,CAAA,MAAA,CAAO,MAAO,CAAA,MAAA,wCACnB,IAAK,EAAA,EAAA,IAAA,EAAI,IACR,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,UAAW,EAAA,EAAA,OAAA,EAAQ,SAAU,EAAA,SAAA,EAAW,OAAQ,CAAA,KAAA,EAAA,EAAO,QAExD,CAAA,kBACC,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,SAAQ,IACjB,EAAA,EAAA,MAAA,CAAO,MAAO,CAAA,MAAA,CAAO,MAAO,CAAA,cAAA,EAC/B,CACF,CAED,EAAA,MAAA,CAAO,MAAO,CAAA,MAAA,CAAO,OACpB,oBAAA,KAAA,CAAA,aAAA,CAAC,QAAK,IAAI,EAAA,IAAA,EAAA,kBACP,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,OAAQ,EAAA,SAAA,EAAU,SAAW,EAAA,OAAA,CAAQ,KAAO,EAAA,EAAA,SAExD,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,UAAW,EAAA,EAAA,OAAA,EAAQ,QACjB,MAAO,CAAA,MAAA,CAAO,MAAO,CAAA,OAAA,CAAQ,cAAe,EAC/C,CACF,CAEJ,CACF,CACF,CAEJ,CACF,CAEA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,IAAM,EAAA,WAAA;AAAA,MACN,OAAA,EAAS,MAAM,cAAA,CAAe,KAAK,CAAA;AAAA,MACnC,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,oBACA,KAAA,CAAA,aAAA,CAAC,aACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,MAAO,EAAA,EAAA,OAAA,EAAS,MAAM,cAAe,CAAA,KAAK,CAAG,EAAA,EAAA,QAAM,CACpD,kBAAA,KAAA,CAAA,aAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,OAAQ,EAAA,WAAA;AAAA,QACR,KAAM,EAAA,SAAA;AAAA,QACN,OAAS,EAAA;AAAA,OAAA;AAAA,MACV;AAAA,KAGH;AAAA,GAEJ,CAAA;AAEJ;;;;"}
|
|
@@ -2,7 +2,8 @@ import React, { useState, useMemo } from 'react';
|
|
|
2
2
|
import { useAsync } from 'react-use';
|
|
3
3
|
import { CodeSnippet, Progress, ResponseErrorPanel, Table } from '@backstage/core-components';
|
|
4
4
|
import { Box, Typography, Tabs, Tab, Grid, Button, Menu, MenuItem, Dialog, DialogTitle, DialogContent, DialogActions, Chip, Tooltip, IconButton, CircularProgress } from '@material-ui/core';
|
|
5
|
-
import { useApi,
|
|
5
|
+
import { useApi, identityApiRef, alertApiRef } from '@backstage/core-plugin-api';
|
|
6
|
+
import { kuadrantApiRef } from '../../api.esm.js';
|
|
6
7
|
import { useEntity } from '@backstage/plugin-catalog-react';
|
|
7
8
|
import VisibilityIcon from '@material-ui/icons/Visibility';
|
|
8
9
|
import VisibilityOffIcon from '@material-ui/icons/VisibilityOff';
|
|
@@ -18,17 +19,14 @@ import { EditAPIKeyDialog } from '../EditAPIKeyDialog/EditAPIKeyDialog.esm.js';
|
|
|
18
19
|
import { ConfirmDeleteDialog } from '../ConfirmDeleteDialog/ConfirmDeleteDialog.esm.js';
|
|
19
20
|
import { generateAuthCodeSnippets } from '../../utils/codeSnippets.esm.js';
|
|
20
21
|
import { RequestAccessDialog } from '../RequestAccessDialog/RequestAccessDialog.esm.js';
|
|
21
|
-
import { handleFetchError } from '../../utils/errors.esm.js';
|
|
22
22
|
|
|
23
23
|
const ApiKeyManagementTab = ({
|
|
24
24
|
namespace: propNamespace
|
|
25
25
|
}) => {
|
|
26
26
|
const { entity } = useEntity();
|
|
27
|
-
const
|
|
27
|
+
const kuadrantApi = useApi(kuadrantApiRef);
|
|
28
28
|
const identityApi = useApi(identityApiRef);
|
|
29
|
-
const fetchApi = useApi(fetchApiRef);
|
|
30
29
|
const alertApi = useApi(alertApiRef);
|
|
31
|
-
const backendUrl = config.getString("backend.baseUrl");
|
|
32
30
|
const [visibleKeys, setVisibleKeys] = useState(/* @__PURE__ */ new Set());
|
|
33
31
|
const [refresh, setRefresh] = useState(0);
|
|
34
32
|
const [userId, setUserId] = useState("");
|
|
@@ -63,37 +61,23 @@ const ApiKeyManagementTab = ({
|
|
|
63
61
|
loading: requestsLoading,
|
|
64
62
|
error: requestsError
|
|
65
63
|
} = useAsync(async () => {
|
|
66
|
-
const
|
|
67
|
-
`${backendUrl}/api/kuadrant/requests/my?namespace=${namespace}`
|
|
68
|
-
);
|
|
69
|
-
if (!response.ok) {
|
|
70
|
-
const error2 = await handleFetchError(response);
|
|
71
|
-
throw new Error(`failed to fetch requests. ${error2}`);
|
|
72
|
-
}
|
|
73
|
-
const data = await response.json();
|
|
64
|
+
const data = await kuadrantApi.getRequestsByNamespace(namespace);
|
|
74
65
|
return (data.items || []).filter(
|
|
75
66
|
(r) => r.spec.apiProductRef.name === apiProductName && r.metadata.namespace === namespace
|
|
76
67
|
// APIProducts and APIKeys (and its Secret) will be in the same NS
|
|
77
68
|
);
|
|
78
|
-
}, [apiProductName, namespace, refresh,
|
|
69
|
+
}, [apiProductName, namespace, refresh, kuadrantApi]);
|
|
79
70
|
const {
|
|
80
71
|
value: apiProduct,
|
|
81
72
|
loading: plansLoading,
|
|
82
73
|
error: plansError
|
|
83
74
|
} = useAsync(async () => {
|
|
84
|
-
const
|
|
85
|
-
`${backendUrl}/api/kuadrant/apiproducts`
|
|
86
|
-
);
|
|
87
|
-
if (!response.ok) {
|
|
88
|
-
const error2 = await handleFetchError(response);
|
|
89
|
-
throw new Error(`failed to fetch api products. ${error2}`);
|
|
90
|
-
}
|
|
91
|
-
const data = await response.json();
|
|
75
|
+
const data = await kuadrantApi.getApiProducts();
|
|
92
76
|
const product = data.items?.find(
|
|
93
77
|
(p) => p.metadata.namespace === namespace && p.metadata.name === apiProductName
|
|
94
78
|
);
|
|
95
79
|
return product;
|
|
96
|
-
}, [namespace, apiProductName,
|
|
80
|
+
}, [namespace, apiProductName, kuadrantApi]);
|
|
97
81
|
const resourceRef = apiProduct ? `apiproduct:${apiProduct.metadata.namespace}/${apiProduct.metadata.name}` : undefined;
|
|
98
82
|
const {
|
|
99
83
|
allowed: canCreateRequest,
|
|
@@ -119,14 +103,7 @@ const ApiKeyManagementTab = ({
|
|
|
119
103
|
setOptimisticallyDeleted((prev) => new Set(prev).add(name));
|
|
120
104
|
setDeleting(name);
|
|
121
105
|
try {
|
|
122
|
-
|
|
123
|
-
`${backendUrl}/api/kuadrant/requests/${namespace}/${name}`,
|
|
124
|
-
{ method: "DELETE" }
|
|
125
|
-
);
|
|
126
|
-
if (!response.ok) {
|
|
127
|
-
const error2 = await handleFetchError(response);
|
|
128
|
-
throw new Error(error2);
|
|
129
|
-
}
|
|
106
|
+
await kuadrantApi.deleteRequest(namespace, name);
|
|
130
107
|
alertApi.post({
|
|
131
108
|
message: "API key deleted successfully",
|
|
132
109
|
severity: "success",
|
|
@@ -156,28 +133,25 @@ const ApiKeyManagementTab = ({
|
|
|
156
133
|
}
|
|
157
134
|
setApiKeyLoading((prev) => new Set(prev).add(key));
|
|
158
135
|
try {
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
);
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
setAlreadyReadKeys((prev) => new Set(prev).add(key));
|
|
166
|
-
} else if (response.status === 403) {
|
|
136
|
+
const data = await kuadrantApi.getApiKeySecret(requestNamespace, requestName);
|
|
137
|
+
setApiKeyValues((prev) => new Map(prev).set(key, data.apiKey));
|
|
138
|
+
setAlreadyReadKeys((prev) => new Set(prev).add(key));
|
|
139
|
+
} catch (err) {
|
|
140
|
+
const errorMessage = err instanceof Error ? err.message : "unknown error occurred";
|
|
141
|
+
if (errorMessage.includes("403") || errorMessage.includes("already been viewed")) {
|
|
167
142
|
setAlreadyReadKeys((prev) => new Set(prev).add(key));
|
|
168
143
|
alertApi.post({
|
|
169
144
|
message: "This API key has already been viewed and cannot be retrieved again.",
|
|
170
145
|
severity: "warning",
|
|
171
146
|
display: "transient"
|
|
172
147
|
});
|
|
148
|
+
} else {
|
|
149
|
+
alertApi.post({
|
|
150
|
+
message: `Failed to fetch api key: ${errorMessage}`,
|
|
151
|
+
severity: "error",
|
|
152
|
+
display: "transient"
|
|
153
|
+
});
|
|
173
154
|
}
|
|
174
|
-
} catch (err) {
|
|
175
|
-
const errorMessage = err instanceof Error ? err.message : "unknown error occurred";
|
|
176
|
-
alertApi.post({
|
|
177
|
-
message: `Failed to fetch api key: ${errorMessage}`,
|
|
178
|
-
severity: "error",
|
|
179
|
-
display: "transient"
|
|
180
|
-
});
|
|
181
155
|
} finally {
|
|
182
156
|
setApiKeyLoading((prev) => {
|
|
183
157
|
const next = new Set(prev);
|