-
Notifications
You must be signed in to change notification settings - Fork 0
Phase 4: Migrate all views from JSP/JSF to Thymeleaf #14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: devin/1771291744-spring-boot-migration-phase1-2
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,17 @@ | ||
| <!DOCTYPE html> | ||
| <html xmlns:th="http://www.thymeleaf.org"> | ||
| <html xmlns:th="http://www.thymeleaf.org" | ||
| xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" | ||
| layout:decorate="~{layout/base}"> | ||
| <head> | ||
| <title th:text="#{change.title}">Password Expired</title> | ||
| <title th:text="#{change.title}">Password Has Expired</title> | ||
| </head> | ||
| <body> | ||
| <h1 th:text="#{change.title}">Password Has Expired</h1> | ||
| <p th:text="#{change.message}">Your password has expired.</p> | ||
| <p th:text="${username}">username</p> | ||
| <a th:href="@{/editLogon}" th:text="#{change.try}">Try Again</a> | ||
| <div layout:fragment="menu"> | ||
| <div th:replace="~{fragments/loggedoff-menu :: menu}"></div> | ||
| </div> | ||
| <div layout:fragment="content"> | ||
| <p th:text="#{change.message}">Your password has expired. Please ask the system administrator to change it.</p> | ||
| <a th:href="@{/editLogon}" th:text="#{change.try}">Try Again</a> | ||
| </div> | ||
| </body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| <!DOCTYPE html> | ||
| <html xmlns:th="http://www.thymeleaf.org"> | ||
| <body> | ||
| <div th:fragment="footer"> | ||
| <span th:text="#{footer.value}">Copyright (C) 1999-2004, The Apache Software Foundation</span> | ||
| </div> | ||
| </body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| <!DOCTYPE html> | ||
| <html xmlns:th="http://www.thymeleaf.org"> | ||
| <body> | ||
| <div th:fragment="header"> | ||
| <span th:text="#{header.value}">Struts + Faces + Tiles</span> | ||
| </div> | ||
| </body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| <!DOCTYPE html> | ||
| <html xmlns:th="http://www.thymeleaf.org"> | ||
| <body> | ||
| <div th:fragment="menu"> | ||
| <a th:href="@{/editRegistration(action='Create')}" th:text="#{loggedoff.register}">Register</a> | ||
| <br /> | ||
| <a th:href="@{/editLogon}" th:text="#{loggedoff.logon}">Log On</a> | ||
| </div> | ||
| </body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| <!DOCTYPE html> | ||
| <html xmlns:th="http://www.thymeleaf.org"> | ||
| <body> | ||
| <div th:fragment="menu"> | ||
| <a th:href="@{/editRegistration(action='Edit')}" th:text="#{mainMenu.registration}">Edit Registration</a> | ||
| <br /> | ||
| <a th:href="@{/logoff}" th:text="#{loggedon.logoff}">Log Off</a> | ||
| </div> | ||
| </body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| <!DOCTYPE html> | ||
| <html xmlns:th="http://www.thymeleaf.org" | ||
| xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"> | ||
| <head> | ||
| <title layout:title-pattern="$CONTENT_TITLE - $LAYOUT_TITLE" th:text="#{layout.title}">Struts+Tiles+Faces Example Application</title> | ||
| <link th:href="@{/css/stylesheet.css}" rel="stylesheet" /> | ||
| </head> | ||
| <body> | ||
| <table border="1" width="100%" cellspacing="5"> | ||
| <tr> | ||
| <th colspan="2" align="center"> | ||
| <div th:replace="~{fragments/header :: header}"></div> | ||
| </th> | ||
| </tr> | ||
| <tr> | ||
| <td width="140" valign="top"> | ||
| <div layout:fragment="menu"></div> | ||
| </td> | ||
| <td align="left" valign="top"> | ||
| <div layout:fragment="content"></div> | ||
| </td> | ||
| </tr> | ||
| <tr> | ||
| <td colspan="2" align="center"> | ||
| <div th:replace="~{fragments/footer :: footer}"></div> | ||
| </td> | ||
| </tr> | ||
| </table> | ||
| </body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,25 +1,52 @@ | ||
| <!DOCTYPE html> | ||
| <html xmlns:th="http://www.thymeleaf.org"> | ||
| <html xmlns:th="http://www.thymeleaf.org" | ||
| xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" | ||
| layout:decorate="~{layout/base}"> | ||
| <head> | ||
| <title th:text="#{logon.title}">Logon</title> | ||
| </head> | ||
| <body> | ||
| <h1 th:text="#{logon.header}">Logon Form</h1> | ||
| <div th:if="${#fields.hasGlobalErrors()}" th:each="err : ${#fields.globalErrors()}"> | ||
| <span th:text="${err}" class="error">Error</span> | ||
| <div layout:fragment="menu"> | ||
| <div th:replace="~{fragments/loggedoff-menu :: menu}"></div> | ||
| </div> | ||
| <div layout:fragment="content"> | ||
| <form th:action="@{/logon}" th:object="${logonForm}" method="post"> | ||
| <table class="form-background"> | ||
| <tr> | ||
| <th colspan="2" class="form-header" th:text="#{logon.header}">Logon Form</th> | ||
| </tr> | ||
| <tr> | ||
| <td class="form-prompt"><label for="username" th:text="#{prompt.username}">Username</label></td> | ||
| <td class="form-field"> | ||
| <input type="text" th:field="*{username}" id="username" size="16" /> | ||
| <span th:if="${#fields.hasErrors('username')}" th:errors="*{username}" class="error"></span> | ||
| </td> | ||
| </tr> | ||
| <tr> | ||
| <td class="form-prompt"><label for="password" th:text="#{prompt.password}">Password</label></td> | ||
| <td class="form-field"> | ||
| <input type="password" th:field="*{password}" id="password" size="16" /> | ||
| <span th:if="${#fields.hasErrors('password')}" th:errors="*{password}" class="error"></span> | ||
| </td> | ||
| </tr> | ||
| <tr th:if="${#fields.hasGlobalErrors()}"> | ||
| <td colspan="2" class="form-field"> | ||
| <span th:each="err : ${#fields.globalErrors()}" th:text="${err}" class="error"></span> | ||
| </td> | ||
| </tr> | ||
| <tr> | ||
| <td class="form-field"> | ||
| <button type="submit" class="command-single">Log On</button> | ||
| </td> | ||
| <td class="form-field"> | ||
| <button type="reset" class="command-single">Reset</button> | ||
| </td> | ||
| </tr> | ||
| <tr> | ||
| <td colspan="2" class="form-footer" th:text="#{logon.footer}">Enter your username and password</td> | ||
| </tr> | ||
| </table> | ||
| </form> | ||
| </div> | ||
| <form th:action="@{/logon}" th:object="${logonForm}" method="post"> | ||
| <div> | ||
| <label th:text="#{prompt.username}">Username</label> | ||
| <input type="text" th:field="*{username}" /> | ||
| <span th:if="${#fields.hasErrors('username')}" th:errors="*{username}" class="error">Username Error</span> | ||
| </div> | ||
| <div> | ||
| <label th:text="#{prompt.password}">Password</label> | ||
| <input type="password" th:field="*{password}" /> | ||
| <span th:if="${#fields.hasErrors('password')}" th:errors="*{password}" class="error">Password Error</span> | ||
| </div> | ||
| <button type="submit" th:text="#{button.save}">Log On</button> | ||
| </form> | ||
| </body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,23 @@ | ||
| <!DOCTYPE html> | ||
| <html xmlns:th="http://www.thymeleaf.org"> | ||
| <html xmlns:th="http://www.thymeleaf.org" | ||
| xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" | ||
| layout:decorate="~{layout/base}"> | ||
| <head> | ||
| <title th:text="#{mainMenu.title}">Main Menu</title> | ||
| </head> | ||
| <body> | ||
| <h1 th:text="#{mainMenu.heading}">Main Menu Options</h1> | ||
| <ul> | ||
| <li><a th:href="@{/editRegistration?action=Edit}" th:text="#{mainMenu.registration}">Edit Registration</a></li> | ||
| <li><a th:href="@{/logoff}" th:text="#{mainMenu.logoff}">Log Off</a></li> | ||
| </ul> | ||
| <div layout:fragment="menu"> | ||
| <div th:replace="~{fragments/loggedon-menu :: menu}"></div> | ||
| </div> | ||
| <div layout:fragment="content"> | ||
| <h3> | ||
| <span th:text="#{mainMenu.heading}">Main Menu Options for </span> | ||
| <span th:text="${session.user.username}">username</span> | ||
| </h3> | ||
| <ul> | ||
| <li><a th:href="@{/editRegistration(action='Edit')}" th:text="#{mainMenu.registration}">Edit your user registration profile</a></li> | ||
| <li><a th:href="@{/logoff}" th:text="#{mainMenu.logoff}">Log off MailReader Demonstration Application</a></li> | ||
| </ul> | ||
| </div> | ||
| </body> | ||
| </html> | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,46 +1,121 @@ | ||||||
| <!DOCTYPE html> | ||||||
| <html xmlns:th="http://www.thymeleaf.org"> | ||||||
| <html xmlns:th="http://www.thymeleaf.org" | ||||||
| xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" | ||||||
| layout:decorate="~{layout/base}"> | ||||||
| <head> | ||||||
| <title>Registration</title> | ||||||
| <title th:if="${registrationForm.action == 'Create'}" th:text="#{registration.title.create}">Register</title> | ||||||
| <title th:if="${registrationForm.action == 'Edit'}" th:text="#{registration.title.edit}">Edit Registration</title> | ||||||
| </head> | ||||||
| <body> | ||||||
| <h1>Registration</h1> | ||||||
| <form th:action="@{/saveRegistration}" th:object="${registrationForm}" method="post"> | ||||||
| <input type="hidden" th:field="*{action}" /> | ||||||
| <div> | ||||||
| <label th:text="#{prompt.username}">Username</label> | ||||||
| <input type="text" th:field="*{username}" /> | ||||||
| <span th:if="${#fields.hasErrors('username')}" th:errors="*{username}"></span> | ||||||
| <div layout:fragment="menu"> | ||||||
| <th:block th:if="${session.user != null}"> | ||||||
| <div th:replace="~{fragments/loggedon-menu :: menu}"></div> | ||||||
| </th:block> | ||||||
| <th:block th:if="${session.user == null}"> | ||||||
| <div th:replace="~{fragments/loggedoff-menu :: menu}"></div> | ||||||
| </th:block> | ||||||
| </div> | ||||||
| <div layout:fragment="content"> | ||||||
| <form th:action="@{/saveRegistration}" th:object="${registrationForm}" method="post"> | ||||||
| <input type="hidden" th:field="*{action}" /> | ||||||
| <table class="form-background"> | ||||||
| <tr> | ||||||
| <th colspan="2" class="form-header"> | ||||||
| <span th:if="${registrationForm.action == 'Create'}" th:text="#{registration.header.create}">Enter Registration Information</span> | ||||||
| <span th:if="${registrationForm.action == 'Edit'}" th:text="#{registration.header.edit}">Edit Your Registration Information</span> | ||||||
| </th> | ||||||
| </tr> | ||||||
| <tr> | ||||||
| <td class="form-prompt"><label for="username" th:text="#{prompt.username}">Username</label></td> | ||||||
| <td class="form-field"> | ||||||
| <span th:if="${registrationForm.action == 'Create'}"> | ||||||
| <input type="text" th:field="*{username}" id="username" size="16" /> | ||||||
| </span> | ||||||
| <span th:if="${registrationForm.action == 'Edit'}"> | ||||||
| <span th:text="*{username}">username</span> | ||||||
| <input type="hidden" th:field="*{username}" /> | ||||||
| </span> | ||||||
| <span th:if="${#fields.hasErrors('username')}" th:errors="*{username}" class="error"></span> | ||||||
| </td> | ||||||
| </tr> | ||||||
| <tr> | ||||||
| <td class="form-prompt"><label for="password" th:text="#{prompt.password}">Password</label></td> | ||||||
| <td class="form-field"> | ||||||
| <input type="text" th:field="*{password}" id="password" size="16" /> | ||||||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 Password fields changed from type="password" to type="text" in registration form The password and password confirmation fields in Security ImpactThe old code used Actual: Password input is displayed as plain text (
Suggested change
Was this helpful? React with 👍 or 👎 to provide feedback. |
||||||
| <span th:if="${#fields.hasErrors('password')}" th:errors="*{password}" class="error"></span> | ||||||
| </td> | ||||||
| </tr> | ||||||
| <tr> | ||||||
| <td class="form-prompt"><label for="password2" th:text="#{prompt.password2}">(Repeat) Password</label></td> | ||||||
| <td class="form-field"> | ||||||
| <input type="text" th:field="*{password2}" id="password2" size="16" /> | ||||||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 Password confirmation field changed from type="password" to type="text" in registration form The password2 (confirmation) field in Security ImpactSame issue as the password field — the old code at diff left side line 37 used
Suggested change
Was this helpful? React with 👍 or 👎 to provide feedback. |
||||||
| <span th:if="${#fields.hasErrors('password2')}" th:errors="*{password2}" class="error"></span> | ||||||
| </td> | ||||||
| </tr> | ||||||
| <tr> | ||||||
| <td class="form-prompt"><label for="fullName" th:text="#{prompt.fullName}">Full Name</label></td> | ||||||
| <td class="form-field"> | ||||||
| <input type="text" th:field="*{fullName}" id="fullName" size="50" /> | ||||||
| <span th:if="${#fields.hasErrors('fullName')}" th:errors="*{fullName}" class="error"></span> | ||||||
| </td> | ||||||
| </tr> | ||||||
| <tr> | ||||||
| <td class="form-prompt"><label for="fromAddress" th:text="#{prompt.fromAddress}">From Address</label></td> | ||||||
| <td class="form-field"> | ||||||
| <input type="text" th:field="*{fromAddress}" id="fromAddress" size="50" /> | ||||||
| <span th:if="${#fields.hasErrors('fromAddress')}" th:errors="*{fromAddress}" class="error"></span> | ||||||
| </td> | ||||||
| </tr> | ||||||
| <tr> | ||||||
| <td class="form-prompt"><label for="replyToAddress" th:text="#{prompt.replyToAddress}">Reply To Address</label></td> | ||||||
| <td class="form-field"> | ||||||
| <input type="text" th:field="*{replyToAddress}" id="replyToAddress" size="50" /> | ||||||
| <span th:if="${#fields.hasErrors('replyToAddress')}" th:errors="*{replyToAddress}" class="error"></span> | ||||||
| </td> | ||||||
| </tr> | ||||||
| <tr th:if="${#fields.hasGlobalErrors()}"> | ||||||
| <td colspan="2" class="form-field"> | ||||||
| <span th:each="err : ${#fields.globalErrors()}" th:text="${err}" class="error"></span> | ||||||
| </td> | ||||||
| </tr> | ||||||
| <tr> | ||||||
| <td class="form-field"> | ||||||
| <button type="submit" class="command-single" th:text="#{button.save}">Save</button> | ||||||
| </td> | ||||||
| <td class="form-field"> | ||||||
| <button type="reset" class="command-multiple" th:text="#{button.reset}">Reset</button> | ||||||
| <a th:href="@{/mainMenu}" class="command-multiple" th:text="#{button.cancel}">Cancel</a> | ||||||
| </td> | ||||||
| </tr> | ||||||
| </table> | ||||||
| </form> | ||||||
|
|
||||||
| <div th:if="${registrationForm.action == 'Edit' and session.user != null}"> | ||||||
| <h3 th:text="#{heading.subscriptions}">Current Subscriptions</h3> | ||||||
| <table class="list-background"> | ||||||
| <tr class="list-header"> | ||||||
| <th th:text="#{heading.host}">Host Name</th> | ||||||
| <th th:text="#{heading.user}">User Name</th> | ||||||
| <th th:text="#{heading.type}">Server Type</th> | ||||||
| <th th:text="#{heading.autoConnect}">Auto</th> | ||||||
| <th th:text="#{heading.action}">Action</th> | ||||||
| </tr> | ||||||
| <tr th:each="subscription, iterStat : ${session.user.subscriptions}" | ||||||
| th:class="${iterStat.odd ? 'list-row-odd' : 'list-row-even'}"> | ||||||
| <td class="list-column-host" th:text="${subscription.host}">host</td> | ||||||
| <td class="list-column-user" th:text="${subscription.username}">username</td> | ||||||
| <td class="list-column-type" th:text="${subscription.type}">type</td> | ||||||
| <td class="list-column-auto" th:text="${subscription.autoConnect}">false</td> | ||||||
| <td class="list-column-action"> | ||||||
| <a th:href="@{/editSubscription(action='Delete',host=${subscription.host})}" | ||||||
| class="command-multiple" th:text="#{registration.deleteSubscription}">Delete</a> | ||||||
| <a th:href="@{/editSubscription(action='Edit',host=${subscription.host})}" | ||||||
| class="command-multiple" th:text="#{registration.editSubscription}">Edit</a> | ||||||
| </td> | ||||||
| </tr> | ||||||
| </table> | ||||||
| <a th:href="@{/editSubscription(action='Create')}" th:text="#{registration.addSubscription}">Add</a> | ||||||
| </div> | ||||||
| <div> | ||||||
| <label th:text="#{prompt.fullName}">Full Name</label> | ||||||
| <input type="text" th:field="*{fullName}" /> | ||||||
| <span th:if="${#fields.hasErrors('fullName')}" th:errors="*{fullName}"></span> | ||||||
| </div> | ||||||
| <div> | ||||||
| <label th:text="#{prompt.fromAddress}">From Address</label> | ||||||
| <input type="text" th:field="*{fromAddress}" /> | ||||||
| <span th:if="${#fields.hasErrors('fromAddress')}" th:errors="*{fromAddress}"></span> | ||||||
| </div> | ||||||
| <div> | ||||||
| <label th:text="#{prompt.replyToAddress}">Reply To Address</label> | ||||||
| <input type="text" th:field="*{replyToAddress}" /> | ||||||
| <span th:if="${#fields.hasErrors('replyToAddress')}" th:errors="*{replyToAddress}"></span> | ||||||
| </div> | ||||||
| <div> | ||||||
| <label th:text="#{prompt.password}">Password</label> | ||||||
| <input type="password" th:field="*{password}" /> | ||||||
| <span th:if="${#fields.hasErrors('password')}" th:errors="*{password}"></span> | ||||||
| </div> | ||||||
| <div> | ||||||
| <label th:text="#{prompt.password2}">(Repeat) Password</label> | ||||||
| <input type="password" th:field="*{password2}" /> | ||||||
| <span th:if="${#fields.hasErrors('password2')}" th:errors="*{password2}"></span> | ||||||
| </div> | ||||||
| <div> | ||||||
| <button type="submit" th:text="#{button.save}">Save</button> | ||||||
| <button type="reset" th:text="#{button.reset}">Reset</button> | ||||||
| </div> | ||||||
| </form> | ||||||
| </div> | ||||||
| </body> | ||||||
| </html> | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔴 mainMenu.html accesses session.user.username without null guard, but controller has no login check
The
mainMenu.htmltemplate at line 15 accesses${session.user.username}, but theWelcomeController.mainMenu()method does not verify the user is logged in before rendering the template.Root Cause
The
WelcomeController.mainMenu()atcontroller/WelcomeController.java:37-40simply returns the"mainMenu"view name without checking if a user exists in the session:The template at
mainMenu.html:15then accesses${session.user.username}. If a user navigates directly to/mainMenuwithout being logged in,session.userwill benull, causing a Thymeleaf template evaluation error (equivalent to a NullPointerException) when trying to access.usernameon a null object.Impact: Unauthenticated users visiting
/mainMenuwill see a 500 error page instead of being redirected to the login page.Prompt for agents
Was this helpful? React with 👍 or 👎 to provide feedback.