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