QGIS API Documentation 3.41.0-Master (45a0abf3bec)
Loading...
Searching...
No Matches
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 "moc_qgsauthtrustedcasdialog.cpp"
19#include "ui_qgsauthtrustedcasdialog.h"
20
21#include <QPushButton>
22
23#include "qgssettings.h"
24#include "qgsapplication.h"
26#include "qgsauthcertutils.h"
27#include "qgsauthguiutils.h"
28#include "qgsauthmanager.h"
29#include "qgslogger.h"
30#include "qgsvariantutils.h"
31
33 const QList<QSslCertificate> &trustedCAs )
34 : QDialog( parent )
35 , mTrustedCAs( trustedCAs )
36{
37 if ( QgsApplication::authManager()->isDisabled() )
38 {
39 mDisabled = true;
40 mAuthNotifyLayout = new QVBoxLayout;
41 this->setLayout( mAuthNotifyLayout );
42 mAuthNotify = new QLabel( QgsApplication::authManager()->disabledMessage(), this );
43 mAuthNotifyLayout->addWidget( mAuthNotify );
44 }
45 else
46 {
47 setupUi( this );
48 connect( btnInfoCa, &QToolButton::clicked, this, &QgsAuthTrustedCAsDialog::btnInfoCa_clicked );
49 connect( btnGroupByOrg, &QToolButton::toggled, this, &QgsAuthTrustedCAsDialog::btnGroupByOrg_toggled );
50
52 this, &QgsAuthTrustedCAsDialog::authMessageLog );
53
54 setupCaCertsTree();
55
56 connect( treeTrustedCAs->selectionModel(), &QItemSelectionModel::selectionChanged,
57 this, &QgsAuthTrustedCAsDialog::selectionChanged );
58
59 connect( treeTrustedCAs, &QTreeWidget::itemDoubleClicked,
60 this, &QgsAuthTrustedCAsDialog::handleDoubleClick );
61
62
63 btnGroupByOrg->setChecked( false );
64 const QVariant sortbyval = QgsApplication::authManager()->authSetting( QStringLiteral( "trustedcasortby" ), QVariant( false ) );
65 if ( !QgsVariantUtils::isNull( sortbyval ) )
66 btnGroupByOrg->setChecked( sortbyval.toBool() );
67
68 populateCaCertsView();
69 checkSelection();
70 }
71}
72
73static void setItemBold_( QTreeWidgetItem *item )
74{
75 item->setFirstColumnSpanned( true );
76 QFont secf( item->font( 0 ) );
77 secf.setBold( true );
78 item->setFont( 0, secf );
79}
80
81void QgsAuthTrustedCAsDialog::setupCaCertsTree()
82{
83 treeTrustedCAs->setColumnCount( 3 );
84 treeTrustedCAs->setHeaderLabels(
85 QStringList() << tr( "Common Name" )
86 << tr( "Serial #" )
87 << tr( "Expiry Date" ) );
88 treeTrustedCAs->setColumnWidth( 0, 300 );
89 treeTrustedCAs->setColumnWidth( 1, 75 );
90
91 // add root section
92 mRootCaSecItem = new QTreeWidgetItem(
93 treeTrustedCAs,
94 QStringList( tr( "Authorities/Issuers" ) ),
95 static_cast<int>( QgsAuthTrustedCAsDialog::Section ) );
96 setItemBold_( mRootCaSecItem );
97 mRootCaSecItem->setFlags( Qt::ItemIsEnabled );
98 mRootCaSecItem->setExpanded( true );
99 treeTrustedCAs->insertTopLevelItem( 0, mRootCaSecItem );
100}
101
102static void removeChildren_( QTreeWidgetItem *item )
103{
104 const auto constTakeChildren = item->takeChildren();
105 for ( QTreeWidgetItem *child : constTakeChildren )
106 {
107 delete child;
108 }
109}
110
111void QgsAuthTrustedCAsDialog::populateCaCertsView()
112{
113 removeChildren_( mRootCaSecItem );
114
115 if ( mTrustedCAs.isEmpty() )
116 {
118 }
119
120 populateCaCertsSection( mRootCaSecItem, mTrustedCAs, QgsAuthTrustedCAsDialog::CaCert );
121}
122
123void QgsAuthTrustedCAsDialog::populateCaCertsSection( QTreeWidgetItem *item, const QList<QSslCertificate> &certs,
124 QgsAuthTrustedCAsDialog::CaType catype )
125{
126 if ( btnGroupByOrg->isChecked() )
127 {
128 appendCertsToGroup( certs, catype, item );
129 }
130 else
131 {
132 appendCertsToItem( certs, catype, item );
133 }
134}
135
136void QgsAuthTrustedCAsDialog::appendCertsToGroup( const QList<QSslCertificate> &certs,
137 QgsAuthTrustedCAsDialog::CaType catype,
138 QTreeWidgetItem *parent )
139{
140 if ( certs.empty() )
141 return;
142
143 if ( !parent )
144 {
145 parent = treeTrustedCAs->currentItem();
146 }
147
148 // TODO: find all organizational name, sort and make subsections
149 const QMap< QString, QList<QSslCertificate> > orgcerts(
151
152 QMap< QString, QList<QSslCertificate> >::const_iterator it = orgcerts.constBegin();
153 for ( ; it != orgcerts.constEnd(); ++it )
154 {
155 QTreeWidgetItem *grpitem( new QTreeWidgetItem( parent,
156 QStringList() << it.key(),
157 static_cast<int>( QgsAuthTrustedCAsDialog::OrgName ) ) );
158 grpitem->setFirstColumnSpanned( true );
159 grpitem->setFlags( Qt::ItemIsEnabled );
160 grpitem->setExpanded( true );
161
162 QBrush orgb( grpitem->foreground( 0 ) );
163 orgb.setColor( QColor::fromRgb( 90, 90, 90 ) );
164 grpitem->setForeground( 0, orgb );
165 QFont grpf( grpitem->font( 0 ) );
166 grpf.setItalic( true );
167 grpitem->setFont( 0, grpf );
168
169 appendCertsToItem( it.value(), catype, grpitem );
170 }
171
172 parent->sortChildren( 0, Qt::AscendingOrder );
173}
174
175void QgsAuthTrustedCAsDialog::appendCertsToItem( const QList<QSslCertificate> &certs,
176 QgsAuthTrustedCAsDialog::CaType catype,
177 QTreeWidgetItem *parent )
178{
179 if ( certs.empty() )
180 return;
181
182 if ( !parent )
183 {
184 parent = treeTrustedCAs->currentItem();
185 }
186
187 const QBrush redb( QgsAuthGuiUtils::redColor() );
188
189 // Columns: Common Name, Serial #, Expiry Date
190 const auto constCerts = certs;
191 for ( const QSslCertificate &cert : constCerts )
192 {
193 const QString id( QgsAuthCertUtils::shaHexForCert( cert ) );
194
195 QStringList coltxts;
196 coltxts << QgsAuthCertUtils::resolvedCertName( cert );
197 coltxts << QString( cert.serialNumber() );
198 coltxts << cert.expiryDate().toString();
199
200 QTreeWidgetItem *item( new QTreeWidgetItem( parent, coltxts, static_cast<int>( catype ) ) );
201
202 item->setIcon( 0, QgsApplication::getThemeIcon( QStringLiteral( "/mIconCertificate.svg" ) ) );
203 if ( !QgsAuthCertUtils::certIsViable( cert ) )
204 {
205 item->setForeground( 2, redb );
206 item->setIcon( 0, QgsApplication::getThemeIcon( QStringLiteral( "/mIconCertificateUntrusted.svg" ) ) );
207 }
208
209 item->setData( 0, Qt::UserRole, id );
210 }
211
212 parent->sortChildren( 0, Qt::AscendingOrder );
213}
214
215void QgsAuthTrustedCAsDialog::showCertInfo( QTreeWidgetItem *item )
216{
217 if ( !item )
218 return;
219
220 const QString digest( item->data( 0, Qt::UserRole ).toString() );
221
222 const QMap<QString, QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > cacertscache(
223 QgsApplication::authManager()->caCertsCache() );
224
225 if ( !cacertscache.contains( digest ) )
226 {
227 QgsDebugError( QStringLiteral( "Certificate Authority not in CA certs cache" ) );
228 return;
229 }
230
231 const QSslCertificate cert( cacertscache.value( digest ).second );
232
233 QgsAuthCertInfoDialog *dlg = new QgsAuthCertInfoDialog( cert, false, this );
234 dlg->setWindowModality( Qt::WindowModal );
235 dlg->resize( 675, 500 );
236 dlg->exec();
237 dlg->deleteLater();
238}
239
240void QgsAuthTrustedCAsDialog::selectionChanged( const QItemSelection &selected, const QItemSelection &deselected )
241{
242 Q_UNUSED( selected )
243 Q_UNUSED( deselected )
244 checkSelection();
245}
246
247void QgsAuthTrustedCAsDialog::checkSelection()
248{
249 bool iscert = false;
250 if ( treeTrustedCAs->selectionModel()->selection().length() > 0 )
251 {
252 QTreeWidgetItem *item( treeTrustedCAs->currentItem() );
253
254 switch ( ( QgsAuthTrustedCAsDialog::CaType )item->type() )
255 {
256 case QgsAuthTrustedCAsDialog::CaCert:
257 iscert = true;
258 break;
259 default:
260 break;
261 }
262 }
263
264 btnInfoCa->setEnabled( iscert );
265}
266
267void QgsAuthTrustedCAsDialog::handleDoubleClick( QTreeWidgetItem *item, int col )
268{
269 Q_UNUSED( col )
270 bool iscert = true;
271
272 switch ( ( QgsAuthTrustedCAsDialog::CaType )item->type() )
273 {
274 case QgsAuthTrustedCAsDialog::Section:
275 iscert = false;
276 break;
277 case QgsAuthTrustedCAsDialog::OrgName:
278 iscert = false;
279 break;
280 default:
281 break;
282 }
283
284 if ( iscert )
285 {
286 showCertInfo( item );
287 }
288}
289
290void QgsAuthTrustedCAsDialog::btnInfoCa_clicked()
291{
292 if ( treeTrustedCAs->selectionModel()->selection().length() > 0 )
293 {
294 QTreeWidgetItem *item( treeTrustedCAs->currentItem() );
295 handleDoubleClick( item, 0 );
296 }
297}
298
299void QgsAuthTrustedCAsDialog::btnGroupByOrg_toggled( bool checked )
300{
301 if ( !QgsApplication::authManager()->storeAuthSetting( QStringLiteral( "trustedcasortby" ), QVariant( checked ) ) )
302 {
303 authMessageLog( QObject::tr( "Could not store sort by preference" ),
304 QObject::tr( "Trusted Authorities/Issuers" ),
306 }
307 populateCaCertsView();
308}
309
310void QgsAuthTrustedCAsDialog::authMessageLog( const QString &message, const QString &authtag, Qgis::MessageLevel level )
311{
312 messageBar()->pushMessage( authtag, message, level, 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:154
@ Warning
Warning message.
Definition qgis.h:156
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.
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 messageLog(const QString &message, const QString &tag=QgsAuthManager::AUTH_MAN_TAG, Qgis::MessageLevel level=Qgis::MessageLevel::Info) const
Custom logging signal to relay to console output and QgsMessageLog.
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.
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