Binde Auftragshistorie an und korrigiere Kundenanzeige
Ergänzt die lesende Historien-API mit Verlaufsanzeige und ordnet Auftragskunden dem effektiven Zahler zu. Enthält VS-Code-Debugkonfiguration, Dokumentation und Regressionstests. Validiert mit Frontend-Build, 76 Backend-Tests und 25 Browsertests. Live-Datenbankprüfung wegen fehlender Erreichbarkeit offen.
This commit is contained in:
1 parent
ac5ea374b9
commit
75e2bf2bec
24 files changed
+1069
-60
No files matched your search
@@ -17,6 +17,7 @@ import org.springframework.test.web.servlet.MvcResult;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
@@ -35,6 +36,7 @@ class ApiSecurityTest {
|
||||
record Csrf(MockHttpSession session, String token, String header) {}
|
||||
|
||||
@BeforeEach void configure() {
|
||||
when(database.readTransaction(any())).thenAnswer(call -> ((Supplier<?>)call.getArgument(0)).get());
|
||||
when(database.checkConnection()).thenReturn(new DatabaseService.ConnectionCheck(true,"CONNECTED","Verbunden"));
|
||||
when(database.queryForList(eq(LegacyAuthenticationProvider.AUTH_SQL),eq("existing-user"),eq("existing-password"),eq("existing-password")))
|
||||
.thenReturn(List.of(Map.of("usr_id",11,"emp_id",12,"hq_id",7,"usr_account","existing-user","emp_rights","111111111111")));
|
||||
@@ -70,6 +72,8 @@ class ApiSecurityTest {
|
||||
MvcResult unauthorized = mvc.perform(get("/api/orders")).andExpect(status().isUnauthorized())
|
||||
.andExpect(header().doesNotExist("WWW-Authenticate")).andReturn();
|
||||
assertThat(unauthorized.getRequest().getSession(false)).isNull();
|
||||
mvc.perform(get("/api/orders/42/history")).andExpect(status().isUnauthorized())
|
||||
.andExpect(header().doesNotExist("WWW-Authenticate"));
|
||||
Csrf csrf = csrf(null);
|
||||
mvc.perform(post("/api/orders").session(csrf.session()).header(csrf.header(),csrf.token())
|
||||
.contentType("application/json").content("{}"))
|
||||
@@ -180,6 +184,52 @@ class ApiSecurityTest {
|
||||
mvc.perform(get("/api/orders").session(session)).andExpect(status().isForbidden());
|
||||
mvc.perform(get("/api/customers").session(session)).andExpect(status().isForbidden());
|
||||
mvc.perform(get("/api/orders/export.csv").session(session)).andExpect(status().isForbidden());
|
||||
mvc.perform(get("/api/orders/42/history").session(session)).andExpect(status().isForbidden());
|
||||
verify(database,never()).queryForList(contains("phoenix_log"),any(Object[].class));
|
||||
}
|
||||
|
||||
@Test void historyOfMissingOrForeignOrderReturns404WithoutReadingLog() throws Exception {
|
||||
MockHttpSession session = authenticated("existing-user","existing-password");
|
||||
mvc.perform(get("/api/orders/42/history").session(session)).andExpect(status().isNotFound());
|
||||
verify(database).queryForList("SELECT jb.jb_id FROM job jb WHERE jb.jb_id=? AND jb.hq_id=?",42L,7L);
|
||||
verify(database,never()).queryForList(contains("phoenix_log"),any(Object[].class));
|
||||
}
|
||||
|
||||
@Test void accessibleOrderWithNoLogReturnsEmptyHistory() throws Exception {
|
||||
MockHttpSession session = authenticated("existing-user","existing-password");
|
||||
when(database.queryForList("SELECT jb.jb_id FROM job jb WHERE jb.jb_id=? AND jb.hq_id=?",42L,7L))
|
||||
.thenReturn(List.of(Map.of("jb_id",42L)));
|
||||
|
||||
mvc.perform(get("/api/orders/42/history").session(session))
|
||||
.andExpect(status().isOk()).andExpect(content().json("[]"));
|
||||
verify(database).queryForList(contains("FROM `phoenix_log`.log l"),eq(42L),eq(7L));
|
||||
}
|
||||
|
||||
@Test void historyReturnsExistingEvents() throws Exception {
|
||||
MockHttpSession session = authenticated("existing-user","existing-password");
|
||||
when(database.queryForList("SELECT jb.jb_id FROM job jb WHERE jb.jb_id=? AND jb.hq_id=?",42L,7L))
|
||||
.thenReturn(List.of(Map.of("jb_id",42L)));
|
||||
when(database.queryForList(contains("FROM `phoenix_log`.log l"),eq(42L),eq(7L)))
|
||||
.thenReturn(List.of(Map.of("log_id",81L,"logo_id",1,"log_createtime","2026-10-07 08:15:00",
|
||||
"logo_op_name","Auftrag angelegt","logo_description","Testhistorie","usr_account","disponent")));
|
||||
|
||||
mvc.perform(get("/api/orders/42/history").session(session)).andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.length()").value(1)).andExpect(jsonPath("$[0].id").value(81))
|
||||
.andExpect(jsonPath("$[0].at").value("2026-10-07T08:15:00"))
|
||||
.andExpect(jsonPath("$[0].action").isString()).andExpect(jsonPath("$[0].actor").isString());
|
||||
}
|
||||
|
||||
@Test void logFailureReturns503AndDoesNotDiscloseDatabaseDetails() throws Exception {
|
||||
MockHttpSession session = authenticated("existing-user","existing-password");
|
||||
when(database.queryForList("SELECT jb.jb_id FROM job jb WHERE jb.jb_id=? AND jb.hq_id=?",42L,7L))
|
||||
.thenReturn(List.of(Map.of("jb_id",42L)));
|
||||
when(database.queryForList(contains("FROM `phoenix_log`.log l"),eq(42L),eq(7L)))
|
||||
.thenThrow(new DataAccessResourceFailureException("private database credentials"));
|
||||
|
||||
var response=mvc.perform(get("/api/orders/42/history").session(session))
|
||||
.andExpect(status().isServiceUnavailable()).andReturn();
|
||||
String message=json.readTree(response.getResponse().getContentAsString()).get("message").asText();
|
||||
assertThat(message).contains("Auftragshistorie").doesNotContain("private database credentials");
|
||||
}
|
||||
|
||||
@Test void databaseAccountDenialIsDistinguishedFromNetworkFailure() throws Exception {
|
||||
|
||||
Reference in new issue
Block a user