This commit is contained in:
@@ -7,6 +7,8 @@ Versionierung [semantisch](https://semver.org/lang/de/).
|
|||||||
## [Unreleased] – 2026-07-21 · Gesamt-Audit: Light Mode, Barrierefreiheit, AP2-Inhalte, DSGVO
|
## [Unreleased] – 2026-07-21 · Gesamt-Audit: Light Mode, Barrierefreiheit, AP2-Inhalte, DSGVO
|
||||||
|
|
||||||
### Light Mode & Design
|
### Light Mode & Design
|
||||||
|
- **Browser-Icon:** Das Neural-Emblem wird unter `/favicon.ico` ausgeliefert und
|
||||||
|
ersetzt damit das Standard-Globus-Symbol im Browser-Tab.
|
||||||
- **Preismodell offen formuliert:** Die öffentliche Einstiegsseite verspricht keine
|
- **Preismodell offen formuliert:** Die öffentliche Einstiegsseite verspricht keine
|
||||||
kostenlose Nutzung mehr; Beschreibung, Registrierungs-Teaser und Account-Hinweis
|
kostenlose Nutzung mehr; Beschreibung, Registrierungs-Teaser und Account-Hinweis
|
||||||
bleiben bewusst preisneutral.
|
bleiben bewusst preisneutral.
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class SecurityConfig {
|
|||||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
http
|
http
|
||||||
.authorizeHttpRequests(auth -> auth
|
.authorizeHttpRequests(auth -> auth
|
||||||
.requestMatchers("/", "/login", "/register", "/forgot-password", "/reset-password", "/verify-email", "/verification/resend", "/impressum", "/nutzungsbedingungen", "/datenschutz", "/richtlinien", "/css/**", "/js/**", "/img/**").permitAll()
|
.requestMatchers("/", "/login", "/register", "/forgot-password", "/reset-password", "/verify-email", "/verification/resend", "/impressum", "/nutzungsbedingungen", "/datenschutz", "/richtlinien", "/favicon.ico", "/css/**", "/js/**", "/img/**").permitAll()
|
||||||
.requestMatchers("/actuator/health").permitAll() // Container-Healthcheck
|
.requestMatchers("/actuator/health").permitAll() // Container-Healthcheck
|
||||||
.requestMatchers("/admin/**").hasRole("ADMIN")
|
.requestMatchers("/admin/**").hasRole("ADMIN")
|
||||||
.requestMatchers("/api/users/**").hasRole("ADMIN")
|
.requestMatchers("/api/users/**").hasRole("ADMIN")
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.example.mindflux.controller;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.http.CacheControl;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class FaviconController {
|
||||||
|
|
||||||
|
@GetMapping(value = "/favicon.ico", produces = MediaType.IMAGE_PNG_VALUE)
|
||||||
|
public ResponseEntity<Resource> favicon() {
|
||||||
|
Resource emblem = new ClassPathResource("static/img/mindflux-emblem.png");
|
||||||
|
return ResponseEntity.ok()
|
||||||
|
.cacheControl(CacheControl.maxAge(Duration.ofDays(30)).cachePublic())
|
||||||
|
.body(emblem);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package com.example.mindflux;
|
|||||||
import com.example.mindflux.config.SecurityConfig;
|
import com.example.mindflux.config.SecurityConfig;
|
||||||
import com.example.mindflux.controller.AdminUserController;
|
import com.example.mindflux.controller.AdminUserController;
|
||||||
import com.example.mindflux.controller.DashboardController;
|
import com.example.mindflux.controller.DashboardController;
|
||||||
|
import com.example.mindflux.controller.FaviconController;
|
||||||
import com.example.mindflux.controller.ProgressController;
|
import com.example.mindflux.controller.ProgressController;
|
||||||
import com.example.mindflux.controller.PlatformStatusController;
|
import com.example.mindflux.controller.PlatformStatusController;
|
||||||
import com.example.mindflux.dto.ProgressData;
|
import com.example.mindflux.dto.ProgressData;
|
||||||
@@ -28,9 +29,10 @@ import static org.springframework.security.test.web.servlet.request.SecurityMock
|
|||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||||
|
|
||||||
/** Absichert die zentralen Security-Regeln: Login-Zwang, Admin-Schutz, gelöschter Legacy-Endpunkt. */
|
/** Absichert die zentralen Security-Regeln: Login-Zwang, Admin-Schutz, gelöschter Legacy-Endpunkt. */
|
||||||
@WebMvcTest(controllers = {DashboardController.class, ProgressController.class, PlatformStatusController.class, AdminUserController.class})
|
@WebMvcTest(controllers = {DashboardController.class, ProgressController.class, PlatformStatusController.class, AdminUserController.class, FaviconController.class})
|
||||||
@Import(SecurityConfig.class)
|
@Import(SecurityConfig.class)
|
||||||
class SecurityRulesTest {
|
class SecurityRulesTest {
|
||||||
|
|
||||||
@@ -58,6 +60,13 @@ class SecurityRulesTest {
|
|||||||
.andExpect(status().is3xxRedirection());
|
.andExpect(status().is3xxRedirection());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void faviconIstOhneAnmeldungErreichbar() throws Exception {
|
||||||
|
mockMvc.perform(get("/favicon.ico"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(content().contentType("image/png"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@WithMockUser(username = "alice")
|
@WithMockUser(username = "alice")
|
||||||
void eingeloggteNutzerSehenDasDashboard() throws Exception {
|
void eingeloggteNutzerSehenDasDashboard() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user