QGIS API Documentation  3.8.0-Zanzibar (11aff65)
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"
24 #include "qgsauthcertificateinfo.h"
25 #include "qgsauthcertutils.h"
26 #include "qgsauthguiutils.h"
27 #include "qgsauthmanager.h"
28 #include "qgslogger.h"
29 
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  QVariant sortbyval = QgsApplication::authManager()->authSetting( QStringLiteral( "trustedcasortby" ), QVariant( false ) );
64  if ( !sortbyval.isNull() )
65  btnGroupByOrg->setChecked( sortbyval.toBool() );
66 
67  populateCaCertsView();
68  checkSelection();
69  }
70 }
71 
72 static 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 
80 void 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 
101 static void removeChildren_( QTreeWidgetItem *item )
102 {
103  const auto constTakeChildren = item->takeChildren();
104  for ( QTreeWidgetItem *child : constTakeChildren )
105  {
106  delete child;
107  }
108 }
109 
110 void QgsAuthTrustedCAsDialog::populateCaCertsView()
111 {
112  removeChildren_( mRootCaSecItem );
113 
114  if ( mTrustedCAs.isEmpty() )
115  {
116  mTrustedCAs = QgsApplication::authManager()->trustedCaCerts();
117  }
118 
119  populateCaCertsSection( mRootCaSecItem, mTrustedCAs, QgsAuthTrustedCAsDialog::CaCert );
120 }
121 
122 void 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 
135 void 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  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 
174 void 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  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  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 
214 void QgsAuthTrustedCAsDialog::showCertInfo( QTreeWidgetItem *item )
215 {
216  if ( !item )
217  return;
218 
219  QString digest( item->data( 0, Qt::UserRole ).toString() );
220 
221  QMap<QString, QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > cacertscache(
222  QgsApplication::authManager()->caCertsCache() );
223 
224  if ( !cacertscache.contains( digest ) )
225  {
226  QgsDebugMsg( QStringLiteral( "Certificate Authority not in CA certs cache" ) );
227  return;
228  }
229 
230  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 
239 void QgsAuthTrustedCAsDialog::selectionChanged( const QItemSelection &selected, const QItemSelection &deselected )
240 {
241  Q_UNUSED( selected )
242  Q_UNUSED( deselected )
243  checkSelection();
244 }
245 
246 void 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 
266 void 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 
289 void QgsAuthTrustedCAsDialog::btnInfoCa_clicked()
290 {
291  if ( treeTrustedCAs->selectionModel()->selection().length() > 0 )
292  {
293  QTreeWidgetItem *item( treeTrustedCAs->currentItem() );
294  handleDoubleClick( item, 0 );
295  }
296 }
297 
298 void 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 
309 void QgsAuthTrustedCAsDialog::authMessageOut( const QString &message, const QString &authtag, QgsAuthManager::MessageLevel level )
310 {
311  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 
324 QgsMessageBar *QgsAuthTrustedCAsDialog::messageBar()
325 {
326  return msgBar;
327 }
328 
329 int QgsAuthTrustedCAsDialog::messageTimeout()
330 {
331  QgsSettings settings;
332  return settings.value( QStringLiteral( "qgis/messageTimeout" ), 5 ).toInt();
333 }
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.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:58
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
A bar for displaying non-blocking messages to the user.
Definition: qgsmessagebar.h:45
void showEvent(QShowEvent *e) override
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
MessageLevel
Level for messages This will be used both for message log and message bar in application.
Definition: qgis.h:66
MessageLevel
Message log level (mirrors that of QgsMessageLog, so it can also output there)
const QList< QSslCertificate > trustedCaCerts(bool includeinvalid=false)
trustedCaCerts get list of all trusted CA certificates
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.
Dialog wrapper for widget displaying detailed info on a certificate and its hierarchical trust chain...
QgsAuthTrustedCAsDialog(QWidget *parent=nullptr, const QList< QSslCertificate > &trustedCAs=QList< QSslCertificate >())
Construct a dialog that will list the trusted Certificate Authorities.
void pushMessage(const QString &text, Qgis::MessageLevel level=Qgis::Info, int duration=5)
convenience method for pushing a message to the bar
Definition: qgsmessagebar.h:88
static QString shaHexForCert(const QSslCertificate &cert, bool formatted=false)
Gets the sha1 hash for certificate.
static QgsAuthManager * authManager()
Returns the application&#39;s authentication manager instance.
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 )) ...
static QMap< QString, QList< QSslCertificate > > certsGroupedByOrg(const QList< QSslCertificate > &certs)
Map certificates to their oraganization.
static QString resolvedCertName(const QSslCertificate &cert, bool issuer=false)
Gets the general name via RFC 5280 resolution.