Skip to content

Commit

Permalink
Add new check about SSL and a automatic repair SSL button
Browse files Browse the repository at this point in the history
  • Loading branch information
Gustry committed Oct 19, 2023
1 parent 83c5bc3 commit 2835759
Show file tree
Hide file tree
Showing 7 changed files with 264 additions and 27 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,16 @@

## Unreleased

* Disabling Stamen base-maps checkbox, see https://stamen.com/faq
* Fix an error on Windows when the path of a layer is on a different drive
* Improve links to documentation
* Add a new panel for some settings and tools coming soon
* Add an SSL connection checker for PostgreSQL layers
* Add a link to the project folder if the thumbnail is not found
* Review help about `@lizmap_user_groups`
* Various minor fixes :
* Py-QGIS-Server version
* new layouts configuration for LWC 3.7

## 3.17.1 - 2023-10-04

Expand Down
3 changes: 2 additions & 1 deletion lizmap/definitions/online_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def online_lwc_help(page: str = '', version=VERSION) -> QUrl:
2: 'publish/lizmap_plugin/layers.html',
3: 'publish/lizmap_plugin/basemap.html',
4: 'publish/lizmap_plugin/attribute_table.html',
5: 'publish/lizmap_plugin/edition.html', # TODO change soon
5: 'publish/lizmap_plugin/editing.html',
6: None, # Layouts
7: 'publish/lizmap_plugin/form_filtering.html',
8: 'publish/lizmap_plugin/dataviz.html',
Expand All @@ -61,4 +61,5 @@ def online_lwc_help(page: str = '', version=VERSION) -> QUrl:
12: 'publish/lizmap_plugin/atlas.html',
13: 'publish/lizmap_plugin/locate_by_layer.html',
14: 'publish/lizmap_plugin/tooltip.html',
15: None,
}
47 changes: 44 additions & 3 deletions lizmap/dialogs/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@
QSizePolicy,
QSpacerItem,
)
from qgis.utils import iface
from qgis.utils import OverrideCursor, iface

from lizmap.log_panel import LogPanel
from lizmap.saas import fix_ssl

try:
from qgis.PyQt.QtWebKitWidgets import QWebView
Expand Down Expand Up @@ -93,6 +94,9 @@ def __init__(self, parent=None):
self.check_project_thumbnail()
self.setup_icons()

self.button_convert_ssl.clicked.connect(self.fix_project_ssl)
self.button_convert_ssl.setIcon(QIcon(":images/themes/default/mIconPostgis.svg"))

self.buttonBox.button(QDialogButtonBox.Help).setToolTip(tr(
'Open the help in the web-browser'
))
Expand Down Expand Up @@ -188,6 +192,15 @@ def check_ign_french_free_key(self):
else:
self.cbIgnTerrain.setEnabled(True)

def enabled_ssl_button(self, status: bool):
""" Enable or not the button. """
if Qgis.QGIS_VERSION_INT <= 32200:
self.button_convert_ssl.setToolTip(tr("QGIS 3.22 is required"))
self.button_convert_ssl.setEnbled(False)
return

self.button_convert_ssl.setEnabled(status)

def follow_map_theme_toggled(self):
""" If the theme is loaded at startup, the UX is updated about the toggled checkbox and the legend option. """
text = ". " + tr("Overriden by the map theme")
Expand Down Expand Up @@ -451,118 +464,134 @@ def setup_icons(self):
icon.addFile(resources_path('icons', '03-metadata-white'), mode=QIcon.Normal)
icon.addFile(resources_path('icons', '03-metadata-dark'), mode=QIcon.Selected)
self.mOptionsListWidget.item(i).setIcon(icon)
self.mOptionsListWidget.item(i).setData(Qt.UserRole, 'info')
i += 1

# Map options
icon = QIcon()
icon.addFile(resources_path('icons', '15-baselayer-white.png'), mode=QIcon.Normal)
icon.addFile(resources_path('icons', '15-baselayer-dark.png'), mode=QIcon.Selected)
self.mOptionsListWidget.item(i).setIcon(icon)
self.mOptionsListWidget.item(i).setData(Qt.UserRole, 'map-options')
i += 1

# Layers
icon = QIcon()
icon.addFile(resources_path('icons', '02-switcher-white.png'), mode=QIcon.Normal)
icon.addFile(resources_path('icons', '02-switcher-dark.png'), mode=QIcon.Selected)
self.mOptionsListWidget.item(i).setIcon(icon)
self.mOptionsListWidget.item(i).setData(Qt.UserRole, 'layers')
i += 1

