Staged undo, built-ins window, machine warnings; raw and dynamic set fixes
- Undo is staged like any edit: in review mode the web UI's Undo, and hc history undo with -C or HOUSECARL_CHANGESET, add a revert operation that checks, when replayed, that nothing it touches changed since; applied, History links the entries. Imports and takeovers still can't be staged. - The rules page sums up a chain's built-ins in one line; a window lists them with what they do and their hits, and switches them. - Warnings about the machine (dashboard, hc status): nftables.service enabled (it loads /etc/nftables.conf at boot and flushes every table when stopped), and the imported table still in force beside Housecarl's. The docs say to disable nftables.service but not stop it. - A raw rule with other fields set is refused (raw_conflict) instead of silently ignoring them; the rule dialog's nftables section hides what it replaces, and the importer's raw rules carry only their text. - A dynamic set with configured entries is refused (set_dynamic_entries): they were silently ignored. The set dialog shows entries or the entry timeout, as fits. - The rule dialog's chain choices are just the chains' names. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d25e12995e
commit
9a165cf70b
26 files changed
+408
-58
No files matched your search
@@ -36,8 +36,8 @@ func changesetParam(r *http.Request) (int64, error) {
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// notStaged refuses a changeset on a change that can't be staged (undo,
|
||||
// import, takeover): it would otherwise be applied at once, unexpectedly.
|
||||
// notStaged refuses a changeset on a change that can't be staged (an
|
||||
// import, a takeover): it would otherwise be applied at once, unexpectedly.
|
||||
func notStaged(r *http.Request, what string) error {
|
||||
if id, err := changesetParam(r); err != nil || id == 0 {
|
||||
return err
|
||||
@@ -102,6 +102,11 @@ func (s *Server) stage(w http.ResponseWriter, r *http.Request, p *auth.Principal
|
||||
return nil
|
||||
}
|
||||
op.Summary = engine.Describe(changes)
|
||||
if op.Op == model.OpRevert {
|
||||
var h model.HistoryEntry
|
||||
json.Unmarshal(op.Data, &h)
|
||||
op.Summary = engine.UndoDescription(&h)
|
||||
}
|
||||
op.AddedAt = s.nowFn()
|
||||
for _, o := range cs.Ops {
|
||||
if o.Seq >= op.Seq {
|
||||
@@ -353,7 +358,17 @@ func (s *Server) applyChangeset(w http.ResponseWriter, r *http.Request, p *auth.
|
||||
if len(cs.Ops) == 0 {
|
||||
return badRequest("changeset %d has no changes to apply", id)
|
||||
}
|
||||
res, err := s.eng.Apply(r.Context(), p, cs.Description, engine.Options{Via: via(r, p)}, func(st *model.State, _ func() int64) error {
|
||||
opts := engine.Options{Via: via(r, p)}
|
||||
desc := cs.Description
|
||||
for _, o := range cs.Ops {
|
||||
if o.Op == model.OpRevert {
|
||||
opts.RevertOf = o.ID // History links the undo
|
||||
if desc == "" && len(cs.Ops) == 1 {
|
||||
desc = o.Summary
|
||||
}
|
||||
}
|
||||
}
|
||||
res, err := s.eng.Apply(r.Context(), p, desc, opts, func(st *model.State, _ func() int64) error {
|
||||
return replay(st, cs.Ops)
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
Reference in new issue
Block a user