Skip to content
API Documentation
BastionGuard™
SettingsPage.cpp
Go to the documentation of this file.
1#include "SettingsPage.hpp"
2
3#include <glibmm/i18n.h>
4#include <glibmm/miscutils.h>
5#include <glibmm/markup.h>
6
7#include <cstdlib>
8
9#ifndef BSC_SERVICECTL_PATH
10#define BSC_SERVICECTL_PATH "/usr/libexec/bastionguard/bastionguard-service"
11#endif
12#include <filesystem>
13#include <fstream>
14
15namespace fs = std::filesystem;
16
17namespace {
18 constexpr const char* kServiceName = "bsc-daemon.service";
19 constexpr const char* kAutostartPath = "/etc/xdg/autostart/bastionguard-sc-autostart.desktop";
20 constexpr const char* kFallbackAutostartPath = "/etc/xdg/autostart/bastionguard-sc.desktop";
21 constexpr const char* kAutostartBackupPath = "/etc/xdg/autostart/bastionguard-sc-autostart.desktop.bak";
22
23 void set_badge_class(Gtk::Widget& w, const char* css_class)
24 {
25 w.remove_css_class("status-badge-success");
26 w.remove_css_class("status-badge-danger");
27 w.remove_css_class("status-badge-warning");
28 w.remove_css_class("status-badge-info");
29
30 if (css_class && *css_class) {
31 w.add_css_class(css_class);
32 }
33 }
34}
35
37: Gtk::Box(Gtk::Orientation::VERTICAL, 0),
38m_applyButton(_("Applica")),
39m_refreshButton(_("Aggiorna stato"))
40{
41 const auto cfgDir = Glib::get_user_config_dir() + "/bastionguard-sc";
42 m_configPath = cfgDir + "/service-control.ini";
43 m_backupPath = kAutostartBackupPath;
44
45 buildUi();
48}
49
51{
52 m_savedEnabled = enabled;
53 m_updatingSwitch = true;
54 m_enableSwitch.set_active(enabled);
55 m_updatingSwitch = false;
56}
57
58void SettingsPage::setSystemIntegrationStatus(const std::string& text)
59{
60 m_statusLabel.set_text(text);
61}
62
64{
65 set_hexpand(true);
66 set_vexpand(true);
67
68 m_scroll.set_policy(Gtk::PolicyType::NEVER, Gtk::PolicyType::AUTOMATIC);
69 m_scroll.set_hexpand(true);
70 m_scroll.set_vexpand(true);
71
72 m_content.set_margin_top(24);
73 m_content.set_margin_bottom(24);
74 m_content.set_margin_start(24);
75 m_content.set_margin_end(24);
76 m_content.set_hexpand(true);
77 m_content.set_spacing(16);
78
79 m_title.set_markup(
80 "<span size='xx-large' weight='bold'>" +
81 Glib::Markup::escape_text(_("Impostazioni")) +
82 "</span>");
83 m_title.set_halign(Gtk::Align::START);
84
85 m_intro.set_text(_("Da questa pagina puoi attivare o disattivare BastionGuard™ Secure Connection in modo persistente. La scelta viene salvata in ~/.config; quando disattivi viene fermato/disabilitato bsc-daemon, l'autostart viene rimosso da /etc/xdg/autostart dopo backup nello stesso percorso e i flag vengono impostati a false."));
86 m_intro.add_css_class("alert-info");
87 m_intro.set_wrap(true);
88 m_intro.set_halign(Gtk::Align::START);
89 m_intro.set_justify(Gtk::Justification::LEFT);
90 m_intro.set_margin_bottom(4);
91
92 // =========================
93 // Card: Protezione di sistema
94 // =========================
95 m_serviceFrame.set_label(_("Protezione di sistema"));
97
98 m_serviceBox.set_margin_top(12);
99 m_serviceBox.set_margin_bottom(12);
100 m_serviceBox.set_margin_start(12);
101 m_serviceBox.set_margin_end(12);
102 m_serviceBox.set_spacing(12);
103 m_serviceBox.add_css_class("settings-card");
104
105 auto serviceHeader = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 12);
106 serviceHeader->set_hexpand(true);
107 serviceHeader->set_halign(Gtk::Align::FILL);
108
109 m_serviceTitle.set_text(_("Protezione di sistema"));
110 m_serviceTitle.set_halign(Gtk::Align::START);
111 m_serviceTitle.set_hexpand(true);
112 m_serviceTitle.add_css_class("settings-card-title");
113
114 m_serviceBadge.set_halign(Gtk::Align::END);
115 m_serviceBadge.set_valign(Gtk::Align::CENTER);
116
117 serviceHeader->append(m_serviceTitle);
118 serviceHeader->append(m_serviceBadge);
119
120 auto switchRow = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 12);
121 switchRow->set_halign(Gtk::Align::FILL);
122 switchRow->set_hexpand(true);
123
124 m_enableLabel.set_text(_("BastionGuard™ Secure Connection attivo"));
125 m_enableLabel.set_halign(Gtk::Align::START);
126 m_enableLabel.set_hexpand(true);
127 m_enableLabel.set_valign(Gtk::Align::CENTER);
128
129 // Il CSS dell'app usa un reset globale (`all: unset`), quindi i widget
130 // nativi come Gtk::Switch devono avere dimensioni/stile espliciti.
131 // Senza questo il controllo può essere presente nel layout ma invisibile.
132 m_enableSwitch.set_halign(Gtk::Align::END);
133 m_enableSwitch.set_valign(Gtk::Align::CENTER);
134 m_enableSwitch.set_size_request(56, 30);
135 m_enableSwitch.add_css_class("bsc-toggle-switch");
136 m_enableSwitch.set_tooltip_text(_("Attiva o disattiva l'avvio automatico e bsc-daemon"));
137
138 switchRow->append(m_enableLabel);
139 switchRow->append(m_enableSwitch);
140
141 m_statusLabel.set_wrap(true);
142 m_statusLabel.set_halign(Gtk::Align::START);
143 m_statusLabel.set_xalign(0.0f);
144 m_statusLabel.set_selectable(true);
145
146 m_infoLabel.set_wrap(true);
147 m_infoLabel.set_halign(Gtk::Align::START);
148 m_infoLabel.set_xalign(0.0f);
149 m_infoLabel.set_text(_("Disattivando vengono eseguite queste operazioni: salvataggio di enabled=false, autostart_enabled=false e daemon_enabled=false, backup dell'autostart in /etc/xdg/autostart/bastionguard-sc-autostart.desktop.bak, rimozione dell'autostart attivo e disattivazione di bsc-daemon tramite il gestore servizi. Riattivando, il backup viene ripristinato e il servizio viene riabilitato."));
150 m_infoLabel.add_css_class("alert-info");
151
152 auto buttons = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 8);
153 buttons->append(m_applyButton);
154 buttons->append(m_refreshButton);
155
156 m_serviceBox.append(*serviceHeader);
157 m_serviceBox.append(*switchRow);
160 m_serviceBox.append(*buttons);
161
162 // =========================
163 // Card: Stato rilevato
164 // =========================
165 m_detailsFrame.set_label(_("Stato rilevato"));
166 m_detailsFrame.set_child(m_detailsBox);
167
168 m_detailsBox.set_margin_top(12);
169 m_detailsBox.set_margin_bottom(12);
170 m_detailsBox.set_margin_start(12);
171 m_detailsBox.set_margin_end(12);
172 m_detailsBox.set_spacing(8);
173 m_detailsBox.add_css_class("settings-card");
174
175 auto detailsHeader = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 12);
176 detailsHeader->set_hexpand(true);
177 detailsHeader->set_halign(Gtk::Align::FILL);
178
179 m_detailsTitle.set_text(_("Stato rilevato"));
180 m_detailsTitle.set_halign(Gtk::Align::START);
181 m_detailsTitle.set_hexpand(true);
182 m_detailsTitle.add_css_class("settings-card-title");
183
184 m_detailsBadge.set_halign(Gtk::Align::END);
185 m_detailsBadge.set_valign(Gtk::Align::CENTER);
186
187 detailsHeader->append(m_detailsTitle);
188 detailsHeader->append(m_detailsBadge);
189
190 m_savedPrefLabel.set_halign(Gtk::Align::START);
191 m_savedPrefLabel.set_xalign(0.0f);
192
193 m_serviceStateLabel.set_halign(Gtk::Align::START);
194 m_serviceStateLabel.set_xalign(0.0f);
195
196 m_autostartStateLabel.set_halign(Gtk::Align::START);
197 m_autostartStateLabel.set_xalign(0.0f);
198
199 m_backupStateLabel.set_halign(Gtk::Align::START);
200 m_backupStateLabel.set_xalign(0.0f);
201
202 m_detailsBox.append(*detailsHeader);
207
208 m_enableSwitch.property_active().signal_changed().connect([this]() {
209 if (m_updatingSwitch) return;
210
211 const bool enabled = m_enableSwitch.get_active();
212 m_statusLabel.set_text(enabled
213 ? _("Attivazione richiesta dalle impostazioni...")
214 : _("Disattivazione richiesta dalle impostazioni..."));
216 });
217
218 m_applyButton.signal_clicked().connect([this]() {
219 const bool enabled = m_enableSwitch.get_active();
220 m_statusLabel.set_text(enabled
221 ? _("Attivazione richiesta dalle impostazioni...")
222 : _("Disattivazione richiesta dalle impostazioni..."));
224 });
225
226 m_refreshButton.signal_clicked().connect([this]() {
227 refreshState();
228 });
229
230 m_content.append(m_title);
231 m_content.append(m_intro);
234
235 m_scroll.set_child(m_content);
236 append(m_scroll);
237}
238
240{
241 m_savedEnabled = true;
242
243 std::ifstream in(m_configPath);
244 std::string line;
245 while (std::getline(in, line)) {
246 if (line == "enabled=false") m_savedEnabled = false;
247 if (line == "enabled=true") m_savedEnabled = true;
248 if (line == "autostart_enabled=false") m_savedEnabled = false;
249 if (line == "daemon_enabled=false") m_savedEnabled = false;
250 }
251
252 m_updatingSwitch = true;
253 m_enableSwitch.set_active(m_savedEnabled);
254 m_updatingSwitch = false;
255}
256
257
259{
260 const std::string cmd =
261 std::string(BSC_SERVICECTL_PATH) + " --system is-enabled " +
262 kServiceName + " >/dev/null 2>&1";
263 return std::system(cmd.c_str()) == 0;
264}
265
267{
268 return fs::exists(kAutostartPath) || fs::exists(kFallbackAutostartPath);
269}
270
272{
273 return fs::exists(m_backupPath);
274}
275
276
277std::string SettingsPage::boolText(bool value)
278{
279 return value ? _("sì") : _("no");
280}
281
282
284{
286
287 const bool svc = serviceEnabled();
288 const bool autoStart = autostartInstalled();
289 const bool backup = backupExists();
290
291 const bool protectionActive = m_savedEnabled && svc && autoStart;
292 const bool protectionInactive = !m_savedEnabled && !svc && !autoStart;
293 const bool protectionPartial = !protectionActive && !protectionInactive;
294
295 m_savedPrefLabel.set_text(
296 _("Preferenza salvata in ~/.config: ") +
297 std::string(m_savedEnabled ? _("attivo") : _("disattivato")));
298
299 m_serviceStateLabel.set_text(
300 _("Servizio di sistema abilitato: ") + boolText(svc));
301
302 m_autostartStateLabel.set_text(
303 _("Autostart presente in /etc/xdg/autostart: ") + boolText(autoStart));
304
305 m_backupStateLabel.set_text(
306 _("Backup autostart in /etc/xdg/autostart disponibile: ") + boolText(backup));
307
308 if (m_statusLabel.get_text().empty()) {
309 m_statusLabel.set_text(
310 _("Usa questa pagina per applicare o ripristinare la configurazione di avvio di BastionGuard."));
311 }
312
313 if (protectionActive) {
314 m_serviceBadge.set_text(_("Attivo"));
315 m_detailsBadge.set_text(_("Coerente"));
316 set_badge_class(m_serviceBadge, "status-badge-success");
317 set_badge_class(m_detailsBadge, "status-badge-success");
318 } else if (protectionInactive) {
319 m_serviceBadge.set_text(_("Disattivato"));
320 m_detailsBadge.set_text(_("Disattivato"));
321 set_badge_class(m_serviceBadge, "status-badge-danger");
322 set_badge_class(m_detailsBadge, "status-badge-danger");
323 } else if (protectionPartial) {
324 m_serviceBadge.set_text(_("Parziale"));
325 m_detailsBadge.set_text(_("Incoerente"));
326 set_badge_class(m_serviceBadge, "status-badge-warning");
327 set_badge_class(m_detailsBadge, "status-badge-warning");
328 } else {
329 m_serviceBadge.set_text(_("Info"));
330 m_detailsBadge.set_text(_("Info"));
331 set_badge_class(m_serviceBadge, "status-badge-info");
332 set_badge_class(m_detailsBadge, "status-badge-info");
333 }
334
335 m_updatingSwitch = true;
336 m_enableSwitch.set_active(m_savedEnabled);
337 m_updatingSwitch = false;
338}
#define _(s)
Gtk::Label m_serviceTitle
Gtk::Box m_detailsBox
std::string m_configPath
void setProtectionEnabled(bool enabled)
Gtk::ScrolledWindow m_scroll
Gtk::Button m_refreshButton
bool autostartInstalled() const
Gtk::Label m_savedPrefLabel
std::string m_backupPath
Gtk::Switch m_enableSwitch
Gtk::Box m_content
Gtk::Label m_intro
Gtk::Label m_autostartStateLabel
Gtk::Label m_infoLabel
Gtk::Frame m_detailsFrame
static std::string boolText(bool value)
Gtk::Label m_serviceBadge
Gtk::Label m_title
void setSystemIntegrationStatus(const std::string &text)
bool backupExists() const
Gtk::Label m_backupStateLabel
Gtk::Label m_serviceStateLabel
Gtk::Label m_statusLabel
Gtk::Frame m_serviceFrame
Gtk::Box m_serviceBox
bool serviceEnabled() const
Gtk::Label m_detailsBadge
sigc::signal< void(bool)> m_signalToggleProtectionRequested
void loadPreference()
Gtk::Label m_enableLabel
Gtk::Label m_detailsTitle
Gtk::Button m_applyButton
void set_badge_class(Gtk::Widget &w, const char *css_class)
constexpr const char * kAutostartBackupPath
constexpr const char * kFallbackAutostartPath
constexpr const char * kAutostartPath
#define BSC_SERVICECTL_PATH