Skip to content
API Documentation
BastionGuard™
PasswordManagerPage Class Reference

#include <PasswordManagerPage.hpp>

Inheritance diagram for PasswordManagerPage:

Public Member Functions

 PasswordManagerPage ()
 ~PasswordManagerPage () override

Private Member Functions

void buildUi ()
void setVaultState (bool unlocked, const std::string &msg="")
void reload ()
void refreshEntries (const std::string &filter="")
void createEntryRow (const PasswordEntry &entry)
void onUnlockClicked ()
void onLockClicked ()
void onAddClicked ()
void onImportClicked ()
void onVaultViewClicked ()
void onDeleteAllClicked ()
void onRefreshClicked ()
void onSearchChanged ()
void onRevealEntry (const PasswordEntry &entry)
void onEditEntry (const PasswordEntry &entry)
void onDeleteEntry (const PasswordEntry &entry)
Gtk::Window * getParentWindow ()
void logSafe (const std::string &msg)

Private Attributes

PasswordVault vault_
std::vector< PasswordEntry > entriesCache_
Gtk::Box securityBanner_
Gtk::Label securityIcon_
Gtk::Label securityLabel_
Gtk::Box topBar_
Gtk::Button unlockButton_
Gtk::Button lockButton_
Gtk::Box stateBox_
Gtk::Label stateLabel_
Gtk::Box actionBar_
Gtk::Button addButton_
Gtk::Button importButton_
Gtk::Button vaultViewButton_
Gtk::Button refreshButton_
Gtk::Button deleteAllButton_
Gtk::SearchEntry searchEntry_
Gtk::ScrolledWindow listScrolled_
Gtk::Box entriesBox_
Gtk::ScrolledWindow logScrolled_
Gtk::TextView outputView_
Glib::RefPtr< Gtk::TextBuffer > buffer_
BastionGuard::AliveFlag alive_ = BastionGuard::make_alive_flag()

Detailed Description

Definition at line 31 of file PasswordManagerPage.hpp.

Constructor & Destructor Documentation

◆ PasswordManagerPage()

PasswordManagerPage::PasswordManagerPage ( )

Definition at line 32 of file PasswordManagerPage.cpp.

