feat(ui): integrate bootstrap with auth shell

This commit is contained in:
sechmachine
2026-08-15 01:08:11 +07:00
parent f48fc63775
commit f9ddef6861
3 changed files with 51 additions and 11 deletions
+21 -2
View File
@@ -8,11 +8,11 @@
## Protected behavior
The authenticated account-creation page consumes the shared role-aware desktop shell and posts to the real account endpoint. The public activation and login pages consume the local themed authentication shell while preserving their raw-token and Spring Security form contracts. The Admin dashboard and navigation link to the implemented `/admin/accounts/new` route, and logout remains a CSRF-protected POST in the shared shell.
The authenticated account-creation page consumes the shared role-aware desktop shell and posts to the real account endpoint. The public bootstrap, activation, and login pages consume the local themed authentication shell while preserving their first-Admin, raw-token, and Spring Security form contracts. The Admin dashboard and navigation link to the implemented `/admin/accounts/new` route, and logout remains a CSRF-protected POST in the shared shell.
## Test method
A focused MockMvc slice renders the production account-creation, activation, and login templates through a test-only controller. It asserts the authenticated and public shell markers, local pre-paint theme and CSS assets, real form actions, accessible error status, activation token retention, and the real account-creation URL. The existing PostgreSQL Account and Authentication web flows then exercise account creation, activation, normalized login, failed login, authorization, and logout through the production controllers and services.
A focused MockMvc slice renders the production bootstrap, account-creation, activation, and login templates through a test-only controller. It asserts the authenticated and public shell markers, local pre-paint theme and CSS assets, real form actions, accessible error status, activation token retention, and the real account-creation URL. The existing PostgreSQL Bootstrap, Account, and Authentication flows then exercise one-time initialization, account creation, activation, normalized login, failed login, authorization, and logout through the production controllers and services.
## Hand-derived expected result
@@ -49,6 +49,15 @@ BUILD FAILURE
Total time: 5.343 s
```
The first-Admin bootstrap page then established its own layout RED:
```text
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0
AccountTemplateIntegrationTest.bootstrapUsesPublicAuthShellAndPreservesFirstAdminContract expected class="auth-shell"
BUILD FAILURE
Total time: 4.771 s
```
## GREEN
**Command**
@@ -81,6 +90,16 @@ PostgreSQL 18.4
Tests run: 5, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS
Total time: 18.361 s
Bootstrap-specific affected suite:
```text
./mvnw -Dtest=AccountTemplateIntegrationTest,BootstrapIntegrationTest test
PostgreSQL 18.4
Tests run: 7, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS
Total time: 17.350 s
```
```
## External-test boundaries
@@ -1,15 +1,18 @@
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="utf-8"><title>Initialize Lab Timesheet</title></head>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
th:replace="~{fragments/auth-layout :: shell(
pageTitle='Create the first administrator',
eyebrow='One-time initialization',
content=~{::main})}">
<body>
<main>
<h1>Create the first administrator</h1>
<p th:if="${error}" th:text="${error}" role="alert"></p>
<form method="post" th:action="@{/bootstrap}">
<label>Email <input name="email" type="email" required autocomplete="email"></label>
<label>Display name <input name="displayName" required autocomplete="name"></label>
<label>Password <input name="password" type="password" minlength="12" maxlength="128" required autocomplete="new-password"></label>
<button type="submit">Create administrator</button>
<p class="page-description">Initialize this installation once. Later accounts are created by an active Admin.</p>
<p class="alert alert-error" th:if="${error}" th:text="${error}" role="alert"></p>
<form class="form-grid auth-form" method="post" th:action="@{/bootstrap}">
<div class="field"><label class="field-label" for="email">Email</label><input class="control" id="email" name="email" type="email" required autocomplete="email" autofocus></div>
<div class="field"><label class="field-label" for="displayName">Display name</label><input class="control" id="displayName" name="displayName" required autocomplete="name"></div>
<div class="field"><label class="field-label" for="password">Password</label><input class="control" id="password" name="password" type="password" minlength="12" maxlength="128" required autocomplete="new-password"></div>
<button class="button button-primary" type="submit">Create administrator</button>
</form>
</main>
</body>
@@ -63,6 +63,19 @@ class AccountTemplateIntegrationTest {
.andExpect(content().string(containsString("src=\"/assets/theme.js\"")));
}
@Test
void bootstrapUsesPublicAuthShellAndPreservesFirstAdminContract() throws Exception {
mvc.perform(get("/template-contract/bootstrap")
.with(user("bootstrap-template-viewer")))
.andExpect(status().isOk())
.andExpect(content().string(containsString("class=\"auth-shell\"")))
.andExpect(content().string(containsString("action=\"/bootstrap\"")))
.andExpect(content().string(containsString("name=\"email\"")))
.andExpect(content().string(containsString("name=\"displayName\"")))
.andExpect(content().string(containsString("autocomplete=\"new-password\"")))
.andExpect(content().string(containsString("src=\"/assets/theme.js\"")));
}
@Controller
public static class TemplateController {
@@ -81,5 +94,10 @@ class AccountTemplateIntegrationTest {
String login() {
return "accounts/login";
}
@GetMapping("/template-contract/bootstrap")
String bootstrap() {
return "bootstrap/form";
}
}
}