import { FormEvent, useMemo, useState } from "react"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { Plus, Shield } from "lucide-react"; import { api, Project, SecurityGroup, SecurityRule } from "../api/client"; import { DataTable } from "../components/DataTable"; import { buttonClass, Field, inputClass, selectClass } from "../components/FormControls"; import { Modal } from "../components/Modal"; import { PageHeader } from "../components/PageHeader"; export function SecurityGroups() { const queryClient = useQueryClient(); const projects = useQuery({ queryKey: ["projects"], queryFn: () => api("/projects") }); const groups = useQuery({ queryKey: ["security-groups"], queryFn: () => api("/security-groups") }); const [selectedGroupId, setSelectedGroupId] = useState(""); const selectedGroup = useMemo(() => selectedGroupId || groups.data?.[0]?.id || "", [groups.data, selectedGroupId]); const rules = useQuery({ queryKey: ["security-rules", selectedGroup], queryFn: () => api(`/security-groups/${selectedGroup}/rules`), enabled: Boolean(selectedGroup), }); const [groupForm, setGroupForm] = useState({ project_id: "", name: "Web Tier", description: "Application frontend workloads" }); const [ruleForm, setRuleForm] = useState({ direction: "ingress", action: "allow", protocol: "tcp", source: "any", destination: "sg:Web Tier", port: "443", priority: 1000, logging: true, description: "Allow HTTPS", }); const [groupOpen, setGroupOpen] = useState(false); const [ruleOpen, setRuleOpen] = useState(false); const createGroup = useMutation({ mutationFn: () => api("/security-groups", { method: "POST", body: JSON.stringify({ ...groupForm, project_id: groupForm.project_id || null }) }), onSuccess: () => { setGroupOpen(false); queryClient.invalidateQueries({ queryKey: ["security-groups"] }); }, }); const createRule = useMutation({ mutationFn: () => api("/security-rules", { method: "POST", body: JSON.stringify({ ...ruleForm, security_group_id: selectedGroup }) }), onSuccess: () => { setRuleOpen(false); queryClient.invalidateQueries({ queryKey: ["security-rules", selectedGroup] }); }, }); async function submitGroup(event: FormEvent) { event.preventDefault(); const group = await createGroup.mutateAsync(); setSelectedGroupId(group.id); } async function submitRule(event: FormEvent) { event.preventDefault(); await createRule.mutateAsync(); } return ( <>
setGroupOpen(false)}>
Add Group
setGroupForm({ ...groupForm, name: event.target.value })} /> setGroupForm({ ...groupForm, description: event.target.value })} />
setRuleOpen(false)}>
Add Rule
setRuleForm({ ...ruleForm, source: event.target.value })} /> setRuleForm({ ...ruleForm, destination: event.target.value })} />
setRuleForm({ ...ruleForm, protocol: event.target.value })} /> setRuleForm({ ...ruleForm, port: event.target.value })} />
[]} columns={[{ key: "name", label: "Group" }, { key: "description", label: "Description" }]} /> []} columns={[{ key: "priority", label: "Priority" }, { key: "direction", label: "Direction" }, { key: "action", label: "Action" }, { key: "protocol", label: "Protocol" }, { key: "port", label: "Port" }]} />
); }