Skip to content

Commit

Permalink
Add new options about safeguards
Browse files Browse the repository at this point in the history
  • Loading branch information
Gustry committed Oct 26, 2023
1 parent dbe76bd commit b77225b
Show file tree
Hide file tree
Showing 8 changed files with 598 additions and 147 deletions.
26 changes: 26 additions & 0 deletions lizmap/definitions/qgis_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""Definitions for QgsSettings."""

# TODO, use the settings API from QGIS 3.30 etc
# Mail QGIS-Dev 24/10/2023

__copyright__ = 'Copyright 2023, 3Liz'
__license__ = 'GPL version 3'
__email__ = '[email protected]'

KEY = 'lizmap'


class Settings:

@classmethod
def key(cls, key):
return KEY + '/' + key

PreventEcw = 'prevent_ecw'
PreventPgAuthId = 'prevent_pg_auth_id'
PreventPgService = 'prevent_pg_service'
ForcePgUserPass = 'force_pg_user_password'
PreventNetworkDrive = 'prevent_network_drive'
AllowParentFolder = 'allow_parent_folder'
NumberParentFolder = 'number_parent_folder'
BeginnerMode = 'beginner_mode'
145 changes: 143 additions & 2 deletions lizmap/dialogs/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@
)
from qgis.utils import OverrideCursor, iface

from lizmap.definitions.qgis_settings import Settings
from lizmap.log_panel import LogPanel
from lizmap.project_checker_tools import (
project_trust_layer_metadata,
simplify_provider_side,
use_estimated_metadata,
)
from lizmap.saas import fix_ssl
from lizmap.saas import SAAS_MAX_PARENT_FOLDER, SAAS_NAME, fix_ssl

try:
from qgis.PyQt.QtWebKitWidgets import QWebView
Expand All @@ -44,7 +45,12 @@
from lizmap.qgis_plugin_tools.tools.i18n import tr
from lizmap.qgis_plugin_tools.tools.resources import load_ui, resources_path
from lizmap.qt_style_sheets import COMPLETE_STYLE_SHEET
from lizmap.tools import format_qgis_version, human_size, qgis_version
from lizmap.tools import (
format_qgis_version,
human_size,
qgis_version,
relative_path,
)

FORM_CLASS = load_ui('ui_lizmap.ui')
LOGGER = logging.getLogger("Lizmap")
Expand Down Expand Up @@ -171,6 +177,103 @@ def __init__(self, parent=None):
)
self.label_file_action.setOpenExternalLinks(True)

self.radio_beginner.setToolTip(
'If one safeguard is not OK, the Lizmap configuration file is not going to be generated.'
)
self.radio_normal.setToolTip(
'If one safeguard is not OK, only a warning will be displayed, not blocking the saving of the Lizmap '
'configuration file.'
)

msg_parent_force_local = tr('Prevent file based layers to be in a parent folder')
self.radio_force_local_folder.setText(msg_parent_force_local)
self.radio_force_local_folder.setToolTip(tr(
'Files must be located in {} or in a sub directory.'
).format(self.project.absolutePath()))

msg_parent_folder = tr('Allow file based layers to be in a parent folder')
self.radio_allow_parent_folder.setText(msg_parent_folder)
self.radio_allow_parent_folder.setToolTip(tr(
'Files can be located in a parent folder from {}, up to the setting below.'
).format(self.project.absolutePath()))

msg_network_drive = tr('Prevent file based layers to be stored on another network drive')
self.safe_network_drive.setText(msg_network_drive)

msg_service = tr('Prevent PostgreSQL layers to use a service file')
self.safe_pg_service.setText(msg_service)

msg_auth_db = tr('Prevent PostgreSQL layers to use the authentication database')
self.safe_pg_auth_db.setText(msg_auth_db)

msg_pg_user_pass = tr(
'PostgreSQL layers, if using a user and password, must have credentials saved in the datasource')
self.safe_pg_user_password.setText(msg_pg_user_pass)

msg_ecw = tr('Prevent from using a ECW raster')
self.safe_ecw.setText(msg_ecw)

# Normal / beginner
self.radio_normal.setChecked(
not QgsSettings().value(Settings.key(Settings.BeginnerMode), type=bool))
self.radio_beginner.setChecked(
QgsSettings().value(Settings.key(Settings.BeginnerMode), type=bool))
self.radio_normal.toggled.connect(self.radio_mode_normal_toggled)
self.radio_normal.toggled.connect(self.save_settings)
self.radio_mode_normal_toggled()

# Parent or subdirectory
self.radio_force_local_folder.setChecked(
not QgsSettings().value(Settings.key(Settings.AllowParentFolder), type=bool))
self.radio_allow_parent_folder.setChecked(
QgsSettings().value(Settings.key(Settings.AllowParentFolder), type=bool))
self.radio_allow_parent_folder.toggled.connect(self.radio_parent_folder_toggled)
self.radio_allow_parent_folder.toggled.connect(self.save_settings)
self.radio_parent_folder_toggled()

# Number
self.safe_number_parent.setValue(QgsSettings().value(Settings.key(Settings.NumberParentFolder)))
self.safe_number_parent.valueChanged.connect(self.save_settings)

# Network drive
self.safe_network_drive.setChecked(QgsSettings().value(Settings.key(Settings.PreventNetworkDrive), type=bool))
self.safe_network_drive.toggled.connect(self.save_settings)

# PG Service
self.safe_pg_service.setChecked(QgsSettings().value(Settings.key(Settings.PreventPgService), type=bool))
self.safe_pg_service.toggled.connect(self.save_settings)

# PG Auth DB
self.safe_pg_auth_db.setChecked(QgsSettings().value(Settings.key(Settings.PreventPgAuthId), type=bool))
self.safe_pg_auth_db.toggled.connect(self.save_settings)

# User password
self.safe_pg_user_password.setChecked(QgsSettings().value(Settings.key(Settings.ForcePgUserPass), type=bool))
self.safe_pg_user_password.toggled.connect(self.save_settings)

# ECW
self.safe_ecw.setChecked(QgsSettings().value(Settings.key(Settings.PreventEcw), type=bool))
self.safe_ecw.toggled.connect(self.save_settings)

self.label_safe_lizmap_cloud.setText(tr("Some safe guards are overridden by {}.").format(SAAS_NAME))
msg = (
'<ul>'
'<li>{max_parent}</li>'
'<li>{network}</li>'
'<li>{auth_db}</li>'
'<li>{user_pass}</li>'
'<li>{ecw}</li>'
'</ul>'.format(
max_parent=tr("Maximum of parent folder {} : {}").format(
SAAS_MAX_PARENT_FOLDER, relative_path(SAAS_MAX_PARENT_FOLDER)),
network=msg_network_drive,
auth_db=msg_auth_db,
user_pass=msg_pg_user_pass,
ecw=msg_ecw,
)
)
self.label_safe_lizmap_cloud.setToolTip(msg)

def check_api_key_address(self):
""" Check the API key is provided for the address search bar. """
provider = self.liExternalSearch.currentData()
Expand Down Expand Up @@ -723,6 +826,44 @@ def check_action_file_exists(self) -> bool:
self.label_file_action_found.setText("<strong>" + tr('Not found') + "</strong>")
return False

def radio_parent_folder_toggled(self):
""" When the parent allowed folder radio is toggled. """
parent_allowed = self.radio_allow_parent_folder.isChecked()
widgets = (
self.label_parent_folder,
self.safe_number_parent,
)
for widget in widgets:
widget.setEnabled(parent_allowed)

def radio_mode_normal_toggled(self):
""" When the beginner/normal radio are toggled. """
is_normal = self.radio_normal.isChecked()
widgets = (
self.group_file_layer,
self.safe_number_parent,
self.safe_network_drive,
self.safe_pg_service,
self.safe_pg_auth_db,
self.safe_pg_user_password,
self.safe_ecw,
self.label_parent_folder,
)
for widget in widgets:
widget.setEnabled(is_normal)
widget.setVisible(is_normal)

def save_settings(self):
""" Save settings checkboxes. """
QgsSettings().setValue(Settings.key(Settings.BeginnerMode), not self.radio_normal.isChecked())
QgsSettings().setValue(Settings.key(Settings.AllowParentFolder), self.radio_allow_parent_folder.isChecked())
QgsSettings().setValue(Settings.key(Settings.NumberParentFolder), self.safe_number_parent.value())
QgsSettings().setValue(Settings.key(Settings.PreventNetworkDrive), self.safe_network_drive.isChecked())
QgsSettings().setValue(Settings.key(Settings.PreventPgService), self.safe_pg_service.isChecked())
QgsSettings().setValue(Settings.key(Settings.PreventPgAuthId), self.safe_pg_auth_db.isChecked())
QgsSettings().setValue(Settings.key(Settings.ForcePgUserPass), self.safe_pg_user_password.isChecked())
QgsSettings().setValue(Settings.key(Settings.PreventEcw), self.safe_ecw.isChecked())

def allow_navigation(self, allow_navigation: bool, message: str = ''):
""" Allow the navigation or not in the UI. """
for i in range(1, self.mOptionsListWidget.count()):
Expand Down
95 changes: 86 additions & 9 deletions lizmap/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
online_cloud_help,
online_lwc_help,
)
from lizmap.definitions.qgis_settings import Settings
from lizmap.definitions.time_manager import TimeManagerDefinitions
from lizmap.definitions.tooltip import ToolTipDefinitions
from lizmap.definitions.warnings import Warnings
Expand Down Expand Up @@ -120,15 +121,16 @@
duplicated_layer_name_or_group,
duplicated_layer_with_filter,
invalid_int8_primary_key,
project_safeguards_checks,
project_trust_layer_metadata,
simplify_provider_side,
use_estimated_metadata,
)
from lizmap.saas import (
SAAS_MAX_PARENT_FOLDER,
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
Expand Down Expand Up @@ -166,6 +168,7 @@
lizmap_user_folder,
next_git_tag,
qgis_version,
relative_path,
to_bool,
unaccent,
)
Expand Down Expand Up @@ -198,6 +201,39 @@ def __init__(self, iface):
# 04/01/2022
QgsSettings().remove('lizmap/instance_target_url_authid')

# Set some default settings when loading the plugin
beginner_mode = QgsSettings().value(Settings.key(Settings.BeginnerMode), defaultValue=None)
if beginner_mode is None:
QgsSettings().setValue(Settings.key(Settings.BeginnerMode), True)

prevent_ecw = QgsSettings().value(Settings.key(Settings.PreventEcw), defaultValue=None)
if prevent_ecw is None:
QgsSettings().setValue(Settings.key(Settings.PreventEcw), True)

prevent_auth_id = QgsSettings().value(Settings.key(Settings.PreventPgAuthId), defaultValue=None)
if prevent_auth_id is None:
QgsSettings().setValue(Settings.key(Settings.PreventPgAuthId), True)

prevent_service = QgsSettings().value(Settings.key(Settings.PreventPgService), defaultValue=None)
if prevent_service is None:
QgsSettings().setValue(Settings.key(Settings.PreventPgService), True)

force_pg_user_pass = QgsSettings().value(Settings.key(Settings.ForcePgUserPass), defaultValue=None)
if force_pg_user_pass is None:
QgsSettings().setValue(Settings.key(Settings.ForcePgUserPass), True)

prevent_network_drive = QgsSettings().value(Settings.key(Settings.PreventNetworkDrive), defaultValue=None)
if prevent_network_drive is None:
QgsSettings().setValue(Settings.key(Settings.PreventNetworkDrive), True)

allow_parent_folder = QgsSettings().value(Settings.key(Settings.AllowParentFolder), defaultValue=None)
if allow_parent_folder is None:
QgsSettings().setValue(Settings.key(Settings.AllowParentFolder), False)

parent_folder = QgsSettings().value(Settings.key(Settings.NumberParentFolder), defaultValue=None)
if parent_folder is None:
QgsSettings().setValue(Settings.key(Settings.NumberParentFolder), 2)

# Connect the current project filepath
self.current_path = None
# noinspection PyUnresolvedReferences
Expand Down Expand Up @@ -359,6 +395,7 @@ def write_log_message(message, tag, level):

self.lizmap_cloud = [
self.dlg.label_lizmap_search_grant,
self.dlg.label_safe_lizmap_cloud,
]

# Add widgets (not done in lizmap_var to avoid dependencies on ui)
Expand Down Expand Up @@ -2852,14 +2889,45 @@ def project_config_file(

server_metadata = self.dlg.server_combo.currentData(ServerComboData.JsonMetadata.value)

if check_server and is_lizmap_cloud(server_metadata):
results, more = valid_lizmap_cloud(self.project)
if check_server:

# Global checks config
prevent_ecw = QgsSettings().value(Settings.key(Settings.PreventEcw), True, bool)
prevent_auth_id = QgsSettings().value(Settings.key(Settings.PreventPgAuthId), True, bool)
prevent_service = QgsSettings().value(Settings.key(Settings.PreventPgService), True, bool)
force_pg_user_pass = QgsSettings().value(Settings.key(Settings.ForcePgUserPass), True, bool)
prevent_network_drive = QgsSettings().value(Settings.key(Settings.PreventNetworkDrive), True, bool)
allow_parent_folder = QgsSettings().value(Settings.key(Settings.AllowParentFolder), False, bool)
parent_folder = relative_path(QgsSettings().value(Settings.key(Settings.NumberParentFolder), 2, int))

beginner_mode = QgsSettings().value(Settings.key(Settings.BeginnerMode), True, bool)

lizmap_cloud = is_lizmap_cloud(server_metadata)
if lizmap_cloud:
# But Lizmap Cloud override some user globals checks
prevent_ecw = True
prevent_auth_id = True
force_pg_user_pass = True
prevent_network_drive = True
parent_folder = relative_path(SAAS_MAX_PARENT_FOLDER)
# prevent_service = False We encourage service
# allow_parent_folder = False Of course we can

results, more = project_safeguards_checks(
self.project,
prevent_ecw=prevent_ecw,
prevent_auth_id=prevent_auth_id,
prevent_service=prevent_service,
force_pg_user_pass=force_pg_user_pass,
prevent_network_drive=prevent_network_drive,
allow_parent_folder=allow_parent_folder,
parent_folder=parent_folder,
lizmap_cloud=lizmap_cloud,
)
if len(results):
show_log_panel = True
warnings.append(Warnings.SaasLizmapCloud.value)
self.dlg.log_panel.append(tr(
'Some configurations are not valid with {} hosting'
).format(SAAS_NAME), Html.H2)
self.dlg.log_panel.append(tr('Some safeguards are not compatible'), Html.H2)
self.dlg.log_panel.append(warning_suggest, Html.P)
self.dlg.log_panel.append("<br>")

Expand All @@ -2876,9 +2944,18 @@ def project_config_file(
self.dlg.log_panel.append(more)
self.dlg.log_panel.append("<br>")

self.dlg.log_panel.append(tr(
"The process is continuing but expect these layers to not be visible in Lizmap Web Client."
), Html.P)
if beginner_mode:
error_cfg_saving = True
self.dlg.log_panel.append(tr(
"The process is stopping, the CFG file is not going to be generated because some safeguards "
"are not compatible and you are using the 'Beginner' mode. Either fix these issues or switch "
"to a 'Normal' mode if you know what you are doing."
), Html.P, level=Qgis.Critical)
else:
self.dlg.log_panel.append(tr(
"The process is continuing but expect these layers to not be visible in Lizmap Web Client if "
"QGIS Server knows what to do with invalid layers."
), Html.P)

if check_server:

Expand Down
Loading

0 comments on commit b77225b

Please sign in to comment.