From 1c66bbb89a92976cdbdd0738363c38bc0e83d43a Mon Sep 17 00:00:00 2001
From: Hannah <hz018@hdm-stuttgart.de>
Date: Wed, 13 Dec 2023 10:38:32 +0100
Subject: [PATCH] #31 #37 Bug Fix

---
 growbros-frontend/src/App.tsx                 | 48 ++--------------
 growbros-frontend/src/jwt/Cookies.ts          | 57 +++++++++++++++++--
 growbros-frontend/src/pages/Login.tsx         | 43 +++++++++++---
 .../growbros/auth/AuthenticationService.java  |  3 +-
 .../growbros/security/ApplicationConfig.java  |  6 +-
 .../security/SecurityConfiguration.java       |  2 +-
 6 files changed, 96 insertions(+), 63 deletions(-)

diff --git a/growbros-frontend/src/App.tsx b/growbros-frontend/src/App.tsx
index ca552f0..2e7acd8 100644
--- a/growbros-frontend/src/App.tsx
+++ b/growbros-frontend/src/App.tsx
@@ -2,61 +2,23 @@ import "./App.css";
 import Home from "./pages/Home";
 import Garten from "./pages/Garten";
 import Suche from "./pages/Suche";
-import {Routes, Route, useLocation} from "react-router-dom";
+import {Routes, Route} from "react-router-dom";
 import Wunschliste from "./pages/Wunschliste";
 import PlantDetails from "./components/PlantDetails";
 import Navbar from "./components/Navbar.tsx";
 import NavbarRegistrationAndLogin from "./components/NavbarRegistrationAndLogin.tsx";
