Rechtstexte, FinalFlux-Überarbeitung, neue Login-Optik, Konto-Löschung-Fix, BTTF-Farbrelaunch
- Rechtsseiten: Impressum-Platzhalter + echte Nutzungsbedingungen/AGB, Datenschutz (DSGVO) und Richtlinien; LegalController/ImpressumController, Footer app-weit verlinkt, Seiten als permitAll freigegeben. - FinalFlux: 28 Themen / ~742 Fragen überarbeitet (plausible Distraktoren statt Dummy-Antworten, echte Erklärungen) + echte Lehrtexte je Seite; Netzwerktopologien mit Inline-SVG-Diagrammen (Stern/Bus/Ring/Mesh/Baum). - Login/Registrierung als kombiniertes Dual-Panel (Slide-Overlay + Neon-Hover- Button), ausgelagert nach auth.css; Register-Duplikat -> /?registerError. - Konto löschen repariert: @Transactional + Löschen von Spielständen, Achievements und Profilbild-Datei (DSGVO Art. 17). Impressum-Zurück-Link login-abhängig. - App-weiter Farb-Relaunch auf "Back to the Future"-Palette: Feuer-Amber primär + Flux-Blau sekundär, warmer Glow; Dark/Light bleiben. Spiele-Feedback ohne Grün: richtig = Blau + Haken, falsch = Rot + Kreuz (neue Tokens --success/--danger/--secondary). Legacy-Cyan in style.css auf Variablen. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -19,7 +19,7 @@ public class SecurityConfig {
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers("/", "/login", "/register", "/css/**", "/js/**", "/img/**").permitAll()
|
||||
.requestMatchers("/", "/login", "/register", "/impressum", "/nutzungsbedingungen", "/datenschutz", "/richtlinien", "/css/**", "/js/**", "/img/**").permitAll()
|
||||
.requestMatchers("/admin/**").hasRole("ADMIN") // NEU: Adminbereich absichern
|
||||
.requestMatchers("/api/users/**").hasRole("ADMIN")
|
||||
.anyRequest().authenticated()
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.example.mindflux.controller;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
@Controller
|
||||
public class ImpressumController {
|
||||
|
||||
@GetMapping("/impressum")
|
||||
public String impressum() {
|
||||
return "impressum"; // verweist auf impressum.html in src/main/resources/templates
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.example.mindflux.controller;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
/**
|
||||
* Liefert die statischen Rechts-/Informationsseiten aus dem Footer:
|
||||
* AGB / Nutzungsbedingungen, Datenschutzerklärung und Community-Richtlinien.
|
||||
*/
|
||||
@Controller
|
||||
public class LegalController {
|
||||
|
||||
@GetMapping("/nutzungsbedingungen")
|
||||
public String nutzungsbedingungen() {
|
||||
return "legal/nutzungsbedingungen";
|
||||
}
|
||||
|
||||
@GetMapping("/datenschutz")
|
||||
public String datenschutz() {
|
||||
return "legal/datenschutz";
|
||||
}
|
||||
|
||||
@GetMapping("/richtlinien")
|
||||
public String richtlinien() {
|
||||
return "legal/richtlinien";
|
||||
}
|
||||
}
|
||||
@@ -179,6 +179,21 @@ public class ProfileController {
|
||||
@PostMapping("/profile/delete")
|
||||
public String deleteProfile(Principal principal, Authentication authentication, HttpServletRequest request, HttpServletResponse response) {
|
||||
String username = principal.getName();
|
||||
|
||||
// Profilbild-Datei von der Platte entfernen (DB-Daten löscht der Service in einer Transaktion).
|
||||
User user = userService.findByUsername(username);
|
||||
if (user != null) {
|
||||
String profilePicture = user.getProfilePicture();
|
||||
if (profilePicture != null && !profilePicture.trim().isEmpty()) {
|
||||
try {
|
||||
Path picturePath = Paths.get(System.getProperty("user.dir"), "uploads", "profiles", profilePicture);
|
||||
Files.deleteIfExists(picturePath);
|
||||
} catch (IOException e) {
|
||||
System.err.println("Fehler beim Löschen des Profilbilds: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
userService.deleteByUsername(username);
|
||||
new SecurityContextLogoutHandler().logout(request, response, authentication);
|
||||
return "redirect:/?logout";
|
||||
|
||||
@@ -30,8 +30,8 @@ public class RegisterController {
|
||||
|
||||
// Prüfen, ob Benutzername schon existiert
|
||||
if (userService.findByUsername(user.getUsername()) != null) {
|
||||
model.addAttribute("error", "Benutzername bereits vergeben.");
|
||||
return "register";
|
||||
// Zurück zur kombinierten Login/Signup-Seite mit geöffnetem Signup-Panel
|
||||
return "redirect:/?registerError";
|
||||
}
|
||||
|
||||
// Passwort verschlüsseln
|
||||
|
||||
@@ -7,4 +7,7 @@ import java.util.List;
|
||||
|
||||
public interface AchievementRepository extends JpaRepository<Achievement, Long> {
|
||||
List<Achievement> findByUsername(String username);
|
||||
|
||||
/** Alle Achievements eines Spielers löschen (z. B. beim Löschen des Kontos). */
|
||||
void deleteByUsername(String username);
|
||||
}
|
||||
|
||||
@@ -15,4 +15,7 @@ public interface GameScoreRepository extends JpaRepository<GameScore, Long> {
|
||||
|
||||
/** Wie oft ein Spieler ein Spiel abgeschlossen hat. */
|
||||
long countByUsernameAndGame(String username, String game);
|
||||
|
||||
/** Alle Spielstände eines Spielers löschen (z. B. beim Löschen des Kontos). */
|
||||
void deleteByUsername(String username);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package com.example.mindflux.service;
|
||||
|
||||
import com.example.mindflux.model.User;
|
||||
import com.example.mindflux.repository.AchievementRepository;
|
||||
import com.example.mindflux.repository.GameScoreRepository;
|
||||
import com.example.mindflux.repository.UserRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class UserServiceImpl implements UserService {
|
||||
@@ -11,6 +14,12 @@ public class UserServiceImpl implements UserService {
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private GameScoreRepository gameScoreRepository;
|
||||
|
||||
@Autowired
|
||||
private AchievementRepository achievementRepository;
|
||||
|
||||
@Override
|
||||
public User findByUsername(String username) {
|
||||
return userRepository.findByUsername(username).orElse(null); // <-- Optional aufgelöst
|
||||
@@ -22,7 +31,13 @@ public class UserServiceImpl implements UserService {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void deleteByUsername(String username) {
|
||||
// Zugehörige Daten mitlöschen (kein FK/Cascade -> manuell), damit keine
|
||||
// verwaisten Datensätze zurückbleiben und ein neuer gleichnamiger Account
|
||||
// keine Alt-Daten erbt.
|
||||
gameScoreRepository.deleteByUsername(username);
|
||||
achievementRepository.deleteByUsername(username);
|
||||
userRepository.deleteByUsername(username);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user