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