33: Gtk::Box(Gtk::Orientation::VERTICAL, 6),
34 securityBanner_(Gtk::Orientation::HORIZONTAL, 8),
35 topBar_(Gtk::Orientation::HORIZONTAL, 8),
36 unlockButton_(_("🔓 Sblocca vault")),
37 lockButton_(_("🔒 Blocca")),
38 stateBox_(Gtk::Orientation::HORIZONTAL, 0),
39 actionBar_(Gtk::Orientation::HORIZONTAL, 8),
40 addButton_(_("+ Nuova")),
41 importButton_(_("⬆ Importa")),
42 vaultViewButton_(_("🗄 Vault")),
43 refreshButton_(_("↺ Aggiorna")),
44 deleteAllButton_(_("🗑 Elimina tutto")),
45 entriesBox_(Gtk::Orientation::VERTICAL, 6)
46{
47 auto cssProvider = Gtk::CssProvider::create();
48 Gtk::StyleContext::add_provider_for_display(
49 Gdk::Display::get_default(),
50 cssProvider,
51 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
52
53 buildUi();
55
56 unlockButton_.signal_clicked().connect(sigc::mem_fun(*this, &PasswordManagerPage::onUnlockClicked));
57 lockButton_.signal_clicked().connect(sigc::mem_fun(*this, &PasswordManagerPage::onLockClicked));
58 addButton_.signal_clicked().connect(sigc::mem_fun(*this, &PasswordManagerPage::onAddClicked));
59 importButton_.signal_clicked().connect(sigc::mem_fun(*this, &PasswordManagerPage::onImportClicked));
60 vaultViewButton_.signal_clicked().connect(sigc::mem_fun(*this, &PasswordManagerPage::onVaultViewClicked));
61 refreshButton_.signal_clicked().connect(sigc::mem_fun(*this, &PasswordManagerPage::onRefreshClicked));
62 deleteAllButton_.signal_clicked().connect(sigc::mem_fun(*this, &PasswordManagerPage::onDeleteAllClicked));
63 searchEntry_.signal_search_changed().connect(sigc::mem_fun(*this, &PasswordManagerPage::onSearchChanged));
64
65 reload();
66}
#define _(s)
Gtk::SearchEntry searchEntry_

References _, actionBar_, addButton_, buildUi(), deleteAllButton_, entriesBox_, importButton_, PasswordVault::initialize(), lockButton_, onAddClicked(), onDeleteAllClicked(), onImportClicked(), onLockClicked(), onRefreshClicked(), onSearchChanged(), onUnlockClicked(), onVaultViewClicked(), refreshButton_, reload(), searchEntry_, securityBanner_, stateBox_, topBar_, unlockButton_, vault_, and vaultViewButton_.

◆ ~PasswordManagerPage()

PasswordManagerPage::~PasswordManagerPage ( )
override

Definition at line 68 of file PasswordManagerPage.cpp.

68 {
69 if (alive_) alive_->store(false, std::memory_order_release);
70}
BastionGuard::AliveFlag alive_

References alive_.

Member Function Documentation

◆ buildUi()

void PasswordManagerPage::buildUi ( )
private

Definition at line 73 of file PasswordManagerPage.cpp.

73 {
74 buffer_ = Gtk::TextBuffer::create();
75 outputView_.set_buffer(buffer_);
76 outputView_.set_editable(false);
77 outputView_.set_monospace(true);
78
79 set_margin_top(8);
80 set_margin_bottom(8);
81 set_margin_start(8);
82 set_margin_end(8);
83
84 securityBanner_.get_style_context()->add_class("security-banner");
85 securityBanner_.get_style_context()->add_class("alert-info");
86 securityIcon_.set_text("🔐");
88
89 securityLabel_.set_markup(_(
90 "<b>Protezione avanzata AES-256-GCM</b> — "
91 "Le password sono cifrate con AES-256-GCM e la chiave è derivata dalla master password "
92 "tramite PBKDF2-SHA256 (100.000 iterazioni). Il file cifrato include un tag di "
93 "autenticazione: qualsiasi manipolazione esterna renderà il vault permanentemente illeggibile."
94 ));
95 securityLabel_.set_wrap(true);
96 securityLabel_.set_xalign(0.0f);
97 securityLabel_.set_hexpand(true);
99
100 auto* dangerBanner = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 8);
101 dangerBanner->get_style_context()->add_class("security-banner");
102 dangerBanner->get_style_context()->add_class("alert-danger");
103
104 auto* dangerIcon = Gtk::make_managed<Gtk::Label>();
105 dangerIcon->set_text("⚠️");
106 dangerBanner->append(*dangerIcon);
107
108 auto* dangerLabel = Gtk::make_managed<Gtk::Label>();
109 dangerLabel->set_markup(_(
110 "<b>Attenzione:</b> — L'esportazione del vault salva il file CSV con password in chiaro. "
111 "Salvare il file in un luogo sicuro e non accessibile."
112 ));
113 dangerLabel->set_wrap(true);
114 dangerLabel->set_xalign(0.0f);
115 dangerLabel->set_hexpand(true);
116 dangerBanner->append(*dangerLabel);
117
118 topBar_.set_margin_bottom(4);
119 topBar_.append(unlockButton_);
120 topBar_.append(lockButton_);
121
122 auto* spacer1 = Gtk::make_managed<Gtk::Box>();
123 spacer1->set_hexpand(true);
124 topBar_.append(*spacer1);
125 stateBox_.set_margin_start(4);
126 stateLabel_.set_text(_("🔒 Vault bloccato"));
127 stateBox_.append(stateLabel_);
128 stateBox_.get_style_context()->add_class("alert-success");
129 topBar_.append(stateBox_);
130 actionBar_.set_margin_bottom(4);
131
132 addButton_.get_style_context()->add_class("suggested-action");
133 actionBar_.append(addButton_);
134
135 {
136 importButton_.get_style_context()->add_class("suggested-action");
137 auto p = Gtk::CssProvider::create();
138 p->load_from_data(
139 "button.suggested-action#importBtn {"
140 " background:linear-gradient(to bottom,#33d17a,#26a269);"
141 " color:white;font-weight:bold;"
142 " padding:6px 16px;border-radius:6px;"
143 " border:1px solid #1e8449;"
144 "}");
145 importButton_.set_name("importBtn");
146 importButton_.get_style_context()->add_provider(p, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
147 }
149 {
150 vaultViewButton_.get_style_context()->add_class("suggested-action");
151 auto p = Gtk::CssProvider::create();
152 p->load_from_data(
153 "button.suggested-action#vaultBtn {"
154 " background:linear-gradient(to bottom,#3584e4,#1c71d8);"
155 " color:white;font-weight:bold;"
156 " padding:6px 16px;border-radius:6px;"
157 " border:1px solid #1558b0;"
158 "}");
159 vaultViewButton_.set_name("vaultBtn");
160 vaultViewButton_.get_style_context()->add_provider(p, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
161 }
164
165 auto* spacer2 = Gtk::make_managed<Gtk::Box>();
166 spacer2->set_hexpand(true);
167 actionBar_.append(*spacer2);
168
169 deleteAllButton_.get_style_context()->add_class("destructive-action");
171
172 searchEntry_.set_placeholder_text(_("Cerca credenziali..."));
173 searchEntry_.set_size_request(200, -1);
174 actionBar_.append(searchEntry_);
175
176 auto* sep = Gtk::make_managed<Gtk::Separator>(Gtk::Orientation::HORIZONTAL);
177
178 listScrolled_.set_child(entriesBox_);
179 listScrolled_.set_expand(true);
180
181 logScrolled_.set_child(outputView_);
182 logScrolled_.set_min_content_height(100);
183 logScrolled_.set_expand(false);
184
185 append(securityBanner_);
186 append(*dangerBanner);
187 append(topBar_);
188 append(actionBar_);
189 append(*sep);
190 append(listScrolled_);
191 append(logScrolled_);
192}
Gtk::ScrolledWindow logScrolled_
Gtk::ScrolledWindow listScrolled_
Glib::RefPtr< Gtk::TextBuffer > buffer_

References _, actionBar_, addButton_, buffer_, deleteAllButton_, entriesBox_, importButton_, listScrolled_, lockButton_, logScrolled_, outputView_, refreshButton_, searchEntry_, securityBanner_, securityIcon_, securityLabel_, stateBox_, stateLabel_, topBar_, unlockButton_, and vaultViewButton_.

Referenced by PasswordManagerPage().

◆ createEntryRow()

void PasswordManagerPage::createEntryRow ( const PasswordEntry & entry)
private

Definition at line 233 of file PasswordManagerPage.cpp.

233 {
234 auto* row = Gtk::make_managed<PasswordSearchRow>(entry);
235 row->signal_reveal().connect([this](const PasswordEntry& e) { onRevealEntry(e); });
236 row->signal_edit().connect([this](const PasswordEntry& e) { onEditEntry(e); });
237 row->signal_delete().connect([this](const PasswordEntry& e) { onDeleteEntry(e); });
238 entriesBox_.append(*row);
239}
void onRevealEntry(const PasswordEntry &entry)
void onDeleteEntry(const PasswordEntry &entry)
void onEditEntry(const PasswordEntry &entry)

References entriesBox_, onDeleteEntry(), onEditEntry(), and onRevealEntry().

Referenced by refreshEntries().

◆ getParentWindow()

Gtk::Window * PasswordManagerPage::getParentWindow ( )
private

Definition at line 581 of file PasswordManagerPage.cpp.

581 {
582 auto* root = get_root();
583 return dynamic_cast<Gtk::Window*>(root);
584}

Referenced by onAddClicked(), onDeleteAllClicked(), onDeleteEntry(), onEditEntry(), onImportClicked(), onRevealEntry(), onUnlockClicked(), and onVaultViewClicked().

◆ logSafe()

void PasswordManagerPage::logSafe ( const std::string & msg)
private

Definition at line 586 of file PasswordManagerPage.cpp.

586 {
587 auto alive = alive_;
588 Glib::signal_idle().connect_once([this, alive, msg]() {
589 BastionGuard::if_alive(alive, [this, &msg]() {
590 buffer_->insert(buffer_->end(), msg);
591 });
592 });
593}
void if_alive(const AliveFlag &alive, Fn &&fn)

References alive_, buffer_, and BastionGuard::if_alive().

Referenced by onAddClicked(), onDeleteAllClicked(), onDeleteEntry(), onEditEntry(), onImportClicked(), onLockClicked(), onRefreshClicked(), onRevealEntry(), onUnlockClicked(), and onVaultViewClicked().

◆ onAddClicked()

void PasswordManagerPage::onAddClicked ( )
private

Definition at line 360 of file PasswordManagerPage.cpp.

360 {
361
362 if (!vault_.isUnlocked()) { logSafe(_("Sblocca il vault prima.\n")); return; }
363 auto* parent = getParentWindow();
364 if (!parent) return;
365
366 auto* dialog = new PasswordDialog(*parent, _("Nuova credenziale"));
367 dialog->signal_response().connect([this, dialog](int response) {
368 if (response == Gtk::ResponseType::OK) {
369 PasswordEntry entry = dialog->getEntry();
370 if (entry.name.empty()) {
371 logSafe(_("Nome credenziale obbligatorio.\n"));
372 } else {
373 entry.id = vault_.generateId();
374 entry.created_at = vault_.nowIso();
375 entry.updated_at = entry.created_at;
376 if (vault_.addEntry(entry, dialog->getSecret())) {
377 logSafe(std::string(_("Credenziale aggiunta: ")) + entry.name + "\n");
378 reload();
379 } else {
380 logSafe(_("Errore durante il salvataggio.\n"));
381 }
382 }
383 }
384 dialog->hide();
385 delete dialog;
386 });
387 dialog->present();
388}
PasswordDialog(Gtk::Window &parent, const Glib::ustring &title)
Gtk::Window * getParentWindow()
void logSafe(const std::string &msg)
std::string generateId() const
bool isUnlocked() const
bool addEntry(const PasswordEntry &entry, const std::string &secret)
std::string nowIso() const
std::string created_at
std::string id
std::string updated_at
std::string name

References _, PasswordVault::addEntry(), PasswordEntry::created_at, PasswordVault::generateId(), getParentWindow(), PasswordEntry::id, PasswordVault::isUnlocked(), logSafe(), PasswordEntry::name, PasswordVault::nowIso(), PasswordDialog::PasswordDialog(), reload(), PasswordEntry::updated_at, and vault_.

Referenced by PasswordManagerPage().

◆ onDeleteAllClicked()

void PasswordManagerPage::onDeleteAllClicked ( )
private

Definition at line 441 of file PasswordManagerPage.cpp.

441 {
442
443 if (!vault_.isUnlocked()) { logSafe(_("Sblocca il vault prima.\n")); return; }
444 auto* parent = getParentWindow();
445 if (!parent) return;
446
447 const auto count = entriesCache_.size();
448 if (count == 0) { logSafe(_("Nessuna credenziale da eliminare.\n")); return; }
449
450 auto* confirm1 = new Gtk::MessageDialog(
451 *parent, _("Eliminare tutte le credenziali?"),
452 false, Gtk::MessageType::WARNING, Gtk::ButtonsType::OK_CANCEL, true);
453 confirm1->set_secondary_text(
454 std::string(_("Questa operazione eliminerà ")) + std::to_string(count) +
455 std::string(_(" credenziali e non può essere annullata.")));
456
457 confirm1->signal_response().connect([this, confirm1, parent](int r1) {
458 confirm1->hide();
459 if (r1 != Gtk::ResponseType::OK) { delete confirm1; return; }
460
461 auto* confirm2 = new Gtk::MessageDialog(
462 *parent, _("Sei sicuro? L'operazione è irreversibile."),
463 false, Gtk::MessageType::ERROR, Gtk::ButtonsType::NONE, true);
464 confirm2->set_secondary_text(_("Il file cifrato verrà eliminato definitivamente."));
465 confirm2->add_button(_("Annulla"), Gtk::ResponseType::CANCEL);
466 confirm2->add_button(_("Sì, elimina tutto"), Gtk::ResponseType::OK);
467 auto* ok_btn = confirm2->get_widget_for_response(Gtk::ResponseType::OK);
468 if (ok_btn) ok_btn->get_style_context()->add_class("destructive-action");
469
470 confirm2->signal_response().connect([this, confirm2](int r2) {
471 confirm2->hide();
472 if (r2 == Gtk::ResponseType::OK) {
473 logSafe(_("Eliminazione in corso…\n"));
474 vault_.deleteAllEntries([this](bool ok) {
475 logSafe(ok ? _("✔ Tutte le credenziali eliminate.\n")
476 : _("Errore durante l'eliminazione.\n"));
477 reload();
478 });
479 }
480 delete confirm2;
481 });
482 confirm2->present();
483 delete confirm1;
484 });
485 confirm1->present();
486}
std::vector< PasswordEntry > entriesCache_
void deleteAllEntries(std::function< void(bool)> onDone)

References _, PasswordVault::deleteAllEntries(), entriesCache_, getParentWindow(), PasswordVault::isUnlocked(), logSafe(), reload(), and vault_.

Referenced by PasswordManagerPage().

◆ onDeleteEntry()

void PasswordManagerPage::onDeleteEntry ( const PasswordEntry & entry)
private

Definition at line 555 of file PasswordManagerPage.cpp.

555 {
556
557 if (!vault_.isUnlocked()) { logSafe(_("Vault bloccato.\n")); return; }
558 auto* parent = getParentWindow();
559 if (!parent) return;
560
561 auto* confirm = new Gtk::MessageDialog(
562 *parent, _("Eliminare la credenziale selezionata?"),
563 false, Gtk::MessageType::QUESTION, Gtk::ButtonsType::OK_CANCEL, true);
564 confirm->set_secondary_text(entry.name);
565 confirm->signal_response().connect([this, confirm, entry](int response) {
566 if (response == Gtk::ResponseType::OK) {
567 if (vault_.deleteEntry(entry.id)) {
568 logSafe(std::string(_("Credenziale eliminata: ")) + entry.name + "\n");
569 reload();
570 } else {
571 logSafe(_("Errore durante l'eliminazione.\n"));
572 }
573 }
574 confirm->hide();
575 delete confirm;
576 });
577 confirm->present();
578}
bool deleteEntry(const std::string &id)

References _, PasswordVault::deleteEntry(), getParentWindow(), PasswordEntry::id, PasswordVault::isUnlocked(), logSafe(), PasswordEntry::name, reload(), and vault_.

Referenced by createEntryRow().

◆ onEditEntry()

void PasswordManagerPage::onEditEntry ( const PasswordEntry & entry)
private

Definition at line 521 of file PasswordManagerPage.cpp.

521 {
522
523 if (!vault_.isUnlocked()) { logSafe(_("Vault bloccato.\n")); return; }
524 auto* parent = getParentWindow();
525 if (!parent) return;
526
527 auto alive = alive_;
528 vault_.getSecretAsync(entry.id, [this, alive, entry](std::string secret) {
529 if (!alive || !alive->load(std::memory_order_acquire)) return;
530 auto* p = getParentWindow();
531 if (!p) return;
532 auto* dialog = new PasswordDialog(
533 *p, _("Modifica credenziale"), entry, secret);
534 dialog->signal_response().connect([this, dialog, entry](int response) {
535 if (response == Gtk::ResponseType::OK) {
536 PasswordEntry updated = dialog->getEntry();
537 updated.id = entry.id;
538 updated.created_at = entry.created_at;
539 updated.updated_at = vault_.nowIso();
540 if (vault_.updateEntry(updated, dialog->getSecret())) {
541 logSafe(std::string(_("Credenziale aggiornata: ")) + updated.name + "\n");
542 reload();
543 } else {
544 logSafe(_("Errore durante l'aggiornamento.\n"));
545 }
546 }
547 dialog->hide();
548 delete dialog;
549 });
550 dialog->present();
551 });
552}
void getSecretAsync(const std::string &id, std::function< void(std::string)> callback) const

References _, alive_, getParentWindow(), PasswordVault::getSecretAsync(), PasswordEntry::id, PasswordVault::isUnlocked(), logSafe(), and vault_.

Referenced by createEntryRow().

◆ onImportClicked()

void PasswordManagerPage::onImportClicked ( )
private

Definition at line 391 of file PasswordManagerPage.cpp.

391 {
392
393 if (!vault_.isUnlocked()) { logSafe(_("Sblocca il vault prima di importare.\n")); return; }
394 auto* parent = getParentWindow();
395 if (!parent) return;
396
397 auto* dialog = new PasswordImportDialog(*parent);
398 dialog->signal_import_confirmed().connect(
399 [this, dialog](std::vector<PasswordImportDialog::BulkItem> items) {
400 dialog->hide();
401 if (items.empty()) { delete dialog; return; }
402
403 const std::string now = vault_.nowIso();
404 for (auto& [entry, pwd] : items) {
405 entry.id = vault_.generateId();
406 entry.created_at = now;
407 entry.updated_at = now;
408 if (entry.name.empty() && !entry.url.empty()) {
409 auto url = entry.url;
410 auto p = url.find("://");
411 if (p != std::string::npos) url = url.substr(p + 3);
412 auto sl = url.find('/');
413 if (sl != std::string::npos) url = url.substr(0, sl);
414 entry.name = url;
415 }
416 }
417
418 vault_.addEntriesBulk(items, [this, dialog](int ok, int fail) {
419 logSafe(std::string(_("Import completato: ")) + std::to_string(ok) +
420 std::string(_(" importate")) +
421 (fail > 0 ? (", " + std::to_string(fail) + std::string(_(" fallite"))) : "") +
422 ".\n");
423 reload();
424 delete dialog;
425 });
426 });
427 dialog->present();
428}
PasswordImportDialog(Gtk::Window &parent)
void addEntriesBulk(const std::vector< std::pair< PasswordEntry, std::string > > &items, std::function< void(int ok, int fail)> onDone)

References _, PasswordVault::addEntriesBulk(), PasswordVault::generateId(), getParentWindow(), PasswordVault::isUnlocked(), logSafe(), PasswordVault::nowIso(), PasswordImportDialog::PasswordImportDialog(), reload(), and vault_.

Referenced by PasswordManagerPage().

◆ onLockClicked()

void PasswordManagerPage::onLockClicked ( )
private

Definition at line 352 of file PasswordManagerPage.cpp.

352 {
353
354 vault_.lock();
355 setVaultState(false);
356 logSafe(_("Vault bloccato.\n"));
357}
void setVaultState(bool unlocked, const std::string &msg="")

References _, PasswordVault::lock(), logSafe(), setVaultState(), and vault_.

Referenced by PasswordManagerPage().

◆ onRefreshClicked()

void PasswordManagerPage::onRefreshClicked ( )
private

Definition at line 489 of file PasswordManagerPage.cpp.

489 {
490
491 reload();
492 logSafe(_("Elenco aggiornato.\n"));
493}

References _, logSafe(), and reload().

Referenced by PasswordManagerPage().

◆ onRevealEntry()

void PasswordManagerPage::onRevealEntry ( const PasswordEntry & entry)
private

Definition at line 500 of file PasswordManagerPage.cpp.

500 {
501
502 if (!vault_.isUnlocked()) { logSafe(_("Vault bloccato.\n")); return; }
503 auto* parent = getParentWindow();
504 if (!parent) return;
505
506 auto alive = alive_;
507 vault_.getSecretAsync(entry.id, [this, alive, entry](std::string secret) {
508 if (!alive || !alive->load(std::memory_order_acquire)) return;
509 auto* p = getParentWindow();
510 if (!p) return;
511 auto* reveal = new Gtk::MessageDialog(
512 *p, _("Password per: ") + entry.name,
513 false, Gtk::MessageType::INFO, Gtk::ButtonsType::CLOSE, true);
514 reveal->set_secondary_text(secret, false);
515 reveal->signal_response().connect([reveal](int) { reveal->hide(); delete reveal; });
516 reveal->present();
517 });
518}

References _, alive_, getParentWindow(), PasswordVault::getSecretAsync(), PasswordEntry::id, PasswordVault::isUnlocked(), logSafe(), and vault_.

Referenced by createEntryRow().

◆ onSearchChanged()

void PasswordManagerPage::onSearchChanged ( )
private

Definition at line 495 of file PasswordManagerPage.cpp.

495 {
496
497 refreshEntries(searchEntry_.get_text());
498}
void refreshEntries(const std::string &filter="")

References refreshEntries(), and searchEntry_.

Referenced by PasswordManagerPage().

◆ onUnlockClicked()

void PasswordManagerPage::onUnlockClicked ( )
private

Definition at line 242 of file PasswordManagerPage.cpp.

242 {
243
244 auto* parent = getParentWindow();
245 if (!parent) { logSafe(_("Impossibile trovare la finestra padre.\n")); return; }
246
247 if (vault_.isFirstRun()) {
248 auto* dialog = Gtk::make_managed<Gtk::Dialog>(_("Crea master password"), *parent, true);
249 dialog->get_content_area()->set_margin(12);
250 dialog->get_content_area()->set_spacing(8);
251
252 auto* infoLabel = Gtk::make_managed<Gtk::Label>(
253 _("Prima configurazione: scegli una master password.\n"
254 "Minimo 8 caratteri. Non può essere recuperata se dimenticata."));
255 infoLabel->set_wrap(true);
256 infoLabel->set_xalign(0.0f);
257 infoLabel->get_style_context()->add_class("dim-label");
258
259 auto* entry1 = Gtk::make_managed<Gtk::Entry>();
260 entry1->set_placeholder_text(_("Nuova master password"));
261 entry1->set_visibility(false);
262 entry1->set_input_purpose(Gtk::InputPurpose::PASSWORD);
263
264 auto* entry2 = Gtk::make_managed<Gtk::Entry>();
265 entry2->set_placeholder_text(_("Conferma master password"));
266 entry2->set_visibility(false);
267 entry2->set_input_purpose(Gtk::InputPurpose::PASSWORD);
268 entry2->set_activates_default(true);
269
270 auto* strengthLabel = Gtk::make_managed<Gtk::Label>("");
271 strengthLabel->set_xalign(0.0f);
272
273 dialog->get_content_area()->append(*infoLabel);
274 dialog->get_content_area()->append(*entry1);
275 dialog->get_content_area()->append(*entry2);
276 dialog->get_content_area()->append(*strengthLabel);
277 dialog->add_button(_("Annulla"), Gtk::ResponseType::CANCEL);
278 dialog->add_button(_("Crea vault"), Gtk::ResponseType::OK);
279 dialog->set_default_response(Gtk::ResponseType::OK);
280
281 entry1->signal_changed().connect([entry1, strengthLabel]() {
282 const auto pwd = entry1->get_text();
283 const size_t len = pwd.size();
284 bool hasUpper = false, hasLower = false, hasDigit = false, hasSymbol = false;
285 for (char c : pwd) {
286 if (std::isupper(c)) hasUpper = true;
287 else if (std::islower(c)) hasLower = true;
288 else if (std::isdigit(c)) hasDigit = true;
289 else hasSymbol = true;
290 }
291 const int score = (len >= 8) + (len >= 12) + hasUpper + hasLower + hasDigit + hasSymbol;
292 std::string markup;
293 if (len == 0) markup = "";
294 else if (score <= 2) markup = "<span foreground='red'>⚠ Debole</span>";
295 else if (score <= 4) markup = "<span foreground='orange'>◑ Media</span>";
296 else markup = "<span foreground='green'>✔ Forte</span>";
297 strengthLabel->set_markup(markup);
298 });
299
300 dialog->signal_response().connect([this, dialog, entry1, entry2](int response) {
301 if (response == Gtk::ResponseType::OK) {
302 const auto pwd1 = entry1->get_text();
303 const auto pwd2 = entry2->get_text();
304 if (pwd1 != pwd2) {
305 logSafe(_("Le password non coincidono.\n"));
306 } else if (pwd1.size() < 8) {
307 logSafe(_("La master password deve essere di almeno 8 caratteri.\n"));
308 } else if (vault_.createMasterPassword(pwd1)) {
309 setVaultState(true, _("🔓 Vault creato e sbloccato"));
310 logSafe(_("Vault creato. Master password impostata.\n"));
311 } else {
312 logSafe(_("Errore durante la creazione del vault.\n"));
313 }
314 }
315 dialog->hide();
316 });
317 dialog->present();
318
319 } else {
320 auto* dialog = Gtk::make_managed<Gtk::Dialog>(_("Sblocca vault"), *parent, true);
321 auto* entry = Gtk::make_managed<Gtk::Entry>();
322 entry->set_placeholder_text(_("Master password"));
323 entry->set_visibility(false);
324 entry->set_input_purpose(Gtk::InputPurpose::PASSWORD);
325 entry->set_activates_default(true);
326 dialog->get_content_area()->set_margin(12);
327 dialog->get_content_area()->append(*entry);
328 dialog->add_button(_("Annulla"), Gtk::ResponseType::CANCEL);
329 dialog->add_button(_("Sblocca"), Gtk::ResponseType::OK);
330 dialog->set_default_response(Gtk::ResponseType::OK);
331
332 dialog->signal_response().connect([this, dialog, entry](int response) {
333 if (response == Gtk::ResponseType::OK) {
334 if (vault_.unlock(entry->get_text())) {
335 setVaultState(true, _("🔓 Vault sbloccato — caricamento cache…"));
336 logSafe(_("Vault sbloccato. Precaricamento password in background…\n"));
337 Glib::signal_timeout().connect_once([this]() {
338 if (vault_.isUnlocked())
339 setVaultState(true);
340 }, 3000);
341 } else {
342 logSafe(_("Password errata.\n"));
343 }
344 }
345 dialog->hide();
346 });
347 dialog->present();
348 }
349}
bool createMasterPassword(const std::string &masterPassword)
bool isFirstRun() const
bool unlock(const std::string &masterPassword)

References _, PasswordVault::createMasterPassword(), getParentWindow(), PasswordVault::isFirstRun(), PasswordVault::isUnlocked(), logSafe(), setVaultState(), PasswordVault::unlock(), and vault_.

Referenced by PasswordManagerPage().

◆ onVaultViewClicked()

void PasswordManagerPage::onVaultViewClicked ( )
private

Definition at line 431 of file PasswordManagerPage.cpp.

431 {
432
433 if (!vault_.isUnlocked()) { logSafe(_("Sblocca il vault prima.\n")); return; }
434 auto* parent = getParentWindow();
435 if (!parent) return;
436 auto* view = new PasswordVaultView(*parent, vault_);
437 view->present();
438}
PasswordVaultView(Gtk::Window &parent, PasswordVault &vault)

References _, getParentWindow(), PasswordVault::isUnlocked(), logSafe(), PasswordVaultView::PasswordVaultView(), and vault_.

Referenced by PasswordManagerPage().

◆ refreshEntries()

void PasswordManagerPage::refreshEntries ( const std::string & filter = "")
private

Definition at line 218 of file PasswordManagerPage.cpp.

218 {
219 while (auto* child = entriesBox_.get_first_child())
220 entriesBox_.remove(*child);
221
222 std::string needle = filter;
223 std::transform(needle.begin(), needle.end(), needle.begin(), ::tolower);
224
225 for (const auto& entry : entriesCache_) {
226 std::string hay = entry.name + " " + entry.username + " " + entry.url + " " + entry.notes;
227 std::transform(hay.begin(), hay.end(), hay.begin(), ::tolower);
228 if (!needle.empty() && hay.find(needle) == std::string::npos) continue;
229 createEntryRow(entry);
230 }
231}
void createEntryRow(const PasswordEntry &entry)

References createEntryRow(), entriesBox_, and entriesCache_.

Referenced by onSearchChanged(), and reload().

◆ reload()

void PasswordManagerPage::reload ( )
private

◆ setVaultState()

void PasswordManagerPage::setVaultState ( bool unlocked,
const std::string & msg = "" )
private

Definition at line 198 of file PasswordManagerPage.cpp.

198 {
199 auto ctx = stateBox_.get_style_context();
200 ctx->remove_class("alert-success");
201 ctx->remove_class("alert-danger");
202
203 if (unlocked) {
204 ctx->add_class("alert-danger");
205 stateLabel_.set_text(msg.empty() ? _("🔓 Vault sbloccato") : msg);
206 } else {
207 ctx->add_class("alert-success");
208 stateLabel_.set_text(msg.empty() ? _("🔒 Vault bloccato") : msg);
209 }
210}

References _, stateBox_, and stateLabel_.

Referenced by onLockClicked(), and onUnlockClicked().

Member Data Documentation

◆ actionBar_

Gtk::Box PasswordManagerPage::actionBar_
private

Definition at line 49 of file PasswordManagerPage.hpp.

Referenced by buildUi(), and PasswordManagerPage().

◆ addButton_

Gtk::Button PasswordManagerPage::addButton_
private

Definition at line 50 of file PasswordManagerPage.hpp.

Referenced by buildUi(), and PasswordManagerPage().

◆ alive_

BastionGuard::AliveFlag PasswordManagerPage::alive_ = BastionGuard::make_alive_flag()
private

Definition at line 86 of file PasswordManagerPage.hpp.

Referenced by logSafe(), onEditEntry(), onRevealEntry(), and ~PasswordManagerPage().

◆ buffer_

Glib::RefPtr<Gtk::TextBuffer> PasswordManagerPage::buffer_
private

Definition at line 62 of file PasswordManagerPage.hpp.

Referenced by buildUi(), and logSafe().

◆ deleteAllButton_

Gtk::Button PasswordManagerPage::deleteAllButton_
private

Definition at line 54 of file PasswordManagerPage.hpp.

Referenced by buildUi(), and PasswordManagerPage().

◆ entriesBox_

Gtk::Box PasswordManagerPage::entriesBox_
private

◆ entriesCache_

std::vector<PasswordEntry> PasswordManagerPage::entriesCache_
private

Definition at line 38 of file PasswordManagerPage.hpp.

Referenced by onDeleteAllClicked(), refreshEntries(), and reload().

◆ importButton_

Gtk::Button PasswordManagerPage::importButton_
private

Definition at line 51 of file PasswordManagerPage.hpp.

Referenced by buildUi(), and PasswordManagerPage().

◆ listScrolled_

Gtk::ScrolledWindow PasswordManagerPage::listScrolled_
private

Definition at line 57 of file PasswordManagerPage.hpp.

Referenced by buildUi().

◆ lockButton_

Gtk::Button PasswordManagerPage::lockButton_
private

Definition at line 44 of file PasswordManagerPage.hpp.

Referenced by buildUi(), and PasswordManagerPage().

◆ logScrolled_

Gtk::ScrolledWindow PasswordManagerPage::logScrolled_
private

Definition at line 60 of file PasswordManagerPage.hpp.

Referenced by buildUi().

◆ outputView_

Gtk::TextView PasswordManagerPage::outputView_
private

Definition at line 61 of file PasswordManagerPage.hpp.

Referenced by buildUi().

◆ refreshButton_

Gtk::Button PasswordManagerPage::refreshButton_
private

Definition at line 53 of file PasswordManagerPage.hpp.

Referenced by buildUi(), and PasswordManagerPage().

◆ searchEntry_

Gtk::SearchEntry PasswordManagerPage::searchEntry_
private

Definition at line 55 of file PasswordManagerPage.hpp.

Referenced by buildUi(), onSearchChanged(), PasswordManagerPage(), and reload().

◆ securityBanner_

Gtk::Box PasswordManagerPage::securityBanner_
private

Definition at line 39 of file PasswordManagerPage.hpp.

Referenced by buildUi(), and PasswordManagerPage().

◆ securityIcon_

Gtk::Label PasswordManagerPage::securityIcon_
private

Definition at line 40 of file PasswordManagerPage.hpp.

Referenced by buildUi().

◆ securityLabel_

Gtk::Label PasswordManagerPage::securityLabel_
private

Definition at line 41 of file PasswordManagerPage.hpp.

Referenced by buildUi().

◆ stateBox_

Gtk::Box PasswordManagerPage::stateBox_
private

Definition at line 45 of file PasswordManagerPage.hpp.

Referenced by buildUi(), PasswordManagerPage(), and setVaultState().

◆ stateLabel_

Gtk::Label PasswordManagerPage::stateLabel_
private

Definition at line 46 of file PasswordManagerPage.hpp.

Referenced by buildUi(), and setVaultState().

◆ topBar_

Gtk::Box PasswordManagerPage::topBar_
private

Definition at line 42 of file PasswordManagerPage.hpp.

Referenced by buildUi(), and PasswordManagerPage().

◆ unlockButton_

Gtk::Button PasswordManagerPage::unlockButton_
private

Definition at line 43 of file PasswordManagerPage.hpp.

Referenced by buildUi(), and PasswordManagerPage().

◆ vault_

◆ vaultViewButton_

Gtk::Button PasswordManagerPage::vaultViewButton_
private

Definition at line 52 of file PasswordManagerPage.hpp.

Referenced by buildUi(), and PasswordManagerPage().


The documentation for this class was generated from the following files: