diff --git a/src/main/java/com/faf223/expensetrackerfaf/controller/UserController.java b/src/main/java/com/faf223/expensetrackerfaf/controller/UserController.java index 160be82..5fbbe4f 100644 --- a/src/main/java/com/faf223/expensetrackerfaf/controller/UserController.java +++ b/src/main/java/com/faf223/expensetrackerfaf/controller/UserController.java @@ -1,15 +1,20 @@ package com.faf223.expensetrackerfaf.controller; +import com.faf223.expensetrackerfaf.controller.auth.ChangePasswordRequest; import com.faf223.expensetrackerfaf.dto.UserCreationDTO; import com.faf223.expensetrackerfaf.dto.UserDTO; import com.faf223.expensetrackerfaf.dto.mappers.UserMapper; +import com.faf223.expensetrackerfaf.model.Credential; import com.faf223.expensetrackerfaf.model.User; +import com.faf223.expensetrackerfaf.repository.CredentialRepository; +import com.faf223.expensetrackerfaf.service.AuthenticationService; import com.faf223.expensetrackerfaf.service.UserService; import com.faf223.expensetrackerfaf.util.errors.ErrorResponse; import com.faf223.expensetrackerfaf.util.exceptions.UserNotCreatedException; import com.faf223.expensetrackerfaf.util.exceptions.UserNotFoundException; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; @@ -19,6 +24,9 @@ import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.*; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; @RestController @RequestMapping("/users") @@ -27,29 +35,53 @@ public class UserController { private final UserService userService; private final UserMapper userMapper; + private final CredentialRepository credentialRepository; + private final AuthenticationService authenticationService; @PatchMapping() public ResponseEntity updateUser(@RequestBody @Valid UserCreationDTO userDTO, BindingResult bindingResult) { - if(bindingResult.hasErrors()) + if (bindingResult.hasErrors()) throw new UserNotCreatedException(ErrorResponse.from(bindingResult).getMessage()); User user = userMapper.toUser(userDTO); + if (!bindingResult.hasErrors()) { + userService.updateUser(user); return ResponseEntity.ok(userMapper.toDto(user)); + } else { throw new UserNotFoundException("The user has not been found"); } } + @PatchMapping("/update-password") + public ResponseEntity updateUserPassword(@RequestBody ChangePasswordRequest password) { + + System.out.println("Hi"); + + authenticationService.updatePassword(password.getPassword()); + return ResponseEntity.status(HttpStatus.OK).build(); + } + @GetMapping("/get-user-data") - public ResponseEntity getUser() { + public ResponseEntity> getUser() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication != null && authentication.getPrincipal() instanceof UserDetails userDetails) { User user = userService.getUserByEmail(userDetails.getUsername()); - if (user != null) return ResponseEntity.ok(userMapper.toDto(user)); + Optional credential = credentialRepository.findByUser(user); + + if (credential.isPresent()) { + Map userData = new HashMap<>(); + userData.put("firstname", user.getFirstName()); + userData.put("lastname", user.getLastName()); + userData.put("username", user.getUsername()); + userData.put("userrole", credential.get().getRole().toString()); // Assuming UserRole is an enum + + return ResponseEntity.ok(userData); + } } throw new UserNotFoundException("The user has not been found"); } @@ -61,5 +93,14 @@ public class UserController { return ResponseEntity.ok(userMapper.toDto(users)); } + + @GetMapping("/delete/{username}") + @PreAuthorize("hasRole('ADMIN')") + public ResponseEntity deleteUserByUsername(@PathVariable String username) { + + userService.deleteByUsername(username); + + return ResponseEntity.status(HttpStatus.OK).build(); + } } diff --git a/src/main/java/com/faf223/expensetrackerfaf/controller/auth/ChangePasswordRequest.java b/src/main/java/com/faf223/expensetrackerfaf/controller/auth/ChangePasswordRequest.java new file mode 100644 index 0000000..f550630 --- /dev/null +++ b/src/main/java/com/faf223/expensetrackerfaf/controller/auth/ChangePasswordRequest.java @@ -0,0 +1,14 @@ +package com.faf223.expensetrackerfaf.controller.auth; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ChangePasswordRequest { + private String password; +} diff --git a/src/main/java/com/faf223/expensetrackerfaf/dto/UserDTO.java b/src/main/java/com/faf223/expensetrackerfaf/dto/UserDTO.java index e2024b1..bae5e2a 100644 --- a/src/main/java/com/faf223/expensetrackerfaf/dto/UserDTO.java +++ b/src/main/java/com/faf223/expensetrackerfaf/dto/UserDTO.java @@ -17,5 +17,4 @@ public class UserDTO { @NotNull(message = "Username must not be null") @NotEmpty(message = "Username must not be empty") private String username; - } diff --git a/src/main/java/com/faf223/expensetrackerfaf/model/User.java b/src/main/java/com/faf223/expensetrackerfaf/model/User.java index e3b0166..26dbd9c 100644 --- a/src/main/java/com/faf223/expensetrackerfaf/model/User.java +++ b/src/main/java/com/faf223/expensetrackerfaf/model/User.java @@ -1,48 +1,48 @@ -package com.faf223.expensetrackerfaf.model; + package com.faf223.expensetrackerfaf.model; -import jakarta.persistence.*; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.*; + import jakarta.persistence.*; + import jakarta.validation.constraints.NotEmpty; + import jakarta.validation.constraints.NotNull; + import lombok.*; -import java.util.List; + import java.util.List; -@Entity(name = "users") -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class User { - @Id - @Column(name = "user_uuid") - @GeneratedValue(strategy = GenerationType.UUID) - private String userUuid; + @Entity(name = "users") + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public class User { + @Id + @Column(name = "user_uuid") + @GeneratedValue(strategy = GenerationType.UUID) + private String userUuid; - @Column(name = "name") - @NotNull(message = "First name must not be null") - @NotEmpty(message = "First name must not be empty") - private String firstName; + @Column(name = "name") + @NotNull(message = "First name must not be null") + @NotEmpty(message = "First name must not be empty") + private String firstName; - @Column(name = "surname") - @NotNull(message = "Last name must not be null") - @NotEmpty(message = "Last name must not be empty") - private String lastName; + @Column(name = "surname") + @NotNull(message = "Last name must not be null") + @NotEmpty(message = "Last name must not be empty") + private String lastName; - @Column(name = "username") - @NotNull(message = "Username must not be null") - @NotEmpty(message = "Username must not be empty") - private String username; + @Column(name = "username") + @NotNull(message = "Username must not be null") + @NotEmpty(message = "Username must not be empty") + private String username; - @Transient -// @NotNull(message = "Password must not be null") -// @NotEmpty(message = "Password must not be empty") - private String password; + @Transient + // @NotNull(message = "Password must not be null") + // @NotEmpty(message = "Password must not be empty") + private String password; - @OneToMany(mappedBy = "user", fetch = FetchType.LAZY) - @ToString.Exclude - private List expenses; + @OneToMany(mappedBy = "user", fetch = FetchType.LAZY, cascade = CascadeType.ALL) + @ToString.Exclude + private List expenses; - @OneToMany(mappedBy = "user", fetch = FetchType.LAZY) - @ToString.Exclude - private List incomes; -} + @OneToMany(mappedBy = "user", fetch = FetchType.LAZY, cascade = CascadeType.ALL) + @ToString.Exclude + private List incomes; + } diff --git a/src/main/java/com/faf223/expensetrackerfaf/repository/CredentialRepository.java b/src/main/java/com/faf223/expensetrackerfaf/repository/CredentialRepository.java index 065212d..8be7ee4 100644 --- a/src/main/java/com/faf223/expensetrackerfaf/repository/CredentialRepository.java +++ b/src/main/java/com/faf223/expensetrackerfaf/repository/CredentialRepository.java @@ -1,6 +1,7 @@ package com.faf223.expensetrackerfaf.repository; import com.faf223.expensetrackerfaf.model.Credential; +import com.faf223.expensetrackerfaf.model.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -9,4 +10,8 @@ import java.util.Optional; @Repository public interface CredentialRepository extends JpaRepository { Optional findByEmail(String email); + + Optional findByUser(User user); + + void deleteByEmail(String email); } \ No newline at end of file diff --git a/src/main/java/com/faf223/expensetrackerfaf/repository/UserRepository.java b/src/main/java/com/faf223/expensetrackerfaf/repository/UserRepository.java index e044309..0877079 100644 --- a/src/main/java/com/faf223/expensetrackerfaf/repository/UserRepository.java +++ b/src/main/java/com/faf223/expensetrackerfaf/repository/UserRepository.java @@ -9,4 +9,6 @@ public interface UserRepository extends JpaRepository { Optional getUserByUserUuid(String userUuid); Optional findByUsername(String username); + + void deleteByUsername(String username); } diff --git a/src/main/java/com/faf223/expensetrackerfaf/service/AuthenticationService.java b/src/main/java/com/faf223/expensetrackerfaf/service/AuthenticationService.java index 6f1bf22..6044361 100644 --- a/src/main/java/com/faf223/expensetrackerfaf/service/AuthenticationService.java +++ b/src/main/java/com/faf223/expensetrackerfaf/service/AuthenticationService.java @@ -15,6 +15,8 @@ import com.faf223.expensetrackerfaf.util.exceptions.UserNotFoundException; import lombok.RequiredArgsConstructor; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.oauth2.core.user.OAuth2User; @@ -27,6 +29,7 @@ import java.util.Optional; public class AuthenticationService { private final UserRepository userRepository; + private final UserService userService; private final CredentialRepository credentialRepository; private final PasswordEncoder passwordEncoder; private final JwtService jwtService; @@ -136,4 +139,22 @@ public class AuthenticationService { } } + public void updatePassword(String newPassword) { + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + if (authentication != null && authentication.getPrincipal() instanceof UserDetails userDetails) { + User user = userService.getUserByEmail(userDetails.getUsername()); + Optional credential = credentialRepository.findByUser(user); + + if (credential.isPresent()) { + + Credential updatedCredential = credential.get(); + updatedCredential.setPassword(passwordEncoder.encode(newPassword)); + credentialRepository.save(updatedCredential); + } + } + + } + } diff --git a/src/main/java/com/faf223/expensetrackerfaf/service/UserService.java b/src/main/java/com/faf223/expensetrackerfaf/service/UserService.java index 20dbc96..7550bac 100644 --- a/src/main/java/com/faf223/expensetrackerfaf/service/UserService.java +++ b/src/main/java/com/faf223/expensetrackerfaf/service/UserService.java @@ -4,6 +4,7 @@ import com.faf223.expensetrackerfaf.model.Credential; import com.faf223.expensetrackerfaf.model.User; import com.faf223.expensetrackerfaf.repository.CredentialRepository; import com.faf223.expensetrackerfaf.repository.UserRepository; +import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -36,4 +37,20 @@ public class UserService { } return null; } + + @Transactional + public void deleteByUsername(String username) { + + Optional user = userRepository.findByUsername(username); + if (user.isPresent()) { + + Optional credential = credentialRepository.findByUser(user.get()); + + if (credential.isPresent()) { + + credentialRepository.deleteByEmail(credential.get().getEmail()); + userRepository.deleteByUsername(username); + } + } + } } \ No newline at end of file