Skip to content
API Documentation
BastionGuard™
RulesPage Class Reference

#include <RulesPage.hpp>

Inheritance diagram for RulesPage:

Classes

struct  Columns
struct  ComboColumns
struct  Rule

Public Member Functions

 RulesPage ()

Private Member Functions

bool replaceJsonStringField (const std::string &filepath, const std::string &key, const std::string &value)
bool replaceJsonBoolField (const std::string &filepath, const std::string &key, bool value)
bool writeFileAsRoot (const std::string &filepath, const std::string &content)
bool createRuleFileAsRoot (const Rule &rule)
std::string escapeJson (const std::string &input)
std::string makeSafeFilename (const std::string &input)
void onActionEdited (const Glib::ustring &path, const Glib::ustring &new_text)
void onDurationEdited (const Glib::ustring &path, const Glib::ustring &new_text)
void onDataEdited (const Glib::ustring &path, const Glib::ustring &new_text)
void onEnabledToggled (const Glib::ustring &path)
void buildComboModels ()
void buildToolbar ()
void buildTreeView ()
void loadRules ()
Rule parseRule (const std::string &filepath)
std::string jsonField (const std::string &jsonjson, const std::string &key)
void onCreateRule ()
void onDelete ()
void updateCount ()

Private Attributes

Columns m_columns
ComboColumns m_comboColumns
Glib::RefPtr< Gtk::ListStore > m_actionModel
Glib::RefPtr< Gtk::ListStore > m_durationModel
Glib::RefPtr< Gtk::ListStore > m_store
Gtk::TreeView m_treeView
Gtk::ScrolledWindow m_scroll
Gtk::Box m_toolbar { Gtk::Orientation::HORIZONTAL, 6 }
Gtk::Button m_createBtn
Gtk::Button m_reloadBtn
Gtk::Button m_deleteBtn
Gtk::Label m_countLabel

Detailed Description

Definition at line 11 of file RulesPage.hpp.

Constructor & Destructor Documentation

◆ RulesPage()

RulesPage::RulesPage ( )

Definition at line 30 of file RulesPage.cpp.

31 : Gtk::Box(Gtk::Orientation::VERTICAL, 0)
32{
36
37 m_scroll.set_child(m_treeView);
38 m_scroll.set_vexpand(true);
39
40 append(m_toolbar);
41 append(m_scroll);
42
43 loadRules();
44}
void loadRules()
Gtk::ScrolledWindow m_scroll
Definition RulesPage.hpp:52
void buildToolbar()
Definition RulesPage.cpp:71
void buildTreeView()
void buildComboModels()
Definition RulesPage.cpp:50
Gtk::Box m_toolbar
Definition RulesPage.hpp:53
Gtk::TreeView m_treeView
Definition RulesPage.hpp:51

References buildComboModels(), buildToolbar(), buildTreeView(), loadRules(), m_scroll, m_toolbar, and m_treeView.

Member Function Documentation

◆ buildComboModels()

void RulesPage::buildComboModels ( )
private

Definition at line 50 of file RulesPage.cpp.

51{
52 // ── Azione: allow | deny ────────────────────────────────────────────
53 m_actionModel = Gtk::ListStore::create(m_comboColumns);
54 for (const char* v : { "allow", "deny" }) {
55 auto row = *m_actionModel->append();
57 }
58
59 // ── Durata: once | always ───────────────────────────────────────────
60 m_durationModel = Gtk::ListStore::create(m_comboColumns);
61 for (const char* v : { "once", "always" }) {
62 auto row = *m_durationModel->append();
64 }
65}
Glib::RefPtr< Gtk::ListStore > m_actionModel
Definition RulesPage.hpp:47
Glib::RefPtr< Gtk::ListStore > m_durationModel
Definition RulesPage.hpp:48
ComboColumns m_comboColumns
Definition RulesPage.hpp:44
Gtk::TreeModelColumn< Glib::ustring > col_value
Definition RulesPage.hpp:40

References RulesPage::ComboColumns::col_value, m_actionModel, m_comboColumns, and m_durationModel.

Referenced by RulesPage().

◆ buildToolbar()

void RulesPage::buildToolbar ( )
private

Definition at line 71 of file RulesPage.cpp.

