Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 83929f24ba | |||
| fc98e5aad1 |
@@ -10,6 +10,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.core.userdetails.*;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
|
||||
@Configuration
|
||||
public class SecurityConfig {
|
||||
@@ -31,10 +32,16 @@ public class SecurityConfig {
|
||||
.permitAll()
|
||||
)
|
||||
.logout(logout -> logout
|
||||
// Logout-Links in den Templates sind GET -> GET-Logout erlauben, sonst 404/Fehler unter CSRF
|
||||
.logoutRequestMatcher(new AntPathRequestMatcher("/logout", "GET"))
|
||||
.logoutSuccessUrl("/?logout")
|
||||
.permitAll()
|
||||
)
|
||||
.csrf(csrf -> csrf.disable()); // optional deaktivieren bei Custom-Logik/API-Nutzung
|
||||
.csrf(csrf -> csrf
|
||||
// Spiele-APIs werden per fetch (application/json) ohne Token aufgerufen -> ausnehmen.
|
||||
// Reine JSON-Endpunkte sind nicht über klassische HTML-Formulare CSRF-ausnutzbar.
|
||||
.ignoringRequestMatchers("/api/games/**", "/api/techtacular/**", "/api/mindmatch/**")
|
||||
);
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
||||
@@ -14,6 +14,11 @@ import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.BufferedImage;
|
||||
import javax.imageio.ImageIO;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
@@ -99,26 +104,42 @@ public class ProfileController {
|
||||
|
||||
if (file != null && !file.isEmpty()) {
|
||||
try {
|
||||
// Altes Profilbild löschen (falls vorhanden)
|
||||
if (existingUser.getProfilePicture() != null && !existingUser.getProfilePicture().isEmpty()) {
|
||||
Path oldFilePath = Paths.get(System.getProperty("user.dir"), "uploads", "profiles", existingUser.getProfilePicture());
|
||||
if (Files.exists(oldFilePath)) {
|
||||
Files.delete(oldFilePath);
|
||||
BufferedImage original = ImageIO.read(file.getInputStream());
|
||||
if (original == null) {
|
||||
// Keine lesbare Bilddatei -> Upload ignorieren, restliches Profil trotzdem speichern.
|
||||
System.out.println("Profilbild-Upload ignoriert: keine lesbare Bilddatei.");
|
||||
} else {
|
||||
// Auf max. Kantenlänge herunterskalieren (kein Hochskalieren).
|
||||
final int MAX_DIM = 400;
|
||||
int w = original.getWidth();
|
||||
int h = original.getHeight();
|
||||
double scale = Math.min(1.0, (double) MAX_DIM / Math.max(w, h));
|
||||
int nw = Math.max(1, (int) Math.round(w * scale));
|
||||
int nh = Math.max(1, (int) Math.round(h * scale));
|
||||
|
||||
BufferedImage scaled = new BufferedImage(nw, nh, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D g = scaled.createGraphics();
|
||||
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
|
||||
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
|
||||
g.setColor(Color.WHITE); // JPEG kennt kein Alpha -> Transparenz auf weißem Grund
|
||||
g.fillRect(0, 0, nw, nh);
|
||||
g.drawImage(original, 0, 0, nw, nh, null);
|
||||
g.dispose();
|
||||
|
||||
// Altes Profilbild löschen (falls vorhanden)
|
||||
if (existingUser.getProfilePicture() != null && !existingUser.getProfilePicture().isEmpty()) {
|
||||
Path oldFilePath = Paths.get(System.getProperty("user.dir"), "uploads", "profiles", existingUser.getProfilePicture());
|
||||
Files.deleteIfExists(oldFilePath);
|
||||
}
|
||||
|
||||
// Normalisiert als JPEG speichern
|
||||
String fileName = UUID.randomUUID() + ".jpg";
|
||||
Path uploadPath = Paths.get(UPLOAD_DIR);
|
||||
Files.createDirectories(uploadPath);
|
||||
ImageIO.write(scaled, "jpg", uploadPath.resolve(fileName).toFile());
|
||||
|
||||
existingUser.setProfilePicture(fileName);
|
||||
}
|
||||
|
||||
// Neues Profilbild speichern
|
||||
String fileExtension = getFileExtension(file.getOriginalFilename());
|
||||
String fileName = UUID.randomUUID() + fileExtension;
|
||||
|
||||
Path uploadPath = Paths.get(UPLOAD_DIR);
|
||||
Files.createDirectories(uploadPath);
|
||||
|
||||
Path filePath = uploadPath.resolve(fileName);
|
||||
file.transferTo(filePath.toFile());
|
||||
|
||||
existingUser.setProfilePicture(fileName);
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@@ -41,3 +41,11 @@ spring.output.ansi.enabled=ALWAYS
|
||||
|
||||
# Öffentliche Basis-URL, z. B. für künftig erzeugte absolute Links.
|
||||
mindflux.public-url=${MINDFLUX_PUBLIC_URL:http://localhost:8282}
|
||||
|
||||
# =======================
|
||||
# Datei-Uploads (Profilbilder)
|
||||
# =======================
|
||||
# Hinweis: Der nginx-Reverse-Proxy muss client_max_body_size passend gesetzt haben,
|
||||
# sonst greift schon dort ein 413, bevor die App den Upload sieht.
|
||||
spring.servlet.multipart.max-file-size=10MB
|
||||
spring.servlet.multipart.max-request-size=10MB
|
||||
|
||||
Reference in New Issue
Block a user