'use strict';

var errors = require('@backstage/errors');
var pluginPermissionCommon = require('@backstage/plugin-permission-common');
var pluginPermissionNode = require('@backstage/plugin-permission-node');
var zod = require('zod');
var express = require('express');
var Router = require('express-promise-router');
var cors = require('cors');
var crypto = require('crypto');
var k8sClient = require('./k8s-client.cjs.js');
var module$1 = require('./module.cjs.js');
var permissions = require('./permissions.cjs.js');

function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }

var express__default = /*#__PURE__*/_interopDefaultCompat(express);
var Router__default = /*#__PURE__*/_interopDefaultCompat(Router);
var cors__default = /*#__PURE__*/_interopDefaultCompat(cors);

const secretKey = "api_key";
function extractNameFromEntityRef(entityRef) {
  const parts = entityRef.split("/");
  return parts[parts.length - 1];
}
async function getUserIdentity(req, httpAuth, userInfo) {
  const credentials = await httpAuth.credentials(req);
  if (!credentials || !credentials.principal) {
    throw new errors.NotAllowedError("authentication required");
  }
  const info = await userInfo.getUserInfo(credentials);
  const groups = info.ownershipEntityRefs || [];
  console.log(`user identity resolved: userEntityRef=${info.userEntityRef}, groups=${groups.join(",")}`);
  return {
    userEntityRef: info.userEntityRef,
    groups
  };
}
async function verifyApiKeyUpdatePermission(credentials, userEntityRef, namespace, apiProductName, k8sClient, permissions$1) {
  const updateAllDecision = await permissions$1.authorize(
    [{ permission: permissions.kuadrantApiKeyUpdateAllPermission }],
    { credentials }
  );
  if (updateAllDecision[0].result === pluginPermissionCommon.AuthorizeResult.ALLOW) {
    return;
  }
  const updateOwnDecision = await permissions$1.authorize(
    [{ permission: permissions.kuadrantApiKeyUpdateOwnPermission }],
    { credentials }
  );
  if (updateOwnDecision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
    throw new errors.NotAllowedError("unauthorised");
  }
  let apiProduct;
  try {
    apiProduct = await k8sClient.getCustomResource(
      "devportal.kuadrant.io",
      "v1alpha1",
      namespace,
      "apiproducts",
      apiProductName
    );
  } catch (error) {
    throw new errors.InputError(`APIProduct '${apiProductName}' not found in namespace '${namespace}' - cannot verify ownership`);
  }
  const owner = apiProduct.metadata?.annotations?.["backstage.io/owner"];
  if (owner !== userEntityRef) {
    throw new errors.NotAllowedError("you can only update requests for your own api products");
  }
}
async function createRouter({
  httpAuth,
  userInfo,
  config,
  permissions: permissions$1
}) {
  const router = Router__default.default();
  router.use(cors__default.default({
    origin: "http://localhost:3000",
    credentials: true
  }));
  router.use(express__default.default.json());
  const k8sClient$1 = new k8sClient.KuadrantK8sClient(config);
  router.get("/apiproducts", async (req, res) => {
    try {
      const credentials = await httpAuth.credentials(req);
      const listDecision = await permissions$1.authorize(
        [{ permission: permissions.kuadrantApiProductListPermission }],
        { credentials }
      );
      if (listDecision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
        throw new errors.NotAllowedError("unauthorised");
      }
      const { userEntityRef } = await getUserIdentity(req, httpAuth, userInfo);
      const data = await k8sClient$1.listCustomResources("devportal.kuadrant.io", "v1alpha1", "apiproducts");
      const readAllDecision = await permissions$1.authorize(
        [{ permission: permissions.kuadrantApiProductReadAllPermission }],
        { credentials }
      );
      if (readAllDecision[0].result === pluginPermissionCommon.AuthorizeResult.ALLOW) {
        res.json(data);
      } else {
        const readOwnDecision = await permissions$1.authorize(
          [{ permission: permissions.kuadrantApiProductReadOwnPermission }],
          { credentials }
        );
        if (readOwnDecision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
          throw new errors.NotAllowedError("unauthorised");
        }
        const ownedItems = (data.items || []).filter((item) => {
          const owner = item.metadata?.annotations?.["backstage.io/owner"];
          return owner === userEntityRef;
        });
        res.json({ ...data, items: ownedItems });
      }
    } catch (error) {
      console.error("error fetching apiproducts:", error);
      if (error instanceof errors.NotAllowedError) {
        res.status(403).json({ error: error.message });
      } else {
        res.status(500).json({ error: "failed to fetch apiproducts" });
      }
    }
  });
  router.get("/apiproducts/:namespace/:name", async (req, res) => {
    try {
      const credentials = await httpAuth.credentials(req);
      const { namespace, name } = req.params;
      const readAllDecision = await permissions$1.authorize(
        [{ permission: permissions.kuadrantApiProductReadAllPermission }],
        { credentials }
      );
      if (readAllDecision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
        const readOwnDecision = await permissions$1.authorize(
          [{ permission: permissions.kuadrantApiProductReadOwnPermission }],
          { credentials }
        );
        if (readOwnDecision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
          throw new errors.NotAllowedError("unauthorised");
        }
        const { userEntityRef } = await getUserIdentity(req, httpAuth, userInfo);
        const data = await k8sClient$1.getCustomResource("devportal.kuadrant.io", "v1alpha1", namespace, "apiproducts", name);
        const owner = data.metadata?.annotations?.["backstage.io/owner"];
        if (owner !== userEntityRef) {
          throw new errors.NotAllowedError("you can only read your own api products");
        }
        res.json(data);
      } else {
        const data = await k8sClient$1.getCustomResource("devportal.kuadrant.io", "v1alpha1", namespace, "apiproducts", name);
        res.json(data);
      }
    } catch (error) {
      console.error("error fetching apiproduct:", error);
      if (error instanceof errors.NotAllowedError) {
        res.status(403).json({ error: error.message });
      } else {
        res.status(500).json({ error: "failed to fetch apiproduct" });
      }
    }
  });
  router.post("/apiproducts", async (req, res) => {
    try {
      const credentials = await httpAuth.credentials(req);
      const decision = await permissions$1.authorize(
        [{ permission: permissions.kuadrantApiProductCreatePermission }],
        { credentials }
      );
      if (decision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
        throw new errors.NotAllowedError("unauthorised");
      }
      const { userEntityRef } = await getUserIdentity(req, httpAuth, userInfo);
      const apiProduct = req.body;
      const targetRef = apiProduct.spec?.targetRef;
      if (!targetRef?.name || !targetRef?.kind || !targetRef?.namespace) {
        throw new errors.InputError("targetRef with name, kind, and namespace is required");
      }
      const namespace = targetRef.namespace;
      apiProduct.metadata.namespace = namespace;
      if (!apiProduct.metadata.annotations) {
        apiProduct.metadata.annotations = {};
      }
      apiProduct.metadata.annotations["backstage.io/owner"] = userEntityRef;
      const created = await k8sClient$1.createCustomResource(
        "devportal.kuadrant.io",
        "v1alpha1",
        namespace,
        "apiproducts",
        apiProduct
      );
      const provider = module$1.getAPIProductEntityProvider();
      if (provider) {
        await provider.refresh();
      }
      res.status(201).json(created);
    } catch (error) {
      console.error("error creating apiproduct:", error);
      const errorMessage = error instanceof Error ? error.message : String(error);
      if (error instanceof errors.NotAllowedError) {
        res.status(403).json({ error: error.message });
      } else if (error instanceof errors.InputError) {
        res.status(400).json({ error: error.message });
      } else {
        res.status(500).json({ error: errorMessage });
      }
    }
  });
  router.delete("/apiproducts/:namespace/:name", async (req, res) => {
    try {
      const credentials = await httpAuth.credentials(req);
      const { namespace, name } = req.params;
      const deleteAllDecision = await permissions$1.authorize(
        [{ permission: permissions.kuadrantApiProductDeleteAllPermission }],
        { credentials }
      );
      if (deleteAllDecision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
        const deleteOwnDecision = await permissions$1.authorize(
          [{ permission: permissions.kuadrantApiProductDeleteOwnPermission }],
          { credentials }
        );
        if (deleteOwnDecision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
          throw new errors.NotAllowedError("unauthorised");
        }
        const { userEntityRef } = await getUserIdentity(req, httpAuth, userInfo);
        const existing = await k8sClient$1.getCustomResource("devportal.kuadrant.io", "v1alpha1", namespace, "apiproducts", name);
        const owner = existing.metadata?.annotations?.["backstage.io/owner"];
        if (owner !== userEntityRef) {
          throw new errors.NotAllowedError("you can only delete your own api products");
        }
      }
      console.log(`cascading delete: finding apikeys for ${namespace}/${name}`);
      let allRequests;
      try {
        allRequests = await k8sClient$1.listCustomResources(
          "devportal.kuadrant.io",
          "v1alpha1",
          "apikeys",
          namespace
        );
      } catch (error) {
        console.warn("failed to list apikeys during cascade delete:", error);
        allRequests = { items: [] };
      }
      const relatedRequests = (allRequests.items || []).filter(
        (req2) => req2.spec?.apiProductRef?.name === name
      );
      console.log(`found ${relatedRequests.length} apikeys to delete`);
      const deletionResults = await Promise.allSettled(
        relatedRequests.map(async (request) => {
          const requestName = request.metadata.name;
          console.log(`deleting apikey: ${namespace}/${requestName}`);
          await k8sClient$1.deleteCustomResource(
            "devportal.kuadrant.io",
            "v1alpha1",
            namespace,
            "apikeys",
            requestName
          );
        })
      );
      const failures = deletionResults.filter((r) => r.status === "rejected");
      if (failures.length > 0) {
        console.warn(
          `${failures.length} apikeys failed to delete:`,
          failures.map((f) => f.reason)
        );
      }
      await k8sClient$1.deleteCustomResource(
        "devportal.kuadrant.io",
        "v1alpha1",
        namespace,
        "apiproducts",
        name
      );
      const provider = module$1.getAPIProductEntityProvider();
      if (provider) {
        await provider.refresh();
      }
      res.status(204).send();
    } catch (error) {
      console.error("error deleting apiproduct:", error);
      if (error instanceof errors.NotAllowedError) {
        res.status(403).json({ error: error.message });
      } else {
        res.status(500).json({ error: "failed to delete apiproduct" });
      }
    }
  });
  router.get("/httproutes", async (req, res) => {
    try {
      const credentials = await httpAuth.credentials(req);
      const decision = await permissions$1.authorize(
        [{ permission: permissions.kuadrantHttpRouteListPermission }],
        { credentials }
      );
      if (decision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
        throw new errors.NotAllowedError("unauthorised");
      }
      const data = await k8sClient$1.listCustomResources("gateway.networking.k8s.io", "v1", "httproutes");
      res.json(data);
    } catch (error) {
      console.error("error fetching httproutes:", error);
      if (error instanceof errors.NotAllowedError) {
        res.status(403).json({ error: error.message });
      } else {
        res.status(500).json({ error: "failed to fetch httproutes" });
      }
    }
  });
  router.get("/httproutes/:namespace/:name", async (req, res) => {
    try {
      const credentials = await httpAuth.credentials(req);
      const decision = await permissions$1.authorize(
        [{ permission: permissions.kuadrantHttpRouteListPermission }],
        { credentials }
      );
      if (decision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
        throw new errors.NotAllowedError("unauthorised");
      }
      const { namespace, name } = req.params;
      const data = await k8sClient$1.getCustomResource("gateway.networking.k8s.io", "v1", namespace, "httproutes", name);
      res.json(data);
    } catch (error) {
      console.error("error fetching httproute:", error);
      if (error instanceof errors.NotAllowedError) {
        res.status(403).json({ error: error.message });
      } else {
        res.status(500).json({ error: "failed to fetch httproute" });
      }
    }
  });
  router.patch("/apiproducts/:namespace/:name", async (req, res) => {
    const patchSchema = zod.z.object({
      metadata: zod.z.object({
        labels: zod.z.object({
          // allow updating lifecycle phase via edit apiproduct dialog
          // synced to backstage catalog entity's lifecycle field
          lifecycle: zod.z.enum(["experimental", "production", "deprecated", "retired"]).optional()
        }).partial().optional()
      }).partial().optional(),
      spec: zod.z.object({
        displayName: zod.z.string().optional(),
        description: zod.z.string().optional(),
        version: zod.z.string().optional(),
        publishStatus: zod.z.enum(["Draft", "Published"]).optional(),
        approvalMode: zod.z.enum(["automatic", "manual"]).optional(),
        tags: zod.z.array(zod.z.string()).optional(),
        contact: zod.z.object({
          email: zod.z.string().optional(),
          team: zod.z.string().optional(),
          slack: zod.z.string().optional()
        }).partial().optional(),
        documentation: zod.z.object({
          docsURL: zod.z.string().optional(),
          openAPISpecURL: zod.z.string().optional()
        }).partial().optional()
      }).partial()
    });
    const parsed = patchSchema.safeParse(req.body);
    if (!parsed.success) {
      return res.status(400).json({ error: "invalid patch: " + parsed.error.toString() });
    }
    try {
      const credentials = await httpAuth.credentials(req);
      if (!credentials || !credentials.principal) {
        throw new errors.NotAllowedError("authentication required");
      }
      const { namespace, name } = req.params;
      const updateAllDecision = await permissions$1.authorize(
        [{ permission: permissions.kuadrantApiProductUpdateAllPermission }],
        { credentials }
      );
      if (updateAllDecision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
        const updateOwnDecision = await permissions$1.authorize(
          [{ permission: permissions.kuadrantApiProductUpdateOwnPermission }],
          { credentials }
        );
        if (updateOwnDecision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
          throw new errors.NotAllowedError("unauthorised");
        }
        const { userEntityRef } = await getUserIdentity(req, httpAuth, userInfo);
        const existing = await k8sClient$1.getCustomResource("devportal.kuadrant.io", "v1alpha1", namespace, "apiproducts", name);
        const owner = existing.metadata?.annotations?.["backstage.io/owner"];
        if (owner !== userEntityRef) {
          throw new errors.NotAllowedError("you can only update your own api products");
        }
      }
      if (req.body.metadata?.annotations) {
        delete req.body.metadata.annotations["backstage.io/owner"];
      }
      if (parsed.data.spec?.publishStatus === "Published" && parsed.data.metadata?.labels?.lifecycle === "retired") {
        throw new errors.InputError("cannot publish a retired API product");
      }
      if (parsed.data.metadata?.labels?.lifecycle === "retired") {
        const existing = await k8sClient$1.getCustomResource("devportal.kuadrant.io", "v1alpha1", namespace, "apiproducts", name);
        if (existing.spec?.publishStatus === "Published") {
          if (!parsed.data.spec) {
            parsed.data.spec = {};
          }
          parsed.data.spec.publishStatus = "Draft";
        }
      }
      const updated = await k8sClient$1.patchCustomResource(
        "devportal.kuadrant.io",
        "v1alpha1",
        namespace,
        "apiproducts",
        name,
        parsed.data
      );
      const provider = module$1.getAPIProductEntityProvider();
      if (provider) {
        await provider.refresh();
      }
      return res.json(updated);
    } catch (error) {
      console.error("error updating apiproduct:", error);
      const errorMessage = error instanceof Error ? error.message : String(error);
      if (error instanceof errors.NotAllowedError) {
        return res.status(403).json({ error: error.message });
      } else if (error instanceof errors.InputError) {
        return res.status(400).json({ error: error.message });
      } else {
        return res.status(500).json({ error: errorMessage });
      }
    }
  });
  router.get("/planpolicies", async (req, res) => {
    try {
      const credentials = await httpAuth.credentials(req);
      const decision = await permissions$1.authorize(
        [{ permission: permissions.kuadrantPlanPolicyListPermission }],
        { credentials }
      );
      if (decision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
        throw new errors.NotAllowedError("unauthorised");
      }
      const data = await k8sClient$1.listCustomResources("extensions.kuadrant.io", "v1alpha1", "planpolicies");
      const filtered = {
        items: (data.items || []).map((policy) => ({
          metadata: {
            name: policy.metadata.name,
            namespace: policy.metadata.namespace
          },
          spec: policy.spec ? {
            // expose targetRef to allow UI to match PlanPolicy -> HTTPRoute
            targetRef: policy.spec.targetRef ? {
              kind: policy.spec.targetRef.kind,
              name: policy.spec.targetRef.name,
              namespace: policy.spec.targetRef.namespace
            } : void 0,
            plans: (policy.spec.plans || []).map((plan) => ({
              tier: plan.tier,
              description: plan.description,
              limits: plan.limits
            }))
          } : {},
          status: policy.status
        }))
      };
      res.json(filtered);
    } catch (error) {
      console.error("error fetching planpolicies:", error);
      if (error instanceof errors.NotAllowedError) {
        res.status(403).json({ error: error.message });
      } else {
        res.status(500).json({ error: "failed to fetch planpolicies" });
      }
    }
  });
  router.get("/planpolicies/:namespace/:name", async (req, res) => {
    try {
      const credentials = await httpAuth.credentials(req);
      const decision = await permissions$1.authorize(
        [{ permission: permissions.kuadrantPlanPolicyReadPermission }],
        { credentials }
      );
      if (decision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
        throw new errors.NotAllowedError("unauthorised");
      }
      const { namespace, name } = req.params;
      const data = await k8sClient$1.getCustomResource("extensions.kuadrant.io", "v1alpha1", namespace, "planpolicies", name);
      res.json(data);
    } catch (error) {
      console.error("error fetching planpolicy:", error);
      if (error instanceof errors.NotAllowedError) {
        res.status(403).json({ error: error.message });
      } else {
        res.status(500).json({ error: "failed to fetch planpolicy" });
      }
    }
  });
  const requestSchema = zod.z.object({
    apiProductName: zod.z.string(),
    // name of the APIProduct
    namespace: zod.z.string(),
    // namespace where both APIProduct and APIKey live
    planTier: zod.z.string(),
    useCase: zod.z.string().optional(),
    userEmail: zod.z.string().optional()
  });
  router.post("/requests", async (req, res) => {
    const parsed = requestSchema.safeParse(req.body);
    if (!parsed.success) {
      throw new errors.InputError(parsed.error.toString());
    }
    try {
      const credentials = await httpAuth.credentials(req);
      const { apiProductName, namespace, planTier, useCase, userEmail } = parsed.data;
      const { userEntityRef } = await getUserIdentity(req, httpAuth, userInfo);
      const resourceRef = `apiproduct:${namespace}/${apiProductName}`;
      const decision = await permissions$1.authorize(
        [{
          permission: permissions.kuadrantApiKeyCreatePermission,
          resourceRef
        }],
        { credentials }
      );
      if (decision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
        throw new errors.NotAllowedError(`not authorised to request access to ${apiProductName}`);
      }
      const randomSuffix = crypto.randomBytes(4).toString("hex");
      const userName = extractNameFromEntityRef(userEntityRef);
      const requestName = `${userName}-${apiProductName}-${randomSuffix}`.toLowerCase().replace(/[^a-z0-9-]/g, "-");
      const requestedBy = { userId: userEntityRef };
      if (userEmail) {
        requestedBy.email = userEmail;
      }
      const request = {
        apiVersion: "devportal.kuadrant.io/v1alpha1",
        kind: "APIKey",
        metadata: {
          name: requestName,
          namespace
        },
        spec: {
          apiProductRef: {
            name: apiProductName
          },
          planTier,
          useCase: useCase || "",
          requestedBy
        }
      };
      const created = await k8sClient$1.createCustomResource(
        "devportal.kuadrant.io",
        "v1alpha1",
        namespace,
        "apikeys",
        request
      );
      res.status(201).json(created);
    } catch (error) {
      console.error("error creating api key request:", error);
      if (error instanceof errors.NotAllowedError) {
        res.status(403).json({ error: error.message });
      } else {
        const errorMessage = error instanceof Error ? error.message : "failed to create api key request";
        res.status(500).json({ error: errorMessage });
      }
    }
  });
  router.get("/requests", async (req, res) => {
    try {
      const credentials = await httpAuth.credentials(req);
      const readAllDecision = await permissions$1.authorize(
        [{ permission: permissions.kuadrantApiKeyReadAllPermission }],
        { credentials }
      );
      const canReadAll = readAllDecision[0].result === pluginPermissionCommon.AuthorizeResult.ALLOW;
      if (!canReadAll) {
        const readOwnDecision = await permissions$1.authorize(
          [{ permission: permissions.kuadrantApiKeyReadOwnPermission }],
          { credentials }
        );
        if (readOwnDecision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
          throw new errors.NotAllowedError("unauthorised");
        }
      }
      const status = req.query.status;
      const namespace = req.query.namespace;
      let data;
      if (namespace) {
        data = await k8sClient$1.listCustomResources("devportal.kuadrant.io", "v1alpha1", "apikeys", namespace);
      } else {
        data = await k8sClient$1.listCustomResources("devportal.kuadrant.io", "v1alpha1", "apikeys");
      }
      let filteredItems = data.items || [];
      if (!canReadAll) {
        const { userEntityRef } = await getUserIdentity(req, httpAuth, userInfo);
        const apiproducts = await k8sClient$1.listCustomResources("devportal.kuadrant.io", "v1alpha1", "apiproducts");
        const ownedApiProducts = (apiproducts.items || []).filter((product) => {
          const owner = product.metadata?.annotations?.["backstage.io/owner"];
          return owner === userEntityRef;
        }).map((product) => product.metadata.name);
        filteredItems = filteredItems.filter(
          (req2) => ownedApiProducts.includes(req2.spec?.apiProductRef?.name)
        );
      }
      if (status) {
        filteredItems = filteredItems.filter((req2) => {
          const phase = req2.status?.phase || "Pending";
          return phase === status;
        });
      }
      res.json({ items: filteredItems });
    } catch (error) {
      console.error("error fetching api key requests:", error);
      if (error instanceof errors.NotAllowedError) {
        res.status(403).json({ error: error.message });
      } else {
        res.status(500).json({ error: "failed to fetch api key requests" });
      }
    }
  });
  router.get("/requests/my", async (req, res) => {
    try {
      const credentials = await httpAuth.credentials(req);
      const decision = await permissions$1.authorize(
        [{ permission: permissions.kuadrantApiKeyReadOwnPermission }],
        { credentials }
      );
      if (decision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
        throw new errors.NotAllowedError("unauthorised");
      }
      const { userEntityRef } = await getUserIdentity(req, httpAuth, userInfo);
      const namespace = req.query.namespace;
      let data;
      if (namespace) {
        data = await k8sClient$1.listCustomResources("devportal.kuadrant.io", "v1alpha1", "apikeys", namespace);
      } else {
        data = await k8sClient$1.listCustomResources("devportal.kuadrant.io", "v1alpha1", "apikeys");
      }
      const filteredItems = (data.items || []).filter(
        (req2) => req2.spec?.requestedBy?.userId === userEntityRef
      );
      res.json({ items: filteredItems });
    } catch (error) {
      console.error("error fetching user api key requests:", error);
      if (error instanceof errors.NotAllowedError) {
        res.status(403).json({ error: error.message });
      } else {
        res.status(500).json({ error: "failed to fetch user api key requests" });
      }
    }
  });
  const approveRejectSchema = zod.z.object({
    comment: zod.z.string().optional()
  });
  router.post("/requests/:namespace/:name/approve", async (req, res) => {
    const parsed = approveRejectSchema.safeParse(req.body);
    if (!parsed.success) {
      throw new errors.InputError(parsed.error.toString());
    }
    try {
      const credentials = await httpAuth.credentials(req);
      const { userEntityRef } = await getUserIdentity(req, httpAuth, userInfo);
      const { namespace, name } = req.params;
      const reviewedBy = userEntityRef;
      const request = await k8sClient$1.getCustomResource(
        "devportal.kuadrant.io",
        "v1alpha1",
        namespace,
        "apikeys",
        name
      );
      const spec = request.spec;
      const apiProductName = spec.apiProductRef?.name;
      if (!apiProductName) {
        throw new errors.InputError("apiProductRef.name is required in APIKey spec");
      }
      await verifyApiKeyUpdatePermission(
        credentials,
        userEntityRef,
        namespace,
        apiProductName,
        k8sClient$1,
        permissions$1
      );
      const status = {
        phase: "Approved",
        reviewedBy,
        reviewedAt: (/* @__PURE__ */ new Date()).toISOString()
      };
      await k8sClient$1.patchCustomResourceStatus(
        "devportal.kuadrant.io",
        "v1alpha1",
        namespace,
        "apikeys",
        name,
        status
      );
      res.json({ success: true });
    } catch (error) {
      console.error("error approving api key request:", error);
      if (error instanceof errors.NotAllowedError) {
        res.status(403).json({ error: error.message });
      } else {
        res.status(500).json({ error: "failed to approve api key request" });
      }
    }
  });
  router.post("/requests/:namespace/:name/reject", async (req, res) => {
    const parsed = approveRejectSchema.safeParse(req.body);
    if (!parsed.success) {
      throw new errors.InputError(parsed.error.toString());
    }
    try {
      const credentials = await httpAuth.credentials(req);
      const { userEntityRef } = await getUserIdentity(req, httpAuth, userInfo);
      const { namespace, name } = req.params;
      const reviewedBy = userEntityRef;
      const request = await k8sClient$1.getCustomResource(
        "devportal.kuadrant.io",
        "v1alpha1",
        namespace,
        "apikeys",
        name
      );
      const spec = request.spec;
      const apiProductName = spec.apiProductRef?.name;
      if (!apiProductName) {
        throw new errors.InputError("apiProductRef.name is required in APIKey spec");
      }
      await verifyApiKeyUpdatePermission(
        credentials,
        userEntityRef,
        namespace,
        apiProductName,
        k8sClient$1,
        permissions$1
      );
      const status = {
        phase: "Rejected",
        reviewedBy,
        reviewedAt: (/* @__PURE__ */ new Date()).toISOString()
      };
      await k8sClient$1.patchCustomResourceStatus(
        "devportal.kuadrant.io",
        "v1alpha1",
        namespace,
        "apikeys",
        name,
        status
      );
      res.status(204).send();
    } catch (error) {
      console.error("error rejecting api key request:", error);
      if (error instanceof errors.NotAllowedError) {
        res.status(403).json({ error: error.message });
      } else {
        res.status(500).json({ error: "failed to reject api key request" });
      }
    }
  });
  const bulkApproveSchema = zod.z.object({
    requests: zod.z.array(zod.z.object({
      namespace: zod.z.string(),
      name: zod.z.string()
    })),
    comment: zod.z.string().optional()
  });
  router.post("/requests/bulk-approve", async (req, res) => {
    const parsed = bulkApproveSchema.safeParse(req.body);
    if (!parsed.success) {
      throw new errors.InputError(parsed.error.toString());
    }
    try {
      const credentials = await httpAuth.credentials(req);
      const { userEntityRef } = await getUserIdentity(req, httpAuth, userInfo);
      const updateAllDecision = await permissions$1.authorize(
        [{ permission: permissions.kuadrantApiKeyUpdateAllPermission }],
        { credentials }
      );
      const canUpdateAll = updateAllDecision[0].result === pluginPermissionCommon.AuthorizeResult.ALLOW;
      if (!canUpdateAll) {
        const updateOwnDecision = await permissions$1.authorize(
          [{ permission: permissions.kuadrantApiKeyUpdateOwnPermission }],
          { credentials }
        );
        if (updateOwnDecision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
          throw new errors.NotAllowedError("unauthorised");
        }
      }
      const { requests } = parsed.data;
      const reviewedBy = userEntityRef;
      const results = [];
      for (const reqRef of requests) {
        try {
          if (!canUpdateAll) {
            const request = await k8sClient$1.getCustomResource(
              "devportal.kuadrant.io",
              "v1alpha1",
              reqRef.namespace,
              "apikeys",
              reqRef.name
            );
            const apiProductName = request.spec?.apiProductRef?.name;
            if (!apiProductName) {
              results.push({
                namespace: reqRef.namespace,
                name: reqRef.name,
                success: false,
                error: "API key has no associated API product."
              });
              continue;
            }
            const apiProduct = await k8sClient$1.getCustomResource(
              "devportal.kuadrant.io",
              "v1alpha1",
              reqRef.namespace,
              "apiproducts",
              apiProductName
            );
            const owner = apiProduct.metadata?.annotations?.["backstage.io/owner"];
            if (owner !== userEntityRef) {
              results.push({
                namespace: reqRef.namespace,
                name: reqRef.name,
                success: false,
                error: "You can only approve requests for your own API products."
              });
              continue;
            }
          }
          const status = {
            phase: "Approved",
            reviewedBy,
            reviewedAt: (/* @__PURE__ */ new Date()).toISOString()
          };
          await k8sClient$1.patchCustomResourceStatus(
            "devportal.kuadrant.io",
            "v1alpha1",
            reqRef.namespace,
            "apikeys",
            reqRef.name,
            status
          );
          results.push({ namespace: reqRef.namespace, name: reqRef.name, success: true });
        } catch (error) {
          console.error(`error approving request ${reqRef.namespace}/${reqRef.name}:`, error);
          results.push({
            namespace: reqRef.namespace,
            name: reqRef.name,
            success: false,
            error: error instanceof Error ? error.message : "unknown error"
          });
        }
      }
      res.json({ results });
    } catch (error) {
      console.error("error in bulk approve:", error);
      if (error instanceof errors.NotAllowedError) {
        res.status(403).json({ error: error.message });
      } else {
        res.status(500).json({ error: "failed to bulk approve api key requests" });
      }
    }
  });
  router.post("/requests/bulk-reject", async (req, res) => {
    const parsed = bulkApproveSchema.safeParse(req.body);
    if (!parsed.success) {
      throw new errors.InputError(parsed.error.toString());
    }
    try {
      const credentials = await httpAuth.credentials(req);
      const { userEntityRef } = await getUserIdentity(req, httpAuth, userInfo);
      const updateAllDecision = await permissions$1.authorize(
        [{ permission: permissions.kuadrantApiKeyUpdateAllPermission }],
        { credentials }
      );
      const canUpdateAll = updateAllDecision[0].result === pluginPermissionCommon.AuthorizeResult.ALLOW;
      if (!canUpdateAll) {
        const updateOwnDecision = await permissions$1.authorize(
          [{ permission: permissions.kuadrantApiKeyUpdateOwnPermission }],
          { credentials }
        );
        if (updateOwnDecision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
          throw new errors.NotAllowedError("unauthorised");
        }
      }
      const { requests } = parsed.data;
      const reviewedBy = userEntityRef;
      const results = [];
      for (const reqRef of requests) {
        try {
          const request = await k8sClient$1.getCustomResource(
            "devportal.kuadrant.io",
            "v1alpha1",
            reqRef.namespace,
            "apikeys",
            reqRef.name
          );
          const spec = request.spec;
          const apiProduct = await k8sClient$1.getCustomResource(
            "devportal.kuadrant.io",
            "v1alpha1",
            reqRef.namespace,
            "apiproducts",
            spec.apiProductRef?.name
          );
          const owner = apiProduct.metadata?.annotations?.["backstage.io/owner"];
          if (!canUpdateAll && owner !== userEntityRef) {
            results.push({
              namespace: reqRef.namespace,
              name: reqRef.name,
              success: false,
              error: "You can only reject requests for your own API products."
            });
            continue;
          }
          const status = {
            phase: "Rejected",
            reviewedBy,
            reviewedAt: (/* @__PURE__ */ new Date()).toISOString()
          };
          await k8sClient$1.patchCustomResourceStatus(
            "devportal.kuadrant.io",
            "v1alpha1",
            reqRef.namespace,
            "apikeys",
            reqRef.name,
            status
          );
          results.push({ namespace: reqRef.namespace, name: reqRef.name, success: true });
        } catch (error) {
          console.error(`error rejecting request ${reqRef.namespace}/${reqRef.name}:`, error);
          results.push({
            namespace: reqRef.namespace,
            name: reqRef.name,
            success: false,
            error: error instanceof Error ? error.message : "unknown error"
          });
        }
      }
      res.json({ results });
    } catch (error) {
      console.error("error in bulk reject:", error);
      if (error instanceof errors.NotAllowedError) {
        res.status(403).json({ error: error.message });
      } else {
        res.status(500).json({ error: "failed to bulk reject api key requests" });
      }
    }
  });
  router.delete("/requests/:namespace/:name", async (req, res) => {
    try {
      const credentials = await httpAuth.credentials(req);
      const { userEntityRef } = await getUserIdentity(req, httpAuth, userInfo);
      const { namespace, name } = req.params;
      const request = await k8sClient$1.getCustomResource(
        "devportal.kuadrant.io",
        "v1alpha1",
        namespace,
        "apikeys",
        name
      );
      const requestUserId = request.spec?.requestedBy?.userId;
      const deleteAllDecision = await permissions$1.authorize(
        [{ permission: permissions.kuadrantApiKeyDeleteAllPermission }],
        { credentials }
      );
      const canDeleteAll = deleteAllDecision[0].result === pluginPermissionCommon.AuthorizeResult.ALLOW;
      if (!canDeleteAll) {
        const deleteOwnDecision = await permissions$1.authorize(
          [{ permission: permissions.kuadrantApiKeyDeleteOwnPermission }],
          { credentials }
        );
        if (deleteOwnDecision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
          throw new errors.NotAllowedError("unauthorised");
        }
        if (requestUserId !== userEntityRef) {
          throw new errors.NotAllowedError("you can only delete your own api key requests");
        }
      }
      await k8sClient$1.deleteCustomResource(
        "devportal.kuadrant.io",
        "v1alpha1",
        namespace,
        "apikeys",
        name
      );
      res.status(204).send();
    } catch (error) {
      console.error("error deleting api key request:", error);
      if (error instanceof errors.NotAllowedError) {
        res.status(403).json({ error: error.message });
      } else {
        res.status(500).json({ error: "failed to delete api key request" });
      }
    }
  });
  router.patch("/requests/:namespace/:name", async (req, res) => {
    const patchSchema = zod.z.object({
      spec: zod.z.object({
        useCase: zod.z.string().optional(),
        planTier: zod.z.string().optional()
      }).partial()
    });
    const parsed = patchSchema.safeParse(req.body);
    if (!parsed.success) {
      throw new errors.InputError("invalid patch: " + parsed.error.toString());
    }
    try {
      const credentials = await httpAuth.credentials(req);
      const { userEntityRef } = await getUserIdentity(req, httpAuth, userInfo);
      const { namespace, name } = req.params;
      const existing = await k8sClient$1.getCustomResource(
        "devportal.kuadrant.io",
        "v1alpha1",
        namespace,
        "apikeys",
        name
      );
      const requestUserId = existing.spec?.requestedBy?.userId;
      const currentPhase = existing.status?.phase || "Pending";
      if (currentPhase !== "Pending") {
        throw new errors.NotAllowedError("only pending requests can be edited");
      }
      const updateAllDecision = await permissions$1.authorize(
        [{ permission: permissions.kuadrantApiKeyUpdateAllPermission }],
        { credentials }
      );
      if (updateAllDecision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
        const updateOwnDecision = await permissions$1.authorize(
          [{ permission: permissions.kuadrantApiKeyUpdateOwnPermission }],
          { credentials }
        );
        if (updateOwnDecision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
          throw new errors.NotAllowedError("unauthorised");
        }
        if (requestUserId !== userEntityRef) {
          throw new errors.NotAllowedError("you can only update your own api key requests");
        }
      }
      const updated = await k8sClient$1.patchCustomResource(
        "devportal.kuadrant.io",
        "v1alpha1",
        namespace,
        "apikeys",
        name,
        parsed.data
      );
      res.json(updated);
    } catch (error) {
      console.error("error updating api key request:", error);
      if (error instanceof errors.NotAllowedError) {
        res.status(403).json({ error: error.message });
      } else if (error instanceof errors.InputError) {
        res.status(400).json({ error: error.message });
      } else {
        res.status(500).json({ error: "failed to update api key request" });
      }
    }
  });
  router.get("/apikeys/:namespace/:name", async (req, res) => {
    try {
      const credentials = await httpAuth.credentials(req);
      const { userEntityRef } = await getUserIdentity(req, httpAuth, userInfo);
      const { namespace, name } = req.params;
      const readAllDecision = await permissions$1.authorize(
        [{ permission: permissions.kuadrantApiKeyReadAllPermission }],
        { credentials }
      );
      const canReadAll = readAllDecision[0].result === pluginPermissionCommon.AuthorizeResult.ALLOW;
      if (!canReadAll) {
        const readOwnDecision = await permissions$1.authorize(
          [{ permission: permissions.kuadrantApiKeyReadOwnPermission }],
          { credentials }
        );
        if (readOwnDecision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
          throw new errors.NotAllowedError("unauthorised");
        }
      }
      const apiKey = await k8sClient$1.getCustomResource(
        "devportal.kuadrant.io",
        "v1alpha1",
        namespace,
        "apikeys",
        name
      );
      if (!apiKey) {
        res.status(404).json({ error: "API key not found" });
        return;
      }
      if (!canReadAll) {
        const ownerId = apiKey.spec?.requestedBy?.userId;
        if (ownerId !== userEntityRef) {
          throw new errors.NotAllowedError("not authorised to view this API key");
        }
      }
      res.status(200).json(apiKey);
    } catch (error) {
      console.error("failed to get api key:", error);
      if (error instanceof errors.NotAllowedError) {
        res.status(403).json({ error: error.message });
      } else {
        res.status(500).json({ error: "failed to get api key" });
      }
    }
  });
  router.get("/apikeys/:namespace/:name/secret", async (req, res) => {
    try {
      const credentials = await httpAuth.credentials(req);
      const { userEntityRef } = await getUserIdentity(req, httpAuth, userInfo);
      const { namespace, name } = req.params;
      const readAllDecision = await permissions$1.authorize(
        [{ permission: permissions.kuadrantApiKeyReadAllPermission }],
        { credentials }
      );
      const canReadAll = readAllDecision[0].result === pluginPermissionCommon.AuthorizeResult.ALLOW;
      if (!canReadAll) {
        const readOwnDecision = await permissions$1.authorize(
          [{ permission: permissions.kuadrantApiKeyReadOwnPermission }],
          { credentials }
        );
        if (readOwnDecision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
          throw new errors.NotAllowedError("unauthorised");
        }
      }
      const apiKey = await k8sClient$1.getCustomResource(
        "devportal.kuadrant.io",
        "v1alpha1",
        namespace,
        "apikeys",
        name
      );
      if (!canReadAll) {
        const requestUserId = apiKey.spec?.requestedBy?.userId;
        if (requestUserId !== userEntityRef) {
          throw new errors.NotAllowedError("you can only read your own api key secrets");
        }
      }
      if (apiKey.status?.canReadSecret !== true) {
        res.status(403).json({
          error: "secret has already been read and cannot be retrieved again"
        });
        return;
      }
      if (!apiKey.status?.secretRef?.name || !apiKey.status?.secretRef?.key) {
        res.status(404).json({
          error: "secret reference not found in apikey status"
        });
        return;
      }
      const secretName = apiKey.status.secretRef.name;
      let secret;
      try {
        secret = await k8sClient$1.getSecret(namespace, secretName);
      } catch (error) {
        console.error("error fetching secret:", error);
        res.status(404).json({
          error: "secret not found"
        });
        return;
      }
      const secretData = secret.data || {};
      const apiKeyValue = secretData[secretKey];
      if (!apiKeyValue) {
        res.status(404).json({
          error: `secret key '${secretKey}' not found in secret`
        });
        return;
      }
      const decodedApiKey = Buffer.from(apiKeyValue, "base64").toString("utf-8");
      await k8sClient$1.patchCustomResourceStatus(
        "devportal.kuadrant.io",
        "v1alpha1",
        namespace,
        "apikeys",
        name,
        {
          ...apiKey.status,
          canReadSecret: false
        }
      );
      res.json({
        apiKey: decodedApiKey
      });
    } catch (error) {
      console.error("error reading api key secret:", error);
      if (error instanceof errors.NotAllowedError) {
        res.status(403).json({ error: error.message });
      } else {
        res.status(500).json({ error: "failed to read api key secret" });
      }
    }
  });
  router.get("/authpolicies", async (req, res) => {
    try {
      const credentials = await httpAuth.credentials(req);
      const decision = await permissions$1.authorize(
        [{ permission: permissions.kuadrantAuthPolicyListPermission }],
        { credentials }
      );
      if (decision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
        throw new errors.NotAllowedError("unauthorised");
      }
      const data = await k8sClient$1.listCustomResources("kuadrant.io", "v1", "authpolicies");
      const filtered = {
        items: (data.items || []).map((policy) => ({
          metadata: {
            name: policy.metadata.name,
            namespace: policy.metadata.namespace
          },
          spec: policy.spec ? {
            // expose targetRef to allow UI to match AuthPolicy -> HTTPRoute
            targetRef: policy.spec.targetRef ? {
              kind: policy.spec.targetRef.kind,
              name: policy.spec.targetRef.name,
              namespace: policy.spec.targetRef.namespace
            } : void 0
          } : {},
          status: policy.status
        }))
      };
      res.json(filtered);
    } catch (error) {
      console.error("error fetching authpolicies:", error);
      if (error instanceof errors.NotAllowedError) {
        res.status(403).json({ error: error.message });
      } else {
        res.status(500).json({ error: "failed to fetch authpolicies" });
      }
    }
  });
  router.get("/ratelimitpolicies", async (req, res) => {
    try {
      const credentials = await httpAuth.credentials(req);
      const decision = await permissions$1.authorize(
        [{ permission: permissions.kuadrantRateLimitPolicyListPermission }],
        { credentials }
      );
      if (decision[0].result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
        throw new errors.NotAllowedError("unauthorised");
      }
      const data = await k8sClient$1.listCustomResources("kuadrant.io", "v1", "ratelimitpolicies");
      const filtered = {
        items: (data.items || []).map((policy) => ({
          metadata: {
            name: policy.metadata.name,
            namespace: policy.metadata.namespace
          },
          spec: policy.spec ? {
            // expose targetRef to allow UI to match AuthPolicy -> HTTPRoute
            targetRef: policy.spec.targetRef ? {
              kind: policy.spec.targetRef.kind,
              name: policy.spec.targetRef.name,
              namespace: policy.spec.targetRef.namespace
            } : void 0
          } : {},
          status: policy.status
        }))
      };
      res.json(filtered);
    } catch (error) {
      console.error("error fetching ratelimitpolicies:", error);
      if (error instanceof errors.NotAllowedError) {
        res.status(403).json({ error: error.message });
      } else {
        res.status(500).json({ error: "failed to fetch ratelimitpolicies" });
      }
    }
  });
  router.use(pluginPermissionNode.createPermissionIntegrationRouter({
    permissions: permissions.kuadrantPermissions
  }));
  return router;
}

exports.createRouter = createRouter;
//# sourceMappingURL=router.cjs.js.map