72{
73 m_toolbar.set_margin_top(8);
74 m_toolbar.set_margin_bottom(8);
75 m_toolbar.set_margin_start(8);
76 m_toolbar.set_margin_end(8);
77
78 m_createBtn.set_label(_("➕ Crea regola"));
79 m_createBtn.get_style_context()->add_class("suggested-action");
80 m_createBtn.signal_clicked().connect(
81 sigc::mem_fun(*this, &RulesPage::onCreateRule));
82 m_toolbar.append(m_createBtn);
83
84 m_reloadBtn.set_label(_("🔄 Ricarica"));
85 m_reloadBtn.signal_clicked().connect(
86 sigc::mem_fun(*this, &RulesPage::loadRules));
87 m_toolbar.append(m_reloadBtn);
88
89 m_deleteBtn.set_label(_("🗑 Elimina"));
90 m_deleteBtn.get_style_context()->add_class("destructive-action");
91 m_deleteBtn.signal_clicked().connect(
92 sigc::mem_fun(*this, &RulesPage::onDelete));
93 m_toolbar.append(m_deleteBtn);
94
95 auto spacer = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL);
96 spacer->set_hexpand(true);
97 m_toolbar.append(*spacer);
98
99 m_countLabel.set_markup("<small>0 regole</small>");
100 m_countLabel.set_halign(Gtk::Align::END);
101 m_toolbar.append(m_countLabel);
102}
#define _(s)
Gtk::Button m_deleteBtn
Definition RulesPage.hpp:56
void onDelete()
void onCreateRule()
Gtk::Label m_countLabel
Definition RulesPage.hpp:57
Gtk::Button m_createBtn
Definition RulesPage.hpp:54
Gtk::Button m_reloadBtn
Definition RulesPage.hpp:55

References _, loadRules(), m_countLabel, m_createBtn, m_deleteBtn, m_reloadBtn, m_toolbar, onCreateRule(), and onDelete().

Referenced by RulesPage().

◆ buildTreeView()

void RulesPage::buildTreeView ( )
private

Definition at line 108 of file RulesPage.cpp.

109{
110 m_store = Gtk::ListStore::create(m_columns);
111 m_treeView.set_model(m_store);
112 m_treeView.get_style_context()->add_class("bsc-treeview");
113 m_treeView.set_grid_lines(Gtk::TreeView::GridLines::HORIZONTAL);
114
115 // ── Colonna: Nome (read-only) ───────────────────────────────────────
116 m_treeView.append_column(_("Nome"), m_columns.col_name);
117
118 // ── Colonna: Azione — CellRendererCombo (allow | deny) ─────────────
119 {
120 auto* col = Gtk::make_managed<Gtk::TreeViewColumn>(_("Azione"));
121 auto* cell = Gtk::make_managed<Gtk::CellRendererCombo>();
122
123 cell->property_model() = m_actionModel;
124 cell->property_text_column() = 0; // colonna "col_value" nel modello combo
125 cell->property_editable() = true;
126 cell->property_has_entry() = false; // solo valori dalla lista
127
128 cell->signal_edited().connect(
129 sigc::mem_fun(*this, &RulesPage::onActionEdited));
130
131 col->pack_start(*cell, true);
132 col->add_attribute(cell->property_text(), m_columns.col_action);
133 m_treeView.append_column(*col);
134 }
135
136 // ── Colonna: Durata — CellRendererCombo (once | always) ────────────
137 {
138 auto* col = Gtk::make_managed<Gtk::TreeViewColumn>(_("Durata"));
139 auto* cell = Gtk::make_managed<Gtk::CellRendererCombo>();
140
141 cell->property_model() = m_durationModel;
142 cell->property_text_column() = 0;
143 cell->property_editable() = true;
144 cell->property_has_entry() = false;
145
146 cell->signal_edited().connect(
147 sigc::mem_fun(*this, &RulesPage::onDurationEdited));
148
149 col->pack_start(*cell, true);
150 col->add_attribute(cell->property_text(), m_columns.col_duration);
151 m_treeView.append_column(*col);
152 }
153
154 // ── Colonna: Operando (read-only) ───────────────────────────────────
155 m_treeView.append_column(_("Operando"), m_columns.col_operand);
156
157 // ── Colonna: Valore (testo libero editable) ─────────────────────────
158 {
159 auto* col = Gtk::make_managed<Gtk::TreeViewColumn>(_("Valore"));
160 auto* cell = Gtk::make_managed<Gtk::CellRendererText>();
161 cell->property_editable() = true;
162 cell->signal_edited().connect(
163 sigc::mem_fun(*this, &RulesPage::onDataEdited));
164 col->pack_start(*cell, true);
165 col->add_attribute(cell->property_text(), m_columns.col_data);
166 m_treeView.append_column(*col);
167 }
168
169 // ── Colonna: Attiva (toggle) ────────────────────────────────────────
170 {
171 auto* col = Gtk::make_managed<Gtk::TreeViewColumn>(_("Attiva"));
172 auto* cell = Gtk::make_managed<Gtk::CellRendererToggle>();
173 cell->property_activatable() = true;
174 cell->signal_toggled().connect(
175 sigc::mem_fun(*this, &RulesPage::onEnabledToggled));
176 col->pack_start(*cell, false);
177 col->add_attribute(cell->property_active(), m_columns.col_enabled);
178 m_treeView.append_column(*col);
179 }
180
181 // ── Larghezze minime e ridimensionamento ────────────────────────────
182 const int minWidths[] = { 220, 90, 100, 130, 240, 80 };
183 for (int i = 0; i < 6; ++i) {
184 if (auto* c = m_treeView.get_column(i)) {
185 c->set_min_width(minWidths[i]);
186 c->set_resizable(true);
187 }
188 }
189}
void onDataEdited(const Glib::ustring &path, const Glib::ustring &new_text)
Glib::RefPtr< Gtk::ListStore > m_store
Definition RulesPage.hpp:50
void onActionEdited(const Glib::ustring &path, const Glib::ustring &new_text)
void onDurationEdited(const Glib::ustring &path, const Glib::ustring &new_text)
void onEnabledToggled(const Glib::ustring &path)
Columns m_columns
Definition RulesPage.hpp:43
Gtk::TreeModelColumn< Glib::ustring > col_data
Definition RulesPage.hpp:32
Gtk::TreeModelColumn< Glib::ustring > col_action
Definition RulesPage.hpp:29
Gtk::TreeModelColumn< Glib::ustring > col_operand
Definition RulesPage.hpp:31
Gtk::TreeModelColumn< Glib::ustring > col_duration
Definition RulesPage.hpp:30
Gtk::TreeModelColumn< bool > col_enabled
Definition RulesPage.hpp:33
Gtk::TreeModelColumn< Glib::ustring > col_name
Definition RulesPage.hpp:28

