Line data Source code
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
16 : /**
17 : * @brief UsersDialog::UsersDialog basic constructor
18 : * @param parent
19 : */
20 0 : UsersDialog::UsersDialog(QString dir, QWidget *parent)
21 0 : : QDialog(parent), ui(new Ui::UsersDialog), m_dir(std::move(dir)) {
22 :
23 0 : ui->setupUi(this);
24 :
25 0 : QList<UserInfo> users = QtPassSettings::getPass()->listKeys();
26 0 : if (users.isEmpty()) {
27 0 : QMessageBox::critical(parent, tr("Keylist missing"),
28 0 : tr("Could not fetch list of available GPG keys"));
29 : return;
30 : }
31 :
32 0 : QList<UserInfo> secret_keys = QtPassSettings::getPass()->listKeys("", true);
33 0 : foreach (const UserInfo &sec, secret_keys) {
34 0 : for (auto &user : users) {
35 0 : if (sec.key_id == user.key_id) {
36 0 : user.have_secret = true;
37 : }
38 : }
39 : }
40 :
41 0 : QList<UserInfo> selected_users;
42 0 : int count = 0;
43 :
44 0 : QStringList recipients = QtPassSettings::getPass()->getRecipientString(
45 0 : m_dir.isEmpty() ? "" : m_dir, " ", &count);
46 0 : if (!recipients.isEmpty()) {
47 0 : selected_users = QtPassSettings::getPass()->listKeys(recipients);
48 : }
49 0 : foreach (const UserInfo &sel, selected_users) {
50 0 : for (auto &user : users) {
51 0 : if (sel.key_id == user.key_id) {
52 0 : user.enabled = true;
53 : }
54 : }
55 : }
56 :
57 0 : if (count > selected_users.size()) {
58 : // Some keys seem missing from keyring, add them separately
59 0 : QStringList recipients = QtPassSettings::getPass()->getRecipientList(
60 0 : m_dir.isEmpty() ? "" : m_dir);
61 0 : foreach (const QString recipient, recipients) {
62 0 : if (QtPassSettings::getPass()->listKeys(recipient).empty()) {
63 0 : UserInfo i;
64 0 : i.enabled = true;
65 0 : i.key_id = recipient;
66 0 : i.name = " ?? " + tr("Key not found in keyring");
67 : users.append(i);
68 0 : }
69 : }
70 : }
71 :
72 : m_userList = users;
73 0 : populateList();
74 :
75 0 : connect(ui->buttonBox, &QDialogButtonBox::accepted, this,
76 0 : &UsersDialog::accept);
77 0 : connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
78 0 : connect(ui->listWidget, &QListWidget::itemChanged, this,
79 0 : &UsersDialog::itemChange);
80 :
81 0 : ui->lineEdit->setClearButtonEnabled(true);
82 0 : }
83 :
84 : /**
85 : * @brief UsersDialog::~UsersDialog basic destructor.
86 : */
87 0 : UsersDialog::~UsersDialog() { delete ui; }
88 :
89 0 : Q_DECLARE_METATYPE(UserInfo *)
90 :
91 : /**
92 : * @brief UsersDialog::accept
93 : */
94 0 : void UsersDialog::accept() {
95 0 : QtPassSettings::getPass()->Init(m_dir, m_userList);
96 :
97 0 : QDialog::accept();
98 0 : }
99 :
100 : /**
101 : * @brief UsersDialog::closeEvent might have to store size and location if that
102 : * is wanted.
103 : * @param event
104 : */
105 0 : void UsersDialog::closeEvent(QCloseEvent *event) {
106 : // TODO(annejan): save window size or something
107 : event->accept();
108 0 : }
109 :
110 : /**
111 : * @brief UsersDialog::keyPressEvent clear the lineEdit when escape is pressed.
112 : * No action for Enter currently.
113 : * @param event
114 : */
115 0 : void UsersDialog::keyPressEvent(QKeyEvent *event) {
116 0 : switch (event->key()) {
117 0 : case Qt::Key_Escape:
118 0 : ui->lineEdit->clear();
119 0 : break;
120 : default:
121 : break;
122 : }
123 0 : }
124 :
125 : /**
126 : * @brief UsersDialog::itemChange update the item information.
127 : * @param item
128 : */
129 0 : void UsersDialog::itemChange(QListWidgetItem *item) {
130 0 : if (!item) {
131 : return;
132 : }
133 0 : auto *info = item->data(Qt::UserRole).value<UserInfo *>();
134 0 : if (!info) {
135 : return;
136 : }
137 0 : info->enabled = item->checkState() == Qt::Checked;
138 : }
139 :
140 : /**
141 : * @brief UsersDialog::populateList update the view based on filter options
142 : * (such as searching).
143 : * @param filter
144 : */
145 0 : void UsersDialog::populateList(const QString &filter) {
146 : QRegularExpression nameFilter(
147 0 : QRegularExpression::wildcardToRegularExpression("*" + filter + "*"),
148 0 : QRegularExpression::CaseInsensitiveOption);
149 0 : ui->listWidget->clear();
150 0 : if (!m_userList.isEmpty()) {
151 0 : for (auto &user : m_userList) {
152 0 : if (filter.isEmpty() || nameFilter.match(user.name).hasMatch()) {
153 0 : if (!user.isValid() && !ui->checkBox->isChecked()) {
154 0 : continue;
155 : }
156 0 : if (user.expiry.toSecsSinceEpoch() > 0 &&
157 0 : user.expiry.daysTo(QDateTime::currentDateTime()) > 0 &&
158 0 : !ui->checkBox->isChecked()) {
159 0 : continue;
160 : }
161 0 : QString userText = user.name + "\n" + user.key_id;
162 0 : if (user.created.toSecsSinceEpoch() > 0) {
163 : userText +=
164 0 : " " + tr("created") + " " +
165 0 : QLocale::system().toString(user.created, QLocale::ShortFormat);
166 : }
167 0 : if (user.expiry.toSecsSinceEpoch() > 0) {
168 : userText +=
169 0 : " " + tr("expires") + " " +
170 0 : QLocale::system().toString(user.expiry, QLocale::ShortFormat);
171 : }
172 0 : auto *item = new QListWidgetItem(userText, ui->listWidget);
173 0 : item->setCheckState(user.enabled ? Qt::Checked : Qt::Unchecked);
174 0 : item->setData(Qt::UserRole, QVariant::fromValue(&user));
175 0 : if (user.have_secret) {
176 : // item->setForeground(QColor(32, 74, 135));
177 0 : item->setForeground(Qt::blue);
178 0 : QFont font;
179 0 : font.setFamily(font.defaultFamily());
180 : font.setBold(true);
181 0 : item->setFont(font);
182 0 : } else if (!user.isValid()) {
183 0 : item->setBackground(QColor(164, 0, 0));
184 0 : item->setForeground(Qt::white);
185 0 : } else if (user.expiry.toSecsSinceEpoch() > 0 &&
186 0 : user.expiry.daysTo(QDateTime::currentDateTime()) > 0) {
187 0 : item->setForeground(QColor(164, 0, 0));
188 0 : } else if (!user.fullyValid()) {
189 0 : item->setBackground(QColor(164, 80, 0));
190 0 : item->setForeground(Qt::white);
191 : }
192 :
193 0 : ui->listWidget->addItem(item);
194 : }
195 : }
196 : }
197 0 : }
198 :
199 : /**
200 : * @brief UsersDialog::on_lineEdit_textChanged typing in the searchbox.
201 : * @param filter
202 : */
203 0 : void UsersDialog::on_lineEdit_textChanged(const QString &filter) {
204 0 : populateList(filter);
205 0 : }
206 :
207 : /**
208 : * @brief UsersDialog::on_checkBox_clicked filtering.
209 : */
210 0 : void UsersDialog::on_checkBox_clicked() { populateList(ui->lineEdit->text()); }
|