@kuadrant/kuadrant-backstage-plugin-frontend 0.2.0 → 0.3.0-aaa46b4
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 +40 -2
- package/dist/api.esm.js.map +1 -1
- package/dist/components/ApiAccessCard/ApiAccessCard.esm.js +20 -85
- package/dist/components/ApiAccessCard/ApiAccessCard.esm.js.map +1 -1
- package/dist/components/ApiKeyApprovalPage/ApiKeyApprovalPageWithPermissions.esm.js +18 -0
- package/dist/components/ApiKeyApprovalPage/ApiKeyApprovalPageWithPermissions.esm.js.map +1 -0
- package/dist/components/ApiKeyApprovalPage/index.esm.js +1 -0
- package/dist/components/ApiKeyApprovalPage/index.esm.js.map +1 -1
- package/dist/components/ApiKeyDetailPage/ApiKeyDetailPage.esm.js +19 -60
- package/dist/components/ApiKeyDetailPage/ApiKeyDetailPage.esm.js.map +1 -1
- package/dist/components/ApiKeyManagementTab/ApiKeyManagementTab.esm.js +66 -113
- package/dist/components/ApiKeyManagementTab/ApiKeyManagementTab.esm.js.map +1 -1
- package/dist/components/ApiProductInfoCard/ApiProductInfoCard.esm.js +3 -2
- package/dist/components/ApiProductInfoCard/ApiProductInfoCard.esm.js.map +1 -1
- package/dist/components/ApprovalQueueTable/ApprovalQueueTable.esm.js +16 -15
- package/dist/components/ApprovalQueueTable/ApprovalQueueTable.esm.js.map +1 -1
- package/dist/components/CreateAPIProductDialog/CreateAPIProductDialog.esm.js +1 -7
- package/dist/components/CreateAPIProductDialog/CreateAPIProductDialog.esm.js.map +1 -1
- package/dist/components/EditAPIProductDialog/EditAPIProductDialog.esm.js +2 -3
- package/dist/components/EditAPIProductDialog/EditAPIProductDialog.esm.js.map +1 -1
- package/dist/components/KuadrantIcon/KuadrantIcon.esm.js +22 -0
- package/dist/components/KuadrantIcon/KuadrantIcon.esm.js.map +1 -0
- package/dist/components/KuadrantPage/ApiProductsPage.esm.js +5 -18
- package/dist/components/KuadrantPage/ApiProductsPage.esm.js.map +1 -1
- package/dist/components/MyApiKeysTable/MyApiKeysTable.esm.js +28 -138
- package/dist/components/MyApiKeysTable/MyApiKeysTable.esm.js.map +1 -1
- package/dist/components/PermissionGate/PermissionGate.esm.js +2 -2
- package/dist/components/PermissionGate/PermissionGate.esm.js.map +1 -1
- package/dist/components/RequestAccessDialog/RequestAccessDialog.esm.js +32 -18
- package/dist/components/RequestAccessDialog/RequestAccessDialog.esm.js.map +1 -1
- package/dist/components/SimpleRequestAccessDialog/SimpleRequestAccessDialog.esm.js +13 -2
- package/dist/components/SimpleRequestAccessDialog/SimpleRequestAccessDialog.esm.js.map +1 -1
- package/dist/components/icons.esm.js +11 -0
- package/dist/components/icons.esm.js.map +1 -0
- package/dist/index.d.ts +54 -6
- package/dist/index.esm.js +3 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/plugin.esm.js +2 -10
- package/dist/plugin.esm.js.map +1 -1
- package/dist/utils/apikeys.esm.js +21 -0
- package/dist/utils/apikeys.esm.js.map +1 -0
- package/dist/utils/styles.esm.js +5 -2
- package/dist/utils/styles.esm.js.map +1 -1
- package/dist-scalprum/internal.plugin-kuadrant.7f1de85661b1b848af15.js +2 -0
- package/dist-scalprum/internal.plugin-kuadrant.7f1de85661b1b848af15.js.map +1 -0
- package/dist-scalprum/plugin-manifest.json +3 -3
- package/dist-scalprum/static/{1037.58dd29ad.chunk.js → 1037.25758556.chunk.js} +1 -1
- package/dist-scalprum/static/{1037.58dd29ad.chunk.js.map → 1037.25758556.chunk.js.map} +1 -1
- package/dist-scalprum/static/1340.7c4f4722.chunk.js +3 -0
- package/dist-scalprum/static/1340.7c4f4722.chunk.js.map +1 -0
- package/dist-scalprum/static/1719.52ca7daf.chunk.js +2 -0
- package/dist-scalprum/static/1719.52ca7daf.chunk.js.map +1 -0
- package/dist-scalprum/static/{1881.8221c002.chunk.js → 1931.f6a5edbb.chunk.js} +2 -2
- package/dist-scalprum/static/1931.f6a5edbb.chunk.js.map +1 -0
- package/dist-scalprum/static/20.b3a37d1d.chunk.js +3 -0
- package/dist-scalprum/static/20.b3a37d1d.chunk.js.map +1 -0
- package/dist-scalprum/static/2251.08f3db99.chunk.js +2 -0
- package/dist-scalprum/static/2251.08f3db99.chunk.js.map +1 -0
- package/dist-scalprum/static/2769.e09b0ab0.chunk.js +2 -0
- package/dist-scalprum/static/2769.e09b0ab0.chunk.js.map +1 -0
- package/dist-scalprum/static/2821.1ac360ec.chunk.js +2 -0
- package/dist-scalprum/static/2821.1ac360ec.chunk.js.map +1 -0
- package/dist-scalprum/static/2952.b54bd390.chunk.js +2 -0
- package/dist-scalprum/static/2952.b54bd390.chunk.js.map +1 -0
- package/dist-scalprum/static/2967.004a950e.chunk.js +2 -0
- package/dist-scalprum/static/2967.004a950e.chunk.js.map +1 -0
- package/dist-scalprum/static/3015.1fe097c2.chunk.js +3 -0
- package/dist-scalprum/static/3015.1fe097c2.chunk.js.LICENSE.txt +9 -0
- package/dist-scalprum/static/3015.1fe097c2.chunk.js.map +1 -0
- package/dist-scalprum/static/327.74ecd572.chunk.js +2 -0
- package/dist-scalprum/static/327.74ecd572.chunk.js.map +1 -0
- package/dist-scalprum/static/3657.882640ca.chunk.js +3 -0
- package/dist-scalprum/static/3657.882640ca.chunk.js.LICENSE.txt +8 -0
- package/dist-scalprum/static/3657.882640ca.chunk.js.map +1 -0
- package/dist-scalprum/static/3658.104704cc.chunk.js +2 -0
- package/dist-scalprum/static/3658.104704cc.chunk.js.map +1 -0
- package/dist-scalprum/static/{3897.ef4554b5.chunk.js → 3897.6e9c07c0.chunk.js} +1 -1
- package/dist-scalprum/static/{3897.ef4554b5.chunk.js.map → 3897.6e9c07c0.chunk.js.map} +1 -1
- package/dist-scalprum/static/3917.888fba36.chunk.js +2 -0
- package/dist-scalprum/static/3917.888fba36.chunk.js.map +1 -0
- package/dist-scalprum/static/3947.f5320e89.chunk.js +2 -0
- package/dist-scalprum/static/3947.f5320e89.chunk.js.map +1 -0
- package/dist-scalprum/static/{4083.488ff7a9.chunk.js → 4083.811c4e7a.chunk.js} +2 -2
- package/dist-scalprum/static/{4083.488ff7a9.chunk.js.map → 4083.811c4e7a.chunk.js.map} +1 -1
- package/dist-scalprum/static/438.4335b833.chunk.js +2 -0
- package/dist-scalprum/static/438.4335b833.chunk.js.map +1 -0
- package/dist-scalprum/static/4908.4f21d453.chunk.js +2 -0
- package/dist-scalprum/static/4908.4f21d453.chunk.js.map +1 -0
- package/dist-scalprum/static/{5010.6241b64f.chunk.js → 5010.4f67737b.chunk.js} +2 -2
- package/dist-scalprum/static/{5010.6241b64f.chunk.js.map → 5010.4f67737b.chunk.js.map} +1 -1
- package/dist-scalprum/static/5197.53535ff4.chunk.js +2 -0
- package/dist-scalprum/static/5197.53535ff4.chunk.js.map +1 -0
- package/dist-scalprum/static/5289.6c803140.chunk.js +2 -0
- package/dist-scalprum/static/5289.6c803140.chunk.js.map +1 -0
- package/dist-scalprum/static/5943.4e1dedc5.chunk.js +2 -0
- package/dist-scalprum/static/5943.4e1dedc5.chunk.js.map +1 -0
- package/dist-scalprum/static/6038.63d1f832.chunk.js +3 -0
- package/dist-scalprum/static/6038.63d1f832.chunk.js.LICENSE.txt +8 -0
- package/dist-scalprum/static/6038.63d1f832.chunk.js.map +1 -0
- package/dist-scalprum/static/{6272.b5645dc2.chunk.js → 6272.3ed14ea4.chunk.js} +1 -1
- package/dist-scalprum/static/{6272.b5645dc2.chunk.js.map → 6272.3ed14ea4.chunk.js.map} +1 -1
- package/dist-scalprum/static/6311.da1849d1.chunk.js +2 -0
- package/dist-scalprum/static/6311.da1849d1.chunk.js.map +1 -0
- package/dist-scalprum/static/635.f63679a5.chunk.js +3 -0
- package/dist-scalprum/static/635.f63679a5.chunk.js.map +1 -0
- package/dist-scalprum/static/6371.02375475.chunk.js +3 -0
- package/dist-scalprum/static/6371.02375475.chunk.js.LICENSE.txt +9 -0
- package/dist-scalprum/static/6371.02375475.chunk.js.map +1 -0
- package/dist-scalprum/static/{6386.2d20c412.chunk.js → 6386.5922f271.chunk.js} +3 -3
- package/dist-scalprum/static/{6386.2d20c412.chunk.js.map → 6386.5922f271.chunk.js.map} +1 -1
- package/dist-scalprum/static/6837.6252b97a.chunk.js +2 -0
- package/dist-scalprum/static/6837.6252b97a.chunk.js.map +1 -0
- package/dist-scalprum/static/{6972.e47ec97e.chunk.js → 6972.f22b9446.chunk.js} +1 -1
- package/dist-scalprum/static/{6972.e47ec97e.chunk.js.map → 6972.f22b9446.chunk.js.map} +1 -1
- package/dist-scalprum/static/7164.5dc4bc72.chunk.js +2 -0
- package/dist-scalprum/static/7164.5dc4bc72.chunk.js.map +1 -0
- package/dist-scalprum/static/{7266.e760b8c3.chunk.js → 7266.3c4174cc.chunk.js} +1 -1
- package/dist-scalprum/static/{7266.e760b8c3.chunk.js.map → 7266.3c4174cc.chunk.js.map} +1 -1
- package/dist-scalprum/static/7270.8ee9d452.chunk.js +2 -0
- package/dist-scalprum/static/7270.8ee9d452.chunk.js.map +1 -0
- package/dist-scalprum/static/{7791.8f84478d.chunk.js → 7791.ad31cf6d.chunk.js} +2 -2
- package/dist-scalprum/static/{7791.8f84478d.chunk.js.map → 7791.ad31cf6d.chunk.js.map} +1 -1
- package/dist-scalprum/static/{8563.46f1a3e1.chunk.js → 8563.6501eafb.chunk.js} +2 -2
- package/dist-scalprum/static/{8563.46f1a3e1.chunk.js.map → 8563.6501eafb.chunk.js.map} +1 -1
- package/dist-scalprum/static/980.744a4d36.chunk.js +2 -0
- package/dist-scalprum/static/980.744a4d36.chunk.js.map +1 -0
- package/dist-scalprum/static/exposed-KuadrantIcon.08abbb96.chunk.js +3 -0
- package/dist-scalprum/static/exposed-KuadrantIcon.08abbb96.chunk.js.LICENSE.txt +9 -0
- package/dist-scalprum/static/exposed-KuadrantIcon.08abbb96.chunk.js.map +1 -0
- package/dist-scalprum/static/exposed-KuadrantPage.f123b200.chunk.js +2 -0
- package/dist-scalprum/static/exposed-KuadrantPage.f123b200.chunk.js.map +1 -0
- package/dist-scalprum/static/exposed-PluginRoot.3a5f9157.chunk.js +2 -0
- package/dist-scalprum/static/exposed-PluginRoot.3a5f9157.chunk.js.map +1 -0
- package/package.json +6 -3
- package/dist/components/EntityApiApprovalTab/EntityApiApprovalTab.esm.js +0 -265
- package/dist/components/EntityApiApprovalTab/EntityApiApprovalTab.esm.js.map +0 -1
- package/dist/components/EntityApiApprovalTab/index.esm.js +0 -2
- package/dist/components/EntityApiApprovalTab/index.esm.js.map +0 -1
- package/dist-scalprum/internal.plugin-kuadrant.b3d35dc8b21ce867aa09.js +0 -2
- package/dist-scalprum/internal.plugin-kuadrant.b3d35dc8b21ce867aa09.js.map +0 -1
- package/dist-scalprum/static/1319.ac195ac2.chunk.js +0 -2
- package/dist-scalprum/static/1319.ac195ac2.chunk.js.map +0 -1
- package/dist-scalprum/static/1584.ae3779f0.chunk.js +0 -3
- package/dist-scalprum/static/1584.ae3779f0.chunk.js.map +0 -1
- package/dist-scalprum/static/1881.8221c002.chunk.js.map +0 -1
- package/dist-scalprum/static/2967.7c6a34cd.chunk.js +0 -2
- package/dist-scalprum/static/2967.7c6a34cd.chunk.js.map +0 -1
- package/dist-scalprum/static/3118.daee3324.chunk.js +0 -3
- package/dist-scalprum/static/3118.daee3324.chunk.js.map +0 -1
- package/dist-scalprum/static/3581.b5b97f08.chunk.js +0 -2
- package/dist-scalprum/static/3581.b5b97f08.chunk.js.map +0 -1
- package/dist-scalprum/static/369.2374941c.chunk.js +0 -2
- package/dist-scalprum/static/369.2374941c.chunk.js.map +0 -1
- package/dist-scalprum/static/3947.ad129ba4.chunk.js +0 -2
- package/dist-scalprum/static/3947.ad129ba4.chunk.js.map +0 -1
- package/dist-scalprum/static/3976.e0873210.chunk.js +0 -2
- package/dist-scalprum/static/3976.e0873210.chunk.js.map +0 -1
- package/dist-scalprum/static/4434.f92f6ba4.chunk.js +0 -2
- package/dist-scalprum/static/4434.f92f6ba4.chunk.js.map +0 -1
- package/dist-scalprum/static/483.d55d6ab2.chunk.js +0 -2
- package/dist-scalprum/static/483.d55d6ab2.chunk.js.map +0 -1
- package/dist-scalprum/static/512.f1c51799.chunk.js +0 -2
- package/dist-scalprum/static/512.f1c51799.chunk.js.map +0 -1
- package/dist-scalprum/static/5203.3df62d7e.chunk.js +0 -2
- package/dist-scalprum/static/5203.3df62d7e.chunk.js.map +0 -1
- package/dist-scalprum/static/5289.2e686027.chunk.js +0 -2
- package/dist-scalprum/static/5289.2e686027.chunk.js.map +0 -1
- package/dist-scalprum/static/5453.3c20d0a6.chunk.js +0 -2
- package/dist-scalprum/static/5453.3c20d0a6.chunk.js.map +0 -1
- package/dist-scalprum/static/6371.f183dddb.chunk.js +0 -3
- package/dist-scalprum/static/6371.f183dddb.chunk.js.map +0 -1
- package/dist-scalprum/static/6426.bf20c588.chunk.js +0 -2
- package/dist-scalprum/static/6426.bf20c588.chunk.js.map +0 -1
- package/dist-scalprum/static/6800.ddabed69.chunk.js +0 -2
- package/dist-scalprum/static/6800.ddabed69.chunk.js.map +0 -1
- package/dist-scalprum/static/7005.d548f8f1.chunk.js +0 -2
- package/dist-scalprum/static/7005.d548f8f1.chunk.js.map +0 -1
- package/dist-scalprum/static/7057.fcd688c7.chunk.js +0 -2
- package/dist-scalprum/static/7057.fcd688c7.chunk.js.map +0 -1
- package/dist-scalprum/static/7270.301a3c46.chunk.js +0 -2
- package/dist-scalprum/static/7270.301a3c46.chunk.js.map +0 -1
- package/dist-scalprum/static/9051.f095a8a1.chunk.js +0 -2
- package/dist-scalprum/static/9051.f095a8a1.chunk.js.map +0 -1
- package/dist-scalprum/static/9079.b6d5c19c.chunk.js +0 -2
- package/dist-scalprum/static/9079.b6d5c19c.chunk.js.map +0 -1
- package/dist-scalprum/static/9625.b0c6610a.chunk.js +0 -2
- package/dist-scalprum/static/9625.b0c6610a.chunk.js.map +0 -1
- package/dist-scalprum/static/9838.589f2156.chunk.js +0 -2
- package/dist-scalprum/static/9838.589f2156.chunk.js.map +0 -1
- package/dist-scalprum/static/exposed-PluginRoot.a8448fcc.chunk.js +0 -2
- package/dist-scalprum/static/exposed-PluginRoot.a8448fcc.chunk.js.map +0 -1
- /package/dist-scalprum/static/{1584.ae3779f0.chunk.js.LICENSE.txt → 1340.7c4f4722.chunk.js.LICENSE.txt} +0 -0
- /package/dist-scalprum/static/{3118.daee3324.chunk.js.LICENSE.txt → 20.b3a37d1d.chunk.js.LICENSE.txt} +0 -0
- /package/dist-scalprum/static/{4083.488ff7a9.chunk.js.LICENSE.txt → 4083.811c4e7a.chunk.js.LICENSE.txt} +0 -0
- /package/dist-scalprum/static/{5010.6241b64f.chunk.js.LICENSE.txt → 5010.4f67737b.chunk.js.LICENSE.txt} +0 -0
- /package/dist-scalprum/static/{6371.f183dddb.chunk.js.LICENSE.txt → 635.f63679a5.chunk.js.LICENSE.txt} +0 -0
- /package/dist-scalprum/static/{6386.2d20c412.chunk.js.LICENSE.txt → 6386.5922f271.chunk.js.LICENSE.txt} +0 -0
- /package/dist-scalprum/static/{8563.46f1a3e1.chunk.js.LICENSE.txt → 8563.6501eafb.chunk.js.LICENSE.txt} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RequestAccessDialog.esm.js","sources":["../../../src/components/RequestAccessDialog/RequestAccessDialog.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport {\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n Button,\n TextField,\n Select,\n MenuItem,\n FormControl,\n InputLabel,\n Box,\n Typography,\n CircularProgress,\n} from '@material-ui/core';\nimport InfoIcon from '@material-ui/icons/Info';\nimport {\n useApi,\n alertApiRef,\n} from '@backstage/core-plugin-api';\nimport { kuadrantApiRef } from '../../api';\nimport { Plan } from \"../../types/api-management.ts\";\n\nexport interface RequestAccessDialogProps {\n open: boolean;\n onClose: () => void;\n onSuccess: () => void;\n apiProductName: string;\n namespace: string;\n userEmail: string;\n plans: Plan[];\n}\n\nexport const RequestAccessDialog = ({\n open,\n onClose,\n onSuccess,\n apiProductName,\n namespace,\n userEmail,\n plans,\n}: RequestAccessDialogProps) => {\n const kuadrantApi = useApi(kuadrantApiRef);\n const alertApi = useApi(alertApiRef);\n\n const [selectedPlan, setSelectedPlan] = useState('');\n const [useCase, setUseCase] = useState('');\n const [creating, setCreating] = useState(false);\n const [createError, setCreateError] = useState<string | null>(null);\n\n const handleClose = () => {\n setSelectedPlan('');\n setUseCase('');\n setCreateError(null);\n onClose();\n };\n\n const handleRequestAccess = async () => {\n if (!selectedPlan) return;\n\n setCreating(true);\n setCreateError(null);\n try {\n await kuadrantApi.createRequest({\n apiProductName,\n namespace,\n planTier: selectedPlan,\n useCase: useCase.trim() || '',\n userEmail,\n });\n\n alertApi.post({\n message: 'API key requested successfully',\n severity: 'success',\n display: 'transient',\n });\n\n setSelectedPlan('');\n setUseCase('');\n onSuccess();\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : 'unknown error occurred';\n alertApi.post({\n message: `Failed to request API key: ${errorMessage}`,\n severity: 'error',\n display: 'transient',\n });\n setCreateError(errorMessage);\n } finally {\n setCreating(false);\n }\n };\n\n return (\n <Dialog open={open} onClose={handleClose} maxWidth=\"sm\" fullWidth>\n <DialogTitle>Request API Access</DialogTitle>\n <DialogContent>\n <Box\n mb={2}\n p={1.5}\n bgcolor=\"info.light\"\n borderRadius={1}\n display=\"flex\"\n alignItems=\"flex-start\"\n style={{ gap: 8 }}\n >\n <InfoIcon\n color=\"primary\"\n fontSize=\"small\"\n style={{ marginTop: 2 }}\n />\n <Typography variant=\"body2\">\n Your request will be reviewed by an API owner before access is\n granted.\n </Typography>\n </Box>\n {createError && (\n <Box\n mb={2}\n p={2}\n bgcolor=\"error.main\"\n color=\"error.contrastText\"\n borderRadius={1}\n >\n <Typography variant=\"body2\">{createError}</Typography>\n </Box>\n )}\n <FormControl\n fullWidth\n margin=\"normal\"\n disabled={creating}\n data-testid=\"tier-select-form\"\n >\n <InputLabel id=\"tier-select-label\">Select Tier</InputLabel>\n <Select\n labelId=\"tier-select-label\"\n data-testid=\"tier-select\"\n value={selectedPlan}\n onChange={(e) => setSelectedPlan(e.target.value as string)}\n disabled={creating}\n >\n {plans.map((plan: Plan) => {\n const limitDesc = Object.entries(plan.limits || {})\n .map(([key, val]) => `${val} per ${key}`)\n .join(', ');\n return (\n <MenuItem\n key={plan.tier}\n value={plan.tier}\n data-testid={`tier-option-${plan.tier}`}\n >\n {plan.tier} {limitDesc ? `(${limitDesc})` : ''}\n </MenuItem>\n );\n })}\n </Select>\n </FormControl>\n <TextField\n label=\"Use Case (optional)\"\n placeholder=\"Describe how you plan to use this API\"\n multiline\n rows={3}\n fullWidth\n margin=\"normal\"\n value={useCase}\n onChange={(e) => setUseCase(e.target.value)}\n helperText=\"Explain your intended use of this API for admin review\"\n disabled={creating}\n />\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose} disabled={creating}>\n Cancel\n </Button>\n <Button\n onClick={handleRequestAccess}\n color=\"primary\"\n variant=\"contained\"\n disabled={!selectedPlan || creating}\n startIcon={\n creating ? (\n <CircularProgress size={16} color=\"inherit\" />\n ) : undefined\n }\n >\n {creating ? 'Submitting...' : 'Submit Request'}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RequestAccessDialog.esm.js","sources":["../../../src/components/RequestAccessDialog/RequestAccessDialog.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport {\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n Button,\n TextField,\n Select,\n MenuItem,\n FormControl,\n InputLabel,\n Box,\n Typography,\n CircularProgress,\n} from '@material-ui/core';\nimport InfoIcon from '@material-ui/icons/Info';\nimport {\n useApi,\n alertApiRef,\n} from '@backstage/core-plugin-api';\nimport { kuadrantApiRef } from '../../api';\nimport { Plan } from \"../../types/api-management.ts\";\n\nexport interface RequestAccessDialogProps {\n open: boolean;\n onClose: () => void;\n onSuccess: () => void;\n apiProductName: string;\n namespace: string;\n userEmail: string;\n plans: Plan[];\n}\n\nexport const RequestAccessDialog = ({\n open,\n onClose,\n onSuccess,\n apiProductName,\n namespace,\n userEmail,\n plans,\n}: RequestAccessDialogProps) => {\n const kuadrantApi = useApi(kuadrantApiRef);\n const alertApi = useApi(alertApiRef);\n\n const [selectedPlan, setSelectedPlan] = useState('');\n const [useCase, setUseCase] = useState('');\n const [creating, setCreating] = useState(false);\n const [createError, setCreateError] = useState<string | null>(null);\n\n const handleClose = () => {\n setSelectedPlan('');\n setUseCase('');\n setCreateError(null);\n onClose();\n };\n\n const handleRequestAccess = async () => {\n if (!selectedPlan) return;\n\n setCreating(true);\n setCreateError(null);\n\n try {\n // 1. generate secret name and API key value\n const randomSuffix = Math.random().toString(36).substring(2, 10);\n const secretName = `${apiProductName}-${randomSuffix}-secret`\n .toLowerCase()\n .replace(/[^a-z0-9-]/g, '-');\n const apiKeyValue = crypto.randomUUID().replace(/-/g, '');\n\n // 2. create secret in consumer's namespace first (design doc: secret before APIKey)\n await kuadrantApi.createSecret(secretName, apiKeyValue);\n\n try {\n // 3. create APIKey referencing the pre-existing secret\n await kuadrantApi.createRequest({\n apiProductName,\n namespace,\n planTier: selectedPlan,\n useCase: useCase.trim() || '',\n userEmail,\n secretName,\n });\n\n alertApi.post({\n message: `Request submitted successfully. Pending API owner approval.`,\n severity: 'info',\n display: 'transient',\n });\n\n setSelectedPlan('');\n setUseCase('');\n onSuccess();\n\n } catch (apiKeyError) {\n // cleanup orphaned secret if APIKey creation fails\n try {\n await kuadrantApi.deleteSecret(secretName);\n } catch (deleteError) {\n console.warn('Failed to cleanup orphaned secret:', deleteError);\n }\n throw apiKeyError;\n }\n\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'unknown error occurred';\n alertApi.post({\n message: `Failed to create request: ${errorMessage}`,\n severity: 'error',\n display: 'transient',\n });\n setCreateError(errorMessage);\n } finally {\n setCreating(false);\n }\n };\n\n return (\n <Dialog open={open} onClose={handleClose} maxWidth=\"sm\" fullWidth>\n <DialogTitle>Request API Access</DialogTitle>\n <DialogContent>\n <Box\n mb={2}\n p={1.5}\n bgcolor=\"info.light\"\n borderRadius={1}\n display=\"flex\"\n alignItems=\"flex-start\"\n style={{ gap: 8 }}\n >\n <InfoIcon\n color=\"primary\"\n fontSize=\"small\"\n style={{ marginTop: 2 }}\n />\n <Typography variant=\"body2\">\n Your request will be reviewed by an API owner before access is\n granted.\n </Typography>\n </Box>\n {createError && (\n <Box\n mb={2}\n p={2}\n bgcolor=\"error.main\"\n color=\"error.contrastText\"\n borderRadius={1}\n >\n <Typography variant=\"body2\">{createError}</Typography>\n </Box>\n )}\n <FormControl\n fullWidth\n margin=\"normal\"\n disabled={creating}\n data-testid=\"tier-select-form\"\n >\n <InputLabel id=\"tier-select-label\">Select Tier</InputLabel>\n <Select\n labelId=\"tier-select-label\"\n data-testid=\"tier-select\"\n value={selectedPlan}\n onChange={(e) => setSelectedPlan(e.target.value as string)}\n disabled={creating}\n >\n {plans.map((plan: Plan) => {\n const limitDesc = Object.entries(plan.limits || {})\n .map(([key, val]) => `${val} per ${key}`)\n .join(', ');\n return (\n <MenuItem\n key={plan.tier}\n value={plan.tier}\n data-testid={`tier-option-${plan.tier}`}\n >\n {plan.tier} {limitDesc ? `(${limitDesc})` : ''}\n </MenuItem>\n );\n })}\n </Select>\n </FormControl>\n <TextField\n label=\"Use Case (optional)\"\n placeholder=\"Describe how you plan to use this API\"\n multiline\n rows={3}\n fullWidth\n margin=\"normal\"\n value={useCase}\n onChange={(e) => setUseCase(e.target.value)}\n helperText=\"Explain your intended use of this API for admin review\"\n disabled={creating}\n />\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose} disabled={creating}>\n Cancel\n </Button>\n <Button\n onClick={handleRequestAccess}\n color=\"primary\"\n variant=\"contained\"\n disabled={!selectedPlan || creating}\n startIcon={\n creating ? (\n <CircularProgress size={16} color=\"inherit\" />\n ) : undefined\n }\n >\n {creating ? 'Submitting...' : 'Submit Request'}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import React, { useState } from 'react';
|
|
|
2
2
|
import { Dialog, DialogTitle, DialogContent, Typography, FormControl, InputLabel, Select, MenuItem, FormHelperText, TextField, DialogActions, Button, CircularProgress } from '@material-ui/core';
|
|
3
3
|
import { useApi, configApiRef, fetchApiRef, alertApiRef, identityApiRef } from '@backstage/core-plugin-api';
|
|
4
4
|
import useAsync from 'react-use/lib/useAsync';
|
|
5
|
+
import { kuadrantApiRef } from '../../api.esm.js';
|
|
5
6
|
|
|
6
7
|
const SimpleRequestAccessDialog = ({
|
|
7
8
|
open,
|
|
@@ -12,6 +13,7 @@ const SimpleRequestAccessDialog = ({
|
|
|
12
13
|
const fetchApi = useApi(fetchApiRef);
|
|
13
14
|
const alertApi = useApi(alertApiRef);
|
|
14
15
|
const identityApi = useApi(identityApiRef);
|
|
16
|
+
const kuadrantApi = useApi(kuadrantApiRef);
|
|
15
17
|
const backendUrl = config.getString("backend.baseUrl");
|
|
16
18
|
const [selectedApi, setSelectedApi] = useState("");
|
|
17
19
|
const [selectedTier, setSelectedTier] = useState("");
|
|
@@ -53,6 +55,12 @@ const SimpleRequestAccessDialog = ({
|
|
|
53
55
|
const [namespace, apiProductName] = selectedApi.split("/");
|
|
54
56
|
setCreating(true);
|
|
55
57
|
try {
|
|
58
|
+
const identity = await identityApi.getBackstageIdentity();
|
|
59
|
+
const username = identity.userEntityRef.split("/")[1] || "unknown";
|
|
60
|
+
const randomSuffix = Math.random().toString(36).substring(2, 10);
|
|
61
|
+
const secretName = `${username}-${apiProductName}-secret-${randomSuffix}`.toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
|
62
|
+
const apiKeyValue = crypto.randomUUID().replace(/-/g, "");
|
|
63
|
+
await kuadrantApi.createSecret(secretName, apiKeyValue);
|
|
56
64
|
const response = await fetchApi.fetch(
|
|
57
65
|
`${backendUrl}/api/kuadrant/requests`,
|
|
58
66
|
{
|
|
@@ -65,7 +73,8 @@ const SimpleRequestAccessDialog = ({
|
|
|
65
73
|
namespace,
|
|
66
74
|
planTier: selectedTier,
|
|
67
75
|
useCase: useCase.trim() || "",
|
|
68
|
-
userEmail: userEmail || "unknown"
|
|
76
|
+
userEmail: userEmail || "unknown",
|
|
77
|
+
secretName
|
|
69
78
|
})
|
|
70
79
|
}
|
|
71
80
|
);
|
|
@@ -85,7 +94,8 @@ const SimpleRequestAccessDialog = ({
|
|
|
85
94
|
namespace,
|
|
86
95
|
planTier: selectedTier,
|
|
87
96
|
useCase: useCase.trim() || "",
|
|
88
|
-
userEmail: userEmail || "unknown"
|
|
97
|
+
userEmail: userEmail || "unknown",
|
|
98
|
+
secretName: "(generated)"
|
|
89
99
|
}
|
|
90
100
|
});
|
|
91
101
|
const rawError = errorData.error || errorData.message || `Server returned ${response.status}`;
|
|
@@ -104,6 +114,7 @@ const SimpleRequestAccessDialog = ({
|
|
|
104
114
|
} else if (response.status >= 500) {
|
|
105
115
|
errorMsg = `Server error: ${rawError}`;
|
|
106
116
|
}
|
|
117
|
+
await kuadrantApi.deleteSecret(secretName).catch((e) => console.warn("Failed to cleanup orphaned secret:", e));
|
|
107
118
|
throw new Error(errorMsg);
|
|
108
119
|
}
|
|
109
120
|
alertApi.post({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SimpleRequestAccessDialog.esm.js","sources":["../../../src/components/SimpleRequestAccessDialog/SimpleRequestAccessDialog.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport {\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n Button,\n TextField,\n Select,\n MenuItem,\n FormControl,\n InputLabel,\n Typography,\n CircularProgress,\n FormHelperText,\n} from '@material-ui/core';\nimport {\n useApi,\n configApiRef,\n fetchApiRef,\n alertApiRef,\n identityApiRef,\n} from '@backstage/core-plugin-api';\nimport useAsync from 'react-use/lib/useAsync';\n\nexport interface SimpleRequestAccessDialogProps {\n open: boolean;\n onClose: () => void;\n onSuccess: () => void;\n}\n\ntype ApiProduct = {\n metadata: {\n name: string;\n namespace: string;\n };\n spec?: {\n publishStatus?: string;\n };\n status?: {\n discoveredPlans?: Array<{\n tier: string;\n limits?: Record<string, number>;\n }>;\n };\n};\n\nexport const SimpleRequestAccessDialog = ({\n open,\n onClose,\n onSuccess,\n}: SimpleRequestAccessDialogProps) => {\n const config = useApi(configApiRef);\n const fetchApi = useApi(fetchApiRef);\n const alertApi = useApi(alertApiRef);\n const identityApi = useApi(identityApiRef);\n const backendUrl = config.getString('backend.baseUrl');\n\n const [selectedApi, setSelectedApi] = useState('');\n const [selectedTier, setSelectedTier] = useState('');\n const [useCase, setUseCase] = useState('');\n const [creating, setCreating] = useState(false);\n\n // Fetch all published API products\n const {\n value: apiProducts,\n loading: loadingProducts,\n } = useAsync(async () => {\n if (!open) return [];\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/apiproducts`,\n );\n if (!response.ok) {\n throw new Error('Failed to fetch API products');\n }\n const data = await response.json();\n // Filter to only show Published products\n return (data.items || []).filter(\n (p: ApiProduct) => p.spec?.publishStatus === 'Published',\n );\n }, [backendUrl, fetchApi, open]);\n\n // Get user email\n const { value: userEmail } = useAsync(async () => {\n const identity = await identityApi.getBackstageIdentity();\n\n // Extract username from userEntityRef (e.g., \"user:default/john\" -> \"john\")\n const username = identity.userEntityRef.split('/')[1] || 'unknown';\n\n // Construct email from username\n return `${username}@example.com`;\n }, [identityApi]);\n\n // Get available tiers for selected API\n const selectedProduct = apiProducts?.find(\n (p: ApiProduct) =>\n `${p.metadata.namespace}/${p.metadata.name}` === selectedApi,\n );\n const availableTiers = selectedProduct?.status?.discoveredPlans || [];\n\n const handleClose = () => {\n setSelectedApi('');\n setSelectedTier('');\n setUseCase('');\n onClose();\n };\n\n const handleSubmit = async () => {\n if (!selectedApi || !selectedTier) return;\n\n const [namespace, apiProductName] = selectedApi.split('/');\n\n setCreating(true);\n try {\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/requests`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n apiProductName,\n namespace,\n planTier: selectedTier,\n useCase: useCase.trim() || '',\n userEmail: userEmail || 'unknown',\n }),\n },\n );\n\n if (!response.ok) {\n let errorData;\n try {\n errorData = await response.json();\n } catch {\n errorData = { error: `Server returned ${response.status} ${response.statusText}` };\n }\n\n console.error('Backend error response:', {\n status: response.status,\n statusText: response.statusText,\n errorData,\n requestBody: {\n apiProductName,\n namespace,\n planTier: selectedTier,\n useCase: useCase.trim() || '',\n userEmail: userEmail || 'unknown',\n }\n });\n\n // Extract user-friendly error message\n const rawError = errorData.error || errorData.message || `Server returned ${response.status}`;\n\n // Try to extract validation error details from Kubernetes error messages\n // Example: \"failed to create apikeys: APIKey.devportal.kuadrant.io \"name\" is invalid: spec.requestedBy.email: Invalid value: \"admin\": spec.requestedBy.email in body should match '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$'\"\n let errorMsg = rawError;\n\n if (rawError.includes('spec.requestedBy.email')) {\n errorMsg = 'Invalid email format. Please contact your administrator to update your profile email.';\n } else if (rawError.includes('is invalid:')) {\n // Extract the validation message after \"is invalid:\"\n const match = rawError.match(/is invalid: (.+?)(?:\\s+\\(|$)/);\n if (match) {\n errorMsg = `Validation error: ${match[1]}`;\n }\n } else if (response.status === 403) {\n errorMsg = 'You do not have permission to request access to this API.';\n } else if (response.status === 404) {\n errorMsg = 'The selected API or tier was not found.';\n } else if (response.status >= 500) {\n errorMsg = `Server error: ${rawError}`;\n }\n\n throw new Error(errorMsg);\n }\n\n alertApi.post({\n message: 'API key requested successfully',\n severity: 'success',\n display: 'transient',\n });\n\n handleClose();\n onSuccess();\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : 'unknown error occurred';\n console.error('Failed to create API key request:', {\n error: err,\n selectedApi,\n selectedTier,\n userEmail,\n });\n alertApi.post({\n message: `Failed to request API key: ${errorMessage}`,\n severity: 'error',\n display: 'permanent',\n });\n } finally {\n setCreating(false);\n }\n };\n\n return (\n <Dialog open={open} onClose={handleClose} maxWidth=\"sm\" fullWidth>\n <DialogTitle>Request API key</DialogTitle>\n <DialogContent>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Submit your request to generate an API key.\n </Typography>\n\n <FormControl fullWidth margin=\"normal\" disabled={creating || loadingProducts}>\n <InputLabel id=\"api-select-label\" required>\n API\n </InputLabel>\n <Select\n labelId=\"api-select-label\"\n value={selectedApi}\n onChange={e => {\n setSelectedApi(e.target.value as string);\n setSelectedTier(''); // Reset tier when API changes\n }}\n disabled={creating || loadingProducts}\n data-testid=\"api-select\"\n >\n {loadingProducts ? (\n <MenuItem disabled>Loading...</MenuItem>\n ) : (\n apiProducts?.map((product: ApiProduct) => (\n <MenuItem\n key={`${product.metadata.namespace}/${product.metadata.name}`}\n value={`${product.metadata.namespace}/${product.metadata.name}`}\n >\n {product.metadata.name}\n </MenuItem>\n ))\n )}\n </Select>\n <FormHelperText>\n Select one API. Please submit separate requests for multiple APIs.\n </FormHelperText>\n </FormControl>\n\n <FormControl\n fullWidth\n margin=\"normal\"\n disabled={creating || !selectedApi}\n required\n >\n <InputLabel id=\"tier-select-label\">Tiers</InputLabel>\n <Select\n labelId=\"tier-select-label\"\n value={selectedTier}\n onChange={e => setSelectedTier(e.target.value as string)}\n disabled={creating || !selectedApi}\n data-testid=\"tier-select\"\n >\n {!selectedApi ? (\n <MenuItem disabled>Select an API first</MenuItem>\n ) : availableTiers.length === 0 ? (\n <MenuItem disabled>No tiers available</MenuItem>\n ) : (\n availableTiers.map((plan: { tier: string; limits?: Record<string, number> }) => {\n const limitDesc = Object.entries(plan.limits || {})\n .map(([key, val]) => `${val} per ${key}`)\n .join(', ');\n return (\n <MenuItem key={plan.tier} value={plan.tier}>\n {plan.tier} {limitDesc ? `(${limitDesc})` : ''}\n </MenuItem>\n );\n })\n )}\n </Select>\n <FormHelperText>Select an API to view available tiers.</FormHelperText>\n </FormControl>\n\n <TextField\n label=\"Use case\"\n placeholder=\"Briefly describe your specific use case of using this API key\"\n multiline\n rows={2}\n fullWidth\n margin=\"normal\"\n value={useCase}\n onChange={e => setUseCase(e.target.value)}\n disabled={creating}\n inputProps={{ 'data-testid': 'usecase-input' }}\n />\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose} disabled={creating} data-testid=\"cancel-button\">\n Cancel\n </Button>\n <Button\n onClick={handleSubmit}\n color=\"primary\"\n variant=\"contained\"\n disabled={!selectedApi || !selectedTier || creating}\n startIcon={\n creating ? (\n <CircularProgress size={16} color=\"inherit\" />\n ) : undefined\n }\n data-testid=\"submit-button\"\n >\n {creating ? 'Submitting...' : 'Request'}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SimpleRequestAccessDialog.esm.js","sources":["../../../src/components/SimpleRequestAccessDialog/SimpleRequestAccessDialog.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport {\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n Button,\n TextField,\n Select,\n MenuItem,\n FormControl,\n InputLabel,\n Typography,\n CircularProgress,\n FormHelperText,\n} from '@material-ui/core';\nimport {\n useApi,\n configApiRef,\n fetchApiRef,\n alertApiRef,\n identityApiRef,\n} from '@backstage/core-plugin-api';\nimport useAsync from 'react-use/lib/useAsync';\nimport { kuadrantApiRef } from '../../api';\n\nexport interface SimpleRequestAccessDialogProps {\n open: boolean;\n onClose: () => void;\n onSuccess: () => void;\n}\n\ntype ApiProduct = {\n metadata: {\n name: string;\n namespace: string;\n };\n spec?: {\n publishStatus?: string;\n };\n status?: {\n discoveredPlans?: Array<{\n tier: string;\n limits?: Record<string, number>;\n }>;\n };\n};\n\nexport const SimpleRequestAccessDialog = ({\n open,\n onClose,\n onSuccess,\n}: SimpleRequestAccessDialogProps) => {\n const config = useApi(configApiRef);\n const fetchApi = useApi(fetchApiRef);\n const alertApi = useApi(alertApiRef);\n const identityApi = useApi(identityApiRef);\n const kuadrantApi = useApi(kuadrantApiRef);\n const backendUrl = config.getString('backend.baseUrl');\n\n const [selectedApi, setSelectedApi] = useState('');\n const [selectedTier, setSelectedTier] = useState('');\n const [useCase, setUseCase] = useState('');\n const [creating, setCreating] = useState(false);\n\n // Fetch all published API products\n const {\n value: apiProducts,\n loading: loadingProducts,\n } = useAsync(async () => {\n if (!open) return [];\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/apiproducts`,\n );\n if (!response.ok) {\n throw new Error('Failed to fetch API products');\n }\n const data = await response.json();\n // Filter to only show Published products\n return (data.items || []).filter(\n (p: ApiProduct) => p.spec?.publishStatus === 'Published',\n );\n }, [backendUrl, fetchApi, open]);\n\n // Get user email\n const { value: userEmail } = useAsync(async () => {\n const identity = await identityApi.getBackstageIdentity();\n\n // Extract username from userEntityRef (e.g., \"user:default/john\" -> \"john\")\n const username = identity.userEntityRef.split('/')[1] || 'unknown';\n\n // Construct email from username\n return `${username}@example.com`;\n }, [identityApi]);\n\n // Get available tiers for selected API\n const selectedProduct = apiProducts?.find(\n (p: ApiProduct) =>\n `${p.metadata.namespace}/${p.metadata.name}` === selectedApi,\n );\n const availableTiers = selectedProduct?.status?.discoveredPlans || [];\n\n const handleClose = () => {\n setSelectedApi('');\n setSelectedTier('');\n setUseCase('');\n onClose();\n };\n\n const handleSubmit = async () => {\n if (!selectedApi || !selectedTier) return;\n\n const [namespace, apiProductName] = selectedApi.split('/');\n\n setCreating(true);\n try {\n // 1. generate secret name and API key value\n const identity = await identityApi.getBackstageIdentity();\n const username = identity.userEntityRef.split('/')[1] || 'unknown';\n const randomSuffix = Math.random().toString(36).substring(2, 10);\n const secretName = `${username}-${apiProductName}-secret-${randomSuffix}`\n .toLowerCase()\n .replace(/[^a-z0-9-]/g, '-');\n const apiKeyValue = crypto.randomUUID().replace(/-/g, '');\n\n // 2. create secret first (design doc: secret must exist before APIKey)\n await kuadrantApi.createSecret(secretName, apiKeyValue);\n\n // 3. create APIKey referencing the pre-existing secret\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/requests`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n apiProductName,\n namespace,\n planTier: selectedTier,\n useCase: useCase.trim() || '',\n userEmail: userEmail || 'unknown',\n secretName,\n }),\n },\n );\n\n if (!response.ok) {\n let errorData;\n try {\n errorData = await response.json();\n } catch {\n errorData = { error: `Server returned ${response.status} ${response.statusText}` };\n }\n\n console.error('Backend error response:', {\n status: response.status,\n statusText: response.statusText,\n errorData,\n requestBody: {\n apiProductName,\n namespace,\n planTier: selectedTier,\n useCase: useCase.trim() || '',\n userEmail: userEmail || 'unknown',\n secretName: '(generated)',\n }\n });\n\n // Extract user-friendly error message\n const rawError = errorData.error || errorData.message || `Server returned ${response.status}`;\n\n // Try to extract validation error details from Kubernetes error messages\n // Example: \"failed to create apikeys: APIKey.devportal.kuadrant.io \"name\" is invalid: spec.requestedBy.email: Invalid value: \"admin\": spec.requestedBy.email in body should match '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$'\"\n let errorMsg = rawError;\n\n if (rawError.includes('spec.requestedBy.email')) {\n errorMsg = 'Invalid email format. Please contact your administrator to update your profile email.';\n } else if (rawError.includes('is invalid:')) {\n // Extract the validation message after \"is invalid:\"\n const match = rawError.match(/is invalid: (.+?)(?:\\s+\\(|$)/);\n if (match) {\n errorMsg = `Validation error: ${match[1]}`;\n }\n } else if (response.status === 403) {\n errorMsg = 'You do not have permission to request access to this API.';\n } else if (response.status === 404) {\n errorMsg = 'The selected API or tier was not found.';\n } else if (response.status >= 500) {\n errorMsg = `Server error: ${rawError}`;\n }\n\n // cleanup orphaned secret since APIKey creation failed\n await kuadrantApi.deleteSecret(secretName)\n .catch(e => console.warn('Failed to cleanup orphaned secret:', e));\n\n throw new Error(errorMsg);\n }\n\n alertApi.post({\n message: 'API key requested successfully',\n severity: 'success',\n display: 'transient',\n });\n\n handleClose();\n onSuccess();\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : 'unknown error occurred';\n console.error('Failed to create API key request:', {\n error: err,\n selectedApi,\n selectedTier,\n userEmail,\n });\n alertApi.post({\n message: `Failed to request API key: ${errorMessage}`,\n severity: 'error',\n display: 'permanent',\n });\n } finally {\n setCreating(false);\n }\n };\n\n return (\n <Dialog open={open} onClose={handleClose} maxWidth=\"sm\" fullWidth>\n <DialogTitle>Request API key</DialogTitle>\n <DialogContent>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Submit your request to generate an API key.\n </Typography>\n\n <FormControl fullWidth margin=\"normal\" disabled={creating || loadingProducts}>\n <InputLabel id=\"api-select-label\" required>\n API\n </InputLabel>\n <Select\n labelId=\"api-select-label\"\n value={selectedApi}\n onChange={e => {\n setSelectedApi(e.target.value as string);\n setSelectedTier(''); // Reset tier when API changes\n }}\n disabled={creating || loadingProducts}\n data-testid=\"api-select\"\n >\n {loadingProducts ? (\n <MenuItem disabled>Loading...</MenuItem>\n ) : (\n apiProducts?.map((product: ApiProduct) => (\n <MenuItem\n key={`${product.metadata.namespace}/${product.metadata.name}`}\n value={`${product.metadata.namespace}/${product.metadata.name}`}\n >\n {product.metadata.name}\n </MenuItem>\n ))\n )}\n </Select>\n <FormHelperText>\n Select one API. Please submit separate requests for multiple APIs.\n </FormHelperText>\n </FormControl>\n\n <FormControl\n fullWidth\n margin=\"normal\"\n disabled={creating || !selectedApi}\n required\n >\n <InputLabel id=\"tier-select-label\">Tiers</InputLabel>\n <Select\n labelId=\"tier-select-label\"\n value={selectedTier}\n onChange={e => setSelectedTier(e.target.value as string)}\n disabled={creating || !selectedApi}\n data-testid=\"tier-select\"\n >\n {!selectedApi ? (\n <MenuItem disabled>Select an API first</MenuItem>\n ) : availableTiers.length === 0 ? (\n <MenuItem disabled>No tiers available</MenuItem>\n ) : (\n availableTiers.map((plan: { tier: string; limits?: Record<string, number> }) => {\n const limitDesc = Object.entries(plan.limits || {})\n .map(([key, val]) => `${val} per ${key}`)\n .join(', ');\n return (\n <MenuItem key={plan.tier} value={plan.tier}>\n {plan.tier} {limitDesc ? `(${limitDesc})` : ''}\n </MenuItem>\n );\n })\n )}\n </Select>\n <FormHelperText>Select an API to view available tiers.</FormHelperText>\n </FormControl>\n\n <TextField\n label=\"Use case\"\n placeholder=\"Briefly describe your specific use case of using this API key\"\n multiline\n rows={2}\n fullWidth\n margin=\"normal\"\n value={useCase}\n onChange={e => setUseCase(e.target.value)}\n disabled={creating}\n inputProps={{ 'data-testid': 'usecase-input' }}\n />\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose} disabled={creating} data-testid=\"cancel-button\">\n Cancel\n </Button>\n <Button\n onClick={handleSubmit}\n color=\"primary\"\n variant=\"contained\"\n disabled={!selectedApi || !selectedTier || creating}\n startIcon={\n creating ? (\n <CircularProgress size={16} color=\"inherit\" />\n ) : undefined\n }\n data-testid=\"submit-button\"\n >\n {creating ? 'Submitting...' : 'Request'}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n"],"names":[],"mappings":";;;;;;AAgDO,MAAM,4BAA4B,CAAC;AAAA,EACxC,IAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAsC,KAAA;AACpC,EAAM,MAAA,MAAA,GAAS,OAAO,YAAY,CAAA;AAClC,EAAM,MAAA,QAAA,GAAW,OAAO,WAAW,CAAA;AACnC,EAAM,MAAA,QAAA,GAAW,OAAO,WAAW,CAAA;AACnC,EAAM,MAAA,WAAA,GAAc,OAAO,cAAc,CAAA;AACzC,EAAM,MAAA,WAAA,GAAc,OAAO,cAAc,CAAA;AACzC,EAAM,MAAA,UAAA,GAAa,MAAO,CAAA,SAAA,CAAU,iBAAiB,CAAA;AAErD,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAAS,EAAE,CAAA;AACjD,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,SAAS,EAAE,CAAA;AACnD,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,EAAE,CAAA;AACzC,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,SAAS,KAAK,CAAA;AAG9C,EAAM,MAAA;AAAA,IACJ,KAAO,EAAA,WAAA;AAAA,IACP,OAAS,EAAA;AAAA,GACX,GAAI,SAAS,YAAY;AACvB,IAAI,IAAA,CAAC,IAAM,EAAA,OAAO,EAAC;AACnB,IAAM,MAAA,QAAA,GAAW,MAAM,QAAS,CAAA,KAAA;AAAA,MAC9B,GAAG,UAAU,CAAA,yBAAA;AAAA,KACf;AACA,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAM,MAAA,IAAI,MAAM,8BAA8B,CAAA;AAAA;AAEhD,IAAM,MAAA,IAAA,GAAO,MAAM,QAAA,CAAS,IAAK,EAAA;AAEjC,IAAQ,OAAA,CAAA,IAAA,CAAK,KAAS,IAAA,EAAI,EAAA,MAAA;AAAA,MACxB,CAAC,CAAA,KAAkB,CAAE,CAAA,IAAA,EAAM,aAAkB,KAAA;AAAA,KAC/C;AAAA,GACC,EAAA,CAAC,UAAY,EAAA,QAAA,EAAU,IAAI,CAAC,CAAA;AAG/B,EAAA,MAAM,EAAE,KAAA,EAAO,SAAU,EAAA,GAAI,SAAS,YAAY;AAChD,IAAM,MAAA,QAAA,GAAW,MAAM,WAAA,CAAY,oBAAqB,EAAA;AAGxD,IAAA,MAAM,WAAW,QAAS,CAAA,aAAA,CAAc,MAAM,GAAG,CAAA,CAAE,CAAC,CAAK,IAAA,SAAA;AAGzD,IAAA,OAAO,GAAG,QAAQ,CAAA,YAAA,CAAA;AAAA,GACpB,EAAG,CAAC,WAAW,CAAC,CAAA;AAGhB,EAAA,MAAM,kBAAkB,WAAa,EAAA,IAAA;AAAA,IACnC,CAAC,CACC,KAAA,CAAA,EAAG,CAAE,CAAA,QAAA,CAAS,SAAS,CAAI,CAAA,EAAA,CAAA,CAAE,QAAS,CAAA,IAAI,CAAO,CAAA,KAAA;AAAA,GACrD;AACA,EAAA,MAAM,cAAiB,GAAA,eAAA,EAAiB,MAAQ,EAAA,eAAA,IAAmB,EAAC;AAEpE,EAAA,MAAM,cAAc,MAAM;AACxB,IAAA,cAAA,CAAe,EAAE,CAAA;AACjB,IAAA,eAAA,CAAgB,EAAE,CAAA;AAClB,IAAA,UAAA,CAAW,EAAE,CAAA;AACb,IAAQ,OAAA,EAAA;AAAA,GACV;AAEA,EAAA,MAAM,eAAe,YAAY;AAC/B,IAAI,IAAA,CAAC,WAAe,IAAA,CAAC,YAAc,EAAA;AAEnC,IAAA,MAAM,CAAC,SAAW,EAAA,cAAc,CAAI,GAAA,WAAA,CAAY,MAAM,GAAG,CAAA;AAEzD,IAAA,WAAA,CAAY,IAAI,CAAA;AAChB,IAAI,IAAA;AAEF,MAAM,MAAA,QAAA,GAAW,MAAM,WAAA,CAAY,oBAAqB,EAAA;AACxD,MAAA,MAAM,WAAW,QAAS,CAAA,aAAA,CAAc,MAAM,GAAG,CAAA,CAAE,CAAC,CAAK,IAAA,SAAA;AACzD,MAAM,MAAA,YAAA,GAAe,KAAK,MAAO,EAAA,CAAE,SAAS,EAAE,CAAA,CAAE,SAAU,CAAA,CAAA,EAAG,EAAE,CAAA;AAC/D,MAAA,MAAM,UAAa,GAAA,CAAA,EAAG,QAAQ,CAAA,CAAA,EAAI,cAAc,CAAA,QAAA,EAAW,YAAY,CAAA,CAAA,CACpE,WAAY,EAAA,CACZ,OAAQ,CAAA,aAAA,EAAe,GAAG,CAAA;AAC7B,MAAA,MAAM,cAAc,MAAO,CAAA,UAAA,EAAa,CAAA,OAAA,CAAQ,MAAM,EAAE,CAAA;AAGxD,MAAM,MAAA,WAAA,CAAY,YAAa,CAAA,UAAA,EAAY,WAAW,CAAA;AAGtD,MAAM,MAAA,QAAA,GAAW,MAAM,QAAS,CAAA,KAAA;AAAA,QAC9B,GAAG,UAAU,CAAA,sBAAA,CAAA;AAAA,QACb;AAAA,UACE,MAAQ,EAAA,MAAA;AAAA,UACR,OAAS,EAAA;AAAA,YACP,cAAgB,EAAA;AAAA,WAClB;AAAA,UACA,IAAA,EAAM,KAAK,SAAU,CAAA;AAAA,YACnB,cAAA;AAAA,YACA,SAAA;AAAA,YACA,QAAU,EAAA,YAAA;AAAA,YACV,OAAA,EAAS,OAAQ,CAAA,IAAA,EAAU,IAAA,EAAA;AAAA,YAC3B,WAAW,SAAa,IAAA,SAAA;AAAA,YACxB;AAAA,WACD;AAAA;AACH,OACF;AAEA,MAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,QAAI,IAAA,SAAA;AACJ,QAAI,IAAA;AACF,UAAY,SAAA,GAAA,MAAM,SAAS,IAAK,EAAA;AAAA,SAC1B,CAAA,MAAA;AACN,UAAY,SAAA,GAAA,EAAE,OAAO,CAAmB,gBAAA,EAAA,QAAA,CAAS,MAAM,CAAI,CAAA,EAAA,QAAA,CAAS,UAAU,CAAG,CAAA,EAAA;AAAA;AAGnF,QAAA,OAAA,CAAQ,MAAM,yBAA2B,EAAA;AAAA,UACvC,QAAQ,QAAS,CAAA,MAAA;AAAA,UACjB,YAAY,QAAS,CAAA,UAAA;AAAA,UACrB,SAAA;AAAA,UACA,WAAa,EAAA;AAAA,YACX,cAAA;AAAA,YACA,SAAA;AAAA,YACA,QAAU,EAAA,YAAA;AAAA,YACV,OAAA,EAAS,OAAQ,CAAA,IAAA,EAAU,IAAA,EAAA;AAAA,YAC3B,WAAW,SAAa,IAAA,SAAA;AAAA,YACxB,UAAY,EAAA;AAAA;AACd,SACD,CAAA;AAGD,QAAA,MAAM,WAAW,SAAU,CAAA,KAAA,IAAS,UAAU,OAAW,IAAA,CAAA,gBAAA,EAAmB,SAAS,MAAM,CAAA,CAAA;AAI3F,QAAA,IAAI,QAAW,GAAA,QAAA;AAEf,QAAI,IAAA,QAAA,CAAS,QAAS,CAAA,wBAAwB,CAAG,EAAA;AAC/C,UAAW,QAAA,GAAA,uFAAA;AAAA,SACF,MAAA,IAAA,QAAA,CAAS,QAAS,CAAA,aAAa,CAAG,EAAA;AAE3C,UAAM,MAAA,KAAA,GAAQ,QAAS,CAAA,KAAA,CAAM,8BAA8B,CAAA;AAC3D,UAAA,IAAI,KAAO,EAAA;AACT,YAAW,QAAA,GAAA,CAAA,kBAAA,EAAqB,KAAM,CAAA,CAAC,CAAC,CAAA,CAAA;AAAA;AAC1C,SACF,MAAA,IAAW,QAAS,CAAA,MAAA,KAAW,GAAK,EAAA;AAClC,UAAW,QAAA,GAAA,2DAAA;AAAA,SACb,MAAA,IAAW,QAAS,CAAA,MAAA,KAAW,GAAK,EAAA;AAClC,UAAW,QAAA,GAAA,yCAAA;AAAA,SACb,MAAA,IAAW,QAAS,CAAA,MAAA,IAAU,GAAK,EAAA;AACjC,UAAA,QAAA,GAAW,iBAAiB,QAAQ,CAAA,CAAA;AAAA;AAItC,QAAM,MAAA,WAAA,CAAY,YAAa,CAAA,UAAU,CACtC,CAAA,KAAA,CAAM,OAAK,OAAQ,CAAA,IAAA,CAAK,oCAAsC,EAAA,CAAC,CAAC,CAAA;AAEnE,QAAM,MAAA,IAAI,MAAM,QAAQ,CAAA;AAAA;AAG1B,MAAA,QAAA,CAAS,IAAK,CAAA;AAAA,QACZ,OAAS,EAAA,gCAAA;AAAA,QACT,QAAU,EAAA,SAAA;AAAA,QACV,OAAS,EAAA;AAAA,OACV,CAAA;AAED,MAAY,WAAA,EAAA;AACZ,MAAU,SAAA,EAAA;AAAA,aACH,GAAK,EAAA;AACZ,MAAA,MAAM,YACJ,GAAA,GAAA,YAAe,KAAQ,GAAA,GAAA,CAAI,OAAU,GAAA,wBAAA;AACvC,MAAA,OAAA,CAAQ,MAAM,mCAAqC,EAAA;AAAA,QACjD,KAAO,EAAA,GAAA;AAAA,QACP,WAAA;AAAA,QACA,YAAA;AAAA,QACA;AAAA,OACD,CAAA;AACD,MAAA,QAAA,CAAS,IAAK,CAAA;AAAA,QACZ,OAAA,EAAS,8BAA8B,YAAY,CAAA,CAAA;AAAA,QACnD,QAAU,EAAA,OAAA;AAAA,QACV,OAAS,EAAA;AAAA,OACV,CAAA;AAAA,KACD,SAAA;AACA,MAAA,WAAA,CAAY,KAAK,CAAA;AAAA;AACnB,GACF;AAEA,EAAA,2CACG,MAAO,EAAA,EAAA,IAAA,EAAY,OAAS,EAAA,WAAA,EAAa,UAAS,IAAK,EAAA,SAAA,EAAS,IAC/D,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,mBAAY,iBAAe,CAAA,sCAC3B,aACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,OAAQ,EAAA,OAAA,EAAQ,KAAM,EAAA,eAAA,EAAA,EAAgB,6CAElD,CAEA,kBAAA,KAAA,CAAA,aAAA,CAAC,eAAY,SAAS,EAAA,IAAA,EAAC,QAAO,QAAS,EAAA,QAAA,EAAU,QAAY,IAAA,eAAA,EAAA,sCAC1D,UAAW,EAAA,EAAA,EAAA,EAAG,oBAAmB,QAAQ,EAAA,IAAA,EAAA,EAAC,KAE3C,CACA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,OAAQ,EAAA,kBAAA;AAAA,MACR,KAAO,EAAA,WAAA;AAAA,MACP,UAAU,CAAK,CAAA,KAAA;AACb,QAAe,cAAA,CAAA,CAAA,CAAE,OAAO,KAAe,CAAA;AACvC,QAAA,eAAA,CAAgB,EAAE,CAAA;AAAA,OACpB;AAAA,MACA,UAAU,QAAY,IAAA,eAAA;AAAA,MACtB,aAAY,EAAA;AAAA,KAAA;AAAA,IAEX,eAAA,mBACE,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EAAS,QAAQ,EAAA,IAAA,EAAA,EAAC,YAAU,CAE7B,GAAA,WAAA,EAAa,GAAI,CAAA,CAAC,OAChB,qBAAA,KAAA,CAAA,aAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,GAAA,EAAK,GAAG,OAAQ,CAAA,QAAA,CAAS,SAAS,CAAI,CAAA,EAAA,OAAA,CAAQ,SAAS,IAAI,CAAA,CAAA;AAAA,QAC3D,KAAA,EAAO,GAAG,OAAQ,CAAA,QAAA,CAAS,SAAS,CAAI,CAAA,EAAA,OAAA,CAAQ,SAAS,IAAI,CAAA;AAAA,OAAA;AAAA,MAE5D,QAAQ,QAAS,CAAA;AAAA,KAErB;AAAA,GAGL,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAe,EAAA,IAAA,EAAA,oEAEhB,CACF,CAEA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,WAAA;AAAA,IAAA;AAAA,MACC,SAAS,EAAA,IAAA;AAAA,MACT,MAAO,EAAA,QAAA;AAAA,MACP,QAAA,EAAU,YAAY,CAAC,WAAA;AAAA,MACvB,QAAQ,EAAA;AAAA,KAAA;AAAA,oBAEP,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,EAAG,EAAA,mBAAA,EAAA,EAAoB,OAAK,CAAA;AAAA,oBACxC,KAAA,CAAA,aAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,OAAQ,EAAA,mBAAA;AAAA,QACR,KAAO,EAAA,YAAA;AAAA,QACP,QAAU,EAAA,CAAA,CAAA,KAAK,eAAgB,CAAA,CAAA,CAAE,OAAO,KAAe,CAAA;AAAA,QACvD,QAAA,EAAU,YAAY,CAAC,WAAA;AAAA,QACvB,aAAY,EAAA;AAAA,OAAA;AAAA,MAEX,CAAC,8BACC,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EAAS,UAAQ,IAAC,EAAA,EAAA,qBAAmB,IACpC,cAAe,CAAA,MAAA,KAAW,oBAC3B,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EAAS,UAAQ,IAAC,EAAA,EAAA,oBAAkB,IAErC,cAAe,CAAA,GAAA,CAAI,CAAC,IAA4D,KAAA;AAC9E,QAAM,MAAA,SAAA,GAAY,OAAO,OAAQ,CAAA,IAAA,CAAK,UAAU,EAAE,EAC/C,GAAI,CAAA,CAAC,CAAC,GAAK,EAAA,GAAG,MAAM,CAAG,EAAA,GAAG,QAAQ,GAAG,CAAA,CAAE,CACvC,CAAA,IAAA,CAAK,IAAI,CAAA;AACZ,QAAA,uBACG,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EAAS,GAAK,EAAA,IAAA,CAAK,MAAM,KAAO,EAAA,IAAA,CAAK,IACnC,EAAA,EAAA,IAAA,CAAK,MAAK,GAAE,EAAA,SAAA,GAAY,CAAI,CAAA,EAAA,SAAS,MAAM,EAC9C,CAAA;AAAA,OAEH;AAAA,KAEL;AAAA,oBACA,KAAA,CAAA,aAAA,CAAC,sBAAe,wCAAsC;AAAA,GAGxD,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,KAAM,EAAA,UAAA;AAAA,MACN,WAAY,EAAA,+DAAA;AAAA,MACZ,SAAS,EAAA,IAAA;AAAA,MACT,IAAM,EAAA,CAAA;AAAA,MACN,SAAS,EAAA,IAAA;AAAA,MACT,MAAO,EAAA,QAAA;AAAA,MACP,KAAO,EAAA,OAAA;AAAA,MACP,QAAU,EAAA,CAAA,CAAA,KAAK,UAAW,CAAA,CAAA,CAAE,OAAO,KAAK,CAAA;AAAA,MACxC,QAAU,EAAA,QAAA;AAAA,MACV,UAAA,EAAY,EAAE,aAAA,EAAe,eAAgB;AAAA;AAAA,GAEjD,CAAA,kBACC,KAAA,CAAA,aAAA,CAAA,aAAA,EAAA,IAAA,kBACE,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA,EAAO,OAAS,EAAA,WAAA,EAAa,QAAU,EAAA,QAAA,EAAU,aAAY,EAAA,eAAA,EAAA,EAAgB,QAE9E,CACA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,OAAS,EAAA,YAAA;AAAA,MACT,KAAM,EAAA,SAAA;AAAA,MACN,OAAQ,EAAA,WAAA;AAAA,MACR,QAAU,EAAA,CAAC,WAAe,IAAA,CAAC,YAAgB,IAAA,QAAA;AAAA,MAC3C,SAAA,EACE,2BACG,KAAA,CAAA,aAAA,CAAA,gBAAA,EAAA,EAAiB,MAAM,EAAI,EAAA,KAAA,EAAM,WAAU,CAC1C,GAAA,SAAA;AAAA,MAEN,aAAY,EAAA;AAAA,KAAA;AAAA,IAEX,WAAW,eAAkB,GAAA;AAAA,GAElC,CACF,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import ApiOutlined from '@mui/icons-material/ApiOutlined';
|
|
3
|
+
import KeyOutlined from '@mui/icons-material/KeyOutlined';
|
|
4
|
+
import ApprovalOutlined from '@mui/icons-material/ApprovalOutlined';
|
|
5
|
+
|
|
6
|
+
const ApiIcon = (props) => /* @__PURE__ */ React.createElement(ApiOutlined, { ...props });
|
|
7
|
+
const KeyIcon = (props) => /* @__PURE__ */ React.createElement(KeyOutlined, { ...props });
|
|
8
|
+
const ApprovalIcon = (props) => /* @__PURE__ */ React.createElement(ApprovalOutlined, { ...props });
|
|
9
|
+
|
|
10
|
+
export { ApiIcon, ApprovalIcon, KeyIcon };
|
|
11
|
+
//# sourceMappingURL=icons.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icons.esm.js","sources":["../../src/components/icons.tsx"],"sourcesContent":["import React from 'react';\nimport ApiOutlined from '@mui/icons-material/ApiOutlined';\nimport KeyOutlined from '@mui/icons-material/KeyOutlined';\nimport ApprovalOutlined from '@mui/icons-material/ApprovalOutlined';\nimport { SvgIconProps } from '@mui/material/SvgIcon';\n\nexport const ApiIcon = (props: SvgIconProps) => <ApiOutlined {...props} />;\nexport const KeyIcon = (props: SvgIconProps) => <KeyOutlined {...props} />;\nexport const ApprovalIcon = (props: SvgIconProps) => <ApprovalOutlined {...props} />;\n"],"names":[],"mappings":";;;;;AAMO,MAAM,UAAU,CAAC,KAAA,qBAAyB,KAAA,CAAA,aAAA,CAAA,WAAA,EAAA,EAAa,GAAG,KAAO,EAAA;AACjE,MAAM,UAAU,CAAC,KAAA,qBAAyB,KAAA,CAAA,aAAA,CAAA,WAAA,EAAA,EAAa,GAAG,KAAO,EAAA;AACjE,MAAM,eAAe,CAAC,KAAA,qBAAyB,KAAA,CAAA,aAAA,CAAA,gBAAA,EAAA,EAAkB,GAAG,KAAO,EAAA;;;;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import * as react from 'react';
|
|
|
2
2
|
import react__default from 'react';
|
|
3
3
|
import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
|
|
4
4
|
import { DiscoveryApi, FetchApi, IdentityApi } from '@backstage/core-plugin-api';
|
|
5
|
+
import { SvgIconProps } from '@mui/material/SvgIcon';
|
|
5
6
|
import * as _backstage_plugin_permission_common from '@backstage/plugin-permission-common';
|
|
6
7
|
|
|
7
8
|
interface ApiKeyManagementTabProps {
|
|
@@ -27,12 +28,17 @@ declare const EntityKuadrantApiKeyManagementTab: ({ namespace: propNamespace, }:
|
|
|
27
28
|
declare const EntityKuadrantApiKeysContent: ({ namespace: propNamespace, }: ApiKeyManagementTabProps) => react.JSX.Element;
|
|
28
29
|
declare const EntityKuadrantApiProductInfoContent: () => react.JSX.Element;
|
|
29
30
|
declare const ApiKeyDetailPage: () => react.JSX.Element;
|
|
30
|
-
declare const EntityKuadrantApiApprovalTab: () => react.JSX.Element;
|
|
31
31
|
declare const EntityKuadrantApiProductOpenApiAlert: () => react.JSX.Element | null;
|
|
32
32
|
declare const ApiProductDetailPage: () => react.JSX.Element;
|
|
33
33
|
|
|
34
34
|
declare const ApiProductInfoCard: () => react__default.JSX.Element;
|
|
35
35
|
|
|
36
|
+
declare const KuadrantIcon: (props: SvgIconProps) => react__default.JSX.Element;
|
|
37
|
+
|
|
38
|
+
declare const ApiIcon: (props: SvgIconProps) => react__default.JSX.Element;
|
|
39
|
+
declare const KeyIcon: (props: SvgIconProps) => react__default.JSX.Element;
|
|
40
|
+
declare const ApprovalIcon: (props: SvgIconProps) => react__default.JSX.Element;
|
|
41
|
+
|
|
36
42
|
/**
|
|
37
43
|
* permission definitions for the kuadrant plugin
|
|
38
44
|
*
|
|
@@ -150,7 +156,7 @@ declare const kuadrantApiKeyApprovePermission: _backstage_plugin_permission_comm
|
|
|
150
156
|
declare const kuadrantPermissions: (_backstage_plugin_permission_common.BasicPermission | _backstage_plugin_permission_common.ResourcePermission<"apiproduct">)[];
|
|
151
157
|
|
|
152
158
|
type PlanTier = string;
|
|
153
|
-
type RequestPhase = 'Pending' | 'Approved' | '
|
|
159
|
+
type RequestPhase = 'Pending' | 'Approved' | 'Denied';
|
|
154
160
|
interface PlanLimits {
|
|
155
161
|
daily?: number;
|
|
156
162
|
weekly?: number;
|
|
@@ -173,6 +179,7 @@ interface StatusCondition {
|
|
|
173
179
|
interface APIKeySpec {
|
|
174
180
|
apiProductRef: {
|
|
175
181
|
name: string;
|
|
182
|
+
namespace: string;
|
|
176
183
|
};
|
|
177
184
|
planTier: PlanTier;
|
|
178
185
|
useCase: string;
|
|
@@ -180,6 +187,9 @@ interface APIKeySpec {
|
|
|
180
187
|
userId: string;
|
|
181
188
|
email: string;
|
|
182
189
|
};
|
|
190
|
+
secretRef: {
|
|
191
|
+
name: string;
|
|
192
|
+
};
|
|
183
193
|
}
|
|
184
194
|
interface CredentialsAuthorizationHeader {
|
|
185
195
|
prefix?: string;
|
|
@@ -214,16 +224,21 @@ interface APIKeyAuthScheme {
|
|
|
214
224
|
credentials?: Credentials;
|
|
215
225
|
}
|
|
216
226
|
interface APIKeyStatus {
|
|
227
|
+
/** @deprecated Use getAPIKeyPhase(conditions) instead. Will be removed after all components migrated. */
|
|
217
228
|
phase?: RequestPhase;
|
|
229
|
+
/** @deprecated Will be removed in future version. */
|
|
218
230
|
reviewedBy?: string;
|
|
231
|
+
/** @deprecated Will be removed in future version. */
|
|
219
232
|
reviewedAt?: string;
|
|
220
|
-
|
|
221
|
-
limits?: PlanLimits;
|
|
233
|
+
/** @deprecated Use spec.secretRef instead. */
|
|
222
234
|
secretRef?: {
|
|
223
235
|
name: string;
|
|
224
236
|
key: string;
|
|
225
237
|
};
|
|
238
|
+
/** @deprecated Secret viewing no longer restricted. Will be removed in future version. */
|
|
226
239
|
canReadSecret?: boolean;
|
|
240
|
+
apiHostname?: string;
|
|
241
|
+
limits?: PlanLimits;
|
|
227
242
|
authScheme?: APIKeyAuthScheme;
|
|
228
243
|
conditions?: StatusCondition[];
|
|
229
244
|
}
|
|
@@ -246,6 +261,7 @@ interface APIKeyRequest {
|
|
|
246
261
|
planTier: PlanTier;
|
|
247
262
|
useCase: string;
|
|
248
263
|
userEmail: string;
|
|
264
|
+
secretName?: string;
|
|
249
265
|
}
|
|
250
266
|
interface APIProductSpec {
|
|
251
267
|
displayName: string;
|
|
@@ -449,6 +465,20 @@ interface KuadrantAPI {
|
|
|
449
465
|
* @returns Promise with list of requests in the namespace
|
|
450
466
|
*/
|
|
451
467
|
getRequestsByNamespace(namespace: string): Promise<KuadrantList<APIKey>>;
|
|
468
|
+
/**
|
|
469
|
+
* Fetch the current user's API key requests for a specific APIProduct
|
|
470
|
+
* @param apiProductName - Name of the APIProduct
|
|
471
|
+
* @param apiProductNamespace - Namespace of the APIProduct
|
|
472
|
+
* @returns Promise with list of the user's API key requests for this product
|
|
473
|
+
*/
|
|
474
|
+
getRequestsByApiProduct(apiProductName: string, apiProductNamespace: string): Promise<KuadrantList<APIKey>>;
|
|
475
|
+
/**
|
|
476
|
+
* Fetch all API key requests for a specific APIProduct (admin view)
|
|
477
|
+
* @param apiProductName - Name of the APIProduct
|
|
478
|
+
* @param apiProductNamespace - Namespace of the APIProduct
|
|
479
|
+
* @returns Promise with list of all API key requests for this product
|
|
480
|
+
*/
|
|
481
|
+
getAllRequestsByApiProduct(apiProductName: string, apiProductNamespace: string): Promise<KuadrantList<APIKey>>;
|
|
452
482
|
/**
|
|
453
483
|
* Fetch a single API key request
|
|
454
484
|
* @param namespace - API key request name
|
|
@@ -490,7 +520,7 @@ interface KuadrantAPI {
|
|
|
490
520
|
* @param namespace - Kubernetes namespace
|
|
491
521
|
* @param name - API key request name
|
|
492
522
|
* @param reviewedBy - Reviewed By User / System
|
|
493
|
-
* @returns Promise with the
|
|
523
|
+
* @returns Promise with the denied API key
|
|
494
524
|
*/
|
|
495
525
|
rejectRequest(namespace: string, name: string, reviewedBy: string): Promise<APIKey>;
|
|
496
526
|
/**
|
|
@@ -587,6 +617,20 @@ interface KuadrantAPI {
|
|
|
587
617
|
* @returns Promise with list of all ratelimitpolicies
|
|
588
618
|
*/
|
|
589
619
|
getRateLimitPolicies(): Promise<KuadrantList<RateLimitPolicy>>;
|
|
620
|
+
/**
|
|
621
|
+
* Create a secret in consumer's own namespace
|
|
622
|
+
* Backend determines namespace from authenticated user identity.
|
|
623
|
+
* @param name - Secret name
|
|
624
|
+
* @param apiKeyValue - API key value to store
|
|
625
|
+
* @returns Promise that resolves when secret is created
|
|
626
|
+
*/
|
|
627
|
+
createSecret(name: string, apiKeyValue: string): Promise<void>;
|
|
628
|
+
/**
|
|
629
|
+
* Delete a secret from consumer's own namespace
|
|
630
|
+
* @param name - Secret name
|
|
631
|
+
* @returns Promise that resolves when secret is deleted
|
|
632
|
+
*/
|
|
633
|
+
deleteSecret(name: string): Promise<void>;
|
|
590
634
|
}
|
|
591
635
|
/**
|
|
592
636
|
* API reference for the Kuadrant API
|
|
@@ -616,6 +660,8 @@ declare class KuadrantApiClient implements KuadrantAPI {
|
|
|
616
660
|
getRequests(): Promise<KuadrantList<APIKey>>;
|
|
617
661
|
getAllRequests(): Promise<KuadrantList<APIKey>>;
|
|
618
662
|
getRequestsByNamespace(namespace: string): Promise<KuadrantList<APIKey>>;
|
|
663
|
+
getRequestsByApiProduct(apiProductName: string, apiProductNamespace: string): Promise<KuadrantList<APIKey>>;
|
|
664
|
+
getAllRequestsByApiProduct(apiProductName: string, apiProductNamespace: string): Promise<KuadrantList<APIKey>>;
|
|
619
665
|
getRequest(namespace: string, name: string): Promise<APIKey>;
|
|
620
666
|
createRequest(request: APIKeyRequest): Promise<APIKey>;
|
|
621
667
|
updateRequest(namespace: string, name: string, patch: Partial<APIKeySpec>): Promise<APIKey>;
|
|
@@ -642,6 +688,8 @@ declare class KuadrantApiClient implements KuadrantAPI {
|
|
|
642
688
|
getPlanPolicies(): Promise<KuadrantList<PlanPolicy>>;
|
|
643
689
|
getAuthPolicies(): Promise<KuadrantList<AuthPolicy>>;
|
|
644
690
|
getRateLimitPolicies(): Promise<KuadrantList<RateLimitPolicy>>;
|
|
691
|
+
createSecret(name: string, apiKeyValue: string): Promise<void>;
|
|
692
|
+
deleteSecret(name: string): Promise<void>;
|
|
645
693
|
}
|
|
646
694
|
|
|
647
695
|
/**
|
|
@@ -654,4 +702,4 @@ declare const kuadrantApiFactory: _backstage_core_plugin_api.ApiFactory<Kuadrant
|
|
|
654
702
|
identityApi: _backstage_core_plugin_api.IdentityApi;
|
|
655
703
|
}>;
|
|
656
704
|
|
|
657
|
-
export { ApiAccessCard, ApiKeyApprovalPage, ApiKeyDetailPage, ApiKeyManagementTab, ApiProductDetailPage, ApiProductInfoCard, ApiProductsPage,
|
|
705
|
+
export { ApiAccessCard, ApiIcon, ApiKeyApprovalPage, ApiKeyDetailPage, ApiKeyManagementTab, ApiProductDetailPage, ApiProductInfoCard, ApiProductsPage, ApprovalIcon, EntityKuadrantApiAccessCard, EntityKuadrantApiKeyManagementTab, EntityKuadrantApiKeysContent, EntityKuadrantApiProductInfoContent, EntityKuadrantApiProductOpenApiAlert, KeyIcon, type KuadrantAPI, KuadrantIcon, KuadrantPage, MyApiKeysPage, kuadrantApiFactory, kuadrantApiKeyApprovePermission, kuadrantApiKeyCreatePermission, kuadrantApiKeyDeleteAllPermission, kuadrantApiKeyDeleteOwnPermission, kuadrantApiKeyReadAllPermission, kuadrantApiKeyReadOwnPermission, kuadrantApiKeyUpdateAllPermission, kuadrantApiKeyUpdateOwnPermission, kuadrantApiProductCreatePermission, kuadrantApiProductDeleteAllPermission, kuadrantApiProductDeleteOwnPermission, kuadrantApiProductListPermission, kuadrantApiProductReadAllPermission, kuadrantApiProductReadOwnPermission, kuadrantApiProductUpdateAllPermission, kuadrantApiProductUpdateOwnPermission, kuadrantApiRef, kuadrantAuthPolicyListPermission, kuadrantPermissions, kuadrantPlanPolicyCreatePermission, kuadrantPlanPolicyDeletePermission, kuadrantPlanPolicyListPermission, kuadrantPlanPolicyReadPermission, kuadrantPlanPolicyUpdatePermission, kuadrantPlugin, kuadrantRateLimitPolicyListPermission };
|
package/dist/index.esm.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
export { ApiKeyApprovalPage, ApiKeyDetailPage, ApiProductDetailPage, ApiProductsPage, EntityKuadrantApiAccessCard,
|
|
1
|
+
export { ApiKeyApprovalPage, ApiKeyDetailPage, ApiProductDetailPage, ApiProductsPage, EntityKuadrantApiAccessCard, EntityKuadrantApiKeyManagementTab, EntityKuadrantApiKeysContent, EntityKuadrantApiProductInfoContent, EntityKuadrantApiProductOpenApiAlert, KuadrantPage, MyApiKeysPage, kuadrantPlugin } from './plugin.esm.js';
|
|
2
2
|
export { ApiAccessCard } from './components/ApiAccessCard/ApiAccessCard.esm.js';
|
|
3
3
|
export { ApiKeyManagementTab } from './components/ApiKeyManagementTab/ApiKeyManagementTab.esm.js';
|
|
4
4
|
export { ApiProductInfoCard } from './components/ApiProductInfoCard/ApiProductInfoCard.esm.js';
|
|
5
|
+
export { KuadrantIcon } from './components/KuadrantIcon/KuadrantIcon.esm.js';
|
|
6
|
+
export { ApiIcon, ApprovalIcon, KeyIcon } from './components/icons.esm.js';
|
|
5
7
|
export { kuadrantApiKeyApprovePermission, kuadrantApiKeyCreatePermission, kuadrantApiKeyDeleteAllPermission, kuadrantApiKeyDeleteOwnPermission, kuadrantApiKeyReadAllPermission, kuadrantApiKeyReadOwnPermission, kuadrantApiKeyUpdateAllPermission, kuadrantApiKeyUpdateOwnPermission, kuadrantApiProductCreatePermission, kuadrantApiProductDeleteAllPermission, kuadrantApiProductDeleteOwnPermission, kuadrantApiProductListPermission, kuadrantApiProductReadAllPermission, kuadrantApiProductReadOwnPermission, kuadrantApiProductUpdateAllPermission, kuadrantApiProductUpdateOwnPermission, kuadrantAuthPolicyListPermission, kuadrantPermissions, kuadrantPlanPolicyCreatePermission, kuadrantPlanPolicyDeletePermission, kuadrantPlanPolicyListPermission, kuadrantPlanPolicyReadPermission, kuadrantPlanPolicyUpdatePermission, kuadrantRateLimitPolicyListPermission } from './permissions.esm.js';
|
|
6
8
|
export { kuadrantApiRef } from './api.esm.js';
|
|
7
9
|
export { kuadrantApiFactory } from './apis.esm.js';
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
|
package/dist/plugin.esm.js
CHANGED
|
@@ -32,7 +32,7 @@ const MyApiKeysPage = kuadrantPlugin.provide(
|
|
|
32
32
|
const ApiKeyApprovalPage = kuadrantPlugin.provide(
|
|
33
33
|
createRoutableExtension({
|
|
34
34
|
name: "ApiKeyApprovalPage",
|
|
35
|
-
component: () => import('./components/ApiKeyApprovalPage/index.esm.js').then((m) => m.
|
|
35
|
+
component: () => import('./components/ApiKeyApprovalPage/index.esm.js').then((m) => m.ApiKeyApprovalPageWithPermissions),
|
|
36
36
|
mountPoint: rootRouteRef
|
|
37
37
|
})
|
|
38
38
|
);
|
|
@@ -75,14 +75,6 @@ const ApiKeyDetailPage = kuadrantPlugin.provide(
|
|
|
75
75
|
mountPoint: rootRouteRef
|
|
76
76
|
})
|
|
77
77
|
);
|
|
78
|
-
const EntityKuadrantApiApprovalTab = kuadrantPlugin.provide(
|
|
79
|
-
createComponentExtension({
|
|
80
|
-
name: "EntityKuadrantApiApprovalTab",
|
|
81
|
-
component: {
|
|
82
|
-
lazy: () => import('./components/EntityApiApprovalTab/index.esm.js').then((m) => m.EntityApiApprovalTab)
|
|
83
|
-
}
|
|
84
|
-
})
|
|
85
|
-
);
|
|
86
78
|
const EntityKuadrantApiProductOpenApiAlert = kuadrantPlugin.provide(
|
|
87
79
|
createComponentExtension({
|
|
88
80
|
name: "EntityKuadrantApiProductOpenApiAlert",
|
|
@@ -99,5 +91,5 @@ const ApiProductDetailPage = kuadrantPlugin.provide(
|
|
|
99
91
|
})
|
|
100
92
|
);
|
|
101
93
|
|
|
102
|
-
export { ApiKeyApprovalPage, ApiKeyDetailPage, ApiProductDetailPage, ApiProductsPage, EntityKuadrantApiAccessCard,
|
|
94
|
+
export { ApiKeyApprovalPage, ApiKeyDetailPage, ApiProductDetailPage, ApiProductsPage, EntityKuadrantApiAccessCard, EntityKuadrantApiKeyManagementTab, EntityKuadrantApiKeysContent, EntityKuadrantApiProductInfoContent, EntityKuadrantApiProductOpenApiAlert, KuadrantPage, MyApiKeysPage, kuadrantPlugin };
|
|
103
95
|
//# sourceMappingURL=plugin.esm.js.map
|
package/dist/plugin.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.esm.js","sources":["../src/plugin.ts"],"sourcesContent":["import {\n createPlugin,\n createRoutableExtension,\n createComponentExtension,\n} from '@backstage/core-plugin-api';\n\nimport { rootRouteRef, resourceRouteRef } from './routes';\n\nexport const kuadrantPlugin = createPlugin({\n id: 'kuadrant',\n routes: {\n root: rootRouteRef,\n resource: resourceRouteRef,\n },\n});\n\nexport const KuadrantPage = kuadrantPlugin.provide(\n createRoutableExtension({\n name: 'KuadrantPage',\n component: () =>\n import('./components/KuadrantPage').then(m => m.ApiProductsPage),\n mountPoint: rootRouteRef,\n }),\n);\n\nexport const ApiProductsPage = kuadrantPlugin.provide(\n createRoutableExtension({\n name: 'ApiProductsPage',\n component: () =>\n import('./components/KuadrantPage').then(m => m.ApiProductsPage),\n mountPoint: rootRouteRef,\n }),\n);\n\nexport const MyApiKeysPage = kuadrantPlugin.provide(\n createRoutableExtension({\n name: 'MyApiKeysPage',\n component: () =>\n import('./components/MyApiKeysPage').then(m => m.MyApiKeysPage),\n mountPoint: rootRouteRef,\n }),\n);\n\nexport const ApiKeyApprovalPage = kuadrantPlugin.provide(\n createRoutableExtension({\n name: 'ApiKeyApprovalPage',\n component: () =>\n import('./components/ApiKeyApprovalPage').then(m => m.
|
|
1
|
+
{"version":3,"file":"plugin.esm.js","sources":["../src/plugin.ts"],"sourcesContent":["import {\n createPlugin,\n createRoutableExtension,\n createComponentExtension,\n} from '@backstage/core-plugin-api';\n\nimport { rootRouteRef, resourceRouteRef } from './routes';\n\nexport const kuadrantPlugin = createPlugin({\n id: 'kuadrant',\n routes: {\n root: rootRouteRef,\n resource: resourceRouteRef,\n },\n});\n\nexport const KuadrantPage = kuadrantPlugin.provide(\n createRoutableExtension({\n name: 'KuadrantPage',\n component: () =>\n import('./components/KuadrantPage').then(m => m.ApiProductsPage),\n mountPoint: rootRouteRef,\n }),\n);\n\nexport const ApiProductsPage = kuadrantPlugin.provide(\n createRoutableExtension({\n name: 'ApiProductsPage',\n component: () =>\n import('./components/KuadrantPage').then(m => m.ApiProductsPage),\n mountPoint: rootRouteRef,\n }),\n);\n\nexport const MyApiKeysPage = kuadrantPlugin.provide(\n createRoutableExtension({\n name: 'MyApiKeysPage',\n component: () =>\n import('./components/MyApiKeysPage').then(m => m.MyApiKeysPage),\n mountPoint: rootRouteRef,\n }),\n);\n\nexport const ApiKeyApprovalPage = kuadrantPlugin.provide(\n createRoutableExtension({\n name: 'ApiKeyApprovalPage',\n component: () =>\n import('./components/ApiKeyApprovalPage').then(m => m.ApiKeyApprovalPageWithPermissions),\n mountPoint: rootRouteRef,\n }),\n);\n\nexport const EntityKuadrantApiAccessCard = kuadrantPlugin.provide(\n createComponentExtension({\n name: 'EntityKuadrantApiAccessCard',\n component: {\n lazy: () =>\n import('./components/ApiAccessCard').then(m => m.ApiAccessCard),\n },\n }),\n);\n\nexport const EntityKuadrantApiKeyManagementTab = kuadrantPlugin.provide(\n createComponentExtension({\n name: 'EntityKuadrantApiKeyManagementTab',\n component: {\n lazy: () =>\n import('./components/ApiKeyManagementTab').then(m => m.ApiKeyManagementTab),\n },\n }),\n);\n\n// entity content extension for api keys tab\nexport const EntityKuadrantApiKeysContent = kuadrantPlugin.provide(\n createComponentExtension({\n name: 'EntityKuadrantApiKeysContent',\n component: {\n lazy: () =>\n import('./components/ApiKeyManagementTab').then(m => m.ApiKeyManagementTab),\n },\n }),\n);\n\nexport const EntityKuadrantApiProductInfoContent = kuadrantPlugin.provide(\n createComponentExtension({\n name: 'EntityKuadrantApiProductInfoContent',\n component: {\n lazy: () =>\n import('./components/ApiProductInfoCard').then(m => m.ApiProductInfoCard),\n },\n }),\n);\n\nexport const ApiKeyDetailPage = kuadrantPlugin.provide(\n createRoutableExtension({\n name: 'ApiKeyDetailPage',\n component: () =>\n import('./components/ApiKeyDetailPage').then(m => m.ApiKeyDetailPage),\n mountPoint: rootRouteRef,\n }),\n);\n\nexport const EntityKuadrantApiProductOpenApiAlert = kuadrantPlugin.provide(\n createComponentExtension({\n name: 'EntityKuadrantApiProductOpenApiAlert',\n component: {\n lazy: () =>\n import('./components/ApiProductOpenApiAlert').then(m => m.ApiProductOpenApiAlert),\n },\n }),\n);\n\nexport const ApiProductDetailPage = kuadrantPlugin.provide(\n createRoutableExtension({\n name: 'ApiProductDetailPage',\n component: () =>\n import('./components/ApiProductDetailPage').then(m => m.ApiProductDetailPage),\n mountPoint: rootRouteRef,\n }),\n);\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
function getAPIKeyPhase(conditions) {
|
|
2
|
+
if (!conditions || conditions.length === 0) {
|
|
3
|
+
return "Pending";
|
|
4
|
+
}
|
|
5
|
+
const approved = conditions.find(
|
|
6
|
+
(c) => c.type === "Approved" && c.status === "True"
|
|
7
|
+
);
|
|
8
|
+
if (approved) return "Approved";
|
|
9
|
+
const denied = conditions.find(
|
|
10
|
+
(c) => c.type === "Denied" && c.status === "True"
|
|
11
|
+
);
|
|
12
|
+
if (denied) return "Denied";
|
|
13
|
+
const failed = conditions.find(
|
|
14
|
+
(c) => c.type === "Failed" && c.status === "True"
|
|
15
|
+
);
|
|
16
|
+
if (failed) return "Failed";
|
|
17
|
+
return "Pending";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { getAPIKeyPhase };
|
|
21
|
+
//# sourceMappingURL=apikeys.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apikeys.esm.js","sources":["../../src/utils/apikeys.ts"],"sourcesContent":["import { StatusCondition } from '../types/api-management';\n\n/**\n * Derives the APIKey approval phase from Kubernetes conditions.\n *\n * Maps conditions to phases:\n * - Empty conditions array → Pending\n * - Approved condition (status: True) → Approved\n * - Denied condition (status: True) → Denied\n * - Failed condition (status: True) → Failed\n *\n * @param conditions - Array of Kubernetes status conditions\n * @returns Current approval phase\n */\nexport function getAPIKeyPhase(\n conditions?: StatusCondition[]\n): 'Pending' | 'Approved' | 'Denied' | 'Failed' {\n if (!conditions || conditions.length === 0) {\n return 'Pending';\n }\n\n const approved = conditions.find(\n c => c.type === 'Approved' && c.status === 'True'\n );\n if (approved) return 'Approved';\n\n const denied = conditions.find(\n c => c.type === 'Denied' && c.status === 'True'\n );\n if (denied) return 'Denied';\n\n const failed = conditions.find(\n c => c.type === 'Failed' && c.status === 'True'\n );\n if (failed) return 'Failed';\n\n return 'Pending';\n}\n"],"names":[],"mappings":"AAcO,SAAS,eACd,UAC8C,EAAA;AAC9C,EAAA,IAAI,CAAC,UAAA,IAAc,UAAW,CAAA,MAAA,KAAW,CAAG,EAAA;AAC1C,IAAO,OAAA,SAAA;AAAA;AAGT,EAAA,MAAM,WAAW,UAAW,CAAA,IAAA;AAAA,IAC1B,CAAK,CAAA,KAAA,CAAA,CAAE,IAAS,KAAA,UAAA,IAAc,EAAE,MAAW,KAAA;AAAA,GAC7C;AACA,EAAA,IAAI,UAAiB,OAAA,UAAA;AAErB,EAAA,MAAM,SAAS,UAAW,CAAA,IAAA;AAAA,IACxB,CAAK,CAAA,KAAA,CAAA,CAAE,IAAS,KAAA,QAAA,IAAY,EAAE,MAAW,KAAA;AAAA,GAC3C;AACA,EAAA,IAAI,QAAe,OAAA,QAAA;AAEnB,EAAA,MAAM,SAAS,UAAW,CAAA,IAAA;AAAA,IACxB,CAAK,CAAA,KAAA,CAAA,CAAE,IAAS,KAAA,QAAA,IAAY,EAAE,MAAW,KAAA;AAAA,GAC3C;AACA,EAAA,IAAI,QAAe,OAAA,QAAA;AAEnB,EAAO,OAAA,SAAA;AACT;;;;"}
|
package/dist/utils/styles.esm.js
CHANGED
|
@@ -4,9 +4,12 @@ const getMyApiKeysStatusChipStyle = (phase) => {
|
|
|
4
4
|
case "Approved":
|
|
5
5
|
return { ...base, backgroundColor: "#1976d2", color: "#fff" };
|
|
6
6
|
// Blue
|
|
7
|
-
case "
|
|
7
|
+
case "Denied":
|
|
8
8
|
return { ...base, backgroundColor: "#d32f2f", color: "#fff" };
|
|
9
9
|
// Red
|
|
10
|
+
case "Failed":
|
|
11
|
+
return { ...base, backgroundColor: "#ed6c02", color: "#fff" };
|
|
12
|
+
// Orange
|
|
10
13
|
case "Pending":
|
|
11
14
|
return { ...base, backgroundColor: "#9c27b0", color: "#fff" };
|
|
12
15
|
// Purple
|
|
@@ -20,7 +23,7 @@ const getApprovalQueueStatusChipStyle = (phase) => {
|
|
|
20
23
|
case "Approved":
|
|
21
24
|
return { ...base, backgroundColor: "#2e7d32", color: "#fff" };
|
|
22
25
|
// Green
|
|
23
|
-
case "
|
|
26
|
+
case "Denied":
|
|
24
27
|
return { ...base, backgroundColor: "#d32f2f", color: "#fff" };
|
|
25
28
|
// Red
|
|
26
29
|
case "Pending":
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"styles.esm.js","sources":["../../src/utils/styles.ts"],"sourcesContent":["import { CSSProperties } from \"react\";\n\n/**\n * Returns inline styles for API key status chips on the My API Keys page.\n */\nexport const getMyApiKeysStatusChipStyle = (phase: string): CSSProperties => {\n const base = { border: \"none\" };\n switch (phase) {\n case \"Approved\":\n return { ...base, backgroundColor: \"#1976d2\", color: \"#fff\" }; // Blue\n case \"
|
|
1
|
+
{"version":3,"file":"styles.esm.js","sources":["../../src/utils/styles.ts"],"sourcesContent":["import { CSSProperties } from \"react\";\n\n/**\n * Returns inline styles for API key status chips on the My API Keys page.\n */\nexport const getMyApiKeysStatusChipStyle = (phase: string): CSSProperties => {\n const base = { border: \"none\" };\n switch (phase) {\n case \"Approved\":\n return { ...base, backgroundColor: \"#1976d2\", color: \"#fff\" }; // Blue\n case \"Denied\":\n return { ...base, backgroundColor: \"#d32f2f\", color: \"#fff\" }; // Red\n case \"Failed\":\n return { ...base, backgroundColor: \"#ed6c02\", color: \"#fff\" }; // Orange\n case \"Pending\":\n return { ...base, backgroundColor: \"#9c27b0\", color: \"#fff\" }; // Purple\n default:\n return { ...base, backgroundColor: \"#9c27b0\", color: \"#fff\" }; // Purple (fallback for Pending)\n }\n};\n\n/**\n * Returns inline styles for API key status chips on the Approval Queue page.\n * Uses inline styles to ensure proper specificity with Material-UI Chip.\n */\nexport const getApprovalQueueStatusChipStyle = (phase: string): CSSProperties => {\n const base = { border: \"none\" };\n switch (phase) {\n case \"Approved\":\n return { ...base, backgroundColor: \"#2e7d32\", color: \"#fff\" }; // Green\n case \"Denied\":\n return { ...base, backgroundColor: \"#d32f2f\", color: \"#fff\" }; // Red\n case \"Pending\":\n return { ...base, backgroundColor: \"#ed6c02\", color: \"#fff\" }; // Orange\n default:\n return { ...base, backgroundColor: \"#ed6c02\", color: \"#fff\" }; // Orange (fallback for Pending)\n }\n};\n\n/**\n * Returns inline styles for lifecycle chips.\n * Uses inline styles to ensure proper specificity with Material-UI Chip.\n */\nexport const getLifecycleChipStyle = (lifecycle: string): CSSProperties => {\n switch (lifecycle) {\n case \"production\":\n return { backgroundColor: \"#1976d2\", color: \"#fff\" }; // Blue\n case \"experimental\":\n return { backgroundColor: \"#9c27b0\", color: \"#fff\" }; // Purple\n case \"deprecated\":\n return { backgroundColor: \"#ff9800\", color: \"#fff\" }; // Orange\n case \"retired\":\n return { backgroundColor: \"#d32f2f\", color: \"#fff\" }; // Red\n default:\n return {};\n }\n};\n"],"names":[],"mappings":"AAKa,MAAA,2BAAA,GAA8B,CAAC,KAAiC,KAAA;AAC3E,EAAM,MAAA,IAAA,GAAO,EAAE,MAAA,EAAQ,MAAO,EAAA;AAC9B,EAAA,QAAQ,KAAO;AAAA,IACb,KAAK,UAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAAA,IAC9D,KAAK,QAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAAA,IAC9D,KAAK,QAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAAA,IAC9D,KAAK,SAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAAA,IAC9D;AACE,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAElE;AAMa,MAAA,+BAAA,GAAkC,CAAC,KAAiC,KAAA;AAC/E,EAAM,MAAA,IAAA,GAAO,EAAE,MAAA,EAAQ,MAAO,EAAA;AAC9B,EAAA,QAAQ,KAAO;AAAA,IACb,KAAK,UAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAAA,IAC9D,KAAK,QAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAAA,IAC9D,KAAK,SAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAAA,IAC9D;AACE,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAElE;AAMa,MAAA,qBAAA,GAAwB,CAAC,SAAqC,KAAA;AACzE,EAAA,QAAQ,SAAW;AAAA,IACjB,KAAK,YAAA;AACH,MAAA,OAAO,EAAE,eAAA,EAAiB,SAAW,EAAA,KAAA,EAAO,MAAO,EAAA;AAAA;AAAA,IACrD,KAAK,cAAA;AACH,MAAA,OAAO,EAAE,eAAA,EAAiB,SAAW,EAAA,KAAA,EAAO,MAAO,EAAA;AAAA;AAAA,IACrD,KAAK,YAAA;AACH,MAAA,OAAO,EAAE,eAAA,EAAiB,SAAW,EAAA,KAAA,EAAO,MAAO,EAAA;AAAA;AAAA,IACrD,KAAK,SAAA;AACH,MAAA,OAAO,EAAE,eAAA,EAAiB,SAAW,EAAA,KAAA,EAAO,MAAO,EAAA;AAAA;AAAA,IACrD;AACE,MAAA,OAAO,EAAC;AAAA;AAEd;;;;"}
|