References _, RulesPage::Columns::col_action, RulesPage::Columns::col_data, RulesPage::Columns::col_duration, RulesPage::Columns::col_enabled, RulesPage::Columns::col_name, RulesPage::Columns::col_operand, m_actionModel, m_columns, m_durationModel, m_store, m_treeView, onActionEdited(), onDataEdited(), onDurationEdited(), and onEnabledToggled().

Referenced by RulesPage().

◆ createRuleFileAsRoot()

bool RulesPage::createRuleFileAsRoot ( const Rule & rule)
private

Definition at line 354 of file RulesPage.cpp.

355{
356 std::error_code ec;
357 std::filesystem::create_directories(RULES_DIR, ec);
358
359 std::string filename = makeSafeFilename(rule.name);
360 if (filename.empty())
361 filename = "rule";
362
363 std::string filepath = std::string(RULES_DIR) + filename + ".json";
364 int suffix = 1;
365 while (std::filesystem::exists(filepath)) {
366 filepath = std::string(RULES_DIR) + filename + "-" + std::to_string(suffix++) + ".json";
367 }
368
369 const std::string json =
370 "{\n"
371 " \"name\": \"" + escapeJson(rule.name) + "\",\n"
372 " \"action\": \"" + escapeJson(rule.action) + "\",\n"
373 " \"duration\": \"" + escapeJson(rule.duration) + "\",\n"
374 " \"operand\": \"" + escapeJson(rule.operand) + "\",\n"
375 " \"data\": \"" + escapeJson(rule.data) + "\",\n"
376 " \"enabled\": " + std::string(rule.enabled ? "true" : "false") + "\n"
377 "}\n";
378
379 return writeFileAsRoot(filepath, json);
380}
nlohmann::json json
Definition Backend.cpp:2908
static const char * RULES_DIR
Definition RulesPage.cpp:28
bool writeFileAsRoot(const std::string &filepath, const std::string &content)
std::string escapeJson(const std::string &input)
std::string makeSafeFilename(const std::string &input)