# Base layer
icon = QIcon()
icon.addFile(resources_path('icons', '02-switcher-white.png'), mode=QIcon.Normal)
icon.addFile(resources_path('icons', '02-switcher-dark.png'), mode=QIcon.Selected)
self.mOptionsListWidget.item(i).setIcon(icon)
self.mOptionsListWidget.item(i).setData(Qt.UserRole, 'base-layers')
i += 1

# Attribute table
icon = QIcon()
icon.addFile(resources_path('icons', '11-attribute-white.png'), mode=QIcon.Normal)
icon.addFile(resources_path('icons', '11-attribute-dark.png'), mode=QIcon.Selected)
self.mOptionsListWidget.item(i).setIcon(icon)
self.mOptionsListWidget.item(i).setData(Qt.UserRole, 'attribute-table')
i += 1

# Layer editing
icon = QIcon()
icon.addFile(resources_path('icons', '10-edition-white.png'), mode=QIcon.Normal)
icon.addFile(resources_path('icons', '10-edition-dark.png'), mode=QIcon.Selected)
self.mOptionsListWidget.item(i).setIcon(icon)
self.mOptionsListWidget.item(i).setData(Qt.UserRole, 'layer-editing')
i += 1

# Layouts
icon = QIcon()
icon.addFile(resources_path('icons', '08-print-white.png'), mode=QIcon.Normal)
icon.addFile(resources_path('icons', '08-print-dark.png'), mode=QIcon.Selected)
self.mOptionsListWidget.item(i).setIcon(icon)
self.mOptionsListWidget.item(i).setData(Qt.UserRole, 'layouts')
i += 1

# Filter data with form
icon = QIcon()
icon.addFile(resources_path('icons', 'filter-icon-white.png'), mode=QIcon.Normal)
icon.addFile(resources_path('icons', 'filter-icon-dark.png'), mode=QIcon.Selected)
self.mOptionsListWidget.item(i).setIcon(icon)
self.mOptionsListWidget.item(i).setData(Qt.UserRole, 'filter-data-form')
i += 1

# Dataviz
icon = QIcon()
icon.addFile(resources_path('icons', 'dataviz-icon-white.png'), mode=QIcon.Normal)
icon.addFile(resources_path('icons', 'dataviz-icon-dark.png'), mode=QIcon.Selected)
self.mOptionsListWidget.item(i).setIcon(icon)
self.mOptionsListWidget.item(i).setData(Qt.UserRole, 'dataviz')
i += 1

# Filter layer by user
icon = QIcon()
icon.addFile(resources_path('icons', '12-user-white.png'), mode=QIcon.Normal)
icon.addFile(resources_path('icons', '12-user-dark.png'), mode=QIcon.Selected)
self.mOptionsListWidget.item(i).setIcon(icon)
self.mOptionsListWidget.item(i).setData(Qt.UserRole, 'filter-data-user')
i += 1

# Actions
icon = QIcon()
icon.addFile(resources_path('icons', 'actions-white.svg'), mode=QIcon.Normal)
icon.addFile(resources_path('icons', 'actions-dark.svg'), mode=QIcon.Selected)
self.mOptionsListWidget.item(i).setIcon(icon)

self.mOptionsListWidget.item(i).setData(Qt.UserRole, 'actions')
i += 1

# Time manager
icon = QIcon()
icon.addFile(resources_path('icons', '13-timemanager-white.png'), mode=QIcon.Normal)
icon.addFile(resources_path('icons', '13-timemanager-dark.png'), mode=QIcon.Selected)
self.mOptionsListWidget.item(i).setIcon(icon)
self.mOptionsListWidget.item(i).setData(Qt.UserRole, 'time-manager')
i += 1

# Atlas
icon = QIcon()
icon.addFile(resources_path('icons', 'atlas-icon-white.png'), mode=QIcon.Normal)
icon.addFile(resources_path('icons', 'atlas-icon-dark.png'), mode=QIcon.Selected)
self.mOptionsListWidget.item(i).setIcon(icon)
self.mOptionsListWidget.item(i).setData(Qt.UserRole, 'atlas')
i += 1

