From 553ea9607145b39016b5f36049f414ca2f3e27aa Mon Sep 17 00:00:00 2001 From: eastmeet Date: Thu, 19 Jan 2023 03:06:23 +0900 Subject: [PATCH 1/4] refactor: Add Build Pattern(#43) --- .../dto/AttractionDetailResponseDto.java | 3 - .../attraction/mapper/AttractionMapper.java | 6 -- .../comment/controller/CommentController.java | 99 +++++++++---------- .../picha/domain/comment/dto/CommentDto.java | 9 -- .../domain/comment/dto/CommentPostDto.java | 4 +- .../picha/domain/comment/entity/Comment.java | 4 +- .../domain/comment/mapper/CommentMapper.java | 4 + .../comment/service/CommentService.java | 9 -- .../picha/domain/hashtag/entity/HashTag.java | 7 +- .../member/controller/MemberController.java | 23 ++--- .../domain/member/mapper/MemberMapper.java | 6 -- .../post/controller/PostController.java | 85 ++++++++++------ .../post/dto/PostDetailPageResponseDto.java | 26 ----- .../picha/domain/post/dto/PostHomeDto.java | 4 +- ...PatchRequestDto.java => PostPatchDto.java} | 5 +- .../domain/post/dto/PostPatchResponseDto.java | 24 ----- .../domain/post/dto/PostRegisterDto.java | 9 +- .../post/dto/PostRegisterResponseDto.java | 21 ---- ...nseDto.java => SinglePostResponseDto.java} | 25 +++-- .../main36/picha/domain/post/entity/Post.java | 12 ++- .../picha/domain/post/mapper/PostMapper.java | 77 ++++++++++----- .../domain/post/service/PostService.java | 7 +- .../domain/post_likes/entity/PostLikes.java | 7 +- .../handler/OAuth2MemberSuccessHandler.java | 4 +- .../global/config/SecurityConfiguration.java | 11 +-- 25 files changed, 212 insertions(+), 279 deletions(-) delete mode 100644 server/src/main/java/com/main36/picha/domain/comment/dto/CommentDto.java delete mode 100644 server/src/main/java/com/main36/picha/domain/post/dto/PostDetailPageResponseDto.java rename server/src/main/java/com/main36/picha/domain/post/dto/{PostPatchRequestDto.java => PostPatchDto.java} (78%) delete mode 100644 server/src/main/java/com/main36/picha/domain/post/dto/PostPatchResponseDto.java delete mode 100644 server/src/main/java/com/main36/picha/domain/post/dto/PostRegisterResponseDto.java rename server/src/main/java/com/main36/picha/domain/post/dto/{PostResponseDto.java => SinglePostResponseDto.java} (69%) diff --git a/server/src/main/java/com/main36/picha/domain/attraction/dto/AttractionDetailResponseDto.java b/server/src/main/java/com/main36/picha/domain/attraction/dto/AttractionDetailResponseDto.java index 562ab29c..3fd56230 100644 --- a/server/src/main/java/com/main36/picha/domain/attraction/dto/AttractionDetailResponseDto.java +++ b/server/src/main/java/com/main36/picha/domain/attraction/dto/AttractionDetailResponseDto.java @@ -1,11 +1,8 @@ package com.main36.picha.domain.attraction.dto; -import com.main36.picha.domain.post.dto.PostResponseDto; import lombok.Builder; import lombok.Data; -import java.util.List; - // 명소 상세 페이지 @Data public class AttractionDetailResponseDto { diff --git a/server/src/main/java/com/main36/picha/domain/attraction/mapper/AttractionMapper.java b/server/src/main/java/com/main36/picha/domain/attraction/mapper/AttractionMapper.java index 72850aaa..dca89d28 100644 --- a/server/src/main/java/com/main36/picha/domain/attraction/mapper/AttractionMapper.java +++ b/server/src/main/java/com/main36/picha/domain/attraction/mapper/AttractionMapper.java @@ -5,15 +5,9 @@ import com.main36.picha.domain.attraction.dto.AttractionPostDto; import com.main36.picha.domain.attraction.dto.AttractionResponseDto; import com.main36.picha.domain.attraction.entity.Attraction; -import com.main36.picha.domain.post.dto.PostResponseDto; import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.ReportingPolicy; -import org.springframework.stereotype.Component; import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; @Mapper(componentModel = "spring") public interface AttractionMapper { diff --git a/server/src/main/java/com/main36/picha/domain/comment/controller/CommentController.java b/server/src/main/java/com/main36/picha/domain/comment/controller/CommentController.java index a9ab25bf..1ac567d6 100644 --- a/server/src/main/java/com/main36/picha/domain/comment/controller/CommentController.java +++ b/server/src/main/java/com/main36/picha/domain/comment/controller/CommentController.java @@ -1,10 +1,11 @@ package com.main36.picha.domain.comment.controller; -import com.main36.picha.domain.comment.dto.CommentDto; +import com.main36.picha.domain.comment.dto.CommentPostDto; import com.main36.picha.domain.comment.dto.CommentResponseDto; import com.main36.picha.domain.comment.entity.Comment; import com.main36.picha.domain.comment.mapper.CommentMapper; import com.main36.picha.domain.comment.service.CommentService; +import com.main36.picha.domain.member.entity.Member; import com.main36.picha.domain.member.service.MemberService; import com.main36.picha.domain.post.service.PostService; import com.main36.picha.global.auth.jwt.JwtTokenizer; @@ -14,6 +15,7 @@ import com.main36.picha.global.response.MultiResponseDto; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jws; +import lombok.Data; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; @@ -23,8 +25,10 @@ import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; +import javax.validation.Valid; import javax.validation.constraints.Positive; import java.util.List; +import java.util.Optional; @RestController @Slf4j @@ -42,75 +46,70 @@ public class CommentController { private final CommentMapper mapper; - @PostMapping("/upload/{post-id}") - public ResponseEntity postComment(HttpServletRequest request, - @PathVariable("post-id")@Positive long postId, - @RequestBody CommentDto postDto) { - Comment comment = new Comment(); - // 멤버 넣기 - String userEmail = extractedUsername(request); - System.out.println("userEmail is : "+ userEmail); - comment.setMember(memberService.findMember(userEmail)); - - // 글 넣기 - comment.setPost(postService.findPost(postId)); - - // 댓글 내용 넣기 - comment.setCommentContent(postDto.getCommentContent()); - Comment createdComment = commentService.createComment(comment); - return new ResponseEntity<>(new DataResponseDto<>( - mapper.commentToCommentResponseDto(createdComment)), HttpStatus.CREATED); + @PostMapping("/upload/{member-id}/{post-id}") + public ResponseEntity> postComment(@PathVariable("member-id") @Positive long memberId, + @PathVariable("post-id") @Positive long postId, + @RequestBody @Valid CommentPostDto commentPostDto) { + + Comment.CommentBuilder commentBuilder = Comment.builder(); + + Comment comment = + commentService.createComment( + commentBuilder + .commentContent(commentPostDto.getCommentContent()) + .member(memberService.findVerifiedMemberById(memberId)) + .post(postService.findPost(postId)) + .build() + ); + + CommentResponseDto commentResponseDto = mapper.commentToCommentResponseDto(comment); + + return new ResponseEntity<>(new DataResponseDto<>(commentResponseDto), HttpStatus.CREATED); } - @PatchMapping("/edit/{comment-id}") - public ResponseEntity patchComment(HttpServletRequest request, - @PathVariable("comment-id")@Positive long commentId, - @RequestBody CommentDto postDto){ + @PatchMapping("/edit/{member-id}/{comment-id}") + public ResponseEntity> patchComment(@PathVariable("member-id") @Positive long memberId, + @PathVariable("comment-id") @Positive long commentId, + @RequestBody @Valid CommentPostDto commentPostDto) { - String userEmail = extractedUsername(request); - Comment findComment = commentService.findComment(commentId); + Member member = memberService.findVerifiedMemberById(memberId); + Comment comment = commentService.findComment(commentId); - // 다른 회원의 댓글을 수정할 수 없음 - if(!findComment.getMember().getEmail().equals(userEmail)){ + if (!comment.getMember().getMemberId().equals(memberId)) { throw new BusinessLogicException(ExceptionCode.NOT_AUTHOR); } - Comment comment = new Comment(); comment.setCommentId(commentId); - comment.setCommentContent(postDto.getCommentContent()); - Comment updatedComment = commentService.updateComment(comment); - return new ResponseEntity<>(new DataResponseDto<>(mapper.commentToCommentResponseDto(updatedComment)),HttpStatus.OK); + comment.setMember(member); + comment.setCommentContent(commentPostDto.getCommentContent()); + + CommentResponseDto commentResponseDto = mapper.commentToCommentResponseDto(comment); + + return ResponseEntity.ok(new DataResponseDto<>(commentResponseDto)); } @GetMapping("/{comment-id}") - public ResponseEntity getComment(@PathVariable("comment-id")@Positive long commentId){ + public ResponseEntity> getComment(@PathVariable("comment-id") @Positive long commentId) { CommentResponseDto response = mapper.commentToCommentResponseDto(commentService.findComment(commentId)); - return new ResponseEntity<>(new DataResponseDto<>(response), HttpStatus.OK); + return ResponseEntity.ok(new DataResponseDto<>(response)); } - @GetMapping - public ResponseEntity getComment(@Positive @RequestParam(required = false, defaultValue = "1") int page, - @Positive @RequestParam(required = false, defaultValue = "10") int size){ - Page commentPage = commentService.findComments(page-1, size); + @GetMapping() + public ResponseEntity> getComment(@Positive @RequestParam(required = false, defaultValue = "1") int page, + @Positive @RequestParam(required = false, defaultValue = "10") int size) { + Page commentPage = commentService.findComments(page - 1, size); List comments = commentPage.getContent(); - return new ResponseEntity<>(new MultiResponseDto<>( - mapper.commentsToCommentResponseDtos(comments),commentPage), HttpStatus.OK); + + List commentResponseDtos = mapper.commentsToCommentResponseDtos(comments); + + return ResponseEntity.ok(new MultiResponseDto<>(commentResponseDtos, commentPage)); } @DeleteMapping("/delete/{comment-id}") - public ResponseEntity deleteCommnet(@PathVariable("comment-id")@Positive long commentId){ + public ResponseEntity deleteCommnet(@PathVariable("comment-id") @Positive long commentId) { commentService.deleteComment(commentId); - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } - - private String extractedUsername(HttpServletRequest request) { - String authorization = request.getHeader("authorization"); - String substring = authorization.substring(7); - log.info("subString = {}", substring); - String secretKey = jwtTokenizer.getSecretKey(); - Jws claims = jwtTokenizer.getClaims(substring, jwtTokenizer.encodeBase64SecretKey(secretKey)); - return String.valueOf(claims.getBody().get("username")); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); } } diff --git a/server/src/main/java/com/main36/picha/domain/comment/dto/CommentDto.java b/server/src/main/java/com/main36/picha/domain/comment/dto/CommentDto.java deleted file mode 100644 index 9ab6c924..00000000 --- a/server/src/main/java/com/main36/picha/domain/comment/dto/CommentDto.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.main36.picha.domain.comment.dto; - -import lombok.Builder; -import lombok.Data; - -@Data -public class CommentDto { - private String commentContent; -} diff --git a/server/src/main/java/com/main36/picha/domain/comment/dto/CommentPostDto.java b/server/src/main/java/com/main36/picha/domain/comment/dto/CommentPostDto.java index d10aeb03..036d05f1 100644 --- a/server/src/main/java/com/main36/picha/domain/comment/dto/CommentPostDto.java +++ b/server/src/main/java/com/main36/picha/domain/comment/dto/CommentPostDto.java @@ -1,13 +1,13 @@ package com.main36.picha.domain.comment.dto; -import lombok.Builder; import lombok.Data; -import lombok.Getter; import javax.validation.constraints.NotBlank; @Data public class CommentPostDto { + + @NotBlank(message = "댓글 내용을 입력해주세요.") private String commentContent; } diff --git a/server/src/main/java/com/main36/picha/domain/comment/entity/Comment.java b/server/src/main/java/com/main36/picha/domain/comment/entity/Comment.java index 33200121..e8313356 100644 --- a/server/src/main/java/com/main36/picha/domain/comment/entity/Comment.java +++ b/server/src/main/java/com/main36/picha/domain/comment/entity/Comment.java @@ -6,12 +6,11 @@ import lombok.*; import javax.persistence.*; - @Getter @Setter @Builder @AllArgsConstructor -@NoArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity public class Comment extends Auditable { @@ -27,6 +26,7 @@ public class Comment extends Auditable { @JoinColumn(name = "member_id") private Member member; + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "post_id") private Post post; diff --git a/server/src/main/java/com/main36/picha/domain/comment/mapper/CommentMapper.java b/server/src/main/java/com/main36/picha/domain/comment/mapper/CommentMapper.java index 4f81a5fc..85f756dd 100644 --- a/server/src/main/java/com/main36/picha/domain/comment/mapper/CommentMapper.java +++ b/server/src/main/java/com/main36/picha/domain/comment/mapper/CommentMapper.java @@ -1,5 +1,6 @@ package com.main36.picha.domain.comment.mapper; +import com.main36.picha.domain.comment.dto.CommentPostDto; import com.main36.picha.domain.comment.dto.CommentResponseDto; import com.main36.picha.domain.comment.entity.Comment; import org.mapstruct.Mapper; @@ -9,6 +10,9 @@ @Mapper(componentModel = "spring") public interface CommentMapper { + + Comment CommentDtoToComment(CommentPostDto commentPostDto); + @Mapping(target = "username", source = "member.username") @Mapping(target = "memberId", source = "member.memberId") @Mapping(target = "memberPicture", source = "member.picture") diff --git a/server/src/main/java/com/main36/picha/domain/comment/service/CommentService.java b/server/src/main/java/com/main36/picha/domain/comment/service/CommentService.java index ef2f3678..9bb6c68a 100644 --- a/server/src/main/java/com/main36/picha/domain/comment/service/CommentService.java +++ b/server/src/main/java/com/main36/picha/domain/comment/service/CommentService.java @@ -24,15 +24,6 @@ public Comment createComment(Comment comment){ return commentRepository.save(comment); } - public Comment updateComment(Comment comment){ - Comment findComment = findVerifiedComment(comment.getCommentId()); - - // 댓글 내용만 변경 가능 - Optional.ofNullable(comment.getCommentContent()) - .ifPresent(findComment::setCommentContent); - return commentRepository.save(findComment); - } - public Comment findComment(long commentId){ return findVerifiedComment(commentId); } diff --git a/server/src/main/java/com/main36/picha/domain/hashtag/entity/HashTag.java b/server/src/main/java/com/main36/picha/domain/hashtag/entity/HashTag.java index a995da39..52fff326 100644 --- a/server/src/main/java/com/main36/picha/domain/hashtag/entity/HashTag.java +++ b/server/src/main/java/com/main36/picha/domain/hashtag/entity/HashTag.java @@ -2,16 +2,13 @@ import com.main36.picha.global.audit.Auditable; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; +import lombok.*; import javax.persistence.*; @Getter @Builder -@NoArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor @Entity public class HashTag extends Auditable { diff --git a/server/src/main/java/com/main36/picha/domain/member/controller/MemberController.java b/server/src/main/java/com/main36/picha/domain/member/controller/MemberController.java index 6f29317d..11144824 100644 --- a/server/src/main/java/com/main36/picha/domain/member/controller/MemberController.java +++ b/server/src/main/java/com/main36/picha/domain/member/controller/MemberController.java @@ -56,20 +56,21 @@ public ResponseEntity getToken(@RequestParam String access_token, log.info("at={}", access_token); log.info("rt={}", refresh_token); String at = "Bearer " + access_token; -// Token tokenBuilder = -// Token.builder() -// .accessToken(at) -// .refreshToken(refresh_token) -// .build(); + // 1. 헤더에 담아서 보내기 HttpHeaders headers = new HttpHeaders(); headers.set("Authorization", at); headers.set("RefreshToken", refresh_token); -// headers.add(HttpHeaders.AUTHORIZATION, at); - return ResponseEntity.ok().headers(headers).body("SUCCESS"); - } + // 2. 토큰 엔티티에 담아 보내기 +// Token tokenBuilder = +// Token.builder() +// .accessToken(at) +// .refreshToken(refresh_token) +// .build(); +// return ResponseEntity.ok(tokenBuilder); + } @PatchMapping("/edit/{member-id}") public ResponseEntity patchMember(@PathVariable("member-id") @Positive long memberId, @@ -83,12 +84,6 @@ public ResponseEntity patchMember(@PathVariable("member-id") @P ); } -// @GetMapping("/token") -// public ResponseEntity getOauth2MemberToken() { -// Member member = memberService.findMember() -// return new ResponseEntity(HttpStatus.OK); -// } - // 멤버 프로필 조회(홈) // TODO: 스프링 시큐리티 적용 @GetMapping("/{member-id}/{email}") diff --git a/server/src/main/java/com/main36/picha/domain/member/mapper/MemberMapper.java b/server/src/main/java/com/main36/picha/domain/member/mapper/MemberMapper.java index c301f45d..38d451fc 100644 --- a/server/src/main/java/com/main36/picha/domain/member/mapper/MemberMapper.java +++ b/server/src/main/java/com/main36/picha/domain/member/mapper/MemberMapper.java @@ -2,14 +2,10 @@ import com.main36.picha.domain.member.dto.*; import com.main36.picha.domain.member.entity.Member; -import com.main36.picha.domain.post.dto.PostResponseDto; import com.main36.picha.domain.post.entity.Post; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.MappingConstants; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.data.domain.Auditable; -import org.springframework.stereotype.Component; import java.util.List; @@ -27,11 +23,9 @@ public interface MemberMapper { @Mapping(target = "totalMySaves", expression = "java(member.getSaves().size())") ProfileHomeDto memberToProfileHomeDto(Member member); - List postListToPostResponseDtos(List posts); @Mapping(target = "password", constant = "") @Mapping(target = "phoneNumber", constant = "") @Mapping(target = "address", constant = "") - @Mapping(target = "memberTitle", constant = "") Member oauthMemberDtoToMember(OauthMemberDto oauthMemberDto); diff --git a/server/src/main/java/com/main36/picha/domain/post/controller/PostController.java b/server/src/main/java/com/main36/picha/domain/post/controller/PostController.java index b9d088cc..f016dea5 100644 --- a/server/src/main/java/com/main36/picha/domain/post/controller/PostController.java +++ b/server/src/main/java/com/main36/picha/domain/post/controller/PostController.java @@ -3,6 +3,7 @@ import com.main36.picha.domain.attraction.entity.Attraction; import com.main36.picha.domain.attraction.service.AttractionService; +import com.main36.picha.domain.comment.entity.Comment; import com.main36.picha.domain.member.entity.Member; import com.main36.picha.domain.member.service.MemberService; import com.main36.picha.domain.post.dto.*; @@ -17,6 +18,7 @@ import org.springframework.data.domain.Page; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.core.parameters.P; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -24,6 +26,8 @@ import javax.validation.Valid; import javax.validation.constraints.Positive; +import java.rmi.activation.ActivationGroupDesc; +import java.util.ArrayList; import java.util.List; @RestController @@ -40,59 +44,76 @@ public class PostController { private final JwtTokenizer jwtTokenizer; // 로그인 객체 찾기 - @PostMapping("/register/{attraction-id}") - public ResponseEntity> registerPost(HttpServletRequest request, - @PathVariable("attraction-id") long attractionId, - @Valid @RequestBody PostRegisterDto postRegisterDto) { - String username = jwtTokenizer.getUsername(request); - Member member = memberService.findMember(username); + @PostMapping("/register/{member-id}/{attraction-id}") + public ResponseEntity> registerPost(@PathVariable("member-id") @Positive long memberId, + @PathVariable("attraction-id") @Positive long attractionId, + @Valid @RequestBody PostRegisterDto postRegisterDto) { + Member member = memberService.findVerifiedMemberById(memberId); Attraction attraction = attractionService.findAttraction(attractionId); + List comments = new ArrayList<>(); + attraction.setNumOfPosts(attraction.getNumOfPosts() + 1); - attraction.setNumOfPosts(attraction.getNumOfPosts()+1); - - Post post = mapper.postRegisterDtoToPost(postRegisterDto, member, attraction); - + Post post = mapper.postRegisterDtoToPost(postRegisterDto, member, attraction, comments); Post createPost = postService.createPost(post); - PostRegisterResponseDto postRegisterResponseDto = mapper.postToPostRegisterResponseDto(createPost); - - return new ResponseEntity<>(new DataResponseDto<>(postRegisterResponseDto), HttpStatus.CREATED); + return new ResponseEntity<>(new DataResponseDto<>(mapper.postToSingleResponseDto(createPost)), HttpStatus.CREATED); } - @PatchMapping("/edit/{post-id}") - public ResponseEntity> editPost(@Positive @PathVariable("post-id") long postId, - @Valid @RequestBody PostPatchRequestDto postPatchRequestDto) { - postPatchRequestDto.setPostId(postId); - Post post = postService.updatePost(mapper.postPatchDtoToPost(postPatchRequestDto)); - PostRegisterResponseDto postRegisterResponseDto = mapper.postToPostRegisterResponseDto(post); + @PatchMapping("/edit/{member-id}/{post-id}") + public ResponseEntity> editPost(@PathVariable("member-id") @Positive long memberId, + @PathVariable("post-id") @Positive long postId, + @Valid @RequestBody PostPatchDto postPatchDto) { + postPatchDto.setPostId(postId); + Post post = postService.updatePost(mapper.postPatchDtoToPost(postPatchDto)); - return ResponseEntity.ok(new DataResponseDto<>(postRegisterResponseDto)); + return ResponseEntity.ok(new DataResponseDto<>(mapper.postToSingleResponseDto(post))); } - // 포스트 단일 조회 @GetMapping("/{post-id}") - public ResponseEntity> getPost(@Positive @PathVariable("post-id") long postId) { + public ResponseEntity> getPost(@PathVariable("post-id") @Positive long postId) { Post post = postService.findPost(postId); - PostResponseDto postResponseDto = mapper.postToPostResponseDto(post); - return ResponseEntity.ok(new DataResponseDto<>(postResponseDto)); + return ResponseEntity.ok(new DataResponseDto<>(mapper.postToSingleResponseDto(post))); + } + + @GetMapping("/home") + public ResponseEntity getHomePosts(@RequestParam(defaultValue = "postId", required = false) String sort, + @RequestParam(defaultValue = "1", required = false) @Positive int page, + @RequestParam(defaultValue = "8", required = false) @Positive int size) { + switch (sort) { + case "latest": + sort = "postId"; + break; + case "likes": + sort = "likes"; + break; + case "views": + sort = "views"; + break; + } + + Page allPostsBySort = postService.findAllPostsBySort(page - 1, size, sort); + List content = allPostsBySort.getContent(); + + return new ResponseEntity<>(new MultiResponseDto<>( + mapper.postListToPostHomeResponseDtoList(content), allPostsBySort), HttpStatus.OK); + } - // 포스트 페이지(전체 조회) @GetMapping() - public ResponseEntity getPosts(@RequestParam(defaultValue = "newest", required = false) String tab, - @RequestParam(defaultValue = "1", required = false) int page, - @RequestParam(defaultValue = "9", required = false) int size) { - Page postsByNewestByPage = postService.findAllPostsByNewest(page - 1, size); + public ResponseEntity getAllPosts(@RequestParam(defaultValue = "newest", required = false) String sort, + @RequestParam(defaultValue = "1", required = false) @Positive int page, + @RequestParam(defaultValue = "9", required = false) @Positive int size) { + Page postsByNewestByPage = postService.findAllPostsBySort(page - 1, size, sort); List postsByNewest = postsByNewestByPage.getContent(); return new ResponseEntity<>(new MultiResponseDto<>( mapper.postListToPostPageResponseDtoList(postsByNewest), postsByNewestByPage), HttpStatus.OK); } - // 포스트 삭제 - @DeleteMapping("delete/{post-id}") - public ResponseEntity deletePost(@PathVariable("post-id") long postId) { + @DeleteMapping("delete/{member-id}/{post-id}") + public ResponseEntity deletePost(@PathVariable("member-id") long memberId, + @PathVariable("post-id") long postId) { return new ResponseEntity<>(HttpStatus.NO_CONTENT); } } diff --git a/server/src/main/java/com/main36/picha/domain/post/dto/PostDetailPageResponseDto.java b/server/src/main/java/com/main36/picha/domain/post/dto/PostDetailPageResponseDto.java deleted file mode 100644 index edda8fa5..00000000 --- a/server/src/main/java/com/main36/picha/domain/post/dto/PostDetailPageResponseDto.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.main36.picha.domain.post.dto; - -import com.main36.picha.domain.comment.dto.CommentResponseDto; -import lombok.Builder; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -@Data -@Builder -public class PostDetailPageResponseDto { - private long postId; - private String postTitle; - private long attractionId; - private String attractionAddress; - private String content; - // private List hashTagList; - private int views; - private int likes; - private String username; - private String picture; - private List comments; - private LocalDateTime createdAt; - -} diff --git a/server/src/main/java/com/main36/picha/domain/post/dto/PostHomeDto.java b/server/src/main/java/com/main36/picha/domain/post/dto/PostHomeDto.java index 8798f5ec..40e9bac3 100644 --- a/server/src/main/java/com/main36/picha/domain/post/dto/PostHomeDto.java +++ b/server/src/main/java/com/main36/picha/domain/post/dto/PostHomeDto.java @@ -9,10 +9,10 @@ @Data @Builder public class PostHomeDto { - + private Long postId; private Long memberId; private String username; - private String userImage; + private String picture; private int views; private int likes; private String postTitle; diff --git a/server/src/main/java/com/main36/picha/domain/post/dto/PostPatchRequestDto.java b/server/src/main/java/com/main36/picha/domain/post/dto/PostPatchDto.java similarity index 78% rename from server/src/main/java/com/main36/picha/domain/post/dto/PostPatchRequestDto.java rename to server/src/main/java/com/main36/picha/domain/post/dto/PostPatchDto.java index bc0e9cc7..ec7b5b35 100644 --- a/server/src/main/java/com/main36/picha/domain/post/dto/PostPatchRequestDto.java +++ b/server/src/main/java/com/main36/picha/domain/post/dto/PostPatchDto.java @@ -6,13 +6,12 @@ import javax.validation.constraints.NotBlank; @Data -@Builder -public class PostPatchRequestDto { +public class PostPatchDto { private Long postId; @NotBlank(message = "제목을 입력해주세요.") private String postTitle; private String postContent; -// private String[] hashtags; + private String hashTagContent; } diff --git a/server/src/main/java/com/main36/picha/domain/post/dto/PostPatchResponseDto.java b/server/src/main/java/com/main36/picha/domain/post/dto/PostPatchResponseDto.java deleted file mode 100644 index d704f741..00000000 --- a/server/src/main/java/com/main36/picha/domain/post/dto/PostPatchResponseDto.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.main36.picha.domain.post.dto; - -import com.main36.picha.domain.comment.dto.CommentResponseDto; - -import java.time.LocalDateTime; -import java.util.List; - -public class PostPatchResponseDto { - private Long memberId; - private Long postId; - private String attractionName; - private String attractionAddress; - private String postTitle; - private String postContent; - private int views; - private int likes; - - //TODO : HashTag -// private List hashtags; - - private List comments; - private LocalDateTime createdAt; - private LocalDateTime modifiedAt; -} diff --git a/server/src/main/java/com/main36/picha/domain/post/dto/PostRegisterDto.java b/server/src/main/java/com/main36/picha/domain/post/dto/PostRegisterDto.java index 5592bfe1..f6e79516 100644 --- a/server/src/main/java/com/main36/picha/domain/post/dto/PostRegisterDto.java +++ b/server/src/main/java/com/main36/picha/domain/post/dto/PostRegisterDto.java @@ -1,16 +1,15 @@ package com.main36.picha.domain.post.dto; -import lombok.Builder; -import lombok.Data; +import lombok.*; + import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Null; @Data -@Builder public class PostRegisterDto { @NotBlank(message = "제목을 입력해주세요.") private String postTitle; private String postContent; - private String hashtags; - + private String hashTagContent; } diff --git a/server/src/main/java/com/main36/picha/domain/post/dto/PostRegisterResponseDto.java b/server/src/main/java/com/main36/picha/domain/post/dto/PostRegisterResponseDto.java deleted file mode 100644 index 54b5f1bd..00000000 --- a/server/src/main/java/com/main36/picha/domain/post/dto/PostRegisterResponseDto.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.main36.picha.domain.post.dto; - -import lombok.Builder; -import lombok.Data; - -import java.time.LocalDateTime; - -@Data -@Builder -public class PostRegisterResponseDto { - private Long memberId; - private Long postId; - private String attractionName; - private String attractionAddress; - private String postTitle; - private String postContent; - private int views; - private int likes; - private LocalDateTime createdAt; - private LocalDateTime modifiedAt; -} diff --git a/server/src/main/java/com/main36/picha/domain/post/dto/PostResponseDto.java b/server/src/main/java/com/main36/picha/domain/post/dto/SinglePostResponseDto.java similarity index 69% rename from server/src/main/java/com/main36/picha/domain/post/dto/PostResponseDto.java rename to server/src/main/java/com/main36/picha/domain/post/dto/SinglePostResponseDto.java index 2d7638bc..eca2f5c9 100644 --- a/server/src/main/java/com/main36/picha/domain/post/dto/PostResponseDto.java +++ b/server/src/main/java/com/main36/picha/domain/post/dto/SinglePostResponseDto.java @@ -1,32 +1,31 @@ package com.main36.picha.domain.post.dto; - import com.main36.picha.domain.comment.dto.CommentResponseDto; -import lombok.AllArgsConstructor; +import lombok.AccessLevel; import lombok.Builder; import lombok.Data; +import lombok.Setter; import java.time.LocalDateTime; import java.util.List; @Data +@Setter(AccessLevel.NONE) @Builder -@AllArgsConstructor -public class PostResponseDto { - private Long postId; +public class SinglePostResponseDto { + private long postId; private String postTitle; private String postContent; - private Long memberId; - private String username; - private String picture; - private Long attractionId; - private String attractionName; + private String hashTagContent; + private long attractionId; private String attractionAddress; + private String attractionName; private int views; private int likes; - - //TODO : HashTag -// private List hashtags; + private String username; + private String picture; private List comments; private LocalDateTime createdAt; + private LocalDateTime modifiedAt; + } diff --git a/server/src/main/java/com/main36/picha/domain/post/entity/Post.java b/server/src/main/java/com/main36/picha/domain/post/entity/Post.java index 367dd8f2..3adbae8e 100644 --- a/server/src/main/java/com/main36/picha/domain/post/entity/Post.java +++ b/server/src/main/java/com/main36/picha/domain/post/entity/Post.java @@ -13,7 +13,7 @@ @Getter -@NoArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor @Builder @Entity @@ -26,18 +26,20 @@ public class Post extends Auditable { @Column(name = "post_title", nullable = false) private String postTitle; - private String hashTagContent; - @Setter @Lob @Column(name = "post_content") private String postContent; @Setter - @Column(name = "views", columnDefinition = "integer default 0", nullable = false) + @Column(name = "hash_tag_content") + private String hashTagContent; + + @Setter + @Column(name = "views", nullable = false, columnDefinition = "integer default 0") private int views; - @Column(name = "likes", columnDefinition = "integer default 0", nullable = false ) + @Column(name = "likes", nullable = false, columnDefinition = "integer default 0" ) private int likes; @ManyToOne diff --git a/server/src/main/java/com/main36/picha/domain/post/mapper/PostMapper.java b/server/src/main/java/com/main36/picha/domain/post/mapper/PostMapper.java index 0bc2cd6f..8e769c3f 100644 --- a/server/src/main/java/com/main36/picha/domain/post/mapper/PostMapper.java +++ b/server/src/main/java/com/main36/picha/domain/post/mapper/PostMapper.java @@ -3,6 +3,7 @@ import com.main36.picha.domain.attraction.entity.Attraction; import com.main36.picha.domain.comment.dto.CommentResponseDto; +import com.main36.picha.domain.comment.entity.Comment; import com.main36.picha.domain.member.entity.Member; import com.main36.picha.domain.post.dto.*; import com.main36.picha.domain.post.entity.Post; @@ -17,47 +18,48 @@ public interface PostMapper { // 포스트 등록 - default Post postRegisterDtoToPost(PostRegisterDto postRegisterDto, Member member, Attraction attraction) { - if ( postRegisterDto == null && member == null && attraction == null ) { + default Post postRegisterDtoToPost(PostRegisterDto postRegisterDto, Member member, Attraction attraction, List comments) { + if (postRegisterDto == null && member == null && attraction == null && comments == null) { return null; } - return Post.builder() - .postContent(postRegisterDto.getPostContent()) - .postTitle(postRegisterDto.getPostTitle()) - .member(member) - .attraction(attraction) - .build(); + assert postRegisterDto != null; + + Post.PostBuilder post = Post.builder(); + post.postTitle(postRegisterDto.getPostTitle()); + post.postContent(postRegisterDto.getPostContent()); + post.hashTagContent(postRegisterDto.getHashTagContent()); + + post.member(member); + post.attraction(attraction); + post.comments(comments); + + return post.build(); } // 포스트 수정 - Post postPatchDtoToPost(PostPatchRequestDto postPatchRequestDto); + Post postPatchDtoToPost(PostPatchDto postPatchDto); - // 포스트 등록 및 수정 리스폰스 - @Mapping(target = "memberId", expression = "java(post.getMember().getMemberId())") - @Mapping(target = "attractionAddress", expression = "java(post.getAttraction().getAttractionAddress())") - @Mapping(target = "attractionName", expression = "java(post.getAttraction().getAttractionName())") - PostRegisterResponseDto postToPostRegisterResponseDto(Post post); // 포스트 단일 조회 리스폰스 - default PostResponseDto postToPostResponseDto(Post post) { + default SinglePostResponseDto postToSingleResponseDto(Post post) { if (post == null) { return null; } - return PostResponseDto.builder() + return SinglePostResponseDto.builder() .postId(post.getPostId()) .postTitle(post.getPostTitle()) .postContent(post.getPostContent()) - .memberId(post.getMember().getMemberId()) - .username(post.getMember().getUsername()) - .picture(post.getMember().getPicture()) + .hashTagContent(post.getHashTagContent()) .attractionId(post.getAttraction().getAttractionId()) - .attractionName(post.getAttraction().getAttractionName()) .attractionAddress(post.getAttraction().getAttractionAddress()) + .attractionName(post.getAttraction().getAttractionName()) .views(post.getViews()) .likes(post.getLikes()) + .username(post.getMember().getUsername()) + .picture(post.getMember().getPicture()) .comments(post.getComments().stream() .map(comment -> { return CommentResponseDto.builder() @@ -71,17 +73,40 @@ default PostResponseDto postToPostResponseDto(Post post) { .build(); }).collect(Collectors.toList())) .createdAt(post.getCreatedAt()) + .modifiedAt(post.getModifiedAt()) .build(); - } @Mapping(target = "memberId", expression = "java(post.getMember().getMemberId())") @Mapping(target = "username", expression = "java(post.getMember().getUsername())") - @Mapping(target = "userImage", expression = "java(post.getMember().getPicture())") + @Mapping(target = "picture", expression = "java(post.getMember().getPicture())") PostHomeDto postToPostHomeDto(Post post); + default List postListToPostHomeResponseDtoList(List postList) { + if (postList == null) { + return null; + } + + return postList.stream() + .map(post -> { + return PostHomeDto.builder() + .postId(post.getPostId()) + .memberId(post.getMember().getMemberId()) + .username(post.getMember().getUsername()) + .picture(post.getMember().getPicture()) + .views(post.getViews()) + .likes(post.getLikes()) + .postTitle(post.getPostTitle()) + .createdAt(post.getCreatedAt()) + .modifiedAt(post.getModifiedAt()) + .build(); + }).collect(Collectors.toList()); + } + + + // 포스트 페이지(전체 조회) 리스폰스 - default List postListToPostPageResponseDtoList(List postList) { + default List postListToPostPageResponseDtoList(List postList) { if (postList == null) { return null; @@ -89,12 +114,13 @@ default List postListToPostPageResponseDtoList(List

{ - return PostDetailPageResponseDto.builder() + return SinglePostResponseDto.builder() .postId(post.getPostId()) .postTitle(post.getPostTitle()) + .postContent(post.getPostContent()) + .hashTagContent(post.getHashTagContent()) .attractionId(post.getAttraction().getAttractionId()) .attractionAddress(post.getAttraction().getAttractionAddress()) - .content(post.getPostContent()) .views(post.getViews()) .likes(post.getLikes()) .username(post.getMember().getUsername()) @@ -112,6 +138,7 @@ default List postListToPostPageResponseDtoList(List

findAllPostsByNewest(int page, int size) { - Pageable pageable = PageRequest.of(page, size, Sort.by("postId").descending()); + public Page findAllPostsBySort(int page, int size, String sort) { + Pageable pageable = PageRequest.of(page, size, Sort.by(sort).descending()); return postRepository.findAll(pageable); } diff --git a/server/src/main/java/com/main36/picha/domain/post_likes/entity/PostLikes.java b/server/src/main/java/com/main36/picha/domain/post_likes/entity/PostLikes.java index 5a805b0c..f40a84ca 100644 --- a/server/src/main/java/com/main36/picha/domain/post_likes/entity/PostLikes.java +++ b/server/src/main/java/com/main36/picha/domain/post_likes/entity/PostLikes.java @@ -3,15 +3,12 @@ import com.main36.picha.domain.member.entity.Member; import com.main36.picha.domain.post.entity.Post; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; +import lombok.*; import javax.persistence.*; @Getter -@NoArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor @Entity public class PostLikes { diff --git a/server/src/main/java/com/main36/picha/global/auth/handler/OAuth2MemberSuccessHandler.java b/server/src/main/java/com/main36/picha/global/auth/handler/OAuth2MemberSuccessHandler.java index c8aad515..52e40414 100644 --- a/server/src/main/java/com/main36/picha/global/auth/handler/OAuth2MemberSuccessHandler.java +++ b/server/src/main/java/com/main36/picha/global/auth/handler/OAuth2MemberSuccessHandler.java @@ -106,8 +106,8 @@ private URI createURI(String accessToken, String refreshToken) { return UriComponentsBuilder .newInstance() .scheme("http") -// .host( "pikcha36.o-r.kr") - .host("localhost") + .host( "pikcha36.o-r.kr") +// .host("localhost") .port(8080) .path("/users/token") .queryParams(queryParams) diff --git a/server/src/main/java/com/main36/picha/global/config/SecurityConfiguration.java b/server/src/main/java/com/main36/picha/global/config/SecurityConfiguration.java index 8d74ee21..39c65bec 100644 --- a/server/src/main/java/com/main36/picha/global/config/SecurityConfiguration.java +++ b/server/src/main/java/com/main36/picha/global/config/SecurityConfiguration.java @@ -4,8 +4,8 @@ import com.main36.picha.domain.member.mapper.MemberMapper; import com.main36.picha.domain.member.repository.MemberRepository; import com.main36.picha.domain.member.service.MemberService; -import com.main36.picha.global.auth.filter.JwtAuthenticationFilter; +import com.main36.picha.global.auth.filter.JwtAuthenticationFilter; import com.main36.picha.global.auth.filter.JwtVerificationFilter; import com.main36.picha.global.auth.handler.*; import com.main36.picha.global.auth.jwt.JwtTokenizer; @@ -13,14 +13,11 @@ import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.crypto.factory.PasswordEncoderFactories; -import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter; import org.springframework.security.web.SecurityFilterChain; import org.springframework.web.cors.CorsConfiguration; @@ -40,7 +37,6 @@ public class SecurityConfiguration { private final CustomAuthorityUtils authorityUtils; private final MemberService memberService; private final MemberMapper mapper; - private final MemberRepository memberRepository; @Bean @@ -61,8 +57,9 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .apply(new CustomFilterConfigure()) .and() .authorizeHttpRequests(authorize -> authorize - .mvcMatchers("/", "/users/signup", "/login/**", "/login", "/users/token/**", "/main", "/attractions", "/attractions/**", "/posts", "/posts/*").permitAll() - .mvcMatchers("admin").hasRole("ADMIN") + .antMatchers("/", "/users/signup", "/users/login", "/users/token/**", + "/main", "/attractions", "/attractions/**", "/posts", "/posts/*", "/comments", "comments/*").permitAll() + .antMatchers("admin").hasRole("ADMIN") .requestMatchers(toH2Console()).permitAll() .anyRequest().authenticated() ) From 2be3625184872ad27aba76c482ad3db7bf9a0078 Mon Sep 17 00:00:00 2001 From: eastmeet Date: Thu, 19 Jan 2023 03:48:09 +0900 Subject: [PATCH 2/4] feat: Add post sort(#34) --- .../post/controller/PostController.java | 68 ++++++++++++++----- .../picha/domain/post/dto/PostPatchDto.java | 2 + .../picha/domain/post/mapper/PostMapper.java | 26 +------ .../domain/post/service/PostService.java | 17 ++++- 4 files changed, 68 insertions(+), 45 deletions(-) diff --git a/server/src/main/java/com/main36/picha/domain/post/controller/PostController.java b/server/src/main/java/com/main36/picha/domain/post/controller/PostController.java index f016dea5..09a00bc9 100644 --- a/server/src/main/java/com/main36/picha/domain/post/controller/PostController.java +++ b/server/src/main/java/com/main36/picha/domain/post/controller/PostController.java @@ -11,6 +11,8 @@ import com.main36.picha.domain.post.mapper.PostMapper; import com.main36.picha.domain.post.service.PostService; import com.main36.picha.global.auth.jwt.JwtTokenizer; +import com.main36.picha.global.exception.BusinessLogicException; +import com.main36.picha.global.exception.ExceptionCode; import com.main36.picha.global.response.DataResponseDto; import com.main36.picha.global.response.MultiResponseDto; import lombok.RequiredArgsConstructor; @@ -41,32 +43,36 @@ public class PostController { private final PostMapper mapper; private final MemberService memberService; private final AttractionService attractionService; - private final JwtTokenizer jwtTokenizer; - - // 로그인 객체 찾기 @PostMapping("/register/{member-id}/{attraction-id}") public ResponseEntity> registerPost(@PathVariable("member-id") @Positive long memberId, @PathVariable("attraction-id") @Positive long attractionId, @Valid @RequestBody PostRegisterDto postRegisterDto) { - Member member = memberService.findVerifiedMemberById(memberId); - Attraction attraction = attractionService.findAttraction(attractionId); - List comments = new ArrayList<>(); - attraction.setNumOfPosts(attraction.getNumOfPosts() + 1); - - Post post = mapper.postRegisterDtoToPost(postRegisterDto, member, attraction, comments); - Post createPost = postService.createPost(post); - - return new ResponseEntity<>(new DataResponseDto<>(mapper.postToSingleResponseDto(createPost)), HttpStatus.CREATED); + Post.PostBuilder postBuilder = Post.builder(); + + Post post = postService.createPost( + postBuilder + .postTitle(postRegisterDto.getPostTitle()) + .postContent(postRegisterDto.getPostContent()) + .hashTagContent(postRegisterDto.getHashTagContent()) + .member(memberService.findVerifiedMemberById(memberId)) + .attraction(attractionService.findAttraction(attractionId)) + .comments(new ArrayList<>()) + .build() + ); + + return new ResponseEntity<>(new DataResponseDto<>(mapper.postToSingleResponseDto(post)), HttpStatus.CREATED); } @PatchMapping("/edit/{member-id}/{post-id}") public ResponseEntity> editPost(@PathVariable("member-id") @Positive long memberId, @PathVariable("post-id") @Positive long postId, @Valid @RequestBody PostPatchDto postPatchDto) { - postPatchDto.setPostId(postId); - Post post = postService.updatePost(mapper.postPatchDtoToPost(postPatchDto)); + verifiedById(memberId, postId); - return ResponseEntity.ok(new DataResponseDto<>(mapper.postToSingleResponseDto(post))); + postPatchDto.setPostId(memberId); + Post updatePost = postService.updatePost(mapper.postPatchDtoToPost(postPatchDto)); + + return ResponseEntity.ok(new DataResponseDto<>(mapper.postToSingleResponseDto(updatePost))); } @GetMapping("/{post-id}") @@ -77,11 +83,11 @@ public ResponseEntity> getPost(@PathVaria } @GetMapping("/home") - public ResponseEntity getHomePosts(@RequestParam(defaultValue = "postId", required = false) String sort, + public ResponseEntity getHomePosts(@RequestParam(defaultValue = "newest", required = false) String sort, @RequestParam(defaultValue = "1", required = false) @Positive int page, @RequestParam(defaultValue = "8", required = false) @Positive int size) { switch (sort) { - case "latest": + case "newest": sort = "postId"; break; case "likes": @@ -104,6 +110,17 @@ public ResponseEntity getHomePosts(@RequestParam(defaultValue public ResponseEntity getAllPosts(@RequestParam(defaultValue = "newest", required = false) String sort, @RequestParam(defaultValue = "1", required = false) @Positive int page, @RequestParam(defaultValue = "9", required = false) @Positive int size) { + switch (sort) { + case "newest": + sort = "postId"; + break; + case "likes": + sort = "likes"; + break; + case "views": + sort = "views"; + break; + } Page postsByNewestByPage = postService.findAllPostsBySort(page - 1, size, sort); List postsByNewest = postsByNewestByPage.getContent(); @@ -111,9 +128,24 @@ public ResponseEntity getAllPosts(@RequestParam(defaultValue = mapper.postListToPostPageResponseDtoList(postsByNewest), postsByNewestByPage), HttpStatus.OK); } - @DeleteMapping("delete/{member-id}/{post-id}") + @DeleteMapping("/delete/{member-id}/{post-id}") public ResponseEntity deletePost(@PathVariable("member-id") long memberId, @PathVariable("post-id") long postId) { + + Post post = verifiedById(memberId, postId); + postService.erasePost(post); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); } + + private Post verifiedById(long memberId, long postId) { + Post post = postService.findPostNoneSetView(postId); + + if (!post.getMember().getMemberId().equals(memberId)) { + throw new BusinessLogicException(ExceptionCode.NOT_AUTHOR); + } + + return post; + } + } diff --git a/server/src/main/java/com/main36/picha/domain/post/dto/PostPatchDto.java b/server/src/main/java/com/main36/picha/domain/post/dto/PostPatchDto.java index ec7b5b35..8c0b0430 100644 --- a/server/src/main/java/com/main36/picha/domain/post/dto/PostPatchDto.java +++ b/server/src/main/java/com/main36/picha/domain/post/dto/PostPatchDto.java @@ -12,6 +12,8 @@ public class PostPatchDto { @NotBlank(message = "제목을 입력해주세요.") private String postTitle; private String postContent; + + //TODO: 정규표현식 적용 -> [] private String hashTagContent; } diff --git a/server/src/main/java/com/main36/picha/domain/post/mapper/PostMapper.java b/server/src/main/java/com/main36/picha/domain/post/mapper/PostMapper.java index 8e769c3f..7a0590f7 100644 --- a/server/src/main/java/com/main36/picha/domain/post/mapper/PostMapper.java +++ b/server/src/main/java/com/main36/picha/domain/post/mapper/PostMapper.java @@ -5,6 +5,7 @@ import com.main36.picha.domain.comment.dto.CommentResponseDto; import com.main36.picha.domain.comment.entity.Comment; import com.main36.picha.domain.member.entity.Member; +import com.main36.picha.domain.member.service.MemberService; import com.main36.picha.domain.post.dto.*; import com.main36.picha.domain.post.entity.Post; import org.mapstruct.Mapper; @@ -17,31 +18,8 @@ @Mapper(componentModel = MappingConstants.ComponentModel.SPRING) public interface PostMapper { - // 포스트 등록 - default Post postRegisterDtoToPost(PostRegisterDto postRegisterDto, Member member, Attraction attraction, List comments) { - if (postRegisterDto == null && member == null && attraction == null && comments == null) { - return null; - } - - assert postRegisterDto != null; - - Post.PostBuilder post = Post.builder(); - post.postTitle(postRegisterDto.getPostTitle()); - post.postContent(postRegisterDto.getPostContent()); - post.hashTagContent(postRegisterDto.getHashTagContent()); - - post.member(member); - post.attraction(attraction); - post.comments(comments); - - return post.build(); - } - - // 포스트 수정 Post postPatchDtoToPost(PostPatchDto postPatchDto); - - // 포스트 단일 조회 리스폰스 default SinglePostResponseDto postToSingleResponseDto(Post post) { if (post == null) { @@ -104,8 +82,6 @@ default List postListToPostHomeResponseDtoList(List postList) } - - // 포스트 페이지(전체 조회) 리스폰스 default List postListToPostPageResponseDtoList(List postList) { if (postList == null) { diff --git a/server/src/main/java/com/main36/picha/domain/post/service/PostService.java b/server/src/main/java/com/main36/picha/domain/post/service/PostService.java index fb5be1e6..6eae5a12 100644 --- a/server/src/main/java/com/main36/picha/domain/post/service/PostService.java +++ b/server/src/main/java/com/main36/picha/domain/post/service/PostService.java @@ -1,6 +1,8 @@ package com.main36.picha.domain.post.service; +import com.main36.picha.domain.attraction.entity.Attraction; +import com.main36.picha.domain.attraction.service.AttractionService; import com.main36.picha.domain.post.entity.Post; import com.main36.picha.domain.post.repository.PostRepository; import com.main36.picha.global.exception.BusinessLogicException; @@ -24,6 +26,9 @@ public class PostService { private final PostRepository postRepository; public Post createPost(Post post) { + Long numOfPostsPlusOne = post.getAttraction().getNumOfPosts() + 1; + post.getAttraction().setNumOfPosts(numOfPostsPlusOne); + return postRepository.save(post); } @@ -41,6 +46,7 @@ public Post updatePost(Post post) { private Post getVerifiedPostById(Post post) { Optional postById = postRepository.findById(post.getPostId()); + return postById.orElseThrow(() -> new BusinessLogicException(ExceptionCode.POST_NOT_FOUND)); } @@ -52,14 +58,21 @@ public Post findPost(Long postId) { return post; } + public Post findPostNoneSetView(Long postId) { + Optional optionalPost = postRepository.findById(postId); + + return optionalPost.orElseThrow(() -> new BusinessLogicException(ExceptionCode.POST_NOT_FOUND)); + } + + public Page findAllPostsBySort(int page, int size, String sort) { Pageable pageable = PageRequest.of(page, size, Sort.by(sort).descending()); return postRepository.findAll(pageable); } - public void deletePost(long postId, long memberId) { - Post post = findPost(postId); + public void erasePost(Post post) { + postRepository.delete(post); } From 44f26231f2a28e60f2b3479d43e468b2a2109431 Mon Sep 17 00:00:00 2001 From: eastmeet Date: Thu, 19 Jan 2023 14:32:20 +0900 Subject: [PATCH 3/4] refactor: Change packagename --- .../controller/AttractionController.java | 15 +------ .../comment/controller/CommentController.java | 35 +++++++-------- .../member/controller/MemberController.java | 34 +++++--------- .../post/controller/PostController.java | 45 +++++++------------ .../{auth => authorization}/dto/LoginDto.java | 3 +- .../authorization/dto/TokenDto.java} | 10 ++--- .../filter/JwtAuthenticationFilter.java | 13 +----- .../filter/JwtVerificationFilter.java | 4 +- .../handler/MemberAccessDeniedHandler.java | 3 +- .../MemberAuthenticationEntryPoint.java | 4 +- .../MemberAuthenticationFailureHandler.java | 2 +- .../MemberAuthenticationSuccessHandler.java | 4 +- .../handler/OAuth2MemberSuccessHandler.java | 21 ++++----- .../jwt/JwtTokenizer.java | 9 ++-- .../userdetails/MemberDetailsService.java | 2 +- .../global/config/SecurityConfiguration.java | 8 ++-- .../main36/picha/auth/JwtTokenizerTest.java | 2 +- 17 files changed, 79 insertions(+), 135 deletions(-) rename server/src/main/java/com/main36/picha/global/{auth => authorization}/dto/LoginDto.java (53%) rename server/src/main/java/com/main36/picha/{domain/member/dto/Token.java => global/authorization/dto/TokenDto.java} (55%) rename server/src/main/java/com/main36/picha/global/{auth => authorization}/filter/JwtAuthenticationFilter.java (73%) rename server/src/main/java/com/main36/picha/global/{auth => authorization}/filter/JwtVerificationFilter.java (95%) rename server/src/main/java/com/main36/picha/global/{auth => authorization}/handler/MemberAccessDeniedHandler.java (90%) rename server/src/main/java/com/main36/picha/global/{auth => authorization}/handler/MemberAuthenticationEntryPoint.java (89%) rename server/src/main/java/com/main36/picha/global/{auth => authorization}/handler/MemberAuthenticationFailureHandler.java (96%) rename server/src/main/java/com/main36/picha/global/{auth => authorization}/handler/MemberAuthenticationSuccessHandler.java (95%) rename server/src/main/java/com/main36/picha/global/{auth => authorization}/handler/OAuth2MemberSuccessHandler.java (86%) rename server/src/main/java/com/main36/picha/global/{auth => authorization}/jwt/JwtTokenizer.java (96%) rename server/src/main/java/com/main36/picha/global/{auth => authorization}/userdetails/MemberDetailsService.java (97%) diff --git a/server/src/main/java/com/main36/picha/domain/attraction/controller/AttractionController.java b/server/src/main/java/com/main36/picha/domain/attraction/controller/AttractionController.java index 354f5e6d..76a2a185 100644 --- a/server/src/main/java/com/main36/picha/domain/attraction/controller/AttractionController.java +++ b/server/src/main/java/com/main36/picha/domain/attraction/controller/AttractionController.java @@ -5,13 +5,10 @@ import com.main36.picha.domain.attraction.entity.Attraction; import com.main36.picha.domain.attraction.mapper.AttractionMapper; import com.main36.picha.domain.attraction.service.AttractionService; -import com.main36.picha.domain.attraction_file.entity.AttractionImage; import com.main36.picha.domain.attraction_file.service.AttractionImageService; -import com.main36.picha.domain.attraction_likes.repository.AttractionLikesRepository; import com.main36.picha.domain.member.entity.Member; import com.main36.picha.domain.member.service.MemberService; -import com.main36.picha.global.auth.jwt.JwtTokenizer; -import com.main36.picha.global.config.S3Service; +import com.main36.picha.global.authorization.jwt.JwtTokenizer; import com.main36.picha.global.response.DataResponseDto; import com.main36.picha.global.response.MultiResponseDto; import io.jsonwebtoken.Claims; @@ -20,23 +17,13 @@ import org.springframework.data.domain.Page; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.security.core.userdetails.UserDetails; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; -import javax.validation.Valid; import javax.validation.constraints.Positive; -import java.io.File; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Date; import java.util.List; -import java.util.UUID; @RestController @RequestMapping("/attractions") diff --git a/server/src/main/java/com/main36/picha/domain/comment/controller/CommentController.java b/server/src/main/java/com/main36/picha/domain/comment/controller/CommentController.java index 1ac567d6..954c7d5a 100644 --- a/server/src/main/java/com/main36/picha/domain/comment/controller/CommentController.java +++ b/server/src/main/java/com/main36/picha/domain/comment/controller/CommentController.java @@ -8,14 +8,11 @@ import com.main36.picha.domain.member.entity.Member; import com.main36.picha.domain.member.service.MemberService; import com.main36.picha.domain.post.service.PostService; -import com.main36.picha.global.auth.jwt.JwtTokenizer; +import com.main36.picha.global.authorization.jwt.JwtTokenizer; import com.main36.picha.global.exception.BusinessLogicException; import com.main36.picha.global.exception.ExceptionCode; import com.main36.picha.global.response.DataResponseDto; import com.main36.picha.global.response.MultiResponseDto; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jws; -import lombok.Data; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; @@ -24,11 +21,9 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; import javax.validation.constraints.Positive; import java.util.List; -import java.util.Optional; @RestController @Slf4j @@ -71,16 +66,7 @@ public ResponseEntity> postComment(@PathVariable("member-id") public ResponseEntity> patchComment(@PathVariable("member-id") @Positive long memberId, @PathVariable("comment-id") @Positive long commentId, @RequestBody @Valid CommentPostDto commentPostDto) { - - Member member = memberService.findVerifiedMemberById(memberId); - Comment comment = commentService.findComment(commentId); - - if (!comment.getMember().getMemberId().equals(memberId)) { - throw new BusinessLogicException(ExceptionCode.NOT_AUTHOR); - } - - comment.setCommentId(commentId); - comment.setMember(member); + Comment comment = verifiedById(memberId, commentId); comment.setCommentContent(commentPostDto.getCommentContent()); CommentResponseDto commentResponseDto = mapper.commentToCommentResponseDto(comment); @@ -106,10 +92,23 @@ public ResponseEntity> getComment(@Positive @RequestParam(re return ResponseEntity.ok(new MultiResponseDto<>(commentResponseDtos, commentPage)); } - @DeleteMapping("/delete/{comment-id}") - public ResponseEntity deleteCommnet(@PathVariable("comment-id") @Positive long commentId) { + @DeleteMapping("/delete/{member-id}/{comment-id}") + public ResponseEntity deleteComment(@PathVariable("member-id") @Positive long memberId, + @PathVariable("comment-id") @Positive long commentId) { + verifiedById(memberId, commentId); commentService.deleteComment(commentId); return new ResponseEntity<>(HttpStatus.NO_CONTENT); } + + private Comment verifiedById(long memberId, long commentId) { + Member member = memberService.findVerifiedMemberById(memberId); + Comment comment = commentService.findComment(commentId); + + if (!comment.getMember().getMemberId().equals(memberId)) { + throw new BusinessLogicException(ExceptionCode.NOT_AUTHOR); + } + + return comment; + } } diff --git a/server/src/main/java/com/main36/picha/domain/member/controller/MemberController.java b/server/src/main/java/com/main36/picha/domain/member/controller/MemberController.java index 11144824..4f65d71a 100644 --- a/server/src/main/java/com/main36/picha/domain/member/controller/MemberController.java +++ b/server/src/main/java/com/main36/picha/domain/member/controller/MemberController.java @@ -3,15 +3,12 @@ import com.main36.picha.domain.member.dto.MemberPatchDto; import com.main36.picha.domain.member.dto.MemberPostDto; -import com.main36.picha.domain.member.dto.Token; import com.main36.picha.domain.member.entity.Member; import com.main36.picha.domain.member.mapper.MemberMapper; import com.main36.picha.domain.member.service.MemberService; -import com.main36.picha.global.auth.userdetails.MemberDetailsService; import com.main36.picha.global.response.DataResponseDto; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.data.domain.Page; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -20,12 +17,8 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import javax.validation.constraints.Positive; -import java.util.List; @Slf4j @RestController @@ -40,19 +33,19 @@ public class MemberController { //멤버 회원가입 @PostMapping("/signup") - public ResponseEntity postMember(@Valid @RequestBody MemberPostDto memberPostDto) { + public ResponseEntity> postMember(@Valid @RequestBody MemberPostDto memberPostDto) { Member member = mapper.memberPostDtoToMember(memberPostDto); member.setPicture("https://drive.google.com/file/d/1OmsgU1GLU9iUBYe9ruw_Uy1AcrN57n4g/view?usp=sharing"); Member createMember = memberService.createMember(member); - return new ResponseEntity( + return new ResponseEntity<>( new DataResponseDto<>(mapper.memberToSignUpResponseDto(createMember)), HttpStatus.CREATED); } @GetMapping("/token") - public ResponseEntity getToken(@RequestParam String access_token, - @RequestParam String refresh_token) { + public ResponseEntity getToken(@RequestParam String access_token, + @RequestParam String refresh_token) { log.info("at={}", access_token); log.info("rt={}", refresh_token); String at = "Bearer " + access_token; @@ -73,8 +66,8 @@ public ResponseEntity getToken(@RequestParam String access_token, } @PatchMapping("/edit/{member-id}") - public ResponseEntity patchMember(@PathVariable("member-id") @Positive long memberId, - @Valid @RequestBody MemberPatchDto memberPatchDto) { + public ResponseEntity> patchMember(@PathVariable("member-id") @Positive long memberId, + @Valid @RequestBody MemberPatchDto memberPatchDto) { memberPatchDto.setMemberId(memberId); Member member = memberService.updateMember(mapper.memberPatchDtoToMember(memberPatchDto)); @@ -84,11 +77,9 @@ public ResponseEntity patchMember(@PathVariable("member-id") @P ); } - // 멤버 프로필 조회(홈) - // TODO: 스프링 시큐리티 적용 @GetMapping("/{member-id}/{email}") - public ResponseEntity getMemberProfile(@Positive @PathVariable("member-id") long memberId, - @PathVariable("email") String email) { + public ResponseEntity> getMemberProfile(@Positive @PathVariable("member-id") long memberId, + @PathVariable("email") String email) { //TODO: verifyLoginMember Member member = memberService.findMember(memberId, email); return new ResponseEntity<>(new DataResponseDto<>(mapper.memberToProfileHomeDto(member)), @@ -96,17 +87,14 @@ public ResponseEntity getMemberProfile(@Positive @PathVariable( } @GetMapping() - public ResponseEntity getMembers(@RequestParam(defaultValue = "1", required = false) int page, - @RequestParam(defaultValue = "9", required = false) int size) { + public ResponseEntity getMembers(@RequestParam(defaultValue = "1", required = false) int page, + @RequestParam(defaultValue = "9", required = false) int size) { // Page pageMember = return new ResponseEntity<>(HttpStatus.OK); } - - // 멤버 삭제 - // TODO: 스프링 시큐리티 적용 @DeleteMapping("/delete/{member-id}/confirm") - public ResponseEntity deleteMember(@PathVariable("member-id") @Positive long memberId) { + public ResponseEntity deleteMember(@PathVariable("member-id") @Positive long memberId) { //TODO: verifyLoginMember memberService.deleteMember(memberId); return new ResponseEntity(HttpStatus.NO_CONTENT); diff --git a/server/src/main/java/com/main36/picha/domain/post/controller/PostController.java b/server/src/main/java/com/main36/picha/domain/post/controller/PostController.java index 09a00bc9..9abb6150 100644 --- a/server/src/main/java/com/main36/picha/domain/post/controller/PostController.java +++ b/server/src/main/java/com/main36/picha/domain/post/controller/PostController.java @@ -1,16 +1,13 @@ package com.main36.picha.domain.post.controller; -import com.main36.picha.domain.attraction.entity.Attraction; import com.main36.picha.domain.attraction.service.AttractionService; -import com.main36.picha.domain.comment.entity.Comment; -import com.main36.picha.domain.member.entity.Member; + import com.main36.picha.domain.member.service.MemberService; import com.main36.picha.domain.post.dto.*; import com.main36.picha.domain.post.entity.Post; import com.main36.picha.domain.post.mapper.PostMapper; import com.main36.picha.domain.post.service.PostService; -import com.main36.picha.global.auth.jwt.JwtTokenizer; import com.main36.picha.global.exception.BusinessLogicException; import com.main36.picha.global.exception.ExceptionCode; import com.main36.picha.global.response.DataResponseDto; @@ -20,15 +17,12 @@ import org.springframework.data.domain.Page; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.security.core.parameters.P; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; import javax.validation.constraints.Positive; -import java.rmi.activation.ActivationGroupDesc; import java.util.ArrayList; import java.util.List; @@ -69,35 +63,24 @@ public ResponseEntity> editPost(@PathVari @Valid @RequestBody PostPatchDto postPatchDto) { verifiedById(memberId, postId); - postPatchDto.setPostId(memberId); + postPatchDto.setPostId(postId); Post updatePost = postService.updatePost(mapper.postPatchDtoToPost(postPatchDto)); return ResponseEntity.ok(new DataResponseDto<>(mapper.postToSingleResponseDto(updatePost))); } @GetMapping("/{post-id}") - public ResponseEntity> getPost(@PathVariable("post-id") @Positive long postId) { + public ResponseEntity> getPost(@PathVariable("post-id") @Positive long postId) { Post post = postService.findPost(postId); return ResponseEntity.ok(new DataResponseDto<>(mapper.postToSingleResponseDto(post))); } @GetMapping("/home") - public ResponseEntity getHomePosts(@RequestParam(defaultValue = "newest", required = false) String sort, + public ResponseEntity> getHomePosts(@RequestParam(defaultValue = "newest", required = false) String sort, @RequestParam(defaultValue = "1", required = false) @Positive int page, @RequestParam(defaultValue = "8", required = false) @Positive int size) { - switch (sort) { - case "newest": - sort = "postId"; - break; - case "likes": - sort = "likes"; - break; - case "views": - sort = "views"; - break; - } - + sort = getString(sort); Page allPostsBySort = postService.findAllPostsBySort(page - 1, size, sort); List content = allPostsBySort.getContent(); @@ -106,10 +89,20 @@ public ResponseEntity getHomePosts(@RequestParam(defaultValue } + @GetMapping() - public ResponseEntity getAllPosts(@RequestParam(defaultValue = "newest", required = false) String sort, + public ResponseEntity> getAllPosts(@RequestParam(defaultValue = "newest", required = false) String sort, @RequestParam(defaultValue = "1", required = false) @Positive int page, @RequestParam(defaultValue = "9", required = false) @Positive int size) { + sort = getString(sort); + Page postsByNewestByPage = postService.findAllPostsBySort(page - 1, size, sort); + List postsByNewest = postsByNewestByPage.getContent(); + + return new ResponseEntity<>(new MultiResponseDto<>( + mapper.postListToPostPageResponseDtoList(postsByNewest), postsByNewestByPage), HttpStatus.OK); + } + + private static String getString(String sort) { switch (sort) { case "newest": sort = "postId"; @@ -121,11 +114,7 @@ public ResponseEntity getAllPosts(@RequestParam(defaultValue = sort = "views"; break; } - Page postsByNewestByPage = postService.findAllPostsBySort(page - 1, size, sort); - List postsByNewest = postsByNewestByPage.getContent(); - - return new ResponseEntity<>(new MultiResponseDto<>( - mapper.postListToPostPageResponseDtoList(postsByNewest), postsByNewestByPage), HttpStatus.OK); + return sort; } @DeleteMapping("/delete/{member-id}/{post-id}") diff --git a/server/src/main/java/com/main36/picha/global/auth/dto/LoginDto.java b/server/src/main/java/com/main36/picha/global/authorization/dto/LoginDto.java similarity index 53% rename from server/src/main/java/com/main36/picha/global/auth/dto/LoginDto.java rename to server/src/main/java/com/main36/picha/global/authorization/dto/LoginDto.java index c96b9766..024ffb69 100644 --- a/server/src/main/java/com/main36/picha/global/auth/dto/LoginDto.java +++ b/server/src/main/java/com/main36/picha/global/authorization/dto/LoginDto.java @@ -1,7 +1,6 @@ -package com.main36.picha.global.auth.dto; +package com.main36.picha.global.authorization.dto; import lombok.Getter; -import org.springframework.web.bind.annotation.GetMapping; @Getter public class LoginDto { diff --git a/server/src/main/java/com/main36/picha/domain/member/dto/Token.java b/server/src/main/java/com/main36/picha/global/authorization/dto/TokenDto.java similarity index 55% rename from server/src/main/java/com/main36/picha/domain/member/dto/Token.java rename to server/src/main/java/com/main36/picha/global/authorization/dto/TokenDto.java index e6d6c25b..4816649e 100644 --- a/server/src/main/java/com/main36/picha/domain/member/dto/Token.java +++ b/server/src/main/java/com/main36/picha/global/authorization/dto/TokenDto.java @@ -1,4 +1,4 @@ -package com.main36.picha.domain.member.dto; +package com.main36.picha.global.authorization.dto; import lombok.AllArgsConstructor; @@ -6,14 +6,14 @@ import lombok.Data; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotBlank; - @Data @NoArgsConstructor @AllArgsConstructor @Builder -public class Token { - +public class TokenDto { +// private String grantType; +// private String authorizationType; +// private Long accessTokenExpiresIn; private String accessToken; private String refreshToken; diff --git a/server/src/main/java/com/main36/picha/global/auth/filter/JwtAuthenticationFilter.java b/server/src/main/java/com/main36/picha/global/authorization/filter/JwtAuthenticationFilter.java similarity index 73% rename from server/src/main/java/com/main36/picha/global/auth/filter/JwtAuthenticationFilter.java rename to server/src/main/java/com/main36/picha/global/authorization/filter/JwtAuthenticationFilter.java index 163bf826..2cdec838 100644 --- a/server/src/main/java/com/main36/picha/global/auth/filter/JwtAuthenticationFilter.java +++ b/server/src/main/java/com/main36/picha/global/authorization/filter/JwtAuthenticationFilter.java @@ -1,25 +1,16 @@ -package com.main36.picha.global.auth.filter; +package com.main36.picha.global.authorization.filter; import com.fasterxml.jackson.databind.ObjectMapper; -import com.main36.picha.domain.member.entity.Member; -import com.main36.picha.global.auth.dto.LoginDto; -import com.main36.picha.global.auth.jwt.JwtTokenizer; +import com.main36.picha.global.authorization.dto.LoginDto; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; @RequiredArgsConstructor diff --git a/server/src/main/java/com/main36/picha/global/auth/filter/JwtVerificationFilter.java b/server/src/main/java/com/main36/picha/global/authorization/filter/JwtVerificationFilter.java similarity index 95% rename from server/src/main/java/com/main36/picha/global/auth/filter/JwtVerificationFilter.java rename to server/src/main/java/com/main36/picha/global/authorization/filter/JwtVerificationFilter.java index 8405694c..c2c00e6f 100644 --- a/server/src/main/java/com/main36/picha/global/auth/filter/JwtVerificationFilter.java +++ b/server/src/main/java/com/main36/picha/global/authorization/filter/JwtVerificationFilter.java @@ -1,6 +1,6 @@ -package com.main36.picha.global.auth.filter; +package com.main36.picha.global.authorization.filter; -import com.main36.picha.global.auth.jwt.JwtTokenizer; +import com.main36.picha.global.authorization.jwt.JwtTokenizer; import com.main36.picha.global.utils.CustomAuthorityUtils; import io.jsonwebtoken.ExpiredJwtException; diff --git a/server/src/main/java/com/main36/picha/global/auth/handler/MemberAccessDeniedHandler.java b/server/src/main/java/com/main36/picha/global/authorization/handler/MemberAccessDeniedHandler.java similarity index 90% rename from server/src/main/java/com/main36/picha/global/auth/handler/MemberAccessDeniedHandler.java rename to server/src/main/java/com/main36/picha/global/authorization/handler/MemberAccessDeniedHandler.java index e2f31e62..0ac358ae 100644 --- a/server/src/main/java/com/main36/picha/global/auth/handler/MemberAccessDeniedHandler.java +++ b/server/src/main/java/com/main36/picha/global/authorization/handler/MemberAccessDeniedHandler.java @@ -1,6 +1,5 @@ -package com.main36.picha.global.auth.handler; +package com.main36.picha.global.authorization.handler; -import com.main36.picha.global.response.ErrorResponse; import com.main36.picha.global.utils.ErrorResponder; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; diff --git a/server/src/main/java/com/main36/picha/global/auth/handler/MemberAuthenticationEntryPoint.java b/server/src/main/java/com/main36/picha/global/authorization/handler/MemberAuthenticationEntryPoint.java similarity index 89% rename from server/src/main/java/com/main36/picha/global/auth/handler/MemberAuthenticationEntryPoint.java rename to server/src/main/java/com/main36/picha/global/authorization/handler/MemberAuthenticationEntryPoint.java index 37a31586..d0cc1d28 100644 --- a/server/src/main/java/com/main36/picha/global/auth/handler/MemberAuthenticationEntryPoint.java +++ b/server/src/main/java/com/main36/picha/global/authorization/handler/MemberAuthenticationEntryPoint.java @@ -1,10 +1,8 @@ -package com.main36.picha.global.auth.handler; +package com.main36.picha.global.authorization.handler; -import com.main36.picha.global.response.ErrorResponse; import com.main36.picha.global.utils.ErrorResponder; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; -import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.stereotype.Component; diff --git a/server/src/main/java/com/main36/picha/global/auth/handler/MemberAuthenticationFailureHandler.java b/server/src/main/java/com/main36/picha/global/authorization/handler/MemberAuthenticationFailureHandler.java similarity index 96% rename from server/src/main/java/com/main36/picha/global/auth/handler/MemberAuthenticationFailureHandler.java rename to server/src/main/java/com/main36/picha/global/authorization/handler/MemberAuthenticationFailureHandler.java index 08d75f93..638b5f59 100644 --- a/server/src/main/java/com/main36/picha/global/auth/handler/MemberAuthenticationFailureHandler.java +++ b/server/src/main/java/com/main36/picha/global/authorization/handler/MemberAuthenticationFailureHandler.java @@ -1,4 +1,4 @@ -package com.main36.picha.global.auth.handler; +package com.main36.picha.global.authorization.handler; import com.google.gson.Gson; import com.main36.picha.global.response.ErrorResponse; diff --git a/server/src/main/java/com/main36/picha/global/auth/handler/MemberAuthenticationSuccessHandler.java b/server/src/main/java/com/main36/picha/global/authorization/handler/MemberAuthenticationSuccessHandler.java similarity index 95% rename from server/src/main/java/com/main36/picha/global/auth/handler/MemberAuthenticationSuccessHandler.java rename to server/src/main/java/com/main36/picha/global/authorization/handler/MemberAuthenticationSuccessHandler.java index dcc12af5..7d3da06c 100644 --- a/server/src/main/java/com/main36/picha/global/auth/handler/MemberAuthenticationSuccessHandler.java +++ b/server/src/main/java/com/main36/picha/global/authorization/handler/MemberAuthenticationSuccessHandler.java @@ -1,7 +1,7 @@ -package com.main36.picha.global.auth.handler; +package com.main36.picha.global.authorization.handler; import com.main36.picha.domain.member.entity.Member; -import com.main36.picha.global.auth.jwt.JwtTokenizer; +import com.main36.picha.global.authorization.jwt.JwtTokenizer; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.Authentication; diff --git a/server/src/main/java/com/main36/picha/global/auth/handler/OAuth2MemberSuccessHandler.java b/server/src/main/java/com/main36/picha/global/authorization/handler/OAuth2MemberSuccessHandler.java similarity index 86% rename from server/src/main/java/com/main36/picha/global/auth/handler/OAuth2MemberSuccessHandler.java rename to server/src/main/java/com/main36/picha/global/authorization/handler/OAuth2MemberSuccessHandler.java index 52e40414..570eee5a 100644 --- a/server/src/main/java/com/main36/picha/global/auth/handler/OAuth2MemberSuccessHandler.java +++ b/server/src/main/java/com/main36/picha/global/authorization/handler/OAuth2MemberSuccessHandler.java @@ -1,20 +1,15 @@ -package com.main36.picha.global.auth.handler; +package com.main36.picha.global.authorization.handler; import com.main36.picha.domain.member.dto.OauthMemberDto; import com.main36.picha.domain.member.entity.Member; import com.main36.picha.domain.member.mapper.MemberMapper; -import com.main36.picha.domain.member.repository.MemberRepository; import com.main36.picha.domain.member.service.MemberService; -import com.main36.picha.global.auth.jwt.JwtTokenizer; -import com.main36.picha.global.exception.BusinessLogicException; -import com.main36.picha.global.exception.ExceptionCode; +import com.main36.picha.global.authorization.jwt.JwtTokenizer; import com.main36.picha.global.utils.CustomAuthorityUtils; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Profile; import org.springframework.security.core.Authentication; -import org.springframework.security.core.parameters.P; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; import org.springframework.util.LinkedMultiValueMap; @@ -68,7 +63,7 @@ private void redirect(HttpServletRequest request, String accessToken = delegateAccessToken(username, authorities); String refreshToken = delegateRefreshToken(username); - String uri = createURI(accessToken, refreshToken).toString(); + String uri = createURI(request, accessToken, refreshToken).toString(); getRedirectStrategy().sendRedirect(request, response, uri); } @@ -97,17 +92,17 @@ private String delegateRefreshToken(String username) { return refreshToken; } - - private URI createURI(String accessToken, String refreshToken) { + private URI createURI(HttpServletRequest request, String accessToken, String refreshToken) { MultiValueMap queryParams = new LinkedMultiValueMap<>(); queryParams.add("access_token", accessToken); - queryParams.add("refresh_token", refreshToken); +// queryParams.add("refresh_token", refreshToken); + + String serverName = request.getServerName(); return UriComponentsBuilder .newInstance() .scheme("http") - .host( "pikcha36.o-r.kr") -// .host("localhost") + .host( serverName) .port(8080) .path("/users/token") .queryParams(queryParams) diff --git a/server/src/main/java/com/main36/picha/global/auth/jwt/JwtTokenizer.java b/server/src/main/java/com/main36/picha/global/authorization/jwt/JwtTokenizer.java similarity index 96% rename from server/src/main/java/com/main36/picha/global/auth/jwt/JwtTokenizer.java rename to server/src/main/java/com/main36/picha/global/authorization/jwt/JwtTokenizer.java index d5371f8e..0a8cb24c 100644 --- a/server/src/main/java/com/main36/picha/global/auth/jwt/JwtTokenizer.java +++ b/server/src/main/java/com/main36/picha/global/authorization/jwt/JwtTokenizer.java @@ -1,15 +1,14 @@ -package com.main36.picha.global.auth.jwt; +package com.main36.picha.global.authorization.jwt; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jws; import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.io.Decoder; import io.jsonwebtoken.io.Decoders; import io.jsonwebtoken.io.Encoders; import io.jsonwebtoken.security.Keys; import lombok.Getter; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; @@ -19,13 +18,13 @@ import java.util.Date; import java.util.Map; +@Slf4j @Component - public class JwtTokenizer { + @Getter @Value("${jwt.secret-key}") private String secretKey; - @Getter @Value("${jwt.access-token-expiration-minutes}") private int accessTokenExpirationMinutes; diff --git a/server/src/main/java/com/main36/picha/global/auth/userdetails/MemberDetailsService.java b/server/src/main/java/com/main36/picha/global/authorization/userdetails/MemberDetailsService.java similarity index 97% rename from server/src/main/java/com/main36/picha/global/auth/userdetails/MemberDetailsService.java rename to server/src/main/java/com/main36/picha/global/authorization/userdetails/MemberDetailsService.java index ba797cdc..e808675b 100644 --- a/server/src/main/java/com/main36/picha/global/auth/userdetails/MemberDetailsService.java +++ b/server/src/main/java/com/main36/picha/global/authorization/userdetails/MemberDetailsService.java @@ -1,4 +1,4 @@ -package com.main36.picha.global.auth.userdetails; +package com.main36.picha.global.authorization.userdetails; import com.main36.picha.domain.member.entity.Member; import com.main36.picha.domain.member.repository.MemberRepository; diff --git a/server/src/main/java/com/main36/picha/global/config/SecurityConfiguration.java b/server/src/main/java/com/main36/picha/global/config/SecurityConfiguration.java index 39c65bec..22853a72 100644 --- a/server/src/main/java/com/main36/picha/global/config/SecurityConfiguration.java +++ b/server/src/main/java/com/main36/picha/global/config/SecurityConfiguration.java @@ -5,10 +5,10 @@ import com.main36.picha.domain.member.repository.MemberRepository; import com.main36.picha.domain.member.service.MemberService; -import com.main36.picha.global.auth.filter.JwtAuthenticationFilter; -import com.main36.picha.global.auth.filter.JwtVerificationFilter; -import com.main36.picha.global.auth.handler.*; -import com.main36.picha.global.auth.jwt.JwtTokenizer; +import com.main36.picha.global.authorization.filter.JwtAuthenticationFilter; +import com.main36.picha.global.authorization.filter.JwtVerificationFilter; +import com.main36.picha.global.authorization.handler.*; +import com.main36.picha.global.authorization.jwt.JwtTokenizer; import com.main36.picha.global.utils.CustomAuthorityUtils; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; diff --git a/server/src/test/java/com/main36/picha/auth/JwtTokenizerTest.java b/server/src/test/java/com/main36/picha/auth/JwtTokenizerTest.java index 94f01e2c..dab19877 100644 --- a/server/src/test/java/com/main36/picha/auth/JwtTokenizerTest.java +++ b/server/src/test/java/com/main36/picha/auth/JwtTokenizerTest.java @@ -1,7 +1,7 @@ package com.main36.picha.auth; -import com.main36.picha.global.auth.jwt.JwtTokenizer; +import com.main36.picha.global.authorization.jwt.JwtTokenizer; import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.io.Decoders; import org.junit.jupiter.api.BeforeAll; From 629d1d7ec7cef7b4754f6daadf018897194070c2 Mon Sep 17 00:00:00 2001 From: eastmeet Date: Thu, 19 Jan 2023 15:12:57 +0900 Subject: [PATCH 4/4] feat: Add LoginUser Resolver --- .../authorization/resolver/LoginUser.java | 11 +++++ .../resolver/UserArgumentResolver.java | 43 +++++++++++++++++++ .../picha/global/config/WebMvcConfig.java | 19 ++++++++ 3 files changed, 73 insertions(+) create mode 100644 server/src/main/java/com/main36/picha/global/authorization/resolver/LoginUser.java create mode 100644 server/src/main/java/com/main36/picha/global/authorization/resolver/UserArgumentResolver.java diff --git a/server/src/main/java/com/main36/picha/global/authorization/resolver/LoginUser.java b/server/src/main/java/com/main36/picha/global/authorization/resolver/LoginUser.java new file mode 100644 index 00000000..33bd2807 --- /dev/null +++ b/server/src/main/java/com/main36/picha/global/authorization/resolver/LoginUser.java @@ -0,0 +1,11 @@ +package com.main36.picha.global.authorization.resolver; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +public @interface LoginUser { +} diff --git a/server/src/main/java/com/main36/picha/global/authorization/resolver/UserArgumentResolver.java b/server/src/main/java/com/main36/picha/global/authorization/resolver/UserArgumentResolver.java new file mode 100644 index 00000000..6fa5a62c --- /dev/null +++ b/server/src/main/java/com/main36/picha/global/authorization/resolver/UserArgumentResolver.java @@ -0,0 +1,43 @@ +package com.main36.picha.global.authorization.resolver; + +import com.main36.picha.global.authorization.dto.LoginDto; +import com.main36.picha.global.authorization.jwt.JwtTokenizer; +import org.springframework.core.MethodParameter; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.ModelAndViewContainer; + +import javax.servlet.http.HttpServletRequest; + +@Component +public class UserArgumentResolver implements HandlerMethodArgumentResolver { + + @Override + public boolean supportsParameter(MethodParameter parameter) { + + return parameter.getParameterAnnotation(LoginUser.class) != null + && parameter.getParameterType().equals(Long.class); + +// return isLoginUserAnnotation && isUserClass; +// return parameter.getParameterType().equals(LoginDto.class); + } + + @Override + public Object resolveArgument(MethodParameter parameter, + ModelAndViewContainer mavContainer, + NativeWebRequest webRequest, + WebDataBinderFactory binderFactory) throws Exception { + + HttpServletRequest httpServletRequest = (HttpServletRequest) webRequest.getNativeRequest(); + return httpServletRequest.getHeader("User-Agent"); +// String token = JwtTokenizer.getUsername(httpServletRequest); +// JwtUtil.validateToken(token); +// +// String userId = JwtUtil.getPayload(token); +// String ipAddress = httpServletRequest.getRemoteAddr(); +// +// return new UserDto(userId, ipAddress); + } +} diff --git a/server/src/main/java/com/main36/picha/global/config/WebMvcConfig.java b/server/src/main/java/com/main36/picha/global/config/WebMvcConfig.java index c3591a57..0a4df19a 100644 --- a/server/src/main/java/com/main36/picha/global/config/WebMvcConfig.java +++ b/server/src/main/java/com/main36/picha/global/config/WebMvcConfig.java @@ -1,15 +1,34 @@ package com.main36.picha.global.config; +import com.main36.picha.global.authorization.resolver.LoginUser; +import com.main36.picha.global.authorization.resolver.UserArgumentResolver; +import lombok.RequiredArgsConstructor; +import org.springframework.boot.SpringApplication; import org.springframework.context.annotation.Configuration; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import java.util.List; + @Configuration +@RequiredArgsConstructor public class WebMvcConfig implements WebMvcConfigurer { + + private final UserArgumentResolver userArgumentResolver; @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedOrigins("*"); } + + @Override + public void addArgumentResolvers(List resolvers) { + resolvers.add(userArgumentResolver); + } + +// public static void main(String[] args) { +// SpringApplication.run(WebMvcConfig.class, args); +// } } \ No newline at end of file