fix(ui): persist SMTP restriction in shared shell

This commit is contained in:
sechmachine
2026-08-15 04:33:37 +07:00
parent ec99586393
commit ddf688a533
10 changed files with 303 additions and 61 deletions
@@ -71,6 +71,8 @@ class BootstrapOnboardingWebIntegrationTest {
.with(user("admin@example.com").roles("ADMIN")))
.andExpect(status().isOk())
.andExpect(view().name("smtp/defer"))
.andExpect(content().string(org.hamcrest.Matchers.containsString("/assets/theme.js")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("data-sidebar-toggle")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("Account onboarding is disabled")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("Back")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("Configure SMTP")))
@@ -91,6 +93,20 @@ class BootstrapOnboardingWebIntegrationTest {
.with(csrf()))
.andExpect(status().is3xxRedirection())
.andExpect(redirectedUrl("/dashboard"));
mockMvc.perform(get("/dashboard")
.with(user("admin@example.com").roles("ADMIN")))
.andExpect(status().isOk())
.andExpect(content().string(org.hamcrest.Matchers.containsString(
"This installation remains restricted until tested SMTP is active.")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("href=\"/admin/smtp\"")));
mockMvc.perform(get("/admin/accounts/new")
.with(user("admin@example.com").roles("ADMIN")))
.andExpect(status().isOk())
.andExpect(content().string(org.hamcrest.Matchers.containsString(
"This installation remains restricted until tested SMTP is active.")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("href=\"/admin/smtp\"")));
}
@Test
@@ -102,6 +102,11 @@ class SmtpOnboardingWebIntegrationTest {
.andExpect(content().string(org.hamcrest.Matchers.containsString("SMTP is active")))
.andExpect(content().string(org.hamcrest.Matchers.not(
org.hamcrest.Matchers.containsString("restricted installation"))));
mockMvc.perform(get("/admin/accounts/new").with(user("admin@example.com").roles("ADMIN")))
.andExpect(status().isOk())
.andExpect(content().string(org.hamcrest.Matchers.not(
org.hamcrest.Matchers.containsString("installation remains restricted"))));
}
@Test
@@ -111,16 +116,71 @@ class SmtpOnboardingWebIntegrationTest {
.with(csrf())
.param("host", "")
.param("port", "70000")
.param("securityMode", "STARTTLS")
.param("securityMode", "")
.param("username", "smtp-user")
.param("password", "must-not-be-rendered")
.param("password", "")
.param("fromAddress", "not-an-email")
.param("fromName", "Safe sender name"))
.param("fromName", ""))
.andExpect(status().isOk())
.andExpect(view().name("smtp/form"))
.andExpect(content().string(org.hamcrest.Matchers.containsString("/assets/theme.js")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("id=\"smtp-form-error-summary\"")))
.andExpect(content().string(org.hamcrest.Matchers.containsString(
"aria-labelledby=\"smtp-form-error-summary-title\"")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("id=\"smtp-host\"")))
.andExpect(content().string(org.hamcrest.Matchers.containsString(
"aria-describedby=\"smtp-host-error\"")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("id=\"smtp-host-error\"")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("id=\"smtp-port\"")))
.andExpect(content().string(org.hamcrest.Matchers.containsString(
"aria-describedby=\"smtp-port-error\"")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("id=\"smtp-port-error\"")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("id=\"smtp-security-mode\"")))
.andExpect(content().string(org.hamcrest.Matchers.containsString(
"aria-describedby=\"smtp-security-mode-error\"")))
.andExpect(content().string(org.hamcrest.Matchers.containsString(
"id=\"smtp-security-mode-error\"")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("id=\"smtp-username\"")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("id=\"smtp-password\"")))
.andExpect(content().string(org.hamcrest.Matchers.containsString(
"aria-describedby=\"smtp-authentication-error\"")))
.andExpect(content().string(org.hamcrest.Matchers.containsString(
"id=\"smtp-username\" autocomplete=\"username\" aria-invalid=\"true\""
+ " aria-describedby=\"smtp-authentication-error\"")))
.andExpect(content().string(org.hamcrest.Matchers.containsString(
"id=\"smtp-authentication-error\"")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("id=\"smtp-from-address\"")))
.andExpect(content().string(org.hamcrest.Matchers.containsString(
"aria-describedby=\"smtp-from-address-error\"")))
.andExpect(content().string(org.hamcrest.Matchers.containsString(
"id=\"smtp-from-address-error\"")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("id=\"smtp-from-name\"")))
.andExpect(content().string(org.hamcrest.Matchers.containsString(
"aria-describedby=\"smtp-from-name-error\"")))
.andExpect(content().string(org.hamcrest.Matchers.containsString(
"id=\"smtp-from-name-error\"")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("Host is required")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("Port must be between")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("valid email address")))
.andExpect(content().string(org.hamcrest.Matchers.not(
org.hamcrest.Matchers.containsString("value=\"smtp-secret\""))));
}
@Test
void invalidDraftRetainsSafeValuesButNeverTheSubmittedPassword() throws Exception {
mockMvc.perform(post("/admin/smtp/draft")
.with(user("admin@example.com").roles("ADMIN"))
.with(csrf())
.param("host", "")
.param("port", "1025")
.param("securityMode", "NONE")
.param("username", "safe-smtp-user")
.param("password", "must-not-be-rendered")
.param("fromAddress", "notifications@example.com")
.param("fromName", "Safe sender name"))
.andExpect(status().isOk())
.andExpect(view().name("smtp/form"))
.andExpect(content().string(org.hamcrest.Matchers.containsString("safe-smtp-user")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("Safe sender name")))
.andExpect(content().string(org.hamcrest.Matchers.not(
org.hamcrest.Matchers.containsString("must-not-be-rendered"))));
@@ -130,7 +190,8 @@ class SmtpOnboardingWebIntegrationTest {
void restrictedWarningPersistsOnAdminPagesUntilActivationAndMutationsRequireCsrf() throws Exception {
mockMvc.perform(get("/admin/accounts/new").with(user("admin@example.com").roles("ADMIN")))
.andExpect(status().isOk())
.andExpect(content().string(org.hamcrest.Matchers.containsString("restricted installation")));
.andExpect(content().string(org.hamcrest.Matchers.containsString(
"installation remains restricted")));
mockMvc.perform(post("/admin/smtp/draft")
.with(user("admin@example.com").roles("ADMIN"))
@@ -6,6 +6,7 @@ import static org.mockito.Mockito.verifyNoInteractions;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
@@ -35,15 +36,31 @@ class DashboardControllerWebTest {
void adminRendersAdminDashboardForAuthenticatedIdentity() throws Exception {
var dashboard = new DashboardView.Admin(2, 1, 1, 3);
given(dashboards.admin("admin@example.test")).willReturn(dashboard);
given(smtpConfiguration.hasActiveConfiguration()).willReturn(false);
mvc.perform(get("/dashboard").with(user("admin@example.test").roles("ADMIN")))
.andExpect(status().isOk())
.andExpect(view().name("dashboard/admin"))
.andExpect(model().attribute("dashboard", dashboard));
.andExpect(model().attribute("dashboard", dashboard))
.andExpect(content().string(org.hamcrest.Matchers.containsString(
"This installation remains restricted until tested SMTP is active.")))
.andExpect(content().string(org.hamcrest.Matchers.containsString("href=\"/admin/smtp\"")));
verify(dashboards).admin("admin@example.test");
}
@Test
void activeSmtpKeepsAdminDashboardFreeOfTheRestrictedInstallationWarning() throws Exception {
var dashboard = new DashboardView.Admin(2, 1, 1, 3);
given(dashboards.admin("admin@example.test")).willReturn(dashboard);
given(smtpConfiguration.hasActiveConfiguration()).willReturn(true);
mvc.perform(get("/dashboard").with(user("admin@example.test").roles("ADMIN")))
.andExpect(status().isOk())
.andExpect(content().string(org.hamcrest.Matchers.not(org.hamcrest.Matchers.containsString(
"This installation remains restricted until tested SMTP is active."))));
}
@Test
void mentorRendersMentorDashboardForAuthenticatedIdentity() throws Exception {
var dashboard = new DashboardView.Mentor("Mentor", 2, 4, 1);
@@ -52,7 +69,9 @@ class DashboardControllerWebTest {
mvc.perform(get("/dashboard").with(user("mentor@example.test").roles("MENTOR")))
.andExpect(status().isOk())
.andExpect(view().name("dashboard/mentor"))
.andExpect(model().attribute("dashboard", dashboard));
.andExpect(model().attribute("dashboard", dashboard))
.andExpect(content().string(org.hamcrest.Matchers.not(org.hamcrest.Matchers.containsString(
"This installation remains restricted until tested SMTP is active."))));
verify(dashboards).mentor("mentor@example.test");
}