diff --git a/config b/config index a8c27c00..6e041abb 160000 --- a/config +++ b/config @@ -1 +1 @@ -Subproject commit a8c27c00efa6f8a39fe2133c396c0ece8066da93 +Subproject commit 6e041abbb7d0b160aea337d0d7210c0471ced18f diff --git a/src/main/java/com/example/ReviewZIP/domain/follow/FollowsRepository.java b/src/main/java/com/example/ReviewZIP/domain/follow/FollowsRepository.java index 65276f19..a857bb20 100644 --- a/src/main/java/com/example/ReviewZIP/domain/follow/FollowsRepository.java +++ b/src/main/java/com/example/ReviewZIP/domain/follow/FollowsRepository.java @@ -1,25 +1,15 @@ package com.example.ReviewZIP.domain.follow; import com.example.ReviewZIP.domain.user.Users; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; -import java.util.List; @Repository public interface FollowsRepository extends JpaRepository { - List findAllBySender(Users sender); - List findAllByReceiver(Users user); - Follows getBySenderAndReceiver(Users sender, Users receiver); - Integer countBySenderId(Long userId); - - Integer countByReceiverId(Long userid); - boolean existsBySenderAndReceiver(Users sender, Users receiver); } diff --git a/src/main/java/com/example/ReviewZIP/domain/image/ImageConverter.java b/src/main/java/com/example/ReviewZIP/domain/image/ImageConverter.java index 4fad6b65..5f2f97b0 100644 --- a/src/main/java/com/example/ReviewZIP/domain/image/ImageConverter.java +++ b/src/main/java/com/example/ReviewZIP/domain/image/ImageConverter.java @@ -1,6 +1,6 @@ package com.example.ReviewZIP.domain.image; -import com.example.ReviewZIP.domain.image.dto.response.UploadImageResponseDto; +import com.example.ReviewZIP.domain.image.dto.response.ImageResponseDto; import org.springframework.stereotype.Component; import java.util.List; @@ -8,8 +8,14 @@ @Component public class ImageConverter { - public static UploadImageResponseDto toUploadImageDto(List imagesList) { - List imageIds = imagesList.stream().map(Images::getId).collect(Collectors.toList()); - return new UploadImageResponseDto(imageIds); + + public static ImageResponseDto.ImageDto toImageDto(Images image){ + return ImageResponseDto.ImageDto.builder() + .imageId(image.getId()) + .imageUrl(image.getUrl()) + .build(); + } + public static List toUploadImageDto(List imagesList) { + return imagesList.stream().map(ImageConverter::toImageDto).collect(Collectors.toList()); } } diff --git a/src/main/java/com/example/ReviewZIP/domain/image/ImagesController.java b/src/main/java/com/example/ReviewZIP/domain/image/ImagesController.java index 669a59d4..4df29493 100644 --- a/src/main/java/com/example/ReviewZIP/domain/image/ImagesController.java +++ b/src/main/java/com/example/ReviewZIP/domain/image/ImagesController.java @@ -1,10 +1,8 @@ package com.example.ReviewZIP.domain.image; -import com.example.ReviewZIP.domain.image.dto.response.UploadImageResponseDto; +import com.example.ReviewZIP.domain.image.dto.response.ImageResponseDto; import com.example.ReviewZIP.global.response.ApiResponse; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponses; @@ -26,9 +24,9 @@ public class ImagesController { @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "SEARCH203",description = "OK, 성공"), @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "IMAGE402", description = "이미지 업로드 실패",content = @Content(schema = @Schema(implementation = ApiResponse.class))), }) - public ApiResponse uploadImage(@PathVariable(name="userId") Long userId, @RequestParam("fileList") List fileList){ + public ApiResponse> uploadImage(@PathVariable(name="userId") Long userId, @RequestParam("fileList") List fileList){ List imageList = imageService.uploadImage(fileList, userId); - UploadImageResponseDto imageResponseDto = ImageConverter.toUploadImageDto(imageList); - return ApiResponse.onSuccess(imageResponseDto); + List imageDtoList = ImageConverter.toUploadImageDto(imageList); + return ApiResponse.onSuccess(imageDtoList); } } diff --git a/src/main/java/com/example/ReviewZIP/domain/image/dto/response/ImageResponseDto.java b/src/main/java/com/example/ReviewZIP/domain/image/dto/response/ImageResponseDto.java new file mode 100644 index 00000000..2ccbcafa --- /dev/null +++ b/src/main/java/com/example/ReviewZIP/domain/image/dto/response/ImageResponseDto.java @@ -0,0 +1,18 @@ +package com.example.ReviewZIP.domain.image.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +public class ImageResponseDto { + + @Builder + @NoArgsConstructor + @AllArgsConstructor + @Getter + public static class ImageDto{ + private Long imageId; + private String imageUrl; + } +} diff --git a/src/main/java/com/example/ReviewZIP/domain/image/dto/response/UploadImageResponseDto.java b/src/main/java/com/example/ReviewZIP/domain/image/dto/response/UploadImageResponseDto.java deleted file mode 100644 index 5e0c37da..00000000 --- a/src/main/java/com/example/ReviewZIP/domain/image/dto/response/UploadImageResponseDto.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.example.ReviewZIP.domain.image.dto.response; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.NoArgsConstructor; - -import java.util.List; -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class UploadImageResponseDto { - public List imageIds; -} diff --git a/src/main/java/com/example/ReviewZIP/domain/jwt/JwtProperties.java b/src/main/java/com/example/ReviewZIP/domain/jwt/JwtProperties.java deleted file mode 100644 index 72723b6a..00000000 --- a/src/main/java/com/example/ReviewZIP/domain/jwt/JwtProperties.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.example.ReviewZIP.domain.jwt; - -import lombok.Getter; -import lombok.Setter; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; - -@Getter -@Setter -@Component -@ConfigurationProperties("jwt") -public class JwtProperties { - @Value("${jwt.issuer}") - private String issuer; - - @Value("${jwt.secretKey}") - private String secretKey; -} diff --git a/src/main/java/com/example/ReviewZIP/domain/jwt/TokenProvider.java b/src/main/java/com/example/ReviewZIP/domain/jwt/TokenProvider.java deleted file mode 100644 index 816f0512..00000000 --- a/src/main/java/com/example/ReviewZIP/domain/jwt/TokenProvider.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.example.ReviewZIP.domain.jwt; - -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Header; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -import java.util.Date; - -@RequiredArgsConstructor -@Service -public class TokenProvider { - private final JwtProperties jwtProperties; - - public String makeToken(Long userId){ - Date now = new Date(); - Date exp = new Date(now.getTime() + 3600000); //1시간 만료 기준 - Claims claims = Jwts.claims(); - claims.put("userid", userId); - - return Jwts.builder() - .setHeaderParam(Header.TYPE, Header.JWT_TYPE) - .setIssuer(jwtProperties.getIssuer()) - .setIssuedAt(now) - .setExpiration(exp) - .setClaims(claims) - //.setSubject(userId.toString()) - .signWith(SignatureAlgorithm.HS256, jwtProperties.getSecretKey()) - .compact(); - } - - public Long getUserId(String token){ - Claims claims = Jwts.parser() - .setSigningKey(jwtProperties.getSecretKey()) - .parseClaimsJws(token) - .getBody(); - return claims.get("userId", Long.class); - } - - public boolean validToken(String token){ - try{ - Jwts.parser() - .setSigningKey(jwtProperties.getSecretKey()) - .parseClaimsJws(token); - return true; - } catch(Exception e){ - return false; - } - } - - -} diff --git a/src/main/java/com/example/ReviewZIP/domain/oauth/KakaoController.java b/src/main/java/com/example/ReviewZIP/domain/oauth/KakaoController.java deleted file mode 100644 index 4601ac7a..00000000 --- a/src/main/java/com/example/ReviewZIP/domain/oauth/KakaoController.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.example.ReviewZIP.domain.oauth; - -import com.example.ReviewZIP.domain.jwt.TokenProvider; -import com.example.ReviewZIP.domain.oauth.dto.request.OauthRequestDto; -import com.example.ReviewZIP.global.response.ApiResponse; -import com.fasterxml.jackson.core.JsonProcessingException; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.Parameters; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.*; - -import java.util.List; -import java.util.Map; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/v1/oauth") -public class KakaoController { - - private final OauthService oauthService; - - // 유저 관련 token 받은 후 해당 정보로 accessToken 발급 - @PostMapping("/kakao") - @Operation(summary = "카카오 소셜 로그인 API",description = "카카오 인가 코드를 받아 access token 발급, KakaoTokenRequest의 token 이용") - @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "GLOBAL502", description = "유효하지 못한 카카오 인가코드입니다",content = @Content(schema = @Schema(implementation = ApiResponse.class))), - }) - public ApiResponse> sendAccessToken(@RequestBody OauthRequestDto.kakaoTokenRequestDto request) throws JsonProcessingException { - - List kakaoUserInfoList = oauthService.getKakaoUserInfo(request); - - return ApiResponse.onSuccess(oauthService.generateAccessToken(kakaoUserInfoList.get(0),kakaoUserInfoList.get(1) , kakaoUserInfoList.get(2))); - - } -} diff --git a/src/main/java/com/example/ReviewZIP/domain/oauth/OauthService.java b/src/main/java/com/example/ReviewZIP/domain/oauth/OauthService.java deleted file mode 100644 index 97d975b8..00000000 --- a/src/main/java/com/example/ReviewZIP/domain/oauth/OauthService.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.example.ReviewZIP.domain.oauth; - -import com.example.ReviewZIP.domain.jwt.TokenProvider; -import com.example.ReviewZIP.domain.oauth.dto.request.OauthRequestDto; -import com.example.ReviewZIP.domain.user.Status; -import com.example.ReviewZIP.domain.user.Users; -import com.example.ReviewZIP.domain.user.UsersRepository; -import com.example.ReviewZIP.global.response.code.resultCode.ErrorStatus; -import com.example.ReviewZIP.global.response.exception.handler.GeneralHandler; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; - -import java.util.*; - -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class OauthService { - private final UsersRepository usersRepository; - private final TokenProvider tokenProvider; - - @Transactional - public Long createUser(String id, String nickname, String email){ - Users newUser = Users.builder() - .social(id) - .nickname(nickname) - .name(nickname) - .email(email) - .status(Status.ENABLED) - .build(); - usersRepository.save(newUser); - - return newUser.getId(); - } - - @Transactional - public Map generateAccessToken(String id, String nickname, String email){ - boolean exist = usersRepository.existsBySocial(id); - - System.out.println(exist); - Long userId; - - if(!exist) { - // 유저가 존재하지 않을때 -> 유저 생성 - userId = createUser(id, nickname, email); - } else { - // 존재할 경우 해당 유저의 userId 반환 - userId = usersRepository.getBySocial(id).getId(); - } - - String accessToken = tokenProvider.makeToken(userId); - - Map map = new LinkedHashMap<>(); - map.put("accessToken", accessToken); - - return map; - } - - public List getKakaoUserInfo(OauthRequestDto.kakaoTokenRequestDto request) throws JsonProcessingException { - String token = request.getToken(); - - HttpHeaders headers = new HttpHeaders(); - headers.set("Content-type", "application/x-www-form-urlencoded;charset=utf-8"); - headers.set("Authorization", "Bearer " + token); - - HttpEntity> kakaoProfileRequest = new HttpEntity<>(null, headers); - - RestTemplate restTemplate = new RestTemplate(); - - ResponseEntity response; - - try { - response = restTemplate.exchange( - "https://kapi.kakao.com/v2/user/me", - HttpMethod.POST, - kakaoProfileRequest, - String.class - ); - } catch (Exception e){ - throw new GeneralHandler(ErrorStatus.KAKAO_TOKEN_ERROR); - } - - ObjectMapper objectMapper = new ObjectMapper(); - String responseBody = response.getBody(); - JsonNode jsonNode = objectMapper.readTree(responseBody); - String id = jsonNode.get("id").asText(); - String nickname = jsonNode.get("properties").get("nickname").asText(); - String email = jsonNode.get("kakao_account").get("email").asText(); - - List kakaoUserInfoList = Arrays.asList(id, nickname, email); - - return kakaoUserInfoList; - } -} diff --git a/src/main/java/com/example/ReviewZIP/domain/oauth/dto/Response/OauthResponseDto.java b/src/main/java/com/example/ReviewZIP/domain/oauth/dto/Response/OauthResponseDto.java deleted file mode 100644 index 98576647..00000000 --- a/src/main/java/com/example/ReviewZIP/domain/oauth/dto/Response/OauthResponseDto.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.example.ReviewZIP.domain.oauth.dto.Response; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.*; - - -public class OauthResponseDto { - -} \ No newline at end of file diff --git a/src/main/java/com/example/ReviewZIP/domain/oauth/dto/request/OauthRequestDto.java b/src/main/java/com/example/ReviewZIP/domain/oauth/dto/request/OauthRequestDto.java deleted file mode 100644 index 06ad296b..00000000 --- a/src/main/java/com/example/ReviewZIP/domain/oauth/dto/request/OauthRequestDto.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.example.ReviewZIP.domain.oauth.dto.request; - -import lombok.Getter; - - -public class OauthRequestDto { - - @Getter - public static class kakaoTokenRequestDto{ - String token; - } -} \ No newline at end of file diff --git a/src/main/java/com/example/ReviewZIP/domain/post/PostsController.java b/src/main/java/com/example/ReviewZIP/domain/post/PostsController.java index 621972d1..87a135b5 100644 --- a/src/main/java/com/example/ReviewZIP/domain/post/PostsController.java +++ b/src/main/java/com/example/ReviewZIP/domain/post/PostsController.java @@ -2,6 +2,7 @@ import com.example.ReviewZIP.domain.post.dto.request.PostRequestDto; import com.example.ReviewZIP.domain.post.dto.response.PostResponseDto; +import com.example.ReviewZIP.domain.postHashtag.PostHashtags; import com.example.ReviewZIP.domain.user.Users; import com.example.ReviewZIP.global.response.ApiResponse; import com.example.ReviewZIP.global.response.code.resultCode.SuccessStatus; @@ -28,16 +29,15 @@ public class PostsController { @Operation(summary = "해시태그 아이디로 게시글을 찾는 API",description = "해시태그 아이디로 게시글을 찾는 기능, 반환 시 PostPreviewListDto, PostPreviewDto 사용") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "POST403", description = "일치하는 해시태그가 존재하지 않습니다.",content = @Content(schema = @Schema(implementation = ApiResponse.class))), }) @Parameters({ @Parameter(name = "hashtagId", description = "해시태그 아이디"), - @Parameter(name = "page", description = "페이지 번호"), - @Parameter(name = "size", description = "페이징 사이즈") }) - public ApiResponse searchPostsByHashtagId(@PathVariable Long hashtagId, @RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "0") Integer size) { - Page postsPage = postsService.searchPostByHashtag(hashtagId, page, size); - PostResponseDto.PostPreviewListDto postPreviewListDto = PostsConverter.toPostPreviewListDto(postsPage); - return ApiResponse.onSuccess(postPreviewListDto); + public ApiResponse> searchPostsByHashtagId(@PathVariable Long hashtagId) { + List postList = postsService.searchPostByHashtag(hashtagId); + List getPostInfoDtoList = postsService.getPostInfoDtoList(postList); + return ApiResponse.onSuccess(getPostInfoDtoList); } // 특정 게시글의 정보 가져오기 @@ -104,9 +104,9 @@ public ApiResponse> getPostLikeUserList(@P List postLikeUserList = postsService.getPostLikeUserList(postId); List userFollowingList = postsService.getFollowigIdList(); - List likeAndFollowing = PostsConverter.toPostUserLikeListDto(postLikeUserList, userFollowingList); + List postLikeList = PostsConverter.toPostUserLikeListDto(postLikeUserList, userFollowingList); - return ApiResponse.onSuccess(likeAndFollowing); + return ApiResponse.onSuccess(postLikeList); } @DeleteMapping("/{postId}") diff --git a/src/main/java/com/example/ReviewZIP/domain/post/PostsConverter.java b/src/main/java/com/example/ReviewZIP/domain/post/PostsConverter.java index a32c6f71..a6526c44 100644 --- a/src/main/java/com/example/ReviewZIP/domain/post/PostsConverter.java +++ b/src/main/java/com/example/ReviewZIP/domain/post/PostsConverter.java @@ -26,28 +26,6 @@ public PostsConverter(UsersRepository usersRepository, FollowsRepository follows } - public static PostResponseDto.PostPreviewDto toPostPreviewDto(Posts post) { - return PostResponseDto.PostPreviewDto.builder() - .id(post.getId()) - .likeNum(post.getPostLikeList().size()) - .scrabNum(post.getScrabList().size()) - .imageUrl(post.getPostImageList().get(0).getUrl()) - .build(); - } - - public static PostResponseDto.PostPreviewListDto toPostPreviewListDto(Page postList) { - List postPreviewDtoList = postList.stream() - .map(PostsConverter::toPostPreviewDto).collect(Collectors.toList()); - - return PostResponseDto.PostPreviewListDto.builder() - .isLast(postList.isLast()) - .isFirst(postList.isFirst()) - .totalPage(postList.getTotalPages()) - .totalElements(postList.getTotalElements()) - .listSize(postPreviewDtoList.size()) - .postList(postPreviewDtoList) - .build(); - } public static PostResponseDto.CreatedPostResponseDto toPostResponseDto(Posts post) { List imageIds = post.getPostImageList().stream() .map(Images::getId) @@ -63,29 +41,41 @@ public static PostResponseDto.CreatedPostResponseDto toPostResponseDto(Posts pos } public static PostResponseDto.UserInfoDto toUserInfoDto(Users user){ return PostResponseDto.UserInfoDto.builder() - .id(user.getId()) + .userId(user.getId()) + .name(user.getName()) .nickname(user.getNickname()) .profileUrl(user.getProfileUrl()) .build(); } - public static PostResponseDto.ImageListDto toImageListDto(Images image){ - return PostResponseDto.ImageListDto.builder() - .id(image.getId()) - .url(image.getUrl()) + public static PostResponseDto.ImageDto toImageDto(Images image){ + return PostResponseDto.ImageDto.builder() + .imageId(image.getId()) + .imageUrl(image.getUrl()) .build(); } - public static PostResponseDto.PostInfoDto toPostInfoResultDto(Users user,Posts post, boolean checkLike, boolean checkScrab, String createdAt){ + + public static PostResponseDto.HashtagDto toHashtagDto(PostHashtags postHashtags){ + return PostResponseDto.HashtagDto.builder() + .hashtagId(postHashtags.getId()) + .tagName(postHashtags.getHashtag()) + .build(); + } + public static PostResponseDto.PostInfoDto toPostInfoResultDto(Posts post, Users user, boolean checkLike, boolean checkScrab, String createdAt){ PostResponseDto.UserInfoDto userInfoDto = toUserInfoDto(post.getUser()); - List imageListDto = post.getPostImageList().stream() - .map(PostsConverter::toImageListDto).collect(Collectors.toList()); + List imageListDto = post.getPostImageList().stream() + .map(PostsConverter::toImageDto).collect(Collectors.toList()); + + List hashtagList = post.getPostHashtagList().stream() + .map(PostsConverter::toHashtagDto).collect(Collectors.toList()); boolean mine = false; if(user.getId().equals(post.getUser().getId())) { mine = true; } + return PostResponseDto.PostInfoDto.builder() .postId(post.getId()) .comment(post.getComment()) @@ -94,8 +84,8 @@ public static PostResponseDto.PostInfoDto toPostInfoResultDto(Users user,Posts p .hashtagNum(post.getPostHashtagList().size()) .checkLike(checkLike) .checkScrab(checkScrab) - .hashtags(post.getPostHashtagList().stream().map(PostHashtags::getHashtag).collect(Collectors.toList())) - .userInfo(userInfoDto) + .hashtags(hashtagList) + .user(userInfoDto) .checkMine(mine) .postImages(imageListDto) .createdAt(createdAt) @@ -108,6 +98,7 @@ public static List toPostUserLikeListDto(List { - Page findAllByUser(Users user, PageRequest pageRequest); @Query("SELECT count(p) FROM Posts p WHERE p.user != :user") long countByUserNot(@Param("user") Users user); diff --git a/src/main/java/com/example/ReviewZIP/domain/post/PostsService.java b/src/main/java/com/example/ReviewZIP/domain/post/PostsService.java index fca224c4..96fd65b2 100644 --- a/src/main/java/com/example/ReviewZIP/domain/post/PostsService.java +++ b/src/main/java/com/example/ReviewZIP/domain/post/PostsService.java @@ -15,10 +15,7 @@ import com.example.ReviewZIP.domain.user.Users; import com.example.ReviewZIP.domain.user.UsersRepository; import com.example.ReviewZIP.global.response.code.resultCode.ErrorStatus; -import com.example.ReviewZIP.global.response.exception.handler.ImagesHandler; -import com.example.ReviewZIP.global.response.exception.handler.PostLikesHandler; -import com.example.ReviewZIP.global.response.exception.handler.PostsHandler; -import com.example.ReviewZIP.global.response.exception.handler.UsersHandler; +import com.example.ReviewZIP.global.response.exception.handler.*; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; @@ -49,16 +46,12 @@ public class PostsService { private final PostHashtagsRepository postHashtagsRepository; private final FollowsRepository followsRepository; - public Page searchPostByHashtag (Long id, Integer page, Integer size){ - Page postHashtagsList = postHashtagsRepository.findPostHashtagsById(id, PageRequest.of(page,size)); - - List postsList = postHashtagsList.getContent().stream() - .map(PostHashtags::getPost) - .collect(Collectors.toList()); - - return new PageImpl<>(postsList, postHashtagsList.getPageable(), postHashtagsList.getTotalElements()); - + public List searchPostByHashtag (Long hashtagId){ + PostHashtags postHashtags = postHashtagsRepository.findById(hashtagId).orElseThrow(()->new PostHashtagsHandler(ErrorStatus.HASHTAG_NOT_FOUND)); + String tagName = postHashtags.getHashtag(); + return postHashtagsRepository.findAllByHashtag(tagName); } + @Transactional public Posts createPost(PostRequestDto postRequestDto) { Users user = usersRepository.findById(postRequestDto.getUserId()).orElseThrow(() -> new UsersHandler(ErrorStatus.USER_NOT_FOUND)); @@ -105,7 +98,7 @@ public PostResponseDto.PostInfoDto getOneRandomPostInfoDto(Long userId) { boolean checkScrab = scrabsRepository.existsByUserAndPost(user, post); String createdAt = getCreatedAt(post.getCreatedAt()); - return PostsConverter.toPostInfoResultDto(user, post, checkLike, checkScrab, createdAt); + return PostsConverter.toPostInfoResultDto(post, user, checkLike, checkScrab, createdAt); } throw new PostsHandler(ErrorStatus.NON_USER_POST_REQUIRED); } @@ -140,7 +133,7 @@ public List getThreeRandomPostsInfo(Long userId) { boolean checkScrab = scrabsRepository.existsByUserAndPost(user, post); String createdAt = getCreatedAt(post.getCreatedAt()); - randomPostInfoDtos.add(PostsConverter.toPostInfoResultDto(user, post, checkLike, checkScrab, createdAt)); + randomPostInfoDtos.add(PostsConverter.toPostInfoResultDto(post, user, checkLike, checkScrab, createdAt)); } } @@ -157,7 +150,13 @@ public PostResponseDto.PostInfoDto getPostInfoDto(Long postId){ String createdAt = getCreatedAt(post.getCreatedAt()); - return PostsConverter.toPostInfoResultDto(user, post, checkLike, checkScrab, createdAt); + return PostsConverter.toPostInfoResultDto(post, user, checkLike, checkScrab, createdAt); + } + + List getPostInfoDtoList(List postHashtagList){ + return postHashtagList.stream() + .map(postHashtag -> getPostInfoDto(postHashtag.getPost().getId())) + .collect(Collectors.toList()); } public String getCreatedAt(LocalDateTime createdAt){ @@ -220,7 +219,7 @@ public void addLike(Long postId) { public List getFollowigIdList(){ // 일단 1L로 나를 대체 Users me = usersRepository.getById(1L); - List followingList = followsRepository.findAllBySender(me); + List followingList = me.getFollowingList(); List followingIdList = new ArrayList<>(); for (Follows following : followingList){ diff --git a/src/main/java/com/example/ReviewZIP/domain/post/dto/response/PostResponseDto.java b/src/main/java/com/example/ReviewZIP/domain/post/dto/response/PostResponseDto.java index c291dfb7..e2d5699d 100644 --- a/src/main/java/com/example/ReviewZIP/domain/post/dto/response/PostResponseDto.java +++ b/src/main/java/com/example/ReviewZIP/domain/post/dto/response/PostResponseDto.java @@ -10,22 +10,13 @@ public class PostResponseDto { - @Builder - @Getter - @NoArgsConstructor - @AllArgsConstructor - public static class PostPreviewDto { - private Long id; - private String imageUrl; - private Integer likeNum; - private Integer scrabNum; - } @Builder @Getter @NoArgsConstructor @AllArgsConstructor public static class UserInfoDto{ - private Long id; + private Long userId; + private String name; private String nickname; private String profileUrl; } @@ -33,23 +24,20 @@ public static class UserInfoDto{ @Builder @Getter @AllArgsConstructor - public static class ImageListDto{ - private Long id; - private String url; + public static class ImageDto{ + private Long imageId; + private String imageUrl; } @Builder @Getter @NoArgsConstructor @AllArgsConstructor - public static class PostPreviewListDto { - private List postList; - private Integer listSize; - private Integer totalPage; - private Long totalElements; - private Boolean isFirst; - private Boolean isLast; + public static class HashtagDto{ + private Long hashtagId; + private String tagName; } + @Builder @Getter @NoArgsConstructor @@ -64,9 +52,9 @@ public static class PostInfoDto{ private boolean checkScrab; private boolean checkMine; private String createdAt; - private UserInfoDto userInfo; - private List hashtags; - private List postImages; + private UserInfoDto user; + private List hashtags; + private List postImages; } @Builder @@ -87,17 +75,9 @@ public static class CreatedPostResponseDto { @AllArgsConstructor public static class PostUserLikeDto{ private Long userId; + private String name; private String nickname; private String profileUrl; private boolean following; } - - @Getter - @Builder - @NoArgsConstructor - @AllArgsConstructor - public static class PostUserLikeListDto{ - private List userLikeDto; - } - } diff --git a/src/main/java/com/example/ReviewZIP/domain/postHashtag/PostHashtagsController.java b/src/main/java/com/example/ReviewZIP/domain/postHashtag/PostHashtagsController.java index 2fb21820..b0329cc6 100644 --- a/src/main/java/com/example/ReviewZIP/domain/postHashtag/PostHashtagsController.java +++ b/src/main/java/com/example/ReviewZIP/domain/postHashtag/PostHashtagsController.java @@ -7,8 +7,6 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponses; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; @@ -23,7 +21,7 @@ public class PostHashtagsController { private final PostHashtagsService postHashtagsService; @GetMapping("/{postId}") - @Operation(summary = "게시물에 해시태그 추가 API", description = "DB와 레디스에 해시태그를 추가") + @Operation(summary = "게시물에 해시태그 추가 API", description = "게시물에 해시태그를 추가") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), }) @@ -38,7 +36,7 @@ public ApiResponse addHashtags(@RequestParam String query, @PathV } @GetMapping("/search") - @Operation(summary = "해시태그 이름으로 해시태그를 검색 API", description = "해시태그 이름으로 검색 시 해시태그 리스트를 반환하고 검색기록에 저장") + @Operation(summary = "해시태그 이름으로 해시태그를 검색 API", description = "해시태그 이름으로 검색 시 해시태그 리스트를 반환하고 검색기록에 저장, PostHashtagsPreviewDto 이용") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), }) diff --git a/src/main/java/com/example/ReviewZIP/domain/postHashtag/PostHashtagsConverter.java b/src/main/java/com/example/ReviewZIP/domain/postHashtag/PostHashtagsConverter.java index 33bc77e3..5c03b768 100644 --- a/src/main/java/com/example/ReviewZIP/domain/postHashtag/PostHashtagsConverter.java +++ b/src/main/java/com/example/ReviewZIP/domain/postHashtag/PostHashtagsConverter.java @@ -9,8 +9,8 @@ public class PostHashtagsConverter { public static PostHashtagResponseDto.PostHashtagsPreviewDto toPostHashtagsPreviewDto(PostHashtags postHashtags) { return PostHashtagResponseDto.PostHashtagsPreviewDto.builder() - .id(postHashtags.getId()) - .name(postHashtags.getHashtag()) + .hashtagId(postHashtags.getId()) + .tagName(postHashtags.getHashtag()) .build(); } diff --git a/src/main/java/com/example/ReviewZIP/domain/postHashtag/PostHashtagsRepository.java b/src/main/java/com/example/ReviewZIP/domain/postHashtag/PostHashtagsRepository.java index d92006a8..b72f7e1a 100644 --- a/src/main/java/com/example/ReviewZIP/domain/postHashtag/PostHashtagsRepository.java +++ b/src/main/java/com/example/ReviewZIP/domain/postHashtag/PostHashtagsRepository.java @@ -1,7 +1,5 @@ package com.example.ReviewZIP.domain.postHashtag; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -11,10 +9,10 @@ public interface PostHashtagsRepository extends JpaRepository { - Page findPostHashtagsById(Long id, PageRequest pageRequest); + List findAllByHashtag(String hashtag); - @Query("SELECT ph FROM PostHashtags ph WHERE ph.hashtag LIKE %:name%") + @Query("SELECT DISTINCT ph FROM PostHashtags ph WHERE ph.hashtag LIKE %:name%") List findByNameContaining(@Param("name") String name); } diff --git a/src/main/java/com/example/ReviewZIP/domain/postHashtag/PostHashtagsService.java b/src/main/java/com/example/ReviewZIP/domain/postHashtag/PostHashtagsService.java index 2dd5f9c1..85e3af89 100644 --- a/src/main/java/com/example/ReviewZIP/domain/postHashtag/PostHashtagsService.java +++ b/src/main/java/com/example/ReviewZIP/domain/postHashtag/PostHashtagsService.java @@ -20,8 +20,6 @@ public class PostHashtagsService { private final PostHashtagsRepository postHashtagsRepository; private final RedisService redisService; private final PostsRepository postsRepository; - private final UsersRepository usersRepository; - private final SearchHistoriesRepository searchHistoriesRepository; @Transactional public void addHashtags(String query, Long postId) { diff --git a/src/main/java/com/example/ReviewZIP/domain/postHashtag/dto/response/PostHashtagResponseDto.java b/src/main/java/com/example/ReviewZIP/domain/postHashtag/dto/response/PostHashtagResponseDto.java index 13e56b61..d9b7322c 100644 --- a/src/main/java/com/example/ReviewZIP/domain/postHashtag/dto/response/PostHashtagResponseDto.java +++ b/src/main/java/com/example/ReviewZIP/domain/postHashtag/dto/response/PostHashtagResponseDto.java @@ -14,7 +14,7 @@ public class PostHashtagResponseDto { @NoArgsConstructor @AllArgsConstructor public static class PostHashtagsPreviewDto { - private Long id; - private String name; + private Long hashtagId; + private String tagName; } } diff --git a/src/main/java/com/example/ReviewZIP/domain/searchHistory/SearchHistoriesRepository.java b/src/main/java/com/example/ReviewZIP/domain/searchHistory/SearchHistoriesRepository.java index cb31c5d1..ceefea17 100644 --- a/src/main/java/com/example/ReviewZIP/domain/searchHistory/SearchHistoriesRepository.java +++ b/src/main/java/com/example/ReviewZIP/domain/searchHistory/SearchHistoriesRepository.java @@ -8,7 +8,4 @@ @Repository public interface SearchHistoriesRepository extends JpaRepository { - SearchHistories findByUserAndObjectId(Users user, Users object); - - SearchHistories findByUserAndHashtag(Users user, String hashtag); } diff --git a/src/main/java/com/example/ReviewZIP/domain/token/RefreshTokenController.java b/src/main/java/com/example/ReviewZIP/domain/token/RefreshTokenController.java index 6cec1c59..7c78470e 100644 --- a/src/main/java/com/example/ReviewZIP/domain/token/RefreshTokenController.java +++ b/src/main/java/com/example/ReviewZIP/domain/token/RefreshTokenController.java @@ -18,7 +18,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -@Tag(name = "로컬 로그인/회원가입", description = "로컬 로그인, 회원가입 API") +@Tag(name = "token-controller", description = "로컬 로그인, 회원가입 API") @RestController @RequestMapping("/auth") @RequiredArgsConstructor diff --git a/src/main/java/com/example/ReviewZIP/domain/user/Users.java b/src/main/java/com/example/ReviewZIP/domain/user/Users.java index 01251c52..41a6c43e 100644 --- a/src/main/java/com/example/ReviewZIP/domain/user/Users.java +++ b/src/main/java/com/example/ReviewZIP/domain/user/Users.java @@ -6,6 +6,7 @@ import com.example.ReviewZIP.domain.scrab.Scrabs; import com.example.ReviewZIP.domain.searchHistory.SearchHistories; import com.example.ReviewZIP.domain.token.dto.SignUpRequestDto; +import com.example.ReviewZIP.domain.userStores.UserStores; import com.example.ReviewZIP.global.entity.BaseEntity; import jakarta.persistence.*; import lombok.*; @@ -13,7 +14,9 @@ import org.hibernate.annotations.Where; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; @Entity @Getter @@ -73,6 +76,9 @@ public class Users extends BaseEntity { @OneToMany(mappedBy = "object", cascade = CascadeType.ALL) private List objectList = new ArrayList<>(); + @OneToMany(mappedBy = "user") + private Set userStores = new HashSet<>(); + public static Users toEntity(SignUpRequestDto signUpRequestDto) { return Users.builder() .name(signUpRequestDto.getName()) diff --git a/src/main/java/com/example/ReviewZIP/domain/user/UsersController.java b/src/main/java/com/example/ReviewZIP/domain/user/UsersController.java index 5fd48c83..4af40a5b 100644 --- a/src/main/java/com/example/ReviewZIP/domain/user/UsersController.java +++ b/src/main/java/com/example/ReviewZIP/domain/user/UsersController.java @@ -2,10 +2,12 @@ import com.example.ReviewZIP.domain.follow.Follows; import com.example.ReviewZIP.domain.post.Posts; +import com.example.ReviewZIP.domain.post.dto.response.PostResponseDto; import com.example.ReviewZIP.domain.scrab.Scrabs; import com.example.ReviewZIP.domain.searchHistory.SearchHistories; -import com.example.ReviewZIP.domain.user.dto.response.FollowResponseDto; import com.example.ReviewZIP.domain.user.dto.response.UserResponseDto; +import com.example.ReviewZIP.domain.userStores.UserStoresService; +import com.example.ReviewZIP.domain.userStores.dto.response.UserStoresResponseDto; import com.example.ReviewZIP.global.response.ApiResponse; import com.example.ReviewZIP.global.response.code.resultCode.SuccessStatus; import io.swagger.v3.oas.annotations.Operation; @@ -15,7 +17,6 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponses; import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -27,7 +28,20 @@ @RequestMapping("/v1/users") public class UsersController { private final UsersService usersService; + private final UserStoresService userStoresService; + @GetMapping("/{userId}/stores") + @Operation(summary = "특정 유저의 관심 장소 목록 API",description = "특정 특정 유저의 관심 장소 목록을 가져온다, 반환 시 StoreInfoListDto 사용") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER404", description = "유저가 존재하지 않습니다",content = @Content(schema = @Schema(implementation = ApiResponse.class))), + }) + @Parameters({ + @Parameter(name = "userId", description = "유저의 아이디"), + }) + public ApiResponse getStoresByUser(@PathVariable Long userId) { + return ApiResponse.onSuccess(userStoresService.getStoreInfo(userId)); + } @GetMapping("/search/name") @Operation(summary = "이름으로 유저 검색 API",description = "유저의 이름으로 특정 유저를 검색 (자신이 팔로잉한 대상은 제외), UserPreviewDto 이용") @ApiResponses({ @@ -62,33 +76,33 @@ public ApiResponse> searchUsersByNickname(@ } @GetMapping("/me/followings") - @Operation(summary = "나의 팔로잉 목록 가져오기 API",description = "토큰 인증 후 나의 팔로잉 목록 조회, FollowingPreviewDto 이용, 임시로 user id 1의 팔로잉 목록 반환") + @Operation(summary = "나의 팔로잉 목록 가져오기 API",description = "토큰 인증 후 나의 팔로잉 목록 조회, UserPreviewDto 이용") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER404", description = "토큰에 해당하는 유저 없음",content = @Content(schema = @Schema(implementation = ApiResponse.class))), }) - public ApiResponse> getUserFollowingList(){ - List FollowsPage = usersService.getFollowingList(1L); //수정 필요 + public ApiResponse> getUserFollowingList(){ + List FollowingList = usersService.getFollowingList(1L); //수정 필요 List followingIdList = usersService.getFollowigIdList(1L); - return ApiResponse.onSuccess(UsersConverter.toFollowingPreviewListDto(FollowsPage, followingIdList)); + return ApiResponse.onSuccess(UsersConverter.toFollowPreviewListDto(FollowingList, followingIdList)); } @GetMapping("/me/followers") - @Operation(summary = "나의 팔로워 목록 가져오기 API",description = "토큰 인증 후 나의 팔로워 목록 조회, FollowerPreviewDto 이용, 임시로 user id 1의 팔로잉 목록 반환") + @Operation(summary = "나의 팔로워 목록 가져오기 API",description = "토큰 인증 후 나의 팔로워 목록 조회, UserPreviewDto 이용") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER404", description = "토큰에 해당하는 유저 없음",content = @Content(schema = @Schema(implementation = ApiResponse.class))), }) - public ApiResponse> getUserFollowerList(){ + public ApiResponse> getUserFollowerList(){ - List FollowsPage = usersService.getFollowerList(1L); //수정 필요 + List FollowerList = usersService.getFollowerList(1L); //수정 필요 List followingIdList = usersService.getFollowigIdList(1L); - return ApiResponse.onSuccess(UsersConverter.toFollowerPreviewListDto(FollowsPage, followingIdList)); + return ApiResponse.onSuccess(UsersConverter.toFollowPreviewListDto(FollowerList, followingIdList)); } @GetMapping("/{userId}/followings") - @Operation(summary = "특정 유저의 팔로잉 목록 가져오기 API",description = "특정 유저의 id를 이용하여 해당 유저의 팔로잉 목록 조회, FollowingPreviewDto 이용") + @Operation(summary = "특정 유저의 팔로잉 목록 가져오기 API",description = "특정 유저의 id를 이용하여 해당 유저의 팔로잉 목록 조회, UserPreviewDto 이용") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER404", description = "유저가 존재하지 않습니다",content = @Content(schema = @Schema(implementation = ApiResponse.class))), @@ -96,14 +110,14 @@ public ApiResponse> getUserFollowerLi @Parameters({ @Parameter(name = "userId", description = "유저의 아이디"), }) - public ApiResponse> getOtherFollowingList(@PathVariable(name = "userId") Long userId){ - List FollowsPage = usersService.getFollowingList(userId); + public ApiResponse> getOtherFollowingList(@PathVariable(name = "userId") Long userId){ + List FollowingList = usersService.getFollowingList(userId); List followingIdList = usersService.getFollowigIdList(userId); - return ApiResponse.onSuccess(UsersConverter.toFollowingPreviewListDto(FollowsPage, followingIdList)); + return ApiResponse.onSuccess(UsersConverter.toFollowPreviewListDto(FollowingList, followingIdList)); } @GetMapping("/{userId}/followers") - @Operation(summary = "특정 유저의 팔로워 목록 가져오기 API",description = "특정 유저의 id를 이용하여 해당 유저의 팔로워 목록 조회, FollowerPreviewDto 이용") + @Operation(summary = "특정 유저의 팔로워 목록 가져오기 API",description = "특정 유저의 id를 이용하여 해당 유저의 팔로워 목록 조회, UserPreviewDto 이용") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER404", description = "유저가 존재하지 않습니다",content = @Content(schema = @Schema(implementation = ApiResponse.class))), @@ -111,79 +125,65 @@ public ApiResponse> getOtherFollowin @Parameters({ @Parameter(name = "userId", description = "유저의 아이디"), }) - public ApiResponse> getOtherFollowerList(@PathVariable(name = "userId")Long userId){ - List FollowsPage = usersService.getFollowerList(userId); + public ApiResponse> getOtherFollowerList(@PathVariable(name = "userId")Long userId){ + List FollowerList = usersService.getFollowerList(userId); List followingIdList = usersService.getFollowigIdList(userId); - return ApiResponse.onSuccess(UsersConverter.toFollowerPreviewListDto(FollowsPage, followingIdList)); + return ApiResponse.onSuccess(UsersConverter.toFollowPreviewListDto(FollowerList, followingIdList)); } @GetMapping("/me/posts") - @Operation(summary = "나의 게시물 목록 가져오기 API",description = "토큰 인증 후 게시글 목록 가져오기, PostPreviewDto와 PostPreviewListDto 이용") + @Operation(summary = "나의 게시물 목록 가져오기 API",description = "토큰 인증 후 게시글 목록 가져오기, UserInfoDto & ImageDto & HashtagDto & PostInfoDto 이용") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), }) - @Parameters({ - @Parameter(name = "page", description = "페이지 번호"), - @Parameter(name = "size", description = "페이징 사이즈") - }) - public ApiResponse getUserPostList(@RequestParam(name = "page")Integer page, @RequestParam(name = "size")Integer size){ + public ApiResponse> getUserPostList(){ // 토큰값 받아서 유저확인 하는 부분, 일단 1L로 대체 - Page UserPage = usersService.getPostList(1L, page, size); - - return ApiResponse.onSuccess(UsersConverter.toPostPreviewListDto(UserPage)); + List postList = usersService.getPostList(1L); + List postInfoDtoList = usersService.getPostInfoDtoList(1L, postList); + return ApiResponse.onSuccess(postInfoDtoList); } @GetMapping("/me/posts/scrabs") - @Operation(summary = "내가 스크랩한 게시물 가져오기 API",description = "토큰 인증 후 스크랩한 게시글들의 목록(대표 이미지들)을 반환, PostPreviewDto와 PostPreviewListDto 이용") + @Operation(summary = "내가 스크랩한 게시물 가져오기 API",description = "토큰 인증 후 스크랩한 게시글들의 목록(대표 이미지들)을 반환, UserInfoDto & ImageDto & HashtagDto & PostInfoDto 이용") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER404", description = "토큰에 해당하는 유저 없음",content = @Content(schema = @Schema(implementation = ApiResponse.class))), }) - @Parameters({ - @Parameter(name = "page", description = "페이지 번호"), - @Parameter(name = "size", description = "페이징 사이즈") - }) - public ApiResponse getUserScrabList(@RequestParam(name = "page")Integer page, @RequestParam(name = "size") Integer size) { - Page UserPage = usersService.getScrabList(1L, page, size); - - return ApiResponse.onSuccess(UsersConverter.toScrabPreviewListDto(UserPage)); + public ApiResponse> getUserScrabList() { + List scrabList = usersService.getScrabList(1L); + List scrabInfoDtoList = usersService.getScrabInfoDtoList(1L, scrabList); + return ApiResponse.onSuccess(scrabInfoDtoList); } @GetMapping("/{userId}/posts") - @Operation(summary = "특정 유저의 게시글 목록 가져오기 API",description = "특정 유저의 id를 받아 게시글들의 목록(대표 이미지들)을 반환, PostPreviewDto와 PostPreviewListDto 이용") + @Operation(summary = "특정 유저의 게시글 목록 가져오기 API",description = "특정 유저의 id를 받아 게시글들의 목록(대표 이미지들)을 반환, UserInfoDto & ImageDto & HashtagDto & PostInfoDto 이용") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER404", description = "토큰에 해당하는 유저 없음",content = @Content(schema = @Schema(implementation = ApiResponse.class))), }) @Parameters({ @Parameter(name = "userId", description = "유저의 아이디"), - @Parameter(name = "page", description = "페이지 번호"), - @Parameter(name = "size", description = "페이징 사이즈") }) - public ApiResponse getOtherPostList(@PathVariable(name = "userId") Long userId - , @RequestParam(name = "page") Integer page , @RequestParam(name = "size") Integer size){ - Page UserPage = usersService.getPostList(userId, page, size); - - return ApiResponse.onSuccess(UsersConverter.toPostPreviewListDto(UserPage)); - + public ApiResponse> getOtherPostList(@PathVariable(name = "userId") Long userId){ + List postList = usersService.getPostList(userId); + List postInfoDtoList = usersService.getPostInfoDtoList(userId, postList); + return ApiResponse.onSuccess(postInfoDtoList); } // 특정 유저의 스크랩들 가져오기 @GetMapping("/{userId}/posts/scrabs") - @Operation(summary = "특정 유저가 스크랩한 게시물 가져오기 API",description = "특정 유저의 id를 받아 스크랩한 게시글들의 목록(대표 이미지들)을 반환, PostPreviewDto와 PostPreviewListDto 이용") + @Operation(summary = "특정 유저가 스크랩한 게시물 가져오기 API",description = "특정 유저의 id를 받아 스크랩한 게시글들의 목록(대표 이미지들)을 반환, UserInfoDto & ImageDto & HashtagDto & PostInfoDto 이용") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER404", description = "유저가 존재하지 않습니다",content = @Content(schema = @Schema(implementation = ApiResponse.class))), }) @Parameters({ @Parameter(name = "userId", description = "유저의 아이디"), - @Parameter(name = "page", description = "페이지 번호"), - @Parameter(name = "size", description = "페이징 사이즈") }) - public ApiResponse getOtherScrabList(@PathVariable(name = "userId") Long userId, @RequestParam(name = "page")Integer page, @RequestParam(name = "size") Integer size) { - Page UserPage = usersService.getScrabList(userId, page, size); - - return ApiResponse.onSuccess(UsersConverter.toScrabPreviewListDto(UserPage)); + public ApiResponse> getOtherScrabList(@PathVariable(name = "userId") Long userId) { + List scrabList = usersService.getScrabList(userId); + List scrabInfoDtoList = usersService.getScrabInfoDtoList(userId, scrabList); + return ApiResponse.onSuccess(scrabInfoDtoList); } @GetMapping("/{userId}") @@ -224,7 +224,7 @@ public ApiResponse deleteUser(@PathVariable(name = "userId")Long return ApiResponse.onSuccess(SuccessStatus._OK); } - @GetMapping("/histories") + @GetMapping("/me/histories") @Operation(summary = "검색기록 가져오기 API",description = "나의 검색기록을 가져온다.") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), diff --git a/src/main/java/com/example/ReviewZIP/domain/user/UsersConverter.java b/src/main/java/com/example/ReviewZIP/domain/user/UsersConverter.java index 4cf8ba6b..5eab81cd 100644 --- a/src/main/java/com/example/ReviewZIP/domain/user/UsersConverter.java +++ b/src/main/java/com/example/ReviewZIP/domain/user/UsersConverter.java @@ -1,15 +1,11 @@ package com.example.ReviewZIP.domain.user; import com.example.ReviewZIP.domain.follow.Follows; -import com.example.ReviewZIP.domain.post.Posts; -import com.example.ReviewZIP.domain.scrab.Scrabs; import com.example.ReviewZIP.domain.searchHistory.SearchHistories; import com.example.ReviewZIP.domain.searchHistory.SearchType; -import com.example.ReviewZIP.domain.user.dto.response.FollowResponseDto; import com.example.ReviewZIP.domain.user.dto.response.UserResponseDto; import com.example.ReviewZIP.global.response.code.resultCode.ErrorStatus; import com.example.ReviewZIP.global.response.exception.handler.SearchHandler; -import org.springframework.data.domain.Page; import java.util.List; import java.util.stream.Collectors; @@ -35,9 +31,9 @@ public static List toUserPreviewListDto(List followingIdList){ + public static UserResponseDto.UserPreviewDto toFollowPreviewDto(Follows follows, List followingIdList){ boolean isFollowing = followingIdList.contains(follows.getReceiver().getId()); - return FollowResponseDto.FollowingPreviewDto.builder() + return UserResponseDto.UserPreviewDto.builder() .userId(follows.getReceiver().getId()) .name(follows.getReceiver().getName()) .profileUrl(follows.getReceiver().getProfileUrl()) @@ -46,73 +42,10 @@ public static FollowResponseDto.FollowingPreviewDto toFollowingPreviewDto(Follow .build(); } - public static List toFollowingPreviewListDto(List followsList, List followingIdList){ + public static List toFollowPreviewListDto(List followsList, List followingIdList){ return followsList.stream() - .map(follow -> toFollowingPreviewDto(follow, followingIdList)).collect(Collectors.toList()); - - } - - public static FollowResponseDto.FollowerPreviewDto toFollowerPreviewDto(Follows follows, List followingIdList){ - boolean isFollowing = followingIdList.contains(follows.getSender().getId()); - return FollowResponseDto.FollowerPreviewDto.builder() - .userId(follows.getSender().getId()) - .name(follows.getSender().getName()) - .nickname(follows.getSender().getNickname()) - .following(isFollowing) - .profileUrl(follows.getSender().getProfileUrl()) - .build(); - } - - public static List toFollowerPreviewListDto(List followsList, List followingIdList){ - return followsList.stream() - .map(follow->toFollowerPreviewDto(follow, followingIdList)).collect(Collectors.toList()); - - } + .map(follow -> toFollowPreviewDto(follow, followingIdList)).collect(Collectors.toList()); - public static UserResponseDto.PostPreviewDto toPostPreviewDto(Posts post){ - return UserResponseDto.PostPreviewDto.builder() - .postId(post.getId()) - .likeNum(post.getPostLikeList().size()) - .scrabNum(post.getScrabList().size()) - .postImageUrl(post.getPostImageList().get(0).getUrl()) - .build(); - } - - public static UserResponseDto.PostPreviewListDto toPostPreviewListDto(Page postList){ - List userPostPriviewDtoList = postList.stream() - .map(UsersConverter::toPostPreviewDto).collect(Collectors.toList()); - - return UserResponseDto.PostPreviewListDto.builder() - .isLast(postList.isLast()) - .isFirst(postList.isFirst()) - .totalElements(postList.getTotalElements()) - .totalPage(postList.getTotalPages()) - .listSize(userPostPriviewDtoList.size()) - .postList(userPostPriviewDtoList) - .build(); - } - - public static UserResponseDto.PostPreviewDto toScrabPreviewDto(Scrabs scrabs){ - return UserResponseDto.PostPreviewDto.builder() - .postId(scrabs.getPost().getId()) - .likeNum(scrabs.getPost().getPostLikeList().size()) - .scrabNum(scrabs.getPost().getScrabList().size()) - .postImageUrl(scrabs.getPost().getPostImageList().get(0).getUrl()) - .build(); - } - - public static UserResponseDto.PostPreviewListDto toScrabPreviewListDto(Page scrabList) { - List scrabPriviewDtoList = scrabList.stream() - .map(UsersConverter::toScrabPreviewDto).collect(Collectors.toList()); - - return UserResponseDto.PostPreviewListDto.builder() - .isLast(scrabList.isLast()) - .isFirst(scrabList.isFirst()) - .totalElements(scrabList.getTotalElements()) - .totalPage(scrabList.getTotalPages()) - .listSize(scrabPriviewDtoList.size()) - .postList(scrabPriviewDtoList) - .build(); } public static UserResponseDto.UserInfoDto toUserInfoDto(Users user){ diff --git a/src/main/java/com/example/ReviewZIP/domain/user/UsersRepository.java b/src/main/java/com/example/ReviewZIP/domain/user/UsersRepository.java index 43581a4e..db6652dd 100644 --- a/src/main/java/com/example/ReviewZIP/domain/user/UsersRepository.java +++ b/src/main/java/com/example/ReviewZIP/domain/user/UsersRepository.java @@ -10,16 +10,12 @@ @Repository public interface UsersRepository extends JpaRepository { - @Query("SELECT u FROM Users u WHERE u.name LIKE :name%") + @Query("SELECT u FROM Users u WHERE u.name LIKE %:name%") List findByName(String name); - @Query("SELECT u FROM Users u WHERE u.nickname LIKE :nickname%") + @Query("SELECT u FROM Users u WHERE u.nickname LIKE %:nickname%") List findByNickname(String nickname); - boolean existsBySocial(String id); - - Users getBySocial(String userId); - boolean existsByEmail(String email); Optional findByEmail(String email); diff --git a/src/main/java/com/example/ReviewZIP/domain/user/UsersService.java b/src/main/java/com/example/ReviewZIP/domain/user/UsersService.java index db733a7c..a95c6fe9 100644 --- a/src/main/java/com/example/ReviewZIP/domain/user/UsersService.java +++ b/src/main/java/com/example/ReviewZIP/domain/user/UsersService.java @@ -3,22 +3,30 @@ import com.example.ReviewZIP.domain.follow.Follows; import com.example.ReviewZIP.domain.follow.FollowsRepository; import com.example.ReviewZIP.domain.post.Posts; +import com.example.ReviewZIP.domain.post.PostsConverter; import com.example.ReviewZIP.domain.post.PostsRepository; +import com.example.ReviewZIP.domain.post.dto.response.PostResponseDto; +import com.example.ReviewZIP.domain.postLike.PostLikesRepository; import com.example.ReviewZIP.domain.scrab.Scrabs; import com.example.ReviewZIP.domain.scrab.ScrabsRepository; import com.example.ReviewZIP.domain.searchHistory.SearchHistories; import com.example.ReviewZIP.domain.user.dto.response.UserResponseDto; import com.example.ReviewZIP.global.response.code.resultCode.ErrorStatus; +import com.example.ReviewZIP.global.response.exception.handler.PostsHandler; import com.example.ReviewZIP.global.response.exception.handler.UsersHandler; import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.Duration; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; @Service @RequiredArgsConstructor @@ -28,6 +36,7 @@ public class UsersService { private final FollowsRepository followsRepository; private final PostsRepository postsRepository; private final ScrabsRepository scrabsRepository; + private final PostLikesRepository postLikesRepository; public List findUsersByName(String name) { List pageUsers = usersRepository.findByName(name); @@ -44,7 +53,7 @@ public List findUsersByNickname(String nickname) throws UsersHandler { public List getFollowigIdList(Long userId){ // 일단 1L로 나를 대체 Users me = usersRepository.getById(userId); - List followingList = followsRepository.findAllBySender(me); + List followingList = me.getFollowingList(); List followingIdList = new ArrayList<>(); for (Follows following : followingList){ @@ -55,34 +64,15 @@ public List getFollowigIdList(Long userId){ } public List getFollowingList(Long userId){ - Users sender = usersRepository.findById(userId).orElseThrow(()->new UsersHandler(ErrorStatus.USER_NOT_FOUND)); - List FollowsPage = followsRepository.findAllBySender(sender); - - return FollowsPage; - } - - public List getFollowerList(Long userId){ - Users receiver = usersRepository.findById(userId).orElseThrow(()->new UsersHandler(ErrorStatus.USER_NOT_FOUND)); - List FollowsPage = followsRepository.findAllByReceiver(receiver); - - return FollowsPage; - } - - public Page getPostList(Long userId, Integer page, Integer size){ Users user = usersRepository.findById(userId).orElseThrow(()->new UsersHandler(ErrorStatus.USER_NOT_FOUND)); - Page UserPage = postsRepository.findAllByUser(user, PageRequest.of(page, size)); - - return UserPage; + return user.getFollowingList(); } - public Page getScrabList(Long userId, Integer page, Integer size){ + public List getFollowerList(Long userId){ Users user = usersRepository.findById(userId).orElseThrow(()->new UsersHandler(ErrorStatus.USER_NOT_FOUND)); - Page UserPage = scrabsRepository.findAllByUser(user, PageRequest.of(page, size)); - - return UserPage; + return user.getFollowerList(); } - // 해당 유저가 맞는지에 대한 검증 필요, 원래 1L 필요하나 일단 데이터베이스 확인을 위하여 다음과 같이 진행 @Transactional public void deleteUser(Long userId) { Users user = usersRepository.findById(userId).orElseThrow(() -> new UsersHandler(ErrorStatus.USER_NOT_FOUND)); @@ -113,4 +103,63 @@ public List getHistoryList(Long userId){ Collections.reverse(historyList); return historyList; } + + public String getCreatedAt(LocalDateTime createdAt){ + + // 서버시간을 UTC로 설정 + ZoneId serverZone = ZoneId.of("UTC"); + LocalDateTime now = ZonedDateTime.now(serverZone).toLocalDateTime(); + + Duration duration = Duration.between(createdAt, now); + + long seconds = duration.getSeconds(); + long minutes = duration.toMinutes(); + long hours = duration.toHours(); + + if (minutes < 1){ + return seconds + "초 전"; + } else if (minutes < 60){ + return minutes + "분 전"; + } else if (hours < 24){ + return hours + "시간 전"; + } else { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일"); + return createdAt.format(formatter); + } + } + + public PostResponseDto.PostInfoDto getPostInfoDto(Long postId, Long userId){ + // 좋아요와 스크랩 표시를 위하여 1L로 해당 유저를 대체 + Users user = usersRepository.getById(1L); + Posts post = postsRepository.findById(postId).orElseThrow(()->new PostsHandler(ErrorStatus.POST_NOT_FOUND)); + boolean checkLike = postLikesRepository.existsByUserAndPost(user, post); + boolean checkScrab = scrabsRepository.existsByUserAndPost(user, post); + + String createdAt = getCreatedAt(post.getCreatedAt()); + + return PostsConverter.toPostInfoResultDto(post, user, checkLike, checkScrab, createdAt); + } + + List getPostInfoDtoList(Long userId, List postList){ + return postList.stream() + .map(post -> getPostInfoDto(post.getId(), userId)) + .collect(Collectors.toList()); + } + + List getScrabInfoDtoList(Long userId, List scrabList){ + return scrabList.stream() + .map(scrab -> getPostInfoDto(scrab.getPost().getId(), 1L)) + .collect(Collectors.toList()); + } + + + List getPostList(Long userId){ + Users me = usersRepository.getById(1L); + return me.getPostList(); + } + + List getScrabList(Long userId){ + Users me = usersRepository.getById(1L); + return me.getScrabList(); + } } diff --git a/src/main/java/com/example/ReviewZIP/domain/user/dto/response/FollowResponseDto.java b/src/main/java/com/example/ReviewZIP/domain/user/dto/response/FollowResponseDto.java deleted file mode 100644 index 3b4cf5df..00000000 --- a/src/main/java/com/example/ReviewZIP/domain/user/dto/response/FollowResponseDto.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.example.ReviewZIP.domain.user.dto.response; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -public class FollowResponseDto { - - @Builder - @Getter - @NoArgsConstructor - @AllArgsConstructor - public static class FollowingPreviewDto{ - private Long userId; - private String profileUrl; - private String nickname; - private String name; - private boolean following; - } - - @Builder - @Getter - @NoArgsConstructor - @AllArgsConstructor - public static class FollowerPreviewListDto{ - private List followsList; - private Integer listSize; - private Integer totalPage; - private Long totalElements; - private Boolean isFirst; - private Boolean isLast; - } - - @Builder - @Getter - @NoArgsConstructor - @AllArgsConstructor - public static class FollowerPreviewDto{ - private Long userId; - private String profileUrl; - private String nickname; - private String name; - private boolean following; - } -} \ No newline at end of file diff --git a/src/main/java/com/example/ReviewZIP/domain/user/dto/response/UserResponseDto.java b/src/main/java/com/example/ReviewZIP/domain/user/dto/response/UserResponseDto.java index 5c035bb4..aba44fc5 100644 --- a/src/main/java/com/example/ReviewZIP/domain/user/dto/response/UserResponseDto.java +++ b/src/main/java/com/example/ReviewZIP/domain/user/dto/response/UserResponseDto.java @@ -21,19 +21,6 @@ public static class UserPreviewDto { private boolean following; } - @Builder - @Getter - @NoArgsConstructor - @AllArgsConstructor - public static class PostPreviewListDto{ - private List postList; - private Integer listSize; - private Integer totalPage; - private Long totalElements; - private Boolean isFirst; - private Boolean isLast; - } - @Builder @Getter @NoArgsConstructor diff --git a/src/main/java/com/example/ReviewZIP/domain/userStores/UserStores.java b/src/main/java/com/example/ReviewZIP/domain/userStores/UserStores.java new file mode 100644 index 00000000..6bcda41d --- /dev/null +++ b/src/main/java/com/example/ReviewZIP/domain/userStores/UserStores.java @@ -0,0 +1,38 @@ +package com.example.ReviewZIP.domain.userStores; + +import com.example.ReviewZIP.domain.user.Users; +import jakarta.persistence.*; +import lombok.*; + + +@Entity +@Getter +@Builder +@Setter +@AllArgsConstructor +@NoArgsConstructor +@Table(name = "user_stores") +public class UserStores { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne + @JoinColumn(name = "user_id") + private Users user; + + @Column(nullable = false) + private String name; + + @Column(nullable = false) + private String address; + + @Column(nullable = false) + private Double longitude; + + @Column(nullable = false) + private Double latitude; + + +} diff --git a/src/main/java/com/example/ReviewZIP/domain/userStores/UserStoresController.java b/src/main/java/com/example/ReviewZIP/domain/userStores/UserStoresController.java new file mode 100644 index 00000000..21a6f8b0 --- /dev/null +++ b/src/main/java/com/example/ReviewZIP/domain/userStores/UserStoresController.java @@ -0,0 +1,50 @@ +package com.example.ReviewZIP.domain.userStores; + + +import com.example.ReviewZIP.domain.userStores.dto.request.UserStoresRequestDto; +import com.example.ReviewZIP.global.response.ApiResponse; +import com.example.ReviewZIP.global.response.code.resultCode.SuccessStatus; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/v1/user-stores") +public class UserStoresController { + + private final UserStoresService userStoresService; + + @PostMapping("/") + @Operation(summary = "특정 장소를 관심 장소로 등록 API",description = "특정 장소를 유저의 관심 장소로 등록한다, 입력 시 CreateUserStoresDto 사용") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER404", description = "유저가 존재하지 않습니다",content = @Content(schema = @Schema(implementation = ApiResponse.class))), + }) + public ApiResponse createUserStores(@RequestBody UserStoresRequestDto.CreateUserStoresDto dto) { + userStoresService.createUserStores(dto); + return ApiResponse.onSuccess(SuccessStatus._OK); + } + + + @GetMapping("/location") + @Operation(summary = "특정 위치의 장소가 관심 장소 인지 판별하는 API",description = "특정 위치의 위도 경도 값을 바탕으로 관심 장소인지 판별하는 기능") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "USER404", description = "유저가 존재하지 않습니다",content = @Content(schema = @Schema(implementation = ApiResponse.class))), + }) + @Parameters({ + @Parameter(name = "lat", description = "장소의 위도"), + @Parameter(name = "lon", description = "장소의 경도"), + + }) + public ApiResponse isInterestPlace(@RequestParam Double lat, @RequestParam Double lon) { + return ApiResponse.onSuccess(userStoresService.isInterestPlace(lat,lon)); + } + +} diff --git a/src/main/java/com/example/ReviewZIP/domain/userStores/UserStoresConverter.java b/src/main/java/com/example/ReviewZIP/domain/userStores/UserStoresConverter.java new file mode 100644 index 00000000..d9644208 --- /dev/null +++ b/src/main/java/com/example/ReviewZIP/domain/userStores/UserStoresConverter.java @@ -0,0 +1,43 @@ +package com.example.ReviewZIP.domain.userStores; + +import com.example.ReviewZIP.domain.userStores.dto.request.UserStoresRequestDto; +import com.example.ReviewZIP.domain.userStores.dto.response.UserStoresResponseDto; + +import java.util.ArrayList; +import java.util.List; + +public class UserStoresConverter { + + public static UserStores toEntity(UserStoresRequestDto.CreateUserStoresDto request) { + return UserStores.builder() + .name(request.getName()) + .address(request.getAddress()) + .latitude(request.getLatitude()) + .longitude(request.getLongitude()) + .build(); + } + + public static UserStoresResponseDto.StoreInfoDto toStoreInfoDto(UserStores userStores) { + return UserStoresResponseDto.StoreInfoDto.builder() + .storeId(userStores.getId()) + .latitude(userStores.getLatitude()) + .longitude(userStores.getLongitude()) + .place(userStores.getName()) + .address(userStores.getAddress()) + .build(); + } + + public static UserStoresResponseDto.StoreInfoListDto toStoreInfoListDto(List userStoresList, Integer saveNum, String nickname) { + List storeInfoDtoList = new ArrayList<>(); + + for(UserStores userStores : userStoresList) { + storeInfoDtoList.add(toStoreInfoDto(userStores)); + } + + return UserStoresResponseDto.StoreInfoListDto.builder() + .storeInfoDtoList(storeInfoDtoList) + .savedStoresCount(saveNum) + .nickname(nickname) + .build(); + } +} diff --git a/src/main/java/com/example/ReviewZIP/domain/userStores/UserStoresRepository.java b/src/main/java/com/example/ReviewZIP/domain/userStores/UserStoresRepository.java new file mode 100644 index 00000000..73be56f9 --- /dev/null +++ b/src/main/java/com/example/ReviewZIP/domain/userStores/UserStoresRepository.java @@ -0,0 +1,14 @@ +package com.example.ReviewZIP.domain.userStores; + +import com.example.ReviewZIP.domain.user.Users; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface UserStoresRepository extends JpaRepository { + List findAllByUser (Users user); + + Boolean existsUserStoresByLatitudeAndLongitude (Double latitude, Double longitude); +} diff --git a/src/main/java/com/example/ReviewZIP/domain/userStores/UserStoresService.java b/src/main/java/com/example/ReviewZIP/domain/userStores/UserStoresService.java new file mode 100644 index 00000000..6089f729 --- /dev/null +++ b/src/main/java/com/example/ReviewZIP/domain/userStores/UserStoresService.java @@ -0,0 +1,54 @@ +package com.example.ReviewZIP.domain.userStores; + + +import com.example.ReviewZIP.domain.store.Stores; +import com.example.ReviewZIP.domain.user.Users; +import com.example.ReviewZIP.domain.user.UsersRepository; +import com.example.ReviewZIP.domain.userStores.dto.request.UserStoresRequestDto; +import com.example.ReviewZIP.domain.userStores.dto.response.UserStoresResponseDto; +import com.example.ReviewZIP.global.response.code.resultCode.ErrorStatus; +import com.example.ReviewZIP.global.response.exception.handler.UsersHandler; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class UserStoresService { + + private final UsersRepository usersRepository; + private final UserStoresRepository userStoresRepository; + @Transactional + public void createUserStores(UserStoresRequestDto.CreateUserStoresDto dto) { + + // 임의로 유저 아이디 값에 1L을 지정 + Users user = usersRepository.findById(1L).orElseThrow(()->new UsersHandler(ErrorStatus.USER_NOT_FOUND)); + + UserStores userStores = UserStoresConverter.toEntity(dto); + userStores.setUser(user); + + userStoresRepository.save(userStores); + + } + + public UserStoresResponseDto.StoreInfoListDto getStoreInfo(Long userId) { + Users user = usersRepository.findById(userId).orElseThrow(()->new UsersHandler(ErrorStatus.USER_NOT_FOUND)); + List userStoresList = userStoresRepository.findAllByUser(user); + + Integer storeSavedNum = userStoresList.size(); + String nickname = user.getNickname(); + + return UserStoresConverter.toStoreInfoListDto(userStoresList,storeSavedNum,nickname); + } + + public Boolean isInterestPlace (Double lat, Double lon) { + return userStoresRepository.existsUserStoresByLatitudeAndLongitude(lat,lon); + } + + + + +} diff --git a/src/main/java/com/example/ReviewZIP/domain/userStores/dto/request/UserStoresRequestDto.java b/src/main/java/com/example/ReviewZIP/domain/userStores/dto/request/UserStoresRequestDto.java new file mode 100644 index 00000000..fd597cb9 --- /dev/null +++ b/src/main/java/com/example/ReviewZIP/domain/userStores/dto/request/UserStoresRequestDto.java @@ -0,0 +1,14 @@ +package com.example.ReviewZIP.domain.userStores.dto.request; + +import lombok.Getter; + +public class UserStoresRequestDto { + + @Getter + public static class CreateUserStoresDto { + private String name; + private String address; + private Double latitude; + private Double longitude; + } +} diff --git a/src/main/java/com/example/ReviewZIP/domain/userStores/dto/response/UserStoresResponseDto.java b/src/main/java/com/example/ReviewZIP/domain/userStores/dto/response/UserStoresResponseDto.java new file mode 100644 index 00000000..1f7b7d3f --- /dev/null +++ b/src/main/java/com/example/ReviewZIP/domain/userStores/dto/response/UserStoresResponseDto.java @@ -0,0 +1,34 @@ +package com.example.ReviewZIP.domain.userStores.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +public class UserStoresResponseDto { + + @Builder + @Getter + @Setter + @AllArgsConstructor + public static class StoreInfoDto { + private Long storeId; + private Double latitude; + private Double longitude; + private String place; + private String address; + + } + + @Builder + @Getter + @Setter + @AllArgsConstructor + public static class StoreInfoListDto { + List storeInfoDtoList; + private Integer savedStoresCount; + private String nickname; + } +} diff --git a/src/main/java/com/example/ReviewZIP/global/security/CorsConfig.java b/src/main/java/com/example/ReviewZIP/global/security/CorsConfig.java index b5298782..680aa489 100644 --- a/src/main/java/com/example/ReviewZIP/global/security/CorsConfig.java +++ b/src/main/java/com/example/ReviewZIP/global/security/CorsConfig.java @@ -6,6 +6,8 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; +import java.util.List; + @Configuration public class CorsConfig { @Bean @@ -15,7 +17,7 @@ public CorsFilter corsFilter() { config.setAllowCredentials(true); config.addAllowedOriginPattern("*"); config.addAllowedHeader("*"); - config.addAllowedMethod("*"); + config.setAllowedMethods(List.of("POST", "GET", "PUT", "DELETE", "PATCH", "OPTIONS")); config.addAllowedOrigin("https://api.egusajo.shop"); source.registerCorsConfiguration("/**", config); diff --git a/src/main/java/com/example/ReviewZIP/global/security/WebSecurityConfig.java b/src/main/java/com/example/ReviewZIP/global/security/WebSecurityConfig.java index fbe692c9..fd30efdb 100644 --- a/src/main/java/com/example/ReviewZIP/global/security/WebSecurityConfig.java +++ b/src/main/java/com/example/ReviewZIP/global/security/WebSecurityConfig.java @@ -4,6 +4,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; @@ -12,7 +13,6 @@ import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; -import org.springframework.web.filter.CorsFilter; @Configuration @EnableWebSecurity @@ -20,7 +20,7 @@ public class WebSecurityConfig { private final JwtProvider jwtProvider; - private final CorsFilter corsFilter; + private final CorsConfig corsConfig; private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; private final JwtAccessDeniedHandler jwtAccessDeniedHandler; private final JwtRequestFilter jwtRequestFilter; @@ -28,7 +28,7 @@ public class WebSecurityConfig { @Bean public SecurityFilterChain apiFilterChain(HttpSecurity http) throws Exception { http - .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class) + .addFilterBefore(corsConfig.corsFilter(), UsernamePasswordAuthenticationFilter.class) .csrf(AbstractHttpConfigurer::disable) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeHttpRequests(authorize -> authorize @@ -36,15 +36,16 @@ public SecurityFilterChain apiFilterChain(HttpSecurity http) throws Exception { .requestMatchers(new AntPathRequestMatcher("/auth/**")).permitAll() .requestMatchers(new AntPathRequestMatcher("/S3/**")).permitAll() .requestMatchers("/swagger-resources/**", "/swagger-ui/**", "/v3/api-docs/**", "/api-docs/**", "/").permitAll() + .requestMatchers("https://api.egusajo.shop ").permitAll() + .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() .anyRequest().authenticated()) .exceptionHandling(exceptionHandling -> exceptionHandling .authenticationEntryPoint(jwtAuthenticationEntryPoint) .accessDeniedHandler(jwtAccessDeniedHandler)) - // JwtFilter를 addFilterBefore로 등록했던 JwtSecurityConfig 클래스를 적용 - .apply(new JwtSecurityConfig(jwtProvider)); - + // apply가 deprecated 되서 JwtRequestFilter에서 직접 설정한 필터를 추가 + .addFilterBefore(new JwtRequestFilter(jwtProvider), UsernamePasswordAuthenticationFilter.class); return http.build(); }