QGIS API Documentation 3.40.0-Bratislava (b56115d8743)
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 "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::authMessageLog );
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 authMessageLog( QObject::tr( "Could not store sort by preference" ),
303 QObject::tr( "Trusted Authorities/Issuers" ),
305 }
306 populateCaCertsView();
307}
308
309void QgsAuthTrustedCAsDialog::authMessageLog( const QString &message, const QString &authtag, Qgis::MessageLevel level )
310{
311 messageBar()->pushMessage( authtag, message, level, 7 );
312}
313
315{
316 if ( !mDisabled )
317 {
318 treeTrustedCAs->setFocus();
319 }
320 QDialog::showEvent( e );
321}
322
323QgsMessageBar *QgsAuthTrustedCAsDialog::messageBar()
324{
325 return msgBar;
326}
327
328int QgsAuthTrustedCAsDialog::messageTimeout()
329{
330 const QgsSettings settings;
331 return settings.value( QStringLiteral( "qgis/messageTimeout" ), 5 ).toInt();
332}
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