# Locate by layer
icon = QIcon()
icon.addFile(resources_path('icons', '04-locate-white.png'), mode=QIcon.Normal)
icon.addFile(resources_path('icons', '04-locate-dark.png'), mode=QIcon.Selected)
self.mOptionsListWidget.item(i).setIcon(icon)
self.mOptionsListWidget.item(i).setData(Qt.UserRole, 'locate-by-layer')
i += 1

# Tooltip layer
icon = QIcon()
icon.addFile(resources_path('icons', '16-tooltip-white.png'), mode=QIcon.Normal)
icon.addFile(resources_path('icons', '16-tooltip-dark.png'), mode=QIcon.Selected)
self.mOptionsListWidget.item(i).setIcon(icon)
self.mOptionsListWidget.item(i).setData(Qt.UserRole, 'tooltip-layer')
i += 1

# Log
# It must be the before last tab
# noinspection PyCallByClass,PyArgumentList
icon = QIcon(QgsApplication.iconPath('mMessageLog.svg'))
self.mOptionsListWidget.item(i).setIcon(icon)
self.mOptionsListWidget.item(i).setData(Qt.UserRole, 'log')
i += 1

# Settings
# noinspection PyCallByClass,PyArgumentList
icon = QIcon(QgsApplication.getThemeIcon("iconSettingsConsole.svg"))
icon = QIcon(":images/themes/default/console/iconSettingsConsole.svg")
self.mOptionsListWidget.item(i).setIcon(icon)
self.mOptionsListWidget.item(i).setData(Qt.UserRole, 'settings')
i += 1

# Set stylesheet for QGroupBox
Expand Down Expand Up @@ -647,6 +676,7 @@ def check_action_file_exists(self) -> bool:

def allow_navigation(self, allow_navigation: bool, message: str = ''):
""" Allow the navigation or not in the UI. """
self.enabled_ssl_button(False)
for i in range(1, self.mOptionsListWidget.count()):
item = self.mOptionsListWidget.item(i)
if allow_navigation:
Expand All @@ -661,6 +691,17 @@ def allow_navigation(self, allow_navigation: bool, message: str = ''):
self.label_warning_project.setVisible(True)
self.label_warning_project.set_text(message)

def fix_project_ssl(self):
""" Fix the current project about SSL. """
with OverrideCursor(Qt.WaitCursor):
count = fix_ssl(self.project, force=False)

if count >= 2:
msg = tr('{} layer(s) updated').format(count)
else:
msg = tr('{} layer updated').format(count)
self.display_message_bar("SSL", msg, Qgis.Success)

