QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
qgsauthtrustedcasdialog.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsauthtrustedcasdialog.cpp
3 ---------------------
4 begin : May 9, 2015
5 copyright : (C) 2015 by Boundless Spatial, Inc. USA
6 author : Larry Shaffer
7 email : lshaffer at boundlessgeo dot com
8 ***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
18#include "ui_qgsauthtrustedcasdialog.h"
19
20#include <QPushButton>
21
22#include "qgssettings.h"
23#include "qgsapplication.h"
25#include "qgsauthcertutils.h"
26#include "qgsauthguiutils.h"
27#include "qgsauthmanager.h"
28#include "qgslogger.h"
29#include "qgsvariantutils.h"
30
32 const QList<QSslCertificate> &trustedCAs )
33 : QDialog( parent )
34 , mTrustedCAs( trustedCAs )
35{
36 if ( QgsApplication::authManager()->isDisabled() )
37 {
38 mDisabled = true;
39 mAuthNotifyLayout = new QVBoxLayout;
40 this->setLayout( mAuthNotifyLayout );
41 mAuthNotify = new QLabel( QgsApplication::authManager()->disabledMessage(), this );
42 mAuthNotifyLayout->addWidget( mAuthNotify );
43 }
44 else
45 {
46 setupUi( this );
47 connect( btnInfoCa, &QToolButton::clicked, this, &QgsAuthTrustedCAsDialog::btnInfoCa_clicked );
48 connect( btnGroupByOrg, &QToolButton::toggled, this, &QgsAuthTrustedCAsDialog::btnGroupByOrg_toggled );
49
51 this, &QgsAuthTrustedCAsDialog::authMessageOut );
52
53 setupCaCertsTree();
54
55 connect( treeTrustedCAs->selectionModel(), &QItemSelectionModel::selectionChanged,
56 this, &QgsAuthTrustedCAsDialog::selectionChanged );
57
58 connect( treeTrustedCAs, &QTreeWidget::itemDoubleClicked,
59 this, &QgsAuthTrustedCAsDialog::handleDoubleClick );
60
61
62 btnGroupByOrg->setChecked( false );
63 const QVariant sortbyval = QgsApplication::authManager()->authSetting( QStringLiteral( "trustedcasortby" ), QVariant( false ) );
64 if ( !QgsVariantUtils::isNull( sortbyval ) )
65 btnGroupByOrg->setChecked( sortbyval.toBool() );
66
67 populateCaCertsView();
68 checkSelection();
69 }
70}
71
72static void setItemBold_( QTreeWidgetItem *item )
73{
74 item->setFirstColumnSpanned( true );
75 QFont secf( item->font( 0 ) );
76 secf.setBold( true );
77 item->setFont( 0, secf );
78}
79
80void QgsAuthTrustedCAsDialog::setupCaCertsTree()
81{
82 treeTrustedCAs->setColumnCount( 3 );
83 treeTrustedCAs->setHeaderLabels(
84 QStringList() << tr( "Common Name" )
85 << tr( "Serial #" )
86 << tr( "Expiry Date" ) );
87 treeTrustedCAs->setColumnWidth( 0, 300 );
88 treeTrustedCAs->setColumnWidth( 1, 75 );
89
90 // add root section
91 mRootCaSecItem = new QTreeWidgetItem(
92 treeTrustedCAs,
93 QStringList( tr( "Authorities/Issuers" ) ),
94 static_cast<int>( QgsAuthTrustedCAsDialog::Section ) );
95 setItemBold_( mRootCaSecItem );
96 mRootCaSecItem->setFlags( Qt::ItemIsEnabled );
97 mRootCaSecItem->setExpanded( true );
98 treeTrustedCAs->insertTopLevelItem( 0, mRootCaSecItem );
99}
100
101static void removeChildren_( QTreeWidgetItem *item )
102{
103 const auto constTakeChildren = item->takeChildren();
104 for ( QTreeWidgetItem *child : constTakeChildren )
105 {
106 delete child;
107 }
108}
109
110void QgsAuthTrustedCAsDialog::populateCaCertsView()
111{
112 removeChildren_( mRootCaSecItem );
113
114 if ( mTrustedCAs.isEmpty() )
115 {
117 }
118
119 populateCaCertsSection( mRootCaSecItem, mTrustedCAs, QgsAuthTrustedCAsDialog::CaCert );
120}
121
122void QgsAuthTrustedCAsDialog::populateCaCertsSection( QTreeWidgetItem *item, const QList<QSslCertificate> &certs,
123 QgsAuthTrustedCAsDialog::CaType catype )
124{
125 if ( btnGroupByOrg->isChecked() )
126 {
127 appendCertsToGroup( certs, catype, item );
128 }
129 else
130 {
131 appendCertsToItem( certs, catype, item );
132 }
133}
134
135void QgsAuthTrustedCAsDialog::appendCertsToGroup( const QList<QSslCertificate> &certs,
136 QgsAuthTrustedCAsDialog::CaType catype,
137 QTreeWidgetItem *parent )
138{
139 if ( certs.empty() )
140 return;
141
142 if ( !parent )
143 {
144 parent = treeTrustedCAs->currentItem();
145 }
146
147 // TODO: find all organizational name, sort and make subsections
148 const QMap< QString, QList<QSslCertificate> > orgcerts(
150
151 QMap< QString, QList<QSslCertificate> >::const_iterator it = orgcerts.constBegin();
152 for ( ; it != orgcerts.constEnd(); ++it )
153 {
154 QTreeWidgetItem *grpitem( new QTreeWidgetItem( parent,
155 QStringList() << it.key(),
156 static_cast<int>( QgsAuthTrustedCAsDialog::OrgName ) ) );
157 grpitem->setFirstColumnSpanned( true );
158 grpitem->setFlags( Qt::ItemIsEnabled );
159 grpitem->setExpanded( true );
160
161 QBrush orgb( grpitem->foreground( 0 ) );
162 orgb.setColor( QColor::fromRgb( 90, 90, 90 ) );
163 grpitem->setForeground( 0, orgb );
164 QFont grpf( grpitem->font( 0 ) );
165 grpf.setItalic( true );
166 grpitem->setFont( 0, grpf );
167
168 appendCertsToItem( it.value(), catype, grpitem );
169 }
170
171 parent->sortChildren( 0, Qt::AscendingOrder );
172}
173
174void QgsAuthTrustedCAsDialog::appendCertsToItem( const QList<QSslCertificate> &certs,
175 QgsAuthTrustedCAsDialog::CaType catype,
176 QTreeWidgetItem *parent )
177{
178 if ( certs.empty() )
179 return;
180
181 if ( !parent )
182 {
183 parent = treeTrustedCAs->currentItem();
184 }
185
186 const QBrush redb( QgsAuthGuiUtils::redColor() );
187
188 // Columns: Common Name, Serial #, Expiry Date
189 const auto constCerts = certs;
190 for ( const QSslCertificate &cert : constCerts )
191 {
192 const QString id( QgsAuthCertUtils::shaHexForCert( cert ) );
193
194 QStringList coltxts;
195 coltxts << QgsAuthCertUtils::resolvedCertName( cert );
196 coltxts << QString( cert.serialNumber() );
197 coltxts << cert.expiryDate().toString();
198
199 QTreeWidgetItem *item( new QTreeWidgetItem( parent, coltxts, static_cast<int>( catype ) ) );
200
201 item->setIcon( 0, QgsApplication::getThemeIcon( QStringLiteral( "/mIconCertificate.svg" ) ) );
202 if ( !QgsAuthCertUtils::certIsViable( cert ) )
203 {
204 item->setForeground( 2, redb );
205 item->setIcon( 0, QgsApplication::getThemeIcon( QStringLiteral( "/mIconCertificateUntrusted.svg" ) ) );
206 }
207
208 item->setData( 0, Qt::UserRole, id );
209 }
210
211 parent->sortChildren( 0, Qt::AscendingOrder );
212}
213
214void QgsAuthTrustedCAsDialog::showCertInfo( QTreeWidgetItem *item )
215{
216 if ( !item )
217 return;
218
219 const QString digest( item->data( 0, Qt::UserRole ).toString() );
220
221 const QMap<QString, QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > cacertscache(
222 QgsApplication::authManager()->caCertsCache() );
223
224 if ( !cacertscache.contains( digest ) )
225 {
226 QgsDebugError( QStringLiteral( "Certificate Authority not in CA certs cache" ) );
227 return;
228 }
229
230 const QSslCertificate cert( cacertscache.value( digest ).second );
231
232 QgsAuthCertInfoDialog *dlg = new QgsAuthCertInfoDialog( cert, false, this );
233 dlg->setWindowModality( Qt::WindowModal );
234 dlg->resize( 675, 500 );
235 dlg->exec();
236 dlg->deleteLater();
237}
238
239void QgsAuthTrustedCAsDialog::selectionChanged( const QItemSelection &selected, const QItemSelection &deselected )
240{
241 Q_UNUSED( selected )
242 Q_UNUSED( deselected )
243 checkSelection();
244}
245
246void QgsAuthTrustedCAsDialog::checkSelection()
247{
248 bool iscert = false;
249 if ( treeTrustedCAs->selectionModel()->selection().length() > 0 )
250 {
251 QTreeWidgetItem *item( treeTrustedCAs->currentItem() );
252
253 switch ( ( QgsAuthTrustedCAsDialog::CaType )item->type() )
254 {
255 case QgsAuthTrustedCAsDialog::CaCert:
256 iscert = true;
257 break;
258 default:
259 break;
260 }
261 }
262
263 btnInfoCa->setEnabled( iscert );
264}
265
266void QgsAuthTrustedCAsDialog::handleDoubleClick( QTreeWidgetItem *item, int col )
267{
268 Q_UNUSED( col )
269 bool iscert = true;
270
271 switch ( ( QgsAuthTrustedCAsDialog::CaType )item->type() )
272 {
273 case QgsAuthTrustedCAsDialog::Section:
274 iscert = false;
275 break;
276 case QgsAuthTrustedCAsDialog::OrgName:
277 iscert = false;
278 break;
279 default:
280 break;
281 }
282
283 if ( iscert )
284 {
285 showCertInfo( item );
286 }
287}
288
289void QgsAuthTrustedCAsDialog::btnInfoCa_clicked()
290{
291 if ( treeTrustedCAs->selectionModel()->selection().length() > 0 )
292 {
293 QTreeWidgetItem *item( treeTrustedCAs->currentItem() );
294 handleDoubleClick( item, 0 );
295 }
296}
297
298void QgsAuthTrustedCAsDialog::btnGroupByOrg_toggled( bool checked )
299{
300 if ( !QgsApplication::authManager()->storeAuthSetting( QStringLiteral( "trustedcasortby" ), QVariant( checked ) ) )
301 {
302 authMessageOut( QObject::tr( "Could not store sort by preference" ),
303 QObject::tr( "Trusted Authorities/Issuers" ),
305 }
306 populateCaCertsView();
307}
308
309void QgsAuthTrustedCAsDialog::authMessageOut( const QString &message, const QString &authtag, QgsAuthManager::MessageLevel level )
310{
311 const int levelint = static_cast<int>( level );
312 messageBar()->pushMessage( authtag, message, ( Qgis::MessageLevel )levelint, 7 );
313}
314
316{
317 if ( !mDisabled )
318 {
319 treeTrustedCAs->setFocus();
320 }
321 QDialog::showEvent( e );
322}
323
324QgsMessageBar *QgsAuthTrustedCAsDialog::messageBar()
325{
326 return msgBar;
327}
328
329int QgsAuthTrustedCAsDialog::messageTimeout()
330{
331 const QgsSettings settings;
332 return settings.value( QStringLiteral( "qgis/messageTimeout" ), 5 ).toInt();
333}
MessageLevel
Level for messages This will be used both for message log and message bar in application.
Definition: qgis.h:99
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QgsAuthManager * authManager()
Returns the application's authentication manager instance.
Dialog wrapper for widget displaying detailed info on a certificate and its hierarchical trust chain.
static QString resolvedCertName(const QSslCertificate &cert, bool issuer=false)
Gets the general name via RFC 5280 resolution.
static QMap< QString, QList< QSslCertificate > > certsGroupedByOrg(const QList< QSslCertificate > &certs)
Map certificates to their oraganization.
static QString shaHexForCert(const QSslCertificate &cert, bool formatted=false)
Gets the sha1 hash for certificate.
static bool certIsViable(const QSslCertificate &cert)
certIsViable checks for viability errors of cert and whether it is NULL
static QColor redColor()
Red color representing invalid, untrusted, etc. certificate.
MessageLevel
Message log level (mirrors that of QgsMessageLog, so it can also output there)
void messageOut(const QString &message, const QString &tag=QgsAuthManager::AUTH_MAN_TAG, QgsAuthManager::MessageLevel level=QgsAuthManager::INFO) const
Custom logging signal to relay to console output and QgsMessageLog.
QVariant authSetting(const QString &key, const QVariant &defaultValue=QVariant(), bool decrypt=false)
authSetting get an authentication setting (retrieved as string and returned as QVariant( QString ))
const QList< QSslCertificate > trustedCaCerts(bool includeinvalid=false)
trustedCaCerts get list of all trusted CA certificates
void showEvent(QShowEvent *e) override
QgsAuthTrustedCAsDialog(QWidget *parent=nullptr, const QList< QSslCertificate > &trustedCAs=QList< QSslCertificate >())
Construct a dialog that will list the trusted Certificate Authorities.
A bar for displaying non-blocking messages to the user.
Definition: qgsmessagebar.h:61
void pushMessage(const QString &text, Qgis::MessageLevel level=Qgis::MessageLevel::Info, int duration=-1)
A convenience method for pushing a message with the specified text to the bar.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:64
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
#define QgsDebugError(str)
Definition: qgslogger.h:38