-import {useEffect, useState} from "react";
-import {deleteJwtInCookie, getCookie} from "./jwt/Cookies.ts";
+import {useState} from "react";
+import {checkJwtStatus, deleteJwtCookie} from "./jwt/Cookies.ts";
 import Login from "./pages/Login.tsx";
 import Register from "./pages/Register.tsx";
 
 function App() {
   const [isLoggedIn, setIsLoggedIn] = useState(false);
-  const location = useLocation();
 
-  useEffect(() => {
-    console.log("check jwt-status")
-    const jwtCookie = getCookie("Jwt");
-    console.log("Jwt Cookie " + jwtCookie)
-
-    if (!jwtCookie) {
-      // Wenn der JWT-Cookie nicht vorhanden ist
-      setIsLoggedIn(false);
-      console.log("Jwt not there")
-      return;
-    }
-
-    // Der JWT-Cookie ist vorhanden - Überprüfe die Gültigkeit
-    // @ts-ignore
-    const tokenParts = jwtCookie.split('.');
-    if (tokenParts.length !== 3) {
-      // Ungültiges JWT-Format (nicht genau 3 Teile)
-      setIsLoggedIn(false);
-      console.log("Jwt is not valid")
-      return;
-    }
-
-    const payload = JSON.parse(atob(tokenParts[1]));
-    const expirationTime = payload.exp * 1000; //Umwandlung in Millisekunden
-    console.log(expirationTime)
-    console.log(Date.now())
-
-    // Überprüfe das Ablaufdatum
-    if (Date.now() > expirationTime) {
-      // JWT ist abgelaufen
-      setIsLoggedIn(false);
-      console.log("Jwt is expired")
-      return;
-    }
-    console.log("Token is there and valid")
-    // JWT ist vorhanden und gültig
-    setIsLoggedIn(true);
-  }, [location.pathname]);
+  checkJwtStatus(setIsLoggedIn);
 
   const handleLogout = async () => {
-    deleteJwtInCookie();
+    deleteJwtCookie();
     setIsLoggedIn(false);
   };
 
diff --git a/growbros-frontend/src/jwt/Cookies.ts b/growbros-frontend/src/jwt/Cookies.ts
index 91f4f00..54ff134 100644
--- a/growbros-frontend/src/jwt/Cookies.ts
+++ b/growbros-frontend/src/jwt/Cookies.ts
@@ -1,8 +1,12 @@
-export function setCookie(name: string, value: any, expirationDate: Date){
+import {useLocation} from "react-router-dom";
+import {SetStateAction, useEffect} from "react";
+
+export function setCookie(name: string, value: any, expirationDate: Date) {
     let expires = "expires=" + expirationDate;
     document.cookie = `${name}=${value}; ${expires}`
 }
-export function getCookie(name: string | any[]){
+
+export function getCookie(name: string | any[]) {
 
     const cDecoded = decodeURIComponent(document.cookie);
     const cArray = cDecoded.split("; ");
@@ -10,14 +14,59 @@ export function getCookie(name: string | any[]){
 
     cArray.forEach(element => {
 
-        if(element.indexOf(<string>name) == 0){
+        if (element.indexOf(<string>name) == 0) {
             result = element.substring(name.length + 1)
         }
     })
     return result;
 }
-export function deleteJwtInCookie(){
+
+export function deleteJwtCookie() {
 
     document.cookie = `Jwt=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
     console.log("deleted Cookie ")
 }
+
+export function checkJwtStatus(setIsLoggedIn: { (value: SetStateAction<boolean>): void; (arg0: boolean): void; }) {
+    const location = useLocation();
+
+    return useEffect(() => {
+        console.log("check jwt-status")
+        const jwtCookie = getCookie("Jwt");
+        console.log("Jwt Cookie " + jwtCookie)
+
+        if (!jwtCookie) {
+            // Wenn der JWT-Cookie nicht vorhanden ist
+            setIsLoggedIn(false);
+            console.log("Jwt not there")
+            return;
+        }
+
+        // Der JWT-Cookie ist vorhanden - Überprüfe die Gültigkeit
+        // @ts-ignore
+        const tokenParts = jwtCookie.split('.');
+        if (tokenParts.length !== 3) {
+            // Ungültiges JWT-Format (nicht genau 3 Teile)
+            setIsLoggedIn(false);
+            console.log("Jwt is not valid")
+            return;
+        }
+
+        const payload = JSON.parse(atob(tokenParts[1]));
+        const expirationTime = payload.exp * 1000; //Umwandlung in Millisekunden
+        console.log(expirationTime)
+        console.log(Date.now())
+
+        // Überprüfe das Ablaufdatum
+        if (Date.now() > expirationTime) {
+            // JWT ist abgelaufen
+            setIsLoggedIn(false);
+            console.log("Jwt is expired")
+            return;
+        }
+        console.log("Token is there and valid")
+        // JWT ist vorhanden und gültig
+        setIsLoggedIn(true);
+    }, [location.pathname]);
+
+}
diff --git a/growbros-frontend/src/pages/Login.tsx b/growbros-frontend/src/pages/Login.tsx
index b30ef8d..bca3ce7 100644
--- a/growbros-frontend/src/pages/Login.tsx
+++ b/growbros-frontend/src/pages/Login.tsx
@@ -1,7 +1,12 @@
 import {useState} from "react";
-import {setCookie} from "../jwt/Cookies.ts";
+import {deleteJwtCookie, setCookie} from "../jwt/Cookies.ts";
+import {jwtDecode} from "jwt-decode";
+import {useNavigate} from "react-router-dom";
 
 function Login() {
+
+    const navigate = useNavigate();
+
     const [email, setEmail] = useState('');
     const [password, setPassword] = useState('');
 
@@ -11,10 +16,32 @@ function Login() {
     };
     const handleLogin = async () => {
         try {
-            const res = await fetch("http://localhost:8080/api/v1/auth/authenticate",{method:"POST",body:JSON.stringify({email:email,password:password})})
-            const {token} = await res.json();
-            setCookie("Jwt",token, 1);
-            console.log(token);
+            const res = await fetch("http://localhost:8080/api/v1/auth/authenticate",{
+                method:"POST",
+                body:JSON.stringify({email:email,password:password}),
+                headers: {
+                    "Content-Type": "application/json",
+                },
+            });
+            if (res.ok) { //delete old cookie and set new one with new expiration date
+                const { token } = await res.json();
+                console.log(token);
+                deleteJwtCookie();
+                const decodedToken = jwtDecode(token);
+                console.log(decodedToken);
+                // @ts-ignore
+                const expirationDate = new Date(decodedToken.exp * 1000); //*1000 Anzahl der Sekunden seit 1.1.1970 darstellt - JS arbeitet jedoch normalerweise mit Millisekunden
+                setCookie("Jwt",token, expirationDate);
+                document.cookie = `Jwt=${token};expires=${new Date(expirationDate).toUTCString()};path=/;`;
+
+                navigate('/');
+
+            } else {
+                window.alert(`Fehler bei der Anmeldung: ${res.status} - ${res.statusText}`);
+                navigate('/login');
+                console.error('Fehler bei der Anmeldung:', res.status, res.statusText);
+            }
+
         } catch (error:any) {
             console.error('Fehler bei der Anmeldung:', error.message);
         }
@@ -24,9 +51,9 @@ function Login() {
         <main>
             <div>
                 <h2>Login</h2>
-                <form>
+                <form onSubmit={handleSubmit}>
                     <div>
-                        <label>Benutzername oder E-Mail:</label>
+                        <label>E-Mail:</label>
                         <input
                             type="text"
                             value={email}
@@ -42,9 +69,7 @@ function Login() {
                         />
                     </div>
                     <div>
-                        <form onSubmit={handleSubmit}>
                             <button type="submit">Anmelden</button>
-                        </form>
                     </div>
                 </form>
             </div>
diff --git a/src/main/java/hdm/mi/growbros/auth/AuthenticationService.java b/src/main/java/hdm/mi/growbros/auth/AuthenticationService.java
index acecf64..9cba373 100644
--- a/src/main/java/hdm/mi/growbros/auth/AuthenticationService.java
+++ b/src/main/java/hdm/mi/growbros/auth/AuthenticationService.java
@@ -46,7 +46,8 @@ public class AuthenticationService {
                 )
         );
         var user = repository.findByEmail(request.getEmail()) //wenn der Nutzername und Passwort korrekt sind wird ein Token generiert
-                .orElseThrow();
+                .orElseThrow(); // = Methode von Optional -> wird auf das Optionale angewendet, das durch repository.findByEmail zurückgegeben wird
+        // Wenn Benutzer gefunden ->  das Optional mit dem Benutzer-Objekt gefüllt. Andernfalls wird eine NoSuchElementException ausgelöst.
         var jwtToken = jwtService.generateToken(user);
         return AuthenticationResponse.builder()
                 .token(jwtToken)
diff --git a/src/main/java/hdm/mi/growbros/security/ApplicationConfig.java b/src/main/java/hdm/mi/growbros/security/ApplicationConfig.java
index 5c2d13d..cdcfea2 100644
--- a/src/main/java/hdm/mi/growbros/security/ApplicationConfig.java
+++ b/src/main/java/hdm/mi/growbros/security/ApplicationConfig.java
@@ -17,16 +17,12 @@ import org.springframework.security.crypto.password.PasswordEncoder;
 @RequiredArgsConstructor
 public class ApplicationConfig {
     private final UserRepository repository;
-    @Bean
+    @Bean //Schnittstelle die verwendet wird, um Benutzerdetails zu laden
     public UserDetailsService userDetailsService() {
         return username -> repository.findByEmail(username)
                 .orElseThrow(() -> new UsernameNotFoundException("User not found"));
     }
 
-    /**
-     * Fetcht die Benutzer Daten und decodiert das Passwort.
-     * @return
-     */
     @Bean
     public AuthenticationProvider authenticationProvider() {
         DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
diff --git a/src/main/java/hdm/mi/growbros/security/SecurityConfiguration.java b/src/main/java/hdm/mi/growbros/security/SecurityConfiguration.java
index 3adcd66..ccabf85 100644
--- a/src/main/java/hdm/mi/growbros/security/SecurityConfiguration.java
+++ b/src/main/java/hdm/mi/growbros/security/SecurityConfiguration.java
@@ -29,7 +29,7 @@ public class SecurityConfiguration {
     public SecurityFilterChain securityFilterChain(HttpSecurity http, MvcRequestMatcher.Builder mvc) throws Exception {
         http
                 .csrf(csrf -> {
-                    csrf.disable();
+                    csrf.disable(); //CSRF-Schutz deaktivieren
                     csrf.ignoringRequestMatchers(toH2Console());
                 })
                 .authorizeHttpRequests((authorize) -> //whitelist
-- 
GitLab