QGIS API Documentation  3.2.0-Bonn (bc43194)
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  ( 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  Q_FOREACH ( QTreeWidgetItem *child, item->takeChildren() )
104  {
105  delete child;
106  }
107 }
108 
109 void QgsAuthTrustedCAsDialog::populateCaCertsView()
110 {
111  removeChildren_( mRootCaSecItem );
112 
113  if ( mTrustedCAs.isEmpty() )
114  {
115  mTrustedCAs = QgsApplication::authManager()->trustedCaCerts();
116  }
117 
118  populateCaCertsSection( mRootCaSecItem, mTrustedCAs, QgsAuthTrustedCAsDialog::CaCert );
119 }
120 
121 void QgsAuthTrustedCAsDialog::populateCaCertsSection( QTreeWidgetItem *item, const QList<QSslCertificate> &certs,
122  QgsAuthTrustedCAsDialog::CaType catype )
123 {
124  if ( btnGroupByOrg->isChecked() )
125  {
126  appendCertsToGroup( certs, catype, item );
127  }
128  else
129  {
130  appendCertsToItem( certs, catype, item );
131  }
132 }
133 
134 void QgsAuthTrustedCAsDialog::appendCertsToGroup( const QList<QSslCertificate> &certs,
135  QgsAuthTrustedCAsDialog::CaType catype,
136  QTreeWidgetItem *parent )
137 {
138  if ( certs.empty() )
139  return;
140 
141  if ( !parent )
142  {
143  parent = treeTrustedCAs->currentItem();
144  }
145 
146  // TODO: find all organizational name, sort and make subsections
147  QMap< QString, QList<QSslCertificate> > orgcerts(
149 
150  QMap< QString, QList<QSslCertificate> >::const_iterator it = orgcerts.constBegin();
151  for ( ; it != orgcerts.constEnd(); ++it )
152  {
153  QTreeWidgetItem *grpitem( new QTreeWidgetItem( parent,
154  QStringList() << it.key(),
155  ( int )QgsAuthTrustedCAsDialog::OrgName ) );
156  grpitem->setFirstColumnSpanned( true );
157  grpitem->setFlags( Qt::ItemIsEnabled );
158  grpitem->setExpanded( true );
159 
160  QBrush orgb( grpitem->foreground( 0 ) );
161  orgb.setColor( QColor::fromRgb( 90, 90, 90 ) );
162  grpitem->setForeground( 0, orgb );
163  QFont grpf( grpitem->font( 0 ) );
164  grpf.setItalic( true );
165  grpitem->setFont( 0, grpf );
166 
167  appendCertsToItem( it.value(), catype, grpitem );
168  }
169 
170  parent->sortChildren( 0, Qt::AscendingOrder );
171 }
172 
173 void QgsAuthTrustedCAsDialog::appendCertsToItem( const QList<QSslCertificate> &certs,
174  QgsAuthTrustedCAsDialog::CaType catype,
175  QTreeWidgetItem *parent )
176 {
177  if ( certs.empty() )
178  return;
179 
180  if ( !parent )
181  {
182  parent = treeTrustedCAs->currentItem();
183  }
184 
185  QBrush redb( QgsAuthGuiUtils::redColor() );
186 
187  // Columns: Common Name, Serial #, Expiry Date
188  Q_FOREACH ( const QSslCertificate &cert, certs )
189  {
190  QString id( QgsAuthCertUtils::shaHexForCert( cert ) );
191 
192  QStringList coltxts;
193  coltxts << QgsAuthCertUtils::resolvedCertName( cert );
194  coltxts << QString( cert.serialNumber() );
195  coltxts << cert.expiryDate().toString();
196 
197  QTreeWidgetItem *item( new QTreeWidgetItem( parent, coltxts, ( int )catype ) );
198 
199  item->setIcon( 0, QgsApplication::getThemeIcon( QStringLiteral( "/mIconCertificate.svg" ) ) );
200  if ( !QgsAuthCertUtils::certIsViable( cert ) )
201  {
202  item->setForeground( 2, redb );
203  item->setIcon( 0, QgsApplication::getThemeIcon( QStringLiteral( "/mIconCertificateUntrusted.svg" ) ) );
204  }
205 
206  item->setData( 0, Qt::UserRole, id );
207  }
208 
209  parent->sortChildren( 0, Qt::AscendingOrder );
210 }
211 
212 void QgsAuthTrustedCAsDialog::showCertInfo( QTreeWidgetItem *item )
213 {
214  if ( !item )
215  return;
216 
217  QString digest( item->data( 0, Qt::UserRole ).toString() );
218 
219  QMap<QString, QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > cacertscache(
220  QgsApplication::authManager()->caCertsCache() );
221 
222  if ( !cacertscache.contains( digest ) )
223  {
224  QgsDebugMsg( "Certificate Authority not in CA certs cache" );
225  return;
226  }
227 
228  QSslCertificate cert( cacertscache.value( digest ).second );
229 
230  QgsAuthCertInfoDialog *dlg = new QgsAuthCertInfoDialog( cert, false, this );
231  dlg->setWindowModality( Qt::WindowModal );
232  dlg->resize( 675, 500 );
233  dlg->exec();
234  dlg->deleteLater();
235 }
236 
237 void QgsAuthTrustedCAsDialog::selectionChanged( const QItemSelection &selected, const QItemSelection &deselected )
238 {
239  Q_UNUSED( selected );
240  Q_UNUSED( deselected );
241  checkSelection();
242 }
243 
244 void QgsAuthTrustedCAsDialog::checkSelection()
245 {
246  bool iscert = false;
247  if ( treeTrustedCAs->selectionModel()->selection().length() > 0 )
248  {
249  QTreeWidgetItem *item( treeTrustedCAs->currentItem() );
250 
251  switch ( ( QgsAuthTrustedCAsDialog::CaType )item->type() )
252  {
253  case QgsAuthTrustedCAsDialog::CaCert:
254  iscert = true;
255  break;
256  default:
257  break;
258  }
259  }
260 
261  btnInfoCa->setEnabled( iscert );
262 }
263 
264 void QgsAuthTrustedCAsDialog::handleDoubleClick( QTreeWidgetItem *item, int col )
265 {
266  Q_UNUSED( col );
267  bool iscert = true;
268 
269  switch ( ( QgsAuthTrustedCAsDialog::CaType )item->type() )
270  {
271  case QgsAuthTrustedCAsDialog::Section:
272  iscert = false;
273  break;
274  case QgsAuthTrustedCAsDialog::OrgName:
275  iscert = false;
276  break;
277  default:
278  break;
279  }
280 
281  if ( iscert )
282  {
283  showCertInfo( item );
284  }
285 }
286 
287 void QgsAuthTrustedCAsDialog::btnInfoCa_clicked()
288 {
289  if ( treeTrustedCAs->selectionModel()->selection().length() > 0 )
290  {
291  QTreeWidgetItem *item( treeTrustedCAs->currentItem() );
292  handleDoubleClick( item, 0 );
293  }
294 }
295 
296 void QgsAuthTrustedCAsDialog::btnGroupByOrg_toggled( bool checked )
297 {
298  if ( !QgsApplication::authManager()->storeAuthSetting( QStringLiteral( "trustedcasortby" ), QVariant( checked ) ) )
299  {
300  authMessageOut( QObject::tr( "Could not store sort by preference" ),
301  QObject::tr( "Trusted Authorities/Issuers" ),
303  }
304  populateCaCertsView();
305 }
306 
307 void QgsAuthTrustedCAsDialog::authMessageOut( const QString &message, const QString &authtag, QgsAuthManager::MessageLevel level )
308 {
309  int levelint = ( int )level;
310  messageBar()->pushMessage( authtag, message, ( Qgis::MessageLevel )levelint, 7 );
311 }
312 
314 {
315  if ( !mDisabled )
316  {
317  treeTrustedCAs->setFocus();
318  }
319  QDialog::showEvent( e );
320 }
321 
322 QgsMessageBar *QgsAuthTrustedCAsDialog::messageBar()
323 {
324  return msgBar;
325 }
326 
327 int QgsAuthTrustedCAsDialog::messageTimeout()
328 {
329  QgsSettings settings;
330  return settings.value( QStringLiteral( "qgis/messageTimeout" ), 5 ).toInt();
331 }
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:78
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.