From 5e2eab6f32bc76918aa17791b688d1df27d6ddfc Mon Sep 17 00:00:00 2001 From: realtradam Date: Sat, 20 Jul 2024 00:51:37 -0400 Subject: code cleanup --- pom.xml | 217 ++++++++++----------- src/main/java/com/blog/web/WebApplication.java | 8 +- .../blog/web/controllers/ArticleController.java | 55 ++---- .../com/blog/web/controllers/AuthController.java | 26 +-- src/main/java/com/blog/web/dto/ArticleDto.java | 17 +- .../java/com/blog/web/dto/RegistrationDto.java | 20 +- .../java/com/blog/web/mappers/ArticleMapper.java | 3 + src/main/java/com/blog/web/models/Article.java | 13 +- src/main/java/com/blog/web/models/UserEntity.java | 21 +- .../com/blog/web/repository/RoleRepository.java | 4 +- .../com/blog/web/repository/UserRepository.java | 9 +- .../web/security/CustomUserDetailsService.java | 13 +- .../java/com/blog/web/security/SecurityConfig.java | 19 +- .../java/com/blog/web/services/ArticleService.java | 6 +- .../java/com/blog/web/services/UserService.java | 8 +- .../blog/web/services/impl/ArticleServiceImpl.java | 38 +++- .../blog/web/services/impl/UserServiceImpl.java | 32 ++- .../web/repository/ArticleRepositoryTests.java | 10 +- .../com/blog/web/services/ArticleServiceTests.java | 5 +- 19 files changed, 238 insertions(+), 286 deletions(-) diff --git a/pom.xml b/pom.xml index b0177f7..db9c68f 100644 --- a/pom.xml +++ b/pom.xml @@ -1,113 +1,112 @@ - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.3.1 - - - com.blog - web - 0.0.1-SNAPSHOT - web - Demo project for Spring Boot - - - - - - - - - - - - - - - 17 - - - - org.springframework.boot - spring-boot-starter-data-jpa - - - org.springframework.boot - spring-boot-starter-thymeleaf - - - nz.net.ultraq.thymeleaf - thymeleaf-layout-dialect - - - org.springframework.boot - spring-boot-starter-web - + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.3.1 + + + com.blog + web + 0.0.1-SNAPSHOT + web + Demo project for Spring Boot + + + + + + + + + + + + + + + 17 + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + nz.net.ultraq.thymeleaf + thymeleaf-layout-dialect + + + org.springframework.boot + spring-boot-starter-web + - - org.springframework.boot - spring-boot-devtools - runtime - true - - - org.postgresql - postgresql - runtime - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.boot - spring-boot-starter-validation - - - org.springframework.boot - spring-boot-starter-security - - - org.thymeleaf.extras - thymeleaf-extras-springsecurity6 - - - org.apache.commons - commons-lang3 - - - com.h2database - h2 - 2.3.230 - test - - - junit - junit - test - - - org.springframework.security - spring-security-test - test - - + + org.springframework.boot + spring-boot-devtools + runtime + true + + + org.postgresql + postgresql + runtime + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-security + + + org.thymeleaf.extras + thymeleaf-extras-springsecurity6 + + + org.apache.commons + commons-lang3 + + + com.h2database + h2 + 2.3.230 + test + + + junit + junit + test + + + org.springframework.security + spring-security-test + test + + - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - - - - - + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/blog/web/WebApplication.java b/src/main/java/com/blog/web/WebApplication.java index 0368f26..f5dd2ef 100644 --- a/src/main/java/com/blog/web/WebApplication.java +++ b/src/main/java/com/blog/web/WebApplication.java @@ -5,7 +5,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class WebApplication { - public static void main(String[] args) { - SpringApplication.run(WebApplication.class, args); - } -} \ No newline at end of file + public static void main(String[] args) { + SpringApplication.run(WebApplication.class, args); + } +} diff --git a/src/main/java/com/blog/web/controllers/ArticleController.java b/src/main/java/com/blog/web/controllers/ArticleController.java index e60be61..b0bbb0b 100644 --- a/src/main/java/com/blog/web/controllers/ArticleController.java +++ b/src/main/java/com/blog/web/controllers/ArticleController.java @@ -3,7 +3,6 @@ package com.blog.web.controllers; import com.blog.web.dto.ArticleDto; import com.blog.web.models.Article; import com.blog.web.models.UserEntity; -import com.blog.web.security.SecurityUtil; import com.blog.web.services.ArticleService; import com.blog.web.services.UserService; import jakarta.validation.Valid; @@ -27,7 +26,7 @@ public class ArticleController { @GetMapping("/articles") public String listArticles(Model model) { List articles = articleService.findAllArticles(); - UserEntity user = userService.getLoggedInUser(); + UserEntity user = userService.getLoggedInUser().orElse(new UserEntity()); model.addAttribute("user", user); model.addAttribute("articles", articles); return "index"; @@ -37,67 +36,54 @@ public class ArticleController { public String showArticle(@PathVariable("articleId") long articleId, Model model) { ArticleDto articleDto = articleService.findArticleById(articleId); model.addAttribute("article", articleDto); - UserEntity user = userService.getLoggedInUser(); + UserEntity user = userService.getLoggedInUser().orElse(new UserEntity()); model.addAttribute("user", user); return "articles/show"; } @GetMapping("/articles/new") public String createArticleForm(Model model) { - UserEntity user = userService.getLoggedInUser(); - model.addAttribute("user", user); - final Article article = new Article(); - model.addAttribute("article", article); + model.addAttribute("user", userService.getLoggedInUser().orElse(new UserEntity())); + model.addAttribute("article", new Article()); return "articles/new"; } @PostMapping("/articles/new") - public String saveArticle(@Valid @ModelAttribute("article") ArticleDto articleDto, - BindingResult result, - Model model) - { - // if un-logged in user tries to create an article + public String saveArticle(@Valid @ModelAttribute("article") ArticleDto articleDto, BindingResult result, Model model) { + // if non-authenticated in user tries to create an article // redirect them to login page - UserEntity user = userService.getLoggedInUser(); - if(userService.getLoggedInUser().getId() == null) { + UserEntity user = userService.getLoggedInUser().orElse(new UserEntity()); + if (user.getId() == null) { return "redirect:/userlogin"; - } - else if(result.hasErrors()) { + } else if (result.hasErrors()) { model.addAttribute("article", articleDto); return "articles/new"; - } - else { + } else { articleService.saveArticle(articleDto); return "redirect:/articles"; } } - @GetMapping("/articles/delete/{articleId}") public String deleteArticle(@PathVariable("articleId") Long articleId) { - UserEntity user = userService.getLoggedInUser(); - ArticleDto article = articleService.findArticleById(articleId); - UserEntity owner = article.getCreatedBy(); - if(owner.equals(user)) { - articleService.delete(articleId); - } + articleService.delete(articleId); return "redirect:/articles"; } @GetMapping("/articles/edit/{articleId}") public String editArticleForm(@PathVariable("articleId") long articleId, Model model) { - UserEntity user = userService.getLoggedInUser(); - model.addAttribute("user", user); - ArticleDto articleDto = articleService.findArticleById(articleId); - model.addAttribute("article", articleDto); + UserEntity user = userService.getLoggedInUser().orElse(null); + if (user != null) { + model.addAttribute("user", user); + ArticleDto articleDto = articleService.findArticleById(articleId); + model.addAttribute("article", articleDto); + } return "articles/edit"; } @PostMapping("/articles/edit/{articleId}") - public String updateArticle(@PathVariable("articleId") Long articleId, - @Valid @ModelAttribute("article") ArticleDto article, - BindingResult result) { - if(result.hasErrors()) { + public String updateArticle(@PathVariable("articleId") Long articleId, @Valid @ModelAttribute("article") ArticleDto article, BindingResult result) { + if (result.hasErrors()) { return "articles/edit"; } article.setId(articleId); @@ -107,14 +93,13 @@ public class ArticleController { @GetMapping("/articles/search") public String searchArticle(@RequestParam(value = "search") String search, Model model) { - UserEntity user = userService.getLoggedInUser(); + UserEntity user = userService.getLoggedInUser().orElse(new UserEntity()); model.addAttribute("user", user); List articles = articleService.searchArticles(search); model.addAttribute("articles", articles); return "index"; } - @GetMapping("/") public String getArticles() { return "redirect:/articles"; diff --git a/src/main/java/com/blog/web/controllers/AuthController.java b/src/main/java/com/blog/web/controllers/AuthController.java index a654ad1..efb3672 100644 --- a/src/main/java/com/blog/web/controllers/AuthController.java +++ b/src/main/java/com/blog/web/controllers/AuthController.java @@ -2,7 +2,6 @@ package com.blog.web.controllers; import com.blog.web.dto.RegistrationDto; import com.blog.web.models.UserEntity; -import com.blog.web.security.SecurityUtil; import com.blog.web.services.UserService; import jakarta.validation.Valid; import org.apache.commons.lang3.StringUtils; @@ -15,7 +14,7 @@ import org.springframework.web.bind.annotation.PostMapping; @Controller public class AuthController { - private UserService userService; + private final UserService userService; public AuthController(UserService userService) { this.userService = userService; @@ -23,7 +22,7 @@ public class AuthController { @GetMapping("/userlogin") public String login(Model model) { - UserEntity user = userService.getLoggedInUser(); + final UserEntity user = userService.getLoggedInUser().orElse(new UserEntity()); model.addAttribute("user", user); return "auth/login"; } @@ -36,27 +35,18 @@ public class AuthController { } @PostMapping("/register/save") - public String register(@Valid @ModelAttribute("user")RegistrationDto user, - BindingResult result, - Model model) { - UserEntity existingUserEmail = userService.findByEmail(user.getEmail()); - if( - existingUserEmail != null && - StringUtils.isBlank(existingUserEmail.getEmail()) - ) { + public String register(@Valid @ModelAttribute("user") RegistrationDto user, BindingResult result, Model model) { + UserEntity existingUserEmail = userService.findByEmail(user.getEmail()).orElse(null); + if (existingUserEmail != null && StringUtils.isBlank(existingUserEmail.getEmail())) { result.rejectValue("email", "There is already a user with this email"); } - UserEntity existingUsername = userService.findByUsername(user.getUsername()); - if( - existingUsername != null && - StringUtils.isBlank(existingUsername.getUsername()) - ) - { + UserEntity existingUsername = userService.findByUsername(user.getUsername()).orElse(null); + if (existingUsername != null && StringUtils.isBlank(existingUsername.getUsername())) { result.rejectValue("username", "There is already a user with this username"); } - if(result.hasErrors()) { + if (result.hasErrors()) { model.addAttribute("user", user); return "register"; } diff --git a/src/main/java/com/blog/web/dto/ArticleDto.java b/src/main/java/com/blog/web/dto/ArticleDto.java index 372b318..d275f3b 100644 --- a/src/main/java/com/blog/web/dto/ArticleDto.java +++ b/src/main/java/com/blog/web/dto/ArticleDto.java @@ -29,15 +29,7 @@ public class ArticleDto { @JoinColumn(name = "created_by", nullable = false) private UserEntity createdBy; - public ArticleDto( - long id, - String title, - String photoUrl, - String content, - UserEntity createdBy, - LocalDateTime createdOn, - LocalDateTime updatedOn - ) { + public ArticleDto(long id, String title, String photoUrl, String content, UserEntity createdBy, LocalDateTime createdOn, LocalDateTime updatedOn) { this.id = id; this.title = title; this.photoUrl = photoUrl; @@ -47,7 +39,10 @@ public class ArticleDto { this.updatedOn = updatedOn; } - public ArticleDto() {}; + public ArticleDto() { + } + + ; public ArticleDto(Article article) { this.id = article.getId(); @@ -114,4 +109,6 @@ public class ArticleDto { public void setCreatedBy(UserEntity createdBy) { this.createdBy = createdBy; } + + public String getUsername() { return createdBy.getUsername(); } } diff --git a/src/main/java/com/blog/web/dto/RegistrationDto.java b/src/main/java/com/blog/web/dto/RegistrationDto.java index fcf5f90..5b86557 100644 --- a/src/main/java/com/blog/web/dto/RegistrationDto.java +++ b/src/main/java/com/blog/web/dto/RegistrationDto.java @@ -1,7 +1,5 @@ package com.blog.web.dto; -import com.blog.web.models.UserEntity; -import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotEmpty; public class RegistrationDto { @@ -10,16 +8,14 @@ public class RegistrationDto { private String username; @NotEmpty private String email; + @NotEmpty private String password; - public RegistrationDto() {}; + public RegistrationDto() { + } - public RegistrationDto( - String username, - String email, - String password - ) { + public RegistrationDto(String username, String email, String password) { this.username = username; this.email = email; this.password = password; @@ -49,11 +45,11 @@ public class RegistrationDto { this.email = email; } - public @NotEmpty String getPassword() { - return password; - } - public void setPassword(@NotEmpty String password) { this.password = password; } + + public @NotEmpty String getPassword() { + return password; + } } diff --git a/src/main/java/com/blog/web/mappers/ArticleMapper.java b/src/main/java/com/blog/web/mappers/ArticleMapper.java index 680f67e..4010052 100644 --- a/src/main/java/com/blog/web/mappers/ArticleMapper.java +++ b/src/main/java/com/blog/web/mappers/ArticleMapper.java @@ -4,6 +4,9 @@ import com.blog.web.dto.ArticleDto; import com.blog.web.models.Article; public class ArticleMapper { + private ArticleMapper() { + } + public static Article mapToArticle(ArticleDto articleDto) { return new Article(articleDto); } diff --git a/src/main/java/com/blog/web/models/Article.java b/src/main/java/com/blog/web/models/Article.java index 42d27a1..ed4ac1c 100644 --- a/src/main/java/com/blog/web/models/Article.java +++ b/src/main/java/com/blog/web/models/Article.java @@ -23,15 +23,7 @@ public class Article { @JoinColumn(name = "created_by", nullable = false) private UserEntity createdBy; - public Article( - Long id, - String title, - String photoUrl, - String content, - UserEntity createdBy, - LocalDateTime createdOn, - LocalDateTime updatedOn - ) { + public Article(Long id, String title, String photoUrl, String content, UserEntity createdBy, LocalDateTime createdOn, LocalDateTime updatedOn) { this.id = id; this.title = title; this.photoUrl = photoUrl; @@ -41,7 +33,8 @@ public class Article { this.updatedOn = updatedOn; } - public Article() {}; + public Article() { + } public Article(ArticleDto articleDto) { this.id = articleDto.getId(); diff --git a/src/main/java/com/blog/web/models/UserEntity.java b/src/main/java/com/blog/web/models/UserEntity.java index d121580..c94db6b 100644 --- a/src/main/java/com/blog/web/models/UserEntity.java +++ b/src/main/java/com/blog/web/models/UserEntity.java @@ -18,25 +18,15 @@ public class UserEntity { private String email; private String password; @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL) - @JoinTable( - name = "user_roles", - joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")}, - inverseJoinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "id")} - ) - private List roles = new ArrayList<>(); + @JoinTable(name = "user_roles", joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")}, inverseJoinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "id")}) + private final List roles = new ArrayList<>(); - public boolean equals(UserEntity user) - { + public boolean equals(UserEntity user) { return this.id == user.getId(); } public User toSecurityUser() { - return new User( - this.getEmail(), - this.getPassword(), - this.getRoles().stream().map((role) -> new SimpleGrantedAuthority(role.getName())) - .collect(Collectors.toList()) - ); + return new User(this.getEmail(), this.getPassword(), this.getRoles().stream().map((role) -> new SimpleGrantedAuthority(role.getName())).collect(Collectors.toList())); } public Long getId() { @@ -76,6 +66,7 @@ public class UserEntity { } public void setRoles(List roles) { - this.roles = roles; + this.roles.clear(); + this.roles.addAll(roles); } } diff --git a/src/main/java/com/blog/web/repository/RoleRepository.java b/src/main/java/com/blog/web/repository/RoleRepository.java index 08c9ef4..f271bf1 100644 --- a/src/main/java/com/blog/web/repository/RoleRepository.java +++ b/src/main/java/com/blog/web/repository/RoleRepository.java @@ -3,6 +3,8 @@ package com.blog.web.repository; import com.blog.web.models.Role; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.Optional; + public interface RoleRepository extends JpaRepository { - Role findByName(String name); + Optional findByName(String name); } diff --git a/src/main/java/com/blog/web/repository/UserRepository.java b/src/main/java/com/blog/web/repository/UserRepository.java index c304fc0..30eefc5 100644 --- a/src/main/java/com/blog/web/repository/UserRepository.java +++ b/src/main/java/com/blog/web/repository/UserRepository.java @@ -3,9 +3,12 @@ package com.blog.web.repository; import com.blog.web.models.UserEntity; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.Optional; + public interface UserRepository extends JpaRepository { - UserEntity findByEmail(String email); - UserEntity findByUsername(String username); + Optional findByEmail(String email); + + Optional findByUsername(String username); - UserEntity findFirstByUsername(String username); + Optional findFirstByUsername(String username); } diff --git a/src/main/java/com/blog/web/security/CustomUserDetailsService.java b/src/main/java/com/blog/web/security/CustomUserDetailsService.java index f221c9e..ee3e950 100644 --- a/src/main/java/com/blog/web/security/CustomUserDetailsService.java +++ b/src/main/java/com/blog/web/security/CustomUserDetailsService.java @@ -2,8 +2,6 @@ package com.blog.web.security; import com.blog.web.models.UserEntity; import com.blog.web.repository.UserRepository; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; @@ -13,7 +11,7 @@ import java.util.stream.Collectors; @Service public class CustomUserDetailsService implements UserDetailsService { - private UserRepository userRepository; + private final UserRepository userRepository; public CustomUserDetailsService(UserRepository userRepository) { this.userRepository = userRepository; @@ -21,12 +19,11 @@ public class CustomUserDetailsService implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - UserEntity userEntity = userRepository.findFirstByUsername(username); - if(userEntity != null) { + UserEntity userEntity = userRepository.findFirstByUsername(username).orElse(new UserEntity()); + if (userEntity.getUsername() != null) { return userEntity.toSecurityUser(); - } - else { - throw new UsernameNotFoundException("Invalid username or password"); + } else { + throw new UsernameNotFoundException("Invalid username"); } } } diff --git a/src/main/java/com/blog/web/security/SecurityConfig.java b/src/main/java/com/blog/web/security/SecurityConfig.java index b459224..17e09c7 100644 --- a/src/main/java/com/blog/web/security/SecurityConfig.java +++ b/src/main/java/com/blog/web/security/SecurityConfig.java @@ -28,24 +28,7 @@ public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // disabling csrf leaves us vulnerable, in a real production app do not do this - http.csrf(c -> c.disable()) - .cors(c -> c.disable()) - .authorizeHttpRequests( auths -> auths - .anyRequest() - .permitAll() - ) - .formLogin(form -> form - .loginPage("/userlogin") - .usernameParameter("username") - .passwordParameter("password") - .defaultSuccessUrl("/articles") - .loginProcessingUrl("/userlogin") - .failureUrl("/userlogin?error=true") - .permitAll() - ).logout( - logout -> logout - .logoutUrl("/logout") - .logoutSuccessUrl("/articles")); + http.csrf(c -> c.disable()).cors(c -> c.disable()).authorizeHttpRequests(auths -> auths.anyRequest().permitAll()).formLogin(form -> form.loginPage("/userlogin").usernameParameter("username").passwordParameter("password").defaultSuccessUrl("/articles").loginProcessingUrl("/userlogin").failureUrl("/userlogin?error=true").permitAll()).logout(logout -> logout.logoutUrl("/logout").logoutSuccessUrl("/articles")); return http.build(); } diff --git a/src/main/java/com/blog/web/services/ArticleService.java b/src/main/java/com/blog/web/services/ArticleService.java index aeedcb4..f0fb05b 100644 --- a/src/main/java/com/blog/web/services/ArticleService.java +++ b/src/main/java/com/blog/web/services/ArticleService.java @@ -2,18 +2,20 @@ package com.blog.web.services; import com.blog.web.dto.ArticleDto; import com.blog.web.models.Article; + import java.util.List; +import java.util.Optional; public interface ArticleService { List findAllArticles(); - Article saveArticle(ArticleDto article); + Optional
saveArticle(ArticleDto article); ArticleDto findArticleById(long articleId); void updateArticle(ArticleDto articleDto); - void delete(Long articleId); + boolean delete(Long articleId); List searchArticles(String search); } diff --git a/src/main/java/com/blog/web/services/UserService.java b/src/main/java/com/blog/web/services/UserService.java index 270c2ef..b9c231b 100644 --- a/src/main/java/com/blog/web/services/UserService.java +++ b/src/main/java/com/blog/web/services/UserService.java @@ -3,12 +3,14 @@ package com.blog.web.services; import com.blog.web.dto.RegistrationDto; import com.blog.web.models.UserEntity; +import java.util.Optional; + public interface UserService { void saveUser(RegistrationDto registrationDto); - UserEntity findByEmail(String email); + Optional findByEmail(String email); - UserEntity findByUsername(String username); + Optional findByUsername(String username); - public UserEntity getLoggedInUser(); + public Optional getLoggedInUser(); } diff --git a/src/main/java/com/blog/web/services/impl/ArticleServiceImpl.java b/src/main/java/com/blog/web/services/impl/ArticleServiceImpl.java index acca7e5..fb55c54 100644 --- a/src/main/java/com/blog/web/services/impl/ArticleServiceImpl.java +++ b/src/main/java/com/blog/web/services/impl/ArticleServiceImpl.java @@ -7,12 +7,15 @@ import com.blog.web.repository.ArticleRepository; import com.blog.web.repository.UserRepository; import com.blog.web.security.SecurityUtil; import com.blog.web.services.ArticleService; +import com.blog.web.services.UserService; import org.springframework.stereotype.Service; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import com.blog.web.mappers.ArticleMapper; + import static com.blog.web.mappers.ArticleMapper.mapToArticle; import static com.blog.web.mappers.ArticleMapper.mapToArticleDto; @@ -20,27 +23,31 @@ import static com.blog.web.mappers.ArticleMapper.mapToArticleDto; public class ArticleServiceImpl implements ArticleService { final private ArticleRepository articleRepository; final private UserRepository userRepository; + final private UserService userService; - public ArticleServiceImpl(ArticleRepository articleRepository, UserRepository userRepository) { + public ArticleServiceImpl(ArticleRepository articleRepository, UserRepository userRepository, UserService userService) { this.userRepository = userRepository; this.articleRepository = articleRepository; + this.userService = userService; } @Override public List findAllArticles() { List
articles = articleRepository.findAll(); - //return articles.stream().map((article) -> mapToArticleDto(article)).collect(Collectors.toList()); return articles.stream().map(ArticleMapper::mapToArticleDto).collect(Collectors.toList()); } @Override - public Article saveArticle(ArticleDto articleDto) { + public Optional
saveArticle(ArticleDto articleDto) { String username = SecurityUtil.getSessionUser(); - UserEntity user = userRepository.findByUsername(username); + UserEntity user = userRepository.findByUsername(username).orElse(null); + if (user == null) { + return null; + } Article article = mapToArticle(articleDto); article.setCreatedBy(user); - return articleRepository.save(article); + return Optional.of(articleRepository.save(article)); } @Override @@ -52,15 +59,30 @@ public class ArticleServiceImpl implements ArticleService { @Override public void updateArticle(ArticleDto articleDto) { String username = SecurityUtil.getSessionUser(); - UserEntity user = userRepository.findByUsername(username); + UserEntity user = userRepository.findByUsername(username).orElse(null); + if (user == null) { + return; + } Article article = mapToArticle(articleDto); article.setCreatedBy(user); articleRepository.save(article); } @Override - public void delete(Long articleId) { - articleRepository.deleteById(articleId); + public boolean delete(Long articleId) { + final UserEntity user = userService.getLoggedInUser().orElse(null); + if (user == null) { + return false; + } + String userId = user.getUsername(); + ArticleDto article = this.findArticleById(articleId); + String ownerId = article.getUsername(); + if (ownerId.equals(userId)) { + articleRepository.deleteById(articleId); + return true; + } else { + return false; + } } @Override diff --git a/src/main/java/com/blog/web/services/impl/UserServiceImpl.java b/src/main/java/com/blog/web/services/impl/UserServiceImpl.java index f77eb9e..859e72c 100644 --- a/src/main/java/com/blog/web/services/impl/UserServiceImpl.java +++ b/src/main/java/com/blog/web/services/impl/UserServiceImpl.java @@ -11,17 +11,15 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import java.util.Arrays; +import java.util.Optional; @Service public class UserServiceImpl implements UserService { - final private UserRepository userRepository; - final private RoleRepository roleRepository; - final private PasswordEncoder passwordEncoder; + private final UserRepository userRepository; + private final RoleRepository roleRepository; + private final PasswordEncoder passwordEncoder; - public UserServiceImpl( - UserRepository userRepository, - RoleRepository roleRepository, - PasswordEncoder passwordEncoder) { + public UserServiceImpl(UserRepository userRepository, RoleRepository roleRepository, PasswordEncoder passwordEncoder) { this.userRepository = userRepository; this.roleRepository = roleRepository; this.passwordEncoder = passwordEncoder; @@ -32,34 +30,30 @@ public class UserServiceImpl implements UserService { UserEntity user = new UserEntity(); user.setUsername(registrationDto.getUsername()); user.setEmail(registrationDto.getEmail()); - // this is an unsafe way to store passwords in production - // it is left this way only because this is a practice project - //user.setPassword(registrationDto.getPassword()); user.setPassword(passwordEncoder.encode(registrationDto.getPassword())); - final Role role = roleRepository.findByName("User"); + final Role role = roleRepository.findByName("User").orElse(new Role()); user.setRoles(Arrays.asList(role)); userRepository.save(user); } @Override - public UserEntity findByEmail(String email) { + public Optional findByEmail(String email) { return userRepository.findByEmail(email); } @Override - public UserEntity findByUsername(String username) { + public Optional findByUsername(String username) { return userRepository.findByUsername(username); } - public UserEntity getLoggedInUser() { - final UserEntity user; + public Optional getLoggedInUser() { + final Optional user; String username = SecurityUtil.getSessionUser(); - if(username != null) { + if (username != null) { user = this.findByUsername(username); - } - else { - user = new UserEntity(); + } else { + user = Optional.of(new UserEntity()); } return user; } diff --git a/src/test/java/com/blog/web/repository/ArticleRepositoryTests.java b/src/test/java/com/blog/web/repository/ArticleRepositoryTests.java index 31764e3..96c5f5b 100644 --- a/src/test/java/com/blog/web/repository/ArticleRepositoryTests.java +++ b/src/test/java/com/blog/web/repository/ArticleRepositoryTests.java @@ -7,21 +7,13 @@ import com.blog.web.models.Article; import com.blog.web.models.UserEntity; import com.blog.web.services.ArticleService; import com.blog.web.services.UserService; -import org.junit.Assert; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.jdbc.EmbeddedDatabaseConnection; import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Lazy; import org.springframework.security.test.context.support.WithMockUser; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; -import org.springframework.test.context.junit4.SpringRunner; import java.time.LocalDateTime; import java.util.List; @@ -48,7 +40,7 @@ public class ArticleRepositoryTests { "blah" ); userService.saveUser(userDto); - UserEntity user = userService.findByUsername("test"); + UserEntity user = userService.findByUsername("test").orElseThrow(); final ArticleDto articleDto1 = new ArticleDto( 1, "Title", diff --git a/src/test/java/com/blog/web/services/ArticleServiceTests.java b/src/test/java/com/blog/web/services/ArticleServiceTests.java index 00e7bbd..d55516a 100644 --- a/src/test/java/com/blog/web/services/ArticleServiceTests.java +++ b/src/test/java/com/blog/web/services/ArticleServiceTests.java @@ -21,6 +21,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.security.test.context.support.WithMockUser; import java.time.LocalDateTime; +import java.util.Optional; import static org.mockito.AdditionalAnswers.returnsFirstArg; import static org.mockito.ArgumentMatchers.any; @@ -63,13 +64,13 @@ public class ArticleServiceTests { LocalDateTime.now() ); - when(userRepository.findByUsername(anyString())).thenReturn(user); + when(userRepository.findByUsername(anyString())).thenReturn(Optional.of(user)); when(articleRepository.save(any(Article.class))).then(returnsFirstArg()); //when(SecurityUtil.getSessionUser()).thenReturn(user.getUsername()); try(MockedStatic utilities = Mockito.mockStatic(SecurityUtil.class)) { utilities.when(SecurityUtil::getSessionUser).thenReturn(user.getUsername()); Assertions.assertEquals(user.getUsername(), SecurityUtil.getSessionUser()); - Article article = articleService.saveArticle(articleDto); + Article article = articleService.saveArticle(articleDto).orElse(null); Assertions.assertNotNull(article); } -- cgit v1.2.3