Add form for creating users to ManageUsers page. Fix delete users bug, add login-in-use validations
This commit is contained in:
parent
38ebab2ff0
commit
aec02f027a
6 changed files with 112 additions and 18 deletions
|
@ -0,0 +1,35 @@
|
||||||
|
package ru.redrise.marinesco;
|
||||||
|
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
import lombok.Data;
|
||||||
|
import ru.redrise.marinesco.data.RolesRepository;
|
||||||
|
import ru.redrise.marinesco.security.UserRole;
|
||||||
|
|
||||||
|
//TODO: refactor along with RegistrationForm.java
|
||||||
|
@Data
|
||||||
|
public class AdministatorAddUserForm {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Size(min=3, max=32, message="Username must be at least 3 characters long. Should not exceed 32 characters.")
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Size(min=8, max = 32, message="Password must be at least 8 characters long. Should not exceed 32 characters.")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@NotEmpty(message = "Display name could not be blank")
|
||||||
|
private String displayname;
|
||||||
|
|
||||||
|
public User toUser(PasswordEncoder passwordEncoder, RolesRepository rolesRepo){
|
||||||
|
return new User(
|
||||||
|
username,
|
||||||
|
passwordEncoder.encode(password),
|
||||||
|
displayname,
|
||||||
|
rolesRepo.findByType(UserRole.Type.USER));
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,21 +2,19 @@ package ru.redrise.marinesco;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.ManyToAny;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
|
||||||
import jakarta.persistence.CascadeType;
|
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.FetchType;
|
import jakarta.persistence.FetchType;
|
||||||
import jakarta.persistence.GeneratedValue;
|
import jakarta.persistence.GeneratedValue;
|
||||||
import jakarta.persistence.GenerationType;
|
import jakarta.persistence.GenerationType;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.ManyToMany;
|
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.val;
|
|
||||||
import ru.redrise.marinesco.security.UserRole;
|
import ru.redrise.marinesco.security.UserRole;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@ -37,7 +35,7 @@ public class User implements UserDetails{
|
||||||
private String password;
|
private String password;
|
||||||
private String displayname;
|
private String displayname;
|
||||||
|
|
||||||
@ManyToMany(cascade = CascadeType.REMOVE, fetch = FetchType.EAGER)
|
@ManyToAny(fetch = FetchType.EAGER)
|
||||||
private final List<UserRole> authorities;
|
private final List<UserRole> authorities;
|
||||||
|
|
||||||
public User(String username, String password, String displayname, List<UserRole> authorities){
|
public User(String username, String password, String displayname, List<UserRole> authorities){
|
||||||
|
|
|
@ -4,19 +4,23 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
|
import org.springframework.validation.Errors;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import ru.redrise.marinesco.AdministatorAddUserForm;
|
||||||
import ru.redrise.marinesco.User;
|
import ru.redrise.marinesco.User;
|
||||||
import ru.redrise.marinesco.UserGenerified;
|
import ru.redrise.marinesco.UserGenerified;
|
||||||
|
import ru.redrise.marinesco.data.RolesRepository;
|
||||||
import ru.redrise.marinesco.data.UserRepository;
|
import ru.redrise.marinesco.data.UserRepository;
|
||||||
|
|
||||||
|
|
||||||
//TODO
|
//TODO
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Controller
|
@Controller
|
||||||
|
@ -24,10 +28,16 @@ import ru.redrise.marinesco.data.UserRepository;
|
||||||
@PreAuthorize("hasRole('ADMIN')")
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public class ManageUsersController {
|
public class ManageUsersController {
|
||||||
|
|
||||||
private UserRepository userRepository;
|
private final UserRepository userRepository;
|
||||||
|
private final RolesRepository rolesRepository;
|
||||||
|
private final PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
public ManageUsersController(UserRepository userRepository){
|
public ManageUsersController(UserRepository userRepository,
|
||||||
|
RolesRepository rolesRepository,
|
||||||
|
PasswordEncoder passwordEncoder) {
|
||||||
this.userRepository = userRepository;
|
this.userRepository = userRepository;
|
||||||
|
this.rolesRepository = rolesRepository;
|
||||||
|
this.passwordEncoder = passwordEncoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ModelAttribute(name = "userGenerified")
|
@ModelAttribute(name = "userGenerified")
|
||||||
|
@ -36,18 +46,19 @@ public class ManageUsersController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ModelAttribute
|
@ModelAttribute
|
||||||
public void addTitle(Model model){
|
public void addTitle(Model model) {
|
||||||
model.addAttribute("header_text", "Manage users");
|
model.addAttribute("header_text", "Manage users");
|
||||||
|
model.addAttribute("administatorAddUserForm", new AdministatorAddUserForm());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ModelAttribute
|
@ModelAttribute
|
||||||
public void addUsers(Model model){
|
public void addUsers(Model model) {
|
||||||
Iterable<User> users = userRepository.findAll();
|
Iterable<User> users = userRepository.findAll();
|
||||||
List<UserGenerified> usersGen = new ArrayList<>();
|
List<UserGenerified> usersGen = new ArrayList<>();
|
||||||
for (User user : users){
|
for (User user : users) {
|
||||||
usersGen.add(new UserGenerified(user)); // TODO: ADD ARRAY INSTEAD OF ONE!
|
usersGen.add(new UserGenerified(user));
|
||||||
}
|
}
|
||||||
model.addAttribute("USR", usersGen); // TODO: ADD ARRAY INSTEAD OF ONE!
|
model.addAttribute("USR", usersGen);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
|
@ -56,11 +67,28 @@ public class ManageUsersController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/delete")
|
@PostMapping("/delete")
|
||||||
public String processDelete(UserGenerified userGenerified){
|
public String processDelete(UserGenerified userGenerified) {
|
||||||
log.info(userGenerified.toString());
|
log.info(userGenerified.toString());
|
||||||
|
|
||||||
userRepository.deleteById(userGenerified.getId());
|
userRepository.deleteById(userGenerified.getId());
|
||||||
|
|
||||||
return "redirect:/manage_users";
|
return "redirect:/manage_users";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public String processNewUser(@Valid AdministatorAddUserForm form, Errors errors, Model model) {
|
||||||
|
if (userRepository.findByUsername(form.getUsername()) != null) {
|
||||||
|
model.addAttribute("loginOccupied", "Login already in use. Please choose another one");
|
||||||
|
return "manage_users";
|
||||||
|
}
|
||||||
|
if (errors.hasErrors()) {
|
||||||
|
log.info(errors.getAllErrors().toString());
|
||||||
|
return "manage_users";
|
||||||
|
}
|
||||||
|
|
||||||
|
User user = userRepository.save(form.toUser(passwordEncoder, rolesRepository));
|
||||||
|
log.info("Added user {} {} {}", user.getId(), user.getUsername(), user.getDisplayname());
|
||||||
|
// Reloads page therefore new records appears
|
||||||
|
return "redirect:/manage_users";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,19 +46,23 @@ public class RegistrationController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public String postMethodName(@Valid RegistrationForm registerForm, Errors errors, Model model) {
|
public String postMethodName(@Valid RegistrationForm form, Errors errors, Model model) {
|
||||||
if (registerForm.isPasswordsNotEqual()) {
|
if (form.isPasswordsNotEqual()) {
|
||||||
model.addAttribute("passwordsMismatch", "Passwords must be the same.");
|
model.addAttribute("passwordsMismatch", "Passwords must be the same.");
|
||||||
return "registration";
|
return "registration";
|
||||||
}
|
}
|
||||||
|
if (userRepo.findByUsername(form.getUsername()) != null){
|
||||||
|
model.addAttribute("loginOccupied", "Login already in use. Please choose another one");
|
||||||
|
return "registration";
|
||||||
|
}
|
||||||
if (errors.hasErrors()) {
|
if (errors.hasErrors()) {
|
||||||
return "registration";
|
return "registration";
|
||||||
}
|
}
|
||||||
|
|
||||||
User user = userRepo.save(registerForm.toUser(passwordEncoder, rolesRepo));
|
User user = userRepo.save(form.toUser(passwordEncoder, rolesRepo));
|
||||||
log.info("Added user {} {} {}", user.getId(), user.getUsername(), user.getDisplayname());
|
log.info("Added user {} {} {}", user.getId(), user.getUsername(), user.getDisplayname());
|
||||||
|
|
||||||
if (registerForm.auth(request))
|
if (form.auth(request))
|
||||||
return "redirect:/";
|
return "redirect:/";
|
||||||
return "redirect:/login";
|
return "redirect:/login";
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,10 +26,37 @@
|
||||||
<input type="hidden" th:value="${role.id}" th:attr="name='role'" />
|
<input type="hidden" th:value="${role.id}" th:attr="name='role'" />
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<button>DELETE</button>
|
<button>Delete</button>
|
||||||
</form>
|
</form>
|
||||||
<br />
|
<br />
|
||||||
</div>
|
</div>
|
||||||
|
<hr>
|
||||||
|
<b>Add user</b>
|
||||||
|
<form method="POST" th:action="@{/manage_users}" th:object="${administatorAddUserForm}">
|
||||||
|
<span class="validationError" th:if="${loginOccupied} != null" th:text="${loginOccupied}">pew</span>
|
||||||
|
<span class="validationError" th:if="${#fields.hasErrors('username')}"
|
||||||
|
th:errors="*{username}">Error</span>
|
||||||
|
<br />
|
||||||
|
<label for="username">Username: </label>
|
||||||
|
<input type="text" name="username" id="username" size="50%" /><br />
|
||||||
|
|
||||||
|
<span class="validationError" th:if="${#fields.hasErrors('password')}"
|
||||||
|
th:errors="*{password}">Error</span>
|
||||||
|
<br />
|
||||||
|
<label for="password">Password: </label>
|
||||||
|
<input type="password" name="password" id="password" size="50%" /><br />
|
||||||
|
<span class="validationError" th:if="${#fields.hasErrors('displayname')}"
|
||||||
|
th:errors="*{displayname}">Error</span>
|
||||||
|
<br />
|
||||||
|
<label for="displayname">Displayed name: </label>
|
||||||
|
<input type="text" name="displayname" id="displayname" size="50%" /><br />
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<button class="sign" type="submit">Add user</button>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div th:replace="~{fragments/footer :: 'footer'}"></div>
|
<div th:replace="~{fragments/footer :: 'footer'}"></div>
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
<div class="container base">
|
<div class="container base">
|
||||||
<h1>Register</h1>
|
<h1>Register</h1>
|
||||||
<form class="regForm" method="POST" th:action="@{/register}" th:object="${registrationForm}">
|
<form class="regForm" method="POST" th:action="@{/register}" th:object="${registrationForm}">
|
||||||
|
<span class="validationError" th:if="${loginOccupied} != null"
|
||||||
|
th:text="${loginOccupied}">pew</span>
|
||||||
|
|
||||||
<span class="validationError" th:if="${#fields.hasErrors('username')}"
|
<span class="validationError" th:if="${#fields.hasErrors('username')}"
|
||||||
th:errors="*{username}">Error</span>
|
th:errors="*{username}">Error</span>
|
||||||
|
|
Loading…
Reference in a new issue