From 16f5ff20e3be537a5f3926e47190d76b627fb720 Mon Sep 17 00:00:00 2001 From: Denis Natusch Date: Wed, 1 Nov 2023 12:32:54 +0100 Subject: [PATCH] Add profile prototype --- src/main/java/catering/users/User.java | 102 ++++++++++++++++++ .../java/catering/users/UserController.java | 54 ++++++++++ .../catering/users/UserDataInitializer.java | 37 +++++++ .../java/catering/users/UserManagement.java | 50 +++++++++ .../java/catering/users/UserRepository.java | 11 ++ src/main/resources/messages.properties | 12 ++- .../static/resources/css/profile/style.css | 57 ++++++++++ src/main/resources/templates/profile.html | 40 +++++++ 8 files changed, 362 insertions(+), 1 deletion(-) create mode 100644 src/main/java/catering/users/User.java create mode 100644 src/main/java/catering/users/UserController.java create mode 100644 src/main/java/catering/users/UserDataInitializer.java create mode 100644 src/main/java/catering/users/UserManagement.java create mode 100644 src/main/java/catering/users/UserRepository.java create mode 100644 src/main/resources/static/resources/css/profile/style.css create mode 100644 src/main/resources/templates/profile.html diff --git a/src/main/java/catering/users/User.java b/src/main/java/catering/users/User.java new file mode 100644 index 0000000..800a0f5 --- /dev/null +++ b/src/main/java/catering/users/User.java @@ -0,0 +1,102 @@ +package catering.users; + +import jakarta.persistence.Embeddable; +import jakarta.persistence.EmbeddedId; +import jakarta.persistence.Entity; +import jakarta.persistence.OneToOne; + +import org.salespointframework.useraccount.UserAccount; +import org.salespointframework.core.AbstractAggregateRoot; + +import catering.users.User.UserIdentifier; +import java.io.Serializable; +import java.util.UUID; +import org.jmolecules.ddd.types.Identifier; + +@Entity +public class User extends AbstractAggregateRoot { + + private @EmbeddedId UserIdentifier id = new UserIdentifier(); + private String address; + + @OneToOne + private UserAccount userAccount; + + @SuppressWarnings("unused") + private User() {} + + public User(UserAccount userAccount,String address){ + this.address = address; + this.userAccount = userAccount; + }; + + public String getAddress(){ + return address; + } + + public boolean setAddress(String address){ + this.address = address; + return true; + // NOTE: the return type is boolean, + // because in the future we may want to check if the input is a real address + }; + + public String getUsername() { + return userAccount.getUsername(); + }; + + public boolean setUsername(String name){ + userAccount.setUsername(name); + return true; + } + + public UserAccount getUserAccount(){ + return this.userAccount; + } + + @Override + public UserIdentifier getId() { + return id; + } + + @Embeddable + public static final class UserIdentifier implements Identifier, Serializable { + + private static final long serialVersionUID = 7740660930809051850L; + private final @SuppressWarnings("unused") UUID identifier; + + UserIdentifier() { + this(UUID.randomUUID()); + } + + UserIdentifier(UUID identifier) { + this.identifier = identifier; + } + + @Override + public int hashCode() { + + final int prime = 31; + int result = 1; + + result = prime * result + (identifier == null ? 0 : identifier.hashCode()); + + return result; + } + + @Override + public boolean equals(Object obj) { + + if (obj == this) { + return true; + } + + if (!(obj instanceof UserIdentifier that)) { + return false; + } + + return this.identifier.equals(that.identifier); + } + } + +} diff --git a/src/main/java/catering/users/UserController.java b/src/main/java/catering/users/UserController.java new file mode 100644 index 0000000..d6694ab --- /dev/null +++ b/src/main/java/catering/users/UserController.java @@ -0,0 +1,54 @@ +package catering.users; + +import org.springframework.ui.Model; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; + +@Controller +public class UserController { + + private final UserManagement userManagement; + + UserController(UserManagement userManagerment){ + this.userManagement = userManagerment; + }; + + @GetMapping("/profile") + public String index(Model model) { + + model.addAttribute("user", userManagement.getUsers().findAll().toList().get(0)); + + return "profile"; + } + + @PostMapping("/profile") + public String editProfile(@RequestParam String password, @RequestParam String address, @RequestParam String username) { + + User userAccount = userManagement.getUsers().findAll().toList().get(0); + + if (!username.isBlank()){ + userAccount.setUsername(username); + } + + if (!address.isBlank()){ + userAccount.setAddress(address); + } + + if (!password.isBlank()){ + userManagement.setPassword(password, userAccount.getUserAccount()); + } + + userManagement.save(userAccount); + + return "redirect:/profile"; + } + + @GetMapping("/profile/delete") + public String deleteUser() { + User userAccount = userManagement.getUsers().findAll().toList().get(0); + userManagement.deleteUser(userAccount); + return "redirect:/"; + } +} diff --git a/src/main/java/catering/users/UserDataInitializer.java b/src/main/java/catering/users/UserDataInitializer.java new file mode 100644 index 0000000..c092ff8 --- /dev/null +++ b/src/main/java/catering/users/UserDataInitializer.java @@ -0,0 +1,37 @@ +package catering.users; + +import org.salespointframework.core.DataInitializer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.util.Assert; +import org.salespointframework.useraccount.AuthenticationManagement; +import org.springframework.web.bind.annotation.SessionAttributes; + +@Component +@Order(10) +@SessionAttributes("profile") +class UserDataInitializer implements DataInitializer { + + private static final Logger LOG = LoggerFactory.getLogger(UserDataInitializer.class); + + private final UserManagement userManagement; + + UserDataInitializer(UserManagement userManagement, AuthenticationManagement auth) { + + Assert.notNull(userManagement, "UserRepository must not be null!"); + + this.userManagement = userManagement; + } + + @Override + public void initialize() { + + LOG.info("Creating default user."); + + userManagement.createUser("Hans","123","Baum Weg"); + + } + +} diff --git a/src/main/java/catering/users/UserManagement.java b/src/main/java/catering/users/UserManagement.java new file mode 100644 index 0000000..18e11a8 --- /dev/null +++ b/src/main/java/catering/users/UserManagement.java @@ -0,0 +1,50 @@ +package catering.users; + +import org.springframework.web.bind.annotation.SessionAttributes; +import org.salespointframework.useraccount.UserAccount; + +import org.salespointframework.useraccount.Password.UnencryptedPassword; +import org.salespointframework.useraccount.Role; +import org.salespointframework.useraccount.UserAccountManagement; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +@SessionAttributes("profile") +public class UserManagement { + + private final UserRepository users; + private final UserAccountManagement userAccounts; + + UserManagement(UserRepository users, UserAccountManagement userAccounts) { + + this.users = users; + this.userAccounts = userAccounts; + } + + public User createUser(String name, String Password, String address) { + + var password = UnencryptedPassword.of(Password); + var userAccount = userAccounts.create(name, password, Role.of("CUSTOMER")); + + return users.save(new User(userAccount, address)); + } + + public User save(User user){ + return users.save(user); + } + + public boolean setPassword(String password, UserAccount userAccount) { + userAccounts.changePassword(userAccount, UnencryptedPassword.of(password)); + return true; + }; + + public UserRepository getUsers(){ + return users; + } + + public void deleteUser(User user){ + users.deleteById(user.getId()); + } +} diff --git a/src/main/java/catering/users/UserRepository.java b/src/main/java/catering/users/UserRepository.java new file mode 100644 index 0000000..e4fcec4 --- /dev/null +++ b/src/main/java/catering/users/UserRepository.java @@ -0,0 +1,11 @@ +package catering.users; + +import catering.users.User.UserIdentifier; +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.util.Streamable; + +interface UserRepository extends CrudRepository { + + @Override + Streamable findAll(); +} diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index fa4fc1b..8d02f56 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -1,4 +1,4 @@ -# ATTENTION: +# ATTENTION: # Spring Boot expects this file to be UTF-8 encoded 👍 However, some IDEs will open it in # the wrong mode. For example, IntelliJ users must go to Preferences > Editor > File Encodings # and set "Default encoding for properties files" to "UTF-8". @@ -9,3 +9,13 @@ welcome.title = Welcome back! welcome.text = If umlauts such as äöü are not displayed correctly, something is broken + +profile.title = Dein Profil +profile.danger_zone = Danger Zone +profile.edit = Bearbeiten +profile.delete = Account löschen +profile.username = Nutzername +profile.password = Passwort +profile.address = Adresse +profile.authentification = Authentifikation +profile.userinformation = Nutzerinformationen diff --git a/src/main/resources/static/resources/css/profile/style.css b/src/main/resources/static/resources/css/profile/style.css new file mode 100644 index 0000000..42f0afe --- /dev/null +++ b/src/main/resources/static/resources/css/profile/style.css @@ -0,0 +1,57 @@ +/* CSS RESET */ + +* { + margin: 0; + padding: 0; +} + +body { + margin: 0 auto; + width: 940px; + font: 13px/22px Helvetica, Arial, sans-serif; + background: #f0f0f0; +} + +h1 { + font-size: 3em; + line-height: 3.2em; + text-align:center; +} + +table { + border-collapse: separate; + border-spacing: 5 2em; + padding: 20px; + padding-left: 50px; + font-size: 20px; +} + +h2 { + margin: 10px; +} + +th, td { + padding: 15px; +} + +.horizontal_center { + display: flex; + justify-content: center; + align-items: center; +} + +div.danger_zone { + margin-bottom: 50px; +} + +button.danger_zone { + padding-top: 15px; + padding-bottom: 15px; + padding-right: 25px; + padding-left: 25px; + margin-left: 40px; + margin-right: 40px; + color: red; + border: 2px solid red; + border-radius: 4px; +} diff --git a/src/main/resources/templates/profile.html b/src/main/resources/templates/profile.html new file mode 100644 index 0000000..ffb4da8 --- /dev/null +++ b/src/main/resources/templates/profile.html @@ -0,0 +1,40 @@ + + + + + + + </head> + <body> + <form th:action="@{/profile}" method="post" > + <h1 th:text="#{profile.title}"></h1> + <h2 class="settings" th:text="#{profile.authentification}"></h2> + <table> + <tr> + <td th:text="#{profile.username}"></td> + <td><input name="username" th:value="${user.username}" type="text"/></td> + </tr> + <tr> + <td th:text="#{profile.password}"></td> + <td><input name="password" type="password"/></td> + </tr> + </table> + <h2 class="settings" th:text="#{profile.userinformation}"></h2> + <table> + <tr> + <td th:text="#{profile.address}"></td> + <td><input name="address" th:value="${user.address}" type="text"/></td> + </tr> + </table> + <div class="danger_zone"> + <h1 class="danger_zone" th:text="#{profile.danger_zone}"></h1> + <div class="horizontal_center"> + <button class="danger_zone" th:text="#{profile.edit}" type="submit"></button> + <a th:href="@{/profile/delete}"> + <button class="danger_zone" th:text="#{profile.delete}" type="button"></button> + </a> + </div> + </div> + </form> + </body> +</html>