def activateWindow(self):
""" When the dialog displayed, to trigger functions in the plugin when the dialog is opening. """
self.check_project_thumbnail()
Expand Down
41 changes: 35 additions & 6 deletions lizmap/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,12 @@
simplify_provider_side,
use_estimated_metadata,
)
from lizmap.saas import is_lizmap_cloud, valid_lizmap_cloud
from lizmap.saas import (
SAAS_NAME,
check_project_ssl_postgis,
is_lizmap_cloud,
valid_lizmap_cloud,
)
from lizmap.table_manager.base import TableManager
from lizmap.table_manager.dataviz import TableManagerDataviz
from lizmap.table_manager.layouts import TableManagerLayouts
Expand Down Expand Up @@ -331,6 +336,7 @@ def write_log_message(message, tag, level):
]
self.lwc_versions[LwcVersions.Lizmap_3_7] = [
# Layout panel
self.dlg.checkbox_default_print,
self.dlg.label_layout_panel,
self.dlg.label_layout_panel_description,
self.dlg.edit_layout_form_button,
Expand Down Expand Up @@ -939,7 +945,7 @@ def initGui(self):
# noinspection PyUnresolvedReferences
self.help_action.triggered.connect(self.show_help)

self.help_action_cloud = QAction(icon, 'Lizmap cloud', self.iface.mainWindow())
self.help_action_cloud = QAction(icon, SAAS_NAME, self.iface.mainWindow())
self.iface.pluginHelpMenu().addAction(self.help_action_cloud)
# noinspection PyUnresolvedReferences
self.help_action.triggered.connect(self.show_help_cloud)
Expand Down Expand Up @@ -2829,7 +2835,7 @@ def project_config_file(self, lwc_version: LwcVersions, with_gui: bool = True, c
if error:
warnings.append(Warnings.SaasLizmapCloud.value)

message = tr('Some configurations are not valid when used with a Lizmap Cloud hosting :')
message = tr('Some configurations are not valid when used with a {} hosting :').format(SAAS_NAME)

message += "<br><ul>"
for error in results.values():
Expand All @@ -2842,10 +2848,33 @@ def project_config_file(self, lwc_version: LwcVersions, with_gui: bool = True, c

message += tr(
"The process is continuing but expect these layers to not be visible in Lizmap Web Client.")
ScrollMessageBox(self.dlg, QMessageBox.Warning, tr('Lizmap Cloud'), message)
ScrollMessageBox(self.dlg, QMessageBox.Warning, SAAS_NAME, message)

log_index_panel = self.dlg.mOptionsListWidget.count() - 2
setting_index_panel = self.dlg.mOptionsListWidget.count() - 1
show_log = False
if check_server:

error, message = check_project_ssl_postgis(self.project)
if error:
show_log = True
self.dlg.log_panel.append(tr('SSL connections to a PostgreSQL database'), Html.H2)
self.dlg.log_panel.append(tr(
"Connections to a PostgreSQL database hosted on {} must use a SSL secured connection."
).format(SAAS_NAME), Html.P)
self.dlg.log_panel.append(tr(
"In the plugin, then in the '{}' panel, there is a helper to change the datasource of layers in "
"the current project only. It works only with minimum QGIS 3.22."
).format(self.dlg.mOptionsListWidget.item(setting_index_panel).text()), Html.P)
self.dlg.log_panel.append(tr(
"You must still edit your global PostgreSQL connection to allow SSL, it will take effect only "
"on newly added layer into a project."
), Html.P)
self.dlg.log_panel.append(message, Html.P)
self.dlg.display_message_bar(
"SSL", tr('You must fix SSL connections used in this project'), Qgis.Warning)
self.dlg.enabled_ssl_button(True)

autogenerated_keys = {}
int8 = []
for layer in self.project.mapLayers().values():
Expand Down Expand Up @@ -2902,7 +2931,7 @@ def project_config_file(self, lwc_version: LwcVersions, with_gui: bool = True, c
"an integer8."), Html.P)
self.dlg.log_panel.append(tr(
"The process is continuing but expect these layers to have some issues with some tools in "
"Lizmap Web Client: zoom to feature, filtering..."
"Lizmap Web Client: zoom to feature, filtering"
), style=Html.P)

if lwc_version >= LwcVersions.Lizmap_3_7:
Expand Down Expand Up @@ -2945,7 +2974,7 @@ def project_config_file(self, lwc_version: LwcVersions, with_gui: bool = True, c
show_log = True

if with_gui and show_log:
self.dlg.mOptionsListWidget.setCurrentRow(self.dlg.mOptionsListWidget.count() - 2)
self.dlg.mOptionsListWidget.setCurrentRow(log_index_panel)
self.dlg.out_log.moveCursor(QTextCursor.Start)
self.dlg.out_log.ensureCursorVisible()

Expand Down
44 changes: 38 additions & 6 deletions lizmap/resources/ui/ui_lizmap.ui
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ QListWidget::item::selected {
</item>
<item>
<property name="text">
<string>Settings</string>
<string>Settings/tools</string>
</property>
</item>
</widget>
Expand Down Expand Up @@ -4552,13 +4552,45 @@ This is different to the map maximum extent (defined in QGIS project properties,
<widget class="QWidget" name="page_settings">
<layout class="QVBoxLayout" name="verticalLayout_64">
<item>
<widget class="QCheckBox" name="checkbox_save_project">
<property name="toolTip">
<string>Save the QGIS project too at the same time as the Lizmap config file.</string>
<widget class="QGroupBox" name="groupBox_12">
<property name="title">
<string>Settings</string>
</property>
<property name="text">
<string>Save QGIS project too</string>
<layout class="QVBoxLayout" name="verticalLayout_66">
<item>
<widget class="QCheckBox" name="checkbox_save_project">
<property name="toolTip">
<string>Save the QGIS project too at the same time as the Lizmap config file.</string>
</property>
<property name="text">
<string>Save QGIS project too</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_9">
<property name="title">
<string>Auto repair tools on the project</string>
</property>
<layout class="QFormLayout" name="formLayout_4">
<item row="0" column="0">
<widget class="QPushButton" name="button_convert_ssl">
<property name="text">
<string>Convert to SSL mode 'prefer'</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_57">
<property name="text">
<string>Convert all connections to a PostgreSQL database to use SSL</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
Expand Down
Loading

0 comments on commit 2835759

Please sign in to comment.