04/23 Enhance app functionalities 2
This commit is contained in:
@@ -427,6 +427,21 @@ class WebsiteDialog(tk.Toplevel):
|
||||
if not name or not url:
|
||||
show_error("Name and URL are required.")
|
||||
return
|
||||
|
||||
# Normalise and validate URL before writing to the database.
|
||||
# Reject schemes that could be executed in-browser (javascript:, data:, etc.)
|
||||
# and enforce that a host is present so the health-check thread and the
|
||||
# "open in browser" action both receive a usable address.
|
||||
url = _validate_and_normalise_url(url)
|
||||
if url is None:
|
||||
show_error(
|
||||
"The URL entered is not valid.\n\n"
|
||||
"Please enter a full web address, e.g.:\n"
|
||||
" https://www.example.com\n"
|
||||
" http://intranet.local/app"
|
||||
)
|
||||
return
|
||||
|
||||
if visibility == "assigned" and not assigned_user_ids:
|
||||
show_error("Please assign at least one user, or set visibility to All Users.")
|
||||
return
|
||||
@@ -463,3 +478,42 @@ class WebsiteDialog(tk.Toplevel):
|
||||
self.destroy()
|
||||
except Exception as e:
|
||||
show_error(f"Save failed:\n{e}")
|
||||
|
||||
|
||||
# ─── URL validation helper ────────────────────────────────────────────────────
|
||||
|
||||
def _validate_and_normalise_url(raw: str) -> "str | None":
|
||||
"""
|
||||
Validate and normalise a user-supplied URL string.
|
||||
|
||||
Rules:
|
||||
- If no scheme is present, prepend 'https://'.
|
||||
- Only 'http' and 'https' schemes are accepted.
|
||||
- A non-empty netloc (host) must be present.
|
||||
- Returns the normalised URL string on success, None on failure.
|
||||
|
||||
This prevents dangerous schemes (javascript:, data:, file:, etc.) from
|
||||
reaching the database, the health-check thread, or webbrowser.open().
|
||||
"""
|
||||
import urllib.parse
|
||||
|
||||
if not raw:
|
||||
return None
|
||||
|
||||
# Prepend https:// if no scheme is given so urlparse can parse the host
|
||||
if "://" not in raw:
|
||||
raw = "https://" + raw
|
||||
|
||||
try:
|
||||
parts = urllib.parse.urlparse(raw)
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
if parts.scheme.lower() not in ("http", "https"):
|
||||
return None
|
||||
|
||||
if not parts.netloc:
|
||||
return None
|
||||
|
||||
# Reconstruct a clean URL (strips any leading/trailing whitespace artefacts)
|
||||
return urllib.parse.urlunparse(parts)
|
||||
|
||||
Reference in New Issue
Block a user