References RulesPage::Rule::action, RulesPage::Rule::data, RulesPage::Rule::duration, RulesPage::Rule::enabled, escapeJson(), makeSafeFilename(), RulesPage::Rule::name, RulesPage::Rule::operand, RULES_DIR, and writeFileAsRoot().

Referenced by onCreateRule().

◆ escapeJson()

std::string RulesPage::escapeJson ( const std::string & input)
private

Definition at line 403 of file RulesPage.cpp.

404{
405 std::string out;
406 out.reserve(input.size());
407 for (char c : input) {
408 switch (c) {
409 case '\\': out += "\\\\"; break;
410 case '"': out += "\\\""; break;
411 case '\n': out += "\\n"; break;
412 case '\r': out += "\\r"; break;
413 case '\t': out += "\\t"; break;
414 default: out += c; break;
415 }
416 }
417 return out;
418}

Referenced by createRuleFileAsRoot(), and replaceJsonStringField().

◆ jsonField()

std::string RulesPage::jsonField ( const std::string & json,
const std::string & key )
private

Definition at line 255 of file RulesPage.cpp.

256{
257 std::smatch m;
258
259 {
260 std::regex re("\"" + key + "\"\\s*:\\s*\"([^\"]+)\"");
261 if (std::regex_search(json, m, re))
262 return m[1].str();
263 }
264 {
265 std::regex re_bool("\"" + key + "\"\\s*:\\s*(true|false)");
266 if (std::regex_search(json, m, re_bool))
267 return m[1].str();
268 }
269 {
270 std::regex re_num("\"" + key + "\"\\s*:\\s*([0-9]+)");
271 if (std::regex_search(json, m, re_num))
272 return m[1].str();
273 }
274
275 return "";
276}

Referenced by parseRule().

◆ loadRules()

void RulesPage::loadRules ( )
private

Definition at line 195 of file RulesPage.cpp.

196{
197 m_store->clear();
198
199 if (!std::filesystem::exists(RULES_DIR)) {
200 std::cerr << "[RulesPage] Dir non trovata: " << RULES_DIR << "\n";
201 updateCount();
202 return;
203 }
204
205 for (const auto& entry : std::filesystem::directory_iterator(RULES_DIR)) {
206 if (!entry.is_regular_file() || entry.path().extension() != ".json")
207 continue;
208
209 auto rule = parseRule(entry.path().string());
210 if (rule.name.empty())
211 continue;
212
213 auto row = *m_store->append();
214 row[m_columns.col_name] = rule.name;
215 row[m_columns.col_action] = rule.action;
216 row[m_columns.col_duration] = rule.duration;
217 row[m_columns.col_operand] = rule.operand;
218 row[m_columns.col_data] = rule.data;
219 row[m_columns.col_enabled] = rule.enabled;
220 row[m_columns.col_filepath] = rule.filepath;
221 }
222
223 updateCount();
224}
void updateCount()
Rule parseRule(const std::string &filepath)
Gtk::TreeModelColumn< Glib::ustring > col_filepath
Definition RulesPage.hpp:34

References RulesPage::Columns::col_action, RulesPage::Columns::col_data, RulesPage::Columns::col_duration, RulesPage::Columns::col_enabled, RulesPage::Columns::col_filepath, RulesPage::Columns::col_name, RulesPage::Columns::col_operand, m_columns, m_store, parseRule(), RULES_DIR, and updateCount().

Referenced by buildToolbar(), onCreateRule(), and RulesPage().

◆ makeSafeFilename()

std::string RulesPage::makeSafeFilename ( const std::string & input)
private

Definition at line 382 of file RulesPage.cpp.

383{
384 std::string out;
385 out.reserve(input.size());
386 for (unsigned char c : input) {
387 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
388 (c >= '0' && c <= '9')) {
389 out += static_cast<char>(c);
390 } else if (c == '-' || c == '_') {
391 out += static_cast<char>(c);
392 } else if (!out.empty() && out.back() != '-') {
393 out += '-';
394 }
395 }
396
397 while (!out.empty() && out.back() == '-')
398 out.pop_back();
399
400 return out;
401}

Referenced by createRuleFileAsRoot().

◆ onActionEdited()

void RulesPage::onActionEdited ( const Glib::ustring & path,
const Glib::ustring & new_text )
private

Definition at line 424 of file RulesPage.cpp.

