diff --git a/src/main/java/io/hexlet/typoreporter/controller/AccountController.java b/src/main/java/io/hexlet/typoreporter/controller/AccountController.java index 12b2f301..f0e6c638 100644 --- a/src/main/java/io/hexlet/typoreporter/controller/AccountController.java +++ b/src/main/java/io/hexlet/typoreporter/controller/AccountController.java @@ -1,7 +1,9 @@ package io.hexlet.typoreporter.controller; import io.hexlet.typoreporter.domain.account.Account; +import io.hexlet.typoreporter.security.service.AccountDetailService; import io.hexlet.typoreporter.service.AccountService; +import io.hexlet.typoreporter.service.dto.account.CustomUserDetails; import io.hexlet.typoreporter.service.dto.account.UpdatePassword; import io.hexlet.typoreporter.service.dto.account.UpdateProfile; import io.hexlet.typoreporter.handler.exception.AccountAlreadyExistException; @@ -23,8 +25,6 @@ import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestMapping; -import java.util.List; - @Slf4j @Controller @RequestMapping("/account") @@ -32,6 +32,7 @@ public class AccountController { private final AccountService accountService; + private final AccountDetailService accountDetailService; @GetMapping public String getAccountInfoPage(final Model model, final Authentication authentication) { @@ -64,8 +65,15 @@ public String putProfileUpdate(final Model model, try { final String email = authentication.getName(); Account updatedAccount = accountService.updateProfile(updateProfile, email); - final var authenticated = UsernamePasswordAuthenticationToken.authenticated(updatedAccount.getEmail(), - updatedAccount.getPassword(), List.of(() -> "ROLE_USER")); + + CustomUserDetails userDetails = (CustomUserDetails) accountDetailService + .loadUserByUsername(updatedAccount.getEmail()); + + final var authenticated = new UsernamePasswordAuthenticationToken( + userDetails, + userDetails.getPassword(), + userDetails.getAuthorities() + ); SecurityContextHolder.getContext().setAuthentication(authenticated); return "redirect:/account"; } catch (AccountAlreadyExistException e) { @@ -93,8 +101,14 @@ public String putPasswordUpdate(final Model model, try { final String email = authentication.getName(); Account updatedAccount = accountService.updatePassword(updatePassword, email); - final var authenticated = UsernamePasswordAuthenticationToken.authenticated(updatedAccount.getEmail(), - updatedAccount.getPassword(), List.of(() -> "ROLE_USER")); + CustomUserDetails userDetails = (CustomUserDetails) accountDetailService + .loadUserByUsername(updatedAccount.getEmail()); + + final var authenticated = new UsernamePasswordAuthenticationToken( + userDetails, + userDetails.getPassword(), + userDetails.getAuthorities() + ); SecurityContextHolder.getContext().setAuthentication(authenticated); return "redirect:/account"; } catch (OldPasswordWrongException | NewPasswordTheSameException e) { diff --git a/src/main/java/io/hexlet/typoreporter/controller/SignupController.java b/src/main/java/io/hexlet/typoreporter/controller/SignupController.java index fd8b406d..d1e86ec2 100644 --- a/src/main/java/io/hexlet/typoreporter/controller/SignupController.java +++ b/src/main/java/io/hexlet/typoreporter/controller/SignupController.java @@ -1,10 +1,11 @@ package io.hexlet.typoreporter.controller; -import io.hexlet.typoreporter.domain.workspace.AccountRole; +import io.hexlet.typoreporter.security.service.AccountDetailService; import io.hexlet.typoreporter.service.account.EmailAlreadyExistException; import io.hexlet.typoreporter.service.account.UsernameAlreadyExistException; import io.hexlet.typoreporter.service.account.signup.SignupAccountMapper; import io.hexlet.typoreporter.service.account.signup.SignupAccountUseCase; +import io.hexlet.typoreporter.service.dto.account.CustomUserDetails; import io.hexlet.typoreporter.service.dto.account.InfoAccount; import io.hexlet.typoreporter.web.model.SignupAccountModel; import jakarta.servlet.http.HttpServletRequest; @@ -27,8 +28,6 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; -import java.util.List; - @Slf4j @Controller @@ -39,6 +38,7 @@ public class SignupController { private final SignupAccountUseCase signupAccountUseCase; private final SignupAccountMapper signupAccountMapper; private final SecurityContextRepository securityContextRepository; + private final AccountDetailService accountDetailService; @GetMapping("/signup") public String getSignUpPage(final Model model) { @@ -61,8 +61,16 @@ public String createAccount(@ModelAttribute("signupAccount") @Valid SignupAccoun final InfoAccount newAccount; try { newAccount = signupAccountUseCase.signup(signupAccountMapper.toSignupAccount(signupAccountModel)); - final var authentication = UsernamePasswordAuthenticationToken. - authenticated(newAccount.email(), null, List.of(AccountRole.ROLE_GUEST::name)); + + CustomUserDetails userDetails = (CustomUserDetails) accountDetailService + .loadUserByUsername(newAccount.email()); + + final var authentication = new UsernamePasswordAuthenticationToken( + userDetails, + null, + userDetails.getAuthorities() + ); + autoLoginAfterSignup(request, response, authentication); return "redirect:/workspaces"; } catch (UsernameAlreadyExistException e) { diff --git a/src/main/java/io/hexlet/typoreporter/security/service/AccountDetailService.java b/src/main/java/io/hexlet/typoreporter/security/service/AccountDetailService.java index 4b85c257..4779886c 100644 --- a/src/main/java/io/hexlet/typoreporter/security/service/AccountDetailService.java +++ b/src/main/java/io/hexlet/typoreporter/security/service/AccountDetailService.java @@ -1,14 +1,19 @@ package io.hexlet.typoreporter.security.service; import io.hexlet.typoreporter.repository.AccountRepository; +import io.hexlet.typoreporter.service.dto.account.CustomUserDetails; import io.hexlet.typoreporter.utils.TextUtils; import lombok.RequiredArgsConstructor; -import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; +import java.util.Collection; +import java.util.Collections; + @Service @RequiredArgsConstructor public class AccountDetailService implements UserDetailsService { @@ -19,10 +24,11 @@ public class AccountDetailService implements UserDetailsService { public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { final String normalizedEmail = TextUtils.toLowerCaseData(email); return accountRepository.findAccountByEmail(normalizedEmail) - .map(acc -> User.withUsername(acc.getEmail()) - .password(acc.getPassword()) - .authorities("USER") - .build()) + .map(acc -> { + Collection authorities = + Collections.singletonList(new SimpleGrantedAuthority("USER")); + return new CustomUserDetails(acc.getEmail(), acc.getPassword(), acc.getUsername(), authorities); + }) .orElseThrow(() -> new UsernameNotFoundException("Account with email='" + email + "' not found")); } } diff --git a/src/main/java/io/hexlet/typoreporter/service/dto/account/CustomUserDetails.java b/src/main/java/io/hexlet/typoreporter/service/dto/account/CustomUserDetails.java new file mode 100644 index 00000000..05ab5ed2 --- /dev/null +++ b/src/main/java/io/hexlet/typoreporter/service/dto/account/CustomUserDetails.java @@ -0,0 +1,52 @@ +package io.hexlet.typoreporter.service.dto.account; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import java.util.Collection; +@AllArgsConstructor +public class CustomUserDetails implements UserDetails { + + private String email; + private String password; + @Getter + private final String nickname; + private Collection authorities; + + @Override + public String getUsername() { + return email; + } + + @Override + public String getPassword() { + return password; + } + + @Override + public Collection getAuthorities() { + return authorities; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } +} + diff --git a/src/main/resources/templates/fragments/panels.html b/src/main/resources/templates/fragments/panels.html index 7aa9be93..b4d9c424 100644 --- a/src/main/resources/templates/fragments/panels.html +++ b/src/main/resources/templates/fragments/panels.html @@ -30,13 +30,20 @@