- Добавил миграции Flyway.
- Добавил профиль пользователя и возможность его редактирования. https://www.youtube.com/watch?v=ArM7nCys4hY&list=PLU2ftbIeotGpAYRP9Iv2KLIwK36-o_qYk&index=12
This commit is contained in:
8
pom.xml
8
pom.xml
@@ -69,6 +69,14 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-mail</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-mysql</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -2,36 +2,37 @@ package net.sytes.kashey.sweater.controller;
|
||||
|
||||
import net.sytes.kashey.sweater.domain.Role;
|
||||
import net.sytes.kashey.sweater.domain.User;
|
||||
import net.sytes.kashey.sweater.repository.UserRepository;
|
||||
import net.sytes.kashey.sweater.security.CustomUserDetails;
|
||||
import net.sytes.kashey.sweater.service.CustomUserDetailsService;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/users")
|
||||
@PreAuthorize("hasAuthority('ADMIN')")
|
||||
|
||||
public class UserController {
|
||||
|
||||
private final UserRepository userRepository;
|
||||
private final CustomUserDetailsService customUserDetailsService;
|
||||
|
||||
public UserController(UserRepository userRepository) {
|
||||
public UserController(CustomUserDetailsService customUserDetailsService) {
|
||||
|
||||
this.userRepository = userRepository;
|
||||
this.customUserDetailsService = customUserDetailsService;
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('ADMIN')")
|
||||
@GetMapping
|
||||
public String getAllUsers(Model model) {
|
||||
|
||||
model.addAttribute("users", userRepository.findAll());
|
||||
model.addAttribute("users", customUserDetailsService.findAll());
|
||||
return "userList";
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('ADMIN')")
|
||||
@GetMapping("/{user}")
|
||||
public String editUser(@PathVariable User user, Model model) {
|
||||
|
||||
@@ -40,20 +41,31 @@ public class UserController {
|
||||
return "userEdit";
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('ADMIN')")
|
||||
@PostMapping
|
||||
public String updateUser(@RequestParam String username,
|
||||
@RequestParam Map<String, String> form,
|
||||
@RequestParam("userId") User user) {
|
||||
|
||||
user.setUsername(username);
|
||||
user.getRoles().clear();
|
||||
Set<String> roles = Arrays.stream(Role.values()).map(Enum::name).collect(Collectors.toSet());
|
||||
for (String role : form.keySet()) {
|
||||
if (roles.contains(role)) {
|
||||
user.getRoles().add(Role.valueOf(role));
|
||||
}
|
||||
}
|
||||
userRepository.save(user);
|
||||
customUserDetailsService.updateUser(username, form, user);
|
||||
return "redirect:/users";
|
||||
}
|
||||
|
||||
@GetMapping("/profile")
|
||||
public String getProfile(Model model, @AuthenticationPrincipal CustomUserDetails customUserDetails) {
|
||||
model.addAttribute("username", customUserDetails.getUsername());
|
||||
model.addAttribute("email", customUserDetails.getEmail());
|
||||
model.addAttribute("password", customUserDetails.getPassword());
|
||||
customUserDetails.getPassword();
|
||||
return "profile";
|
||||
}
|
||||
|
||||
@PostMapping("/profile")
|
||||
public String updateProfile(@AuthenticationPrincipal CustomUserDetails customUserDetails,
|
||||
@RequestParam String password,
|
||||
@RequestParam String email) {
|
||||
|
||||
customUserDetailsService.updateProfile(customUserDetails.getUser(), password, email);
|
||||
return "redirect:/users/profile";
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import jakarta.persistence.*;
|
||||
public class Message {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Integer id;
|
||||
private Long id;
|
||||
private String text;
|
||||
private String tag;
|
||||
|
||||
@@ -25,11 +25,11 @@ public class Message {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,4 +61,8 @@ public class CustomUserDetails implements UserDetails {
|
||||
public boolean isAdmin() {
|
||||
return user.getRoles().contains(Role.ADMIN);
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return user.getEmail();
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,8 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class CustomUserDetailsService implements UserDetailsService {
|
||||
@@ -53,6 +53,11 @@ public class CustomUserDetailsService implements UserDetailsService {
|
||||
user.setPassword("{noop}" + user.getPassword()); //пока не введено шифрование паролей
|
||||
userRepository.save(user);
|
||||
|
||||
sendMessage(user);
|
||||
return "";
|
||||
}
|
||||
|
||||
private void sendMessage(User user) {
|
||||
if (!ObjectUtils.isEmpty(user.getEmail())) {
|
||||
|
||||
String message = String.format(
|
||||
@@ -65,7 +70,6 @@ public class CustomUserDetailsService implements UserDetailsService {
|
||||
|
||||
emailService.send(user.getEmail(), "Activation code", message);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public boolean activateUser(String activationCode) {
|
||||
@@ -80,4 +84,47 @@ public class CustomUserDetailsService implements UserDetailsService {
|
||||
userRepository.save(user);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void updateUser(String username, Map<String, String> form, User user) {
|
||||
|
||||
user.setUsername(username);
|
||||
user.getRoles().clear();
|
||||
Set<String> roles = Arrays.stream(Role.values()).map(Enum::name).collect(Collectors.toSet());
|
||||
for (String role : form.keySet()) {
|
||||
if (roles.contains(role)) {
|
||||
user.getRoles().add(Role.valueOf(role));
|
||||
}
|
||||
}
|
||||
userRepository.save(user);
|
||||
}
|
||||
|
||||
public void updateProfile(User user, String password, String email) {
|
||||
|
||||
String userEmail = user.getEmail();
|
||||
|
||||
boolean isEmailChanged = (email != null && !email.equals(userEmail)) ||
|
||||
(userEmail != null && !userEmail.equals(email));
|
||||
|
||||
if (isEmailChanged) {
|
||||
user.setEmail(email);
|
||||
|
||||
if (!ObjectUtils.isEmpty(email)) {
|
||||
user.setActivationCode(UUID.randomUUID().toString());
|
||||
}
|
||||
}
|
||||
|
||||
if (!ObjectUtils.isEmpty(password)) {
|
||||
user.setPassword("{noop}" + password);
|
||||
}
|
||||
|
||||
userRepository.save(user);
|
||||
|
||||
if (isEmailChanged) {
|
||||
sendMessage(user);
|
||||
}
|
||||
}
|
||||
|
||||
public List<User> findAll() {
|
||||
return userRepository.findAll();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
spring.jpa.hibernate.ddl-auto=validate
|
||||
spring.jpa.show-sql=true
|
||||
spring.datasource.url=jdbc:mysql://${MYSQL_HOST:localhost}:3306/sweater_db
|
||||
spring.datasource.username=user
|
||||
spring.datasource.password=123456
|
||||
|
||||
48
src/main/resources/db/migration/V1__Init_DB.sql
Normal file
48
src/main/resources/db/migration/V1__Init_DB.sql
Normal file
@@ -0,0 +1,48 @@
|
||||
create table message
|
||||
(
|
||||
id bigint not null,
|
||||
user_id bigint,
|
||||
filename varchar(255),
|
||||
tag varchar(255),
|
||||
text varchar(2048) not null,
|
||||
primary key (id)
|
||||
) engine = InnoDB;
|
||||
|
||||
create table message_seq
|
||||
(
|
||||
next_val bigint
|
||||
) engine = InnoDB;
|
||||
|
||||
insert into message_seq
|
||||
values (1);
|
||||
|
||||
create table user_role
|
||||
(
|
||||
user_id bigint not null,
|
||||
roles enum ('ADMIN','USER')
|
||||
) engine = InnoDB;
|
||||
|
||||
create table usr
|
||||
(
|
||||
enabled bit not null,
|
||||
id bigint not null,
|
||||
activation_code varchar(255),
|
||||
email varchar(255),
|
||||
password varchar(255) not null,
|
||||
username varchar(255) not null,
|
||||
primary key (id)
|
||||
) engine = InnoDB;
|
||||
|
||||
create table usr_seq
|
||||
(
|
||||
next_val bigint
|
||||
) engine = InnoDB;
|
||||
|
||||
insert into usr_seq
|
||||
values (1);
|
||||
|
||||
alter table message
|
||||
add constraint message_user_fk foreign key (user_id) references usr (id);
|
||||
|
||||
alter table user_role
|
||||
add constraint user_role_user_fk foreign key (user_id) references usr (id);
|
||||
5
src/main/resources/db/migration/V2__Add_admin.sql
Normal file
5
src/main/resources/db/migration/V2__Add_admin.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
insert into usr (id, username, password, enabled)
|
||||
values (1, 'admin', '{noop}admin', true);
|
||||
|
||||
insert into user_role (user_id, roles)
|
||||
values (1, 'USER'), (1, 'ADMIN');
|
||||
@@ -22,6 +22,11 @@
|
||||
<a class="nav-link" aria-current="page" href="/users">Users</a>
|
||||
</li>
|
||||
</#if>
|
||||
<#if user??>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" aria-current="page" href="/users/profile">Profile</a>
|
||||
</li>
|
||||
</#if>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="navbar-text mr-3" >${name}</div>
|
||||
|
||||
24
src/main/resources/templates/profile.ftl
Normal file
24
src/main/resources/templates/profile.ftl
Normal file
@@ -0,0 +1,24 @@
|
||||
<#import "parts/common.ftl" as com>
|
||||
|
||||
<@com.page>
|
||||
<h5>${username}</h5>
|
||||
<#if message??>
|
||||
<div class="mb-3"> ${message} </div>
|
||||
</#if>
|
||||
<form method="post" xmlns="http://www.w3.org/1999/html">
|
||||
<div class="row mb-3">
|
||||
<label for="inputPassword3" class="col-sm-2 col-form-label"> Password: </label>
|
||||
<div class="col-sm-6">
|
||||
<input type="password" class="form-control" name="password" value="${password}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 col-form-label"> E-mail:</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="email" class="form-control" name="email" value="${email!''}"/>
|
||||
</div>
|
||||
</div>
|
||||
<input class="btn btn-primary" type="submit" value="Save"/>
|
||||
<input type="hidden" name="_csrf" value="${_csrf.token}"/>
|
||||
</form>
|
||||
</@com.page>
|
||||
Reference in New Issue
Block a user