@cobaltcore-dev/aurora 1.2.0 → 2.0.0
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/client/DeleteFlavorModal-C2MqUgGR.mjs +801 -0
- package/dist/client/DeleteFlavorModal-C2MqUgGR.mjs.map +1 -0
- package/dist/client/{FiltersInput-CKI6zWnm.mjs → FiltersInput-Becwxo_J.mjs} +36 -33
- package/dist/client/FiltersInput-Becwxo_J.mjs.map +1 -0
- package/dist/client/FloatingIpActionModals-Cq10WljB.mjs +466 -0
- package/dist/client/FloatingIpActionModals-Cq10WljB.mjs.map +1 -0
- package/dist/client/ImageToastNotifications-BWfzOUMc.mjs +1135 -0
- package/dist/client/ImageToastNotifications-BWfzOUMc.mjs.map +1 -0
- package/dist/client/RouteIdLevelDefaultError-CSseJ1yG.mjs +26 -0
- package/dist/client/RouteIdLevelDefaultError-CSseJ1yG.mjs.map +1 -0
- package/dist/client/{TwoColumnDescriptionList-NvgvErua.mjs → TwoColumnDescriptionList-DKS42RKa.mjs} +9 -3
- package/dist/client/TwoColumnDescriptionList-DKS42RKa.mjs.map +1 -0
- package/dist/client/{_flavorId-a9Gu66R1.mjs → _flavorId-CaA4-Pnf.mjs} +4 -3
- package/dist/client/_flavorId-CaA4-Pnf.mjs.map +1 -0
- package/dist/client/_flavorId-DYv_StX22.mjs +276 -0
- package/dist/client/_flavorId-DYv_StX22.mjs.map +1 -0
- package/dist/client/_flavorId-YV3jCS5g.mjs +22 -0
- package/dist/client/_flavorId-YV3jCS5g.mjs.map +1 -0
- package/dist/client/{_floatingIpId-AZ11Ksmu.mjs → _floatingIpId-BeYElanB.mjs} +2 -2
- package/dist/client/_floatingIpId-BeYElanB.mjs.map +1 -0
- package/dist/client/_floatingIpId-Dpsc7GU4.mjs +196 -0
- package/dist/client/_floatingIpId-Dpsc7GU4.mjs.map +1 -0
- package/dist/client/_imageId-mfKp3JHn.mjs +558 -0
- package/dist/client/_imageId-mfKp3JHn.mjs.map +1 -0
- package/dist/client/_imageId-mpXUMCh_.mjs +22 -0
- package/dist/client/_imageId-mpXUMCh_.mjs.map +1 -0
- package/dist/client/{_imageId-D76BxvFY.mjs → _imageId-pBSS0YcC.mjs} +4 -3
- package/dist/client/_imageId-pBSS0YcC.mjs.map +1 -0
- package/dist/client/{_projectId-B3wmSala.mjs → _projectId-AjgJX6Gl.mjs} +2 -2
- package/dist/client/_projectId-AjgJX6Gl.mjs.map +1 -0
- package/dist/client/{_projectId-DPzv0CCp.mjs → _projectId-BnTBxKfp.mjs} +4 -4
- package/dist/client/_projectId-BnTBxKfp.mjs.map +1 -0
- package/dist/client/{_projectId-DfeVJy0G.mjs → _projectId-CVrdJ52s.mjs} +2 -2
- package/dist/client/_projectId-CVrdJ52s.mjs.map +1 -0
- package/dist/client/_projectId-DgciZslU.mjs +92 -0
- package/dist/client/_projectId-DgciZslU.mjs.map +1 -0
- package/dist/client/{_securityGroupId-D85mSigA.mjs → _securityGroupId-AO3wnH8g.mjs} +2 -2
- package/dist/client/_securityGroupId-AO3wnH8g.mjs.map +1 -0
- package/dist/client/{_securityGroupId-C5huJNfO.mjs → _securityGroupId-Bq0ZyG6z.mjs} +750 -741
- package/dist/client/_securityGroupId-Bq0ZyG6z.mjs.map +1 -0
- package/dist/client/_storageType-c-DAu8qr.mjs +858 -0
- package/dist/client/_storageType-c-DAu8qr.mjs.map +1 -0
- package/dist/client/components/{Error → Errors}/RouteError.d.ts +5 -0
- package/dist/client/components/Errors/RouteIdLevelDefaultError.d.ts +17 -0
- package/dist/client/components/Errors/ServiceLevelDefaultError.d.ts +9 -0
- package/dist/client/components/ListToolbar/SelectedFilters.d.ts +7 -2
- package/dist/client/components/ListToolbar/types.d.ts +6 -0
- package/dist/client/components/ListToolbar/valueLabels.d.ts +11 -0
- package/dist/client/flavors-Bgq3KZmx.mjs +659 -0
- package/dist/client/flavors-Bgq3KZmx.mjs.map +1 -0
- package/dist/client/{flavors-B0rbqffG.mjs → flavors-ZudiAiTU.mjs} +2 -2
- package/dist/client/{flavors-B0rbqffG.mjs.map → flavors-ZudiAiTU.mjs.map} +1 -1
- package/dist/client/floatingips-B1oLH8z6.mjs +551 -0
- package/dist/client/floatingips-B1oLH8z6.mjs.map +1 -0
- package/dist/client/floatingips-BeQEkVH8.mjs +14 -0
- package/dist/client/floatingips-BeQEkVH8.mjs.map +1 -0
- package/dist/client/floatingips-BtLg3yEQ.mjs +22 -0
- package/dist/client/floatingips-BtLg3yEQ.mjs.map +1 -0
- package/dist/client/floatingips-Cz9k80cc.mjs.map +1 -1
- package/dist/client/{images-BGQv9kKT.mjs → images-CnTW3bpy.mjs} +810 -770
- package/dist/client/images-CnTW3bpy.mjs.map +1 -0
- package/dist/client/{images-CPmMa4SQ.mjs → images-DZHDYDQu.mjs} +2 -2
- package/dist/client/{images-CPmMa4SQ.mjs.map → images-DZHDYDQu.mjs.map} +1 -1
- package/dist/client/index.js +412 -409
- package/dist/client/index.js.map +1 -1
- package/dist/client/{objects-BN-59Th0.mjs → objects-25xsh4Ia.mjs} +2 -2
- package/dist/client/objects-25xsh4Ia.mjs.map +1 -0
- package/dist/client/objects-KXY6dgwq.mjs +82 -0
- package/dist/client/objects-KXY6dgwq.mjs.map +1 -0
- package/dist/client/objects-QryuClU3.mjs +82 -0
- package/dist/client/objects-QryuClU3.mjs.map +1 -0
- package/dist/client/{objects-BE_u5yRt.mjs → objects-jYQBFzwg.mjs} +4671 -4702
- package/dist/client/objects-jYQBFzwg.mjs.map +1 -0
- package/dist/client/projects-yiK0HGSA.mjs.map +1 -1
- package/dist/client/securitygroups--0PS2wbM.mjs +580 -0
- package/dist/client/securitygroups--0PS2wbM.mjs.map +1 -0
- package/dist/client/{securitygroups-DEJQBcxm.mjs → securitygroups-BRndk7wh.mjs} +2 -2
- package/dist/client/{securitygroups-DEJQBcxm.mjs.map → securitygroups-BRndk7wh.mjs.map} +1 -1
- package/dist/client/securitygroups-CdN4yAAw.mjs +14 -0
- package/dist/client/securitygroups-CdN4yAAw.mjs.map +1 -0
- package/dist/client/securitygroups-Cs2Op-tu.mjs +22 -0
- package/dist/client/securitygroups-Cs2Op-tu.mjs.map +1 -0
- package/dist/client/securitygroups-CtKne8UQ.mjs.map +1 -1
- package/dist/client/trpcClient.d.ts +6 -1
- package/dist/client/useModalTracking-BYd37pXm.mjs +37 -0
- package/dist/client/useModalTracking-BYd37pXm.mjs.map +1 -0
- package/dist/client/useSecurityGroupPermissions--hK4aR8Y.mjs +294 -0
- package/dist/client/useSecurityGroupPermissions--hK4aR8Y.mjs.map +1 -0
- package/dist/server/index.d.ts +6 -1
- package/dist/server/index.js +96 -30
- package/package.json +4 -4
- package/dist/client/DeleteFlavorModal-V44QCJBd.mjs +0 -773
- package/dist/client/DeleteFlavorModal-V44QCJBd.mjs.map +0 -1
- package/dist/client/FiltersInput-CKI6zWnm.mjs.map +0 -1
- package/dist/client/FloatingIpActionModals-CwEC5GR-.mjs +0 -460
- package/dist/client/FloatingIpActionModals-CwEC5GR-.mjs.map +0 -1
- package/dist/client/ImageToastNotifications-m6c3tVPb.mjs +0 -1152
- package/dist/client/ImageToastNotifications-m6c3tVPb.mjs.map +0 -1
- package/dist/client/TwoColumnDescriptionList-NvgvErua.mjs.map +0 -1
- package/dist/client/_flavorId-9PcBBW52.mjs +0 -231
- package/dist/client/_flavorId-9PcBBW52.mjs.map +0 -1
- package/dist/client/_flavorId-a9Gu66R1.mjs.map +0 -1
- package/dist/client/_floatingIpId-AE9Fu8l6.mjs +0 -210
- package/dist/client/_floatingIpId-AE9Fu8l6.mjs.map +0 -1
- package/dist/client/_floatingIpId-AZ11Ksmu.mjs.map +0 -1
- package/dist/client/_imageId-BtAql2Kr.mjs +0 -570
- package/dist/client/_imageId-BtAql2Kr.mjs.map +0 -1
- package/dist/client/_imageId-D76BxvFY.mjs.map +0 -1
- package/dist/client/_projectId-7Nl1MQTJ.mjs +0 -99
- package/dist/client/_projectId-7Nl1MQTJ.mjs.map +0 -1
- package/dist/client/_projectId-B3wmSala.mjs.map +0 -1
- package/dist/client/_projectId-DPzv0CCp.mjs.map +0 -1
- package/dist/client/_projectId-DfeVJy0G.mjs.map +0 -1
- package/dist/client/_securityGroupId-C5huJNfO.mjs.map +0 -1
- package/dist/client/_securityGroupId-D85mSigA.mjs.map +0 -1
- package/dist/client/_storageType-Dy9uCVXr.mjs +0 -845
- package/dist/client/_storageType-Dy9uCVXr.mjs.map +0 -1
- package/dist/client/flavors-Rl20bxVU.mjs +0 -628
- package/dist/client/flavors-Rl20bxVU.mjs.map +0 -1
- package/dist/client/floatingips-xbO_mu4f.mjs +0 -576
- package/dist/client/floatingips-xbO_mu4f.mjs.map +0 -1
- package/dist/client/images-BGQv9kKT.mjs.map +0 -1
- package/dist/client/objects-BE_u5yRt.mjs.map +0 -1
- package/dist/client/objects-BN-59Th0.mjs.map +0 -1
- package/dist/client/objects-D9Luf9KB.mjs +0 -66
- package/dist/client/objects-D9Luf9KB.mjs.map +0 -1
- package/dist/client/securitygroups-BjhgLBHm.mjs +0 -620
- package/dist/client/securitygroups-BjhgLBHm.mjs.map +0 -1
- package/dist/client/useModalTracking-BcOKTYRN.mjs +0 -33
- package/dist/client/useModalTracking-BcOKTYRN.mjs.map +0 -1
- package/dist/client/useSecurityGroupPermissions-BOyLQLdC.mjs +0 -227
- package/dist/client/useSecurityGroupPermissions-BOyLQLdC.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSecurityGroupPermissions--hK4aR8Y.mjs","names":["getSecurityGroupDeletedToast","name","message","description","getSecurityGroupDeleteErrorToast","errorMessage","getSecurityGroupUpdatedToast","getSecurityGroupUpdateErrorToast","getSecurityGroupRuleCreatedToast","getSecurityGroupRuleCreateErrorToast","getSecurityGroupRuleDeletedToast","getSecurityGroupRuleDeleteErrorToast","getRBACPolicyAddedToast","targetTenant","getRBACPolicyAddErrorToast","getRBACPolicyDeletedToast","getRBACPolicyDeleteErrorToast","React","useState","useEffect","Modal","Form","FormRow","FormSection","TextInput","Button","ButtonRow","Spinner","ModalFooter","Textarea","Message","Status","EditSecurityGroupModal","securityGroup","open","onClose","onUpdate","isLoading","error","useLingui","properties","setProperties","name","description","errors","setErrors","handleInputChange","e","value","type","target","checked","prev","newErrors","validateForm","trim","t","Object","keys","length","handleSubmit","preventDefault","updateData","undefined","id","handleClose","onCancel","size","title","modalFooter","className","variant","onClick","disabled","data-testid","dismissible","status","label","onChange","required","errortext","placeholder","rows","z","useForm","useStore","React","Modal","Stack","Message","Form","FormSection","TextInput","useModalTracking","DeleteSecurityGroupDialog","isOpen","onClose","securityGroup","onDelete","isDeleting","error","useLingui","trackClose","markSubmitted","resetTracking","actionPrefix","formSchema","object","confirm","string","refine","value","message","t","form","defaultValues","validators","onSubmit","id","canDelete","store","state","isSubmitting","values","securityGroupName","name","handleClose","reset","open","onCancel","size","title","confirmButtonLabel","confirmButtonVariant","onConfirm","handleSubmit","cancelButtonLabel","disableConfirmButton","disableCancelButton","disableCloseButton","direction","gap","variant","p","className","e","preventDefault","Field","children","field","label","onChange","handleChange","target","placeholder","disabled","autoComplete","autoFocus","data-testid","required","trpcReact","useSecurityGroupPermissions","projectId","data","permissions","canView","canCreate","canUpdate","canDelete","canCreateRule","canDeleteRule","canManageAccess","canViewRBAC","isLoading","isError","network","canUser","useQuery","project_id","permission","enabled","Boolean","select","canCreateRBAC","canDeleteRBAC","staleTime","Infinity","gcTime"],"sources":["../../src/client/routes/_auth/projects/$projectId/network/securitygroups/-components/SecurityGroupToastNotifications.tsx","../../src/client/routes/_auth/projects/$projectId/network/securitygroups/-components/-modals/EditSecurityGroupModal.tsx","../../src/client/routes/_auth/projects/$projectId/network/securitygroups/-components/-modals/DeleteSecurityGroupDialog.tsx","../../src/client/routes/_auth/projects/$projectId/network/securitygroups/-hooks/useSecurityGroupPermissions.ts"],"sourcesContent":["import { ReactNode } from \"react\"\nimport { NotificationOptions } from \"@cloudoperators/juno-ui-components\"\nimport { Trans } from \"@lingui/react/macro\"\n\ntype ToastReturnType = { message: ReactNode } & NotificationOptions\n\n// ── Security Group operations ──────────────────────────────────────────────\n\nexport const getSecurityGroupDeletedToast = (name: string): ToastReturnType => ({\n message: <Trans>Security Group Deleted</Trans>,\n description: <Trans>Security group \"{name}\" was successfully deleted.</Trans>,\n})\n\nexport const getSecurityGroupDeleteErrorToast = (errorMessage: string): ToastReturnType => ({\n message: <Trans>Failed to Delete Security Group</Trans>,\n description: <Trans>Could not delete security group: {errorMessage}</Trans>,\n})\n\nexport const getSecurityGroupUpdatedToast = (name: string): ToastReturnType => ({\n message: <Trans>Security Group Updated</Trans>,\n description: <Trans>Security group \"{name}\" was successfully updated.</Trans>,\n})\n\nexport const getSecurityGroupUpdateErrorToast = (errorMessage: string): ToastReturnType => ({\n message: <Trans>Failed to Update Security Group</Trans>,\n description: <Trans>Could not update security group: {errorMessage}</Trans>,\n})\n\n// ── Rule operations ────────────────────────────────────────────────────────\n\nexport const getSecurityGroupRuleCreatedToast = (): ToastReturnType => ({\n message: <Trans>Rule Created</Trans>,\n description: <Trans>Security group rule was successfully created.</Trans>,\n})\n\nexport const getSecurityGroupRuleCreateErrorToast = (errorMessage: string): ToastReturnType => ({\n message: <Trans>Failed to Create Rule</Trans>,\n description: <Trans>Could not create security group rule: {errorMessage}</Trans>,\n})\n\nexport const getSecurityGroupRuleDeletedToast = (): ToastReturnType => ({\n message: <Trans>Rule Deleted</Trans>,\n description: <Trans>Security group rule was successfully deleted.</Trans>,\n})\n\nexport const getSecurityGroupRuleDeleteErrorToast = (errorMessage: string): ToastReturnType => ({\n message: <Trans>Failed to Delete Rule</Trans>,\n description: <Trans>Could not delete security group rule: {errorMessage}</Trans>,\n})\n\n// ── RBAC Policy operations ─────────────────────────────────────────────────\n\nexport const getRBACPolicyAddedToast = (targetTenant: string): ToastReturnType => ({\n message: <Trans>Security Group Shared</Trans>,\n description: <Trans>Security group was successfully shared with project \"{targetTenant}\".</Trans>,\n})\n\nexport const getRBACPolicyAddErrorToast = (errorMessage: string): ToastReturnType => ({\n message: <Trans>Failed to Share Security Group</Trans>,\n description: <Trans>Could not share security group: {errorMessage}</Trans>,\n})\n\nexport const getRBACPolicyDeletedToast = (targetTenant: string): ToastReturnType => ({\n message: <Trans>Access Revoked</Trans>,\n description: <Trans>Access for project \"{targetTenant}\" was successfully revoked.</Trans>,\n})\n\nexport const getRBACPolicyDeleteErrorToast = (errorMessage: string): ToastReturnType => ({\n message: <Trans>Failed to Revoke Access</Trans>,\n description: <Trans>Could not revoke access: {errorMessage}</Trans>,\n})\n","import React, { useState, useEffect } from \"react\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport {\n Modal,\n Form,\n FormRow,\n FormSection,\n TextInput,\n Button,\n ButtonRow,\n Spinner,\n ModalFooter,\n Textarea,\n Message,\n Status,\n} from \"@cloudoperators/juno-ui-components\"\nimport type { SecurityGroup } from \"@/server/Network/types/securityGroup\"\nimport { UpdateSecurityGroupInput } from \"@/server/Network/types/securityGroup\"\n\ninterface EditSecurityGroupModalProps {\n securityGroup: SecurityGroup\n open: boolean\n onClose: () => void\n onUpdate?: (\n securityGroupId: string,\n data: Omit<UpdateSecurityGroupInput, \"securityGroupId\" | \"project_id\">\n ) => Promise<void>\n isLoading?: boolean\n error?: string | null\n}\n\ninterface SecurityGroupProperties {\n name: string\n description: string\n}\n\nexport const EditSecurityGroupModal: React.FC<EditSecurityGroupModalProps> = ({\n securityGroup,\n open,\n onClose,\n onUpdate,\n isLoading = false,\n error = null,\n}) => {\n const { t } = useLingui()\n\n const [properties, setProperties] = useState<SecurityGroupProperties>({\n name: securityGroup.name || \"\",\n description: securityGroup.description || \"\",\n })\n const [errors, setErrors] = useState<{ [key: string]: string }>({})\n\n // Update properties when securityGroup changes\n useEffect(() => {\n setProperties({\n name: securityGroup.name || \"\",\n description: securityGroup.description || \"\",\n })\n }, [securityGroup])\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {\n const { name, value, type } = e.target\n const checked = (e.target as HTMLInputElement).checked\n\n setProperties((prev) => ({\n ...prev,\n [name]: type === \"checkbox\" ? checked : value,\n }))\n\n if (errors[name]) {\n setErrors((prev) => {\n const newErrors = { ...prev }\n delete newErrors[name]\n return newErrors\n })\n }\n }\n\n const validateForm = (): boolean => {\n const newErrors: { [key: string]: string } = {}\n\n if (!properties.name || properties.name.trim() === \"\") {\n newErrors.name = t`Security group name is required`\n }\n\n setErrors(newErrors)\n return Object.keys(newErrors).length === 0\n }\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault()\n\n if (!validateForm()) {\n return\n }\n\n if (onUpdate) {\n // Prepare base update data without stateful\n const updateData: Omit<UpdateSecurityGroupInput, \"securityGroupId\" | \"project_id\"> = {\n name: properties.name.trim(),\n description: properties.description.trim() || undefined,\n }\n\n // Note: We deliberately do NOT include 'stateful' field here\n // because it requires special 'update_security_group:stateful' permission\n // which needs cloud admin role. Regular users can only update name/description.\n\n await onUpdate(securityGroup.id, updateData)\n }\n }\n\n const handleClose = () => {\n setErrors({})\n onClose()\n }\n\n return (\n <Modal\n open={open}\n onCancel={handleClose}\n size=\"large\"\n title={t`Edit Security Group`}\n modalFooter={\n <ModalFooter className=\"flex justify-end\">\n <ButtonRow>\n <Button variant=\"default\" onClick={handleClose} disabled={isLoading}>\n <Trans>Cancel</Trans>\n </Button>\n <Button\n variant=\"primary\"\n onClick={(e) => {\n handleSubmit(e)\n }}\n disabled={isLoading}\n data-testid=\"update-security-group-button\"\n >\n {isLoading ? <Spinner size=\"small\" /> : <Trans>Update Security Group</Trans>}\n </Button>\n </ButtonRow>\n </ModalFooter>\n }\n >\n {/* Error Message */}\n {error && (\n <Message dismissible={false} variant=\"error\" className=\"mb-4\">\n {error}\n </Message>\n )}\n\n {isLoading && <Status status=\"progress\" title={t`Updating Security Group...`} className=\"mt-0\" />}\n\n {!isLoading && (\n <Form className=\"mb-6\">\n <FormSection className=\"mb-6\">\n <FormRow className=\"mb-6\">\n <TextInput\n id=\"name\"\n name=\"name\"\n label={t`Name`}\n value={properties.name}\n onChange={handleInputChange}\n required\n errortext={errors.name}\n placeholder={t`Type name`}\n disabled={isLoading}\n />\n </FormRow>\n\n <FormRow className=\"mb-6\">\n <Textarea\n id=\"description\"\n name=\"description\"\n label={t`Description`}\n value={properties.description}\n onChange={handleInputChange}\n placeholder={t`Description`}\n disabled={isLoading}\n rows={3}\n />\n </FormRow>\n {/* Note: Stateful checkbox is not shown here because it requires 'update_security_group:stateful' permission (cloud admin only) */}\n </FormSection>\n </Form>\n )}\n </Modal>\n )\n}\n","import { z } from \"zod\"\nimport { useForm, useStore } from \"@tanstack/react-form\"\nimport React from \"react\"\nimport { Modal, Stack, Message, Form, FormSection, TextInput } from \"@cloudoperators/juno-ui-components\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport type { SecurityGroup } from \"@/server/Network/types/securityGroup\"\nimport { useModalTracking } from \"@/client/hooks/useModalTracking\"\n\ninterface DeleteSecurityGroupDialogProps {\n isOpen: boolean\n securityGroup: SecurityGroup\n onClose: () => void\n onDelete: (securityGroupId: string) => void\n isDeleting?: boolean\n error?: string | null\n}\n\nexport const DeleteSecurityGroupDialog: React.FC<DeleteSecurityGroupDialogProps> = ({\n isOpen,\n onClose,\n securityGroup,\n onDelete,\n isDeleting = false,\n error = null,\n}) => {\n const { t } = useLingui()\n\n const { trackClose, markSubmitted, resetTracking } = useModalTracking({\n isOpen,\n actionPrefix: \"network.securitygroup.delete\",\n })\n\n const formSchema = z.object({\n confirm: z.string().refine((value) => value === \"delete\", {\n message: t`Type \"delete\" to confirm`,\n }),\n })\n\n const form = useForm({\n defaultValues: {\n confirm: \"\",\n },\n validators: {\n onSubmit: formSchema,\n },\n onSubmit: async () => {\n if (isDeleting) return\n\n markSubmitted()\n onDelete(securityGroup.id)\n },\n })\n\n const canDelete = useStore(form.store, (state) => state.isSubmitting || state.values.confirm !== \"delete\")\n\n const securityGroupName = securityGroup.name || securityGroup.id\n\n const handleClose = () => {\n trackClose()\n form.reset()\n resetTracking()\n onClose()\n }\n\n return (\n <Modal\n open={isOpen}\n onCancel={handleClose}\n size=\"small\"\n title={t`Delete Security Group \"${securityGroupName}\"`}\n confirmButtonLabel={isDeleting ? t`Deleting...` : t`Delete Group`}\n confirmButtonVariant=\"primary-danger\"\n onConfirm={form.handleSubmit}\n cancelButtonLabel={t`Cancel`}\n disableConfirmButton={canDelete || isDeleting}\n disableCancelButton={isDeleting}\n disableCloseButton={isDeleting}\n >\n <Stack direction=\"vertical\" gap=\"4\">\n {error && <Message variant=\"error\">{error}</Message>}\n\n <p className=\"text-theme-default\">\n <Trans>This action cannot be undone. The security group will be permanently deleted.</Trans>\n </p>\n\n <Form\n className=\"mb-0\"\n id=\"delete-security-group-form\"\n onSubmit={(e) => {\n e.preventDefault()\n form.handleSubmit()\n }}\n >\n <FormSection>\n <form.Field\n name=\"confirm\"\n children={(field) => (\n <TextInput\n label={t`Type \"delete\" to confirm`}\n id={field.name}\n name={field.name}\n value={field.state.value}\n onChange={(e) => field.handleChange(e.target.value)}\n placeholder=\"delete\"\n disabled={isDeleting}\n autoComplete=\"off\"\n autoFocus\n data-testid=\"delete-confirmation-input\"\n required\n />\n )}\n />\n </FormSection>\n </Form>\n </Stack>\n </Modal>\n )\n}\n","import { trpcReact } from \"@/client/trpcClient\"\n\nexport interface SecurityGroupPermissions {\n canView: boolean\n canCreate: boolean\n canUpdate: boolean\n canDelete: boolean\n canCreateRule: boolean\n canDeleteRule: boolean\n canManageAccess: boolean\n canViewRBAC: boolean\n}\n\n/**\n * Hook to fetch security group permissions for the current user\n * Uses React Query with infinite cache since permissions don't change during session\n */\nexport function useSecurityGroupPermissions(projectId: string) {\n const {\n data: permissions = {\n canView: false,\n canCreate: false,\n canUpdate: false,\n canDelete: false,\n canCreateRule: false,\n canDeleteRule: false,\n canManageAccess: false,\n canViewRBAC: false,\n },\n isLoading,\n isError,\n } = trpcReact.network.canUser.useQuery(\n {\n project_id: projectId || \"\",\n permission: [\n \"network:security_groups:read\",\n \"network:security_groups:create\",\n \"network:security_groups:update\",\n \"network:security_groups:delete\",\n \"network:security_group_rules:create\",\n \"network:security_group_rules:delete\",\n \"network:rbac_policies:create\",\n \"network:rbac_policies:delete\",\n \"network:rbac_policies:read\",\n ],\n },\n {\n enabled: Boolean(projectId), // Only fetch if we have a project ID\n select: ([\n canView,\n canCreate,\n canUpdate,\n canDelete,\n canCreateRule,\n canDeleteRule,\n canCreateRBAC,\n canDeleteRBAC,\n canViewRBAC,\n ]) => ({\n canView,\n canCreate,\n canUpdate,\n canDelete,\n canCreateRule,\n canDeleteRule,\n canManageAccess: canCreateRBAC && canDeleteRBAC,\n canViewRBAC,\n }),\n staleTime: Infinity, // Permissions don't change during session\n gcTime: Infinity, // Keep in cache forever (previously cacheTime)\n }\n )\n\n return {\n permissions,\n isLoading,\n isError,\n }\n}\n"],"mappings":"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"}
|
package/dist/server/index.d.ts
CHANGED
|
@@ -965,6 +965,7 @@ declare const buildBaseRouter: (policyDir: string) => _trpc_server.TRPCBuiltRout
|
|
|
965
965
|
tags_any?: string | undefined;
|
|
966
966
|
not_tags?: string | undefined;
|
|
967
967
|
not_tags_any?: string | undefined;
|
|
968
|
+
stateful?: boolean | undefined;
|
|
968
969
|
searchTerm?: string | undefined;
|
|
969
970
|
};
|
|
970
971
|
output: {
|
|
@@ -1515,7 +1516,11 @@ declare const buildBaseRouter: (policyDir: string) => _trpc_server.TRPCBuiltRout
|
|
|
1515
1516
|
tempUrlKey?: string | undefined;
|
|
1516
1517
|
tempUrlKey2?: string | undefined;
|
|
1517
1518
|
};
|
|
1518
|
-
output:
|
|
1519
|
+
output: {
|
|
1520
|
+
created: true;
|
|
1521
|
+
optionsApplied: boolean;
|
|
1522
|
+
optionsError?: string | undefined;
|
|
1523
|
+
};
|
|
1519
1524
|
meta: object;
|
|
1520
1525
|
}>;
|
|
1521
1526
|
getContainerMetadata: _trpc_server.TRPCQueryProcedure<{
|
package/dist/server/index.js
CHANGED
|
@@ -7,7 +7,11 @@ var __getProtoOf = Object.getPrototypeOf;
|
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
8
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
9
9
|
var __commonJS = (cb, mod) => function __require() {
|
|
10
|
-
|
|
10
|
+
try {
|
|
11
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
12
|
+
} catch (e) {
|
|
13
|
+
throw mod = 0, e;
|
|
14
|
+
}
|
|
11
15
|
};
|
|
12
16
|
var __export = (target, all) => {
|
|
13
17
|
for (var name in all)
|
|
@@ -27306,7 +27310,7 @@ var require_pathHelpers = __commonJS({
|
|
|
27306
27310
|
});
|
|
27307
27311
|
exports2.encodeOpenstackPathSegment = encodeOpenstackPathSegment2;
|
|
27308
27312
|
exports2.encodeOpenstackPath = encodeOpenstackPath;
|
|
27309
|
-
exports2.validateAndEncodeResourceId =
|
|
27313
|
+
exports2.validateAndEncodeResourceId = validateAndEncodeResourceId8;
|
|
27310
27314
|
var error_1 = require_error();
|
|
27311
27315
|
function encodeOpenstackPathSegment2(segment, label = "Path segment") {
|
|
27312
27316
|
if (!segment || typeof segment !== "string") {
|
|
@@ -27328,10 +27332,10 @@ var require_pathHelpers = __commonJS({
|
|
|
27328
27332
|
return segments.map((seg, idx) => encodeOpenstackPathSegment2(seg, `Path segment ${idx}`)).join("/");
|
|
27329
27333
|
}
|
|
27330
27334
|
__name(encodeOpenstackPath, "encodeOpenstackPath");
|
|
27331
|
-
function
|
|
27335
|
+
function validateAndEncodeResourceId8(id, resourceType = "Resource") {
|
|
27332
27336
|
return encodeOpenstackPathSegment2(id, `${resourceType} ID`);
|
|
27333
27337
|
}
|
|
27334
|
-
__name(
|
|
27338
|
+
__name(validateAndEncodeResourceId8, "validateAndEncodeResourceId");
|
|
27335
27339
|
}
|
|
27336
27340
|
});
|
|
27337
27341
|
|
|
@@ -32490,7 +32494,7 @@ function buildObjectMetadataHeaders(options) {
|
|
|
32490
32494
|
}
|
|
32491
32495
|
__name(buildObjectMetadataHeaders, "buildObjectMetadataHeaders");
|
|
32492
32496
|
function mapErrorResponseToTRPCError2(error, context) {
|
|
32493
|
-
const { operation, container, object, additionalInfo } = context;
|
|
32497
|
+
const { operation, container, object, additionalInfo, preconditionFailedMeansAlreadyExists } = context;
|
|
32494
32498
|
const baseMessage = `Failed to ${operation}`;
|
|
32495
32499
|
const containerInfo = container ? ` container: ${container}` : "";
|
|
32496
32500
|
const objectInfo = object ? `, object: ${object}` : "";
|
|
@@ -32521,6 +32525,14 @@ function mapErrorResponseToTRPCError2(error, context) {
|
|
|
32521
32525
|
code: "CONFLICT",
|
|
32522
32526
|
message: `Conflict - ${operation}${containerInfo}${objectInfo}${extraInfo}`
|
|
32523
32527
|
});
|
|
32528
|
+
case 412:
|
|
32529
|
+
return preconditionFailedMeansAlreadyExists ? new import_server10.TRPCError({
|
|
32530
|
+
code: "CONFLICT",
|
|
32531
|
+
message: `Conflict - ${operation}${containerInfo}${objectInfo} - already exists${extraInfo}`
|
|
32532
|
+
}) : new import_server10.TRPCError({
|
|
32533
|
+
code: "PRECONDITION_FAILED",
|
|
32534
|
+
message: `Precondition failed - ${operation}${containerInfo}${objectInfo}${extraInfo}`
|
|
32535
|
+
});
|
|
32524
32536
|
case 413:
|
|
32525
32537
|
return new import_server10.TRPCError({
|
|
32526
32538
|
code: "PAYLOAD_TOO_LARGE",
|
|
@@ -32814,6 +32826,11 @@ var createContainerInputSchema = baseContainerInputSchema.extend({
|
|
|
32814
32826
|
tempUrlKey: import_zod11.z.string().optional(),
|
|
32815
32827
|
tempUrlKey2: import_zod11.z.string().optional()
|
|
32816
32828
|
});
|
|
32829
|
+
var createContainerResultSchema = import_zod11.z.object({
|
|
32830
|
+
created: import_zod11.z.literal(true),
|
|
32831
|
+
optionsApplied: import_zod11.z.boolean(),
|
|
32832
|
+
optionsError: import_zod11.z.string().optional()
|
|
32833
|
+
});
|
|
32817
32834
|
var updateContainerMetadataInputSchema = baseContainerInputSchema.extend({
|
|
32818
32835
|
metadata: import_zod11.z.record(import_zod11.z.string(), import_zod11.z.string()).optional(),
|
|
32819
32836
|
removeMetadata: import_zod11.z.array(import_zod11.z.string()).optional(),
|
|
@@ -33151,21 +33168,54 @@ var swiftRouter = {
|
|
|
33151
33168
|
createContainer: projectScopedProcedure.input(projectScopedInputSchema.extend(createContainerInputSchema.shape)).mutation(async ({ input, ctx }) => {
|
|
33152
33169
|
return withErrorHandling2(async () => {
|
|
33153
33170
|
const { account, container, ...options } = input;
|
|
33171
|
+
const { storagePolicy, ...applyOptions } = options;
|
|
33154
33172
|
const openstackSession = ctx.openstack;
|
|
33155
33173
|
const swift = openstackSession?.service("swift");
|
|
33156
33174
|
validateSwiftService(swift);
|
|
33157
|
-
const headers = buildContainerMetadataHeaders(options);
|
|
33158
33175
|
const accountPath = account || "";
|
|
33159
33176
|
const url = accountPath ? `${accountPath}/${encodeURIComponent(container)}` : encodeURIComponent(container);
|
|
33160
|
-
|
|
33161
|
-
|
|
33177
|
+
const probeHeaders = buildContainerMetadataHeaders({
|
|
33178
|
+
storagePolicy
|
|
33179
|
+
});
|
|
33180
|
+
const response = await swift.put(url, void 0, {
|
|
33181
|
+
headers: probeHeaders
|
|
33162
33182
|
}).catch((error) => {
|
|
33163
33183
|
throw mapErrorResponseToTRPCError2(error, {
|
|
33164
33184
|
operation: "create container",
|
|
33165
33185
|
container
|
|
33166
33186
|
});
|
|
33167
33187
|
});
|
|
33168
|
-
|
|
33188
|
+
if (response.status === 202) {
|
|
33189
|
+
throw new import_server11.TRPCError({
|
|
33190
|
+
code: "CONFLICT",
|
|
33191
|
+
message: `Conflict - create container - container already exists: ${container}`
|
|
33192
|
+
});
|
|
33193
|
+
}
|
|
33194
|
+
const optionHeaders = buildContainerMetadataHeaders(applyOptions);
|
|
33195
|
+
if (Object.keys(optionHeaders).length === 0) {
|
|
33196
|
+
return {
|
|
33197
|
+
created: true,
|
|
33198
|
+
optionsApplied: true
|
|
33199
|
+
};
|
|
33200
|
+
}
|
|
33201
|
+
let optionsError;
|
|
33202
|
+
await swift.post(url, void 0, {
|
|
33203
|
+
headers: optionHeaders
|
|
33204
|
+
}).catch((error) => {
|
|
33205
|
+
optionsError = mapErrorResponseToTRPCError2(error, {
|
|
33206
|
+
operation: "apply container settings",
|
|
33207
|
+
container,
|
|
33208
|
+
additionalInfo: "container was created but its metadata/ACL/quota could not be applied"
|
|
33209
|
+
}).message;
|
|
33210
|
+
});
|
|
33211
|
+
return optionsError === void 0 ? {
|
|
33212
|
+
created: true,
|
|
33213
|
+
optionsApplied: true
|
|
33214
|
+
} : {
|
|
33215
|
+
created: true,
|
|
33216
|
+
optionsApplied: false,
|
|
33217
|
+
optionsError
|
|
33218
|
+
};
|
|
33169
33219
|
}, "create container");
|
|
33170
33220
|
}),
|
|
33171
33221
|
/**
|
|
@@ -33591,7 +33641,8 @@ var swiftRouter = {
|
|
|
33591
33641
|
const normalizedPath = normalizeFolderPath(folderPath);
|
|
33592
33642
|
const headers = {
|
|
33593
33643
|
"Content-Type": "application/directory",
|
|
33594
|
-
"Content-Length": "0"
|
|
33644
|
+
"Content-Length": "0",
|
|
33645
|
+
"If-None-Match": "*"
|
|
33595
33646
|
};
|
|
33596
33647
|
if (metadata) {
|
|
33597
33648
|
Object.entries(metadata).forEach(([key, value]) => {
|
|
@@ -33600,14 +33651,14 @@ var swiftRouter = {
|
|
|
33600
33651
|
}
|
|
33601
33652
|
const accountPath = account || "";
|
|
33602
33653
|
const url = accountPath ? `${accountPath}/${encodeURIComponent(container)}/${encodeURIComponent(normalizedPath)}` : `${encodeURIComponent(container)}/${encodeURIComponent(normalizedPath)}`;
|
|
33603
|
-
await swift.put(url, {
|
|
33604
|
-
headers
|
|
33605
|
-
body: new ArrayBuffer(0)
|
|
33654
|
+
await swift.put(url, new ArrayBuffer(0), {
|
|
33655
|
+
headers
|
|
33606
33656
|
}).catch((error) => {
|
|
33607
33657
|
throw mapErrorResponseToTRPCError2(error, {
|
|
33608
33658
|
operation: "create folder",
|
|
33609
33659
|
container,
|
|
33610
|
-
object: normalizedPath
|
|
33660
|
+
object: normalizedPath,
|
|
33661
|
+
preconditionFailedMeansAlreadyExists: true
|
|
33611
33662
|
});
|
|
33612
33663
|
});
|
|
33613
33664
|
return true;
|
|
@@ -34506,6 +34557,7 @@ var S3_ERROR_MAP = {
|
|
|
34506
34557
|
BucketAlreadyExists: "CONFLICT",
|
|
34507
34558
|
BucketAlreadyOwnedByYou: "CONFLICT",
|
|
34508
34559
|
BucketNotEmpty: "PRECONDITION_FAILED",
|
|
34560
|
+
PreconditionFailed: "CONFLICT",
|
|
34509
34561
|
InvalidBucketState: "BAD_REQUEST",
|
|
34510
34562
|
VersioningNotEnabled: "PRECONDITION_FAILED",
|
|
34511
34563
|
AccessDenied: "FORBIDDEN",
|
|
@@ -34530,7 +34582,7 @@ function mapS3ErrorToTRPCError(error, context) {
|
|
|
34530
34582
|
}
|
|
34531
34583
|
const s3Error = error;
|
|
34532
34584
|
const errorCode = s3Error.Code ?? s3Error.name ?? "";
|
|
34533
|
-
const trpcCode = S3_ERROR_MAP[errorCode] ?? "INTERNAL_SERVER_ERROR";
|
|
34585
|
+
const trpcCode = errorCode === "PreconditionFailed" && !context.preconditionFailedMeansAlreadyExists ? "PRECONDITION_FAILED" : S3_ERROR_MAP[errorCode] ?? "INTERNAL_SERVER_ERROR";
|
|
34534
34586
|
if (!S3_ERROR_MAP[errorCode] && errorCode) {
|
|
34535
34587
|
import_signal_openstack4.logger.warn("Unmapped S3 error code", {
|
|
34536
34588
|
errorCode,
|
|
@@ -34549,6 +34601,8 @@ function mapS3ErrorToTRPCError(error, context) {
|
|
|
34549
34601
|
parts.push("Invalid access key \u2014 your credentials may be expired or incorrect");
|
|
34550
34602
|
} else if (errorCode === "BucketNotEmpty") {
|
|
34551
34603
|
parts.push("The bucket is not empty. Some objects or versions may still exist. Use 'Empty Bucket' first to delete all contents.");
|
|
34604
|
+
} else if (errorCode === "PreconditionFailed") {
|
|
34605
|
+
parts.push(context.preconditionFailedMeansAlreadyExists ? "The object already exists" : "Precondition failed");
|
|
34552
34606
|
} else if (s3Error.message) {
|
|
34553
34607
|
parts.push(s3Error.message);
|
|
34554
34608
|
}
|
|
@@ -35869,8 +35923,10 @@ var objectRouter = {
|
|
|
35869
35923
|
* Create a folder (zero-byte object with key ending in "/").
|
|
35870
35924
|
*
|
|
35871
35925
|
* In S3, folders are virtual - they're just zero-byte objects with keys ending in "/".
|
|
35872
|
-
*
|
|
35926
|
+
* The write is conditional (IfNoneMatch: "*"), so creating a folder that
|
|
35927
|
+
* already exists throws CONFLICT instead of silently overwriting it.
|
|
35873
35928
|
*
|
|
35929
|
+
* @throws TRPCError CONFLICT - a folder (or object) with this key already exists
|
|
35874
35930
|
* @throws TRPCError NOT_FOUND - bucket does not exist
|
|
35875
35931
|
* @throws TRPCError FORBIDDEN - no credentials or access denied
|
|
35876
35932
|
*/
|
|
@@ -35883,14 +35939,16 @@ var objectRouter = {
|
|
|
35883
35939
|
Bucket: containerName,
|
|
35884
35940
|
Key: normalizedPath,
|
|
35885
35941
|
Body: Buffer.from(""),
|
|
35886
|
-
ContentLength: 0
|
|
35942
|
+
ContentLength: 0,
|
|
35943
|
+
IfNoneMatch: "*"
|
|
35887
35944
|
}));
|
|
35888
35945
|
return true;
|
|
35889
35946
|
} catch (error) {
|
|
35890
35947
|
throw mapS3ErrorToTRPCError(error, {
|
|
35891
35948
|
operation: "create folder",
|
|
35892
35949
|
bucket: containerName,
|
|
35893
|
-
key: normalizedPath
|
|
35950
|
+
key: normalizedPath,
|
|
35951
|
+
preconditionFailedMeansAlreadyExists: true
|
|
35894
35952
|
});
|
|
35895
35953
|
}
|
|
35896
35954
|
}),
|
|
@@ -38706,6 +38764,8 @@ var listSecurityGroupsInputSchema = projectScopedInputSchema.extend({
|
|
|
38706
38764
|
tags_any: import_zod23.z.string().optional(),
|
|
38707
38765
|
not_tags: import_zod23.z.string().optional(),
|
|
38708
38766
|
not_tags_any: import_zod23.z.string().optional(),
|
|
38767
|
+
// Filtered in the BFF layer, not forwarded to Neutron
|
|
38768
|
+
stateful: import_zod23.z.boolean().optional(),
|
|
38709
38769
|
// BFF-side search (filtered in BFF layer, not sent to OpenStack)
|
|
38710
38770
|
searchTerm: import_zod23.z.string().optional()
|
|
38711
38771
|
});
|
|
@@ -39048,6 +39108,10 @@ var deduplicateSecurityGroupsById = /* @__PURE__ */ __name((items) => {
|
|
|
39048
39108
|
}
|
|
39049
39109
|
return Array.from(seen.values());
|
|
39050
39110
|
}, "deduplicateSecurityGroupsById");
|
|
39111
|
+
var filterSecurityGroupsByStateful = /* @__PURE__ */ __name((items, stateful) => {
|
|
39112
|
+
if (stateful === void 0) return items;
|
|
39113
|
+
return items.filter((item) => (item.stateful ?? true) === stateful);
|
|
39114
|
+
}, "filterSecurityGroupsByStateful");
|
|
39051
39115
|
var sortSecurityGroups = /* @__PURE__ */ __name((items, sortKey, sortDir = "asc") => {
|
|
39052
39116
|
if (!sortKey) return items;
|
|
39053
39117
|
return [
|
|
@@ -39099,7 +39163,7 @@ __name(fetchSecurityGroupsWithParams, "fetchSecurityGroupsWithParams");
|
|
|
39099
39163
|
var securityGroupRouter = {
|
|
39100
39164
|
list: projectScopedProcedure.input(listSecurityGroupsInputSchema).query(async ({ input, ctx }) => {
|
|
39101
39165
|
return withErrorHandling3(async () => {
|
|
39102
|
-
const { searchTerm, project_id, shared, sort_key, sort_dir, ...queryInput } = input;
|
|
39166
|
+
const { searchTerm, project_id, shared, stateful, sort_key, sort_dir, ...queryInput } = input;
|
|
39103
39167
|
const network = getNetworkService(ctx);
|
|
39104
39168
|
if (shared !== void 0) {
|
|
39105
39169
|
const securityGroups = await fetchSecurityGroupsWithParams(network, {
|
|
@@ -39108,7 +39172,7 @@ var securityGroupRouter = {
|
|
|
39108
39172
|
sort_key,
|
|
39109
39173
|
sort_dir
|
|
39110
39174
|
});
|
|
39111
|
-
return filterBySearchParams(securityGroups, searchTerm, [
|
|
39175
|
+
return filterBySearchParams(filterSecurityGroupsByStateful(securityGroups, stateful), searchTerm, [
|
|
39112
39176
|
"name",
|
|
39113
39177
|
"description",
|
|
39114
39178
|
"id"
|
|
@@ -39129,6 +39193,7 @@ var securityGroupRouter = {
|
|
|
39129
39193
|
...ownGroups,
|
|
39130
39194
|
...sharedGroups
|
|
39131
39195
|
]);
|
|
39196
|
+
combined = filterSecurityGroupsByStateful(combined, stateful);
|
|
39132
39197
|
combined = filterBySearchParams(combined, searchTerm, [
|
|
39133
39198
|
"name",
|
|
39134
39199
|
"description",
|
|
@@ -39214,13 +39279,15 @@ var securityGroupRouter = {
|
|
|
39214
39279
|
};
|
|
39215
39280
|
|
|
39216
39281
|
// src/server/Network/routers/securityGroupRuleRouter.ts
|
|
39282
|
+
var import_signal_openstack9 = __toESM(require_esm());
|
|
39217
39283
|
var SECURITY_GROUP_RULES_BASE_URL = "v2.0/security-group-rules";
|
|
39218
39284
|
var securityGroupRuleRouter = {
|
|
39219
39285
|
delete: projectScopedProcedure.input(deleteSecurityGroupRuleInputSchema).mutation(async ({ input, ctx }) => {
|
|
39220
39286
|
return withErrorHandling3(async () => {
|
|
39221
39287
|
const { ruleId } = input;
|
|
39222
39288
|
const network = getNetworkService(ctx);
|
|
39223
|
-
const
|
|
39289
|
+
const encodedRuleId = (0, import_signal_openstack9.validateAndEncodeResourceId)(ruleId, "Security group rule");
|
|
39290
|
+
const response = await network.del(`${SECURITY_GROUP_RULES_BASE_URL}/${encodedRuleId}`);
|
|
39224
39291
|
if (!response?.ok) {
|
|
39225
39292
|
throw SecurityGroupRuleErrorHandlers.delete(response, ruleId);
|
|
39226
39293
|
}
|
|
@@ -39461,6 +39528,7 @@ function parseRBACPoliciesListResponse(data, operation) {
|
|
|
39461
39528
|
__name(parseRBACPoliciesListResponse, "parseRBACPoliciesListResponse");
|
|
39462
39529
|
|
|
39463
39530
|
// src/server/Network/routers/rbacPolicyRouter.ts
|
|
39531
|
+
var import_signal_openstack10 = __toESM(require_esm());
|
|
39464
39532
|
var RBAC_POLICIES_BASE_URL = "v2.0/rbac-policies";
|
|
39465
39533
|
var rbacPolicyRouter = {
|
|
39466
39534
|
list: projectScopedProcedure.input(listRBACPoliciesForSecurityGroupInputSchema).query(async ({ input, ctx }) => {
|
|
@@ -39509,7 +39577,8 @@ var rbacPolicyRouter = {
|
|
|
39509
39577
|
target_tenant: targetTenant
|
|
39510
39578
|
}
|
|
39511
39579
|
};
|
|
39512
|
-
const
|
|
39580
|
+
const encodedPolicyId = (0, import_signal_openstack10.validateAndEncodeResourceId)(policyId, "RBAC policy");
|
|
39581
|
+
const response = await network.put(`${RBAC_POLICIES_BASE_URL}/${encodedPolicyId}`, requestBody);
|
|
39513
39582
|
if (!response.ok) {
|
|
39514
39583
|
throw RBACPolicyErrorHandlers.update(response, policyId);
|
|
39515
39584
|
}
|
|
@@ -39521,7 +39590,8 @@ var rbacPolicyRouter = {
|
|
|
39521
39590
|
return withErrorHandling3(async () => {
|
|
39522
39591
|
const { policyId } = input;
|
|
39523
39592
|
const network = getNetworkService(ctx);
|
|
39524
|
-
const
|
|
39593
|
+
const encodedPolicyId = (0, import_signal_openstack10.validateAndEncodeResourceId)(policyId, "RBAC policy");
|
|
39594
|
+
const response = await network.del(`${RBAC_POLICIES_BASE_URL}/${encodedPolicyId}`);
|
|
39525
39595
|
if (!response.ok) {
|
|
39526
39596
|
throw RBACPolicyErrorHandlers.delete(response, policyId);
|
|
39527
39597
|
}
|
|
@@ -39686,10 +39756,6 @@ var NETWORK_MAPPINGS = {
|
|
|
39686
39756
|
engine: "network",
|
|
39687
39757
|
rule: "create_security_group_rule"
|
|
39688
39758
|
},
|
|
39689
|
-
"network:security_group_rules:update": {
|
|
39690
|
-
engine: "network",
|
|
39691
|
-
rule: "update_security_group_rule"
|
|
39692
|
-
},
|
|
39693
39759
|
"network:security_group_rules:delete": {
|
|
39694
39760
|
engine: "network",
|
|
39695
39761
|
rule: "delete_security_group_rule"
|
|
@@ -39766,7 +39832,7 @@ var buildAppRouter = /* @__PURE__ */ __name((policyDir, extraRouters = []) => {
|
|
|
39766
39832
|
}, "buildAppRouter");
|
|
39767
39833
|
|
|
39768
39834
|
// src/server/context.ts
|
|
39769
|
-
var
|
|
39835
|
+
var import_signal_openstack11 = __toESM(require_esm());
|
|
39770
39836
|
|
|
39771
39837
|
// src/server/sessionCookie.ts
|
|
39772
39838
|
var import_cookie = require("@fastify/cookie");
|
|
@@ -39854,7 +39920,7 @@ async function createContext(opts, config) {
|
|
|
39854
39920
|
writable: false
|
|
39855
39921
|
});
|
|
39856
39922
|
if (currentAuthToken) {
|
|
39857
|
-
openstackSession = await (0,
|
|
39923
|
+
openstackSession = await (0, import_signal_openstack11.SignalOpenstackSession)(normalizedEndpoint, {
|
|
39858
39924
|
auth: {
|
|
39859
39925
|
identity: {
|
|
39860
39926
|
methods: [
|
|
@@ -39917,7 +39983,7 @@ async function createContext(opts, config) {
|
|
|
39917
39983
|
}
|
|
39918
39984
|
}, "getUserInfo");
|
|
39919
39985
|
const createSession = /* @__PURE__ */ __name(async (params) => {
|
|
39920
|
-
openstackSession = await (0,
|
|
39986
|
+
openstackSession = await (0, import_signal_openstack11.SignalOpenstackSession)(normalizedEndpoint, {
|
|
39921
39987
|
auth: {
|
|
39922
39988
|
identity: {
|
|
39923
39989
|
methods: [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cobaltcore-dev/aurora",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Aurora OpenStack dashboard — server and client library",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -105,10 +105,10 @@
|
|
|
105
105
|
"vite-plugin-dts": "^5.0.3",
|
|
106
106
|
"vite-plugin-svgr": "^5.2.0",
|
|
107
107
|
"vite-tsconfig-paths": "^6.1.1",
|
|
108
|
-
"vitest": "^4.1.
|
|
108
|
+
"vitest": "^4.1.11",
|
|
109
109
|
"@cobaltcore-dev/aurora-config": "0.0.1",
|
|
110
|
-
"@cobaltcore-dev/
|
|
111
|
-
"@cobaltcore-dev/
|
|
110
|
+
"@cobaltcore-dev/signal-openstack": "1.0.1",
|
|
111
|
+
"@cobaltcore-dev/policy-engine": "2.0.0"
|
|
112
112
|
},
|
|
113
113
|
"scripts": {
|
|
114
114
|
"build": "pnpm build:server && pnpm build:client",
|