426{
427 auto it = m_store->get_iter(path);
428 if (!it) return;
429
430 // Sicurezza extra: il combo non dovrebbe permettere altri valori
431 const std::string value = Glib::ustring(new_text).lowercase();
432 if (value != "allow" && value != "deny") return;
433
434 const Glib::ustring filepath = (*it)[m_columns.col_filepath];
435 if (replaceJsonStringField(filepath, "action", value))
436 (*it)[m_columns.col_action] = value;
437}
bool replaceJsonStringField(const std::string &filepath, const std::string &key, const std::string &value)

References RulesPage::Columns::col_action, RulesPage::Columns::col_filepath, m_columns, m_store, and replaceJsonStringField().

Referenced by buildTreeView().

◆ onCreateRule()

void RulesPage::onCreateRule ( )
private

Definition at line 481 of file RulesPage.cpp.

482{
483 Gtk::Dialog dialog;
484 dialog.set_title("");
485 dialog.set_modal(true);
486 dialog.set_resizable(false);
487 dialog.set_default_size(540, -1);
488 dialog.get_style_context()->add_class("bsc-rule-dialog");
489
490 if (auto* root = dynamic_cast<Gtk::Window*>(get_root()))
491 dialog.set_transient_for(*root);
492
493 auto* header = Gtk::make_managed<Gtk::HeaderBar>();
494 header->set_show_title_buttons(false);
495 header->set_decoration_layout("");
496 header->get_style_context()->add_class("custom-headerbar");
497
498 auto* titleLabel = Gtk::make_managed<Gtk::Label>();
499 titleLabel->set_markup("<b>" + Glib::ustring(_("Nuova regola")) + "</b>");
500 titleLabel->get_style_context()->add_class("headerbar-title");
501 header->set_title_widget(*titleLabel);
502
503 auto* headerRight = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 4);
504 headerRight->get_style_context()->add_class("header-right");
505
506 auto* closeBtn = Gtk::make_managed<Gtk::Button>("✕");
507 closeBtn->get_style_context()->add_class("header-button");
508 closeBtn->signal_clicked().connect([&dialog]() {
509 dialog.response(Gtk::ResponseType::CANCEL);
510 });
511 headerRight->append(*closeBtn);
512
513 header->pack_end(*headerRight);
514 dialog.set_titlebar(*header);
515
516 dialog.add_button(_("Annulla"), Gtk::ResponseType::CANCEL);
517 dialog.add_button(_("Crea"), Gtk::ResponseType::OK);
518
519 if (auto* cancelBtn = dialog.get_widget_for_response(Gtk::ResponseType::CANCEL))
520 cancelBtn->get_style_context()->add_class("dialog-secondary");
521 if (auto* createBtn = dialog.get_widget_for_response(Gtk::ResponseType::OK))
522 createBtn->get_style_context()->add_class("suggested-action");
523
524 auto* area = dialog.get_content_area();
525 area->set_margin_top(16);
526 area->set_margin_bottom(16);
527 area->set_margin_start(16);
528 area->set_margin_end(16);
529 area->set_spacing(12);
530 area->get_style_context()->add_class("bsc-rule-dialog-body");
531
532 auto* intro = Gtk::make_managed<Gtk::Label>(_("Compila i campi per creare una nuova regola persistente."));
533 intro->set_wrap(true);
534 intro->set_halign(Gtk::Align::START);
535 intro->get_style_context()->add_class("dialog-intro");
536 area->append(*intro);
537
538 auto* card = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 0);
539 card->get_style_context()->add_class("card");
540 card->get_style_context()->add_class("rule-dialog-card");
541 area->append(*card);
542
543 auto* grid = Gtk::make_managed<Gtk::Grid>();
544 grid->set_row_spacing(10);
545 grid->set_column_spacing(12);
546 grid->set_margin_top(14);
547 grid->set_margin_bottom(14);
548 grid->set_margin_start(14);
549 grid->set_margin_end(14);
550 grid->set_column_homogeneous(false);
551 card->append(*grid);
552
553 auto attach_row = [grid](int row, const Glib::ustring& label, Gtk::Widget& widget) {
554 auto* lbl = Gtk::make_managed<Gtk::Label>(label);
555 lbl->set_halign(Gtk::Align::START);
556 lbl->set_valign(Gtk::Align::CENTER);
557 lbl->get_style_context()->add_class("dialog-label");
558 grid->attach(*lbl, 0, row, 1, 1);
559
560 widget.set_hexpand(true);
561 widget.set_halign(Gtk::Align::FILL);
562 widget.get_style_context()->add_class("dialog-field");
563 grid->attach(widget, 1, row, 1, 1);
564 };
565
566 auto* nameEntry = Gtk::make_managed<Gtk::Entry>();
567 nameEntry->set_text(_("Nuova regola"));
568 attach_row(0, _("Nome"), *nameEntry);
569
570 auto* actionCombo = Gtk::make_managed<Gtk::ComboBoxText>();
571 actionCombo->append("allow", "allow");
572 actionCombo->append("deny", "deny");
573 actionCombo->set_active_id("deny");
574 attach_row(1, _("Azione"), *actionCombo);
575
576 auto* durationCombo = Gtk::make_managed<Gtk::ComboBoxText>();
577 durationCombo->append("once", "once");
578 durationCombo->append("always", "always");
579 durationCombo->set_active_id("always");
580 attach_row(2, _("Durata"), *durationCombo);
581
582 auto* operandCombo = Gtk::make_managed<Gtk::ComboBoxText>();
583 operandCombo->append("host", "host");
584 operandCombo->append("ip", "ip");
585 operandCombo->append("app", "app");
586 operandCombo->append("port", "port");
587 operandCombo->set_active_id("host");
588 attach_row(3, _("Operando"), *operandCombo);
589
590 auto* valueEntry = Gtk::make_managed<Gtk::Entry>();
591 valueEntry->set_text("example.com");
592 attach_row(4, _("Valore"), *valueEntry);
593
594 auto* enabledCheck = Gtk::make_managed<Gtk::CheckButton>(_("Regola attiva"));
595 enabledCheck->set_active(true);
596 enabledCheck->set_halign(Gtk::Align::START);
597 enabledCheck->get_style_context()->add_class("dialog-check");
598 grid->attach(*enabledCheck, 1, 5, 1, 1);
599
600 std::shared_ptr<Glib::MainLoop> loop = Glib::MainLoop::create(false);
601 int response = Gtk::ResponseType::CANCEL;
602
603 dialog.signal_response().connect([&](int id) {
604 response = id;
605 dialog.hide();
606 if (loop->is_running())
607 loop->quit();
608 });
609
610 dialog.present();
611 loop->run();
612
613 if (response != Gtk::ResponseType::OK)
614 return;
615
616 Rule rule;
617 rule.name = nameEntry->get_text();
618 rule.action = actionCombo->get_active_id();
619 rule.duration = durationCombo->get_active_id();
620 rule.operand = operandCombo->get_active_id();
621 rule.data = valueEntry->get_text();
622 rule.enabled = enabledCheck->get_active();
623
624 if (rule.name.empty() || rule.action.empty() || rule.duration.empty() ||
625 rule.operand.empty() || rule.data.empty()) {
626 std::cerr << "[RulesPage] Creazione regola annullata: campi mancanti\n";
627 return;
628 }
629
630 if (createRuleFileAsRoot(rule))
631 loadRules();
632 else
633 std::cerr << "[RulesPage] Impossibile creare la regola\n";
634}
bool createRuleFileAsRoot(const Rule &rule)
std::string name
Definition RulesPage.hpp:61

