that's all, folks?

This commit is contained in:
1yuee 2023-06-20 13:51:27 +04:00
parent 263182db1d
commit 71dd9b4fde
8 changed files with 170 additions and 8 deletions

View File

@ -1,11 +1,19 @@
package com.webproglabs.lab1.mvc;
import com.webproglabs.lab1.dto.UserDto;
import com.webproglabs.lab1.dto.UserSignupDto;
import com.webproglabs.lab1.models.User;
import com.webproglabs.lab1.models.UserRole;
import com.webproglabs.lab1.services.UserService;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@Controller
@RequestMapping("/users")
@ -17,8 +25,55 @@ public class UserMvcController {
}
@GetMapping
@Secured({UserRole.AsString.ADMIN})
public String getUsersPage(Model model){
model.addAttribute("users", userService.findAllUsers().stream().map(UserDto::new).toList());
model.addAttribute("profiles", userService.findAllUsers().stream().map(UserDto::new).toList());
return "users";
}
@PostMapping(value = {"/{id}"})
@Secured({UserRole.AsString.ADMIN})
public String deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
return "redirect:/users";
}
@GetMapping(value = {"/{login}"})
public String getUserPage(@PathVariable String login, Model model) {
model.addAttribute("user", new UserDto(userService.findUserByLogin(login)));
return "userPage";
}
@GetMapping(value = {"/settings"})
public String getUserEditPage(Model model) {
UserDetails principal = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
var currentUser = userService.findUserByLogin(principal.getUsername());
model.addAttribute("user", new UserDto(userService.findUserById(currentUser.getId())));
model.addAttribute("userDto", new UserSignupDto());
return "userEditPage";
}
@PostMapping(value = {"/edit/{id}"})
public String editUserData(@PathVariable Long id, @ModelAttribute("userDto") @Valid UserSignupDto userSignupDto,
BindingResult bindingResult,
Model model) {
UserDetails principal = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
var currentUser = userService.findUserByLogin(principal.getUsername());
model.addAttribute("user", new UserDto(userService.findUserById(currentUser.getId())));
model.addAttribute("userDto", new UserSignupDto());
if (bindingResult.hasErrors()) {
model.addAttribute("errors", bindingResult.getAllErrors());
return "userEditPage";
}
try {
final User user = userService.updateUser(id, userSignupDto.getLogin(), userSignupDto.getPassword(), userSignupDto.getPasswordConfirm());
model.addAttribute("success", "Данные успешно изменены");
return "userEditPage";
} catch (Exception e) {
model.addAttribute("errors", e.getMessage());
return "userEditPage";
}
}
}

View File

