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