Skip to content

Feat: forgot password functionality#151

Merged
EdenBernhard merged 13 commits intoblatt17from
feat/forgot-password-functionality
May 10, 2026
Merged

Feat: forgot password functionality#151
EdenBernhard merged 13 commits intoblatt17from
feat/forgot-password-functionality

Conversation

@EdenBernhard
Copy link
Copy Markdown
Collaborator

  • forgot password functionality with email link and redirection
  • show Password in the input fields
  • delete Account functionality

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Diese PR ergänzt den „Forgot Password“-Flow (E-Mail-Link + Reset-Seite) im Frontend und Backend und erweitert das Profil um modale Dialoge (E-Mail/Passwort ändern, Konto löschen). Zusätzlich wurden UI-Anpassungen für „Passwort anzeigen“ sowie Konfigurations-/Infrastruktur-Details (Env/CORS/DB-Pfad) aktualisiert.

Changes:

  • Backend: neue Endpunkte /auth/forgot-password und /auth/reset-password, Mailversand für Reset-Link, sowie DB-Table für Reset-Tokens.
  • Frontend: Forgot-Password Modal + Reset-Password Seite (Token aus Query), plus Password-Visibility Toggle in Input-Feldern.
  • Profil: Umstellung auf generische Modals für E-Mail/Passwort-Änderung und Konto-Löschen.

Reviewed changes

Copilot reviewed 18 out of 19 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
project/frontend/lib/auth.tsx API-URL konfigurierbar gemacht; Token-Refresh-Flow angepasst (mit Risiko bzgl. relativer URLs).
project/frontend/app/reset-password/page.tsx Neue Reset-Password Seite (Token aus URL, Passwortvalidierung, POST ans Backend).
project/frontend/app/homepage/forgotPassword.tsx Neues „Passwort vergessen“-Formular (Modal-Inhalt).
project/frontend/app/homepage/signin.tsx „Passwort vergessen?“ Link in Login-Modal ergänzt.
project/frontend/app/homepage/homepage.tsx Neues Modal-State „forgot“ und Einbindung des Forgot-Password Formulars.
project/frontend/app/components/fields.tsx Passwort-Visibility Toggle für Passwortfelder ergänzt.
project/frontend/app/profile/page.tsx Profilseite refaktoriert: Loading/Redirect, Modals für ChangeEmail/ChangePassword + Delete confirm.
project/frontend/app/profile/changeEmailPopup.tsx Neues Popup für E-Mail ändern via /users/me PATCH.
project/frontend/app/profile/changePasswordPopup.tsx Neues Popup für Passwort ändern (inkl. optionalem „forgot“-Modus).
project/frontend/app/recipeFinder/style.css Popup-Layout erweitert (stacked fields).
project/frontend/app/layout.tsx CSS-Import auf globals.css angepasst.
project/frontend/app/globals.css CSS-Variable Syntax korrigiert.
project/compose.yaml FRONTEND_URL Env für Backend ergänzt.
project/backend/Routes.py Forgot/Reset Passwort-Endpunkte ergänzt; Refresh-Token AccountID-Feld angepasst.
project/backend/Models.py Token-Model um refresh_token erweitert; neue Request-Models ergänzt.
project/backend/Auth.py Reset-Token Generierung/Validierung ergänzt.
project/backend/Database.py DB-Pfad auf /data/... umgestellt; PasswordResetToken Tabelle + Operationen ergänzt.
project/backend/EmailService.py Versand von Reset-Link E-Mail ergänzt.
project/backend/LazyCookAdministration.py CORS-Origin auf konfigurierbare FRONTEND_URL umgestellt.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread project/backend/Routes.py Outdated
Comment thread project/backend/Routes.py Outdated
Comment thread project/backend/Auth.py Outdated
Comment thread project/backend/Database.py Outdated
Comment thread project/frontend/app/components/fields.tsx
Comment thread project/frontend/app/profile/changePasswordPopup.tsx
Comment thread project/frontend/app/profile/changePasswordPopup.tsx
Comment thread project/frontend/lib/auth.tsx
Comment thread project/backend/Routes.py Outdated
Comment thread project/backend/Auth.py Outdated
EdenBernhard and others added 4 commits May 10, 2026 15:54
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown

Copilot AI commented May 10, 2026

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • fonts.googleapis.com
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node node /home/REDACTED/work/LazyCook/LazyCook/project/frontend/node_modules/.bin/next build (dns block)
    • Triggering command: /opt/hostedtoolcache/node/24.14.1/x64/bin/node /opt/hostedtoolcache/node/24.14.1/x64/bin/node /home/REDACTED/work/LazyCook/LazyCook/project/frontend/node_modules/next/dist/server/lib/start-server.js (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

EdenBernhard and others added 3 commits May 10, 2026 16:04
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 19 changed files in this pull request and generated 9 comments.

Comments suppressed due to low confidence (1)

project/frontend/app/profile/page.tsx:48

  • handleAccountDeletion wirft bei !res.ok einen Error, der im Click-Handler nicht abgefangen wird. Das führt zu unhandled promise rejections und keiner Nutzer-Rückmeldung, wenn das Löschen fehlschlägt. Bitte Fehler lokal abfangen und eine sichtbare Fehlermeldung im Modal anzeigen (und ggf. den Bestätigen-Button währenddessen deaktivieren).
    async function handleAccountDeletion() {
        const res = await fetchWithAuth(`${API_URL}/users/me`, { method: "DELETE" });
        if (!res.ok) throw new Error("Konto löschen fehlgeschlagen");
        logout();
        router.push("/");
    }


# Stelle sicher, dass das Verzeichnis existiert
DB_PATH.parent.mkdir(parents=True, exist_ok=True)
DB_PATH = Path("/data/LazyCookDB.sqlite3")
Comment on lines +132 to +138
res = await fetch(url, {
...options,
headers: {
...options.headers,
Authorization: `Bearer ${tokens.access_token}`,
},
});
Comment on lines +28 to +33
<button
type="button"
onClick={() => setShow((s) => !s)}
aria-label={show ? "Passwort verbergen" : "Passwort anzeigen"}
tabIndex={-1}
style={{
Comment on lines +70 to +87
async function handlePasswordChange() {
setPasswordMsg("");

// Bestätigung prüfen (nur im forgot-Modus relevant, aber sinnvoll auch beim Ändern)
if (newPassword !== confirmPassword) {
setPasswordMsg("Die Passwörter stimmen nicht überein.");
return;
}

try {
const endpoint = isForgot
? `${API_URL}/users/forgot-password`
: `${API_URL}/users/me`;

const body = isForgot
? { newPassword }
: { currentPassword, newPassword };

Comment on lines +79 to +93
try {
const endpoint = isForgot
? `${API_URL}/users/forgot-password`
: `${API_URL}/users/me`;

const body = isForgot
? { newPassword }
: { currentPassword, newPassword };

const fetcher = isForgot ? fetch : fetchWithAuth;

const res = await fetcher(endpoint, {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
Comment on lines +47 to +48
const data = await res.json();
setError(data.detail ?? "Fehler beim Zurücksetzen.");
Comment on lines +15 to +28
const handleSubmit = async () => {
setEmailBlurred(true);
if (!emailValid) return;
setBusy(true);
try {
await fetch(`${API_URL}/auth/forgot-password`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email }),
});
setSubmitted(true);
} finally {
setBusy(false);
}
Comment on lines +43 to +58
html = f"""
<div style="font-family: sans-serif; max-width: 500px; margin: auto;">
<h2>Hallo {name},</h2>
<p>du hast angefordert, dein Passwort bei <strong>Lazy Cook</strong> zurückzusetzen.</p>
<p>Klicke auf den Button, um ein neues Passwort festzulegen:</p>
<p style="text-align:center; margin: 24px 0;">
<a href="{resetLink}"
style="background:#030213; color:#fff; padding:12px 24px;
text-decoration:none; border-radius:6px; display:inline-block;">
Passwort zurücksetzen
</a>
</p>
<p style="font-size:12px; color:#666;">
Oder kopiere diesen Link in deinen Browser:<br>
<a href="{resetLink}">{resetLink}</a>
</p>
Comment thread project/backend/Auth.py
Comment on lines +146 to +165
def createPasswordResetToken(kontoId: int) -> str:
"""Generiert Klartext-Token (geht per Mail) und speichert nur den Hash in der DB."""
from Database import savePasswordResetToken
token = secrets.token_urlsafe(48)
expiresAt = datetime.now(timezone.utc) + timedelta(minutes=PASSWORD_RESET_EXPIRE_MINUTES)
savePasswordResetToken(kontoId, hashResetToken(token), expiresAt.isoformat())
return token


def validatePasswordResetToken(token: str) -> dict | None:
from Database import getPasswordResetToken
entry = getPasswordResetToken(hashResetToken(token))
if entry is None or entry["usedAt"] is not None:
return None
expiresAt = datetime.fromisoformat(entry["expiresAt"])
if expiresAt.tzinfo is None:
expiresAt = expiresAt.replace(tzinfo=timezone.utc)
if expiresAt < datetime.now(timezone.utc):
return None
return entry No newline at end of file
@EdenBernhard EdenBernhard merged commit 0501cd8 into blatt17 May 10, 2026
5 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants