From 52b7f3d76146105f49d73885bafb5dd6e0a344fc Mon Sep 17 00:00:00 2001 From: Danila_Mochalov Date: Tue, 2 May 2023 00:06:37 +0400 Subject: [PATCH] Lab 6 MVC WITHOUT SPA --- build.gradle | 3 + data.mv.db | Bin 94208 -> 151552 bytes .../lab1/PasswordEncoderConfiguration.java | 14 ++++ .../lab1/SecurityConfiguration.java | 71 ++++++++++++++++++ .../webproglabs/lab1/WebConfiguration.java | 2 +- .../lab1/lab34/controller/ProfileDto.java | 7 ++ .../mvc_controllers/FeedMvcController.java | 9 +++ .../mvc_controllers/ProfileMvcController.java | 3 + .../mvc_controllers/UserSignupDto.java | 40 ++++++++++ .../UserSignupMvcController.java | 49 ++++++++++++ .../webproglabs/lab1/lab34/model/Profile.java | 27 +++++++ .../lab1/lab34/model/UserRole.java | 20 +++++ .../lab34/repository/ProfileRepository.java | 1 + .../lab1/lab34/services/ProfileService.java | 63 ++++++++++++++-- src/main/resources/application.properties | 2 + src/main/resources/templates/default.html | 11 ++- src/main/resources/templates/feed.html | 26 +++---- src/main/resources/templates/login.html | 30 ++++++++ src/main/resources/templates/signup.html | 28 +++++++ 19 files changed, 383 insertions(+), 23 deletions(-) create mode 100644 src/main/java/com/webproglabs/lab1/PasswordEncoderConfiguration.java create mode 100644 src/main/java/com/webproglabs/lab1/SecurityConfiguration.java create mode 100644 src/main/java/com/webproglabs/lab1/lab34/controller/mvc_controllers/UserSignupDto.java create mode 100644 src/main/java/com/webproglabs/lab1/lab34/controller/mvc_controllers/UserSignupMvcController.java create mode 100644 src/main/java/com/webproglabs/lab1/lab34/model/UserRole.java create mode 100644 src/main/resources/templates/login.html create mode 100644 src/main/resources/templates/signup.html diff --git a/build.gradle b/build.gradle index 53e4666..a2e618d 100644 --- a/build.gradle +++ b/build.gradle @@ -31,6 +31,9 @@ dependencies { testImplementation 'org.springframework.boot:spring-boot-starter-test' + implementation 'org.springframework.boot:spring-boot-starter-security' + implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5' + } tasks.named('test') { diff --git a/data.mv.db b/data.mv.db index 04dc635f130b82310d83b61c8b830e8d5262e248..de4ff61e1f970ee1829930bb9f9727503d9b8ce7 100644 GIT binary patch literal 151552 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 diff --git a/src/main/java/com/webproglabs/lab1/PasswordEncoderConfiguration.java b/src/main/java/com/webproglabs/lab1/PasswordEncoderConfiguration.java new file mode 100644 index 0000000..8c560b3 --- /dev/null +++ b/src/main/java/com/webproglabs/lab1/PasswordEncoderConfiguration.java @@ -0,0 +1,14 @@ +package com.webproglabs.lab1; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +public class PasswordEncoderConfiguration { + @Bean + public PasswordEncoder createPasswordEncoder() { + return new BCryptPasswordEncoder(); + } +} diff --git a/src/main/java/com/webproglabs/lab1/SecurityConfiguration.java b/src/main/java/com/webproglabs/lab1/SecurityConfiguration.java new file mode 100644 index 0000000..0d0b1cf --- /dev/null +++ b/src/main/java/com/webproglabs/lab1/SecurityConfiguration.java @@ -0,0 +1,71 @@ +package com.webproglabs.lab1; + +import com.webproglabs.lab1.lab34.controller.mvc_controllers.UserSignupMvcController; +import com.webproglabs.lab1.lab34.model.UserRole; +import com.webproglabs.lab1.lab34.services.ProfileService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(securedEnabled = true) +public class SecurityConfiguration extends WebSecurityConfigurerAdapter { + private final Logger log = LoggerFactory.getLogger(SecurityConfiguration.class); + private static final String LOGIN_URL = "/login"; + private final ProfileService userService; + + public SecurityConfiguration(ProfileService userService) { + this.userService = userService; + createAdminOnStartup(); + } + + private void createAdminOnStartup() { + final String admin = "admin"; + if (userService.findByLogin(admin) == null) { + log.info("Admin user successfully created"); + try { + userService.createUser(admin, admin, admin, UserRole.ADMIN); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.headers().frameOptions().sameOrigin().and() + .cors().and() + .csrf().disable() + .authorizeRequests() + .antMatchers(UserSignupMvcController.SIGNUP_URL).permitAll() + .antMatchers(HttpMethod.GET, LOGIN_URL).permitAll() + .anyRequest().authenticated() + .and() + .formLogin() + .loginPage(LOGIN_URL).permitAll() + .and() + .logout().permitAll(); + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(userService); + } + + @Override + public void configure(WebSecurity web) { + web.ignoring() + .antMatchers("/css/**") + .antMatchers("/js/**") + .antMatchers("/templates/**") + .antMatchers("/webjars/**"); + } +} \ No newline at end of file diff --git a/src/main/java/com/webproglabs/lab1/WebConfiguration.java b/src/main/java/com/webproglabs/lab1/WebConfiguration.java index 0a5a2a5..ef50db9 100644 --- a/src/main/java/com/webproglabs/lab1/WebConfiguration.java +++ b/src/main/java/com/webproglabs/lab1/WebConfiguration.java @@ -11,7 +11,7 @@ public class WebConfiguration implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { WebMvcConfigurer.super.addViewControllers(registry); - registry.addViewController("rest-test"); + registry.addViewController("login"); } @Override public void addCorsMappings(CorsRegistry registry) { diff --git a/src/main/java/com/webproglabs/lab1/lab34/controller/ProfileDto.java b/src/main/java/com/webproglabs/lab1/lab34/controller/ProfileDto.java index 8b97a48..41f4aa3 100644 --- a/src/main/java/com/webproglabs/lab1/lab34/controller/ProfileDto.java +++ b/src/main/java/com/webproglabs/lab1/lab34/controller/ProfileDto.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.webproglabs.lab1.lab34.model.Comment; import com.webproglabs.lab1.lab34.model.Post; import com.webproglabs.lab1.lab34.model.Profile; +import com.webproglabs.lab1.lab34.model.UserRole; import java.util.ArrayList; import java.util.List; @@ -16,12 +17,15 @@ public class ProfileDto { private List posts = new ArrayList<>(); + private UserRole role; + public ProfileDto(){} public ProfileDto(Profile profile){ this.id = profile.getId(); this.login = profile.getLogin(); this.password = profile.getPassword(); + this.role = profile.getRole(); for(Comment comment: profile.getComments()){ comments.add(new CommentDto(comment)); } @@ -37,6 +41,9 @@ public class ProfileDto { public String getLogin() {return login;} public void setLogin(String login) {this.login = login;} public String getPassword() {return password;} + + public UserRole getRole() {return role;} + public void setPassword(String password) {this.password = password;} public List getComments() {return comments;} public List getPosts() {return posts;} diff --git a/src/main/java/com/webproglabs/lab1/lab34/controller/mvc_controllers/FeedMvcController.java b/src/main/java/com/webproglabs/lab1/lab34/controller/mvc_controllers/FeedMvcController.java index a173e4c..3985e0d 100644 --- a/src/main/java/com/webproglabs/lab1/lab34/controller/mvc_controllers/FeedMvcController.java +++ b/src/main/java/com/webproglabs/lab1/lab34/controller/mvc_controllers/FeedMvcController.java @@ -3,9 +3,12 @@ package com.webproglabs.lab1.lab34.controller.mvc_controllers; import com.webproglabs.lab1.lab34.controller.CommentDto; import com.webproglabs.lab1.lab34.controller.PostDto; import com.webproglabs.lab1.lab34.controller.ProfileDto; +import com.webproglabs.lab1.lab34.model.Profile; import com.webproglabs.lab1.lab34.services.CommentService; import com.webproglabs.lab1.lab34.services.PostService; import com.webproglabs.lab1.lab34.services.ProfileService; +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.*; @@ -26,6 +29,12 @@ public class FeedMvcController { @GetMapping public String getFeedPage(Model model) { + UserDetails principal = (UserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + var user = profileService.findByLogin(principal.getUsername()); + if (user != null) { + return "redirect:/feed/" + user.getId().toString(); + } + model.addAttribute("profiles", profileService.findAllUsers().stream().map(ProfileDto::new).toList()); return "feed"; } diff --git a/src/main/java/com/webproglabs/lab1/lab34/controller/mvc_controllers/ProfileMvcController.java b/src/main/java/com/webproglabs/lab1/lab34/controller/mvc_controllers/ProfileMvcController.java index 0621cff..a59470f 100644 --- a/src/main/java/com/webproglabs/lab1/lab34/controller/mvc_controllers/ProfileMvcController.java +++ b/src/main/java/com/webproglabs/lab1/lab34/controller/mvc_controllers/ProfileMvcController.java @@ -1,7 +1,9 @@ package com.webproglabs.lab1.lab34.controller.mvc_controllers; import com.webproglabs.lab1.lab34.controller.ProfileDto; +import com.webproglabs.lab1.lab34.model.UserRole; import com.webproglabs.lab1.lab34.services.ProfileService; +import org.springframework.security.access.annotation.Secured; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; @@ -23,6 +25,7 @@ public class ProfileMvcController { } @GetMapping(value={"profiles"}) + @Secured({UserRole.AsString.ADMIN}) public String getProfiles(Model model) { model.addAttribute("profiles", profileService.findAllUsers().stream().map(ProfileDto::new).toList()); model.addAttribute("profileDto", new ProfileDto()); diff --git a/src/main/java/com/webproglabs/lab1/lab34/controller/mvc_controllers/UserSignupDto.java b/src/main/java/com/webproglabs/lab1/lab34/controller/mvc_controllers/UserSignupDto.java new file mode 100644 index 0000000..447b057 --- /dev/null +++ b/src/main/java/com/webproglabs/lab1/lab34/controller/mvc_controllers/UserSignupDto.java @@ -0,0 +1,40 @@ +package com.webproglabs.lab1.lab34.controller.mvc_controllers; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +public class UserSignupDto { + @NotBlank + @Size(min = 3, max = 64) + private String login; + @NotBlank + @Size(min = 6, max = 64) + private String password; + @NotBlank + @Size(min = 6, max = 64) + private String passwordConfirm; + + public String getLogin() { + return login; + } + + public void setLogin(String login) { + this.login = login; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getPasswordConfirm() { + return passwordConfirm; + } + + public void setPasswordConfirm(String passwordConfirm) { + this.passwordConfirm = passwordConfirm; + } +} diff --git a/src/main/java/com/webproglabs/lab1/lab34/controller/mvc_controllers/UserSignupMvcController.java b/src/main/java/com/webproglabs/lab1/lab34/controller/mvc_controllers/UserSignupMvcController.java new file mode 100644 index 0000000..6f4f399 --- /dev/null +++ b/src/main/java/com/webproglabs/lab1/lab34/controller/mvc_controllers/UserSignupMvcController.java @@ -0,0 +1,49 @@ +package com.webproglabs.lab1.lab34.controller.mvc_controllers; + +import com.webproglabs.lab1.lab34.model.Profile; +import com.webproglabs.lab1.lab34.services.ProfileService; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +import javax.validation.Valid; + +@Controller +@RequestMapping(UserSignupMvcController.SIGNUP_URL) +public class UserSignupMvcController { + public static final String SIGNUP_URL = "/signup"; + + private final ProfileService userService; + + public UserSignupMvcController(ProfileService userService) { + this.userService = userService; + } + + @GetMapping + public String showSignupForm(Model model) { + model.addAttribute("userDto", new UserSignupDto()); + return "signup"; + } + + @PostMapping + public String signup(@ModelAttribute("userDto") @Valid UserSignupDto userSignupDto, + BindingResult bindingResult, + Model model) { + if (bindingResult.hasErrors()) { + model.addAttribute("errors", bindingResult.getAllErrors()); + return "signup"; + } + try { + final Profile user = userService.createUser( + userSignupDto.getLogin(), userSignupDto.getPassword(), userSignupDto.getPasswordConfirm()); + return "redirect:/login?created=" + user.getLogin(); + } catch (Exception e) { + model.addAttribute("errors", e.getMessage()); + return "signup"; + } + } +} diff --git a/src/main/java/com/webproglabs/lab1/lab34/model/Profile.java b/src/main/java/com/webproglabs/lab1/lab34/model/Profile.java index 79702d6..be15025 100644 --- a/src/main/java/com/webproglabs/lab1/lab34/model/Profile.java +++ b/src/main/java/com/webproglabs/lab1/lab34/model/Profile.java @@ -1,6 +1,8 @@ package com.webproglabs.lab1.lab34.model; import javax.persistence.*; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -12,9 +14,22 @@ public class Profile { @GeneratedValue(strategy = GenerationType.AUTO) private Long id; + @Column(nullable = false, unique = true, length = 64) + @NotBlank + @Size(min = 3, max = 64) private String login; + + @Column(nullable = false, length = 64) + @NotBlank + @Size(min = 6, max = 64) private String password; + private UserRole role; + + public UserRole getRole() { + return role; + } + @OneToMany(mappedBy = "owner", orphanRemoval = true, fetch = FetchType.EAGER) private List comments = new ArrayList(); @@ -25,6 +40,18 @@ public class Profile { public Profile(String login, String password, List comments, List posts) { this.login = login; this.password=password; + this.role = UserRole.USER; + for (int i = 0; i < comments.size(); i++) { + addComment(comments.get(i)); + } + for (int i = 0; i < posts.size(); i++) { + addPost(posts.get(i)); + } + }; + public Profile(String login, String password, List comments, List posts, UserRole role) { + this.login = login; + this.password=password; + this.role = role; for (int i = 0; i < comments.size(); i++) { addComment(comments.get(i)); } diff --git a/src/main/java/com/webproglabs/lab1/lab34/model/UserRole.java b/src/main/java/com/webproglabs/lab1/lab34/model/UserRole.java new file mode 100644 index 0000000..03102cc --- /dev/null +++ b/src/main/java/com/webproglabs/lab1/lab34/model/UserRole.java @@ -0,0 +1,20 @@ +package com.webproglabs.lab1.lab34.model; + +import org.springframework.security.core.GrantedAuthority; + +public enum UserRole implements GrantedAuthority { + ADMIN, + USER; + + private static final String PREFIX = "ROLE_"; + + @Override + public String getAuthority() { + return PREFIX + this.name(); + } + + public static final class AsString { + public static final String ADMIN = PREFIX + "ADMIN"; + public static final String USER = PREFIX + "USER"; + } +} diff --git a/src/main/java/com/webproglabs/lab1/lab34/repository/ProfileRepository.java b/src/main/java/com/webproglabs/lab1/lab34/repository/ProfileRepository.java index 1497572..0f0be17 100644 --- a/src/main/java/com/webproglabs/lab1/lab34/repository/ProfileRepository.java +++ b/src/main/java/com/webproglabs/lab1/lab34/repository/ProfileRepository.java @@ -8,4 +8,5 @@ import java.util.List; public interface ProfileRepository extends JpaRepository { List findByLoginLike(String login); + Profile findOneByLoginIgnoreCase(String login); } diff --git a/src/main/java/com/webproglabs/lab1/lab34/services/ProfileService.java b/src/main/java/com/webproglabs/lab1/lab34/services/ProfileService.java index 1be9ffe..7a5febd 100644 --- a/src/main/java/com/webproglabs/lab1/lab34/services/ProfileService.java +++ b/src/main/java/com/webproglabs/lab1/lab34/services/ProfileService.java @@ -3,23 +3,28 @@ package com.webproglabs.lab1.lab34.services; import com.webproglabs.lab1.lab34.model.Comment; import com.webproglabs.lab1.lab34.model.Post; import com.webproglabs.lab1.lab34.model.Profile; -import com.webproglabs.lab1.lab34.repository.CommentRepository; +import com.webproglabs.lab1.lab34.model.UserRole; import com.webproglabs.lab1.lab34.repository.ProfileRepository; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import javax.persistence.EntityNotFoundException; import javax.transaction.Transactional; -import java.util.List; -import java.util.Optional; +import java.util.*; @Service -public class ProfileService { +public class ProfileService implements UserDetailsService { private final ProfileRepository profileRepository; + private final PasswordEncoder passwordEncoder; - public ProfileService(ProfileRepository profileRepository) { + public ProfileService(ProfileRepository profileRepository, PasswordEncoder passwordEncoder) { this.profileRepository = profileRepository; + this.passwordEncoder = passwordEncoder; } @Transactional @@ -44,7 +49,40 @@ public class ProfileService { if (!StringUtils.hasText(login) || !StringUtils.hasText(password)) { throw new IllegalArgumentException("User data is null or empty"); } - final Profile user = new Profile(login, password, comments, posts); + final Profile user = new Profile(login, password, comments, posts, UserRole.USER); + return profileRepository.save(user); + } + + @Transactional + public Profile addUser(String login, String password, List comments, List posts, UserRole role) { + if (!StringUtils.hasText(login) || !StringUtils.hasText(password)) { + throw new IllegalArgumentException("User data is null or empty"); + } + final Profile user = new Profile(login, password, comments, posts, role); + return profileRepository.save(user); + } + + @Transactional + public Profile createUser(String login, String password, String passwordConfirm) throws Exception { + if (findByLogin(login) != null) { + throw new Exception("User " + login + " already exists"); + } + final Profile user = new Profile(login, passwordEncoder.encode(password), new ArrayList<>(), new ArrayList<>(), UserRole.USER); + if (!Objects.equals(password, passwordConfirm)) { + throw new Exception("Passwords not equals"); + } + return profileRepository.save(user); + } + + @Transactional + public Profile createUser(String login, String password, String passwordConfirm, UserRole role) throws Exception { + if (findByLogin(login) != null) { + throw new Exception("User " + login + " already exists"); + } + final Profile user = new Profile(login, passwordEncoder.encode(password), new ArrayList<>(), new ArrayList<>(), role); + if (!Objects.equals(password, passwordConfirm)) { + throw new Exception("Passwords not equals"); + } return profileRepository.save(user); } @@ -70,4 +108,17 @@ public class ProfileService { public void deleteAllUsers() { profileRepository.deleteAll(); } + + public Profile findByLogin(String login) { + return profileRepository.findOneByLoginIgnoreCase(login); + } + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + final Profile userEntity = findByLogin(username); + if (userEntity == null) { + throw new UsernameNotFoundException(username); + } + return new org.springframework.security.core.userdetails.User( + userEntity.getLogin(), userEntity.getPassword(), Collections.singleton(userEntity.getRole())); + } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index da7b0b1..8bb0d85 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -9,3 +9,5 @@ spring.jpa.hibernate.ddl-auto=update spring.h2.console.enabled=true spring.h2.console.settings.trace=false spring.h2.console.settings.web-allow-others=false +# Security +spring.security.user.password=user diff --git a/src/main/resources/templates/default.html b/src/main/resources/templates/default.html index 706ec28..119f8f7 100644 --- a/src/main/resources/templates/default.html +++ b/src/main/resources/templates/default.html @@ -1,7 +1,9 @@ + xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" + xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5"> +> Лабораторная работа 5 @@ -21,8 +23,11 @@ diff --git a/src/main/resources/templates/feed.html b/src/main/resources/templates/feed.html index 13aee47..3bb2e58 100644 --- a/src/main/resources/templates/feed.html +++ b/src/main/resources/templates/feed.html @@ -8,19 +8,19 @@
- + + + + + + + + + + + + +
diff --git a/src/main/resources/templates/login.html b/src/main/resources/templates/login.html new file mode 100644 index 0000000..5c9f583 --- /dev/null +++ b/src/main/resources/templates/login.html @@ -0,0 +1,30 @@ + + + +
+
+ Пользователь не найден или пароль указан не верно +
+
+ Выход успешно произведен +
+
+ Пользователь '' успешно создан +
+
+
+ +
+
+ +
+ + Регистрация +
+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/signup.html b/src/main/resources/templates/signup.html new file mode 100644 index 0000000..8cd75f5 --- /dev/null +++ b/src/main/resources/templates/signup.html @@ -0,0 +1,28 @@ + + + +
+
+
+
+ +
+
+ +
+
+ +
+
+ + Назад +
+
+
+ + \ No newline at end of file