References _, RulesPage::Rule::action, createRuleFileAsRoot(), RulesPage::Rule::data, RulesPage::Rule::duration, RulesPage::Rule::enabled, loadRules(), RulesPage::Rule::name, and RulesPage::Rule::operand.

Referenced by buildToolbar().

◆ onDataEdited()

void RulesPage::onDataEdited ( const Glib::ustring & path,
const Glib::ustring & new_text )
private

Definition at line 453 of file RulesPage.cpp.

455{
456 auto it = m_store->get_iter(path);
457 if (!it) return;
458
459 const Glib::ustring filepath = (*it)[m_columns.col_filepath];
460 if (replaceJsonStringField(filepath, "data", new_text))
461 (*it)[m_columns.col_data] = new_text;
462}

References RulesPage::Columns::col_data, RulesPage::Columns::col_filepath, m_columns, m_store, and replaceJsonStringField().

Referenced by buildTreeView().

◆ onDelete()

void RulesPage::onDelete ( )
private

Definition at line 640 of file RulesPage.cpp.

641{
642 auto sel = m_treeView.get_selection();
643 auto it = sel->get_selected();
644 if (!it) return;
645
646 const Glib::ustring path = (*it)[m_columns.col_filepath];
647 if (path.empty()) return;
648
649 const std::string cmd = "pkexec rm -f \"" + std::string(path) + "\"";
650 if (std::system(cmd.c_str()) == 0) {
651 m_store->erase(it);
652 updateCount();
653 } else {
654 std::cerr << "[RulesPage] Impossibile eliminare: " << path << "\n";
655 }
656}

