From e69008a582fdc73e3417034ec84516aa7cce7b3f Mon Sep 17 00:00:00 2001 From: Andrew Lalis Date: Mon, 6 Feb 2023 10:17:50 +0100 Subject: [PATCH] Added user preferences endpoints. --- .../auth/controller/AuthController.java | 23 ---------- .../auth/controller/UserController.java | 43 +++++++++++++++++-- .../auth/dao/UserPreferencesRepository.java | 9 ++++ .../auth/dto/UserPreferencesPayload.java | 6 +++ .../auth/dto/UserPreferencesResponse.java | 17 ++++++++ .../domains/auth/service/UserService.java | 32 +++++++++++--- 6 files changed, 96 insertions(+), 34 deletions(-) create mode 100644 gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/domains/auth/dao/UserPreferencesRepository.java create mode 100644 gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/domains/auth/dto/UserPreferencesPayload.java create mode 100644 gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/domains/auth/dto/UserPreferencesResponse.java diff --git a/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/domains/auth/controller/AuthController.java b/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/domains/auth/controller/AuthController.java index b01b801..6dcf0bd 100644 --- a/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/domains/auth/controller/AuthController.java +++ b/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/domains/auth/controller/AuthController.java @@ -68,29 +68,6 @@ public class AuthController { return tokenService.regenerateAccessToken(auth); } - /** - * Gets information about the user, as determined by the provided access - * token. - * @param user The user that requested information. - * @return The user data. - */ - @GetMapping(path = "/auth/me") - public UserResponse getMyUser(@AuthenticationPrincipal User user) { - return new UserResponse(user); - } - - /** - * Endpoint for updating one's own password. - * @param user The user that's updating their password. - * @param payload The payload with the new password. - * @return An empty 200 OK response. - */ - @PostMapping(path = "/auth/me/password") - public ResponseEntity updateMyPassword(@AuthenticationPrincipal User user, @RequestBody PasswordUpdatePayload payload) { - userService.updatePassword(user.getId(), payload); - return ResponseEntity.ok().build(); - } - /** * Public endpoint for requesting a reset code to be sent * to an account with the given email address. diff --git a/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/domains/auth/controller/UserController.java b/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/domains/auth/controller/UserController.java index 0fadbd9..090606d 100644 --- a/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/domains/auth/controller/UserController.java +++ b/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/domains/auth/controller/UserController.java @@ -1,10 +1,9 @@ package nl.andrewlalis.gymboard_api.domains.auth.controller; -import nl.andrewlalis.gymboard_api.domains.auth.dto.UserPersonalDetailsPayload; -import nl.andrewlalis.gymboard_api.domains.auth.dto.UserPersonalDetailsResponse; -import nl.andrewlalis.gymboard_api.domains.auth.dto.UserResponse; +import nl.andrewlalis.gymboard_api.domains.auth.dto.*; import nl.andrewlalis.gymboard_api.domains.auth.model.User; import nl.andrewlalis.gymboard_api.domains.auth.service.UserService; +import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @@ -19,16 +18,52 @@ public class UserController { this.userService = userService; } + /** + * Gets information about the user, as determined by the provided access + * token. + * @param user The user that requested information. + * @return The user data. + */ + @GetMapping(path = "/auth/me") + public UserResponse getMyUser(@AuthenticationPrincipal User user) { + return new UserResponse(user); + } + + /** + * Endpoint for updating one's own password. + * @param user The user that's updating their password. + * @param payload The payload with the new password. + * @return An empty 200 OK response. + */ + @PostMapping(path = "/auth/me/password") + public ResponseEntity updateMyPassword(@AuthenticationPrincipal User user, @RequestBody PasswordUpdatePayload payload) { + userService.updatePassword(user.getId(), payload); + return ResponseEntity.ok().build(); + } + @GetMapping(path = "/auth/me/personal-details") public UserPersonalDetailsResponse getMyPersonalDetails(@AuthenticationPrincipal User user) { return userService.getPersonalDetails(user.getId()); } @PostMapping(path = "/auth/me/personal-details") - public UserResponse updateMyPersonalDetails( + public UserPersonalDetailsResponse updateMyPersonalDetails( @AuthenticationPrincipal User user, @RequestBody UserPersonalDetailsPayload payload ) { return userService.updatePersonalDetails(user.getId(), payload); } + + @GetMapping(path = "/auth/me/preferences") + public UserPreferencesResponse getMyPreferences(@AuthenticationPrincipal User user) { + return userService.getPreferences(user.getId()); + } + + @PostMapping(path = "/auth/me/preferences") + public UserPreferencesResponse updateMyPreferences( + @AuthenticationPrincipal User user, + @RequestBody UserPreferencesPayload payload + ) { + return userService.updatePreferences(user.getId(), payload); + } } diff --git a/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/domains/auth/dao/UserPreferencesRepository.java b/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/domains/auth/dao/UserPreferencesRepository.java new file mode 100644 index 0000000..5e6738a --- /dev/null +++ b/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/domains/auth/dao/UserPreferencesRepository.java @@ -0,0 +1,9 @@ +package nl.andrewlalis.gymboard_api.domains.auth.dao; + +import nl.andrewlalis.gymboard_api.domains.auth.model.UserPreferences; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface UserPreferencesRepository extends JpaRepository { +} diff --git a/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/domains/auth/dto/UserPreferencesPayload.java b/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/domains/auth/dto/UserPreferencesPayload.java new file mode 100644 index 0000000..70871f8 --- /dev/null +++ b/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/domains/auth/dto/UserPreferencesPayload.java @@ -0,0 +1,6 @@ +package nl.andrewlalis.gymboard_api.domains.auth.dto; + +public record UserPreferencesPayload( + boolean accountPrivate, + String locale +) {} diff --git a/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/domains/auth/dto/UserPreferencesResponse.java b/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/domains/auth/dto/UserPreferencesResponse.java new file mode 100644 index 0000000..bd69629 --- /dev/null +++ b/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/domains/auth/dto/UserPreferencesResponse.java @@ -0,0 +1,17 @@ +package nl.andrewlalis.gymboard_api.domains.auth.dto; + +import nl.andrewlalis.gymboard_api.domains.auth.model.UserPreferences; + +public record UserPreferencesResponse( + String userId, + boolean accountPrivate, + String locale +) { + public UserPreferencesResponse(UserPreferences p) { + this( + p.getUserId(), + p.isAccountPrivate(), + p.getLocale() + ); + } +} diff --git a/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/domains/auth/service/UserService.java b/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/domains/auth/service/UserService.java index ad751a3..e3d3b34 100644 --- a/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/domains/auth/service/UserService.java +++ b/gymboard-api/src/main/java/nl/andrewlalis/gymboard_api/domains/auth/service/UserService.java @@ -3,10 +3,7 @@ package nl.andrewlalis.gymboard_api.domains.auth.service; import jakarta.mail.MessagingException; import jakarta.mail.internet.MimeMessage; import nl.andrewlalis.gymboard_api.domains.api.model.WeightUnit; -import nl.andrewlalis.gymboard_api.domains.auth.dao.PasswordResetCodeRepository; -import nl.andrewlalis.gymboard_api.domains.auth.dao.UserActivationCodeRepository; -import nl.andrewlalis.gymboard_api.domains.auth.dao.UserPersonalDetailsRepository; -import nl.andrewlalis.gymboard_api.domains.auth.dao.UserRepository; +import nl.andrewlalis.gymboard_api.domains.auth.dao.*; import nl.andrewlalis.gymboard_api.domains.auth.dto.*; import nl.andrewlalis.gymboard_api.domains.auth.model.PasswordResetCode; import nl.andrewlalis.gymboard_api.domains.auth.model.User; @@ -38,6 +35,7 @@ public class UserService { private final UserRepository userRepository; private final UserPersonalDetailsRepository userPersonalDetailsRepository; + private final UserPreferencesRepository userPreferencesRepository; private final UserActivationCodeRepository activationCodeRepository; private final PasswordResetCodeRepository passwordResetCodeRepository; private final ULID ulid; @@ -49,7 +47,9 @@ public class UserService { public UserService( UserRepository userRepository, - UserPersonalDetailsRepository userPersonalDetailsRepository, UserActivationCodeRepository activationCodeRepository, + UserPersonalDetailsRepository userPersonalDetailsRepository, + UserPreferencesRepository userPreferencesRepository, + UserActivationCodeRepository activationCodeRepository, PasswordResetCodeRepository passwordResetCodeRepository, ULID ulid, PasswordEncoder passwordEncoder, @@ -57,6 +57,7 @@ public class UserService { ) { this.userRepository = userRepository; this.userPersonalDetailsRepository = userPersonalDetailsRepository; + this.userPreferencesRepository = userPreferencesRepository; this.activationCodeRepository = activationCodeRepository; this.passwordResetCodeRepository = passwordResetCodeRepository; this.ulid = ulid; @@ -228,7 +229,7 @@ public class UserService { } @Transactional - public UserResponse updatePersonalDetails(String id, UserPersonalDetailsPayload payload) { + public UserPersonalDetailsResponse updatePersonalDetails(String id, UserPersonalDetailsPayload payload) { User user = userRepository.findById(id) .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); var pd = user.getPersonalDetails(); @@ -249,7 +250,7 @@ public class UserService { pd.setCurrentMetricWeight(currentMetricWeight); pd.setSex(UserPersonalDetails.PersonSex.parse(payload.sex())); user = userRepository.save(user); - return new UserResponse(user); + return new UserPersonalDetailsResponse(user.getPersonalDetails()); } @Transactional(readOnly = true) @@ -258,4 +259,21 @@ public class UserService { .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); return new UserPersonalDetailsResponse(pd); } + + @Transactional(readOnly = true) + public UserPreferencesResponse getPreferences(String id) { + var p = userPreferencesRepository.findById(id) + .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); + return new UserPreferencesResponse(p); + } + + @Transactional + public UserPreferencesResponse updatePreferences(String id, UserPreferencesPayload payload) { + var p = userPreferencesRepository.findById(id) + .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); + p.setAccountPrivate(payload.accountPrivate()); + p.setLocale(payload.locale()); + p = userPreferencesRepository.save(p); + return new UserPreferencesResponse(p); + } }