@kuadrant/kuadrant-backstage-plugin-frontend 0.2.1 → 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 +45 -110
- 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/EditAPIProductDialog/EditAPIProductDialog.esm.js +2 -3
- package/dist/components/EditAPIProductDialog/EditAPIProductDialog.esm.js.map +1 -1
- 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/index.d.ts +47 -6
- package/dist/index.esm.js +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/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.56cde36b.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/2967.004a950e.chunk.js +2 -0
- package/dist-scalprum/static/2967.004a950e.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/3658.104704cc.chunk.js +2 -0
- package/dist-scalprum/static/3658.104704cc.chunk.js.map +1 -0
- 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/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/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/6311.da1849d1.chunk.js +2 -0
- package/dist-scalprum/static/6311.da1849d1.chunk.js.map +1 -0
- package/dist-scalprum/static/6371.02375475.chunk.js +3 -0
- package/dist-scalprum/static/6371.02375475.chunk.js.map +1 -0
- 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/7270.8ee9d452.chunk.js +2 -0
- package/dist-scalprum/static/7270.8ee9d452.chunk.js.map +1 -0
- 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-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 +1 -1
- 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.c4fb9c2347d3ad03a5d0.js +0 -2
- package/dist-scalprum/internal.plugin-kuadrant.c4fb9c2347d3ad03a5d0.js.map +0 -1
- package/dist-scalprum/static/1584.1e45e570.chunk.js +0 -3
- package/dist-scalprum/static/1584.1e45e570.chunk.js.map +0 -1
- package/dist-scalprum/static/1719.246c020d.chunk.js +0 -2
- package/dist-scalprum/static/1719.246c020d.chunk.js.map +0 -1
- package/dist-scalprum/static/1881.56cde36b.chunk.js.map +0 -1
- package/dist-scalprum/static/286.ee43f560.chunk.js +0 -2
- package/dist-scalprum/static/286.ee43f560.chunk.js.map +0 -1
- package/dist-scalprum/static/2967.0c2ef90e.chunk.js +0 -2
- package/dist-scalprum/static/2967.0c2ef90e.chunk.js.map +0 -1
- package/dist-scalprum/static/3581.ebe5968a.chunk.js +0 -2
- package/dist-scalprum/static/3581.ebe5968a.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.4f4aa8c2.chunk.js +0 -2
- package/dist-scalprum/static/3947.4f4aa8c2.chunk.js.map +0 -1
- package/dist-scalprum/static/3976.e8a8fda2.chunk.js +0 -2
- package/dist-scalprum/static/3976.e8a8fda2.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/4908.196a4425.chunk.js +0 -2
- package/dist-scalprum/static/4908.196a4425.chunk.js.map +0 -1
- package/dist-scalprum/static/512.d592d164.chunk.js +0 -2
- package/dist-scalprum/static/512.d592d164.chunk.js.map +0 -1
- package/dist-scalprum/static/5289.55069930.chunk.js +0 -2
- package/dist-scalprum/static/5289.55069930.chunk.js.map +0 -1
- package/dist-scalprum/static/5605.430f697e.chunk.js +0 -2
- package/dist-scalprum/static/5605.430f697e.chunk.js.map +0 -1
- package/dist-scalprum/static/5978.bf347a09.chunk.js +0 -2
- package/dist-scalprum/static/5978.bf347a09.chunk.js.map +0 -1
- package/dist-scalprum/static/6371.7b57ac27.chunk.js +0 -3
- package/dist-scalprum/static/6371.7b57ac27.chunk.js.map +0 -1
- package/dist-scalprum/static/6426.4c18bab5.chunk.js +0 -2
- package/dist-scalprum/static/6426.4c18bab5.chunk.js.map +0 -1
- package/dist-scalprum/static/6777.a2b77ec5.chunk.js +0 -2
- package/dist-scalprum/static/6777.a2b77ec5.chunk.js.map +0 -1
- package/dist-scalprum/static/6800.a45da2f4.chunk.js +0 -2
- package/dist-scalprum/static/6800.a45da2f4.chunk.js.map +0 -1
- package/dist-scalprum/static/7005.8190ad95.chunk.js +0 -2
- package/dist-scalprum/static/7005.8190ad95.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.d52407cd.chunk.js +0 -2
- package/dist-scalprum/static/7270.d52407cd.chunk.js.map +0 -1
- package/dist-scalprum/static/7717.6f5b9dd7.chunk.js +0 -3
- package/dist-scalprum/static/7717.6f5b9dd7.chunk.js.map +0 -1
- package/dist-scalprum/static/9079.2ddaea57.chunk.js +0 -2
- package/dist-scalprum/static/9079.2ddaea57.chunk.js.map +0 -1
- package/dist-scalprum/static/9239.1acfe112.chunk.js +0 -2
- package/dist-scalprum/static/9239.1acfe112.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/exposed-KuadrantPage.5ae00605.chunk.js +0 -2
- package/dist-scalprum/static/exposed-KuadrantPage.5ae00605.chunk.js.map +0 -1
- package/dist-scalprum/static/exposed-PluginRoot.949381c2.chunk.js +0 -2
- package/dist-scalprum/static/exposed-PluginRoot.949381c2.chunk.js.map +0 -1
- /package/dist-scalprum/static/{1584.1e45e570.chunk.js.LICENSE.txt → 1340.7c4f4722.chunk.js.LICENSE.txt} +0 -0
- /package/dist-scalprum/static/{7717.6f5b9dd7.chunk.js.LICENSE.txt → 20.b3a37d1d.chunk.js.LICENSE.txt} +0 -0
- /package/dist-scalprum/static/{6371.7b57ac27.chunk.js.LICENSE.txt → 6371.02375475.chunk.js.LICENSE.txt} +0 -0
package/dist/api.esm.js
CHANGED
|
@@ -86,6 +86,22 @@ class KuadrantApiClient {
|
|
|
86
86
|
const url = namespace ? `${baseUrl}kuadrant/requests/my?namespace=${namespace}` : `${baseUrl}kuadrant/requests/my`;
|
|
87
87
|
return this.fetchWithRetry(url, "Failed to fetch API Key requests by namespace.");
|
|
88
88
|
}
|
|
89
|
+
async getRequestsByApiProduct(apiProductName, apiProductNamespace) {
|
|
90
|
+
const baseUrl = await this.getBaseUrl();
|
|
91
|
+
const params = new URLSearchParams({ apiProductName, apiProductNamespace });
|
|
92
|
+
return this.fetchWithRetry(
|
|
93
|
+
`${baseUrl}kuadrant/requests/my?${params.toString()}`,
|
|
94
|
+
"Failed to fetch API Key requests by API product."
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
async getAllRequestsByApiProduct(apiProductName, apiProductNamespace) {
|
|
98
|
+
const baseUrl = await this.getBaseUrl();
|
|
99
|
+
const params = new URLSearchParams({ apiProductName, apiProductNamespace });
|
|
100
|
+
return this.fetchWithRetry(
|
|
101
|
+
`${baseUrl}kuadrant/requests?${params.toString()}`,
|
|
102
|
+
"Failed to fetch all API Key requests by API product."
|
|
103
|
+
);
|
|
104
|
+
}
|
|
89
105
|
async getRequest(namespace, name) {
|
|
90
106
|
const baseUrl = await this.getBaseUrl();
|
|
91
107
|
return this.fetchWithRetry(
|
|
@@ -129,17 +145,19 @@ class KuadrantApiClient {
|
|
|
129
145
|
}
|
|
130
146
|
async bulkApproveRequests(requests, reviewedBy) {
|
|
131
147
|
const baseUrl = await this.getBaseUrl();
|
|
132
|
-
|
|
148
|
+
const response = await this.fetchWithoutRetry(`${baseUrl}kuadrant/requests/bulk-approve`, {
|
|
133
149
|
method: "POST",
|
|
134
150
|
body: JSON.stringify({ requests, reviewedBy })
|
|
135
151
|
}, "Failed to bulk approve APIKey requests.");
|
|
152
|
+
return response.results;
|
|
136
153
|
}
|
|
137
154
|
async bulkRejectRequests(requests, reviewedBy) {
|
|
138
155
|
const baseUrl = await this.getBaseUrl();
|
|
139
|
-
|
|
156
|
+
const response = await this.fetchWithoutRetry(`${baseUrl}kuadrant/requests/bulk-reject`, {
|
|
140
157
|
method: "POST",
|
|
141
158
|
body: JSON.stringify({ requests, reviewedBy })
|
|
142
159
|
}, "Failed to bulk reject APIKey requests");
|
|
160
|
+
return response.results;
|
|
143
161
|
}
|
|
144
162
|
// ===== API Keys/Secrets Implementation =====
|
|
145
163
|
async getApiKey(namespace, name) {
|
|
@@ -230,6 +248,26 @@ class KuadrantApiClient {
|
|
|
230
248
|
"Failed to fetch RateLimitPolicies."
|
|
231
249
|
);
|
|
232
250
|
}
|
|
251
|
+
// ===== Secrets Implementation =====
|
|
252
|
+
async createSecret(name, apiKeyValue) {
|
|
253
|
+
const baseUrl = await this.getBaseUrl();
|
|
254
|
+
return this.fetchWithoutRetry(
|
|
255
|
+
`${baseUrl}kuadrant/secrets`,
|
|
256
|
+
{
|
|
257
|
+
method: "POST",
|
|
258
|
+
body: JSON.stringify({ name, apiKeyValue })
|
|
259
|
+
},
|
|
260
|
+
"Failed to create secret"
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
async deleteSecret(name) {
|
|
264
|
+
const baseUrl = await this.getBaseUrl();
|
|
265
|
+
return this.fetchWithoutRetry(
|
|
266
|
+
`${baseUrl}kuadrant/secrets/${name}`,
|
|
267
|
+
{ method: "DELETE" },
|
|
268
|
+
"Failed to delete secret"
|
|
269
|
+
);
|
|
270
|
+
}
|
|
233
271
|
}
|
|
234
272
|
|
|
235
273
|
export { KuadrantApiClient, kuadrantApiRef };
|
package/dist/api.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.esm.js","sources":["../src/api.ts"],"sourcesContent":["import {\n createApiRef,\n DiscoveryApi,\n FetchApi,\n IdentityApi,\n} from '@backstage/core-plugin-api';\nimport retry from 'async-retry';\nimport { handleFetchError } from './utils/errors';\nimport {\n APIKey, APIKeyRequest,\n APIKeySpec,\n APIProduct,\n BulkOperationResult, ExtractedSecret, K8sList, K8sResource,\n PlanPolicy,\n AuthPolicy,\n RateLimitPolicy,\n} from './types/api-management';\n\n/**\n * Generic Kuadrant list type for API responses\n */\nexport interface KuadrantList<T = any> {\n items: T[];\n}\n\n/**\n * Options for constructing the KuadrantApiClient\n */\nexport type Options = {\n discoveryApi: DiscoveryApi;\n fetchApi: FetchApi;\n identityApi: IdentityApi;\n};\n\n/**\n * Retry configuration for read operations (GET requests only)\n * Conservative strategy: 3 retries with exponential backoff\n */\nconst RETRY_OPTIONS: retry.Options = {\n retries: 3,\n factor: 2,\n minTimeout: 300, // 300ms, 600ms, 1200ms\n maxTimeout: 3000,\n randomize: true,\n};\n\n/**\n * Kuadrant API interface defining all operations for managing\n * API products, API keys, and related resources\n */\nexport interface KuadrantAPI {\n // ===== APIKey Requests =====\n\n /**\n * Fetch all API key requests per user\n * @returns Promise with list of all API key requests\n */\n getRequests(): Promise<KuadrantList<APIKey>>;\n\n /**\n * Fetch all API key requests\n * @returns Promise with list of all API key requests\n */\n getAllRequests(): Promise<KuadrantList<APIKey>>;\n\n /**\n * Fetch API key requests for a specific namespace\n * @param namespace - Kubernetes namespace\n * @returns Promise with list of requests in the namespace\n */\n getRequestsByNamespace(namespace: string): Promise<KuadrantList<APIKey>>;\n\n /**\n * Fetch a single API key request\n * @param namespace - API key request name\n * @param name - Kubernetes namespace\n * @returns Promise with the API key request\n */\n getRequest(namespace: string, name: string): Promise<APIKey>;\n\n /**\n * Create a new API key request\n * @param request - APIKeyRequest specification\n * @returns Promise with the created API key\n */\n createRequest(request: APIKeyRequest): Promise<APIKey>;\n\n /**\n * Update an existing API key request\n * @param namespace - Kubernetes namespace\n * @param name - API key request name\n * @param patch - Partial API key spec with fields to update\n * @returns Promise with the updated API key\n */\n updateRequest(\n namespace: string,\n name: string,\n patch: Partial<APIKeySpec>,\n ): Promise<APIKey>;\n\n /**\n * Delete an API key request\n * @param namespace - Kubernetes namespace\n * @param name - API key request name\n * @returns Promise that resolves when deletion completes\n */\n deleteRequest(namespace: string, name: string): Promise<void>;\n\n /**\n * Approve an API key request\n * @param namespace - Kubernetes namespace\n * @param name - API key request name\n * @param reviewedBy - Reviewed By User / System\n * @returns Promise with the approved API key\n */\n approveRequest(namespace: string, name: string, reviewedBy: string): Promise<APIKey>;\n\n /**\n * Reject an API key request\n * @param namespace - Kubernetes namespace\n * @param name - API key request name\n * @param reviewedBy - Reviewed By User / System\n * @returns Promise with the rejected API key\n */\n rejectRequest(namespace: string, name: string, reviewedBy: string): Promise<APIKey>;\n\n /**\n * Bulk approve multiple API key requests\n * @param requests - Array of namespace/name pairs to approve\n * @param reviewedBy - Reviewed By User / System\n * @returns Promise that resolves when all approvals complete\n */\n bulkApproveRequests(\n requests: Array<{ namespace: string; name: string }>,\n reviewedBy: string): Promise<Array<BulkOperationResult>>;\n\n /**\n * Bulk reject multiple API key requests\n * @param requests - Array of namespace/name pairs to reject\n * @param reviewedBy - Reviewed By User / System\n * @returns Promise that resolves when all rejections complete\n */\n bulkRejectRequests(\n requests: Array<{ namespace: string; name: string }>,\n reviewedBy: string): Promise<Array<BulkOperationResult>>;\n\n // ===== API Keys/Secrets =====\n\n /**\n * Fetch an API key resource\n * @param namespace - Kubernetes namespace\n * @param name - API key name\n * @returns Promise with the API key\n */\n getApiKey(namespace: string, name: string): Promise<APIKey>;\n\n /**\n * Retrieve the secret value for an API key (one-time operation)\n * @param namespace - Kubernetes namespace\n * @param name - API key name\n * @returns Promise with the secret value\n */\n getApiKeySecret(namespace: string, name: string): Promise<ExtractedSecret>;\n\n // ===== API Products =====\n\n /**\n * Fetch all API products\n * @returns Promise with list of all API products\n */\n getApiProducts(): Promise<KuadrantList<APIProduct>>;\n\n /**\n * Fetch a single API product\n * @param namespace - Kubernetes namespace\n * @param name - API product name\n * @returns Promise with the API product\n */\n getApiProduct(namespace: string, name: string): Promise<APIProduct>;\n\n /**\n * Create a new API product\n * @param product - API product specification\n * @returns Promise with the created API product\n */\n createApiProduct(product: APIProduct): Promise<APIProduct>;\n\n /**\n * Update an existing API product\n * @param namespace - Kubernetes namespace\n * @param name - API product name\n * @param patch - Partial API product spec with fields to update\n * @returns Promise with the updated API product\n */\n updateApiProduct(\n namespace: string,\n name: string,\n patch: Partial<APIProduct>,\n ): Promise<APIProduct>;\n\n /**\n * Delete an API product\n * @param namespace - Kubernetes namespace\n * @param name - API product name\n * @returns Promise that resolves when deletion completes\n */\n deleteApiProduct(namespace: string, name: string): Promise<void>;\n\n // ===== HTTP Routes & Policies =====\n\n /**\n * Fetch all HTTPRoute(s)\n * @returns Promise with list of all HTTP routes\n */\n getHttpRoutes(): Promise<K8sList>;\n\n /**\n * Fetch a specific HTTPRoute\n * @param namespace - Kubernetes namespace\n * @param name - HTTPRoute name\n * @returns Promise with an HTTPRoute\n */\n getHttpRoute(namespace: string, name: string): Promise<K8sResource>;\n\n // ===== Plan Policies =====\n\n /**\n * Fetch all plan policies\n * @returns Promise with list of all plan policies\n */\n getPlanPolicies(): Promise<KuadrantList<PlanPolicy>>;\n\n // ===== Auth Policies =====\n\n /**\n * Fetch all auth policies\n * @returns Promise with list of all auth policies\n */\n getAuthPolicies(): Promise<KuadrantList<AuthPolicy>>;\n\n // ===== RateLimitPolicies =====\n\n /**\n * Fetch all ratelimitpolicies\n * @returns Promise with list of all ratelimitpolicies\n */\n getRateLimitPolicies(): Promise<KuadrantList<RateLimitPolicy>>;\n}\n\n/**\n * API reference for the Kuadrant API\n */\nexport const kuadrantApiRef = createApiRef<KuadrantAPI>({\n id: 'plugin.kuadrant.service',\n});\n\n/**\n * Implementation of the Kuadrant API client\n */\nexport class KuadrantApiClient implements KuadrantAPI {\n private readonly discoveryApi: DiscoveryApi;\n private readonly fetchApi: FetchApi;\n\n constructor(options: Options) {\n this.discoveryApi = options.discoveryApi;\n this.fetchApi = options.fetchApi;\n }\n\n /**\n * Get the base URL for the backend API\n */\n private async getBaseUrl(): Promise<string> {\n return await this.discoveryApi.getBaseUrl('');\n }\n\n /**\n * Wrapper for GET requests with automatic retry logic\n * Retries on network failures or 5xx errors with exponential backoff\n */\n private async fetchWithRetry<T>(url: string, errorMsg: string = \"\"): Promise<T> {\n return retry(\n async (bail) => {\n const response = await this.fetchApi.fetch(url);\n if (response.status === 401 || response.status === 403) { // Don't retry on Unauthenticated/Unauthorized\n const error = await handleFetchError(response);\n bail(new Error(error));\n }\n else if (!response.ok) {\n const error = await handleFetchError(response);\n throw new Error(`${errorMsg} ${error}`);\n }\n return await response.json();\n },\n RETRY_OPTIONS,\n );\n }\n\n /**\n * Wrapper for mutations (POST, PATCH, DELETE) without retry\n * These operations are not retried to avoid duplicate side effects\n */\n private async fetchWithoutRetry<T>(\n url: string,\n options: RequestInit,\n errorMsg: string = \"\"): Promise<T> {\n const response = await this.fetchApi.fetch(url, {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n ...options,\n });\n\n if (!response.ok) {\n const error = await handleFetchError(response);\n throw new Error(`${errorMsg} ${error}`);\n }\n\n // DELETE operations don't return a body\n if (options.method === 'DELETE') {\n return undefined as T;\n }\n\n return await response.json();\n }\n\n // ===== API Requests Implementation =====\n\n async getRequests(): Promise<KuadrantList<APIKey>> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/requests/my`,\n \"Failed to fetch API Key requests.\"\n );\n }\n\n async getAllRequests(): Promise<KuadrantList<APIKey>> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/requests`,\n \"Failed to fetch API Key requests.\"\n );\n }\n\n async getRequestsByNamespace(namespace: string): Promise<KuadrantList<APIKey>> {\n const baseUrl = await this.getBaseUrl();\n const url = namespace\n ? `${baseUrl}kuadrant/requests/my?namespace=${namespace}`\n : `${baseUrl}kuadrant/requests/my`;\n return this.fetchWithRetry(url, \"Failed to fetch API Key requests by namespace.\");\n }\n\n async getRequest(namespace: string, name: string): Promise<APIKey> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/requests/${namespace}/${name}`,\n \"Failed to fetch API Key request.\"\n );\n }\n\n async createRequest(request: APIKeyRequest): Promise<APIKey> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithoutRetry(`${baseUrl}kuadrant/requests`, {\n method: 'POST',\n body: JSON.stringify(request),\n }, \"Failed to create APIKey request.\");\n }\n\n async updateRequest(\n namespace: string,\n name: string,\n patch: Partial<APIKeySpec>,\n ): Promise<APIKey> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithoutRetry(`${baseUrl}kuadrant/requests/${namespace}/${name}`, {\n method: 'PATCH',\n body: JSON.stringify(patch),\n }, \"Failed to update APIKey request.\");\n }\n\n async deleteRequest(namespace: string, name: string): Promise<void> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithoutRetry(`${baseUrl}kuadrant/requests/${namespace}/${name}`, {\n method: 'DELETE',\n }, \"Failed to delete APIKey request.\");\n }\n\n async approveRequest(namespace: string, name: string, reviewedBy: string = \"system\"): Promise<APIKey> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithoutRetry(`${baseUrl}kuadrant/requests/${namespace}/${name}/approve`, {\n method: 'POST',\n body: JSON.stringify({ reviewedBy }),\n }, \"Failed to approve APIKey request.\");\n }\n\n async rejectRequest(namespace: string, name: string, reviewedBy: string = \"system\"): Promise<APIKey> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithoutRetry(`${baseUrl}kuadrant/requests/${namespace}/${name}/reject`, {\n method: 'POST',\n body: JSON.stringify({ reviewedBy }),\n }, \"Failed to reject APIKey request.\");\n }\n\n async bulkApproveRequests(\n requests: Array<{ namespace: string; name: string }>,\n reviewedBy: string): Promise<Array<BulkOperationResult>> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithoutRetry(`${baseUrl}kuadrant/requests/bulk-approve`, {\n method: 'POST',\n body: JSON.stringify({ requests, reviewedBy }),\n }, \"Failed to bulk approve APIKey requests.\");\n }\n\n async bulkRejectRequests(\n requests: Array<{ namespace: string; name: string }>,\n reviewedBy: string): Promise<Array<BulkOperationResult>> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithoutRetry(`${baseUrl}kuadrant/requests/bulk-reject`, {\n method: 'POST',\n body: JSON.stringify({ requests, reviewedBy }),\n }, \"Failed to bulk reject APIKey requests\");\n }\n\n // ===== API Keys/Secrets Implementation =====\n\n async getApiKey(namespace: string, name: string): Promise<APIKey> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/apikeys/${namespace}/${name}`,\n \"Failed to fetch API Key.\"\n );\n }\n\n async getApiKeySecret(\n namespace: string,\n name: string,\n ): Promise<ExtractedSecret> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/apikeys/${namespace}/${name}/secret`,\n \"Failed to fetch API Key Secret.\"\n );\n }\n\n // ===== API Products Implementation =====\n\n async getApiProducts(): Promise<KuadrantList<APIProduct>> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/apiproducts`,\n \"Failed to fetch API Products.\"\n );\n }\n\n async getApiProduct(namespace: string, name: string): Promise<APIProduct> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/apiproducts/${namespace}/${name}`,\n \"Failed to fetch API Product.\"\n );\n }\n\n async createApiProduct(product: APIProduct): Promise<APIProduct> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithoutRetry(`${baseUrl}kuadrant/apiproducts`, {\n method: 'POST',\n body: JSON.stringify(product),\n }, \"Failed to create API Product.\");\n }\n\n async updateApiProduct(\n namespace: string,\n name: string,\n patch: Partial<APIProduct>,\n ): Promise<APIProduct> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithoutRetry(`${baseUrl}kuadrant/apiproducts/${namespace}/${name}`, {\n method: 'PATCH',\n body: JSON.stringify(patch),\n }, \"Failed to update API Product.\");\n }\n\n async deleteApiProduct(namespace: string, name: string): Promise<void> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithoutRetry(`${baseUrl}kuadrant/apiproducts/${namespace}/${name}`, {\n method: 'DELETE',\n }, \"Failed to delete API Product.\");\n }\n\n // ===== HTTP Routes =====\n\n async getHttpRoutes(): Promise<K8sList> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/httproutes`,\n \"Failed to fetch HTTPRoutes.\"\n );\n }\n\n async getHttpRoute(namespace: string, name: string): Promise<K8sResource> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/httproutes/${namespace}/${name}`,\n `Failed to fetc HTTPRoute ${namespace}/${name}.`\n );\n }\n\n // ===== Plan Policies Implementation =====\n\n async getPlanPolicies(): Promise<KuadrantList<PlanPolicy>> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/planpolicies`,\n \"Failed to fetch PlanPolicies.\"\n );\n }\n\n // ===== AuthPolicies Implementation =====\n\n async getAuthPolicies(): Promise<KuadrantList<AuthPolicy>> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/authpolicies`,\n \"Failed to fetch AuthPolicies.\"\n );\n }\n\n // ===== RateLimitPolicies Implementation =====\n\n async getRateLimitPolicies(): Promise<KuadrantList<RateLimitPolicy>> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/ratelimitpolicies`,\n \"Failed to fetch RateLimitPolicies.\"\n );\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"api.esm.js","sources":["../src/api.ts"],"sourcesContent":["import {\n createApiRef,\n DiscoveryApi,\n FetchApi,\n IdentityApi,\n} from '@backstage/core-plugin-api';\nimport retry from 'async-retry';\nimport { handleFetchError } from './utils/errors';\nimport {\n APIKey, APIKeyRequest,\n APIKeySpec,\n APIProduct,\n BulkOperationResult, ExtractedSecret, K8sList, K8sResource,\n PlanPolicy,\n AuthPolicy,\n RateLimitPolicy,\n} from './types/api-management';\n\n/**\n * Generic Kuadrant list type for API responses\n */\nexport interface KuadrantList<T = any> {\n items: T[];\n}\n\n/**\n * Options for constructing the KuadrantApiClient\n */\nexport type Options = {\n discoveryApi: DiscoveryApi;\n fetchApi: FetchApi;\n identityApi: IdentityApi;\n};\n\n/**\n * Retry configuration for read operations (GET requests only)\n * Conservative strategy: 3 retries with exponential backoff\n */\nconst RETRY_OPTIONS: retry.Options = {\n retries: 3,\n factor: 2,\n minTimeout: 300, // 300ms, 600ms, 1200ms\n maxTimeout: 3000,\n randomize: true,\n};\n\n/**\n * Kuadrant API interface defining all operations for managing\n * API products, API keys, and related resources\n */\nexport interface KuadrantAPI {\n // ===== APIKey Requests =====\n\n /**\n * Fetch all API key requests per user\n * @returns Promise with list of all API key requests\n */\n getRequests(): Promise<KuadrantList<APIKey>>;\n\n /**\n * Fetch all API key requests\n * @returns Promise with list of all API key requests\n */\n getAllRequests(): Promise<KuadrantList<APIKey>>;\n\n /**\n * Fetch API key requests for a specific namespace\n * @param namespace - Kubernetes namespace\n * @returns Promise with list of requests in the namespace\n */\n getRequestsByNamespace(namespace: string): Promise<KuadrantList<APIKey>>;\n\n /**\n * Fetch the current user's API key requests for a specific APIProduct\n * @param apiProductName - Name of the APIProduct\n * @param apiProductNamespace - Namespace of the APIProduct\n * @returns Promise with list of the user's API key requests for this product\n */\n getRequestsByApiProduct(apiProductName: string, apiProductNamespace: string): Promise<KuadrantList<APIKey>>;\n\n /**\n * Fetch all API key requests for a specific APIProduct (admin view)\n * @param apiProductName - Name of the APIProduct\n * @param apiProductNamespace - Namespace of the APIProduct\n * @returns Promise with list of all API key requests for this product\n */\n getAllRequestsByApiProduct(apiProductName: string, apiProductNamespace: string): Promise<KuadrantList<APIKey>>;\n\n /**\n * Fetch a single API key request\n * @param namespace - API key request name\n * @param name - Kubernetes namespace\n * @returns Promise with the API key request\n */\n getRequest(namespace: string, name: string): Promise<APIKey>;\n\n /**\n * Create a new API key request\n * @param request - APIKeyRequest specification\n * @returns Promise with the created API key\n */\n createRequest(request: APIKeyRequest): Promise<APIKey>;\n\n /**\n * Update an existing API key request\n * @param namespace - Kubernetes namespace\n * @param name - API key request name\n * @param patch - Partial API key spec with fields to update\n * @returns Promise with the updated API key\n */\n updateRequest(\n namespace: string,\n name: string,\n patch: Partial<APIKeySpec>,\n ): Promise<APIKey>;\n\n /**\n * Delete an API key request\n * @param namespace - Kubernetes namespace\n * @param name - API key request name\n * @returns Promise that resolves when deletion completes\n */\n deleteRequest(namespace: string, name: string): Promise<void>;\n\n /**\n * Approve an API key request\n * @param namespace - Kubernetes namespace\n * @param name - API key request name\n * @param reviewedBy - Reviewed By User / System\n * @returns Promise with the approved API key\n */\n approveRequest(namespace: string, name: string, reviewedBy: string): Promise<APIKey>;\n\n /**\n * Reject an API key request\n * @param namespace - Kubernetes namespace\n * @param name - API key request name\n * @param reviewedBy - Reviewed By User / System\n * @returns Promise with the denied API key\n */\n rejectRequest(namespace: string, name: string, reviewedBy: string): Promise<APIKey>;\n\n /**\n * Bulk approve multiple API key requests\n * @param requests - Array of namespace/name pairs to approve\n * @param reviewedBy - Reviewed By User / System\n * @returns Promise that resolves when all approvals complete\n */\n bulkApproveRequests(\n requests: Array<{ namespace: string; name: string }>,\n reviewedBy: string): Promise<Array<BulkOperationResult>>;\n\n /**\n * Bulk reject multiple API key requests\n * @param requests - Array of namespace/name pairs to reject\n * @param reviewedBy - Reviewed By User / System\n * @returns Promise that resolves when all rejections complete\n */\n bulkRejectRequests(\n requests: Array<{ namespace: string; name: string }>,\n reviewedBy: string): Promise<Array<BulkOperationResult>>;\n\n // ===== API Keys/Secrets =====\n\n /**\n * Fetch an API key resource\n * @param namespace - Kubernetes namespace\n * @param name - API key name\n * @returns Promise with the API key\n */\n getApiKey(namespace: string, name: string): Promise<APIKey>;\n\n /**\n * Retrieve the secret value for an API key (one-time operation)\n * @param namespace - Kubernetes namespace\n * @param name - API key name\n * @returns Promise with the secret value\n */\n getApiKeySecret(namespace: string, name: string): Promise<ExtractedSecret>;\n\n // ===== API Products =====\n\n /**\n * Fetch all API products\n * @returns Promise with list of all API products\n */\n getApiProducts(): Promise<KuadrantList<APIProduct>>;\n\n /**\n * Fetch a single API product\n * @param namespace - Kubernetes namespace\n * @param name - API product name\n * @returns Promise with the API product\n */\n getApiProduct(namespace: string, name: string): Promise<APIProduct>;\n\n /**\n * Create a new API product\n * @param product - API product specification\n * @returns Promise with the created API product\n */\n createApiProduct(product: APIProduct): Promise<APIProduct>;\n\n /**\n * Update an existing API product\n * @param namespace - Kubernetes namespace\n * @param name - API product name\n * @param patch - Partial API product spec with fields to update\n * @returns Promise with the updated API product\n */\n updateApiProduct(\n namespace: string,\n name: string,\n patch: Partial<APIProduct>,\n ): Promise<APIProduct>;\n\n /**\n * Delete an API product\n * @param namespace - Kubernetes namespace\n * @param name - API product name\n * @returns Promise that resolves when deletion completes\n */\n deleteApiProduct(namespace: string, name: string): Promise<void>;\n\n // ===== HTTP Routes & Policies =====\n\n /**\n * Fetch all HTTPRoute(s)\n * @returns Promise with list of all HTTP routes\n */\n getHttpRoutes(): Promise<K8sList>;\n\n /**\n * Fetch a specific HTTPRoute\n * @param namespace - Kubernetes namespace\n * @param name - HTTPRoute name\n * @returns Promise with an HTTPRoute\n */\n getHttpRoute(namespace: string, name: string): Promise<K8sResource>;\n\n // ===== Plan Policies =====\n\n /**\n * Fetch all plan policies\n * @returns Promise with list of all plan policies\n */\n getPlanPolicies(): Promise<KuadrantList<PlanPolicy>>;\n\n // ===== Auth Policies =====\n\n /**\n * Fetch all auth policies\n * @returns Promise with list of all auth policies\n */\n getAuthPolicies(): Promise<KuadrantList<AuthPolicy>>;\n\n // ===== RateLimitPolicies =====\n\n /**\n * Fetch all ratelimitpolicies\n * @returns Promise with list of all ratelimitpolicies\n */\n getRateLimitPolicies(): Promise<KuadrantList<RateLimitPolicy>>;\n\n /**\n * Create a secret in consumer's own namespace\n * Backend determines namespace from authenticated user identity.\n * @param name - Secret name\n * @param apiKeyValue - API key value to store\n * @returns Promise that resolves when secret is created\n */\n createSecret(name: string, apiKeyValue: string): Promise<void>;\n\n /**\n * Delete a secret from consumer's own namespace\n * @param name - Secret name\n * @returns Promise that resolves when secret is deleted\n */\n deleteSecret(name: string): Promise<void>;\n}\n\n/**\n * API reference for the Kuadrant API\n */\nexport const kuadrantApiRef = createApiRef<KuadrantAPI>({\n id: 'plugin.kuadrant.service',\n});\n\n/**\n * Implementation of the Kuadrant API client\n */\nexport class KuadrantApiClient implements KuadrantAPI {\n private readonly discoveryApi: DiscoveryApi;\n private readonly fetchApi: FetchApi;\n\n constructor(options: Options) {\n this.discoveryApi = options.discoveryApi;\n this.fetchApi = options.fetchApi;\n }\n\n /**\n * Get the base URL for the backend API\n */\n private async getBaseUrl(): Promise<string> {\n return await this.discoveryApi.getBaseUrl('');\n }\n\n /**\n * Wrapper for GET requests with automatic retry logic\n * Retries on network failures or 5xx errors with exponential backoff\n */\n private async fetchWithRetry<T>(url: string, errorMsg: string = \"\"): Promise<T> {\n return retry(\n async (bail) => {\n const response = await this.fetchApi.fetch(url);\n if (response.status === 401 || response.status === 403) { // Don't retry on Unauthenticated/Unauthorized\n const error = await handleFetchError(response);\n bail(new Error(error));\n }\n else if (!response.ok) {\n const error = await handleFetchError(response);\n throw new Error(`${errorMsg} ${error}`);\n }\n return await response.json();\n },\n RETRY_OPTIONS,\n );\n }\n\n /**\n * Wrapper for mutations (POST, PATCH, DELETE) without retry\n * These operations are not retried to avoid duplicate side effects\n */\n private async fetchWithoutRetry<T>(\n url: string,\n options: RequestInit,\n errorMsg: string = \"\"): Promise<T> {\n const response = await this.fetchApi.fetch(url, {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n ...options,\n });\n\n if (!response.ok) {\n const error = await handleFetchError(response);\n throw new Error(`${errorMsg} ${error}`);\n }\n\n // DELETE operations don't return a body\n if (options.method === 'DELETE') {\n return undefined as T;\n }\n\n return await response.json();\n }\n\n // ===== API Requests Implementation =====\n\n async getRequests(): Promise<KuadrantList<APIKey>> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/requests/my`,\n \"Failed to fetch API Key requests.\"\n );\n }\n\n async getAllRequests(): Promise<KuadrantList<APIKey>> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/requests`,\n \"Failed to fetch API Key requests.\"\n );\n }\n\n async getRequestsByNamespace(namespace: string): Promise<KuadrantList<APIKey>> {\n const baseUrl = await this.getBaseUrl();\n const url = namespace\n ? `${baseUrl}kuadrant/requests/my?namespace=${namespace}`\n : `${baseUrl}kuadrant/requests/my`;\n return this.fetchWithRetry(url, \"Failed to fetch API Key requests by namespace.\");\n }\n\n async getRequestsByApiProduct(apiProductName: string, apiProductNamespace: string): Promise<KuadrantList<APIKey>> {\n const baseUrl = await this.getBaseUrl();\n const params = new URLSearchParams({ apiProductName, apiProductNamespace });\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/requests/my?${params.toString()}`,\n \"Failed to fetch API Key requests by API product.\",\n );\n }\n\n async getAllRequestsByApiProduct(apiProductName: string, apiProductNamespace: string): Promise<KuadrantList<APIKey>> {\n const baseUrl = await this.getBaseUrl();\n const params = new URLSearchParams({ apiProductName, apiProductNamespace });\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/requests?${params.toString()}`,\n \"Failed to fetch all API Key requests by API product.\",\n );\n }\n\n async getRequest(namespace: string, name: string): Promise<APIKey> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/requests/${namespace}/${name}`,\n \"Failed to fetch API Key request.\"\n );\n }\n\n async createRequest(request: APIKeyRequest): Promise<APIKey> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithoutRetry(`${baseUrl}kuadrant/requests`, {\n method: 'POST',\n body: JSON.stringify(request),\n }, \"Failed to create APIKey request.\");\n }\n\n async updateRequest(\n namespace: string,\n name: string,\n patch: Partial<APIKeySpec>,\n ): Promise<APIKey> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithoutRetry(`${baseUrl}kuadrant/requests/${namespace}/${name}`, {\n method: 'PATCH',\n body: JSON.stringify(patch),\n }, \"Failed to update APIKey request.\");\n }\n\n async deleteRequest(namespace: string, name: string): Promise<void> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithoutRetry(`${baseUrl}kuadrant/requests/${namespace}/${name}`, {\n method: 'DELETE',\n }, \"Failed to delete APIKey request.\");\n }\n\n async approveRequest(namespace: string, name: string, reviewedBy: string = \"system\"): Promise<APIKey> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithoutRetry(`${baseUrl}kuadrant/requests/${namespace}/${name}/approve`, {\n method: 'POST',\n body: JSON.stringify({ reviewedBy }),\n }, \"Failed to approve APIKey request.\");\n }\n\n async rejectRequest(namespace: string, name: string, reviewedBy: string = \"system\"): Promise<APIKey> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithoutRetry(`${baseUrl}kuadrant/requests/${namespace}/${name}/reject`, {\n method: 'POST',\n body: JSON.stringify({ reviewedBy }),\n }, \"Failed to reject APIKey request.\");\n }\n\n async bulkApproveRequests(\n requests: Array<{ namespace: string; name: string }>,\n reviewedBy: string): Promise<Array<BulkOperationResult>> {\n const baseUrl = await this.getBaseUrl();\n const response = await this.fetchWithoutRetry<{ results: Array<BulkOperationResult> }>(`${baseUrl}kuadrant/requests/bulk-approve`, {\n method: 'POST',\n body: JSON.stringify({ requests, reviewedBy }),\n }, \"Failed to bulk approve APIKey requests.\");\n return response.results;\n }\n\n async bulkRejectRequests(\n requests: Array<{ namespace: string; name: string }>,\n reviewedBy: string): Promise<Array<BulkOperationResult>> {\n const baseUrl = await this.getBaseUrl();\n const response = await this.fetchWithoutRetry<{ results: Array<BulkOperationResult> }>(`${baseUrl}kuadrant/requests/bulk-reject`, {\n method: 'POST',\n body: JSON.stringify({ requests, reviewedBy }),\n }, \"Failed to bulk reject APIKey requests\");\n return response.results;\n }\n\n // ===== API Keys/Secrets Implementation =====\n\n async getApiKey(namespace: string, name: string): Promise<APIKey> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/apikeys/${namespace}/${name}`,\n \"Failed to fetch API Key.\"\n );\n }\n\n async getApiKeySecret(\n namespace: string,\n name: string,\n ): Promise<ExtractedSecret> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/apikeys/${namespace}/${name}/secret`,\n \"Failed to fetch API Key Secret.\"\n );\n }\n\n // ===== API Products Implementation =====\n\n async getApiProducts(): Promise<KuadrantList<APIProduct>> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/apiproducts`,\n \"Failed to fetch API Products.\"\n );\n }\n\n async getApiProduct(namespace: string, name: string): Promise<APIProduct> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/apiproducts/${namespace}/${name}`,\n \"Failed to fetch API Product.\"\n );\n }\n\n async createApiProduct(product: APIProduct): Promise<APIProduct> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithoutRetry(`${baseUrl}kuadrant/apiproducts`, {\n method: 'POST',\n body: JSON.stringify(product),\n }, \"Failed to create API Product.\");\n }\n\n async updateApiProduct(\n namespace: string,\n name: string,\n patch: Partial<APIProduct>,\n ): Promise<APIProduct> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithoutRetry(`${baseUrl}kuadrant/apiproducts/${namespace}/${name}`, {\n method: 'PATCH',\n body: JSON.stringify(patch),\n }, \"Failed to update API Product.\");\n }\n\n async deleteApiProduct(namespace: string, name: string): Promise<void> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithoutRetry(`${baseUrl}kuadrant/apiproducts/${namespace}/${name}`, {\n method: 'DELETE',\n }, \"Failed to delete API Product.\");\n }\n\n // ===== HTTP Routes =====\n\n async getHttpRoutes(): Promise<K8sList> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/httproutes`,\n \"Failed to fetch HTTPRoutes.\"\n );\n }\n\n async getHttpRoute(namespace: string, name: string): Promise<K8sResource> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/httproutes/${namespace}/${name}`,\n `Failed to fetc HTTPRoute ${namespace}/${name}.`\n );\n }\n\n // ===== Plan Policies Implementation =====\n\n async getPlanPolicies(): Promise<KuadrantList<PlanPolicy>> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/planpolicies`,\n \"Failed to fetch PlanPolicies.\"\n );\n }\n\n // ===== AuthPolicies Implementation =====\n\n async getAuthPolicies(): Promise<KuadrantList<AuthPolicy>> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/authpolicies`,\n \"Failed to fetch AuthPolicies.\"\n );\n }\n\n // ===== RateLimitPolicies Implementation =====\n\n async getRateLimitPolicies(): Promise<KuadrantList<RateLimitPolicy>> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithRetry(\n `${baseUrl}kuadrant/ratelimitpolicies`,\n \"Failed to fetch RateLimitPolicies.\"\n );\n }\n\n // ===== Secrets Implementation =====\n\n async createSecret(name: string, apiKeyValue: string): Promise<void> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithoutRetry(\n `${baseUrl}kuadrant/secrets`,\n {\n method: 'POST',\n body: JSON.stringify({ name, apiKeyValue }),\n },\n 'Failed to create secret'\n );\n }\n\n async deleteSecret(name: string): Promise<void> {\n const baseUrl = await this.getBaseUrl();\n return this.fetchWithoutRetry(\n `${baseUrl}kuadrant/secrets/${name}`,\n { method: 'DELETE' },\n 'Failed to delete secret'\n );\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
2
|
import { useAsync } from 'react-use';
|
|
3
3
|
import { InfoCard, ResponseErrorPanel } from '@backstage/core-components';
|
|
4
|
-
import { Box, Typography, Button,
|
|
4
|
+
import { Box, Typography, Button, Chip, Tooltip, IconButton } from '@material-ui/core';
|
|
5
5
|
import { Skeleton } from '@material-ui/lab';
|
|
6
6
|
import AddIcon from '@material-ui/icons/Add';
|
|
7
7
|
import VisibilityIcon from '@material-ui/icons/Visibility';
|
|
8
8
|
import VisibilityOffIcon from '@material-ui/icons/VisibilityOff';
|
|
9
9
|
import FileCopyIcon from '@material-ui/icons/FileCopy';
|
|
10
|
-
import WarningIcon from '@material-ui/icons/Warning';
|
|
11
10
|
import { useApi, identityApiRef, alertApiRef } from '@backstage/core-plugin-api';
|
|
12
11
|
import { kuadrantApiRef } from '../../api.esm.js';
|
|
13
12
|
import { useEntity } from '@backstage/plugin-catalog-react';
|
|
@@ -26,9 +25,6 @@ const ApiAccessCard = ({ namespace: propNamespace }) => {
|
|
|
26
25
|
const [visibleKeys, setVisibleKeys] = useState(/* @__PURE__ */ new Set());
|
|
27
26
|
const [apiKeyValues, setApiKeyValues] = useState(/* @__PURE__ */ new Map());
|
|
28
27
|
const [apiKeyLoading, setApiKeyLoading] = useState(/* @__PURE__ */ new Set());
|
|
29
|
-
const [alreadyReadKeys, setAlreadyReadKeys] = useState(/* @__PURE__ */ new Set());
|
|
30
|
-
const [showOnceWarningOpen, setShowOnceWarningOpen] = useState(false);
|
|
31
|
-
const [pendingKeyReveal, setPendingKeyReveal] = useState(null);
|
|
32
28
|
const apiProductName = entity.metadata.annotations?.["kuadrant.io/apiproduct"] || entity.metadata.name;
|
|
33
29
|
const namespace = entity.metadata.annotations?.["kuadrant.io/namespace"] || propNamespace || "default";
|
|
34
30
|
useAsync(async () => {
|
|
@@ -36,10 +32,10 @@ const ApiAccessCard = ({ namespace: propNamespace }) => {
|
|
|
36
32
|
setUserEmail(profile.email || "");
|
|
37
33
|
}, [identityApi]);
|
|
38
34
|
const { value: requests, loading: keysLoading, error: keysError } = useAsync(async () => {
|
|
39
|
-
const data = await kuadrantApi.
|
|
35
|
+
const data = await kuadrantApi.getRequestsByApiProduct(apiProductName, namespace);
|
|
40
36
|
const allRequests = data.items || [];
|
|
41
37
|
return allRequests.filter(
|
|
42
|
-
(r) => r.
|
|
38
|
+
(r) => r.status?.phase === "Approved"
|
|
43
39
|
);
|
|
44
40
|
}, [namespace, apiProductName, kuadrantApi, refresh]);
|
|
45
41
|
const { value: apiProduct, loading: productLoading } = useAsync(async () => {
|
|
@@ -66,24 +62,15 @@ const ApiAccessCard = ({ namespace: propNamespace }) => {
|
|
|
66
62
|
try {
|
|
67
63
|
const data = await kuadrantApi.getApiKeySecret(requestNamespace, requestName);
|
|
68
64
|
setApiKeyValues((prev) => new Map(prev).set(key, data.apiKey));
|
|
69
|
-
|
|
65
|
+
toggleVisibility(requestName);
|
|
70
66
|
} catch (err) {
|
|
71
67
|
console.error("failed to fetch api key:", err);
|
|
72
68
|
const errorMessage = err instanceof Error ? err.message : "unknown error occurred";
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
display: "transient"
|
|
79
|
-
});
|
|
80
|
-
} else {
|
|
81
|
-
alertApi.post({
|
|
82
|
-
message: `Failed to fetch APIKey. ${errorMessage}`,
|
|
83
|
-
severity: "error",
|
|
84
|
-
display: "transient"
|
|
85
|
-
});
|
|
86
|
-
}
|
|
69
|
+
alertApi.post({
|
|
70
|
+
message: `Failed to fetch APIKey. ${errorMessage}`,
|
|
71
|
+
severity: "error",
|
|
72
|
+
display: "transient"
|
|
73
|
+
});
|
|
87
74
|
} finally {
|
|
88
75
|
setApiKeyLoading((prev) => {
|
|
89
76
|
const next = new Set(prev);
|
|
@@ -126,19 +113,13 @@ const ApiAccessCard = ({ namespace: propNamespace }) => {
|
|
|
126
113
|
const isVisible = visibleKeys.has(request.metadata.name);
|
|
127
114
|
const isLoading = apiKeyLoading.has(key);
|
|
128
115
|
const apiKeyValue = apiKeyValues.get(key);
|
|
129
|
-
const hasSecretRef = request.
|
|
130
|
-
const canReadSecret = request.status?.canReadSecret !== false;
|
|
131
|
-
const isAlreadyRead = alreadyReadKeys.has(key) || !canReadSecret;
|
|
116
|
+
const hasSecretRef = Boolean(request.spec?.secretRef?.name);
|
|
132
117
|
const handleRevealClick = () => {
|
|
133
118
|
if (isVisible) {
|
|
134
119
|
clearApiKeyValue(request.metadata.namespace, request.metadata.name);
|
|
135
120
|
toggleVisibility(request.metadata.name);
|
|
136
|
-
} else
|
|
137
|
-
|
|
138
|
-
namespace: request.metadata.namespace,
|
|
139
|
-
name: request.metadata.name
|
|
140
|
-
});
|
|
141
|
-
setShowOnceWarningOpen(true);
|
|
121
|
+
} else {
|
|
122
|
+
fetchApiKeyFromSecret(request.metadata.namespace, request.metadata.name);
|
|
142
123
|
}
|
|
143
124
|
};
|
|
144
125
|
const handleCopy = async () => {
|
|
@@ -174,22 +155,16 @@ const ApiAccessCard = ({ namespace: propNamespace }) => {
|
|
|
174
155
|
textOverflow: "ellipsis"
|
|
175
156
|
}
|
|
176
157
|
},
|
|
177
|
-
isLoading ? "Loading..." : isVisible && apiKeyValue ? apiKeyValue :
|
|
178
|
-
), isVisible && apiKeyValue && /* @__PURE__ */ React.createElement(Tooltip, { title: "Copy to clipboard" }, /* @__PURE__ */ React.createElement(IconButton, { size: "small", onClick: handleCopy }, /* @__PURE__ */ React.createElement(FileCopyIcon, { fontSize: "small" }))), /* @__PURE__ */ React.createElement(
|
|
179
|
-
|
|
158
|
+
isLoading ? "Loading..." : isVisible && apiKeyValue ? apiKeyValue : "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022"
|
|
159
|
+
), isVisible && apiKeyValue && /* @__PURE__ */ React.createElement(Tooltip, { title: "Copy to clipboard" }, /* @__PURE__ */ React.createElement(IconButton, { size: "small", onClick: handleCopy }, /* @__PURE__ */ React.createElement(FileCopyIcon, { fontSize: "small" }))), /* @__PURE__ */ React.createElement(Tooltip, { title: isVisible ? "Hide API key" : "Reveal API key" }, /* @__PURE__ */ React.createElement("span", null, /* @__PURE__ */ React.createElement(
|
|
160
|
+
IconButton,
|
|
180
161
|
{
|
|
181
|
-
|
|
162
|
+
size: "small",
|
|
163
|
+
onClick: handleRevealClick,
|
|
164
|
+
disabled: isLoading
|
|
182
165
|
},
|
|
183
|
-
/* @__PURE__ */ React.createElement("
|
|
184
|
-
|
|
185
|
-
{
|
|
186
|
-
size: "small",
|
|
187
|
-
onClick: handleRevealClick,
|
|
188
|
-
disabled: isLoading || isAlreadyRead && !apiKeyValue
|
|
189
|
-
},
|
|
190
|
-
isVisible ? /* @__PURE__ */ React.createElement(VisibilityOffIcon, { fontSize: "small" }) : /* @__PURE__ */ React.createElement(VisibilityIcon, { fontSize: "small" })
|
|
191
|
-
))
|
|
192
|
-
))
|
|
166
|
+
isVisible ? /* @__PURE__ */ React.createElement(VisibilityOffIcon, { fontSize: "small" }) : /* @__PURE__ */ React.createElement(VisibilityIcon, { fontSize: "small" })
|
|
167
|
+
))))
|
|
193
168
|
);
|
|
194
169
|
};
|
|
195
170
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(InfoCard, { title: "Kuadrant API Keys" }, /* @__PURE__ */ React.createElement(Box, { p: 2 }, keys.length > 0 ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Typography, { variant: "body2", color: "textSecondary", gutterBottom: true }, keys.length, " active key", keys.length !== 1 ? "s" : ""), keys.map(renderKeyRow)) : /* @__PURE__ */ React.createElement(Typography, { variant: "body1", gutterBottom: true }, "You don't have any API keys for this API yet"), /* @__PURE__ */ React.createElement(Box, { mt: 2 }, canRequest ? /* @__PURE__ */ React.createElement(
|
|
@@ -217,46 +192,6 @@ const ApiAccessCard = ({ namespace: propNamespace }) => {
|
|
|
217
192
|
userEmail,
|
|
218
193
|
plans
|
|
219
194
|
}
|
|
220
|
-
), /* @__PURE__ */ React.createElement(
|
|
221
|
-
Dialog,
|
|
222
|
-
{
|
|
223
|
-
open: showOnceWarningOpen,
|
|
224
|
-
onClose: () => {
|
|
225
|
-
setShowOnceWarningOpen(false);
|
|
226
|
-
setPendingKeyReveal(null);
|
|
227
|
-
},
|
|
228
|
-
maxWidth: "sm"
|
|
229
|
-
},
|
|
230
|
-
/* @__PURE__ */ React.createElement(DialogTitle, null, /* @__PURE__ */ React.createElement(Box, { display: "flex", alignItems: "center" }, /* @__PURE__ */ React.createElement(WarningIcon, { color: "primary", style: { marginRight: 8 } }), "View API Key")),
|
|
231
|
-
/* @__PURE__ */ React.createElement(DialogContent, null, /* @__PURE__ */ React.createElement(Typography, { variant: "body1", paragraph: true }, "This API key can only be viewed ", /* @__PURE__ */ React.createElement("strong", null, "once"), ". After you reveal it, you will not be able to retrieve it again."), /* @__PURE__ */ React.createElement(Typography, { variant: "body2", color: "textSecondary" }, "Make sure to copy and store it securely before closing this view.")),
|
|
232
|
-
/* @__PURE__ */ React.createElement(DialogActions, null, /* @__PURE__ */ React.createElement(
|
|
233
|
-
Button,
|
|
234
|
-
{
|
|
235
|
-
onClick: () => {
|
|
236
|
-
setShowOnceWarningOpen(false);
|
|
237
|
-
setPendingKeyReveal(null);
|
|
238
|
-
}
|
|
239
|
-
},
|
|
240
|
-
"Cancel"
|
|
241
|
-
), /* @__PURE__ */ React.createElement(
|
|
242
|
-
Button,
|
|
243
|
-
{
|
|
244
|
-
variant: "contained",
|
|
245
|
-
color: "primary",
|
|
246
|
-
onClick: () => {
|
|
247
|
-
if (pendingKeyReveal) {
|
|
248
|
-
fetchApiKeyFromSecret(
|
|
249
|
-
pendingKeyReveal.namespace,
|
|
250
|
-
pendingKeyReveal.name
|
|
251
|
-
);
|
|
252
|
-
toggleVisibility(pendingKeyReveal.name);
|
|
253
|
-
}
|
|
254
|
-
setShowOnceWarningOpen(false);
|
|
255
|
-
setPendingKeyReveal(null);
|
|
256
|
-
}
|
|
257
|
-
},
|
|
258
|
-
"Reveal API Key"
|
|
259
|
-
))
|
|
260
195
|
));
|
|
261
196
|
};
|
|
262
197
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApiAccessCard.esm.js","sources":["../../../src/components/ApiAccessCard/ApiAccessCard.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { useAsync } from 'react-use';\nimport {\n InfoCard,\n ResponseErrorPanel,\n} from '@backstage/core-components';\nimport {\n Typography,\n Box,\n Chip,\n Button,\n IconButton,\n Tooltip,\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n} from '@material-ui/core';\nimport { Skeleton } from '@material-ui/lab';\nimport AddIcon from '@material-ui/icons/Add';\nimport VisibilityIcon from '@material-ui/icons/Visibility';\nimport VisibilityOffIcon from '@material-ui/icons/VisibilityOff';\nimport FileCopyIcon from '@material-ui/icons/FileCopy';\nimport WarningIcon from '@material-ui/icons/Warning';\nimport { useApi, identityApiRef, alertApiRef } from '@backstage/core-plugin-api';\nimport { kuadrantApiRef } from '../../api';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { RequestAccessDialog } from '../RequestAccessDialog';\nimport { useKuadrantPermission } from '../../utils/permissions';\nimport { kuadrantApiKeyCreatePermission } from '../../permissions';\nimport { APIKey, APIProduct, Plan } from \"../../types/api-management.ts\";\n\nexport interface ApiAccessCardProps {\n // deprecated: use entity annotations instead\n namespace?: string;\n}\n\nexport const ApiAccessCard = ({ namespace: propNamespace }: ApiAccessCardProps) => {\n const { entity } = useEntity();\n const kuadrantApi = useApi(kuadrantApiRef);\n const identityApi = useApi(identityApiRef);\n const alertApi = useApi(alertApiRef);\n const [userEmail, setUserEmail] = useState<string>('');\n const [requestDialogOpen, setRequestDialogOpen] = useState(false);\n const [refresh, setRefresh] = useState(0);\n\n // key reveal state\n const [visibleKeys, setVisibleKeys] = useState<Set<string>>(new Set());\n const [apiKeyValues, setApiKeyValues] = useState<Map<string, string>>(new Map());\n const [apiKeyLoading, setApiKeyLoading] = useState<Set<string>>(new Set());\n const [alreadyReadKeys, setAlreadyReadKeys] = useState<Set<string>>(new Set());\n const [showOnceWarningOpen, setShowOnceWarningOpen] = useState(false);\n const [pendingKeyReveal, setPendingKeyReveal] = useState<{\n namespace: string;\n name: string;\n } | null>(null);\n\n // get apiproduct name from entity annotation (set by entity provider)\n const apiProductName = entity.metadata.annotations?.['kuadrant.io/apiproduct'] || entity.metadata.name;\n const namespace = entity.metadata.annotations?.['kuadrant.io/namespace'] || propNamespace || 'default';\n\n // get current user identity\n useAsync(async () => {\n const profile = await identityApi.getProfileInfo();\n setUserEmail(profile.email || '');\n }, [identityApi]);\n\n // fetch user's approved keys\n const { value: requests, loading: keysLoading, error: keysError } = useAsync(async () => {\n const data = await kuadrantApi.getRequestsByNamespace(namespace)\n const allRequests = data.items || [];\n return allRequests.filter((r: APIKey) =>\n r.spec.apiProductRef?.name === apiProductName && r.status?.phase === 'Approved'\n );\n }, [namespace, apiProductName, kuadrantApi, refresh]);\n\n // fetch apiproduct to get available plans\n const { value: apiProduct, loading: productLoading } = useAsync(async () => {\n try {\n const data = await kuadrantApi.getApiProducts();\n return data.items?.find(\n (p: APIProduct) =>\n p.metadata.namespace === namespace &&\n p.metadata.name === apiProductName,\n );\n } catch (err) {\n return null;\n }\n }, [namespace, apiProductName, kuadrantApi]);\n\n const resourceRef = apiProduct\n ? `apiproduct:${apiProduct.metadata.namespace}/${apiProduct.metadata.name}`\n : undefined;\n\n const { allowed: canCreateRequest, loading: permissionLoading } = useKuadrantPermission(\n kuadrantApiKeyCreatePermission,\n resourceRef,\n );\n\n const fetchApiKeyFromSecret = async (requestNamespace: string, requestName: string) => {\n const key = `${requestNamespace}/${requestName}`;\n if (apiKeyLoading.has(key)) {\n return;\n }\n\n setApiKeyLoading((prev) => new Set(prev).add(key));\n try {\n const data = await kuadrantApi.getApiKeySecret(requestNamespace, requestName);\n setApiKeyValues((prev) => new Map(prev).set(key, data.apiKey));\n setAlreadyReadKeys((prev) => new Set(prev).add(key));\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 setAlreadyReadKeys((prev) => new Set(prev).add(key));\n alertApi.post({\n message: 'This API key has already been viewed and cannot be retrieved again.',\n severity: 'warning',\n display: 'transient',\n });\n } else {\n alertApi.post({\n message: `Failed to fetch APIKey. ${errorMessage}`,\n severity: 'error',\n display: 'transient',\n });\n }\n } finally {\n setApiKeyLoading((prev) => {\n const next = new Set(prev);\n next.delete(key);\n return next;\n });\n }\n };\n\n const clearApiKeyValue = (requestNamespace: string, requestName: string) => {\n const key = `${requestNamespace}/${requestName}`;\n setApiKeyValues((prev) => {\n const next = new Map(prev);\n next.delete(key);\n return next;\n });\n };\n\n const toggleVisibility = (keyName: string) => {\n setVisibleKeys((prev) => {\n const newSet = new Set(prev);\n if (newSet.has(keyName)) {\n newSet.delete(keyName);\n } else {\n newSet.add(keyName);\n }\n return newSet;\n });\n };\n\n const loading = keysLoading || productLoading || permissionLoading;\n\n if (loading) {\n return (\n <InfoCard title=\"Kuadrant API Keys\">\n <Box p={2}>\n <Skeleton variant=\"text\" width=\"80%\" />\n <Skeleton variant=\"text\" width=\"60%\" />\n <Skeleton variant=\"text\" width=\"70%\" />\n </Box>\n </InfoCard>\n );\n }\n\n if (keysError) {\n return <ResponseErrorPanel error={keysError} />;\n }\n\n const keys = (requests as APIKey[]) || [];\n const plans = (apiProduct?.status?.discoveredPlans || []) as Plan[];\n const canRequest = canCreateRequest && plans.length > 0;\n\n const renderKeyRow = (request: APIKey) => {\n const key = `${request.metadata.namespace}/${request.metadata.name}`;\n const isVisible = visibleKeys.has(request.metadata.name);\n const isLoading = apiKeyLoading.has(key);\n const apiKeyValue = apiKeyValues.get(key);\n const hasSecretRef = request.status?.secretRef?.name;\n const canReadSecret = request.status?.canReadSecret !== false;\n const isAlreadyRead = alreadyReadKeys.has(key) || !canReadSecret;\n\n const handleRevealClick = () => {\n if (isVisible) {\n clearApiKeyValue(request.metadata.namespace, request.metadata.name);\n toggleVisibility(request.metadata.name);\n } else if (!isAlreadyRead) {\n setPendingKeyReveal({\n namespace: request.metadata.namespace,\n name: request.metadata.name,\n });\n setShowOnceWarningOpen(true);\n }\n };\n\n const handleCopy = async () => {\n if (apiKeyValue) {\n await navigator.clipboard.writeText(apiKeyValue);\n alertApi.post({\n message: 'API key copied to clipboard',\n severity: 'success',\n display: 'transient',\n });\n }\n };\n\n return (\n <Box\n key={request.metadata.name}\n mb={1}\n p={1.5}\n border={1}\n borderColor=\"grey.300\"\n borderRadius={4}\n >\n <Box display=\"flex\" justifyContent=\"space-between\" alignItems=\"center\" mb={1}>\n <Typography variant=\"body2\" style={{ fontWeight: 500 }}>\n {request.metadata.name}\n </Typography>\n <Chip label={request.spec.planTier} color=\"primary\" size=\"small\" />\n </Box>\n {hasSecretRef && (\n <Box display=\"flex\" alignItems=\"center\">\n <Typography\n variant=\"body2\"\n style={{\n fontFamily: 'monospace',\n fontSize: '0.8rem',\n flex: 1,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}\n >\n {isLoading\n ? 'Loading...'\n : isVisible && apiKeyValue\n ? apiKeyValue\n : isAlreadyRead && !apiKeyValue\n ? 'Already viewed'\n : '••••••••••••••••'}\n </Typography>\n {isVisible && apiKeyValue && (\n <Tooltip title=\"Copy to clipboard\">\n <IconButton size=\"small\" onClick={handleCopy}>\n <FileCopyIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n )}\n <Tooltip\n title={\n isAlreadyRead && !apiKeyValue\n ? 'Key already viewed'\n : isVisible\n ? 'Hide API key'\n : 'Reveal API key (one-time only)'\n }\n >\n <span>\n <IconButton\n size=\"small\"\n onClick={handleRevealClick}\n disabled={isLoading || (isAlreadyRead && !apiKeyValue)}\n >\n {isVisible ? <VisibilityOffIcon fontSize=\"small\" /> : <VisibilityIcon fontSize=\"small\" />}\n </IconButton>\n </span>\n </Tooltip>\n </Box>\n )}\n </Box>\n );\n };\n\n return (\n <>\n <InfoCard title=\"Kuadrant API Keys\">\n <Box p={2}>\n {keys.length > 0 ? (\n <>\n <Typography variant=\"body2\" color=\"textSecondary\" gutterBottom>\n {keys.length} active key{keys.length !== 1 ? 's' : ''}\n </Typography>\n {keys.map(renderKeyRow)}\n </>\n ) : (\n <Typography variant=\"body1\" gutterBottom>\n You don't have any API keys for this API yet\n </Typography>\n )}\n <Box mt={2}>\n {canRequest ? (\n <Button\n variant=\"contained\"\n color=\"primary\"\n size=\"small\"\n startIcon={<AddIcon />}\n onClick={() => setRequestDialogOpen(true)}\n data-testid=\"request-api-access-button\"\n >\n Request API Access\n </Button>\n ) : (\n <Typography variant=\"caption\" color=\"textSecondary\">\n Visit the API Keys tab to view and manage access\n </Typography>\n )}\n </Box>\n </Box>\n </InfoCard>\n\n <RequestAccessDialog\n open={requestDialogOpen}\n onClose={() => setRequestDialogOpen(false)}\n onSuccess={() => {\n setRequestDialogOpen(false);\n setRefresh((r) => r + 1);\n }}\n apiProductName={apiProductName}\n namespace={namespace}\n userEmail={userEmail}\n plans={plans}\n />\n\n <Dialog\n open={showOnceWarningOpen}\n onClose={() => {\n setShowOnceWarningOpen(false);\n setPendingKeyReveal(null);\n }}\n maxWidth=\"sm\"\n >\n <DialogTitle>\n <Box display=\"flex\" alignItems=\"center\">\n <WarningIcon color=\"primary\" style={{ marginRight: 8 }} />\n View API Key\n </Box>\n </DialogTitle>\n <DialogContent>\n <Typography variant=\"body1\" paragraph>\n This API key can only be viewed <strong>once</strong>. After you\n reveal it, you will not be able to retrieve it again.\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Make sure to copy and store it securely before closing this view.\n </Typography>\n </DialogContent>\n <DialogActions>\n <Button\n onClick={() => {\n setShowOnceWarningOpen(false);\n setPendingKeyReveal(null);\n }}\n >\n Cancel\n </Button>\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={() => {\n if (pendingKeyReveal) {\n fetchApiKeyFromSecret(\n pendingKeyReveal.namespace,\n pendingKeyReveal.name,\n );\n toggleVisibility(pendingKeyReveal.name);\n }\n setShowOnceWarningOpen(false);\n setPendingKeyReveal(null);\n }}\n >\n Reveal API Key\n </Button>\n </DialogActions>\n </Dialog>\n </>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ApiAccessCard.esm.js","sources":["../../../src/components/ApiAccessCard/ApiAccessCard.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { useAsync } from 'react-use';\nimport {\n InfoCard,\n ResponseErrorPanel,\n} from '@backstage/core-components';\nimport {\n Typography,\n Box,\n Chip,\n Button,\n IconButton,\n Tooltip,\n} from '@material-ui/core';\nimport { Skeleton } from '@material-ui/lab';\nimport AddIcon from '@material-ui/icons/Add';\nimport VisibilityIcon from '@material-ui/icons/Visibility';\nimport VisibilityOffIcon from '@material-ui/icons/VisibilityOff';\nimport FileCopyIcon from '@material-ui/icons/FileCopy';\nimport { useApi, identityApiRef, alertApiRef } from '@backstage/core-plugin-api';\nimport { kuadrantApiRef } from '../../api';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { RequestAccessDialog } from '../RequestAccessDialog';\nimport { useKuadrantPermission } from '../../utils/permissions';\nimport { kuadrantApiKeyCreatePermission } from '../../permissions';\nimport { APIKey, APIProduct, Plan } from \"../../types/api-management\";\n\nexport interface ApiAccessCardProps {\n // deprecated: use entity annotations instead\n namespace?: string;\n}\n\nexport const ApiAccessCard = ({ namespace: propNamespace }: ApiAccessCardProps) => {\n const { entity } = useEntity();\n const kuadrantApi = useApi(kuadrantApiRef);\n const identityApi = useApi(identityApiRef);\n const alertApi = useApi(alertApiRef);\n const [userEmail, setUserEmail] = useState<string>('');\n const [requestDialogOpen, setRequestDialogOpen] = useState(false);\n const [refresh, setRefresh] = useState(0);\n\n // key reveal state\n const [visibleKeys, setVisibleKeys] = useState<Set<string>>(new Set());\n const [apiKeyValues, setApiKeyValues] = useState<Map<string, string>>(new Map());\n const [apiKeyLoading, setApiKeyLoading] = useState<Set<string>>(new Set());\n\n // get apiproduct name from entity annotation (set by entity provider)\n const apiProductName = entity.metadata.annotations?.['kuadrant.io/apiproduct'] || entity.metadata.name;\n const namespace = entity.metadata.annotations?.['kuadrant.io/namespace'] || propNamespace || 'default';\n\n // get current user identity\n useAsync(async () => {\n const profile = await identityApi.getProfileInfo();\n setUserEmail(profile.email || '');\n }, [identityApi]);\n\n // fetch user's approved keys for this API product\n // backend filters by apiProductRef.name and scopes to the user's consumer namespace\n const { value: requests, loading: keysLoading, error: keysError } = useAsync(async () => {\n const data = await kuadrantApi.getRequestsByApiProduct(apiProductName, namespace);\n const allRequests = data.items || [];\n return allRequests.filter((r: APIKey) =>\n r.status?.phase === 'Approved'\n );\n }, [namespace, apiProductName, kuadrantApi, refresh]);\n\n // fetch apiproduct to get available plans\n const { value: apiProduct, loading: productLoading } = useAsync(async () => {\n try {\n const data = await kuadrantApi.getApiProducts();\n return data.items?.find(\n (p: APIProduct) =>\n p.metadata.namespace === namespace &&\n p.metadata.name === apiProductName,\n );\n } catch (err) {\n return null;\n }\n }, [namespace, apiProductName, kuadrantApi]);\n\n const resourceRef = apiProduct\n ? `apiproduct:${apiProduct.metadata.namespace}/${apiProduct.metadata.name}`\n : undefined;\n\n const { allowed: canCreateRequest, loading: permissionLoading } = useKuadrantPermission(\n kuadrantApiKeyCreatePermission,\n resourceRef,\n );\n\n const fetchApiKeyFromSecret = async (requestNamespace: string, requestName: string) => {\n const key = `${requestNamespace}/${requestName}`;\n if (apiKeyLoading.has(key)) {\n return;\n }\n\n setApiKeyLoading((prev) => new Set(prev).add(key));\n try {\n const data = await kuadrantApi.getApiKeySecret(requestNamespace, requestName);\n setApiKeyValues((prev) => new Map(prev).set(key, data.apiKey));\n toggleVisibility(requestName);\n } catch (err) {\n console.error('failed to fetch api key:', err);\n const errorMessage = err instanceof Error ? err.message : \"unknown error occurred\";\n alertApi.post({\n message: `Failed to fetch APIKey. ${errorMessage}`,\n severity: 'error',\n display: 'transient',\n });\n } finally {\n setApiKeyLoading((prev) => {\n const next = new Set(prev);\n next.delete(key);\n return next;\n });\n }\n };\n\n const clearApiKeyValue = (requestNamespace: string, requestName: string) => {\n const key = `${requestNamespace}/${requestName}`;\n setApiKeyValues((prev) => {\n const next = new Map(prev);\n next.delete(key);\n return next;\n });\n };\n\n const toggleVisibility = (keyName: string) => {\n setVisibleKeys((prev) => {\n const newSet = new Set(prev);\n if (newSet.has(keyName)) {\n newSet.delete(keyName);\n } else {\n newSet.add(keyName);\n }\n return newSet;\n });\n };\n\n const loading = keysLoading || productLoading || permissionLoading;\n\n if (loading) {\n return (\n <InfoCard title=\"Kuadrant API Keys\">\n <Box p={2}>\n <Skeleton variant=\"text\" width=\"80%\" />\n <Skeleton variant=\"text\" width=\"60%\" />\n <Skeleton variant=\"text\" width=\"70%\" />\n </Box>\n </InfoCard>\n );\n }\n\n if (keysError) {\n return <ResponseErrorPanel error={keysError} />;\n }\n\n const keys = (requests as APIKey[]) || [];\n const plans = (apiProduct?.status?.discoveredPlans || []) as Plan[];\n const canRequest = canCreateRequest && plans.length > 0;\n\n const renderKeyRow = (request: APIKey) => {\n const key = `${request.metadata.namespace}/${request.metadata.name}`;\n const isVisible = visibleKeys.has(request.metadata.name);\n const isLoading = apiKeyLoading.has(key);\n const apiKeyValue = apiKeyValues.get(key);\n const hasSecretRef = Boolean(request.spec?.secretRef?.name);\n\n const handleRevealClick = () => {\n if (isVisible) {\n clearApiKeyValue(request.metadata.namespace, request.metadata.name);\n toggleVisibility(request.metadata.name);\n } else {\n fetchApiKeyFromSecret(request.metadata.namespace, request.metadata.name);\n }\n };\n\n const handleCopy = async () => {\n if (apiKeyValue) {\n await navigator.clipboard.writeText(apiKeyValue);\n alertApi.post({\n message: 'API key copied to clipboard',\n severity: 'success',\n display: 'transient',\n });\n }\n };\n\n return (\n <Box\n key={request.metadata.name}\n mb={1}\n p={1.5}\n border={1}\n borderColor=\"grey.300\"\n borderRadius={4}\n >\n <Box display=\"flex\" justifyContent=\"space-between\" alignItems=\"center\" mb={1}>\n <Typography variant=\"body2\" style={{ fontWeight: 500 }}>\n {request.metadata.name}\n </Typography>\n <Chip label={request.spec.planTier} color=\"primary\" size=\"small\" />\n </Box>\n {hasSecretRef && (\n <Box display=\"flex\" alignItems=\"center\">\n <Typography\n variant=\"body2\"\n style={{\n fontFamily: 'monospace',\n fontSize: '0.8rem',\n flex: 1,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}\n >\n {isLoading\n ? 'Loading...'\n : isVisible && apiKeyValue\n ? apiKeyValue\n : '••••••••••••••••'}\n </Typography>\n {isVisible && apiKeyValue && (\n <Tooltip title=\"Copy to clipboard\">\n <IconButton size=\"small\" onClick={handleCopy}>\n <FileCopyIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n )}\n <Tooltip title={isVisible ? 'Hide API key' : 'Reveal API key'}>\n <span>\n <IconButton\n size=\"small\"\n onClick={handleRevealClick}\n disabled={isLoading}\n >\n {isVisible ? <VisibilityOffIcon fontSize=\"small\" /> : <VisibilityIcon fontSize=\"small\" />}\n </IconButton>\n </span>\n </Tooltip>\n </Box>\n )}\n </Box>\n );\n };\n\n return (\n <>\n <InfoCard title=\"Kuadrant API Keys\">\n <Box p={2}>\n {keys.length > 0 ? (\n <>\n <Typography variant=\"body2\" color=\"textSecondary\" gutterBottom>\n {keys.length} active key{keys.length !== 1 ? 's' : ''}\n </Typography>\n {keys.map(renderKeyRow)}\n </>\n ) : (\n <Typography variant=\"body1\" gutterBottom>\n You don't have any API keys for this API yet\n </Typography>\n )}\n <Box mt={2}>\n {canRequest ? (\n <Button\n variant=\"contained\"\n color=\"primary\"\n size=\"small\"\n startIcon={<AddIcon />}\n onClick={() => setRequestDialogOpen(true)}\n data-testid=\"request-api-access-button\"\n >\n Request API Access\n </Button>\n ) : (\n <Typography variant=\"caption\" color=\"textSecondary\">\n Visit the API Keys tab to view and manage access\n </Typography>\n )}\n </Box>\n </Box>\n </InfoCard>\n\n <RequestAccessDialog\n open={requestDialogOpen}\n onClose={() => setRequestDialogOpen(false)}\n onSuccess={() => {\n setRequestDialogOpen(false);\n setRefresh((r) => r + 1);\n }}\n apiProductName={apiProductName}\n namespace={namespace}\n userEmail={userEmail}\n plans={plans}\n />\n\n </>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ApiKeyApprovalPage } from './ApiKeyApprovalPage.esm.js';
|
|
3
|
+
import { PermissionGate } from '../PermissionGate/PermissionGate.esm.js';
|
|
4
|
+
import { kuadrantApiKeyApprovePermission } from '../../permissions.esm.js';
|
|
5
|
+
|
|
6
|
+
const ApiKeyApprovalPageWithPermissions = () => {
|
|
7
|
+
return /* @__PURE__ */ React.createElement(
|
|
8
|
+
PermissionGate,
|
|
9
|
+
{
|
|
10
|
+
permission: kuadrantApiKeyApprovePermission,
|
|
11
|
+
errorMessage: "You don't have permission to approve API keys"
|
|
12
|
+
},
|
|
13
|
+
/* @__PURE__ */ React.createElement(ApiKeyApprovalPage, null)
|
|
14
|
+
);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export { ApiKeyApprovalPageWithPermissions };
|
|
18
|
+
//# sourceMappingURL=ApiKeyApprovalPageWithPermissions.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApiKeyApprovalPageWithPermissions.esm.js","sources":["../../../src/components/ApiKeyApprovalPage/ApiKeyApprovalPageWithPermissions.tsx"],"sourcesContent":["import React from 'react';\nimport { ApiKeyApprovalPage } from './ApiKeyApprovalPage';\nimport { PermissionGate } from '../PermissionGate';\nimport { kuadrantApiKeyApprovePermission } from '../../permissions';\n\nexport const ApiKeyApprovalPageWithPermissions = () => {\n return (\n <PermissionGate\n permission={kuadrantApiKeyApprovePermission}\n errorMessage=\"You don't have permission to approve API keys\"\n >\n <ApiKeyApprovalPage />\n </PermissionGate>\n );\n};\n"],"names":[],"mappings":";;;;;AAKO,MAAM,oCAAoC,MAAM;AACrD,EACE,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,cAAA;AAAA,IAAA;AAAA,MACC,UAAY,EAAA,+BAAA;AAAA,MACZ,YAAa,EAAA;AAAA,KAAA;AAAA,wCAEZ,kBAAmB,EAAA,IAAA;AAAA,GACtB;AAEJ;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|