@ -62,13 +62,23 @@ public class UserService implements UserDetailsService {
}
@Transactional
public User updateUser(Long id, String login, String password) {
public User updateUser(Long id, String login, String password, String passwordConfirm) {
if (!StringUtils.hasText(login) || !StringUtils.hasText(password)) {
throw new IllegalArgumentException("User data is null or empty");
}
final User currentUser = findUserById(id);
if (Objects.equals(password, currentUser.getPassword())) {
throw new IllegalArgumentException("New password is the same as old");
}
if (!Objects.equals(password, passwordConfirm)) {
throw new IllegalArgumentException("Password mismatch");
}
currentUser.setLogin(login);
currentUser.setPassword(password);
currentUser.setPassword(passwordEncoder.encode(password));
return userRepository.save(currentUser);
}

View File

@ -20,13 +20,14 @@
<body>
<div>
<p class='text-center m-3 h3'> СоцСеточка</p>
<p class='text-center mt-3 h3'> СоцСеточка</p>
</div>
<div>
<p class='h4 text-center'>
<a sec:authorize="hasRole('ROLE_ADMIN')" href="/topic" class="text-decoration-none m-3 text-secondary">Топики</a>
<a sec:authorize="hasRole('ROLE_ADMIN')" href="/users" class="text-decoration-none m-3 text-secondary">Пользователи</a>
<a sec:authorize="isAuthenticated()" href="/feed" class="text-decoration-none m-3 text-secondary">Лента</a>
<a sec:authorize="isAuthenticated()" href="/users/settings" class="text-decoration-none m-3 text-secondary">Настройки</a>
<a sec:authorize="isAuthenticated()" href="/logout" class="text-decoration-none m-3 text-secondary">
Выход
</a>

View File

@ -11,7 +11,7 @@
<div class="dropdown text-center mx-auto w-75">
<div class="text-center mt-3">
<button class="btn btn-secondary dropdown-toggle ms-3 mb-3 w-50" type="button" data-bs-toggle="dropdown" aria-expanded="false">
Выбор топика
Выбор темы
</button>
<ul class="dropdown-menu w-50" >
<li th:each="topic: ${topics}">

View File

@ -33,7 +33,7 @@
<div class="d-flex justify-content-between fst-italic">
<div>
Автор:
<a th:text="${post.getAuthor()}" class="text-start fst-italic" th:href="@{/profile/{login}(login=${post.getAuthor()})}"></a>
<a th:text="${post.getAuthor()}" class="text-start fst-italic" th:href="@{/users/{login}(login=${post.getAuthor()})}"></a>
</div>
<div th:if="${selectedProfile.getLogin() == post.getAuthor()}" class="d-flex justify-content-between fst-italic">
<form th:action="@{/feed/deletePost/{id}/{topicId} (id=${post.id}, topicId=${selectedTopic.id})}" method="post" >

View File

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
</head>
<body>
<div layout:fragment="content">
<div class="text-center">
<div th:if="${errors}" th:text="${errors}" class="margin-bottom alert alert-danger"></div>
<div th:if="${success}" th:text="${success}" class="margin-bottom text-success"></div>
<div class="text-start mx-auto w-50 border p-5">
<p class='h5'>Изменение данных пользователя</p>
<p th:text="${'Логин: ' + user.login}"></p>
<form action="#" th:action="@{/users/edit/{id} (id=${user.id})}" th:object="${userDto}" method="post">
<p>Новый логин:</p>
<input th:field="${userDto.login}" type="text" class="mb-2 form-control" required="true" autofocus="true" maxlength="64"/>
<p>Новый пароль:</p>
<input th:field="${userDto.password}" type="password" class="mb-2 form-control" required="true" minlength="4" maxlength="64"/>
<p>Повторите пароль:</p>
<input th:field="${userDto.passwordConfirm}" type="password" class="mb-2 form-control" required="true" minlength="4" maxlength="64"/>
<button type="submit" class="btn btn-success" >Сохранить изменения</button>
</form>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
</head>
<body>
<div layout:fragment="content">
<div class="text-center">
<div class="text-start mx-auto w-50 border p-5">
<p class='h5'>Профиль</p>
<p th:text="${'Логин: ' + user.login}"></p>
<p class='h6 '>Список постов пользователя: </p>
<div th:if="${user.posts.size()>0}">
<div th:each="post: ${user.posts}">
<p th:text="${post.text}" class="mb-3 ms-2 border p-2"></p>
</div>
</div>
<p th:unless="${user.posts.size()>0}">
Нет постов
</p>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,36 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<div layout:fragment="content" class="text-center">
<div th:each="profile: ${profiles}" class="mb-2">
<div class="text-center">
<div class="text-start mx-auto w-50 border shadow p-3">
<p class='h5'>Профиль</p>
<p th:text="${'Логин: ' + profile.login}"></p>
<p class='h6 '>Список постов пользователя: </p>
<div th:if="${profile.posts.size()>0}">
<div th:each="post: ${profile.posts}">
<p th:text="${post.text}" class="mb-3 ms-2 border p-2"></p>
</div>
</div>
<p th:unless="${profile.posts.size()>0}">
Нет постов
</p>
<div class="text-end" th:if="${profile.login!='admin'}">
<form action="#" th:action="@{/users/{id} (id=${profile.id})}" method="post" >
<button type="submit" class="btn btn-danger">Удалить</button>
</form>
</div>
</div>
</div>
</div>
</div>
</body>
</html>