References RulesPage::Columns::col_filepath, m_columns, m_store, m_treeView, and updateCount().

Referenced by buildToolbar().

◆ onDurationEdited()

void RulesPage::onDurationEdited ( const Glib::ustring & path,
const Glib::ustring & new_text )
private

Definition at line 439 of file RulesPage.cpp.

441{
442 auto it = m_store->get_iter(path);
443 if (!it) return;
444
445 const std::string value = Glib::ustring(new_text).lowercase();
446 if (value != "once" && value != "always") return;
447
448 const Glib::ustring filepath = (*it)[m_columns.col_filepath];
449 if (replaceJsonStringField(filepath, "duration", value))
450 (*it)[m_columns.col_duration] = value;
451}

References RulesPage::Columns::col_duration, RulesPage::Columns::col_filepath, m_columns, m_store, and replaceJsonStringField().

Referenced by buildTreeView().

◆ onEnabledToggled()

void RulesPage::onEnabledToggled ( const Glib::ustring & path)
private

Definition at line 464 of file RulesPage.cpp.

465{
466 auto it = m_store->get_iter(path);
467 if (!it) return;
468
469 const bool current = (*it)[m_columns.col_enabled];
470 const bool next = !current;
471 const Glib::ustring filepath = (*it)[m_columns.col_filepath];
472
473 if (replaceJsonBoolField(filepath, "enabled", next))
474 (*it)[m_columns.col_enabled] = next;
475}
bool replaceJsonBoolField(const std::string &filepath, const std::string &key, bool value)

References RulesPage::Columns::col_enabled, RulesPage::Columns::col_filepath, m_columns, m_store, and replaceJsonBoolField().

Referenced by buildTreeView().

◆ parseRule()

RulesPage::Rule RulesPage::parseRule ( const std::string & filepath)
private

Definition at line 230 of file RulesPage.cpp.

231{
232 Rule r;
233 r.filepath = filepath;
234
235 std::ifstream f(filepath);
236 if (!f.is_open())
237 return r;
238
239 std::ostringstream ss;
240 ss << f.rdbuf();
241 const std::string json = ss.str();
242
243 r.name = jsonField(json, "name");
244 r.action = jsonField(json, "action");
245 r.duration = jsonField(json, "duration");
246 r.operand = jsonField(json, "operand");
247 r.data = jsonField(json, "data");
248
249 const std::string enabled = jsonField(json, "enabled");
250 r.enabled = (enabled != "false");
251
252 return r;
253}
std::string jsonField(const std::string &json, const std::string &key)

References jsonField().

Referenced by loadRules().

◆ replaceJsonBoolField()

bool RulesPage::replaceJsonBoolField ( const std::string & filepath,
const std::string & key,
bool value )
private

Definition at line 308 of file RulesPage.cpp.

311{
312 std::ifstream in(filepath);
313 if (!in.is_open())
314 return false;
315
316 std::ostringstream ss;
317 ss << in.rdbuf();
318 std::string json = ss.str();
319 in.close();
320
321 const std::regex re("\"" + key + "\"\\s*:\\s*(true|false)");
322 const std::string replacement = "\"" + key + "\": " +
323 std::string(value ? "true" : "false");
324
325 if (!std::regex_search(json, re))
326 return false;
327
328 json = std::regex_replace(json, re, replacement,
329 std::regex_constants::format_first_only);
330
331 return writeFileAsRoot(filepath, json);
332}

References writeFileAsRoot().

Referenced by onEnabledToggled().

◆ replaceJsonStringField()

bool RulesPage::replaceJsonStringField ( const std::string & filepath,
const std::string & key,
const std::string & value )
private

Definition at line 282 of file RulesPage.cpp.

