Added endpoints and logic for user following system.
This commit is contained in:
parent
e69008a582
commit
6097b0df7e
|
@ -1,12 +1,10 @@
|
||||||
package nl.andrewlalis.gymboard_api.domains.auth.controller;
|
package nl.andrewlalis.gymboard_api.domains.auth.controller;
|
||||||
|
|
||||||
import nl.andrewlalis.gymboard_api.domains.auth.dto.*;
|
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.TokenService;
|
import nl.andrewlalis.gymboard_api.domains.auth.service.TokenService;
|
||||||
import nl.andrewlalis.gymboard_api.domains.auth.service.UserService;
|
import nl.andrewlalis.gymboard_api.domains.auth.service.UserService;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
|
|
|
@ -3,12 +3,11 @@ package nl.andrewlalis.gymboard_api.domains.auth.controller;
|
||||||
import nl.andrewlalis.gymboard_api.domains.auth.dto.*;
|
import nl.andrewlalis.gymboard_api.domains.auth.dto.*;
|
||||||
import nl.andrewlalis.gymboard_api.domains.auth.model.User;
|
import nl.andrewlalis.gymboard_api.domains.auth.model.User;
|
||||||
import nl.andrewlalis.gymboard_api.domains.auth.service.UserService;
|
import nl.andrewlalis.gymboard_api.domains.auth.service.UserService;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
public class UserController {
|
public class UserController {
|
||||||
|
@ -66,4 +65,26 @@ public class UserController {
|
||||||
) {
|
) {
|
||||||
return userService.updatePreferences(user.getId(), payload);
|
return userService.updatePreferences(user.getId(), payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping(path = "/auth/users/{userId}/followers")
|
||||||
|
public ResponseEntity<Void> followUser(@AuthenticationPrincipal User myUser, @PathVariable String userId) {
|
||||||
|
userService.followUser(myUser.getId(), userId);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping(path = "/auth/users/{userId}/followers")
|
||||||
|
public ResponseEntity<Void> unfollowUser(@AuthenticationPrincipal User myUser, @PathVariable String userId) {
|
||||||
|
userService.unfollowUser(myUser.getId(), userId);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping(path = "/auth/me/followers")
|
||||||
|
public Page<UserResponse> getFollowers(@AuthenticationPrincipal User user, Pageable pageable) {
|
||||||
|
return userService.getFollowers(user.getId(), pageable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping(path = "/auth/me/following")
|
||||||
|
public Page<UserResponse> getFollowing(@AuthenticationPrincipal User user, Pageable pageable) {
|
||||||
|
return userService.getFollowing(user.getId(), pageable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package nl.andrewlalis.gymboard_api.domains.auth.dao;
|
||||||
|
|
||||||
|
import nl.andrewlalis.gymboard_api.domains.auth.model.User;
|
||||||
|
import nl.andrewlalis.gymboard_api.domains.auth.model.UserFollowing;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Modifying;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface UserFollowingRepository extends JpaRepository<UserFollowing, Long> {
|
||||||
|
boolean existsByFollowedUserAndFollowingUser(User followedUser, User followingUser);
|
||||||
|
|
||||||
|
@Modifying
|
||||||
|
void deleteByFollowedUserAndFollowingUser(User followedUser, User followingUser);
|
||||||
|
|
||||||
|
Page<UserFollowing> findAllByFollowedUserOrderByCreatedAtDesc(User followedUser, Pageable pageable);
|
||||||
|
Page<UserFollowing> findAllByFollowingUserOrderByCreatedAtDesc(User followingUser, Pageable pageable);
|
||||||
|
}
|
|
@ -10,7 +10,10 @@ import java.time.LocalDateTime;
|
||||||
* have impacts on the notifications that a user can receive.
|
* have impacts on the notifications that a user can receive.
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "auth_user_following")
|
@Table(
|
||||||
|
name = "auth_user_following",
|
||||||
|
uniqueConstraints = @UniqueConstraint(columnNames = {"followed_user_id", "following_user_id"})
|
||||||
|
)
|
||||||
public class UserFollowing {
|
public class UserFollowing {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
|
|
@ -5,15 +5,14 @@ import jakarta.mail.internet.MimeMessage;
|
||||||
import nl.andrewlalis.gymboard_api.domains.api.model.WeightUnit;
|
import nl.andrewlalis.gymboard_api.domains.api.model.WeightUnit;
|
||||||
import nl.andrewlalis.gymboard_api.domains.auth.dao.*;
|
import nl.andrewlalis.gymboard_api.domains.auth.dao.*;
|
||||||
import nl.andrewlalis.gymboard_api.domains.auth.dto.*;
|
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.*;
|
||||||
import nl.andrewlalis.gymboard_api.domains.auth.model.User;
|
|
||||||
import nl.andrewlalis.gymboard_api.domains.auth.model.UserActivationCode;
|
|
||||||
import nl.andrewlalis.gymboard_api.domains.auth.model.UserPersonalDetails;
|
|
||||||
import nl.andrewlalis.gymboard_api.util.StringGenerator;
|
import nl.andrewlalis.gymboard_api.util.StringGenerator;
|
||||||
import nl.andrewlalis.gymboard_api.util.ULID;
|
import nl.andrewlalis.gymboard_api.util.ULID;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.mail.javamail.JavaMailSender;
|
import org.springframework.mail.javamail.JavaMailSender;
|
||||||
import org.springframework.mail.javamail.MimeMessageHelper;
|
import org.springframework.mail.javamail.MimeMessageHelper;
|
||||||
|
@ -38,6 +37,7 @@ public class UserService {
|
||||||
private final UserPreferencesRepository userPreferencesRepository;
|
private final UserPreferencesRepository userPreferencesRepository;
|
||||||
private final UserActivationCodeRepository activationCodeRepository;
|
private final UserActivationCodeRepository activationCodeRepository;
|
||||||
private final PasswordResetCodeRepository passwordResetCodeRepository;
|
private final PasswordResetCodeRepository passwordResetCodeRepository;
|
||||||
|
private final UserFollowingRepository userFollowingRepository;
|
||||||
private final ULID ulid;
|
private final ULID ulid;
|
||||||
private final PasswordEncoder passwordEncoder;
|
private final PasswordEncoder passwordEncoder;
|
||||||
private final JavaMailSender mailSender;
|
private final JavaMailSender mailSender;
|
||||||
|
@ -51,7 +51,7 @@ public class UserService {
|
||||||
UserPreferencesRepository userPreferencesRepository,
|
UserPreferencesRepository userPreferencesRepository,
|
||||||
UserActivationCodeRepository activationCodeRepository,
|
UserActivationCodeRepository activationCodeRepository,
|
||||||
PasswordResetCodeRepository passwordResetCodeRepository,
|
PasswordResetCodeRepository passwordResetCodeRepository,
|
||||||
ULID ulid,
|
UserFollowingRepository userFollowingRepository, ULID ulid,
|
||||||
PasswordEncoder passwordEncoder,
|
PasswordEncoder passwordEncoder,
|
||||||
JavaMailSender mailSender
|
JavaMailSender mailSender
|
||||||
) {
|
) {
|
||||||
|
@ -60,6 +60,7 @@ public class UserService {
|
||||||
this.userPreferencesRepository = userPreferencesRepository;
|
this.userPreferencesRepository = userPreferencesRepository;
|
||||||
this.activationCodeRepository = activationCodeRepository;
|
this.activationCodeRepository = activationCodeRepository;
|
||||||
this.passwordResetCodeRepository = passwordResetCodeRepository;
|
this.passwordResetCodeRepository = passwordResetCodeRepository;
|
||||||
|
this.userFollowingRepository = userFollowingRepository;
|
||||||
this.ulid = ulid;
|
this.ulid = ulid;
|
||||||
this.passwordEncoder = passwordEncoder;
|
this.passwordEncoder = passwordEncoder;
|
||||||
this.mailSender = mailSender;
|
this.mailSender = mailSender;
|
||||||
|
@ -276,4 +277,40 @@ public class UserService {
|
||||||
p = userPreferencesRepository.save(p);
|
p = userPreferencesRepository.save(p);
|
||||||
return new UserPreferencesResponse(p);
|
return new UserPreferencesResponse(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void followUser(String followerId, String followedId) {
|
||||||
|
User follower = userRepository.findById(followerId).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
|
||||||
|
User followed = userRepository.findById(followedId).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
|
||||||
|
|
||||||
|
if (!userFollowingRepository.existsByFollowedUserAndFollowingUser(followed, follower)) {
|
||||||
|
userFollowingRepository.save(new UserFollowing(followed, follower));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void unfollowUser(String followerId, String followedId) {
|
||||||
|
User follower = userRepository.findById(followerId).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
|
||||||
|
User followed = userRepository.findById(followedId).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
|
||||||
|
|
||||||
|
userFollowingRepository.deleteByFollowedUserAndFollowingUser(followed, follower);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public Page<UserResponse> getFollowers(String userId, Pageable pageable) {
|
||||||
|
User user = userRepository.findById(userId)
|
||||||
|
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
|
||||||
|
return userFollowingRepository.findAllByFollowedUserOrderByCreatedAtDesc(user, pageable)
|
||||||
|
.map(UserFollowing::getFollowingUser)
|
||||||
|
.map(UserResponse::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public Page<UserResponse> getFollowing(String userId, Pageable pageable) {
|
||||||
|
User user = userRepository.findById(userId)
|
||||||
|
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
|
||||||
|
return userFollowingRepository.findAllByFollowingUserOrderByCreatedAtDesc(user, pageable)
|
||||||
|
.map(UserFollowing::getFollowedUser)
|
||||||
|
.map(UserResponse::new);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue