Blatt17#170
Merged
Merged
Conversation
…g Ingridients List
… geschrieben. Die dazugehörigen Abhängigkeiten in requirements.txt angepasst. Sie werden in test_main.py aufgerufen. Namens faktorisierung ist schwer bei den Klassennamen da bei tests der pycharm Debugger eher auf klassen mit test_ vorne guckt. Deswegen leider test_
… Konto deletion reactivation.
* Rename models.py to Models.py * Rename auth.py to Auth.py * Rename Routes.py to routes.py * Added Refactoring Summary * Refactor documentation for code naming conventions * Fix spelling errors in refactoring documentation Corrected spelling of 'Refaktorisierung' and 'Frontend'. * Delete project/data/LazyCookDB.sqlite3 * AI Agent md's changed * Passwort und Email Änderung zu Popups geändert. und neugeordnet untereinander * Update README.md to mark tasks as completed for account management features * Add CI/CD pipeline and Super Linter configuration * Test für lint * Test ci/cd lint.yml * Test ci/cd lint.yml * Test ci/cd lint.yml * Test ci/cd lint.yml regex Filter * Test ci/cd lint.yml * Test ci/cd lint.yml * Test ci/cd lint.yml regex Filter angepasst * Tests für Database, passwort überprüfung und email überürufung wurden geschrieben. Die dazugehörigen Abhängigkeiten in requirements.txt angepasst. Sie werden in test_main.py aufgerufen. Namens faktorisierung ist schwer bei den Klassennamen da bei tests der pycharm Debugger eher auf klassen mit test_ vorne guckt. Deswegen leider test_ * ci pipeline abhägigkeit mit rein gemacht * Feat bei Ci yml entfernt * Update FILTER_REGEX_INCLUDE pattern in lint.yml * Update lint.yml * Enable validation for the entire codebase * Update lint.yml * Update lint.yml * Enable validation for all codebase in lint workflow * Remove Python Black and Markdown validation * Update lint workflow to include additional validations * Update FILTER_REGEX_INCLUDE to support YAML files * Update lint.yml * Update lint.yml * Refactor CI configuration to use Docker Compose v2 syntax and add GitHub Super Linter step * Test ci.yml * Update ci.yml * Enable Flake8 validation for Python files * Test ci.yml * Remove 'feat/*' branch from push trigger in CI configuration * Python black gelöst --------- Co-authored-by: Samuel Goebel <goebelsamuel@gmail.com> Co-authored-by: Eden Tabea Bernhard <105359952+EdenBernhard@users.noreply.github.com> Co-authored-by: Nicoolaus <162422307+Nicoolaus@users.noreply.github.com> Co-authored-by: Hellocrafting <alexanderfgroer@gmail.com> Co-authored-by: nicla <niclas.matzke@gmail.com> Co-authored-by: Hellocrafting <75727565+Hellocrafting@users.noreply.github.com>
# Conflicts: # project/data/LazyCookDB.sqlite3
# Conflicts: # .github/workflows/ci.yml # project/backend/tests/test_database.py # project/backend/tests/test_email.py # project/backend/tests/test_main.py # project/backend/tests/test_password.py
* Separate linter configuration into its own workflow file Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Update README.md to reflect linter workflow separation and installation instructions --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
# Conflicts: # project/backend/Database.py # project/backend/EmailService.py # project/backend/Routes.py
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>
* Feature: Forgot Password link in signin modal. Popup for Email Input. Konto deletion reactivation. * Feature: Email and Password change popup width changed * Feature: Fix problem with refresh token and include show Password * Feature: forgot password functionality works with redirection to homepage * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Fix: Copilot review suggestion * fix: make password visibility toggle keyboard focusable Agent-Logs-Url: https://github.com/GalacticCodeGambit/LazyCook/sessions/bf26f4ce-caa3-43fa-b940-13d7be23d7bf Co-authored-by: EdenBernhard <105359952+EdenBernhard@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding 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-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
# Conflicts: # project/backend/Routes.py # project/frontend/app/components/fields.tsx # project/frontend/app/homepage/forgotPassword.tsx # project/frontend/app/profile/changePasswordPopup.tsx # project/frontend/app/profile/page.tsx # project/frontend/lib/auth.tsx
* Feature: Forgot Password link in signin modal. Popup for Email Input. Konto deletion reactivation. * Feature: Email and Password change popup width changed * Feature: Fix problem with refresh token and include show Password * Feature: forgot password functionality works with redirection to homepage * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Fix: Copilot review suggestion * Fix: Copilot review suggestion * Fix: Copilot review suggestion * Fix: Copilot review suggestion * Feat: Ingredients suggestions. Top 5 most typed shown in popup * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Feat: Ingredients suggestions. Top 5 most typed shown in popup --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Recipe algorithm
Removed participant names from the review protocol.
* Datenschutz und Impressum MD's hinzugefügt und calls angepasst. * Datenschutz und Impressum MD's hinzugefügt und calls angepasst. (Kommentar war invalide) * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Update navigation comments for Datenschutz and Impressum links * Fix Datenschutz and Impressum, Add Datenschutz and Impressum pages with navigation links * Add MarkdownRenderer component for rendering Markdown content in Impressum and Datenschutz pages * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * refactor: extract shared markdown reader helper Agent-Logs-Url: https://github.com/GalacticCodeGambit/LazyCook/sessions/9460d714-3139-45d5-b2e2-e6ee6e3d8563 Co-authored-by: GalacticCodeGambit <150372421+GalacticCodeGambit@users.noreply.github.com> * Update Impressum.md --------- Co-authored-by: F <150372421+GalacticCodeGambit@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR extends LazyCook with (1) password reset (“Passwort vergessen” + Reset-Link per Mail + Reset-Page), (2) ingredient-usage tracking to show “Top 5” ingredient suggestions in the recipe finder popup, and (3) markdown-rendered legal pages (Impressum/Datenschutz). It also splits linting into a dedicated GitHub Actions workflow and refactors parts of the frontend auth/profile UI.
Changes:
- Added forgot/reset-password flow end-to-end (backend routes + email template + frontend pages/modals).
- Added ingredient usage tracking + “Top ingredients” API and frontend suggestion badges with localStorage caching.
- Added markdown rendering utilities and pages for Impressum/Datenschutz; added separate lint workflow and README updates.
Reviewed changes
Copilot reviewed 37 out of 38 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Adds setup/lint docs and badges; installation instructions updated. |
| project/frontend/package.json | Adds react-markdown + remark-gfm dependencies for markdown pages. |
| project/frontend/lib/auth.tsx | Makes API base URL configurable; adjusts token handling and authenticated fetch logic. |
| project/frontend/app/reset-password/page.tsx | New reset-password page consuming the token query param and calling backend reset endpoint. |
| project/frontend/app/recipeFinder/style.css | Adds styling for ingredient suggestion badges and stacked popup fields. |
| project/frontend/app/recipeFinder/popup.tsx | Adds “Top 5” ingredient suggestion badge UI and focus handling. |
| project/frontend/app/recipeFinder/page.tsx | Loads/caches suggestions, updates them after search, and passes them into the popup. |
| project/frontend/app/profile/page.tsx | Refactors profile settings to use reusable modal components for email/password change and deletion confirm. |
| project/frontend/app/profile/changePasswordPopup.tsx | New change-password popup component (used from profile). |
| project/frontend/app/profile/changeEmailPopup.tsx | New change-email popup component (used from profile). |
| project/frontend/app/lib/read-markdown.ts | Server-side helper to read markdown files from the homepage markdown directory. |
| project/frontend/app/layout.tsx | Fixes global stylesheet import name. |
| project/frontend/app/impressum/page.tsx | New Impressum page rendering existing markdown via renderer. |
| project/frontend/app/homepage/signin.tsx | Adds “Passwort vergessen?” entry point and improves error classification. |
| project/frontend/app/homepage/MarkdownFiles/Impressum.md | Adds Impressum markdown content. |
| project/frontend/app/homepage/MarkdownFiles/Datenschutz.md | Adds Datenschutzerklärung markdown content. |
| project/frontend/app/homepage/homepage.tsx | Adds navbar links to legal pages and a “forgot password” modal state. |
| project/frontend/app/homepage/forgotPassword.tsx | New forgot-password modal form calling backend request endpoint. |
| project/frontend/app/globals.css | Fixes a CSS variable typo (10 px → 10px). |
| project/frontend/app/datenschutz/page.tsx | New Datenschutz page rendering existing markdown via renderer. |
| project/frontend/app/components/markdown-renderer.tsx | New markdown renderer component using react-markdown + GFM. |
| project/frontend/app/components/fields.tsx | Enhances Field component with password show/hide toggle. |
| project/Dockerfile-frontend | Pins Node image tag more specifically. |
| project/compose.yaml | Adds FRONTEND_URL env var for backend to build reset links / CORS origin. |
| project/backend/SearchRecipeNames.py | Adds helper to find recipes by name substring. |
| project/backend/Routes.py | Adds forgot/reset-password endpoints; adds recipes search usage tracking + top ingredients endpoints; adjusts refresh account mapping. |
| project/backend/RecipeSUCUK.py | Adds/updates recipe search algorithm draft (SUCUK). |
| project/backend/Recipe.py | Refactors recipe model, persistence helpers, and matching/rating helpers. |
| project/backend/Models.py | Extends Token model + adds request models for password reset and recipe search. |
| project/backend/LazyCookAdministration.py | Makes CORS allowed origin configurable via FRONTEND_URL. |
| project/backend/Ingridient.py | Removes old misspelled Ingredient class file. |
| project/backend/Ingredient.py | Adds new Ingredient class file. |
| project/backend/EmailService.py | Adds password-reset email sending helper. |
| project/backend/Database.py | Enables WAL; renames Ingredient table; adds IngredientUsage + PasswordResetToken tables and new helper queries. |
| project/backend/Auth.py | Adds password reset token generation/validation. |
| docs/Review-Protokoll-01.md | Adds a review protocol document. |
| .github/workflows/lint.yml | Introduces dedicated lint workflow using GitHub Super-Linter. |
| .github/workflows/ci.yml | Removes linter job from CI workflow (now in lint.yml). |
Comments suppressed due to low confidence (4)
project/backend/Database.py:281
getIngridientByNameist aktuell kaputt: es selektiert ausRecipeund vergleichtid = ?, obwohl der Parameternameheißt. Außerdem wird(name)statt(name,)übergeben. Das führt dazu, dass Ingredient-Lookups fehlschlagen. Bitte aufSELECT id, amountType FROM Ingredient WHERE name = ?umstellen und korrektes Tuple verwenden.
def getIngridientByName(name: str):
with getDB() as con:
cur = con.cursor()
cur.execute(
"""
SELECT id, amountType
FROM Recipe
WHERE id = ?
""",
(name),
)
row = cur.fetchone()
return dict(row) if row else None
project/backend/Database.py:345
- Die SQL in
getAllocatedRecipesist syntaktisch/inhaltlich fehlerhaft (Komma nach JOIN,Wherenach Komma, Join-Bedingungrid=idist unklar,Exists_from.idscheint nicht zu existieren). Bitte Query korrigieren oder die Funktion entfernen, falls ungenutzt.
def getAllocatedRecipes(name: str) -> list[dict]:
with getDB() as con:
cur = con.cursor()
cur.execute(
"""
SELECT rid
FROM Exists_from
Inner Join Ingredient on rid=id,
Where Exists_from.id = ?
""",
(name,),
)
rows = cur.fetchall()
return [dict(row) for row in rows]
project/backend/Recipe.py:66
- Die Methode heißt
getingredients, aber der SUCUK-Algorithmus nutztgetIngredients()/recipe.getIngredients(). Dadurch gibt es zur Laufzeit einen AttributeError. Bitte die Methode konsistent benennen (und ggf. alle Call-Sites anpassen).
def getingredients(self) -> list[Ingredient]:
return self.__ingredients
def setIngredient(self, ingredients: list[Ingredient]):
self.__ingredients = ingredients
project/backend/Database.py:69
- Schema-Änderung:
initDB()erstellt jetzt eine TabelleIngredient(statt zuvorIngridient). Da die DB inproject/datapersistiert wird, bleibt eine bestehende alte Tabelle unverändert bestehen (keine Migration) und Queries, dieIngredienterwarten, können auf älteren Datenbanken fehlschlagen. Bitte Migration/Kompatibilität (Rename/Copy) vorsehen oder wenigstens beim Startup prüfen und eine klare Fehlermeldung geben.
cur.execute("""
CREATE TABLE IF NOT EXISTS Ingredient (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT UNIQUE NOT NULL,
amountType VARCHAR(30) NOT NULL
)
""")
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| 1. Klonen das Repository: | ||
| `git clone https://github.com/GalacticCodeGambit/LazyCook.git` | ||
| 2. Navigieren zum Projektverzeichnis: | ||
| `cd LazyCook/Project` |
|
|
||
| Für die Funktion [#115](https://github.com/GalacticCodeGambit/LazyCook/issues/115) von Email Versenden/Empfangen muss im Ordner `project/` eine `.env` Datei mit den folgenden Variablen angelegt werden: | ||
| ``` | ||
| EMAIL_HOST=<dein.mail@gmail.com> |
Comment on lines
111
to
+139
| @@ -118,23 +121,22 @@ async function fetchWithAuth(url: string, options: RequestInit = {}): Promise<Re | |||
| const refreshToken = getRefreshToken(); | |||
| if (!refreshToken) throw new Error("Nicht eingeloggt"); | |||
|
|
|||
| let tokens; | |||
| try { | |||
| const tokens = await apiRefreshTokens(refreshToken); | |||
| saveTokens(tokens.access_token, tokens.refresh_token); | |||
|
|
|||
| // Erneuter Versuch mit neuem Access Token | |||
| res = await fetch(API_URL+url, { | |||
| ...options, | |||
| headers: { | |||
| ...options.headers, | |||
| Authorization: `Bearer ${tokens.access_token}`, | |||
| }, | |||
| }); | |||
| tokens = await apiRefreshTokens(refreshToken); | |||
| } catch { | |||
| // Refresh fehlgeschlagen → komplett ausloggen | |||
| clearTokens(); | |||
| throw new Error("Session abgelaufen"); | |||
| } | |||
| saveTokens(tokens.access_token, tokens.refresh_token); | |||
|
|
|||
| res = await fetch(url, { | |||
| ...options, | |||
| headers: { | |||
| ...options.headers, | |||
| Authorization: `Bearer ${tokens.access_token}`, | |||
| }, | |||
| }); | |||
Comment on lines
+77
to
+114
| def sendPasswordResetEmail(to_email: str, name: str, resetLink: str) -> None: | ||
| try: | ||
| msg = MIMEMultipart("alternative") | ||
| msg["Subject"] = "Passwort zurücksetzen – Lazy Cook" | ||
| msg["From"] = gmailUser | ||
| msg["To"] = to_email | ||
|
|
||
| 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> | ||
| <p>Der Link ist <strong>30 Minuten</strong> gültig.</p> | ||
| <p>Falls du das nicht angefordert hast, ignoriere diese E-Mail einfach – dein Passwort bleibt unverändert.</p> | ||
| <br> | ||
| <p>– Das Lazy Cook Team</p> | ||
| </div> | ||
| """ | ||
| msg.attach(MIMEText(html, "html")) | ||
|
|
||
| with smtplib.SMTP_SSL("smtp.gmail.com", 465) as server: | ||
| server.login(gmailUser, gmailPassword) | ||
| server.sendmail(gmailUser, to_email, msg.as_string()) | ||
|
|
||
| except Exception as e: | ||
| print(f"E-Mail Fehler: {e}") | ||
| raise |
Comment on lines
+19
to
22
| import hashlib | ||
|
|
||
| PASSWORD_RESET_EXPIRE_MINUTES = 30 | ||
|
|
Comment on lines
+20
to
+23
| if not zid: | ||
| return False | ||
| else: | ||
| addIngredientToRecipe(zid, rid, ingridient.getAmount()) |
Comment on lines
+22
to
+28
| def __filterRecipes(recipes: list[Recipe], Ingredient: Ingredient) -> list[Recipe]: | ||
| for recipe in recipes: | ||
| for recipeIngredient in recipe.getIngredients(): | ||
| if recipeIngredient.getName() == Ingredient.getName(): | ||
| recipe.incrementMatching() | ||
| recipe.setRating(recipe.getMatching() / len(recipe.getIngredients())) | ||
| return recipes |
Comment on lines
+52
to
+62
| ini = [] | ||
| ini.append(Ingredient("Linguine", 10)) | ||
| ini.append(Ingredient("Fresh Basil", 10)) | ||
| ini.append(Ingredient("Pine Nuts", 10)) | ||
| ini.append(Ingredient("Parmesan", 10)) | ||
| ini.append(Ingredient("Ground Beef", 10)) | ||
| ini.append(Ingredient("Cumin", 10)) | ||
| ini.append(Ingredient("Cucumber", 10)) | ||
| arr = findRecipes(ini) | ||
| for i in arr: | ||
| print(i.getName() + " " + str(i.getRating())) |
Comment on lines
+5
to
+31
| class Ingredient: | ||
| def __init__(self, name: str, amount: float): | ||
| self.__name = name | ||
| self.__amount = amount | ||
|
|
||
| def getName(self) -> str: | ||
| return self.__name | ||
|
|
||
| def setName(self, name: str): | ||
| self.__name = name | ||
|
|
||
| def getAmount(self) -> float: | ||
| return self.__amount | ||
|
|
||
| def setAmount(self, amount: float): | ||
| self.__amount = amount | ||
|
|
||
| def setAmountType(self, amountType: str): | ||
| self.__amountType = amountType | ||
|
|
||
| def getAmountType(self): | ||
| return self.__amountType | ||
|
|
||
| def saveInDB(self): | ||
| if not self.__amountType: | ||
| return False | ||
| else: |
Comment on lines
+95
to
+111
| 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), | ||
| }); | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.