Make user consistent with design model

Co-authored-by: Simon Bruder <simon.bruder@mailbox.tu-dresden.de>
This commit is contained in:
Denis Natusch 2023-11-11 17:56:01 +01:00 committed by Simon Bruder
parent 040b28fbe0
commit 4588809412
Signed by: simon
GPG key ID: 8D3C82F9F309F8EC
16 changed files with 166 additions and 306 deletions

View file

@ -51,6 +51,7 @@ public class Application {
.csrf(csrf -> csrf.disable()) .csrf(csrf -> csrf.disable())
.formLogin(login -> login.loginPage("/login").loginProcessingUrl("/login")) .formLogin(login -> login.loginPage("/login").loginProcessingUrl("/login"))
.logout(logout -> logout.logoutUrl("/logout").logoutSuccessUrl("/")) .logout(logout -> logout.logoutUrl("/logout").logoutSuccessUrl("/"))
.exceptionHandling(exceptionHandling -> exceptionHandling.accessDeniedPage("/unauthorized"))
.build(); .build();
} }
} }

View file

@ -1,40 +0,0 @@
package catering.customer;
public class Customer {
private int id;
private String surname;
private String name;
public Customer(String name, String surname) {
this.id = (int) (Math.random() * 10 * Math.random() * 10 + Math.random() * 10);
this.name = name;
this.surname = surname;
}
public int getId() {
return id;
}
public String getSurname() {
return surname;
}
public String getName() {
return name;
}
public void setId(int id) {
this.id = id;
}
public void setSurname(String surname) {
this.surname = surname;
}
public void setName(String name) {
this.name = name;
}
}

View file

@ -1,65 +0,0 @@
package catering.customer;
import org.salespointframework.useraccount.Password;
import org.salespointframework.useraccount.UserAccountManagement;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class CustomerController {
private final CustomerRepository customerRepository;
private UserAccountManagement userAccountManagement;
CustomerController(UserAccountManagement userAccountManagement, CustomerRepository customerRepository) {
this.userAccountManagement = userAccountManagement;
this.customerRepository = customerRepository;
}
@GetMapping("/register")
String register() {
return "register";
}
@GetMapping("/login")
public String loginPage(){
return "login";
}
@PostMapping("/register")
String register(@RequestParam String username, @RequestParam String password) {
userAccountManagement.create(username, Password.UnencryptedPassword.of(password));
return "redirect:/";
}
@GetMapping("/customer")
public String getCustomer(Model model) {
model.addAttribute("title", "Kundenverwaltung");
model.addAttribute("customers", customerRepository.getCustomers());
return "customer";
}
@PostMapping("/customer/remove")
public String removeCustomer(@RequestParam("customerID") int customerID, Model model) {
customerRepository.removeCustomer(customerID);
return "redirect:/customer";
}
@GetMapping("/customer/edit/{id}")
public String editCustomer(@PathVariable("id") int id, Model model) {
customerRepository.findById(id).ifPresent(customer -> model.addAttribute("customer", customer));
return "edit-customer";
}
@PostMapping("/customer/update")
public String updateCustomer(@ModelAttribute Customer customer) {
customerRepository.save(customer);
return "redirect:/customer";
}
}

View file

@ -1,35 +0,0 @@
package catering.customer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import jakarta.annotation.PostConstruct;
@Component
public class CustomerDataInitializer {
private static final Logger LOG = LoggerFactory.getLogger(CustomerDataInitializer.class);
private final CustomerRepository customerRepository;
public CustomerDataInitializer(CustomerRepository customerRepository) {
Assert.notNull(customerRepository, "CustomerRepository must not be null!");
this.customerRepository = customerRepository;
}
@PostConstruct
public void initialize() {
LOG.info("Creating default customer.");
customerRepository.save(new Customer("Hans", "Essen"));
customerRepository.save(new Customer("Angela", "Cook"));
LOG.info("Default customer created");
}
}

