QGIS API Documentation 3.99.0-Master (752b475928d)
Loading...
Searching...
No Matches
qgsauthserverseditor.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsauthserverseditor.cpp
3 ---------------------
4 begin : April 26, 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
17#include "ui_qgsauthserverseditor.h"
19
20#include "qgsapplication.h"
22#include "qgsauthcertutils.h"
23#include "qgsauthguiutils.h"
24#include "qgsauthmanager.h"
26#include "qgslogger.h"
27#include "qgssettings.h"
28#include "qgsvariantutils.h"
29
30#include <QMenu>
31#include <QMessageBox>
32
33#include "moc_qgsauthserverseditor.cpp"
34
36 : QWidget( parent )
37{
38 if ( QgsApplication::authManager()->isDisabled() )
39 {
40 mDisabled = true;
41 mAuthNotifyLayout = new QVBoxLayout;
42 this->setLayout( mAuthNotifyLayout );
43 mAuthNotify = new QLabel( QgsApplication::authManager()->disabledMessage(), this );
44 mAuthNotifyLayout->addWidget( mAuthNotify );
45 }
46 else
47 {
48 setupUi( this );
49 connect( btnAddServer, &QToolButton::clicked, this, &QgsAuthServersEditor::btnAddServer_clicked );
50 connect( btnRemoveServer, &QToolButton::clicked, this, &QgsAuthServersEditor::btnRemoveServer_clicked );
51 connect( btnEditServer, &QToolButton::clicked, this, &QgsAuthServersEditor::btnEditServer_clicked );
52 connect( btnGroupByOrg, &QToolButton::toggled, this, &QgsAuthServersEditor::btnGroupByOrg_toggled );
53
54 connect( QgsApplication::authManager(), &QgsAuthManager::messageLog, this, &QgsAuthServersEditor::authMessageLog );
55
56 connect( QgsApplication::authManager(), &QgsAuthManager::authDatabaseChanged, this, &QgsAuthServersEditor::refreshSslConfigsView );
57
58 setupSslConfigsTree();
59
60 connect( treeServerConfigs->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsAuthServersEditor::selectionChanged );
61
62 connect( treeServerConfigs, &QTreeWidget::itemDoubleClicked, this, &QgsAuthServersEditor::handleDoubleClick );
63
64 connect( btnViewRefresh, &QAbstractButton::clicked, this, &QgsAuthServersEditor::refreshSslConfigsView );
65
66 btnGroupByOrg->setChecked( false );
67 const QVariant sortbyval = QgsApplication::authManager()->authSetting( QStringLiteral( "serverssortby" ), QVariant( false ) );
68 if ( !QgsVariantUtils::isNull( sortbyval ) )
69 btnGroupByOrg->setChecked( sortbyval.toBool() );
70
71 populateSslConfigsView();
72 checkSelection();
73 }
74}
75
76void QgsAuthServersEditor::setupSslConfigsTree()
77{
78 treeServerConfigs->setColumnCount( 3 );
79 treeServerConfigs->setHeaderLabels(
80 QStringList() << tr( "Common Name" )
81 << tr( "Host" )
82 << tr( "Expiry Date" )
83 );
84 treeServerConfigs->setColumnWidth( 0, 275 );
85 treeServerConfigs->setColumnWidth( 1, 200 );
86
87 // add root sections
88 mRootSslConfigItem = new QTreeWidgetItem(
89 treeServerConfigs,
90 QStringList( tr( "SSL Server Configurations" ) ),
91 static_cast<int>( QgsAuthServersEditor::Section )
92 );
93 QgsAuthGuiUtils::setItemBold( mRootSslConfigItem );
94 mRootSslConfigItem->setFlags( Qt::ItemIsEnabled );
95 mRootSslConfigItem->setExpanded( true );
96 treeServerConfigs->insertTopLevelItem( 0, mRootSslConfigItem );
97}
98
99void QgsAuthServersEditor::populateSslConfigsView()
100{
101 QgsAuthGuiUtils::removeChildren( mRootSslConfigItem );
102
103 populateSslConfigsSection( mRootSslConfigItem, QgsApplication::authManager()->sslCertCustomConfigs(), QgsAuthServersEditor::ServerConfig );
104}
105
106void QgsAuthServersEditor::refreshSslConfigsView()
107{
108 populateSslConfigsView();
109}
110
111void QgsAuthServersEditor::populateSslConfigsSection( QTreeWidgetItem *item, const QList<QgsAuthConfigSslServer> &configs, QgsAuthServersEditor::ConfigType conftype )
112{
113 if ( btnGroupByOrg->isChecked() )
114 {
115 appendSslConfigsToGroup( configs, conftype, item );
116 }
117 else
118 {
119 appendSslConfigsToItem( configs, conftype, item );
120 }
121}
122
123void QgsAuthServersEditor::appendSslConfigsToGroup( const QList<QgsAuthConfigSslServer> &configs, QgsAuthServersEditor::ConfigType conftype, QTreeWidgetItem *parent )
124{
125 if ( configs.empty() )
126 return;
127
128 if ( !parent )
129 {
130 parent = treeServerConfigs->currentItem();
131 }
132
133 // TODO: find all organizational name, sort and make subsections
134 const QMap<QString, QList<QgsAuthConfigSslServer>> orgconfigs(
136 );
137
138 QMap<QString, QList<QgsAuthConfigSslServer>>::const_iterator it = orgconfigs.constBegin();
139 for ( ; it != orgconfigs.constEnd(); ++it )
140 {
141 QTreeWidgetItem *grpitem( new QTreeWidgetItem( parent, QStringList() << it.key(), static_cast<int>( QgsAuthServersEditor::OrgName ) ) );
142 grpitem->setFirstColumnSpanned( true );
143 grpitem->setFlags( Qt::ItemIsEnabled );
144 grpitem->setExpanded( true );
145
146 QBrush orgb( grpitem->foreground( 0 ) );
147 orgb.setColor( QColor::fromRgb( 90, 90, 90 ) );
148 grpitem->setForeground( 0, orgb );
149 QFont grpf( grpitem->font( 0 ) );
150 grpf.setItalic( true );
151 grpitem->setFont( 0, grpf );
152
153 appendSslConfigsToItem( it.value(), conftype, grpitem );
154 }
155
156 parent->sortChildren( 0, Qt::AscendingOrder );
157}
158
159void QgsAuthServersEditor::appendSslConfigsToItem( const QList<QgsAuthConfigSslServer> &configs, QgsAuthServersEditor::ConfigType conftype, QTreeWidgetItem *parent )
160{
161 if ( configs.empty() )
162 return;
163
164 if ( !parent )
165 {
166 parent = treeServerConfigs->currentItem();
167 }
168
169 const QBrush redb( QgsAuthGuiUtils::redColor() );
170
171 // Columns: Common Name, Host, Expiry Date
172 const auto constConfigs = configs;
173 for ( const QgsAuthConfigSslServer &config : constConfigs )
174 {
175 const QSslCertificate cert( config.sslCertificate() );
176 const QString id( QgsAuthCertUtils::shaHexForCert( cert ) );
177
178 QStringList coltxts;
179 coltxts << QgsAuthCertUtils::resolvedCertName( cert );
180 coltxts << QString( config.sslHostPort() );
181 coltxts << cert.expiryDate().toString();
182
183 QTreeWidgetItem *item( new QTreeWidgetItem( parent, coltxts, static_cast<int>( conftype ) ) );
184
185 item->setIcon( 0, QgsApplication::getThemeIcon( QStringLiteral( "/mIconCertificate.svg" ) ) );
186 if ( !QgsAuthCertUtils::certIsViable( cert ) )
187 {
188 item->setForeground( 2, redb );
189 item->setIcon( 0, QgsApplication::getThemeIcon( QStringLiteral( "/mIconCertificateUntrusted.svg" ) ) );
190 }
191
192 item->setData( 0, Qt::UserRole, id );
193 }
194
195 parent->sortChildren( 0, Qt::AscendingOrder );
196}
197
198void QgsAuthServersEditor::selectionChanged( const QItemSelection &selected, const QItemSelection &deselected )
199{
200 Q_UNUSED( selected )
201 Q_UNUSED( deselected )
202 checkSelection();
203}
204
205void QgsAuthServersEditor::checkSelection()
206{
207 bool isconfig = false;
208 if ( treeServerConfigs->selectionModel()->selection().length() > 0 )
209 {
210 QTreeWidgetItem *item( treeServerConfigs->currentItem() );
211
212 switch ( ( QgsAuthServersEditor::ConfigType ) item->type() )
213 {
214 case QgsAuthServersEditor::ServerConfig:
215 isconfig = true;
216 break;
217 default:
218 break;
219 }
220 }
221
222 btnRemoveServer->setEnabled( isconfig );
223 btnEditServer->setEnabled( isconfig );
224}
225
226void QgsAuthServersEditor::handleDoubleClick( QTreeWidgetItem *item, int col )
227{
228 Q_UNUSED( col )
229 bool isconfig = true;
230
231 switch ( ( QgsAuthServersEditor::ConfigType ) item->type() )
232 {
233 case QgsAuthServersEditor::Section:
234 isconfig = false;
235 break;
236 case QgsAuthServersEditor::OrgName:
237 isconfig = false;
238 break;
239 default:
240 break;
241 }
242
243 if ( isconfig )
244 {
245 btnEditServer_clicked();
246 }
247}
248
249void QgsAuthServersEditor::btnAddServer_clicked()
250{
251 QgsAuthSslImportDialog *dlg = new QgsAuthSslImportDialog( this );
252 dlg->setWindowModality( Qt::WindowModal );
253 dlg->resize( 580, 512 );
254 if ( dlg->exec() )
255 {
256 refreshSslConfigsView();
257 }
258 dlg->deleteLater();
259}
260
261void QgsAuthServersEditor::btnRemoveServer_clicked()
262{
263 QTreeWidgetItem *item( treeServerConfigs->currentItem() );
264
265 if ( !item )
266 {
267 QgsDebugMsgLevel( QStringLiteral( "Current tree widget item not set" ), 2 );
268 return;
269 }
270
271 const QString digest( item->data( 0, Qt::UserRole ).toString() );
272 const QString hostport( item->text( 1 ) );
273
274 if ( digest.isEmpty() )
275 {
276 messageBar()->pushMessage( tr( "SSL custom config id missing" ), Qgis::MessageLevel::Warning );
277 return;
278 }
279 if ( hostport.isEmpty() )
280 {
281 messageBar()->pushMessage( tr( "SSL custom config host:port missing" ), Qgis::MessageLevel::Warning );
282 return;
283 }
284
285 if ( !QgsApplication::authManager()->existsSslCertCustomConfig( digest, hostport ) )
286 {
287 QgsDebugError( QStringLiteral( "SSL custom config does not exist in database for host:port, id %1:" )
288 .arg( hostport, digest ) );
289 return;
290 }
291
292 if ( QMessageBox::warning(
293 this, tr( "Remove SSL Custom Configuration" ),
294 tr( "Are you sure you want to remove the selected "
295 "SSL custom configuration from the database?\n\n"
296 "Operation can NOT be undone!" ),
297 QMessageBox::Ok | QMessageBox::Cancel,
298 QMessageBox::Cancel
299 )
300 == QMessageBox::Cancel )
301 {
302 return;
303 }
304
305 if ( !QgsApplication::authManager()->removeSslCertCustomConfig( digest, hostport ) )
306 {
307 messageBar()->pushMessage( tr( "ERROR removing SSL custom config from authentication storage for host:port, id %1:" ).arg( hostport, digest ), Qgis::MessageLevel::Critical );
308 return;
309 }
310
311 item->parent()->removeChild( item );
312 delete item;
313}
314
315void QgsAuthServersEditor::btnEditServer_clicked()
316{
317 QTreeWidgetItem *item( treeServerConfigs->currentItem() );
318
319 if ( !item )
320 {
321 QgsDebugMsgLevel( QStringLiteral( "Current tree widget item not set" ), 2 );
322 return;
323 }
324
325 const QString digest( item->data( 0, Qt::UserRole ).toString() );
326 const QString hostport( item->text( 1 ) );
327
328 if ( digest.isEmpty() )
329 {
330 messageBar()->pushMessage( tr( "SSL custom config id missing." ), Qgis::MessageLevel::Warning );
331 return;
332 }
333 if ( hostport.isEmpty() )
334 {
335 messageBar()->pushMessage( tr( "SSL custom config host:port missing." ), Qgis::MessageLevel::Warning );
336 return;
337 }
338
339 if ( !QgsApplication::authManager()->existsSslCertCustomConfig( digest, hostport ) )
340 {
341 QgsDebugError( QStringLiteral( "SSL custom config does not exist in database" ) );
342 return;
343 }
344
345 const QgsAuthConfigSslServer config( QgsApplication::authManager()->sslCertCustomConfig( digest, hostport ) );
346 const QSslCertificate cert( config.sslCertificate() );
347
348 QgsAuthSslConfigDialog *dlg = new QgsAuthSslConfigDialog( this, cert, hostport );
350 dlg->setWindowModality( Qt::WindowModal );
351 dlg->resize( 500, 500 );
352 if ( dlg->exec() )
353 {
354 refreshSslConfigsView();
355 }
356 dlg->deleteLater();
357}
358
359void QgsAuthServersEditor::btnGroupByOrg_toggled( bool checked )
360{
361 if ( !QgsApplication::authManager()->storeAuthSetting( QStringLiteral( "serverssortby" ), QVariant( checked ) ) )
362 {
363 authMessageLog( QObject::tr( "Could not store sort by preference." ), QObject::tr( "Authentication SSL Configs" ), Qgis::MessageLevel::Warning );
364 }
365 populateSslConfigsView();
366}
367
368void QgsAuthServersEditor::authMessageLog( const QString &message, const QString &authtag, Qgis::MessageLevel level )
369{
370 messageBar()->pushMessage( authtag, message, level, 7 );
371}
372
374{
375 if ( !mDisabled )
376 {
377 treeServerConfigs->setFocus();
378 }
379 QWidget::showEvent( e );
380}
381
382QgsMessageBar *QgsAuthServersEditor::messageBar()
383{
384 return msgBar;
385}
386
387int QgsAuthServersEditor::messageTimeout()
388{
389 const QgsSettings settings;
390 return settings.value( QStringLiteral( "qgis/messageTimeout" ), 5 ).toInt();
391}
MessageLevel
Level for messages This will be used both for message log and message bar in application.
Definition qgis.h:156
@ Warning
Warning message.
Definition qgis.h:158
@ Critical
Critical/error message.
Definition qgis.h:159
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.
static QString resolvedCertName(const QSslCertificate &cert, bool issuer=false)
Gets the general name via RFC 5280 resolution.
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 QMap< QString, QList< QgsAuthConfigSslServer > > sslConfigsGroupedByOrg(const QList< QgsAuthConfigSslServer > &configs)
Map SSL custom configs' certificates to their oraganization.
static void setItemBold(QTreeWidgetItem *item)
Call setFirstColumnSpanned(true) on the item and make its font bold.
static void removeChildren(QTreeWidgetItem *item)
Remove the children of the passed item.
static QColor redColor()
Red color representing invalid, untrusted, etc. certificate.
void authDatabaseChanged()
Emitted when the authentication db is significantly changed, e.g. large record removal,...
QVariant authSetting(const QString &key, const QVariant &defaultValue=QVariant(), bool decrypt=false)
Returns a previously set authentication setting.
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.
QgsAuthServersEditor(QWidget *parent=nullptr)
Widget for editing authentication configurations directly in database.
void showEvent(QShowEvent *e) override
QgsAuthSslConfigWidget * sslCustomConfigWidget()
Access the embedded SSL server configuration widget.
void setConfigCheckable(bool checkable)
Sets whether the config group box is checkable.
A bar for displaying non-blocking messages to the user.
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 QgsDebugMsgLevel(str, level)
Definition qgslogger.h:61
#define QgsDebugError(str)
Definition qgslogger.h:57