|
15 | 15 | import type { FormEvent } from "react"; |
16 | 16 | import { useEffect, useMemo, useState } from "react"; |
17 | 17 | import { apiSend } from "@/lib/api"; |
| 18 | +import type { AddRuleInitialPreset, RuleType } from "@/lib/rulePresetTypes"; |
18 | 19 |
|
19 | 20 | interface AddRuleModalProps { |
20 | 21 | onClose: () => void; |
21 | 22 | onCreated: (id: string) => void; |
| 23 | + initialPreset?: AddRuleInitialPreset; |
22 | 24 | } |
23 | 25 |
|
24 | | -type RuleType = "bash" | "pkg-install" | "destructive" | "secret-read" | "net-egress-url" | "custom"; |
25 | | - |
26 | 26 | interface Preset { |
27 | 27 | label: string; |
28 | 28 | description: string; |
@@ -110,28 +110,50 @@ const TOOL_OPTIONS = [ |
110 | 110 | "Task", |
111 | 111 | ] as const; |
112 | 112 |
|
113 | | -export function AddRuleModal({ onClose, onCreated }: AddRuleModalProps) { |
114 | | - const [ruleType, setRuleType] = useState<RuleType>("destructive"); |
| 113 | +export function AddRuleModal({ onClose, onCreated, initialPreset }: AddRuleModalProps) { |
| 114 | + const initialRuleType = initialPreset?.ruleType ?? "destructive"; |
| 115 | + const initialBasePreset = PRESETS[initialRuleType]; |
| 116 | + const [ruleType, setRuleType] = useState<RuleType>(initialRuleType); |
115 | 117 | const preset = PRESETS[ruleType]; |
116 | 118 |
|
117 | | - const [id, setId] = useState(preset.idSuggestion); |
118 | | - const [tool, setTool] = useState(preset.tool); |
119 | | - const [commandRegexes, setCommandRegexes] = useState(""); |
120 | | - const [pathRegexes, setPathRegexes] = useState(""); |
121 | | - const [urlRegexes, setUrlRegexes] = useState(""); |
122 | | - const [action, setAction] = useState<"deny" | "allow">(preset.action); |
123 | | - const [mode, setMode] = useState<"inherit" | "monitor" | "enforce">("inherit"); |
| 119 | + const [id, setId] = useState(initialPreset?.id ?? initialBasePreset.idSuggestion); |
| 120 | + const [tool, setTool] = useState(initialPreset?.tool ?? initialBasePreset.tool); |
| 121 | + const [commandRegexes, setCommandRegexes] = useState(initialPreset?.commandRegexes ?? ""); |
| 122 | + const [pathRegexes, setPathRegexes] = useState(initialPreset?.pathRegexes ?? ""); |
| 123 | + const [urlRegexes, setUrlRegexes] = useState(initialPreset?.urlRegexes ?? ""); |
| 124 | + const [action, setAction] = useState<"deny" | "allow">(initialPreset?.action ?? initialBasePreset.action); |
| 125 | + const [mode, setMode] = useState<"inherit" | "monitor" | "enforce">(initialPreset?.mode ?? "inherit"); |
124 | 126 | const [submitting, setSubmitting] = useState(false); |
125 | 127 | const [error, setError] = useState<string | null>(null); |
126 | 128 |
|
127 | | - // Reset id / tool / action whenever the user picks a different preset |
128 | | - // so they always see a sane starting point for the rule type. |
| 129 | + // Re-apply caller-owned presets if the same modal instance is reused for |
| 130 | + // a different ledger event. |
129 | 131 | useEffect(() => { |
130 | | - setId(preset.idSuggestion); |
131 | | - setTool(preset.tool); |
132 | | - setAction(preset.action); |
| 132 | + if (!initialPreset) return; |
| 133 | + const nextRuleType = initialPreset.ruleType ?? "destructive"; |
| 134 | + const nextBasePreset = PRESETS[nextRuleType]; |
| 135 | + setRuleType(nextRuleType); |
| 136 | + setId(initialPreset.id ?? nextBasePreset.idSuggestion); |
| 137 | + setTool(initialPreset.tool ?? nextBasePreset.tool); |
| 138 | + setCommandRegexes(initialPreset.commandRegexes ?? ""); |
| 139 | + setPathRegexes(initialPreset.pathRegexes ?? ""); |
| 140 | + setUrlRegexes(initialPreset.urlRegexes ?? ""); |
| 141 | + setAction(initialPreset.action ?? nextBasePreset.action); |
| 142 | + setMode(initialPreset.mode ?? "inherit"); |
| 143 | + setError(null); |
| 144 | + }, [initialPreset]); |
| 145 | + |
| 146 | + const onRuleTypeChange = (nextRuleType: RuleType) => { |
| 147 | + const nextPreset = PRESETS[nextRuleType]; |
| 148 | + setRuleType(nextRuleType); |
| 149 | + setId(nextPreset.idSuggestion); |
| 150 | + setTool(nextPreset.tool); |
| 151 | + setCommandRegexes(""); |
| 152 | + setPathRegexes(""); |
| 153 | + setUrlRegexes(""); |
| 154 | + setAction(nextPreset.action); |
133 | 155 | setError(null); |
134 | | - }, [ruleType, preset]); |
| 156 | + }; |
135 | 157 |
|
136 | 158 | const showCommand = useMemo( |
137 | 159 | () => preset.fields.includes("command") || preset.fields.includes("all"), |
@@ -206,7 +228,7 @@ export function AddRuleModal({ onClose, onCreated }: AddRuleModalProps) { |
206 | 228 | <select |
207 | 229 | className="oal-input w-full" |
208 | 230 | value={ruleType} |
209 | | - onChange={(e) => setRuleType(e.target.value as RuleType)} |
| 231 | + onChange={(e) => onRuleTypeChange(e.target.value as RuleType)} |
210 | 232 | > |
211 | 233 | {(Object.keys(PRESETS) as RuleType[]).map((k) => ( |
212 | 234 | <option key={k} value={k}> |
|
0 commit comments