QtPass 1.5.1
Multi-platform GUI for pass, the standard unix password manager.
Loading...
Searching...
No Matches
usersdialog.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2016 Anne Jan Brouwer
2// SPDX-License-Identifier: GPL-3.0-or-later
3#include "usersdialog.h"
4#include "qtpasssettings.h"
5#include "ui_usersdialog.h"
6#include <QCloseEvent>
7#include <QKeyEvent>
8#include <QMessageBox>
9#include <QRegularExpression>
10#include <QWidget>
11#include <utility>
12
13#ifdef QT_DEBUG
14#include "debughelper.h"
15#endif
20UsersDialog::UsersDialog(QString dir, QWidget *parent)
21 : QDialog(parent), ui(new Ui::UsersDialog), m_dir(std::move(dir)) {
22
23 ui->setupUi(this);
24
25 QList<UserInfo> users = QtPassSettings::getPass()->listKeys();
26 if (users.isEmpty()) {
27 QMessageBox::critical(parent, tr("Keylist missing"),
28 tr("Could not fetch list of available GPG keys"));
29 return;
30 }
31
32 QList<UserInfo> secret_keys = QtPassSettings::getPass()->listKeys("", true);
33 foreach (const UserInfo &sec, secret_keys) {
34 for (auto &user : users) {
35 if (sec.key_id == user.key_id) {
36 user.have_secret = true;
37 }
38 }
39 }
40
41 QList<UserInfo> selected_users;
42 int count = 0;
43
44 QStringList recipients = QtPassSettings::getPass()->getRecipientString(
45 m_dir.isEmpty() ? "" : m_dir, " ", &count);
46 if (!recipients.isEmpty()) {
47 selected_users = QtPassSettings::getPass()->listKeys(recipients);
48 }
49 foreach (const UserInfo &sel, selected_users) {
50 for (auto &user : users) {
51 if (sel.key_id == user.key_id) {
52 user.enabled = true;
53 }
54 }
55 }
56
57 if (count > selected_users.size()) {
58 // Some keys seem missing from keyring, add them separately
59 QStringList recipients = QtPassSettings::getPass()->getRecipientList(
60 m_dir.isEmpty() ? "" : m_dir);
61 foreach (const QString recipient, recipients) {
62 if (QtPassSettings::getPass()->listKeys(recipient).empty()) {
63 UserInfo i;
64 i.enabled = true;
65 i.key_id = recipient;
66 i.name = " ?? " + tr("Key not found in keyring");
67 users.append(i);
68 }
69 }
70 }
71
72 m_userList = users;
73 populateList();
74
75 connect(ui->buttonBox, &QDialogButtonBox::accepted, this,
77 connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
78 connect(ui->listWidget, &QListWidget::itemChanged, this,
79 &UsersDialog::itemChange);
80
81 ui->lineEdit->setClearButtonEnabled(true);
82}
83
88
89Q_DECLARE_METATYPE(UserInfo *)
90
91
94void UsersDialog::accept() {
95 QtPassSettings::getPass()->Init(m_dir, m_userList);
96
97 QDialog::accept();
98}
99
105void UsersDialog::closeEvent(QCloseEvent *event) {
106 // TODO(annejan): save window size or something
107 event->accept();
108}
109
115void UsersDialog::keyPressEvent(QKeyEvent *event) {
116 switch (event->key()) {
117 case Qt::Key_Escape:
118 ui->lineEdit->clear();
119 break;
120 default:
121 break;
122 }
123}
124
129void UsersDialog::itemChange(QListWidgetItem *item) {
130 if (!item) {
131 return;
132 }
133 auto *info = item->data(Qt::UserRole).value<UserInfo *>();
134 if (!info) {
135 return;
136 }
137 info->enabled = item->checkState() == Qt::Checked;
138}
139
145void UsersDialog::populateList(const QString &filter) {
146 QRegularExpression nameFilter(
147 QRegularExpression::wildcardToRegularExpression("*" + filter + "*"),
148 QRegularExpression::CaseInsensitiveOption);
149 ui->listWidget->clear();
150 if (!m_userList.isEmpty()) {
151 for (auto &user : m_userList) {
152 if (filter.isEmpty() || nameFilter.match(user.name).hasMatch()) {
153 if (!user.isValid() && !ui->checkBox->isChecked()) {
154 continue;
155 }
156 if (user.expiry.toSecsSinceEpoch() > 0 &&
157 user.expiry.daysTo(QDateTime::currentDateTime()) > 0 &&
158 !ui->checkBox->isChecked()) {
159 continue;
160 }
161 QString userText = user.name + "\n" + user.key_id;
162 if (user.created.toSecsSinceEpoch() > 0) {
163 userText +=
164 " " + tr("created") + " " +
165 QLocale::system().toString(user.created, QLocale::ShortFormat);
166 }
167 if (user.expiry.toSecsSinceEpoch() > 0) {
168 userText +=
169 " " + tr("expires") + " " +
170 QLocale::system().toString(user.expiry, QLocale::ShortFormat);
171 }
172 auto *item = new QListWidgetItem(userText, ui->listWidget);
173 item->setCheckState(user.enabled ? Qt::Checked : Qt::Unchecked);
174 item->setData(Qt::UserRole, QVariant::fromValue(&user));
175 if (user.have_secret) {
176 // item->setForeground(QColor(32, 74, 135));
177 item->setForeground(Qt::blue);
178 QFont font;
179 font.setFamily(font.defaultFamily());
180 font.setBold(true);
181 item->setFont(font);
182 } else if (!user.isValid()) {
183 item->setBackground(QColor(164, 0, 0));
184 item->setForeground(Qt::white);
185 } else if (user.expiry.toSecsSinceEpoch() > 0 &&
186 user.expiry.daysTo(QDateTime::currentDateTime()) > 0) {
187 item->setForeground(QColor(164, 0, 0));
188 } else if (!user.fullyValid()) {
189 item->setBackground(QColor(164, 80, 0));
190 item->setForeground(Qt::white);
191 }
192
193 ui->listWidget->addItem(item);
194 }
195 }
196 }
197}
198
203void UsersDialog::on_lineEdit_textChanged(const QString &filter) {
204 populateList(filter);
205}
206
210void UsersDialog::on_checkBox_clicked() { populateList(ui->lineEdit->text()); }
static auto getPass() -> Pass *
Handles listing and editing of GPG users.
Definition usersdialog.h:25
~UsersDialog()
UsersDialog::~UsersDialog basic destructor.
void accept()
UsersDialog::accept.
UsersDialog(QString dir, QWidget *parent=nullptr)
UsersDialog::UsersDialog basic constructor.
void closeEvent(QCloseEvent *event)
UsersDialog::closeEvent might have to store size and location if that is wanted.
void keyPressEvent(QKeyEvent *event)
UsersDialog::keyPressEvent clear the lineEdit when escape is pressed. No action for Enter currently.
Stores key info lines including validity, creation date and more.
Definition userinfo.h:13
bool enabled
UserInfo::enabled.
Definition userinfo.h:52
QString key_id
UserInfo::key_id hexadecimal representation.
Definition userinfo.h:38
QString name
UserInfo::name full name.
Definition userinfo.h:34