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