285{
286 std::ifstream in(filepath);
287 if (!in.is_open())
288 return false;
289
290 std::ostringstream ss;
291 ss << in.rdbuf();
292 std::string json = ss.str();
293 in.close();
294
295 const std::string escaped = escapeJson(value);
296 const std::regex re("\"" + key + "\"\\s*:\\s*\"([^\"]*)\"");
297 const std::string replacement = "\"" + key + "\": \"" + escaped + "\"";
298
299 if (!std::regex_search(json, re))
300 return false;
301
302 json = std::regex_replace(json, re, replacement,
303 std::regex_constants::format_first_only);
304
305 return writeFileAsRoot(filepath, json);
306}

References escapeJson(), and writeFileAsRoot().

Referenced by onActionEdited(), onDataEdited(), and onDurationEdited().

◆ updateCount()

void RulesPage::updateCount ( )
private

Definition at line 658 of file RulesPage.cpp.

659{
660 const int n = static_cast<int>(m_store->children().size());
661 m_countLabel.set_markup(
662 "<small>" + std::to_string(n) +
663 (n == 1 ? " regola" : " regole") + "</small>");
664}

References m_countLabel, and m_store.

Referenced by loadRules(), and onDelete().

◆ writeFileAsRoot()

bool RulesPage::writeFileAsRoot ( const std::string & filepath,
const std::string & content )
private

Definition at line 334 of file RulesPage.cpp.

336{
337 const std::string tmpfile = "/tmp/bsc-rule-edit-" +
338 std::to_string(::getpid()) + ".json";
339 {
340 std::ofstream out(tmpfile, std::ios::trunc);
341 if (!out.is_open())
342 return false;
343 out << content;
344 }
345
346 const std::string cmd =
347 "pkexec sh -c 'install -m 0644 \"" + tmpfile + "\" \"" + filepath + "\"'";
348
349 const int ret = std::system(cmd.c_str());
350 std::filesystem::remove(tmpfile);
351 return ret == 0;
352}

Referenced by createRuleFileAsRoot(), replaceJsonBoolField(), and replaceJsonStringField().

Member Data Documentation

◆ m_actionModel

Glib::RefPtr<Gtk::ListStore> RulesPage::m_actionModel
private

Definition at line 47 of file RulesPage.hpp.

Referenced by buildComboModels(), and buildTreeView().

◆ m_columns

Columns RulesPage::m_columns
private

◆ m_comboColumns

ComboColumns RulesPage::m_comboColumns
private

Definition at line 44 of file RulesPage.hpp.

Referenced by buildComboModels().

◆ m_countLabel

Gtk::Label RulesPage::m_countLabel
private

Definition at line 57 of file RulesPage.hpp.

Referenced by buildToolbar(), and updateCount().

◆ m_createBtn

Gtk::Button RulesPage::m_createBtn
private

Definition at line 54 of file RulesPage.hpp.

Referenced by buildToolbar().

◆ m_deleteBtn

Gtk::Button RulesPage::m_deleteBtn
private

Definition at line 56 of file RulesPage.hpp.

Referenced by buildToolbar().

◆ m_durationModel

Glib::RefPtr<Gtk::ListStore> RulesPage::m_durationModel
private

Definition at line 48 of file RulesPage.hpp.

Referenced by buildComboModels(), and buildTreeView().

◆ m_reloadBtn

Gtk::Button RulesPage::m_reloadBtn
private

Definition at line 55 of file RulesPage.hpp.

Referenced by buildToolbar().

◆ m_scroll

Gtk::ScrolledWindow RulesPage::m_scroll
private

Definition at line 52 of file RulesPage.hpp.

Referenced by RulesPage().

◆ m_store

Glib::RefPtr<Gtk::ListStore> RulesPage::m_store
private

◆ m_toolbar

Gtk::Box RulesPage::m_toolbar { Gtk::Orientation::HORIZONTAL, 6 }
private

Definition at line 53 of file RulesPage.hpp.

Referenced by buildToolbar(), and RulesPage().

◆ m_treeView

Gtk::TreeView RulesPage::m_treeView
private

Definition at line 51 of file RulesPage.hpp.

Referenced by buildTreeView(), onDelete(), and RulesPage().


The documentation for this class was generated from the following files:
  • BastionGuard/thirdparty/bastionguard-secure-connection/ui/src/pages/RulesPage.hpp
  • BastionGuard/thirdparty/bastionguard-secure-connection/ui/src/pages/RulesPage.cpp