1.security config ->PasswordEncoder 변경
@Component
public class PasswordEncoder {
public String encode(String rawPassword) {
return BCrypt.withDefaults().hashToString(BCrypt.MIN_COST, rawPassword.toCharArray());
}
public boolean matches(String rawPassword, String encodedPassword) {
BCrypt.Result result = BCrypt.verifyer().verify(rawPassword.toCharArray(), encodedPassword);
return result.verified;
}
}
2. Invalid DefionitionException
@AllArgsConstructor
@Getter
public class ResponseDto<T> {
private boolean success;
private String message;
private T data;
public static <T> ResponseDto<T> fail(String message) {
return new ResponseDto<>(false, message, null);
}
}
3.?????-> 한글로 인코딩
if (session == null || session.getAttribute("loginUser") == null) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
ResponseDto<Void> failResponse = ResponseDto.fail("로그인이 필요합니다.");
String json = new ObjectMapper().writeValueAsString(failResponse); // Jackson 의 ObjectMapper 사용
response.getWriter().write(json);
return;
}
4. 로그인 로그아웃
@PostMapping(value = "/login")
public ResponseEntity<Void> login(@RequestBody LoginRequestDto dto, HttpServletRequest request) {
HttpSession session =request.getSession();
userService.login(dto,session);
return new ResponseEntity<>(HttpStatus.OK);
}
@PostMapping(value = "/logout")
public ResponseEntity<Void> logout(@RequestBody LoginRequestDto dto, HttpServletRequest request) {
HttpSession session=request.getSession(false);
if(session!=null){
session.invalidate();
}
return new ResponseEntity<>(HttpStatus.OK);
}
public void login(LoginRequestDto dto, HttpSession session) {
User user = userRepository.findByEmail(dto.getEmail())
.orElseThrow(() -> new CustomException(ErrorCode.INVALID_EMAIL));
if (!isPasswordValid(dto.getPassword(), user.getPassword())) {
throw new CustomException(ErrorCode.INVALID_PASSWORD);
}
if (user.getDeletedAt()==null) {
session.setAttribute("loginUser", user.getId());
} else {
throw new CustomException(ErrorCode.INVALID_USER_ID);
}
}
5. 비밀번호 수정
import lombok.Getter;
@Getter
public class ModifyPasswordRequestDto {
String newPassword;
String oldPassword;
}
@Transactional
public void modifyPassword(Long id, ModifyPasswordRequestDto requestDto){
User user = userRepository.findById(id).orElseThrow(() -> new CustomException(ErrorCode.INVALID_USER_ID));
if (!isPasswordValid(requestDto.getOldPassword(),user.getPassword())){
throw new CustomException(ErrorCode.INVALID_PASSWORD);
}
user.setPassword(passwordEncoder.encode(requestDto.getNewPassword()));
}
6.@RequiredArgsConstructor
public class PostLikeController {
private final PostLikeService postLikeService;
@Autowired
public PostLikeController(PostLikeService postLikeService) {
this.postLikeService = postLikeService;
}
@PostMapping
public ResponseEntity<Void> like(@PathVariable Long postId, HttpSession session) {
Long userId = (Long) session.getAttribute("loginUser"); // 로그인한 유저의 ID(FK)를 세션에서 가져옴
postLikeService.like(postId, userId);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
@DeleteMapping
public ResponseEntity<Void> unlike(@PathVariable Long postId, HttpSession session) {
Long userId = (Long) session.getAttribute("loginUser"); // 로그인한 유저의 ID(FK)를 세션에서 가져옴
postLikeService.unlike(postId, userId);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
}
package inxj.newsfeed.like.controller;
import inxj.newsfeed.like.service.CommentLikeService;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RequestMapping("/posts/{postId}/comments/{commentId}/likes")
@RestController
public class CommentLikeController {
private final CommentLikeService commentLikeService;
@Autowired
public CommentLikeController(CommentLikeService commentLikeService) {
this.commentLikeService = commentLikeService;
}
미정사항:
1. varchar에는 글자수 제한 존재 longtext에는 글자 수 제한 X
@Column (columnDefinition = "longtext")
2. 암호화를 걸었기에 원래 비밀번호 알 수 X-> 번호 교체해서 제공
public ChangePasswordResponseDto changePassword(Long id) {
User user = userRepository.findById(id).orElseThrow(() -> new CustomException(ErrorCode.INVALID_USER_ID));
String password="12345678910";
return new ChangePasswordResponseDto(password);
}
3. 통일할까요?
package inxj.newsfeed.friend.controller;
private Long getLoginUserId(HttpSession session){
return (Long) session.getAttribute("loginUser");
}
Long userId = getLoginUserId(session);
Long id = (Long) session.getAttribute("loginUser");
4. 통일할까요? 2
저는 얘를 common-config로 옮겨서 통일해서 변경하는게 나을 것 같습니다.
why? 서비스 throw를 책임을 안져요-> 레포지티리에서 가져오는 책임 하나
-> 실수로 throw를 빈공간으로 만들 가능성이 낮아져요
package inxj.newsfeed.like.service;
import inxj.newsfeed.comment.entity.Comment;
import inxj.newsfeed.comment.repository.CommentRepository;
import inxj.newsfeed.exception.CustomException;
import inxj.newsfeed.exception.ErrorCode;
import inxj.newsfeed.like.entity.CommentLike;
import inxj.newsfeed.like.entity.CommentLikeId;
import inxj.newsfeed.like.entity.PostLike;
import inxj.newsfeed.like.entity.PostLikeId;
import inxj.newsfeed.like.repository.CommentLikeRepository;
import inxj.newsfeed.like.repository.PostLikeRepository;
import inxj.newsfeed.post.entity.Post;
import inxj.newsfeed.post.repository.PostRepository;
import inxj.newsfeed.user.entity.User;
import inxj.newsfeed.user.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor // 생성자가 한 개인 경우 자동으로 @Autowired 가 붙음
public class EntityFetcher {
private final UserRepository userRepository;
private final PostRepository postRepository;
private final PostLikeRepository postLikeRepository;
private final CommentRepository commentRepository;
private final CommentLikeRepository commentLikeRepository;
public User getUserOrThrow(Long userId) {
return userRepository.findById(userId)
.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_USER_ID));
}
public Post getPostOrThrow(Long postId) {
return postRepository.findById(postId)
.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_POST_ID));
}
public PostLike getPostLikeOrThrow(PostLikeId postLikeId) {
return postLikeRepository.findById(postLikeId)
.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_LIKE_ID));
}
public Comment getCommentOrThrow(Long commentId) {
return commentRepository.findById(commentId)
.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_COMMENT_ID));
}
public CommentLike getCommentLikeOrThrow(CommentLikeId commentLikeId) {
return commentLikeRepository.findById(commentLikeId)
.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_LIKE_ID));
}
}
5, 오타발생 확률 저하
ublic interface Const {
String LOGIN_USER = "loginUser";
}
6. 코드 네임 정해야 하지 않을까요?