diff --git a/pom.xml b/pom.xml
index 46299bd..81738c6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -69,6 +69,14 @@
org.springframework.boot
spring-boot-starter-mail
+
+ org.flywaydb
+ flyway-core
+
+
+ org.flywaydb
+ flyway-mysql
+
diff --git a/src/main/java/net/sytes/kashey/sweater/controller/UserController.java b/src/main/java/net/sytes/kashey/sweater/controller/UserController.java
index 6b9adf6..b721c19 100644
--- a/src/main/java/net/sytes/kashey/sweater/controller/UserController.java
+++ b/src/main/java/net/sytes/kashey/sweater/controller/UserController.java
@@ -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 form,
@RequestParam("userId") User user) {
- user.setUsername(username);
- user.getRoles().clear();
- Set 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";
+ }
}
\ No newline at end of file
diff --git a/src/main/java/net/sytes/kashey/sweater/domain/Message.java b/src/main/java/net/sytes/kashey/sweater/domain/Message.java
index 2bff318..4048587 100644
--- a/src/main/java/net/sytes/kashey/sweater/domain/Message.java
+++ b/src/main/java/net/sytes/kashey/sweater/domain/Message.java
@@ -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;
}
diff --git a/src/main/java/net/sytes/kashey/sweater/security/CustomUserDetails.java b/src/main/java/net/sytes/kashey/sweater/security/CustomUserDetails.java
index 8413b67..c2d4c82 100644
--- a/src/main/java/net/sytes/kashey/sweater/security/CustomUserDetails.java
+++ b/src/main/java/net/sytes/kashey/sweater/security/CustomUserDetails.java
@@ -61,4 +61,8 @@ public class CustomUserDetails implements UserDetails {
public boolean isAdmin() {
return user.getRoles().contains(Role.ADMIN);
}
+
+ public String getEmail() {
+ return user.getEmail();
+ }
}
\ No newline at end of file
diff --git a/src/main/java/net/sytes/kashey/sweater/service/CustomUserDetailsService.java b/src/main/java/net/sytes/kashey/sweater/service/CustomUserDetailsService.java
index 7d5cff3..398662d 100644
--- a/src/main/java/net/sytes/kashey/sweater/service/CustomUserDetailsService.java
+++ b/src/main/java/net/sytes/kashey/sweater/service/CustomUserDetailsService.java
@@ -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 form, User user) {
+
+ user.setUsername(username);
+ user.getRoles().clear();
+ Set 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 findAll() {
+ return userRepository.findAll();
+ }
}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 3050627..35ede6f 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -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
diff --git a/src/main/resources/db/migration/V1__Init_DB.sql b/src/main/resources/db/migration/V1__Init_DB.sql
new file mode 100644
index 0000000..ce9f7ca
--- /dev/null
+++ b/src/main/resources/db/migration/V1__Init_DB.sql
@@ -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);
diff --git a/src/main/resources/db/migration/V2__Add_admin.sql b/src/main/resources/db/migration/V2__Add_admin.sql
new file mode 100644
index 0000000..a2ac870
--- /dev/null
+++ b/src/main/resources/db/migration/V2__Add_admin.sql
@@ -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');
\ No newline at end of file
diff --git a/src/main/resources/templates/parts/navbar.ftl b/src/main/resources/templates/parts/navbar.ftl
index 22cd2df..5371439 100644
--- a/src/main/resources/templates/parts/navbar.ftl
+++ b/src/main/resources/templates/parts/navbar.ftl
@@ -22,6 +22,11 @@
Users
#if>
+ <#if user??>
+
+ Profile
+
+ #if>
${name}
diff --git a/src/main/resources/templates/profile.ftl b/src/main/resources/templates/profile.ftl
new file mode 100644
index 0000000..2a50586
--- /dev/null
+++ b/src/main/resources/templates/profile.ftl
@@ -0,0 +1,24 @@
+<#import "parts/common.ftl" as com>
+
+<@com.page>
+ ${username}
+ <#if message??>
+ ${message}
+ #if>
+
+@com.page>
\ No newline at end of file