From 7f7cbb5b1fb0a36d46aefbb8b0fda6bb884b4180 Mon Sep 17 00:00:00 2001 From: EiSiMo Date: Tue, 21 Apr 2026 13:55:24 +0200 Subject: [PATCH] cleanup: drop coord backfill, drop transit overlay, block PM autofill - Remove the admin "Koordinaten nachladen" button, /actions/backfill-coords endpoint, geocode.py, googlemaps dep, GMAPS_API_KEY plumbing in the web service, and the map diagnostic line. Going-forward geocoding happens in alert on scrape; upsert_flat backfill on re-submit remains for edge cases - Remove the OpenRailwayMap transit overlay (visually noisy); keep CartoDB Voyager as the sole basemap - Profile + notifications forms get autocomplete="off" + data-lpignore + data-1p-ignore at form and field level to keep password managers from popping open on /einstellungen; immomio_password uses autocomplete=new-password Co-Authored-By: Claude Opus 4.7 (1M context) --- docker-compose.yml | 1 - web/app.py | 38 ------------------ web/db.py | 29 -------------- web/geocode.py | 46 ---------------------- web/requirements.txt | 1 - web/settings.py | 3 -- web/static/map.js | 7 ---- web/templates/_settings_notifications.html | 8 ++-- web/templates/_settings_profil.html | 25 ++++++------ web/templates/_wohnungen_body.html | 21 +--------- 10 files changed, 20 insertions(+), 159 deletions(-) delete mode 100644 web/geocode.py diff --git a/docker-compose.yml b/docker-compose.yml index 026c454..10fc595 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -28,7 +28,6 @@ services: - SMTP_PASSWORD=${SMTP_PASSWORD:-} - SMTP_FROM=${SMTP_FROM:-lazyflat@localhost} - SMTP_STARTTLS=${SMTP_STARTTLS:-true} - - GMAPS_API_KEY=${GMAPS_API_KEY:-} volumes: - lazyflat_data:/data expose: diff --git a/web/app.py b/web/app.py index 495862a..d784992 100644 --- a/web/app.py +++ b/web/app.py @@ -33,7 +33,6 @@ except Exception: BERLIN_TZ = timezone.utc import db -import geocode import notifications import retention from apply_client import ApplyClient, _row_to_profile @@ -135,9 +134,7 @@ async def security_headers(request: Request, call_next): "script-src 'self' https://cdn.tailwindcss.com https://unpkg.com; " "style-src 'self' https://cdn.tailwindcss.com https://unpkg.com 'unsafe-inline'; " "img-src 'self' data: " - "https://*.tile.openstreetmap.org https://tile.openstreetmap.org " "https://*.basemaps.cartocdn.com https://basemaps.cartocdn.com " - "https://*.tiles.openrailwaymap.org https://tiles.openrailwaymap.org " "https://unpkg.com; " "connect-src 'self'; frame-ancestors 'none';" ) @@ -406,12 +403,6 @@ def _wohnungen_context(user) -> dict: flats_view.append({"row": f, "last": last}) rejected_view = db.rejected_flats(uid) - matched_count = len(flats_view) - matched_with_coords = sum( - 1 for item in flats_view - if item["row"]["lat"] is not None and item["row"]["lng"] is not None - ) - matched_without_coords = matched_count - matched_with_coords allowed, reason = _manual_apply_allowed() alert_label, alert_chip = _alert_status(notif_row) @@ -433,10 +424,6 @@ def _wohnungen_context(user) -> dict: "flats": flats_view, "rejected_flats": rejected_view, "map_points": map_points, - "map_matched_total": matched_count, - "map_matched_with_coords": matched_with_coords, - "map_matched_without_coords": matched_without_coords, - "gmaps_available": bool(geocode._get_client() is not None), "has_filters": _has_filters(filters_row), "alert_label": alert_label, "alert_chip": alert_chip, @@ -562,31 +549,6 @@ async def action_reject( return _wohnungen_partial_or_redirect(request, user) -@app.post("/actions/backfill-coords") -async def action_backfill_coords( - request: Request, - csrf: str = Form(...), - admin=Depends(require_admin), -): - require_csrf(admin["id"], csrf) - rows = db.flats_missing_coords(limit=500) - total = len(rows) - resolved = 0 - skipped = 0 - for row in rows: - coords = geocode.geocode(row["address"]) - if coords is None: - skipped += 1 - continue - db.set_flat_coords(row["id"], coords[0], coords[1]) - resolved += 1 - summary = f"{resolved}/{total} geocoded, {skipped} übersprungen" - logger.info("coord backfill: %s", summary) - db.log_audit(admin["username"], "coords.backfill", summary, - user_id=admin["id"], ip=client_ip(request)) - return _wohnungen_partial_or_redirect(request, admin) - - @app.post("/actions/unreject") async def action_unreject( request: Request, diff --git a/web/db.py b/web/db.py index 1deabba..449cbe4 100644 --- a/web/db.py +++ b/web/db.py @@ -439,35 +439,6 @@ def get_flat(flat_id: str) -> Optional[sqlite3.Row]: return _conn.execute("SELECT * FROM flats WHERE id = ?", (flat_id,)).fetchone() -def flats_missing_coords(limit: int = 500) -> list[sqlite3.Row]: - return list(_conn.execute( - """SELECT id, address FROM flats - WHERE (lat IS NULL OR lng IS NULL) AND address IS NOT NULL AND address != '' - ORDER BY discovered_at DESC LIMIT ?""", - (limit,), - ).fetchall()) - - -def set_flat_coords(flat_id: str, lat: float, lng: float) -> None: - with _lock: - _conn.execute( - "UPDATE flats SET lat = ?, lng = ? WHERE id = ?", - (lat, lng, flat_id), - ) - - -def count_flats_coords() -> tuple[int, int]: - """Return (total_flats, with_coords).""" - row = _conn.execute( - "SELECT COUNT(*) AS total, " - " SUM(CASE WHEN lat IS NOT NULL AND lng IS NOT NULL THEN 1 ELSE 0 END) AS geo " - "FROM flats" - ).fetchone() - total = int(row["total"] or 0) - geo = int(row["geo"] or 0) - return total, geo - - # --------------------------------------------------------------------------- # Applications # --------------------------------------------------------------------------- diff --git a/web/geocode.py b/web/geocode.py deleted file mode 100644 index 6da8e2e..0000000 --- a/web/geocode.py +++ /dev/null @@ -1,46 +0,0 @@ -"""Thin Google-Maps geocoding wrapper used only for the admin coord backfill. - -Runtime geocoding during scraping happens in the alert service. This module -exists so the web service can lazy-fix flats that were scraped before the -lat/lng migration (or where the alert run skipped geocoding). -""" -import logging -from typing import Optional - -from settings import GMAPS_API_KEY - -logger = logging.getLogger("web.geocode") - -_client = None - - -def _get_client(): - global _client - if _client is not None: - return _client - if not GMAPS_API_KEY: - return None - try: - import googlemaps - _client = googlemaps.Client(key=GMAPS_API_KEY) - return _client - except Exception as e: - logger.warning("googlemaps client init failed: %s", e) - return None - - -def geocode(address: str) -> Optional[tuple[float, float]]: - if not address: - return None - gm = _get_client() - if gm is None: - return None - try: - res = gm.geocode(f"{address}, Berlin, Germany") - if not res: - return None - loc = res[0]["geometry"]["location"] - return float(loc["lat"]), float(loc["lng"]) - except Exception as e: - logger.warning("geocode failed for %r: %s", address, e) - return None diff --git a/web/requirements.txt b/web/requirements.txt index b76195b..56293ef 100644 --- a/web/requirements.txt +++ b/web/requirements.txt @@ -6,4 +6,3 @@ itsdangerous==2.2.0 python-multipart==0.0.17 python-dotenv==1.0.1 requests==2.32.5 -googlemaps==4.10.0 diff --git a/web/settings.py b/web/settings.py index d726733..a33d45d 100644 --- a/web/settings.py +++ b/web/settings.py @@ -63,6 +63,3 @@ SMTP_STARTTLS: bool = getenv("SMTP_STARTTLS", "true").lower() in ("true", "1", " # --- App URL (used to build links in notifications) --------------------------- PUBLIC_URL: str = getenv("PUBLIC_URL", "https://flat.lab.moritz.run") - -# --- Google Maps (used for one-shot coord backfill via admin action) ---------- -GMAPS_API_KEY: str = getenv("GMAPS_API_KEY", "") diff --git a/web/static/map.js b/web/static/map.js index 4f7e85d..6d0108f 100644 --- a/web/static/map.js +++ b/web/static/map.js @@ -79,13 +79,6 @@ function buildMap(el) { subdomains: "abcd", maxZoom: 19, }).addTo(mapInstance); - // Transit overlay — OpenRailwayMap highlights S-/U-/Tram-Linien. - L.tileLayer("https://{s}.tiles.openrailwaymap.org/standard/{z}/{x}/{y}.png", { - attribution: "© OpenRailwayMap", - subdomains: "abc", - maxZoom: 19, - opacity: 0.75, - }).addTo(mapInstance); markerLayer = L.layerGroup().addTo(mapInstance); } diff --git a/web/templates/_settings_notifications.html b/web/templates/_settings_notifications.html index 5650dba..0bd6f2a 100644 --- a/web/templates/_settings_notifications.html +++ b/web/templates/_settings_notifications.html @@ -3,7 +3,8 @@ Wähle einen Kanal und entscheide, welche Events dich erreichen sollen.

-
+
@@ -17,12 +18,13 @@
+ placeholder="123456:ABC..." autocomplete="off" data-lpignore="true" data-1p-ignore>

Bot bei @BotFather anlegen, Token hier eintragen.

- +
diff --git a/web/templates/_settings_profil.html b/web/templates/_settings_profil.html index 1be5f61..b8527d0 100644 --- a/web/templates/_settings_profil.html +++ b/web/templates/_settings_profil.html @@ -1,6 +1,7 @@

Bewerbungsdaten

- +
@@ -15,38 +16,38 @@
- +
- +
- +
- +
- +
- +
- +
- +
@@ -94,11 +95,13 @@
- +
- +
diff --git a/web/templates/_wohnungen_body.html b/web/templates/_wohnungen_body.html index f23b41b..339fa7c 100644 --- a/web/templates/_wohnungen_body.html +++ b/web/templates/_wohnungen_body.html @@ -97,26 +97,7 @@ -
-
-
- {{ map_matched_with_coords }} / {{ map_matched_total }} passende Wohnungen mit Koordinaten - {% if map_matched_without_coords %} - · {{ map_matched_without_coords }} ohne Koordinaten - {% endif %} -
- {% if is_admin and map_matched_without_coords %} - - - - - {% endif %} -
+