mirror of
https://github.com/ARUP-CAS/aiscr-qgis-amcr-viewer.git
synced 2026-06-17 11:22:53 +02:00
Ověření přihlašovacích údajů před uložením do správce autentizace
Špatné heslo zadané v přihlašovacím dialogu se dosud uložilo do QGIS Authentication Manageru a chyba se ukázala až po zavření dialogu. - Dialog nyní před uložením zkusí přihlášení k API; při neplatných údajích se nic neuloží a uživatel může údaje rovnou opravit. - Pokud je server nedostupný (údaje nelze ověřit), uživatel si může zvolit, zda je uložit neověřené – změna hesla na webu u dříve uložených údajů tím není dotčena. - login_to_api nově rozlišuje důvod selhání (LAST_LOGIN_ERROR: 'auth' × 'network'), aby dialog uměl oba případy odlišit. - Ověřuje se i změna samotného e-mailu (proti uloženému heslu).
This commit is contained in:
@@ -627,6 +627,39 @@ class LoginDialog(QDialog):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def _verify_credentials(self, username: str, password: str) -> bool:
|
||||||
|
"""
|
||||||
|
Verify the credentials against the API before saving them.
|
||||||
|
Returns True if they should be stored: either the login succeeded,
|
||||||
|
or the server was unreachable and the user chose to keep them
|
||||||
|
unverified. Wrong credentials are never stored.
|
||||||
|
"""
|
||||||
|
# Lazy import to avoid an import cycle
|
||||||
|
# (amcr_tools imports LoginDialog lazily as well)
|
||||||
|
from . import amcr_tools
|
||||||
|
|
||||||
|
if amcr_tools.login_to_api(username, password):
|
||||||
|
return True
|
||||||
|
|
||||||
|
if amcr_tools.LAST_LOGIN_ERROR == 'network':
|
||||||
|
answer = QMessageBox.question(
|
||||||
|
self,
|
||||||
|
"Server nedostupný",
|
||||||
|
"Přihlašovací údaje se nepodařilo ověřit – server AMČR "
|
||||||
|
"je nedostupný.\nChcete je přesto uložit (neověřené)?",
|
||||||
|
QMessageBox.StandardButton.Yes
|
||||||
|
| QMessageBox.StandardButton.No
|
||||||
|
)
|
||||||
|
return answer == QMessageBox.StandardButton.Yes
|
||||||
|
|
||||||
|
QMessageBox.warning(
|
||||||
|
self,
|
||||||
|
"Neplatné přihlašovací údaje",
|
||||||
|
"Přihlášení se nezdařilo – zkontrolujte e-mail a heslo.\n"
|
||||||
|
"Údaje nebyly uloženy."
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
# Button actions
|
# Button actions
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
@@ -653,6 +686,11 @@ class LoginDialog(QDialog):
|
|||||||
if ok:
|
if ok:
|
||||||
if not self._ensure_master_password():
|
if not self._ensure_master_password():
|
||||||
return
|
return
|
||||||
|
# Verify the new username against the stored password
|
||||||
|
if not self._verify_credentials(
|
||||||
|
username, cfg.config("password", "")
|
||||||
|
):
|
||||||
|
return
|
||||||
cfg.setConfig("username", username)
|
cfg.setConfig("username", username)
|
||||||
auth_mgr.updateAuthenticationConfig(cfg)
|
auth_mgr.updateAuthenticationConfig(cfg)
|
||||||
self.accept()
|
self.accept()
|
||||||
@@ -662,6 +700,11 @@ class LoginDialog(QDialog):
|
|||||||
QMessageBox.warning(self, "Chybí údaje", "Vyplňte prosím heslo.")
|
QMessageBox.warning(self, "Chybí údaje", "Vyplňte prosím heslo.")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Verify before prompting for the master password – wrong
|
||||||
|
# credentials must never reach the Authentication Manager
|
||||||
|
if not self._verify_credentials(username, password):
|
||||||
|
return
|
||||||
|
|
||||||
if not self._ensure_master_password():
|
if not self._ensure_master_password():
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ TRANSLATIONS = {}
|
|||||||
# None = not logged in (anonymous access)
|
# None = not logged in (anonymous access)
|
||||||
AMCR_SESSION: requests.Session | None = None
|
AMCR_SESSION: requests.Session | None = None
|
||||||
|
|
||||||
|
# Reason of the last failed login: 'auth' (wrong credentials),
|
||||||
|
# 'network' (server unreachable / invalid response) or None
|
||||||
|
LAST_LOGIN_ERROR: str | None = None
|
||||||
|
|
||||||
# Re-entrancy guard: the download runs in the main thread and pumps the
|
# Re-entrancy guard: the download runs in the main thread and pumps the
|
||||||
# event loop via processEvents(), so the user could otherwise start
|
# event loop via processEvents(), so the user could otherwise start
|
||||||
# a second download while the first one is still running
|
# a second download while the first one is still running
|
||||||
@@ -38,6 +42,9 @@ def login_to_api(username: str, password: str):
|
|||||||
"""
|
"""
|
||||||
login_url = "https://digiarchiv.aiscr.cz/api/user/login"
|
login_url = "https://digiarchiv.aiscr.cz/api/user/login"
|
||||||
|
|
||||||
|
global LAST_LOGIN_ERROR
|
||||||
|
LAST_LOGIN_ERROR = None
|
||||||
|
|
||||||
_log(f"Přihlašuji uživatele: '{username}'")
|
_log(f"Přihlašuji uživatele: '{username}'")
|
||||||
|
|
||||||
if not username or not password:
|
if not username or not password:
|
||||||
@@ -45,6 +52,7 @@ def login_to_api(username: str, password: str):
|
|||||||
"CHYBA: username nebo heslo je prázdné.",
|
"CHYBA: username nebo heslo je prázdné.",
|
||||||
Qgis.MessageLevel.Critical
|
Qgis.MessageLevel.Critical
|
||||||
)
|
)
|
||||||
|
LAST_LOGIN_ERROR = 'auth'
|
||||||
return None
|
return None
|
||||||
|
|
||||||
session = requests.Session()
|
session = requests.Session()
|
||||||
@@ -72,6 +80,7 @@ def login_to_api(username: str, password: str):
|
|||||||
f"CHYBA přihlášení (API): {body['error']}",
|
f"CHYBA přihlášení (API): {body['error']}",
|
||||||
Qgis.MessageLevel.Critical
|
Qgis.MessageLevel.Critical
|
||||||
)
|
)
|
||||||
|
LAST_LOGIN_ERROR = 'auth'
|
||||||
return None
|
return None
|
||||||
|
|
||||||
_log("Přihlášení proběhlo úspěšně.")
|
_log("Přihlášení proběhlo úspěšně.")
|
||||||
@@ -80,18 +89,22 @@ def login_to_api(username: str, password: str):
|
|||||||
return session
|
return session
|
||||||
|
|
||||||
except requests.exceptions.HTTPError as e:
|
except requests.exceptions.HTTPError as e:
|
||||||
_log(f"CHYBA HTTP {e.response.status_code if e.response else '?'}: "
|
status = e.response.status_code if e.response is not None else None
|
||||||
f"{e.response.text[:300] if e.response else 'žádná odpověď'}",
|
_log(f"CHYBA HTTP {status if status else '?'}: "
|
||||||
|
f"{e.response.text[:300] if e.response is not None else 'žádná odpověď'}",
|
||||||
Qgis.MessageLevel.Critical)
|
Qgis.MessageLevel.Critical)
|
||||||
|
LAST_LOGIN_ERROR = 'auth' if status in (401, 403) else 'network'
|
||||||
return None
|
return None
|
||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
_log(f"CHYBA sítě: {e}", Qgis.MessageLevel.Critical)
|
_log(f"CHYBA sítě: {e}", Qgis.MessageLevel.Critical)
|
||||||
|
LAST_LOGIN_ERROR = 'network'
|
||||||
return None
|
return None
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# Server returned non-JSON (e.g. an HTML error page behind a proxy)
|
# Server returned non-JSON (e.g. an HTML error page behind a proxy)
|
||||||
_log("CHYBA: server nevrátil platný JSON: "
|
_log("CHYBA: server nevrátil platný JSON: "
|
||||||
f"{response.text[:300]}",
|
f"{response.text[:300]}",
|
||||||
Qgis.MessageLevel.Critical)
|
Qgis.MessageLevel.Critical)
|
||||||
|
LAST_LOGIN_ERROR = 'network'
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user