From 2609d3504a0f3397998c9098e1bcddc46766313d Mon Sep 17 00:00:00 2001
From: EiSiMo
Date: Tue, 21 Apr 2026 14:20:31 +0200
Subject: [PATCH] guard double-apply, hide error msg, wohnungen polish,
bitwarden block
- /actions/apply now no-ops (returns fresh partial) when a running
application exists for this user+flat, or when a previous one succeeded.
The list button was already visually disabled; this closes the direct-POST
and double-click loopholes
- Drop the one-line error message under flat entries in the list
(bewerbung_detail still shows the full message + the forensic ZIP report)
- Strip "min morgens" commute chip from the list; alert._flat_payload sends
an empty connectivity dict so Maps.calculate_score is no longer called on
every flat. Maps.calculate_score + Flat.connectivity stay in the codebase
for easy re-enable (one-line swap in _flat_payload)
- List entry shows "vor 23 min" instead of "entdeckt vor 23 min"
- Bitwarden: rename profile email/immomio fields to opaque names
(contact_addr, immomio_login, immomio_secret) + add data-bwignore across
every settings form / input. Server-side update_profile maps the new
field names back to the existing DB columns
Co-Authored-By: Claude Opus 4.7 (1M context)
---
alert/main.py | 6 ++++-
web/app.py | 16 ++++++++++---
web/templates/_settings_notifications.html | 6 ++---
web/templates/_settings_profil.html | 28 +++++++++++-----------
web/templates/_settings_users.html | 4 ++--
web/templates/_wohnungen_body.html | 6 +----
6 files changed, 38 insertions(+), 28 deletions(-)
diff --git a/alert/main.py b/alert/main.py
index d56a357..6dad3a2 100644
--- a/alert/main.py
+++ b/alert/main.py
@@ -31,7 +31,11 @@ class FlatAlerter:
self.last_response_hash = ""
def _flat_payload(self, flat: Flat) -> dict:
- c = flat.connectivity
+ # Transit-connectivity is disabled to save Google-Maps quota. The
+ # helper on Flat (flat.connectivity → Maps.calculate_score) is
+ # intentionally kept so it can be re-enabled without re-writing code —
+ # just replace the empty dict with `flat.connectivity` when needed.
+ c: dict = {}
lat, lng = flat.coords
return {
"id": flat.id,
diff --git a/web/app.py b/web/app.py
index 92c763c..dc292de 100644
--- a/web/app.py
+++ b/web/app.py
@@ -544,6 +544,13 @@ async def action_apply(
flat = db.get_flat(flat_id)
if not flat:
raise HTTPException(404, "flat not found")
+ last = db.last_application_for_flat(user["id"], flat_id)
+ if last and last["finished_at"] is None:
+ # Another apply is already running for this user+flat; don't queue a second.
+ return _wohnungen_partial_or_redirect(request, user)
+ if last and last["success"] == 1:
+ # Already successfully applied — no point in re-running.
+ return _wohnungen_partial_or_redirect(request, user)
db.log_audit(user["username"], "trigger_apply", f"flat_id={flat_id}",
user_id=user["id"], ip=client_ip(request))
_kick_apply(user["id"], flat_id, flat["link"], "user")
@@ -838,11 +845,14 @@ async def action_profile(request: Request, user=Depends(require_user)):
try: return int(form.get(name) or 0)
except ValueError: return 0
+ # Field names are intentionally opaque ("contact_addr", "immomio_login",
+ # "immomio_secret") to keep password managers — specifically Bitwarden —
+ # from recognising the form as a login/identity form and autofilling.
db.update_profile(user["id"], {
"salutation": form.get("salutation", ""),
"firstname": form.get("firstname", ""),
"lastname": form.get("lastname", ""),
- "email": form.get("email", ""),
+ "email": form.get("contact_addr", ""),
"telephone": form.get("telephone", ""),
"street": form.get("street", ""),
"house_number": form.get("house_number", ""),
@@ -855,8 +865,8 @@ async def action_profile(request: Request, user=Depends(require_user)):
"wbs_adults": _i("wbs_adults"),
"wbs_children": _i("wbs_children"),
"is_prio_wbs": 1 if _b("is_prio_wbs") else 0,
- "immomio_email": form.get("immomio_email", ""),
- "immomio_password": form.get("immomio_password", ""),
+ "immomio_email": form.get("immomio_login", ""),
+ "immomio_password": form.get("immomio_secret", ""),
})
db.log_audit(user["username"], "profile.updated", user_id=user["id"], ip=client_ip(request))
return RedirectResponse("/einstellungen/profil", status_code=303)
diff --git a/web/templates/_settings_notifications.html b/web/templates/_settings_notifications.html
index 0bd6f2a..23f952e 100644
--- a/web/templates/_settings_notifications.html
+++ b/web/templates/_settings_notifications.html
@@ -4,7 +4,7 @@