View file

@ -1,53 +0,0 @@
package catering.customer;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
@Component
public class CustomerRepository {
private Set<Customer> customers = new HashSet<>();
public CustomerRepository() {
}
public boolean addCustomer(Customer customer) {
return this.customers.add(customer);
}
private int nextId = (int) (Math.random() * 10 * Math.random() * 10 + Math.random() * 10);
public void save(Customer customer) {
if (customer.getId() == 0) {
customer.setId(nextId++);
} else {
this.customers.removeIf(p -> p.getId() == customer.getId());
}
this.customers.add(customer);
}
public long count() {
return this.customers.size();
}
public boolean removeCustomer(int customerID) {
return this.customers.removeIf(customer -> customer.getId() == customerID);
}
public Collection<Customer> getCustomers() {
return new ArrayList<>(this.customers);
}
public Optional<Customer> findById(int id) {
return this.customers.stream().filter(customer -> customer.getId() == id).findFirst();
}
}

View file

@ -1,21 +1,21 @@
package catering.customer; package catering.users;
import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotEmpty;
import org.springframework.validation.Errors; import org.springframework.validation.Errors;
public class RegistrationForm { public class RegistrationForm {
private final @NotEmpty String name, password, address; private final @NotEmpty String username, password, address;
public RegistrationForm(String name, String password, String address) { public RegistrationForm(String username, String password, String address) {
this.name = name; this.username = username;
this.password = password; this.password = password;
this.address = address; this.address = address;
} }
public String getName() { public String getUsername() {
return name; return username;
} }
public String getPassword() { public String getPassword() {

View file

@ -63,7 +63,7 @@ public class User extends AbstractAggregateRoot<UserIdentifier> {
public static final class UserIdentifier implements Identifier, Serializable { public static final class UserIdentifier implements Identifier, Serializable {
private static final long serialVersionUID = 7740660930809051850L; private static final long serialVersionUID = 7740660930809051850L;
private final @SuppressWarnings("unused") UUID identifier; private final UUID identifier;
UserIdentifier() { UserIdentifier() {
this(UUID.randomUUID()); this(UUID.randomUUID());
@ -97,6 +97,11 @@ public class User extends AbstractAggregateRoot<UserIdentifier> {
return this.identifier.equals(that.identifier); return this.identifier.equals(that.identifier);
} }
@Override
public String toString(){
return identifier.toString();
}
} }
} }

View file

@ -1,11 +1,20 @@
package catering.users; package catering.users;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.salespointframework.useraccount.Role;
import org.salespointframework.useraccount.UserAccount;
import org.salespointframework.useraccount.web.LoggedIn;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import jakarta.validation.Valid;
@Controller @Controller
public class UserController { public class UserController {
@ -15,40 +24,96 @@ public class UserController {
this.userManagement = userManagerment; this.userManagement = userManagerment;
}; };
@GetMapping("/unauthorized")
String unauthorized(){
return "unauthorized";
}
@GetMapping("/register")
String register() {
return "register";
}
@PostMapping("/register")
String register(@Valid RegistrationForm form, Errors result) {
if (result.hasErrors()){
return "register";
}
userManagement.createCustomer(form.getUsername(),form.getAddress(),form.getPassword());
return "redirect:/login";
}
@GetMapping("/login")
public String loginPage(){
return "login";
}
@GetMapping("/profile") @GetMapping("/profile")
public String index(Model model) { @PreAuthorize("isAuthenticated()")
public String viewProfile(Model model, @LoggedIn UserAccount userAccount) {
model.addAttribute("user", userManagement.getUsers().findAll().toList().get(0)); if (userAccount == null) {
return "redirect:/";
}
User user = userManagement.getUserByAccount(userAccount).get();
model.addAttribute("user", user);
return "profile"; return "profile";
} }
@PostMapping("/profile") @PostMapping("/profile")
public String editProfile(@RequestParam String password, @RequestParam String address, @RequestParam String username) { @PreAuthorize("isAuthenticated()")
public String editProfile(@LoggedIn UserAccount userAccount, @RequestParam String password, @RequestParam String address, @RequestParam String username) {
User user = userManagement.getUserByAccount(userAccount).get();
User userAccount = userManagement.getUsers().findAll().toList().get(0); if (!username.isBlank()) {
user.setUsername(username);
if (!username.isBlank()){ }
userAccount.setUsername(username); if (!address.isBlank()) {
user.setAddress(address);
}
if (!password.isBlank()) {
userManagement.setPassword(password, user.getUserAccount());
} }
if (!address.isBlank()){ userManagement.save(user);
userAccount.setAddress(address);
}
if (!password.isBlank()){
userManagement.setPassword(password, userAccount.getUserAccount());
}
userManagement.save(userAccount);
return "redirect:/profile"; return "redirect:/profile";
} }
@GetMapping("/profile/delete") @GetMapping("/profile/disable")
public String deleteUser() { @PreAuthorize("hasRole('CUSTOMER')")
User userAccount = userManagement.getUsers().findAll().toList().get(0); public String disableUser(@LoggedIn UserAccount userAccount) {
userManagement.deleteUser(userAccount); userManagement.disableUserAccount(userAccount);
return "redirect:/"; return "redirect:/";
} }
@GetMapping("/customers")
@PreAuthorize("hasRole('ADMIN')")
public String getCustomer(Model model) {
model.addAttribute("title", "Kundenverwaltung");
model.addAttribute("customers", userManagement.getUsers().findAll().stream().filter(customer -> customer.getUserAccount().hasRole(Role.of("CUSTOMER"))).toList());
return "customers";
}
@GetMapping("/customers/remove/{id}")
@PreAuthorize("hasRole('ADMIN')")
public String removeCustomer(@PathVariable("id") User user, Model model) {
userManagement.disableUserAccount(user.getUserAccount());
return "redirect:/customers";
}
@GetMapping("/customers/edit/{id}")
@PreAuthorize("hasRole('ADMIN')")
public String editCustomer(@PathVariable("id") User user, Model model) {
model.addAttribute("customer", user);
return "edit-customer";
}
@PostMapping("/customers/edit/{id}")
@PreAuthorize("hasRole('ADMIN')")
public String updateCustomer(@PathVariable("id") User user, @RequestParam String username, @RequestParam String address, Model model) {
user.setUsername(username);
user.setAddress(address);
userManagement.save(user);
return "redirect:/customers";
}
} }

View file

@ -1,37 +1,28 @@
package catering.users; package catering.users;
import org.salespointframework.core.DataInitializer; import org.salespointframework.core.DataInitializer;
import org.salespointframework.useraccount.AuthenticationManagement;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.salespointframework.useraccount.AuthenticationManagement;
import org.springframework.web.bind.annotation.SessionAttributes; import org.springframework.web.bind.annotation.SessionAttributes;
@Component @Component
@Order(10)
@SessionAttributes("profile") @SessionAttributes("profile")
class UserDataInitializer implements DataInitializer { class UserDataInitializer implements DataInitializer {
private static final Logger LOG = LoggerFactory.getLogger(UserDataInitializer.class); private static final Logger LOG = LoggerFactory.getLogger(UserDataInitializer.class);
private final UserManagement userManagement; private final UserManagement userManagement;
UserDataInitializer(UserManagement userManagement, AuthenticationManagement auth) { UserDataInitializer(UserManagement userManagement, AuthenticationManagement auth) {
Assert.notNull(userManagement, "UserRepository must not be null!"); Assert.notNull(userManagement, "UserRepository must not be null!");
this.userManagement = userManagement; this.userManagement = userManagement;
} }
@Override @Override
public void initialize() { public void initialize() {
LOG.info("Creating default user."); LOG.info("Creating default user.");
userManagement.createAdmin("admin", "admin", "admin");
userManagement.createUser("Hans","123","Baum Weg");
} }
} }

View file

@ -1,13 +1,14 @@
package catering.users; package catering.users;
import org.springframework.web.bind.annotation.SessionAttributes; import java.util.Optional;
import org.salespointframework.useraccount.UserAccount;
import org.salespointframework.useraccount.Password.UnencryptedPassword; import org.salespointframework.useraccount.Password.UnencryptedPassword;
import org.salespointframework.useraccount.Role; import org.salespointframework.useraccount.Role;
import org.salespointframework.useraccount.UserAccount;
import org.salespointframework.useraccount.UserAccountManagement; import org.salespointframework.useraccount.UserAccountManagement;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.SessionAttributes;
@Service @Service
@Transactional @Transactional
@ -18,20 +19,19 @@ public class UserManagement {
private final UserAccountManagement userAccounts; private final UserAccountManagement userAccounts;
UserManagement(UserRepository users, UserAccountManagement userAccounts) { UserManagement(UserRepository users, UserAccountManagement userAccounts) {
this.users = users; this.users = users;
this.userAccounts = userAccounts; this.userAccounts = userAccounts;
} }
public User createUser(String name, String Password, String address) { public User createCustomer(String name, String address, String password) {
return users.save(new User(userAccounts.create(name,UnencryptedPassword.of(password),Role.of("CUSTOMER")), 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){ public User createAdmin(String name, String address, String password) {
return users.save(new User(userAccounts.create(name,UnencryptedPassword.of(password),Role.of("ADMIN")), address));
}
public User save(User user) {
return users.save(user); return users.save(user);
} }
@ -40,11 +40,15 @@ public class UserManagement {
return true; return true;
}; };
public UserRepository getUsers(){ public UserRepository getUsers() {
return users; return users;
} }
public void deleteUser(User user){ public void disableUserAccount(UserAccount userAccount) {
users.deleteById(user.getId()); userAccounts.disable(userAccount.getId());
}
public Optional<User> getUserByAccount(UserAccount userAccount) {
return users.findAll().stream().filter(u -> u.getUserAccount().equals(userAccount)).findFirst();
} }
} }

View file

@ -1,43 +0,0 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout.html(title='Kundenverwaltung')}">
<body>
<section layout:fragment="content">
<div class="verwaltung">
<h2>Kundenübersicht</h2>
<table>
<tr>
<th>ID</th>
<th>Nachname</th>
<th>Vorname</th>
<th>Aufträge</th>
</tr>
<tr th:each="customer : ${customers}">
<td th:text="${customer.id}">01</td>
<td th:text="${customer.surname}">Musterkoch</td>
<td th:text="${customer.name}">Max</td>
<td><a>Aufträge</a></td>
<td>
<a th:href="@{'/customer/edit/' + ${customer.id}}" class="button"
>Bearbeiten</a
>
</td>
<td>
<form th:action="@{/customer/remove}" method="post">
<input
type="hidden"
th:name="customerID"
th:value="${customer.id}"
/>
<button type="submit" class="delete-icon">Entfernen</button>
</form>
</td>
</tr>
</table>
</div>
</section>
</body>
</html>

View file

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout.html(title='Kunden')}">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" th:href="@{/resources/css/customer/style.css}" />
<title th:text="${title}"></title>
</head>
<body>
<section layout:fragment="content">
<div class="verwaltung">
<h1>Kundenverwaltung</h1>
<table>
<tr>
<th>Nutzername</th>
<th>Aufträge</th>
<th>Bearbeiten</th>
<th>Entfernen</th>
</tr>
<tr th:each="customer : ${customers}">
<td th:text="${customer.username}">Musterkoch</td>
<td>Aufträge</td>
<td><a th:href="@{/customers/edit/{id}(id=${customer.id})}" class="button">Bearbeiten</a></td>
<td><a th:href="@{/customers/remove/{id}(id=${customer.id})}" class="button">Entfernen</a></td>
</td>
</tr>
</table>
</div>
</section>
</body>
</html>

View file

@ -16,22 +16,13 @@
<section layout:fragment="content"> <section layout:fragment="content">
<div class="edit-customer-form"> <div class="edit-customer-form">
<h2>Kunde Bearbeiten</h2> <h2>Kunde Bearbeiten</h2>
<form <form method="post">
th:action="@{/customer/update}" <h3>Nutzername</h3>
th:object="${customer}" <input type="text" name="username" th:value="${customer.username}"/>
method="post" <h3>Addresse</h3>
> <input type="text" name="address" th:value="${customer.address}"/>
<input type="hidden" th:field="*{id}" />
<label for="name">Name:</label>
<input type="text" th:field="*{name}" required />
<label for="surname">Nachname:</label>
<input type="text" th:field="*{surname}" required />
<button type="submit">Save</button> <button type="submit">Save</button>
</form> </form>
<a th:href="@{/customer}" class="button">Cancel</a>
</div> </div>
</section> </section>
</body> </body>

View file

@ -10,7 +10,7 @@
<a class="item" th:href="@{/inventory}" sec:authorize="hasRole('ADMIN')">Inventar</a> <a class="item" th:href="@{/inventory}" sec:authorize="hasRole('ADMIN')">Inventar</a>
<a class="item" th:href="@{/catalog}">Katalog</a> <a class="item" th:href="@{/catalog}">Katalog</a>
<a class="item" th:href="@{/staff}" sec:authorize="hasRole('ADMIN')">Angestellte</a> <a class="item" th:href="@{/staff}" sec:authorize="hasRole('ADMIN')">Angestellte</a>
<a class="item" th:href="@{/customer}" sec:authorize="hasRole('ADMIN')">Kunden</a> <a class="item" th:href="@{/customers}" sec:authorize="hasRole('ADMIN')">Kunden</a>
<a class="item" th:href="@{/orders}" sec:authorize="isAuthenticated()">Bestellungen</a> <a class="item" th:href="@{/orders}" sec:authorize="isAuthenticated()">Bestellungen</a>
<a class="item" th:href="@{/event}" sec:authorize="hasRole('CUSTOMER')">Event planen</a> <a class="item" th:href="@{/event}" sec:authorize="hasRole('CUSTOMER')">Event planen</a>
<a class="item" th:href="@{/orders/calender}" sec:authorize="hasRole('ADMIN')">Kalender</a> <a class="item" th:href="@{/orders/calender}" sec:authorize="hasRole('ADMIN')">Kalender</a>
@ -22,7 +22,7 @@
<a class="item" th:href="@{/logout}" sec:authorize="isAuthenticated()">Logout</a> <a class="item" th:href="@{/logout}" sec:authorize="isAuthenticated()">Logout</a>
</div> </div>
</div> </div>
<br/> <br/>
</nav> </nav>
</body> </body>
</html> </html>

View file

@ -34,7 +34,7 @@
<h1 class="danger_zone" th:text="#{profile.danger_zone}"></h1> <h1 class="danger_zone" th:text="#{profile.danger_zone}"></h1>
<div class="horizontal_center"> <div class="horizontal_center">
<button class="danger_zone" th:text="#{profile.edit}" type="submit"></button> <button class="danger_zone" th:text="#{profile.edit}" type="submit"></button>
<a th:href="@{/profile/delete}"> <a th:href="@{/profile/disable}">
<button class="danger_zone" th:text="#{profile.delete}" type="button"></button> <button class="danger_zone" th:text="#{profile.delete}" type="button"></button>
</a> </a>
</div> </div>

View file

@ -0,0 +1,6 @@
<html xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout.html(title='Access Denied')}">
<h1>Access Denied</h1>
</html>