From bc09334ac9903123ef710fa3b4c10de91e6d2213 Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Mon, 24 Jul 2023 21:04:33 +0900 Subject: [PATCH 01/34] =?UTF-8?q?[feat]=20archiving=20=EC=A0=95=EB=B3=B4?= =?UTF-8?q?=20=EB=B3=B4=EC=97=AC=EC=A3=BC=EA=B8=B0=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20(#58)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [feat] 아카이빙 정보 가져오기 기능 구현 #52 * [refac] 아카이빙 제목 보기 response 변경 #52 --- .../controller/ArchivingController.java | 7 ++++++ .../archiving/model/vo/TitleContentCntVo.java | 7 +++++- .../service/GetArchivingInfoUseCase.java | 25 +++++++++++++++++++ .../server/api/common/util/UrlUtil.java | 6 +++++ .../service/ClearOldDeletedObjectUseCase.java | 1 + 5 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 Api/src/main/java/allchive/server/api/archiving/service/GetArchivingInfoUseCase.java diff --git a/Api/src/main/java/allchive/server/api/archiving/controller/ArchivingController.java b/Api/src/main/java/allchive/server/api/archiving/controller/ArchivingController.java index ef85f68d..a1a2553e 100644 --- a/Api/src/main/java/allchive/server/api/archiving/controller/ArchivingController.java +++ b/Api/src/main/java/allchive/server/api/archiving/controller/ArchivingController.java @@ -26,6 +26,7 @@ public class ArchivingController { private final CreateArchivingUseCase createArchivingUseCase; private final UpdateArchivingUseCase updateArchivingUseCase; + private final GetArchivingInfoUseCase getArchivingInfoUseCase; private final DeleteArchivingUseCase deleteArchivingUseCase; private final GetArchivingUseCase getArchivingUseCase; private final GetArchivedArchivingUseCase getArchivedArchivingUseCase; @@ -41,6 +42,12 @@ public void createArchiving(@RequestBody CreateArchivingRequest createArchivingR createArchivingUseCase.execute(createArchivingRequest); } + @Operation(summary = "아카이빙 정보 수정시 보여줄 정보를 가져옵니다.") + @GetMapping(value = "/{archivingId}") + public ArchivingResponse getArchiving(@PathVariable("archivingId") Long archivingId) { + return getArchivingInfoUseCase.execute(archivingId); + } + @Operation(summary = "아카이빙을 수정합니다.") @PatchMapping(value = "/{archivingId}") public void updateArchiving( diff --git a/Api/src/main/java/allchive/server/api/archiving/model/vo/TitleContentCntVo.java b/Api/src/main/java/allchive/server/api/archiving/model/vo/TitleContentCntVo.java index 60085516..7f658787 100644 --- a/Api/src/main/java/allchive/server/api/archiving/model/vo/TitleContentCntVo.java +++ b/Api/src/main/java/allchive/server/api/archiving/model/vo/TitleContentCntVo.java @@ -8,6 +8,9 @@ @Getter public class TitleContentCntVo { + @Schema(description = "아카이빙 고유 아이디") + private Long archivingId; + @Schema(defaultValue = "아카이빙 제목", description = "아카이빙 제목") private String title; @@ -15,13 +18,15 @@ public class TitleContentCntVo { private Long contentCnt; @Builder - private TitleContentCntVo(String title, Long contentCnt) { + private TitleContentCntVo(Long archivingId, String title, Long contentCnt) { + this.archivingId = archivingId; this.title = title; this.contentCnt = contentCnt; } public static TitleContentCntVo from(Archiving archiving) { return TitleContentCntVo.builder() + .archivingId(archiving.getId()) .contentCnt(archiving.getImgCnt() + archiving.getScrapCnt()) .title(archiving.getTitle()) .build(); diff --git a/Api/src/main/java/allchive/server/api/archiving/service/GetArchivingInfoUseCase.java b/Api/src/main/java/allchive/server/api/archiving/service/GetArchivingInfoUseCase.java new file mode 100644 index 00000000..1107df6e --- /dev/null +++ b/Api/src/main/java/allchive/server/api/archiving/service/GetArchivingInfoUseCase.java @@ -0,0 +1,25 @@ +package allchive.server.api.archiving.service; + + +import allchive.server.api.archiving.model.dto.response.ArchivingResponse; +import allchive.server.core.annotation.UseCase; +import allchive.server.domain.domains.archiving.adaptor.ArchivingAdaptor; +import allchive.server.domain.domains.archiving.domain.Archiving; +import allchive.server.domain.domains.archiving.validator.ArchivingValidator; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +@UseCase +@RequiredArgsConstructor +public class GetArchivingInfoUseCase { + private final ArchivingValidator archivingValidator; + private final ArchivingAdaptor archivingAdaptor; + + @Transactional + public ArchivingResponse execute(Long archivingId) { + archivingValidator.validateExistById(archivingId); + + Archiving archiving = archivingAdaptor.findById(archivingId); + return ArchivingResponse.of(archiving, Boolean.FALSE); + } +} diff --git a/Api/src/main/java/allchive/server/api/common/util/UrlUtil.java b/Api/src/main/java/allchive/server/api/common/util/UrlUtil.java index 0500a20d..633c3347 100644 --- a/Api/src/main/java/allchive/server/api/common/util/UrlUtil.java +++ b/Api/src/main/java/allchive/server/api/common/util/UrlUtil.java @@ -16,6 +16,9 @@ private UrlUtil(SpringEnvironmentHelper springEnvironmentHelper) { } public static String toAssetUrl(String key) { + if (key.equals("")) { + return ""; + } if (springEnvironmentHelper.isProdProfile()) { return PROD_ASSET_URL + key; } @@ -23,6 +26,9 @@ public static String toAssetUrl(String key) { } public static String convertUrlToKey(String url) { + if (url.equals("")) { + return ""; + } if (validateUrl(url)) { return url.split("/", 4)[3]; } diff --git a/Api/src/main/java/allchive/server/api/recycle/service/ClearOldDeletedObjectUseCase.java b/Api/src/main/java/allchive/server/api/recycle/service/ClearOldDeletedObjectUseCase.java index ed855e2f..4e9ffea5 100644 --- a/Api/src/main/java/allchive/server/api/recycle/service/ClearOldDeletedObjectUseCase.java +++ b/Api/src/main/java/allchive/server/api/recycle/service/ClearOldDeletedObjectUseCase.java @@ -33,6 +33,7 @@ public class ClearOldDeletedObjectUseCase { private final RecycleDomainService recycleDomainService; /** 삭제 후 30일 지난 항목 제거 스케쥴러 매일 02:30에 수행 */ + // TODO: s3 asset 삭제 @Scheduled(cron = "0 30 2 * * *") @Transactional public void executeSchedule() { From d1f73272b6f6ec2963d7420e54b0bb5a8ced4c2c Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Mon, 24 Jul 2023 23:09:02 +0900 Subject: [PATCH 02/34] =?UTF-8?q?[refac]=20user=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81=20(#60)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [refac] validation 분리, user response 변경 #57 * [feat] content 생성시 archving 데이터 업데이트 로직 추가 #57 --- .../api/content/service/CreateContentUseCase.java | 3 +++ .../model/dto/response/GetUserProfileResponse.java | 11 ++++++++--- .../server/api/user/model/mapper/UserMapper.java | 2 +- .../server/api/user/service/GetUserInfoUseCase.java | 6 +++++- .../api/user/service/GetUserProfileUseCase.java | 6 +++++- .../api/user/service/UpdateUserInfoUseCase.java | 6 +++++- .../domain/domains/archiving/domain/Archiving.java | 8 ++++++++ .../archiving/service/ArchivingDomainService.java | 11 +++++++++++ 8 files changed, 46 insertions(+), 7 deletions(-) diff --git a/Api/src/main/java/allchive/server/api/content/service/CreateContentUseCase.java b/Api/src/main/java/allchive/server/api/content/service/CreateContentUseCase.java index 2afd7967..3a525ffb 100644 --- a/Api/src/main/java/allchive/server/api/content/service/CreateContentUseCase.java +++ b/Api/src/main/java/allchive/server/api/content/service/CreateContentUseCase.java @@ -5,6 +5,7 @@ import allchive.server.api.content.model.dto.request.CreateContentRequest; import allchive.server.api.content.model.mapper.ContentMapper; import allchive.server.core.annotation.UseCase; +import allchive.server.domain.domains.archiving.service.ArchivingDomainService; import allchive.server.domain.domains.archiving.validator.ArchivingValidator; import allchive.server.domain.domains.content.adaptor.TagAdaptor; import allchive.server.domain.domains.content.domain.Content; @@ -26,6 +27,7 @@ public class CreateContentUseCase { private final TagValidator tagValidator; private final TagAdaptor tagAdaptor; private final ContentTagGroupDomainService contentTagGroupDomainService; + private final ArchivingDomainService archivingDomainService; @Transactional public void execute(CreateContentRequest request) { @@ -33,6 +35,7 @@ public void execute(CreateContentRequest request) { Content content = contentMapper.toEntity(request); createContentTagGroup(content, request.getTagIds()); contentDomainService.save(content); + archivingDomainService.updateContentCnt(request.getArchivingId(), request.getContentType()); } private void validateExecution(CreateContentRequest request) { diff --git a/Api/src/main/java/allchive/server/api/user/model/dto/response/GetUserProfileResponse.java b/Api/src/main/java/allchive/server/api/user/model/dto/response/GetUserProfileResponse.java index 45e64bbb..c0af16dd 100644 --- a/Api/src/main/java/allchive/server/api/user/model/dto/response/GetUserProfileResponse.java +++ b/Api/src/main/java/allchive/server/api/user/model/dto/response/GetUserProfileResponse.java @@ -24,24 +24,29 @@ public class GetUserProfileResponse { @Schema(defaultValue = "0", description = "공개 아카이브 개수") private int publicArchivingCount; + + @Schema(defaultValue = "0", description = "모든 아카이브 개수") + private int archivingCount; + @Builder - private GetUserProfileResponse( - String nickname, String imgUrl, int linkCount, int imgCount, int publicArchivingCount) { + public GetUserProfileResponse(String nickname, String imgUrl, int linkCount, int imgCount, int publicArchivingCount, int archivingCount) { this.nickname = nickname; this.imgUrl = imgUrl; this.linkCount = linkCount; this.imgCount = imgCount; this.publicArchivingCount = publicArchivingCount; + this.archivingCount = archivingCount; } public static GetUserProfileResponse of( - User user, int linkCount, int imgCount, int publicArchivingCount) { + User user, int linkCount, int imgCount, int publicArchivingCount, int archivingCount) { return GetUserProfileResponse.builder() .nickname(user.getNickname()) .imgUrl(UrlUtil.toAssetUrl(user.getProfileImgUrl())) .linkCount(linkCount) .imgCount(imgCount) .publicArchivingCount(publicArchivingCount) + .archivingCount(archivingCount) .build(); } } diff --git a/Api/src/main/java/allchive/server/api/user/model/mapper/UserMapper.java b/Api/src/main/java/allchive/server/api/user/model/mapper/UserMapper.java index 84468718..18d84afa 100644 --- a/Api/src/main/java/allchive/server/api/user/model/mapper/UserMapper.java +++ b/Api/src/main/java/allchive/server/api/user/model/mapper/UserMapper.java @@ -17,6 +17,6 @@ public GetUserProfileResponse toGetUserProfileResponse( imgCount += archiving.getImgCnt(); publicArchivingCount += archiving.getPublicStatus() ? 1 : 0; } - return GetUserProfileResponse.of(user, linkCount, imgCount, publicArchivingCount); + return GetUserProfileResponse.of(user, linkCount, imgCount, publicArchivingCount, archivingList.size()); } } diff --git a/Api/src/main/java/allchive/server/api/user/service/GetUserInfoUseCase.java b/Api/src/main/java/allchive/server/api/user/service/GetUserInfoUseCase.java index 0cb03dca..5a8db184 100644 --- a/Api/src/main/java/allchive/server/api/user/service/GetUserInfoUseCase.java +++ b/Api/src/main/java/allchive/server/api/user/service/GetUserInfoUseCase.java @@ -19,8 +19,12 @@ public class GetUserInfoUseCase { @Transactional(readOnly = true) public GetUserInfoResponse execute() { Long userId = SecurityUtil.getCurrentUserId(); - userValidator.validateUserStatusNormal(userId); + validateExecution(userId); User user = userAdaptor.findById(userId); return GetUserInfoResponse.from(user); } + + private void validateExecution(Long userId) { + userValidator.validateUserStatusNormal(userId); + } } diff --git a/Api/src/main/java/allchive/server/api/user/service/GetUserProfileUseCase.java b/Api/src/main/java/allchive/server/api/user/service/GetUserProfileUseCase.java index bf30180f..083d005a 100644 --- a/Api/src/main/java/allchive/server/api/user/service/GetUserProfileUseCase.java +++ b/Api/src/main/java/allchive/server/api/user/service/GetUserProfileUseCase.java @@ -25,9 +25,13 @@ public class GetUserProfileUseCase { @Transactional(readOnly = true) public GetUserProfileResponse execute() { Long userId = SecurityUtil.getCurrentUserId(); - userValidator.validateUserStatusNormal(userId); + validateExecution(userId); User user = userAdaptor.findById(userId); List archivingList = archivingAdaptor.findAllByUserId(userId); return userMapper.toGetUserProfileResponse(archivingList, user); } + + private void validateExecution(Long userId) { + userValidator.validateUserStatusNormal(userId); + } } diff --git a/Api/src/main/java/allchive/server/api/user/service/UpdateUserInfoUseCase.java b/Api/src/main/java/allchive/server/api/user/service/UpdateUserInfoUseCase.java index 9485a883..313810c2 100644 --- a/Api/src/main/java/allchive/server/api/user/service/UpdateUserInfoUseCase.java +++ b/Api/src/main/java/allchive/server/api/user/service/UpdateUserInfoUseCase.java @@ -19,9 +19,13 @@ public class UpdateUserInfoUseCase { @Transactional public void execute(UpdateUserInfoRequest request) { Long userId = SecurityUtil.getCurrentUserId(); - userValidator.validateUserStatusNormal(userId); + validateExecution(userId); String imgKey = UrlUtil.convertUrlToKey(request.getImgUrl()); userDomainService.updateUserInfo( userId, request.getName(), request.getEmail(), request.getNickname(), imgKey); } + + private void validateExecution(Long userId) { + userValidator.validateUserStatusNormal(userId); + } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/archiving/domain/Archiving.java b/Domain/src/main/java/allchive/server/domain/domains/archiving/domain/Archiving.java index 57919d98..7529ec11 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/archiving/domain/Archiving.java +++ b/Domain/src/main/java/allchive/server/domain/domains/archiving/domain/Archiving.java @@ -116,4 +116,12 @@ public void delete() { public void restore() { this.deleteStatus = Boolean.FALSE; } + + public void updateImgCnt(int i) { + this.imgCnt += i; + } + + public void updateLinkCnt(int i) { + this.linkCnt += i; + } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/archiving/service/ArchivingDomainService.java b/Domain/src/main/java/allchive/server/domain/domains/archiving/service/ArchivingDomainService.java index ffcc9f1f..e8694e3c 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/archiving/service/ArchivingDomainService.java +++ b/Domain/src/main/java/allchive/server/domain/domains/archiving/service/ArchivingDomainService.java @@ -6,6 +6,8 @@ import allchive.server.domain.domains.archiving.domain.Archiving; import allchive.server.domain.domains.archiving.domain.enums.Category; import java.util.List; + +import allchive.server.domain.domains.content.domain.enums.ContentType; import lombok.RequiredArgsConstructor; @DomainService @@ -58,4 +60,13 @@ public void restoreInIdList(List archivingIds) { public void deleteAllById(List archivingIds) { archivingAdaptor.deleteAllById(archivingIds); } + + public void updateContentCnt(Long archivingId, ContentType contentType) { + Archiving archiving = archivingAdaptor.findById(archivingId); + if (contentType.equals(ContentType.IMAGE)) { + archiving.updateImgCnt(1); + } else { + archiving.updateLinkCnt(1); + } + } } From bed779555fb22dae524150c58c02f1395c5ff7d7 Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Wed, 26 Jul 2023 14:33:19 +0900 Subject: [PATCH 03/34] =?UTF-8?q?[refac]=20=EA=B2=80=EC=83=89=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81=20=EB=B0=8F=20=EC=B5=9C=EA=B7=BC=20?= =?UTF-8?q?=EA=B2=80=EC=83=89=EC=96=B4=20=EC=82=AD=EC=A0=9C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80=20(#62)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [feat] 최근 검색어 삭제 기능 추가 #59 * [refac] 최근 검색어 불러오기 response 변경 #59 * [chore] spotless 적용 #61 * [refac] 검색어 검색 http method 변경 #61 * [feat] 강제 데이터 주입 기능 추가 #61 * [refac] 연관 검색어 기능 로직 수정 및 코드 정리 #61 * [refac] 연관 검색어 range 수정 #61 * [refac] 점색어 자동완성 get 으로 변환 #61 --- .../search/controller/SearchController.java | 33 +++++++++++++------ .../dto/response/SearchVoListResponse.java | 21 ++++++++++++ .../api/search/model/vo/LatestSearchVo.java | 29 ++++++++++++++++ .../service/DeleteLatestSearchUseCase.java | 27 +++++++++++++++ .../service/GetLatestSearchListUseCase.java | 12 +++---- .../service/GetRelativeSearchListUseCase.java | 6 ++-- .../service/RenewalTitleDataUseCase.java | 17 +++++++--- .../service/SearchArchivingUseCase.java | 13 ++++---- .../dto/response/GetUserProfileResponse.java | 9 +++-- .../api/user/model/mapper/UserMapper.java | 3 +- .../service/ArchivingDomainService.java | 3 +- .../search/adaptor/LatestSearchAdaptor.java | 11 +++++++ .../search/exception/SearchErrorCode.java | 22 +++++++++++++ .../LatestSearchNotFoundException.java | 14 ++++++++ .../repository/LatestSearchRepository.java | 5 +++ .../validator/LatestSearchValidator.java | 16 +++++++++ 16 files changed, 205 insertions(+), 36 deletions(-) create mode 100644 Api/src/main/java/allchive/server/api/search/model/dto/response/SearchVoListResponse.java create mode 100644 Api/src/main/java/allchive/server/api/search/model/vo/LatestSearchVo.java create mode 100644 Api/src/main/java/allchive/server/api/search/service/DeleteLatestSearchUseCase.java create mode 100644 Domain/src/main/java/allchive/server/domain/domains/search/exception/SearchErrorCode.java create mode 100644 Domain/src/main/java/allchive/server/domain/domains/search/exception/exceptions/LatestSearchNotFoundException.java create mode 100644 Domain/src/main/java/allchive/server/domain/domains/search/validator/LatestSearchValidator.java diff --git a/Api/src/main/java/allchive/server/api/search/controller/SearchController.java b/Api/src/main/java/allchive/server/api/search/controller/SearchController.java index d476f5a5..e03afe90 100644 --- a/Api/src/main/java/allchive/server/api/search/controller/SearchController.java +++ b/Api/src/main/java/allchive/server/api/search/controller/SearchController.java @@ -4,10 +4,9 @@ import allchive.server.api.search.model.dto.request.SearchRequest; import allchive.server.api.search.model.dto.response.SearchListResponse; import allchive.server.api.search.model.dto.response.SearchResponse; +import allchive.server.api.search.model.dto.response.SearchVoListResponse; import allchive.server.api.search.model.enums.ArchivingType; -import allchive.server.api.search.service.GetLatestSearchListUseCase; -import allchive.server.api.search.service.GetRelativeSearchListUseCase; -import allchive.server.api.search.service.SearchArchivingUseCase; +import allchive.server.api.search.service.*; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -26,25 +25,39 @@ public class SearchController { private final SearchArchivingUseCase searchArchivingUseCase; private final GetLatestSearchListUseCase getLatestSearchListUseCase; private final GetRelativeSearchListUseCase getRelativeSearchListUseCase; + private final DeleteLatestSearchUseCase deleteLatestSearchUseCase; + private final RenewalTitleDataUseCase renewalTitleDataUseCase; @Operation(summary = "검색어를 검색합니다.") - @PostMapping + @GetMapping public SearchResponse searchArchiving( @ParameterObject @PageableDefault(size = 10) Pageable pageable, @RequestParam("type") ArchivingType type, - @RequestBody SearchRequest request) { - return searchArchivingUseCase.execute(pageable, type, request); + @RequestParam("word") String word) { + return searchArchivingUseCase.execute(pageable, type, word); } @Operation(summary = "최근 검색어 목록을 가져옵니다.", description = "5개만 드릴게요") @GetMapping(value = "/latest") - public SearchListResponse getLatestSearchList() { + public SearchVoListResponse getLatestSearchList() { return getLatestSearchListUseCase.execute(); } + @Operation(summary = "최근 검색어를 삭제합니다.") + @DeleteMapping(value = "/latest/{latestId}") + public void deleteLatestSearch(@PathVariable("latestId") Long latestId) { + deleteLatestSearchUseCase.execute(latestId); + } + @Operation(summary = "검색어 자동 완성") - @PostMapping(value = "/relation") - public SearchListResponse getRelativeSearchList(@RequestBody SearchRequest request) { - return getRelativeSearchListUseCase.execute(request); + @GetMapping(value = "/relation") + public SearchListResponse getRelativeSearchList(@RequestParam("word") String word) { + return getRelativeSearchListUseCase.execute(word); + } + + @Operation(summary = "자동 완성 데이터 강제 리뉴얼", deprecated = true) + @GetMapping(value = "/relation/force") + public void forceRenewalTitleData() { + renewalTitleDataUseCase.executeForce(); } } diff --git a/Api/src/main/java/allchive/server/api/search/model/dto/response/SearchVoListResponse.java b/Api/src/main/java/allchive/server/api/search/model/dto/response/SearchVoListResponse.java new file mode 100644 index 00000000..b922e9c2 --- /dev/null +++ b/Api/src/main/java/allchive/server/api/search/model/dto/response/SearchVoListResponse.java @@ -0,0 +1,21 @@ +package allchive.server.api.search.model.dto.response; + + +import allchive.server.api.search.model.vo.LatestSearchVo; +import java.util.List; +import lombok.Builder; +import lombok.Getter; + +@Getter +public class SearchVoListResponse { + private List keywords; + + @Builder + private SearchVoListResponse(List keywords) { + this.keywords = keywords; + } + + public static SearchVoListResponse from(List keywords) { + return SearchVoListResponse.builder().keywords(keywords).build(); + } +} diff --git a/Api/src/main/java/allchive/server/api/search/model/vo/LatestSearchVo.java b/Api/src/main/java/allchive/server/api/search/model/vo/LatestSearchVo.java new file mode 100644 index 00000000..ac251aaf --- /dev/null +++ b/Api/src/main/java/allchive/server/api/search/model/vo/LatestSearchVo.java @@ -0,0 +1,29 @@ +package allchive.server.api.search.model.vo; + + +import allchive.server.domain.domains.search.domain.LatestSearch; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Getter; + +@Getter +public class LatestSearchVo { + @Schema(description = "최근 검색 내용") + private String word; + + @Schema(description = "최근 검색 내용 고유번호") + private Long latestSearchId; + + @Builder + private LatestSearchVo(String word, Long latestSearchId) { + this.word = word; + this.latestSearchId = latestSearchId; + } + + public static LatestSearchVo from(LatestSearch latestSearch) { + return LatestSearchVo.builder() + .word(latestSearch.getKeyword()) + .latestSearchId(latestSearch.getId()) + .build(); + } +} diff --git a/Api/src/main/java/allchive/server/api/search/service/DeleteLatestSearchUseCase.java b/Api/src/main/java/allchive/server/api/search/service/DeleteLatestSearchUseCase.java new file mode 100644 index 00000000..83d1f24a --- /dev/null +++ b/Api/src/main/java/allchive/server/api/search/service/DeleteLatestSearchUseCase.java @@ -0,0 +1,27 @@ +package allchive.server.api.search.service; + + +import allchive.server.api.config.security.SecurityUtil; +import allchive.server.core.annotation.UseCase; +import allchive.server.domain.domains.search.adaptor.LatestSearchAdaptor; +import allchive.server.domain.domains.search.validator.LatestSearchValidator; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +@UseCase +@RequiredArgsConstructor +public class DeleteLatestSearchUseCase { + private final LatestSearchValidator latestSearchValidator; + private final LatestSearchAdaptor latestSearchAdaptor; + + @Transactional + public void execute(Long latestSearchId) { + Long userId = SecurityUtil.getCurrentUserId(); + validateExecution(latestSearchId, userId); + latestSearchAdaptor.deleteByIdAndUserId(latestSearchId, userId); + } + + private void validateExecution(Long latestSearchId, Long userId) { + latestSearchValidator.validateExistByIdAndUserId(latestSearchId, userId); + } +} diff --git a/Api/src/main/java/allchive/server/api/search/service/GetLatestSearchListUseCase.java b/Api/src/main/java/allchive/server/api/search/service/GetLatestSearchListUseCase.java index a392af40..f1836264 100644 --- a/Api/src/main/java/allchive/server/api/search/service/GetLatestSearchListUseCase.java +++ b/Api/src/main/java/allchive/server/api/search/service/GetLatestSearchListUseCase.java @@ -2,10 +2,10 @@ import allchive.server.api.config.security.SecurityUtil; -import allchive.server.api.search.model.dto.response.SearchListResponse; +import allchive.server.api.search.model.dto.response.SearchVoListResponse; +import allchive.server.api.search.model.vo.LatestSearchVo; import allchive.server.core.annotation.UseCase; import allchive.server.domain.domains.search.adaptor.LatestSearchAdaptor; -import allchive.server.domain.domains.search.domain.LatestSearch; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.transaction.annotation.Transactional; @@ -16,12 +16,12 @@ public class GetLatestSearchListUseCase { private final LatestSearchAdaptor latestSearchAdaptor; @Transactional(readOnly = true) - public SearchListResponse execute() { + public SearchVoListResponse execute() { Long userId = SecurityUtil.getCurrentUserId(); - List keywords = + List keywords = latestSearchAdaptor.findAllByUserIdOrderByCreatedAt(userId).stream() - .map(LatestSearch::getKeyword) + .map(LatestSearchVo::from) .toList(); - return SearchListResponse.from(keywords); + return SearchVoListResponse.from(keywords); } } diff --git a/Api/src/main/java/allchive/server/api/search/service/GetRelativeSearchListUseCase.java b/Api/src/main/java/allchive/server/api/search/service/GetRelativeSearchListUseCase.java index 744c1305..a5745048 100644 --- a/Api/src/main/java/allchive/server/api/search/service/GetRelativeSearchListUseCase.java +++ b/Api/src/main/java/allchive/server/api/search/service/GetRelativeSearchListUseCase.java @@ -20,13 +20,13 @@ public class GetRelativeSearchListUseCase { private final RedisTemplate redisTemplate; @Transactional - public SearchListResponse execute(SearchRequest request) { + public SearchListResponse execute(String word) { ZSetOperations zSetOperations = redisTemplate.opsForZSet(); List autoCompleteList = new ArrayList<>(); - Long rank = zSetOperations.rank(SEARCH_KEY, request.getKeyword()); + Long rank = zSetOperations.rank(SEARCH_KEY, word); if (rank != null) { Set rangeList = zSetOperations.range(SEARCH_KEY, rank, rank + 1000); - autoCompleteList = getAutoCompleteList(rangeList, request.getKeyword()); + autoCompleteList = getAutoCompleteList(rangeList, word); } return SearchListResponse.from(autoCompleteList); } diff --git a/Api/src/main/java/allchive/server/api/search/service/RenewalTitleDataUseCase.java b/Api/src/main/java/allchive/server/api/search/service/RenewalTitleDataUseCase.java index 3f204ba7..6ab96628 100644 --- a/Api/src/main/java/allchive/server/api/search/service/RenewalTitleDataUseCase.java +++ b/Api/src/main/java/allchive/server/api/search/service/RenewalTitleDataUseCase.java @@ -21,12 +21,20 @@ public class RenewalTitleDataUseCase { private final ArchivingAdaptor archivingAdaptor; private final RedisTemplate redisTemplate; - private static final int TIME_LIMIT = 1; - @Scheduled(cron = "0 0 3 * * *") @Transactional(readOnly = true) public void executeSchedule() { log.info("renewal title scheduler on"); + renewalData(); + log.info("renewal title scheduler off"); + } + + @Transactional(readOnly = true) + public void executeForce() { + renewalData(); + } + + private void renewalData() { redisTemplate.delete(SEARCH_KEY); Set archivings = new HashSet<>(archivingAdaptor.findAllByPublicStatus(Boolean.TRUE)); @@ -35,15 +43,14 @@ public void executeSchedule() { redisTemplate .opsForZSet() .add(SEARCH_KEY, archiving.getTitle().trim() + ASTERISK, 0); - for (int index = 1; index < archiving.getTitle().length(); index++) { + for (int index = 0; index <= archiving.getTitle().length(); index++) { redisTemplate .opsForZSet() .add( SEARCH_KEY, - archiving.getTitle().trim().substring(0, index - 1), + archiving.getTitle().trim().substring(0, index), 0); } }); - log.info("renewal title scheduler off"); } } diff --git a/Api/src/main/java/allchive/server/api/search/service/SearchArchivingUseCase.java b/Api/src/main/java/allchive/server/api/search/service/SearchArchivingUseCase.java index df4bc9ea..8c4bb03a 100644 --- a/Api/src/main/java/allchive/server/api/search/service/SearchArchivingUseCase.java +++ b/Api/src/main/java/allchive/server/api/search/service/SearchArchivingUseCase.java @@ -4,7 +4,6 @@ import allchive.server.api.archiving.model.dto.response.ArchivingResponse; import allchive.server.api.common.slice.SliceResponse; import allchive.server.api.config.security.SecurityUtil; -import allchive.server.api.search.model.dto.request.SearchRequest; import allchive.server.api.search.model.dto.response.SearchResponse; import allchive.server.api.search.model.enums.ArchivingType; import allchive.server.core.annotation.UseCase; @@ -32,23 +31,23 @@ public class SearchArchivingUseCase { private final LatestSearchDomainService latestSearchDomainService; @Transactional - public SearchResponse execute(Pageable pageable, ArchivingType type, SearchRequest request) { + public SearchResponse execute(Pageable pageable, ArchivingType type, String word) { Long userId = SecurityUtil.getCurrentUserId(); SliceResponse my = null; SliceResponse community = null; - renewalLatestSearch(userId, request.getKeyword()); + renewalLatestSearch(userId, word); switch (type) { case ALL -> { - my = getMyArchivings(userId, request.getKeyword(), pageable); - community = getCommunityArchivings(userId, request.getKeyword(), pageable); + my = getMyArchivings(userId, word, pageable); + community = getCommunityArchivings(userId, word, pageable); return SearchResponse.forAll(my, community); } case MY -> { - my = getMyArchivings(userId, request.getKeyword(), pageable); + my = getMyArchivings(userId, word, pageable); return SearchResponse.forMy(my); } case COMMUNITY -> { - community = getCommunityArchivings(userId, request.getKeyword(), pageable); + community = getCommunityArchivings(userId, word, pageable); return SearchResponse.forCommunity(community); } } diff --git a/Api/src/main/java/allchive/server/api/user/model/dto/response/GetUserProfileResponse.java b/Api/src/main/java/allchive/server/api/user/model/dto/response/GetUserProfileResponse.java index c0af16dd..5620b9a9 100644 --- a/Api/src/main/java/allchive/server/api/user/model/dto/response/GetUserProfileResponse.java +++ b/Api/src/main/java/allchive/server/api/user/model/dto/response/GetUserProfileResponse.java @@ -24,12 +24,17 @@ public class GetUserProfileResponse { @Schema(defaultValue = "0", description = "공개 아카이브 개수") private int publicArchivingCount; - @Schema(defaultValue = "0", description = "모든 아카이브 개수") private int archivingCount; @Builder - public GetUserProfileResponse(String nickname, String imgUrl, int linkCount, int imgCount, int publicArchivingCount, int archivingCount) { + public GetUserProfileResponse( + String nickname, + String imgUrl, + int linkCount, + int imgCount, + int publicArchivingCount, + int archivingCount) { this.nickname = nickname; this.imgUrl = imgUrl; this.linkCount = linkCount; diff --git a/Api/src/main/java/allchive/server/api/user/model/mapper/UserMapper.java b/Api/src/main/java/allchive/server/api/user/model/mapper/UserMapper.java index 18d84afa..ebd1fe40 100644 --- a/Api/src/main/java/allchive/server/api/user/model/mapper/UserMapper.java +++ b/Api/src/main/java/allchive/server/api/user/model/mapper/UserMapper.java @@ -17,6 +17,7 @@ public GetUserProfileResponse toGetUserProfileResponse( imgCount += archiving.getImgCnt(); publicArchivingCount += archiving.getPublicStatus() ? 1 : 0; } - return GetUserProfileResponse.of(user, linkCount, imgCount, publicArchivingCount, archivingList.size()); + return GetUserProfileResponse.of( + user, linkCount, imgCount, publicArchivingCount, archivingList.size()); } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/archiving/service/ArchivingDomainService.java b/Domain/src/main/java/allchive/server/domain/domains/archiving/service/ArchivingDomainService.java index e8694e3c..f45bea0b 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/archiving/service/ArchivingDomainService.java +++ b/Domain/src/main/java/allchive/server/domain/domains/archiving/service/ArchivingDomainService.java @@ -5,9 +5,8 @@ import allchive.server.domain.domains.archiving.adaptor.ArchivingAdaptor; import allchive.server.domain.domains.archiving.domain.Archiving; import allchive.server.domain.domains.archiving.domain.enums.Category; -import java.util.List; - import allchive.server.domain.domains.content.domain.enums.ContentType; +import java.util.List; import lombok.RequiredArgsConstructor; @DomainService diff --git a/Domain/src/main/java/allchive/server/domain/domains/search/adaptor/LatestSearchAdaptor.java b/Domain/src/main/java/allchive/server/domain/domains/search/adaptor/LatestSearchAdaptor.java index c1087477..ad2f38aa 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/search/adaptor/LatestSearchAdaptor.java +++ b/Domain/src/main/java/allchive/server/domain/domains/search/adaptor/LatestSearchAdaptor.java @@ -3,6 +3,7 @@ import allchive.server.core.annotation.Adaptor; import allchive.server.domain.domains.search.domain.LatestSearch; +import allchive.server.domain.domains.search.exception.exceptions.LatestSearchNotFoundException; import allchive.server.domain.domains.search.repository.LatestSearchRepository; import java.util.List; import lombok.RequiredArgsConstructor; @@ -27,4 +28,14 @@ public void save(LatestSearch newSearch) { public void deleteAllByUserId(Long userId) { latestSearchRepository.deleteAllByUserId(userId); } + + public LatestSearch findByIdAndUserId(Long latestSearchId, Long userId) { + return latestSearchRepository + .findByIdAndUserId(latestSearchId, userId) + .orElseThrow(() -> LatestSearchNotFoundException.EXCEPTION); + } + + public void deleteByIdAndUserId(Long latestSearchId, Long userId) { + latestSearchRepository.deleteByIdAndUserId(latestSearchId, userId); + } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/search/exception/SearchErrorCode.java b/Domain/src/main/java/allchive/server/domain/domains/search/exception/SearchErrorCode.java new file mode 100644 index 00000000..5cb874bb --- /dev/null +++ b/Domain/src/main/java/allchive/server/domain/domains/search/exception/SearchErrorCode.java @@ -0,0 +1,22 @@ +package allchive.server.domain.domains.search.exception; + +import static allchive.server.core.consts.AllchiveConst.*; + +import allchive.server.core.dto.ErrorReason; +import allchive.server.core.error.BaseErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum SearchErrorCode implements BaseErrorCode { + LATEST_SEARCH_NOT_FOUND(NOT_FOUND, "LATESTSEARCH_404_1", "최근 검색어를 찾을 수 없습니다."); + private int status; + private String code; + private String reason; + + @Override + public ErrorReason getErrorReason() { + return ErrorReason.of(status, code, reason); + } +} diff --git a/Domain/src/main/java/allchive/server/domain/domains/search/exception/exceptions/LatestSearchNotFoundException.java b/Domain/src/main/java/allchive/server/domain/domains/search/exception/exceptions/LatestSearchNotFoundException.java new file mode 100644 index 00000000..da24ca92 --- /dev/null +++ b/Domain/src/main/java/allchive/server/domain/domains/search/exception/exceptions/LatestSearchNotFoundException.java @@ -0,0 +1,14 @@ +package allchive.server.domain.domains.search.exception.exceptions; + + +import allchive.server.core.error.BaseErrorException; +import allchive.server.domain.domains.search.exception.SearchErrorCode; + +public class LatestSearchNotFoundException extends BaseErrorException { + + public static final BaseErrorException EXCEPTION = new LatestSearchNotFoundException(); + + private LatestSearchNotFoundException() { + super(SearchErrorCode.LATEST_SEARCH_NOT_FOUND); + } +} diff --git a/Domain/src/main/java/allchive/server/domain/domains/search/repository/LatestSearchRepository.java b/Domain/src/main/java/allchive/server/domain/domains/search/repository/LatestSearchRepository.java index 20ca1d86..aa8738d3 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/search/repository/LatestSearchRepository.java +++ b/Domain/src/main/java/allchive/server/domain/domains/search/repository/LatestSearchRepository.java @@ -3,10 +3,15 @@ import allchive.server.domain.domains.search.domain.LatestSearch; import java.util.List; +import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; public interface LatestSearchRepository extends JpaRepository { List findAllByUserIdOrderByCreatedAt(Long userId); void deleteAllByUserId(Long userId); + + Optional findByIdAndUserId(Long latestSearchId, Long userId); + + void deleteByIdAndUserId(Long latestSearchId, Long userId); } diff --git a/Domain/src/main/java/allchive/server/domain/domains/search/validator/LatestSearchValidator.java b/Domain/src/main/java/allchive/server/domain/domains/search/validator/LatestSearchValidator.java new file mode 100644 index 00000000..05b91078 --- /dev/null +++ b/Domain/src/main/java/allchive/server/domain/domains/search/validator/LatestSearchValidator.java @@ -0,0 +1,16 @@ +package allchive.server.domain.domains.search.validator; + + +import allchive.server.core.annotation.Validator; +import allchive.server.domain.domains.search.adaptor.LatestSearchAdaptor; +import lombok.RequiredArgsConstructor; + +@Validator +@RequiredArgsConstructor +public class LatestSearchValidator { + private final LatestSearchAdaptor latestSearchAdaptor; + + public void validateExistByIdAndUserId(Long latestSearchId, Long userId) { + latestSearchAdaptor.findByIdAndUserId(latestSearchId, userId); + } +} From 42c73df78c31bea6bf7ab0545a54b72299e7bd7d Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Wed, 26 Jul 2023 21:50:34 +0900 Subject: [PATCH 04/34] =?UTF-8?q?[feat]=20=ED=83=9C=EA=B7=B8=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20=EB=B0=8F?= =?UTF-8?q?=20validation=20=EC=B6=94=EA=B0=80=20(#64)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [feat] 검색하기 최근 검색어 중복 판별 로직 추가 #63 * [feat] 최근 검색어 삭제 전체, 다중 삭제 가능하도록 변경 #63 * [feat] 태그도 검색 되도록 수정 #63 * [chore] spotless 적용 #63 * [feat] tag 데이터 검색 데이터 추가 #63 --- .../search/controller/SearchController.java | 14 ++--- .../request/DeleteLatestSearchRequest.java | 12 ++++ .../service/DeleteLatestSearchUseCase.java | 19 ++++--- .../service/GetRelativeSearchListUseCase.java | 1 - ...ase.java => RenewalSearchDataUseCase.java} | 23 +++++++- .../service/SearchArchivingUseCase.java | 55 ++++++++++++++----- .../archiving/adaptor/ArchivingAdaptor.java | 21 ++++--- .../repository/ArchivingCustomRepository.java | 13 +++-- .../ArchivingCustomRepositoryImpl.java | 35 ++++++++---- .../adaptor/ContentTagGroupAdaptor.java | 4 ++ .../domains/content/adaptor/TagAdaptor.java | 8 +++ .../ContentTagGroupCustomRepository.java | 3 + .../ContentTagGroupCustomRepositoryImpl.java | 17 ++++++ .../content/repository/TagRepository.java | 2 + .../search/adaptor/LatestSearchAdaptor.java | 11 ++-- .../search/exception/SearchErrorCode.java | 1 + ...oAuthorityUpdateLatestSearchException.java | 14 +++++ .../repository/LatestSearchRepository.java | 5 +- .../service/LatestSearchDomainService.java | 5 ++ .../validator/LatestSearchValidator.java | 21 ++++++- 20 files changed, 218 insertions(+), 66 deletions(-) create mode 100644 Api/src/main/java/allchive/server/api/search/model/dto/request/DeleteLatestSearchRequest.java rename Api/src/main/java/allchive/server/api/search/service/{RenewalTitleDataUseCase.java => RenewalSearchDataUseCase.java} (70%) create mode 100644 Domain/src/main/java/allchive/server/domain/domains/search/exception/exceptions/NoAuthorityUpdateLatestSearchException.java diff --git a/Api/src/main/java/allchive/server/api/search/controller/SearchController.java b/Api/src/main/java/allchive/server/api/search/controller/SearchController.java index e03afe90..2f24ea7e 100644 --- a/Api/src/main/java/allchive/server/api/search/controller/SearchController.java +++ b/Api/src/main/java/allchive/server/api/search/controller/SearchController.java @@ -1,7 +1,7 @@ package allchive.server.api.search.controller; -import allchive.server.api.search.model.dto.request.SearchRequest; +import allchive.server.api.search.model.dto.request.DeleteLatestSearchRequest; import allchive.server.api.search.model.dto.response.SearchListResponse; import allchive.server.api.search.model.dto.response.SearchResponse; import allchive.server.api.search.model.dto.response.SearchVoListResponse; @@ -26,7 +26,7 @@ public class SearchController { private final GetLatestSearchListUseCase getLatestSearchListUseCase; private final GetRelativeSearchListUseCase getRelativeSearchListUseCase; private final DeleteLatestSearchUseCase deleteLatestSearchUseCase; - private final RenewalTitleDataUseCase renewalTitleDataUseCase; + private final RenewalSearchDataUseCase renewalSearchDataUseCase; @Operation(summary = "검색어를 검색합니다.") @GetMapping @@ -44,9 +44,9 @@ public SearchVoListResponse getLatestSearchList() { } @Operation(summary = "최근 검색어를 삭제합니다.") - @DeleteMapping(value = "/latest/{latestId}") - public void deleteLatestSearch(@PathVariable("latestId") Long latestId) { - deleteLatestSearchUseCase.execute(latestId); + @DeleteMapping(value = "/latest") + public void deleteLatestSearch(@RequestBody DeleteLatestSearchRequest request) { + deleteLatestSearchUseCase.execute(request); } @Operation(summary = "검색어 자동 완성") @@ -57,7 +57,7 @@ public SearchListResponse getRelativeSearchList(@RequestParam("word") String wor @Operation(summary = "자동 완성 데이터 강제 리뉴얼", deprecated = true) @GetMapping(value = "/relation/force") - public void forceRenewalTitleData() { - renewalTitleDataUseCase.executeForce(); + public void forceRenewalSearchData() { + renewalSearchDataUseCase.executeForce(); } } diff --git a/Api/src/main/java/allchive/server/api/search/model/dto/request/DeleteLatestSearchRequest.java b/Api/src/main/java/allchive/server/api/search/model/dto/request/DeleteLatestSearchRequest.java new file mode 100644 index 00000000..c7c3b55d --- /dev/null +++ b/Api/src/main/java/allchive/server/api/search/model/dto/request/DeleteLatestSearchRequest.java @@ -0,0 +1,12 @@ +package allchive.server.api.search.model.dto.request; + + +import io.swagger.v3.oas.annotations.media.Schema; +import java.util.List; +import lombok.Getter; + +@Getter +public class DeleteLatestSearchRequest { + @Schema(description = "삭제할 최근 검색어 고유번호 리스트") + private List ids; +} diff --git a/Api/src/main/java/allchive/server/api/search/service/DeleteLatestSearchUseCase.java b/Api/src/main/java/allchive/server/api/search/service/DeleteLatestSearchUseCase.java index 83d1f24a..9637d8b5 100644 --- a/Api/src/main/java/allchive/server/api/search/service/DeleteLatestSearchUseCase.java +++ b/Api/src/main/java/allchive/server/api/search/service/DeleteLatestSearchUseCase.java @@ -2,9 +2,11 @@ import allchive.server.api.config.security.SecurityUtil; +import allchive.server.api.search.model.dto.request.DeleteLatestSearchRequest; import allchive.server.core.annotation.UseCase; -import allchive.server.domain.domains.search.adaptor.LatestSearchAdaptor; +import allchive.server.domain.domains.search.service.LatestSearchDomainService; import allchive.server.domain.domains.search.validator.LatestSearchValidator; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.transaction.annotation.Transactional; @@ -12,16 +14,17 @@ @RequiredArgsConstructor public class DeleteLatestSearchUseCase { private final LatestSearchValidator latestSearchValidator; - private final LatestSearchAdaptor latestSearchAdaptor; + private final LatestSearchDomainService latestSearchDomainService; @Transactional - public void execute(Long latestSearchId) { - Long userId = SecurityUtil.getCurrentUserId(); - validateExecution(latestSearchId, userId); - latestSearchAdaptor.deleteByIdAndUserId(latestSearchId, userId); + public void execute(DeleteLatestSearchRequest request) { + validateExecution(request.getIds()); + latestSearchDomainService.deleteAllByIdIn(request.getIds()); } - private void validateExecution(Long latestSearchId, Long userId) { - latestSearchValidator.validateExistByIdAndUserId(latestSearchId, userId); + private void validateExecution(List ids) { + Long userId = SecurityUtil.getCurrentUserId(); + latestSearchValidator.validateExistByIdIn(ids); + latestSearchValidator.verifyUserByIdIn(ids, userId); } } diff --git a/Api/src/main/java/allchive/server/api/search/service/GetRelativeSearchListUseCase.java b/Api/src/main/java/allchive/server/api/search/service/GetRelativeSearchListUseCase.java index a5745048..d1d3f681 100644 --- a/Api/src/main/java/allchive/server/api/search/service/GetRelativeSearchListUseCase.java +++ b/Api/src/main/java/allchive/server/api/search/service/GetRelativeSearchListUseCase.java @@ -3,7 +3,6 @@ import static allchive.server.core.consts.AllchiveConst.SEARCH_KEY; import static jodd.util.StringPool.ASTERISK; -import allchive.server.api.search.model.dto.request.SearchRequest; import allchive.server.api.search.model.dto.response.SearchListResponse; import allchive.server.core.annotation.UseCase; import java.util.ArrayList; diff --git a/Api/src/main/java/allchive/server/api/search/service/RenewalTitleDataUseCase.java b/Api/src/main/java/allchive/server/api/search/service/RenewalSearchDataUseCase.java similarity index 70% rename from Api/src/main/java/allchive/server/api/search/service/RenewalTitleDataUseCase.java rename to Api/src/main/java/allchive/server/api/search/service/RenewalSearchDataUseCase.java index 6ab96628..64dc256e 100644 --- a/Api/src/main/java/allchive/server/api/search/service/RenewalTitleDataUseCase.java +++ b/Api/src/main/java/allchive/server/api/search/service/RenewalSearchDataUseCase.java @@ -6,6 +6,8 @@ import allchive.server.core.annotation.UseCase; import allchive.server.domain.domains.archiving.adaptor.ArchivingAdaptor; import allchive.server.domain.domains.archiving.domain.Archiving; +import allchive.server.domain.domains.content.adaptor.TagAdaptor; +import allchive.server.domain.domains.content.domain.Tag; import java.util.HashSet; import java.util.Set; import lombok.RequiredArgsConstructor; @@ -17,8 +19,9 @@ @UseCase @Slf4j @RequiredArgsConstructor -public class RenewalTitleDataUseCase { +public class RenewalSearchDataUseCase { private final ArchivingAdaptor archivingAdaptor; + private final TagAdaptor tagAdaptor; private final RedisTemplate redisTemplate; @Scheduled(cron = "0 0 3 * * *") @@ -36,6 +39,24 @@ public void executeForce() { private void renewalData() { redisTemplate.delete(SEARCH_KEY); + renewalArchiving(); + renewalTag(); + } + + private void renewalTag() { + Set tags = new HashSet<>(tagAdaptor.findAll()); + tags.forEach( + tag -> { + redisTemplate.opsForZSet().add(SEARCH_KEY, tag.getName().trim() + ASTERISK, 0); + for (int index = 0; index <= tag.getName().length(); index++) { + redisTemplate + .opsForZSet() + .add(SEARCH_KEY, tag.getName().trim().substring(0, index), 0); + } + }); + } + + private void renewalArchiving() { Set archivings = new HashSet<>(archivingAdaptor.findAllByPublicStatus(Boolean.TRUE)); archivings.forEach( diff --git a/Api/src/main/java/allchive/server/api/search/service/SearchArchivingUseCase.java b/Api/src/main/java/allchive/server/api/search/service/SearchArchivingUseCase.java index 8c4bb03a..bb0c88b6 100644 --- a/Api/src/main/java/allchive/server/api/search/service/SearchArchivingUseCase.java +++ b/Api/src/main/java/allchive/server/api/search/service/SearchArchivingUseCase.java @@ -10,12 +10,17 @@ import allchive.server.domain.domains.archiving.adaptor.ArchivingAdaptor; import allchive.server.domain.domains.block.adaptor.BlockAdaptor; import allchive.server.domain.domains.block.domain.Block; +import allchive.server.domain.domains.content.adaptor.ContentTagGroupAdaptor; +import allchive.server.domain.domains.content.adaptor.TagAdaptor; +import allchive.server.domain.domains.content.domain.Tag; import allchive.server.domain.domains.search.adaptor.LatestSearchAdaptor; import allchive.server.domain.domains.search.domain.LatestSearch; import allchive.server.domain.domains.search.service.LatestSearchDomainService; import allchive.server.domain.domains.user.adaptor.ScrapAdaptor; import allchive.server.domain.domains.user.domain.Scrap; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; @@ -29,59 +34,79 @@ public class SearchArchivingUseCase { private final BlockAdaptor blockAdaptor; private final LatestSearchAdaptor latestSearchAdaptor; private final LatestSearchDomainService latestSearchDomainService; + private final TagAdaptor tagAdaptor; + private final ContentTagGroupAdaptor contentTagGroupAdaptor; @Transactional public SearchResponse execute(Pageable pageable, ArchivingType type, String word) { Long userId = SecurityUtil.getCurrentUserId(); - SliceResponse my = null; - SliceResponse community = null; + Set tagArchivingIds = getTagArchivingIds(userId, word); + SliceResponse my; + SliceResponse community; renewalLatestSearch(userId, word); switch (type) { case ALL -> { - my = getMyArchivings(userId, word, pageable); - community = getCommunityArchivings(userId, word, pageable); + my = getMyArchivings(userId, word, pageable, tagArchivingIds); + community = getCommunityArchivings(userId, word, pageable, tagArchivingIds); return SearchResponse.forAll(my, community); } case MY -> { - my = getMyArchivings(userId, word, pageable); + my = getMyArchivings(userId, word, pageable, tagArchivingIds); return SearchResponse.forMy(my); } case COMMUNITY -> { - community = getCommunityArchivings(userId, word, pageable); + community = getCommunityArchivings(userId, word, pageable, tagArchivingIds); return SearchResponse.forCommunity(community); } } return null; } + private Set getTagArchivingIds(Long userId, String word) { + List tags = tagAdaptor.findAllByUserIdAndName(userId, word); + return contentTagGroupAdaptor.queryContentTagGroupByTagInWithContent(tags).stream() + .map(contentTagGroup -> contentTagGroup.getContent().getArchivingId()) + .collect(Collectors.toSet()); + } + private void renewalLatestSearch(Long userId, String keyword) { List searches = latestSearchAdaptor.findAllByUserIdOrderByCreatedAt(userId); - if (searches.size() == 5) { - latestSearchDomainService.delete(searches.get(0)); + if (!isExistSearchKeyword(searches, keyword)) { + if (searches.size() == 5) { + latestSearchDomainService.delete(searches.get(0)); + } + LatestSearch newSearch = LatestSearch.of(keyword, userId); + latestSearchDomainService.save(newSearch); } - LatestSearch newSearch = LatestSearch.of(keyword, userId); - latestSearchDomainService.save(newSearch); + } + + private boolean isExistSearchKeyword(List searches, String keyword) { + return !searches.stream() + .filter(search -> search.getKeyword().equals(keyword)) + .toList() + .isEmpty(); } private SliceResponse getMyArchivings( - Long userId, String keyword, Pageable pageable) { + Long userId, String keyword, Pageable pageable, Set tagArchivingIds) { Slice archivingSlices = archivingAdaptor - .querySliceArchivingByUserIdAndKeywords(userId, keyword, pageable) + .querySliceArchivingByUserIdAndKeywordsOrderByTagArchvingIds( + userId, keyword, pageable, tagArchivingIds) .map(archiving -> ArchivingResponse.of(archiving, Boolean.FALSE)); return SliceResponse.of(archivingSlices); } private SliceResponse getCommunityArchivings( - Long userId, String keyword, Pageable pageable) { + Long userId, String keyword, Pageable pageable, Set tagArchivingIds) { List archivingIdList = scrapAdaptor.findAllByUserId(userId).stream().map(Scrap::getArchivingId).toList(); List blockList = blockAdaptor.findByBlockFrom(userId).stream().map(Block::getBlockUser).toList(); Slice archivingSlices = archivingAdaptor - .querySliceArchivingByKeywordExceptBlock( - archivingIdList, blockList, keyword, pageable) + .querySliceArchivingByKeywordExceptBlockOrderByTagArchvingIds( + archivingIdList, blockList, keyword, pageable, tagArchivingIds) .map(archiving -> ArchivingResponse.of(archiving, Boolean.FALSE)); return SliceResponse.of(archivingSlices); } diff --git a/Domain/src/main/java/allchive/server/domain/domains/archiving/adaptor/ArchivingAdaptor.java b/Domain/src/main/java/allchive/server/domain/domains/archiving/adaptor/ArchivingAdaptor.java index b5c84f34..c887e32f 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/archiving/adaptor/ArchivingAdaptor.java +++ b/Domain/src/main/java/allchive/server/domain/domains/archiving/adaptor/ArchivingAdaptor.java @@ -8,6 +8,7 @@ import allchive.server.domain.domains.archiving.exception.exceptions.ArchivingNotFoundException; import allchive.server.domain.domains.archiving.repository.ArchivingRepository; import java.util.List; +import java.util.Set; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; @@ -73,16 +74,20 @@ public void deleteAllById(List archivingIds) { archivingRepository.deleteAllById(archivingIds); } - public Slice querySliceArchivingByUserIdAndKeywords( - Long userId, String keyword, Pageable pageable) { - return archivingRepository.querySliceArchivingByUserIdAndKeywords( - userId, keyword, pageable); + public Slice querySliceArchivingByUserIdAndKeywordsOrderByTagArchvingIds( + Long userId, String keyword, Pageable pageable, Set tagArchivingIds) { + return archivingRepository.querySliceArchivingByUserIdAndKeywordsOrderByTagArchvingIds( + userId, keyword, pageable, tagArchivingIds); } - public Slice querySliceArchivingByKeywordExceptBlock( - List archivingIdList, List blockList, String keyword, Pageable pageable) { - return archivingRepository.querySliceArchivingByKeywordExceptBlock( - archivingIdList, blockList, keyword, pageable); + public Slice querySliceArchivingByKeywordExceptBlockOrderByTagArchvingIds( + List archivingIdList, + List blockList, + String keyword, + Pageable pageable, + Set tagArchivingIds) { + return archivingRepository.querySliceArchivingByKeywordExceptBlockOrderByTagArchvingIds( + archivingIdList, blockList, keyword, pageable, tagArchivingIds); } public List findAllByPublicStatus(Boolean publicStatus) { diff --git a/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepository.java b/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepository.java index 03946df8..db4b6c53 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepository.java +++ b/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepository.java @@ -4,6 +4,7 @@ import allchive.server.domain.domains.archiving.domain.Archiving; import allchive.server.domain.domains.archiving.domain.enums.Category; import java.util.List; +import java.util.Set; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; @@ -20,9 +21,13 @@ Slice querySliceArchivingByIdIn( boolean queryArchivingExistById(Long archivingId); - Slice querySliceArchivingByUserIdAndKeywords( - Long userId, String keyword, Pageable pageable); + Slice querySliceArchivingByUserIdAndKeywordsOrderByTagArchvingIds( + Long userId, String keyword, Pageable pageable, Set tagArchivingIds); - Slice querySliceArchivingByKeywordExceptBlock( - List archivingIdList, List blockList, String keyword, Pageable pageable); + Slice querySliceArchivingByKeywordExceptBlockOrderByTagArchvingIds( + List archivingIdList, + List blockList, + String keyword, + Pageable pageable, + Set tagArchivingIds); } diff --git a/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepositoryImpl.java b/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepositoryImpl.java index c0cae02f..f1d64d47 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepositoryImpl.java +++ b/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepositoryImpl.java @@ -12,6 +12,7 @@ import com.querydsl.jpa.impl.JPAQueryFactory; import java.time.LocalDateTime; import java.util.List; +import java.util.Set; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; @@ -93,13 +94,13 @@ public boolean queryArchivingExistById(Long archivingId) { } @Override - public Slice querySliceArchivingByUserIdAndKeywords( - Long userId, String keyword, Pageable pageable) { + public Slice querySliceArchivingByUserIdAndKeywordsOrderByTagArchvingIds( + Long userId, String keyword, Pageable pageable, Set tagArchivingIds) { List archivings = queryFactory .selectFrom(archiving) - .where(userIdEq(userId), titleContain(keyword)) - .orderBy(createdAtDesc()) + .where(userIdEq(userId), titleContainOrIdIn(keyword, tagArchivingIds)) + .orderBy(idIn(tagArchivingIds), createdAtDesc()) .offset(pageable.getOffset()) .limit(pageable.getPageSize() + 1) .fetch(); @@ -107,8 +108,12 @@ public Slice querySliceArchivingByUserIdAndKeywords( } @Override - public Slice querySliceArchivingByKeywordExceptBlock( - List archivingIdList, List blockList, String keyword, Pageable pageable) { + public Slice querySliceArchivingByKeywordExceptBlockOrderByTagArchvingIds( + List archivingIdList, + List blockList, + String keyword, + Pageable pageable, + Set tagArchivingIds) { List archivings = queryFactory .select(archiving) @@ -117,8 +122,12 @@ public Slice querySliceArchivingByKeywordExceptBlock( userIdNotIn(blockList), publicStatusTrue(), deleteStatusFalse(), - titleContain(keyword)) - .orderBy(scrabListDesc(archivingIdList), scrapCntDesc(), createdAtDesc()) + titleContainOrIdIn(keyword, tagArchivingIds)) + .orderBy( + idIn(tagArchivingIds), + scrabListDesc(archivingIdList), + scrapCntDesc(), + createdAtDesc()) .offset(pageable.getOffset()) .limit(pageable.getPageSize() + 1) .fetch(); @@ -156,8 +165,8 @@ private BooleanExpression archivingIdEq(Long archivingId) { return archiving.id.eq(archivingId); } - private BooleanExpression titleContain(String keyword) { - return archiving.title.contains(keyword); + private BooleanExpression titleContainOrIdIn(String keyword, Set tagArchivingIds) { + return archiving.title.contains(keyword).or(archiving.id.in(tagArchivingIds)); } private OrderSpecifier scrabListDesc(List archivingIdList) { @@ -183,4 +192,10 @@ private OrderSpecifier createdAtDesc() { private OrderSpecifier categoryDesc() { return archiving.category.desc(); } + + private OrderSpecifier idIn(Set tagArchivingIds) { + NumberExpression idInStatus = + new CaseBuilder().when(archiving.id.in(tagArchivingIds)).then(1L).otherwise(0L); + return idInStatus.desc(); + } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/content/adaptor/ContentTagGroupAdaptor.java b/Domain/src/main/java/allchive/server/domain/domains/content/adaptor/ContentTagGroupAdaptor.java index 942c917e..ebbf5bb2 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/content/adaptor/ContentTagGroupAdaptor.java +++ b/Domain/src/main/java/allchive/server/domain/domains/content/adaptor/ContentTagGroupAdaptor.java @@ -41,4 +41,8 @@ public List queryContentTagGroupByContentWithTag(Content conten public void deleteAllByContent(Content content) { contentTagGroupRepository.deleteAllByContent(content); } + + public List queryContentTagGroupByTagInWithContent(List tags) { + return contentTagGroupRepository.queryContentTagGroupByTagInWithContent(tags); + } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/content/adaptor/TagAdaptor.java b/Domain/src/main/java/allchive/server/domain/domains/content/adaptor/TagAdaptor.java index 5b6e53ae..3a43feff 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/content/adaptor/TagAdaptor.java +++ b/Domain/src/main/java/allchive/server/domain/domains/content/adaptor/TagAdaptor.java @@ -44,4 +44,12 @@ public List findAllByUserId(Long userId) { public void deleteAll(List tagList) { tagRepository.deleteAll(tagList); } + + public List findAllByUserIdAndName(Long userId, String word) { + return tagRepository.findAllByUserIdAndName(userId, word); + } + + public List findAll() { + return tagRepository.findAll(); + } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/content/repository/ContentTagGroupCustomRepository.java b/Domain/src/main/java/allchive/server/domain/domains/content/repository/ContentTagGroupCustomRepository.java index 546979cb..05105f26 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/content/repository/ContentTagGroupCustomRepository.java +++ b/Domain/src/main/java/allchive/server/domain/domains/content/repository/ContentTagGroupCustomRepository.java @@ -3,10 +3,13 @@ import allchive.server.domain.domains.content.domain.Content; import allchive.server.domain.domains.content.domain.ContentTagGroup; +import allchive.server.domain.domains.content.domain.Tag; import java.util.List; public interface ContentTagGroupCustomRepository { public List queryContentTagGroupByContentIn(List contentList); List queryContentTagGroupByContentWithTag(Content content); + + List queryContentTagGroupByTagInWithContent(List tags); } diff --git a/Domain/src/main/java/allchive/server/domain/domains/content/repository/ContentTagGroupCustomRepositoryImpl.java b/Domain/src/main/java/allchive/server/domain/domains/content/repository/ContentTagGroupCustomRepositoryImpl.java index 57f47f4a..055f32ce 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/content/repository/ContentTagGroupCustomRepositoryImpl.java +++ b/Domain/src/main/java/allchive/server/domain/domains/content/repository/ContentTagGroupCustomRepositoryImpl.java @@ -1,10 +1,12 @@ package allchive.server.domain.domains.content.repository; +import static allchive.server.domain.domains.content.domain.QContent.content; import static allchive.server.domain.domains.content.domain.QContentTagGroup.contentTagGroup; import static allchive.server.domain.domains.content.domain.QTag.tag; import allchive.server.domain.domains.content.domain.Content; import allchive.server.domain.domains.content.domain.ContentTagGroup; +import allchive.server.domain.domains.content.domain.Tag; import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQueryFactory; @@ -38,6 +40,17 @@ public List queryContentTagGroupByContentWithTag(Content conten .fetch(); } + @Override + public List queryContentTagGroupByTagInWithContent(List tags) { + return queryFactory + .selectFrom(contentTagGroup) + .join(contentTagGroup.content, content) + .fetchJoin() + .where(tagIn(tags)) + .orderBy(createdAtDesc()) + .fetch(); + } + private BooleanExpression contentIdIn(List contentList) { return contentTagGroup.content.in(contentList); } @@ -46,6 +59,10 @@ private BooleanExpression contentEq(Content content) { return contentTagGroup.content.eq(content); } + private BooleanExpression tagIn(List tagList) { + return contentTagGroup.tag.in(tagList); + } + private OrderSpecifier createdAtDesc() { return contentTagGroup.createdAt.desc(); } diff --git a/Domain/src/main/java/allchive/server/domain/domains/content/repository/TagRepository.java b/Domain/src/main/java/allchive/server/domain/domains/content/repository/TagRepository.java index 50911c53..803a0528 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/content/repository/TagRepository.java +++ b/Domain/src/main/java/allchive/server/domain/domains/content/repository/TagRepository.java @@ -9,4 +9,6 @@ public interface TagRepository extends JpaRepository, TagCustomReposi List findAllByUserIdOrderByCreatedAtDesc(Long userId); List findAllByUserId(Long userId); + + List findAllByUserIdAndName(Long userId, String name); } diff --git a/Domain/src/main/java/allchive/server/domain/domains/search/adaptor/LatestSearchAdaptor.java b/Domain/src/main/java/allchive/server/domain/domains/search/adaptor/LatestSearchAdaptor.java index ad2f38aa..4b0c6cee 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/search/adaptor/LatestSearchAdaptor.java +++ b/Domain/src/main/java/allchive/server/domain/domains/search/adaptor/LatestSearchAdaptor.java @@ -3,7 +3,6 @@ import allchive.server.core.annotation.Adaptor; import allchive.server.domain.domains.search.domain.LatestSearch; -import allchive.server.domain.domains.search.exception.exceptions.LatestSearchNotFoundException; import allchive.server.domain.domains.search.repository.LatestSearchRepository; import java.util.List; import lombok.RequiredArgsConstructor; @@ -29,13 +28,11 @@ public void deleteAllByUserId(Long userId) { latestSearchRepository.deleteAllByUserId(userId); } - public LatestSearch findByIdAndUserId(Long latestSearchId, Long userId) { - return latestSearchRepository - .findByIdAndUserId(latestSearchId, userId) - .orElseThrow(() -> LatestSearchNotFoundException.EXCEPTION); + public List findAllByIdIn(List ids) { + return latestSearchRepository.findAllByIdIn(ids); } - public void deleteByIdAndUserId(Long latestSearchId, Long userId) { - latestSearchRepository.deleteByIdAndUserId(latestSearchId, userId); + public void deleteAllByIdIn(List ids) { + latestSearchRepository.deleteAllByIdIn(ids); } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/search/exception/SearchErrorCode.java b/Domain/src/main/java/allchive/server/domain/domains/search/exception/SearchErrorCode.java index 5cb874bb..b0d4154f 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/search/exception/SearchErrorCode.java +++ b/Domain/src/main/java/allchive/server/domain/domains/search/exception/SearchErrorCode.java @@ -10,6 +10,7 @@ @Getter @AllArgsConstructor public enum SearchErrorCode implements BaseErrorCode { + NO_AUTHORITY_UPDATE_LATEST_SEARCH(FORBIDDEN, "LATESTSEARCH_403_1", "최근 검색어 수정 권한이 없습니다."), LATEST_SEARCH_NOT_FOUND(NOT_FOUND, "LATESTSEARCH_404_1", "최근 검색어를 찾을 수 없습니다."); private int status; private String code; diff --git a/Domain/src/main/java/allchive/server/domain/domains/search/exception/exceptions/NoAuthorityUpdateLatestSearchException.java b/Domain/src/main/java/allchive/server/domain/domains/search/exception/exceptions/NoAuthorityUpdateLatestSearchException.java new file mode 100644 index 00000000..5254a849 --- /dev/null +++ b/Domain/src/main/java/allchive/server/domain/domains/search/exception/exceptions/NoAuthorityUpdateLatestSearchException.java @@ -0,0 +1,14 @@ +package allchive.server.domain.domains.search.exception.exceptions; + + +import allchive.server.core.error.BaseErrorException; +import allchive.server.domain.domains.search.exception.SearchErrorCode; + +public class NoAuthorityUpdateLatestSearchException extends BaseErrorException { + + public static final BaseErrorException EXCEPTION = new NoAuthorityUpdateLatestSearchException(); + + private NoAuthorityUpdateLatestSearchException() { + super(SearchErrorCode.NO_AUTHORITY_UPDATE_LATEST_SEARCH); + } +} diff --git a/Domain/src/main/java/allchive/server/domain/domains/search/repository/LatestSearchRepository.java b/Domain/src/main/java/allchive/server/domain/domains/search/repository/LatestSearchRepository.java index aa8738d3..27636cca 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/search/repository/LatestSearchRepository.java +++ b/Domain/src/main/java/allchive/server/domain/domains/search/repository/LatestSearchRepository.java @@ -3,7 +3,6 @@ import allchive.server.domain.domains.search.domain.LatestSearch; import java.util.List; -import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; public interface LatestSearchRepository extends JpaRepository { @@ -11,7 +10,7 @@ public interface LatestSearchRepository extends JpaRepository findByIdAndUserId(Long latestSearchId, Long userId); + List findAllByIdIn(List ids); - void deleteByIdAndUserId(Long latestSearchId, Long userId); + void deleteAllByIdIn(List ids); } diff --git a/Domain/src/main/java/allchive/server/domain/domains/search/service/LatestSearchDomainService.java b/Domain/src/main/java/allchive/server/domain/domains/search/service/LatestSearchDomainService.java index 533529ac..2de4ad1c 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/search/service/LatestSearchDomainService.java +++ b/Domain/src/main/java/allchive/server/domain/domains/search/service/LatestSearchDomainService.java @@ -4,6 +4,7 @@ import allchive.server.core.annotation.DomainService; import allchive.server.domain.domains.search.adaptor.LatestSearchAdaptor; import allchive.server.domain.domains.search.domain.LatestSearch; +import java.util.List; import lombok.RequiredArgsConstructor; @DomainService @@ -22,4 +23,8 @@ public void save(LatestSearch newSearch) { public void deleteAllByUserId(Long userId) { latestSearchAdaptor.deleteAllByUserId(userId); } + + public void deleteAllByIdIn(List ids) { + latestSearchAdaptor.deleteAllByIdIn(ids); + } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/search/validator/LatestSearchValidator.java b/Domain/src/main/java/allchive/server/domain/domains/search/validator/LatestSearchValidator.java index 05b91078..4829967c 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/search/validator/LatestSearchValidator.java +++ b/Domain/src/main/java/allchive/server/domain/domains/search/validator/LatestSearchValidator.java @@ -3,6 +3,10 @@ import allchive.server.core.annotation.Validator; import allchive.server.domain.domains.search.adaptor.LatestSearchAdaptor; +import allchive.server.domain.domains.search.domain.LatestSearch; +import allchive.server.domain.domains.search.exception.exceptions.LatestSearchNotFoundException; +import allchive.server.domain.domains.search.exception.exceptions.NoAuthorityUpdateLatestSearchException; +import java.util.List; import lombok.RequiredArgsConstructor; @Validator @@ -10,7 +14,20 @@ public class LatestSearchValidator { private final LatestSearchAdaptor latestSearchAdaptor; - public void validateExistByIdAndUserId(Long latestSearchId, Long userId) { - latestSearchAdaptor.findByIdAndUserId(latestSearchId, userId); + public void validateExistByIdIn(List ids) { + List searches = latestSearchAdaptor.findAllByIdIn(ids); + if (searches.size() != ids.size()) { + throw LatestSearchNotFoundException.EXCEPTION; + } + } + + public void verifyUserByIdIn(List ids, Long userId) { + List searches = latestSearchAdaptor.findAllByIdIn(ids); + searches.forEach( + search -> { + if (!search.getUserId().equals(userId)) { + throw NoAuthorityUpdateLatestSearchException.EXCEPTION; + } + }); } } From 8f190f30b90ae72095687a511056ff7466a12231 Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Thu, 27 Jul 2023 21:29:30 +0900 Subject: [PATCH 05/34] =?UTF-8?q?[fix]=20=EB=B9=88=20=ED=8C=8C=EB=9E=8C?= =?UTF-8?q?=EA=B0=92=20validation=20=EC=B6=94=EA=B0=80=20(#67)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/api/common/util/StringParamUtil.java | 13 +++++++++++++ .../service/GetRelativeSearchListUseCase.java | 6 ++++++ .../api/search/service/SearchArchivingUseCase.java | 6 ++++++ .../server/core/error/GlobalErrorCode.java | 1 + .../error/exception/EmptyParamValueException.java | 14 ++++++++++++++ 5 files changed, 40 insertions(+) create mode 100644 Api/src/main/java/allchive/server/api/common/util/StringParamUtil.java create mode 100644 Core/src/main/java/allchive/server/core/error/exception/EmptyParamValueException.java diff --git a/Api/src/main/java/allchive/server/api/common/util/StringParamUtil.java b/Api/src/main/java/allchive/server/api/common/util/StringParamUtil.java new file mode 100644 index 00000000..0cc94558 --- /dev/null +++ b/Api/src/main/java/allchive/server/api/common/util/StringParamUtil.java @@ -0,0 +1,13 @@ +package allchive.server.api.common.util; + +import allchive.server.core.error.exception.EmptyParamValueException; +import org.springframework.stereotype.Component; + +@Component +public class StringParamUtil { + public static void checkEmptyString(String param) { + if (param.equals("")) { + throw EmptyParamValueException.EXCEPTION; + } + } +} diff --git a/Api/src/main/java/allchive/server/api/search/service/GetRelativeSearchListUseCase.java b/Api/src/main/java/allchive/server/api/search/service/GetRelativeSearchListUseCase.java index d1d3f681..f148d8b5 100644 --- a/Api/src/main/java/allchive/server/api/search/service/GetRelativeSearchListUseCase.java +++ b/Api/src/main/java/allchive/server/api/search/service/GetRelativeSearchListUseCase.java @@ -3,6 +3,7 @@ import static allchive.server.core.consts.AllchiveConst.SEARCH_KEY; import static jodd.util.StringPool.ASTERISK; +import allchive.server.api.common.util.StringParamUtil; import allchive.server.api.search.model.dto.response.SearchListResponse; import allchive.server.core.annotation.UseCase; import java.util.ArrayList; @@ -20,6 +21,7 @@ public class GetRelativeSearchListUseCase { @Transactional public SearchListResponse execute(String word) { + validateExecution(word); ZSetOperations zSetOperations = redisTemplate.opsForZSet(); List autoCompleteList = new ArrayList<>(); Long rank = zSetOperations.rank(SEARCH_KEY, word); @@ -30,6 +32,10 @@ public SearchListResponse execute(String word) { return SearchListResponse.from(autoCompleteList); } + private void validateExecution(String word) { + StringParamUtil.checkEmptyString(word); + } + private List getAutoCompleteList(Set rangeList, String keyword) { return rangeList.stream() .filter(value -> value.endsWith(ASTERISK) && value.startsWith(keyword)) diff --git a/Api/src/main/java/allchive/server/api/search/service/SearchArchivingUseCase.java b/Api/src/main/java/allchive/server/api/search/service/SearchArchivingUseCase.java index bb0c88b6..dfb0a313 100644 --- a/Api/src/main/java/allchive/server/api/search/service/SearchArchivingUseCase.java +++ b/Api/src/main/java/allchive/server/api/search/service/SearchArchivingUseCase.java @@ -3,6 +3,7 @@ import allchive.server.api.archiving.model.dto.response.ArchivingResponse; import allchive.server.api.common.slice.SliceResponse; +import allchive.server.api.common.util.StringParamUtil; import allchive.server.api.config.security.SecurityUtil; import allchive.server.api.search.model.dto.response.SearchResponse; import allchive.server.api.search.model.enums.ArchivingType; @@ -39,6 +40,7 @@ public class SearchArchivingUseCase { @Transactional public SearchResponse execute(Pageable pageable, ArchivingType type, String word) { + validateExecution(word); Long userId = SecurityUtil.getCurrentUserId(); Set tagArchivingIds = getTagArchivingIds(userId, word); SliceResponse my; @@ -62,6 +64,10 @@ public SearchResponse execute(Pageable pageable, ArchivingType type, String word return null; } + private void validateExecution(String word) { + StringParamUtil.checkEmptyString(word); + } + private Set getTagArchivingIds(Long userId, String word) { List tags = tagAdaptor.findAllByUserIdAndName(userId, word); return contentTagGroupAdaptor.queryContentTagGroupByTagInWithContent(tags).stream() diff --git a/Core/src/main/java/allchive/server/core/error/GlobalErrorCode.java b/Core/src/main/java/allchive/server/core/error/GlobalErrorCode.java index f73bb7a8..aeb58a0c 100644 --- a/Core/src/main/java/allchive/server/core/error/GlobalErrorCode.java +++ b/Core/src/main/java/allchive/server/core/error/GlobalErrorCode.java @@ -14,6 +14,7 @@ public enum GlobalErrorCode implements BaseErrorCode { /** Server 오류 * */ HTTP_MESSAGE_NOT_READABLE(BAD_REQUEST, "GLOBAL_400_1", "잘못된 형식의 값을 입력했습니다."), + EMPTY_PARAM_VALUE(BAD_REQUEST, "GLOBAL_400_2", "빈 파람 값을 입력했습니다."), _INTERNAL_SERVER_ERROR(INTERNAL_SERVER, "GLOBAL_500_1", "서버 오류. 관리자에게 문의 부탁드립니다."), INVALID_OAUTH_PROVIDER(INTERNAL_SERVER, "GLOBAL_500_2", "지원하지 않는 OAuth Provider 입니다."), diff --git a/Core/src/main/java/allchive/server/core/error/exception/EmptyParamValueException.java b/Core/src/main/java/allchive/server/core/error/exception/EmptyParamValueException.java new file mode 100644 index 00000000..1f2d37e7 --- /dev/null +++ b/Core/src/main/java/allchive/server/core/error/exception/EmptyParamValueException.java @@ -0,0 +1,14 @@ +package allchive.server.core.error.exception; + + +import allchive.server.core.error.BaseErrorException; +import allchive.server.core.error.GlobalErrorCode; + +public class EmptyParamValueException extends BaseErrorException { + + public static final BaseErrorException EXCEPTION = new EmptyParamValueException(); + + private EmptyParamValueException() { + super(GlobalErrorCode.EMPTY_PARAM_VALUE); + } +} From 9b1b87c02f8b78184fa04182bddd2b9047c989e4 Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Fri, 28 Jul 2023 01:28:48 +0900 Subject: [PATCH 06/34] =?UTF-8?q?[refac]=20oauth=20=ED=83=88=ED=87=B4=20pr?= =?UTF-8?q?ovider=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95,=20=EC=95=A0?= =?UTF-8?q?=ED=94=8C=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EB=B3=80=EC=88=98=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9=20=EB=B0=8F=20=EB=A1=9C=EC=A7=81=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20(#69)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [refac] oauth 탈퇴 provider 부분 변경 #65 * [refac] apple 로그인 변수 수정 #35 * [feat] apple 로그인 테스트용 deploy 수정 #35 * [feat] apple 로그인 테스트용 deploy 수정2 #35 * [fix] apple authkey property로 변경 #35 * [fix] apple authkey property pem 형식으로 전환 #35 * [fix] apple authkey log 추가 #35 * [fix] apple authkey 개행문자 대체 로직 변경 #35 * [fix] apple authkey 개행문자 대체 로직 변경 #35 * [chore] 미사용 변수 제거 #35 * [chore] spotless 적용 #35 * [fix] action 원상복구 #35 --- .gitignore | 3 ++- .../api/auth/controller/AuthController.java | 6 ++---- .../api/auth/service/WithdrawUserUseCase.java | 6 ++++-- .../auth/service/helper/AppleOauthHelper.java | 6 +++++- .../auth/service/helper/KakaoOauthHelper.java | 2 -- .../server/core/error/GlobalErrorCode.java | 12 ++--------- .../error/exception/ExampleException.java | 14 ------------- .../NoAppleAccessTokenException.java | 14 +++++++++++++ .../core/properties/AppleOAuthProperties.java | 5 +---- Core/src/main/resources/application-core.yml | 7 ++----- .../oauth/apple/helper/AppleLoginUtil.java | 21 ++++++------------- 11 files changed, 38 insertions(+), 58 deletions(-) delete mode 100644 Core/src/main/java/allchive/server/core/error/exception/ExampleException.java create mode 100644 Core/src/main/java/allchive/server/core/error/exception/NoAppleAccessTokenException.java diff --git a/.gitignore b/.gitignore index 9d21c5b9..303c6f31 100644 --- a/.gitignore +++ b/.gitignore @@ -42,4 +42,5 @@ out/ .env.* -Domain/src/main/generated/**/*.java \ No newline at end of file +Domain/src/main/generated/**/*.java +Core/src/main/resources/static/apple/**.p8 \ No newline at end of file diff --git a/Api/src/main/java/allchive/server/api/auth/controller/AuthController.java b/Api/src/main/java/allchive/server/api/auth/controller/AuthController.java index 6cb01deb..1a68afd6 100644 --- a/Api/src/main/java/allchive/server/api/auth/controller/AuthController.java +++ b/Api/src/main/java/allchive/server/api/auth/controller/AuthController.java @@ -5,7 +5,6 @@ import allchive.server.api.auth.service.LogOutUserUseCase; import allchive.server.api.auth.service.TokenRefreshUseCase; import allchive.server.api.auth.service.WithdrawUserUseCase; -import allchive.server.domain.domains.user.domain.enums.OauthProvider; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -23,12 +22,11 @@ public class AuthController { private final TokenRefreshUseCase tokenRefreshUseCase; @Operation(summary = "회원탈퇴를 합니다.") - @DeleteMapping("/withdrawal/{provider}") + @DeleteMapping("/withdrawal") public void withDrawUser( - @PathVariable OauthProvider provider, @RequestParam(required = false, name = "appleAccessToken", value = "") String appleAccessToken) { - withdrawUserUseCase.execute(provider, appleAccessToken); + withdrawUserUseCase.execute(appleAccessToken); } @Operation(summary = "로그아웃을 합니다.") diff --git a/Api/src/main/java/allchive/server/api/auth/service/WithdrawUserUseCase.java b/Api/src/main/java/allchive/server/api/auth/service/WithdrawUserUseCase.java index 9e10da37..45fbff49 100644 --- a/Api/src/main/java/allchive/server/api/auth/service/WithdrawUserUseCase.java +++ b/Api/src/main/java/allchive/server/api/auth/service/WithdrawUserUseCase.java @@ -24,6 +24,7 @@ import allchive.server.domain.domains.user.service.UserDomainService; import java.util.List; import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; @UseCase @RequiredArgsConstructor @@ -43,11 +44,12 @@ public class WithdrawUserUseCase { private final ReportDomainService reportDomainService; private final UserDomainService userDomainService; - public void execute(OauthProvider provider, String appleAccessToken) { + @Transactional + public void execute(String appleAccessToken) { Long userId = SecurityUtil.getCurrentUserId(); User user = userAdaptor.findById(userId); // oauth쪽 탈퇴 - withdrawOauth(provider, appleAccessToken, user); + withdrawOauth(user.getOauthInfo().getProvider(), appleAccessToken, user); // 우리쪽 탈퇴 withdrawService(userId, user); } diff --git a/Api/src/main/java/allchive/server/api/auth/service/helper/AppleOauthHelper.java b/Api/src/main/java/allchive/server/api/auth/service/helper/AppleOauthHelper.java index 5bdb06e0..c8e5c7c7 100644 --- a/Api/src/main/java/allchive/server/api/auth/service/helper/AppleOauthHelper.java +++ b/Api/src/main/java/allchive/server/api/auth/service/helper/AppleOauthHelper.java @@ -4,6 +4,7 @@ import allchive.server.core.annotation.Helper; import allchive.server.core.dto.OIDCDecodePayload; +import allchive.server.core.error.exception.NoAppleAccessTokenException; import allchive.server.core.properties.AppleOAuthProperties; import allchive.server.domain.domains.user.domain.enums.OauthInfo; import allchive.server.domain.domains.user.domain.enums.OauthProvider; @@ -77,6 +78,9 @@ public OIDCDecodePayload getOIDCDecodePayload(String token) { /** apple측 회원 탈퇴 * */ public void withdrawAppleOauthUser(String appleOAuthAccessToken) { + if (appleOAuthAccessToken == null) { + throw NoAppleAccessTokenException.EXCEPTION; + } appleOAuthClient.revoke( appleOAuthProperties.getClientId(), appleOAuthAccessToken, this.getClientSecret()); } @@ -87,7 +91,7 @@ private String getClientSecret() { appleOAuthProperties.getTeamId(), appleOAuthProperties.getClientId(), appleOAuthProperties.getKeyId(), - appleOAuthProperties.getKeyPath(), + appleOAuthProperties.getAuthKey(), appleOAuthProperties.getBaseUrl()); } } diff --git a/Api/src/main/java/allchive/server/api/auth/service/helper/KakaoOauthHelper.java b/Api/src/main/java/allchive/server/api/auth/service/helper/KakaoOauthHelper.java index 14fe20ec..3615e805 100644 --- a/Api/src/main/java/allchive/server/api/auth/service/helper/KakaoOauthHelper.java +++ b/Api/src/main/java/allchive/server/api/auth/service/helper/KakaoOauthHelper.java @@ -26,7 +26,6 @@ public class KakaoOauthHelper { /** link * */ public String getKaKaoOauthLink(String referer) { - // TODO : 프론트 콜백 URL 알아내면 바꾸기 return kakaoOauthProperties.getBaseUrl() + String.format( KAKAO_OAUTH_QUERY_STRING, @@ -44,7 +43,6 @@ public String getKaKaoOauthLinkDev() { /** token * */ public KakaoTokenResponse getKakaoOauthToken(String code, String referer) { - // TODO : 프론트 콜백 URL 알아내면 바꾸기 return kakaoOauthClient.kakaoAuth( kakaoOauthProperties.getClientId(), referer + "kakao/callback", diff --git a/Core/src/main/java/allchive/server/core/error/GlobalErrorCode.java b/Core/src/main/java/allchive/server/core/error/GlobalErrorCode.java index aeb58a0c..1ade62da 100644 --- a/Core/src/main/java/allchive/server/core/error/GlobalErrorCode.java +++ b/Core/src/main/java/allchive/server/core/error/GlobalErrorCode.java @@ -14,25 +14,17 @@ public enum GlobalErrorCode implements BaseErrorCode { /** Server 오류 * */ HTTP_MESSAGE_NOT_READABLE(BAD_REQUEST, "GLOBAL_400_1", "잘못된 형식의 값을 입력했습니다."), - EMPTY_PARAM_VALUE(BAD_REQUEST, "GLOBAL_400_2", "빈 파람 값을 입력했습니다."), + NO_APPLE_ACCESS_TOKEN(BAD_REQUEST, "GLOBAL_400_2", "애플 엑세스 토큰이 필요합니다."), + EMPTY_PARAM_VALUE(BAD_REQUEST, "GLOBAL_400_3", "빈 파람 값을 입력했습니다."), _INTERNAL_SERVER_ERROR(INTERNAL_SERVER, "GLOBAL_500_1", "서버 오류. 관리자에게 문의 부탁드립니다."), INVALID_OAUTH_PROVIDER(INTERNAL_SERVER, "GLOBAL_500_2", "지원하지 않는 OAuth Provider 입니다."), - SECURITY_CONTEXT_NOT_FOUND(INTERNAL_SERVER, "GLOBAL_500_3", "security context not found"), /** 토큰 에러 * */ - // TODO : 에러 코드 정렬 INVALID_TOKEN(UNAUTHORIZED, "AUTH_401_2", "올바르지 않은 토큰입니다."), INVALID_ACCESS_TOKEN_ERROR(UNAUTHORIZED, "AUTH_401_4", "알맞은 accessToken 을 넣어주세요."), EXPIRED_TOKEN(UNAUTHORIZED, "AUTH_401_3", "만료된 엑세스 토큰입니다"), EXPIRED_REFRESH_TOKEN(UNAUTHORIZED, "AUTH_403_1", "인증 시간이 만료되었습니다. 재 로그인 해주세요."), - INVALID_AUTH_TOKEN(UNAUTHORIZED, "AUTH_401_2", "액세스 토큰이 유효하지 않습니다"), - INVALID_REFRESH_TOKEN(UNAUTHORIZED, "AUTH_401_4", "리프레시 토큰이 유효하지 않습니다"), - MISMATCH_REFRESH_TOKEN(UNAUTHORIZED, "AUTH_401_6", "리프레시 토큰의 유저 정보가 일치하지 않습니다"), - FORBIDDEN_ADMIN(FORBIDDEN, "AUTH_403_1", "권한이 부여되지 않은 사용자입니다"), - UNSUPPORTED_TOKEN(UNAUTHORIZED, "AUTH_401_7", "지원하지 않는 토큰입니다"), - INVALID_SIGNATURE(UNAUTHORIZED, "AUTH_401_8", "잘못된 JWT 서명입니다"), - NO_TOKEN(UNAUTHORIZED, "AUTH_401_1", "토큰이 존재하지 않습니다"), /** Feign Client 오류 */ OTHER_SERVER_BAD_REQUEST(BAD_REQUEST, "FEIGN_400_1", "Other server bad request"), diff --git a/Core/src/main/java/allchive/server/core/error/exception/ExampleException.java b/Core/src/main/java/allchive/server/core/error/exception/ExampleException.java deleted file mode 100644 index 478a21d7..00000000 --- a/Core/src/main/java/allchive/server/core/error/exception/ExampleException.java +++ /dev/null @@ -1,14 +0,0 @@ -package allchive.server.core.error.exception; - - -import allchive.server.core.error.BaseErrorException; -import allchive.server.core.error.GlobalErrorCode; - -public class ExampleException extends BaseErrorException { - - public static final BaseErrorException EXCEPTION = new ExampleException(); - - private ExampleException() { - super(GlobalErrorCode.EXAMPLE_ERROR); - } -} diff --git a/Core/src/main/java/allchive/server/core/error/exception/NoAppleAccessTokenException.java b/Core/src/main/java/allchive/server/core/error/exception/NoAppleAccessTokenException.java new file mode 100644 index 00000000..09954b42 --- /dev/null +++ b/Core/src/main/java/allchive/server/core/error/exception/NoAppleAccessTokenException.java @@ -0,0 +1,14 @@ +package allchive.server.core.error.exception; + + +import allchive.server.core.error.BaseErrorException; +import allchive.server.core.error.GlobalErrorCode; + +public class NoAppleAccessTokenException extends BaseErrorException { + + public static final BaseErrorException EXCEPTION = new NoAppleAccessTokenException(); + + private NoAppleAccessTokenException() { + super(GlobalErrorCode.NO_APPLE_ACCESS_TOKEN); + } +} diff --git a/Core/src/main/java/allchive/server/core/properties/AppleOAuthProperties.java b/Core/src/main/java/allchive/server/core/properties/AppleOAuthProperties.java index 5452eeff..b6f6837e 100644 --- a/Core/src/main/java/allchive/server/core/properties/AppleOAuthProperties.java +++ b/Core/src/main/java/allchive/server/core/properties/AppleOAuthProperties.java @@ -13,12 +13,9 @@ public class AppleOAuthProperties { private String baseUrl; private String clientId; - private String appClientId; private String keyId; private String redirectUrl; private String teamId; - private String scope; - private String keyPath; private String webCallbackUrl; - private String appstoreIssuer; + private String authKey; } diff --git a/Core/src/main/resources/application-core.yml b/Core/src/main/resources/application-core.yml index 443a8af9..f0e08718 100644 --- a/Core/src/main/resources/application-core.yml +++ b/Core/src/main/resources/application-core.yml @@ -17,12 +17,9 @@ oauth: apple: baseUrl: ${APPLE_BASE_URL} - clientId: ${APPLE_CLIENT} - appClientId: ${APPLE_APP_CLIENT_ID} + clientId: ${APPLE_CLIENT_ID} keyId: ${APPLE_KEY_ID} redirectUrl: ${APPLE_REDIRECT} teamId: ${APPLE_TEAM_ID} - scope: ${APPLE_SCOPE} - keyPath: ${APPLE_KEY_PATH} webCallbackUrl: ${APPLE_WEB_CALLBACK} - appstoreIssuer: ${APPLE_APPSTORE_ISSUER} \ No newline at end of file + authKey: ${APPLE_AUTH_KEY} \ No newline at end of file diff --git a/Infrastructure/src/main/java/allchive/server/infrastructure/oauth/apple/helper/AppleLoginUtil.java b/Infrastructure/src/main/java/allchive/server/infrastructure/oauth/apple/helper/AppleLoginUtil.java index e55b74e1..a5e0cfb7 100644 --- a/Infrastructure/src/main/java/allchive/server/infrastructure/oauth/apple/helper/AppleLoginUtil.java +++ b/Infrastructure/src/main/java/allchive/server/infrastructure/oauth/apple/helper/AppleLoginUtil.java @@ -8,6 +8,7 @@ import com.nimbusds.jose.crypto.ECDSASigner; import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -19,18 +20,10 @@ import java.util.Date; import org.bouncycastle.util.io.pem.PemObject; import org.bouncycastle.util.io.pem.PemReader; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; public class AppleLoginUtil { - /** - * client_secret 생성 Apple Document URL ‣ - * https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens - * - * @return client_secret(jwt) - */ public static String createClientSecret( - String teamId, String clientId, String keyId, String keyPath, String authUrl) { + String teamId, String clientId, String keyId, String authKey, String authUrl) { JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.ES256).keyID(keyId).build(); JWTClaimsSet claimsSet = new JWTClaimsSet(); @@ -44,7 +37,7 @@ public static String createClientSecret( SignedJWT jwt = new SignedJWT(header, claimsSet); - PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(readPrivateKey(keyPath)); + PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(readPrivateKey(authKey)); try { KeyFactory kf = KeyFactory.getInstance("EC"); ECPrivateKey ecPrivateKey = (ECPrivateKey) kf.generatePrivate(spec); @@ -64,12 +57,10 @@ public static String createClientSecret( * * @return Private Key */ - private static byte[] readPrivateKey(String keyPath) { - - Resource resource = new ClassPathResource(keyPath); + private static byte[] readPrivateKey(String authKey) { byte[] content = null; - - try (InputStream keyInputStream = resource.getInputStream(); + byte[] byteAuthKey = authKey.replace("((()))", "\n").getBytes(); + try (InputStream keyInputStream = new ByteArrayInputStream(byteAuthKey); InputStreamReader keyReader = new InputStreamReader(keyInputStream); PemReader pemReader = new PemReader(keyReader)) { PemObject pemObject = pemReader.readPemObject(); From f256d4521ec091185fefe7f2598a88080cf20df5 Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Fri, 28 Jul 2023 12:53:51 +0900 Subject: [PATCH 07/34] =?UTF-8?q?[feat]=20=EC=9C=A0=EC=A0=80=20=ED=9A=8C?= =?UTF-8?q?=EC=9B=90=EA=B0=80=EC=9E=85=EC=8B=9C=20=EC=9C=A0=EC=A0=80=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EA=B0=80=EC=A0=B8=EC=98=A4=EA=B8=B0=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20(#70)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [feat] 회원가입시 유저 정보 가져오기 기능 구현 #68 * [chore] spotless 적용 #68 * [fix] email 가져오기 로직 변경 #68 * [refac] transaction 범위 수정 #68 --- .../api/auth/controller/OauthController.java | 3 +- .../api/auth/model/dto/KakaoUserInfoDto.java | 26 ---------- .../api/auth/model/dto/OauthUserInfoDto.java | 30 +++++++++++ .../model/dto/request/RegisterRequest.java | 6 +++ .../dto/response/OauthUserInfoResponse.java | 32 ------------ .../api/auth/service/LogOutUserUseCase.java | 2 + .../api/auth/service/OauthLoginUseCase.java | 4 ++ .../auth/service/OauthRegisterUseCase.java | 50 ++++++++++++++++--- .../api/auth/service/TokenRefreshUseCase.java | 2 + .../auth/service/helper/KakaoOauthHelper.java | 10 ++++ .../api/auth/service/helper/OauthHelper.java | 12 +++++ .../api/common/util/StringParamUtil.java | 1 + .../domain/domains/user/domain/User.java | 8 +++ .../user/service/UserDomainService.java | 4 +- .../oauth/kakao/client/KakaoInfoClient.java | 5 ++ .../kakao/dto/KakaoInformationResponse.java | 32 ++---------- 16 files changed, 132 insertions(+), 95 deletions(-) delete mode 100644 Api/src/main/java/allchive/server/api/auth/model/dto/KakaoUserInfoDto.java create mode 100644 Api/src/main/java/allchive/server/api/auth/model/dto/OauthUserInfoDto.java delete mode 100644 Api/src/main/java/allchive/server/api/auth/model/dto/response/OauthUserInfoResponse.java diff --git a/Api/src/main/java/allchive/server/api/auth/controller/OauthController.java b/Api/src/main/java/allchive/server/api/auth/controller/OauthController.java index dfc246a5..45232199 100644 --- a/Api/src/main/java/allchive/server/api/auth/controller/OauthController.java +++ b/Api/src/main/java/allchive/server/api/auth/controller/OauthController.java @@ -82,7 +82,8 @@ public OauthSignInResponse oauthUserIdTokenLogin( public OauthRegisterResponse oauthUserRegister( @PathVariable("provider") OauthProvider provider, @RequestParam("idToken") String idToken, + @RequestParam("oauthAccessToken") String accessToken, @RequestBody RegisterRequest registerRequest) { - return oauthRegisterUseCase.execute(provider, idToken, registerRequest); + return oauthRegisterUseCase.execute(provider, idToken, accessToken, registerRequest); } } diff --git a/Api/src/main/java/allchive/server/api/auth/model/dto/KakaoUserInfoDto.java b/Api/src/main/java/allchive/server/api/auth/model/dto/KakaoUserInfoDto.java deleted file mode 100644 index a6be5cc0..00000000 --- a/Api/src/main/java/allchive/server/api/auth/model/dto/KakaoUserInfoDto.java +++ /dev/null @@ -1,26 +0,0 @@ -package allchive.server.api.auth.model.dto; - - -import allchive.server.domain.domains.user.domain.enums.OauthInfo; -import allchive.server.domain.domains.user.domain.enums.OauthProvider; -import lombok.Builder; -import lombok.Getter; - -@Getter -@Builder -public class KakaoUserInfoDto { - - // oauth인증한 사용자 고유 아이디 - private final String oauthId; - - private final String email; - private final String phoneNumber; - private final String profileImage; - private final String name; - private final OauthProvider oauthProvider; - - public OauthInfo toOauthInfo() { - return OauthInfo.of(oauthProvider, oauthId); - } -} -; diff --git a/Api/src/main/java/allchive/server/api/auth/model/dto/OauthUserInfoDto.java b/Api/src/main/java/allchive/server/api/auth/model/dto/OauthUserInfoDto.java new file mode 100644 index 00000000..e324ba55 --- /dev/null +++ b/Api/src/main/java/allchive/server/api/auth/model/dto/OauthUserInfoDto.java @@ -0,0 +1,30 @@ +package allchive.server.api.auth.model.dto; + + +import allchive.server.domain.domains.user.domain.enums.OauthProvider; +import allchive.server.infrastructure.oauth.kakao.dto.KakaoInformationResponse; +import lombok.Builder; +import lombok.Getter; + +@Getter +public class OauthUserInfoDto { + private String email; + private String name; + private OauthProvider oauthProvider; + + @Builder + private OauthUserInfoDto(String email, String name, OauthProvider oauthProvider) { + this.email = email; + this.name = name; + this.oauthProvider = oauthProvider; + } + + public static OauthUserInfoDto fromKakao(KakaoInformationResponse response) { + return OauthUserInfoDto.builder() + .email(response.getEmail()) + .name(response.getNickName()) + .oauthProvider(OauthProvider.KAKAO) + .build(); + } +} +; diff --git a/Api/src/main/java/allchive/server/api/auth/model/dto/request/RegisterRequest.java b/Api/src/main/java/allchive/server/api/auth/model/dto/request/RegisterRequest.java index fe3d10f2..8abf6ebb 100644 --- a/Api/src/main/java/allchive/server/api/auth/model/dto/request/RegisterRequest.java +++ b/Api/src/main/java/allchive/server/api/auth/model/dto/request/RegisterRequest.java @@ -26,4 +26,10 @@ public class RegisterRequest { @ArraySchema(schema = @Schema(description = "관심 주제", defaultValue = "FOOD")) private List<@ValidEnum(target = Category.class) Category> categories; + + @Schema(defaultValue = "이름", description = "이름, 애플 회원가입용") + private String name; + + @Schema(defaultValue = "이메일", description = "이메일, 애플 회원가입용") + private String email; } diff --git a/Api/src/main/java/allchive/server/api/auth/model/dto/response/OauthUserInfoResponse.java b/Api/src/main/java/allchive/server/api/auth/model/dto/response/OauthUserInfoResponse.java deleted file mode 100644 index e0c97af3..00000000 --- a/Api/src/main/java/allchive/server/api/auth/model/dto/response/OauthUserInfoResponse.java +++ /dev/null @@ -1,32 +0,0 @@ -package allchive.server.api.auth.model.dto.response; - - -import allchive.server.api.auth.model.dto.KakaoUserInfoDto; -import lombok.Builder; -import lombok.Getter; - -@Getter -public class OauthUserInfoResponse { - private final String email; - private final String phoneNumber; - private final String profileImage; - private final String name; - - @Builder - public OauthUserInfoResponse( - String email, String phoneNumber, String profileImage, String name) { - this.email = email; - this.phoneNumber = phoneNumber; - this.profileImage = profileImage; - this.name = name; - } - - public static OauthUserInfoResponse from(KakaoUserInfoDto kakaoUserInfoDto) { - return OauthUserInfoResponse.builder() - .email(kakaoUserInfoDto.getEmail()) - .phoneNumber(kakaoUserInfoDto.getPhoneNumber()) - .profileImage(kakaoUserInfoDto.getProfileImage()) - .name(kakaoUserInfoDto.getName()) - .build(); - } -} diff --git a/Api/src/main/java/allchive/server/api/auth/service/LogOutUserUseCase.java b/Api/src/main/java/allchive/server/api/auth/service/LogOutUserUseCase.java index ec842de9..5163c761 100644 --- a/Api/src/main/java/allchive/server/api/auth/service/LogOutUserUseCase.java +++ b/Api/src/main/java/allchive/server/api/auth/service/LogOutUserUseCase.java @@ -5,12 +5,14 @@ import allchive.server.core.annotation.UseCase; import allchive.server.domain.domains.user.adaptor.RefreshTokenAdaptor; import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; @UseCase @RequiredArgsConstructor public class LogOutUserUseCase { private final RefreshTokenAdaptor refreshTokenAdaptor; + @Transactional public void execute() { Long userId = SecurityUtil.getCurrentUserId(); refreshTokenAdaptor.deleteTokenByUserId(userId); diff --git a/Api/src/main/java/allchive/server/api/auth/service/OauthLoginUseCase.java b/Api/src/main/java/allchive/server/api/auth/service/OauthLoginUseCase.java index 2886b644..9ee94356 100644 --- a/Api/src/main/java/allchive/server/api/auth/service/OauthLoginUseCase.java +++ b/Api/src/main/java/allchive/server/api/auth/service/OauthLoginUseCase.java @@ -11,6 +11,7 @@ import allchive.server.domain.domains.user.domain.enums.OauthProvider; import allchive.server.domain.domains.user.service.UserDomainService; import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; @UseCase @RequiredArgsConstructor @@ -19,16 +20,19 @@ public class OauthLoginUseCase { private final UserDomainService userDomainService; private final TokenGenerateHelper tokenGenerateHelper; + @Transactional public OauthSignInResponse loginWithCode(OauthProvider provider, String code, String referer) { final OauthTokenResponse oauthTokenResponse = oauthHelper.getCredential(provider, code, referer); return processLoginWithIdToken(provider, oauthTokenResponse.getIdToken()); } + @Transactional public OauthSignInResponse loginWithIdToken(OauthProvider provider, String idToken) { return processLoginWithIdToken(provider, idToken); } + @Transactional public OauthSignInResponse devLogin(OauthProvider provider, String code) { final OauthTokenResponse oauthTokenResponse = oauthHelper.getCredentialDev(provider, code); return processLoginWithIdToken(provider, oauthTokenResponse.getIdToken()); diff --git a/Api/src/main/java/allchive/server/api/auth/service/OauthRegisterUseCase.java b/Api/src/main/java/allchive/server/api/auth/service/OauthRegisterUseCase.java index 377dc16d..c06db03e 100644 --- a/Api/src/main/java/allchive/server/api/auth/service/OauthRegisterUseCase.java +++ b/Api/src/main/java/allchive/server/api/auth/service/OauthRegisterUseCase.java @@ -1,6 +1,7 @@ package allchive.server.api.auth.service; +import allchive.server.api.auth.model.dto.OauthUserInfoDto; import allchive.server.api.auth.model.dto.request.RegisterRequest; import allchive.server.api.auth.model.dto.response.OauthRegisterResponse; import allchive.server.api.auth.service.helper.OauthHelper; @@ -12,6 +13,7 @@ import allchive.server.domain.domains.user.domain.enums.OauthProvider; import allchive.server.domain.domains.user.service.UserDomainService; import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; @UseCase @RequiredArgsConstructor @@ -20,15 +22,49 @@ public class OauthRegisterUseCase { private final UserDomainService userDomainService; private final TokenGenerateHelper tokenGenerateHelper; + @Transactional public OauthRegisterResponse execute( - OauthProvider provider, String idToken, RegisterRequest registerRequest) { + OauthProvider provider, + String idToken, + String oauthAccessToken, + RegisterRequest request) { final OauthInfo oauthInfo = oauthHelper.getOauthInfo(provider, idToken); - final User user = - userDomainService.registerUser( - registerRequest.getNickname(), - UrlUtil.convertUrlToKey(registerRequest.getProfileImgUrl()), - registerRequest.getCategories(), - oauthInfo); + final OauthUserInfoDto oauthUserInfoDto = getUserInfo(provider, oauthAccessToken); + final User user = registerUser(provider, oauthInfo, oauthUserInfoDto, request); return OauthRegisterResponse.from(tokenGenerateHelper.execute(user)); } + + private User registerUser( + OauthProvider provider, + OauthInfo oauthInfo, + OauthUserInfoDto oauthUserInfoDto, + RegisterRequest request) { + switch (provider) { + case APPLE: + return userDomainService.registerUser( + request.getName(), + request.getEmail(), + request.getNickname(), + UrlUtil.convertUrlToKey(request.getProfileImgUrl()), + request.getCategories(), + oauthInfo); + default: + return userDomainService.registerUser( + oauthUserInfoDto.getName(), + oauthUserInfoDto.getEmail(), + request.getNickname(), + UrlUtil.convertUrlToKey(request.getProfileImgUrl()), + request.getCategories(), + oauthInfo); + } + } + + private OauthUserInfoDto getUserInfo(OauthProvider provider, String oauthAccessToken) { + switch (provider) { + case APPLE: + return null; + default: + return oauthHelper.getUserInfo(provider, oauthAccessToken); + } + } } diff --git a/Api/src/main/java/allchive/server/api/auth/service/TokenRefreshUseCase.java b/Api/src/main/java/allchive/server/api/auth/service/TokenRefreshUseCase.java index 740c8a5c..0bc1cd7a 100644 --- a/Api/src/main/java/allchive/server/api/auth/service/TokenRefreshUseCase.java +++ b/Api/src/main/java/allchive/server/api/auth/service/TokenRefreshUseCase.java @@ -10,6 +10,7 @@ import allchive.server.domain.domains.user.domain.RefreshTokenEntity; import allchive.server.domain.domains.user.domain.User; import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; @UseCase @RequiredArgsConstructor @@ -19,6 +20,7 @@ public class TokenRefreshUseCase { private final UserAdaptor userAdaptor; private final TokenGenerateHelper tokenGenerateHelper; + @Transactional public OauthRegisterResponse execute(String refreshToken) { RefreshTokenEntity oldToken = refreshTokenAdaptor.findTokenByRefreshToken(refreshToken); Long userId = jwtTokenProvider.parseRefreshToken(oldToken.getRefreshToken()); diff --git a/Api/src/main/java/allchive/server/api/auth/service/helper/KakaoOauthHelper.java b/Api/src/main/java/allchive/server/api/auth/service/helper/KakaoOauthHelper.java index 3615e805..c25e4752 100644 --- a/Api/src/main/java/allchive/server/api/auth/service/helper/KakaoOauthHelper.java +++ b/Api/src/main/java/allchive/server/api/auth/service/helper/KakaoOauthHelper.java @@ -1,7 +1,9 @@ package allchive.server.api.auth.service.helper; +import static allchive.server.core.consts.AllchiveConst.BEARER; import static allchive.server.core.consts.AllchiveConst.KAKAO_OAUTH_QUERY_STRING; +import allchive.server.api.auth.model.dto.OauthUserInfoDto; import allchive.server.core.annotation.Helper; import allchive.server.core.dto.OIDCDecodePayload; import allchive.server.core.properties.KakaoOAuthProperties; @@ -9,6 +11,7 @@ import allchive.server.domain.domains.user.domain.enums.OauthProvider; import allchive.server.infrastructure.oauth.kakao.client.KakaoInfoClient; import allchive.server.infrastructure.oauth.kakao.client.KakaoOauthClient; +import allchive.server.infrastructure.oauth.kakao.dto.KakaoInformationResponse; import allchive.server.infrastructure.oauth.kakao.dto.KakaoTokenResponse; import allchive.server.infrastructure.oauth.kakao.dto.KakaoUnlinkTarget; import allchive.server.infrastructure.oauth.kakao.dto.OIDCPublicKeysResponse; @@ -86,4 +89,11 @@ public void withdrawKakaoOauthUser(String oid) { unlinkKaKaoTarget.getAud()); kakaoInfoClient.unlinkUser(header, unlinkKaKaoTarget); } + + /** 유저 정보 가져오기 * */ + public OauthUserInfoDto getUserInfo(String oauthAccessToken) { + KakaoInformationResponse response = + kakaoInfoClient.kakaoUserInfo(BEARER + oauthAccessToken); + return OauthUserInfoDto.fromKakao(response); + } } diff --git a/Api/src/main/java/allchive/server/api/auth/service/helper/OauthHelper.java b/Api/src/main/java/allchive/server/api/auth/service/helper/OauthHelper.java index b76acbbb..b305be8c 100644 --- a/Api/src/main/java/allchive/server/api/auth/service/helper/OauthHelper.java +++ b/Api/src/main/java/allchive/server/api/auth/service/helper/OauthHelper.java @@ -1,6 +1,7 @@ package allchive.server.api.auth.service.helper; +import allchive.server.api.auth.model.dto.OauthUserInfoDto; import allchive.server.api.auth.model.dto.response.OauthLoginLinkResponse; import allchive.server.api.auth.model.dto.response.OauthTokenResponse; import allchive.server.core.annotation.Helper; @@ -81,6 +82,17 @@ public void withdraw(OauthProvider provider, String oid, String appleAccessToken break; case APPLE: appleOauthHelper.withdrawAppleOauthUser(appleAccessToken); + break; + default: + throw InvalidOauthProviderException.EXCEPTION; + } + } + + /** 유저 정보 가져오기 * */ + public OauthUserInfoDto getUserInfo(OauthProvider provider, String oauthAccessToken) { + switch (provider) { + case KAKAO: + return kakaoOauthHelper.getUserInfo(oauthAccessToken); default: throw InvalidOauthProviderException.EXCEPTION; } diff --git a/Api/src/main/java/allchive/server/api/common/util/StringParamUtil.java b/Api/src/main/java/allchive/server/api/common/util/StringParamUtil.java index 0cc94558..f4203056 100644 --- a/Api/src/main/java/allchive/server/api/common/util/StringParamUtil.java +++ b/Api/src/main/java/allchive/server/api/common/util/StringParamUtil.java @@ -1,5 +1,6 @@ package allchive.server.api.common.util; + import allchive.server.core.error.exception.EmptyParamValueException; import org.springframework.stereotype.Component; diff --git a/Domain/src/main/java/allchive/server/domain/domains/user/domain/User.java b/Domain/src/main/java/allchive/server/domain/domains/user/domain/User.java index c5a87470..16aa572e 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/user/domain/User.java +++ b/Domain/src/main/java/allchive/server/domain/domains/user/domain/User.java @@ -51,10 +51,14 @@ public class User extends BaseTimeEntity { @Builder private User( + String name, + String email, String nickname, String profileImgUrl, List categoryList, OauthInfo oauthInfo) { + this.name = name; + this.email = email; this.nickname = nickname; this.profileImgUrl = profileImgUrl; this.categories = categoryList; @@ -63,11 +67,15 @@ private User( } public static User of( + String name, + String email, String nickname, String profileImgUrl, List categoryList, OauthInfo oauthInfo) { return User.builder() + .name(name) + .email(email) .nickname(nickname) .profileImgUrl(profileImgUrl) .categoryList(categoryList) diff --git a/Domain/src/main/java/allchive/server/domain/domains/user/service/UserDomainService.java b/Domain/src/main/java/allchive/server/domain/domains/user/service/UserDomainService.java index 5c49df2b..0b14420e 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/user/service/UserDomainService.java +++ b/Domain/src/main/java/allchive/server/domain/domains/user/service/UserDomainService.java @@ -24,12 +24,14 @@ public Boolean checkUserCanLogin(OauthInfo oauthInfo) { @Transactional public User registerUser( + String name, + String email, String nickname, String profileImgUrl, List categoryList, OauthInfo oauthInfo) { userValidator.validUserCanRegister(oauthInfo); - final User newUser = User.of(nickname, profileImgUrl, categoryList, oauthInfo); + final User newUser = User.of(name, email, nickname, profileImgUrl, categoryList, oauthInfo); userAdaptor.save(newUser); return newUser; } diff --git a/Infrastructure/src/main/java/allchive/server/infrastructure/oauth/kakao/client/KakaoInfoClient.java b/Infrastructure/src/main/java/allchive/server/infrastructure/oauth/kakao/client/KakaoInfoClient.java index 200cb760..9cf5b46d 100644 --- a/Infrastructure/src/main/java/allchive/server/infrastructure/oauth/kakao/client/KakaoInfoClient.java +++ b/Infrastructure/src/main/java/allchive/server/infrastructure/oauth/kakao/client/KakaoInfoClient.java @@ -2,9 +2,11 @@ import allchive.server.infrastructure.oauth.kakao.config.KakaoInfoConfig; +import allchive.server.infrastructure.oauth.kakao.dto.KakaoInformationResponse; import allchive.server.infrastructure.oauth.kakao.dto.KakaoUnlinkTarget; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestHeader; @@ -16,4 +18,7 @@ public interface KakaoInfoClient { @PostMapping(path = "/v1/user/unlink", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) void unlinkUser( @RequestHeader("Authorization") String adminKey, KakaoUnlinkTarget unlinkKaKaoTarget); + + @GetMapping("/v2/user/me") + KakaoInformationResponse kakaoUserInfo(@RequestHeader("Authorization") String accessToken); } diff --git a/Infrastructure/src/main/java/allchive/server/infrastructure/oauth/kakao/dto/KakaoInformationResponse.java b/Infrastructure/src/main/java/allchive/server/infrastructure/oauth/kakao/dto/KakaoInformationResponse.java index ff4a9e9b..1e5465db 100644 --- a/Infrastructure/src/main/java/allchive/server/infrastructure/oauth/kakao/dto/KakaoInformationResponse.java +++ b/Infrastructure/src/main/java/allchive/server/infrastructure/oauth/kakao/dto/KakaoInformationResponse.java @@ -13,7 +13,6 @@ public class KakaoInformationResponse { private Properties properties; private String id; - private KakaoAccount kakaoAccount; @Getter @@ -27,41 +26,18 @@ public static class Properties { @NoArgsConstructor @JsonNaming(SnakeCaseStrategy.class) public static class KakaoAccount { - - private Profile profile; private String email; - private String phoneNumber; - private String name; - - @Getter - @NoArgsConstructor - @JsonNaming(SnakeCaseStrategy.class) - public static class Profile { - private String profileImageUrl; - } - - public String getProfileImageUrl() { - return profile.getProfileImageUrl(); - } } public String getId() { return id; } - public String getEmail() { - return kakaoAccount.getEmail(); - } - - public String getPhoneNumber() { - return kakaoAccount.getPhoneNumber(); - } - - public String getName() { - return kakaoAccount.getName() != null ? kakaoAccount.getName() : properties.getNickname(); + public String getNickName() { + return properties.getNickname(); } - public String getProfileUrl() { - return kakaoAccount.getProfileImageUrl(); + public String getEmail() { + return kakaoAccount.getEmail(); } } From c0fc12e0f3de3a6a58c3bd7f710513bd72008588 Mon Sep 17 00:00:00 2001 From: wjdtkdgns Date: Mon, 31 Jul 2023 21:23:19 +0900 Subject: [PATCH 08/34] =?UTF-8?q?[fix]=20security=20=ED=97=88=EC=9A=A9=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../allchive/server/api/config/security/SecurityConfig.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Api/src/main/java/allchive/server/api/config/security/SecurityConfig.java b/Api/src/main/java/allchive/server/api/config/security/SecurityConfig.java index cfd71a98..236519ea 100644 --- a/Api/src/main/java/allchive/server/api/config/security/SecurityConfig.java +++ b/Api/src/main/java/allchive/server/api/config/security/SecurityConfig.java @@ -39,6 +39,8 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .permitAll() .mvcMatchers("/auth/token/refresh") .permitAll() + .mvcMatchers("/user/image") + .permitAll() .mvcMatchers("/**/health/**") .permitAll() .mvcMatchers("/example/**") From 7da69d30f8c038f7ccd43078313e4f93209117cc Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Mon, 31 Jul 2023 23:23:20 +0900 Subject: [PATCH 09/34] =?UTF-8?q?[refac]=20recycle=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81=20=EB=B0=8F=20s3=20object=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EC=B6=94=EA=B0=80=20(#73)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [refac] recycle 복구, 가져오기 validation 정리 및 함수 네이밍 변경 #71 * [refac] recycle 삭제 validation 코드 정리, report도 삭제 #71 * [feat] s3 객체 삭제 로직 추가 #72 * [chore] spotless 적용 --- .../api/image/controller/ImageController.java | 2 +- .../service/ClearDeletedObjectUseCase.java | 45 ++++++++++++++---- .../service/ClearOldDeletedObjectUseCase.java | 47 ++++++++++++++----- .../service/GetDeletedObjectUseCase.java | 20 +++++--- .../service/RestoreDeletedObjectUseCase.java | 12 +++-- .../server/core/error/GlobalErrorCode.java | 3 ++ .../exception/S3ObjectNotFoundException.java | 14 ++++++ .../service/ArchivingDomainService.java | 2 +- .../content/service/ContentDomainService.java | 2 +- .../recycle/adaptor/RecycleAdaptor.java | 4 +- .../repository/RecycleCustomRepository.java | 2 +- .../RecycleCustomRepositoryImpl.java | 2 +- .../recycle/service/RecycleDomainService.java | 4 +- .../recycle/validator/RecycleValidator.java | 2 +- .../domains/report/adaptor/ReportAdaptor.java | 6 +++ .../repository/ReportCustomRepository.java | 5 ++ .../ReportCustomRepositoryImpl.java | 12 +++++ .../report/service/ReportDomainService.java | 6 +++ .../s3/service/S3DeleteObjectService.java | 32 +++++++++++++ .../{ => service}/S3PresignedUrlService.java | 4 +- 20 files changed, 182 insertions(+), 44 deletions(-) create mode 100644 Core/src/main/java/allchive/server/core/error/exception/S3ObjectNotFoundException.java create mode 100644 Infrastructure/src/main/java/allchive/server/infrastructure/s3/service/S3DeleteObjectService.java rename Infrastructure/src/main/java/allchive/server/infrastructure/s3/{ => service}/S3PresignedUrlService.java (93%) diff --git a/Api/src/main/java/allchive/server/api/image/controller/ImageController.java b/Api/src/main/java/allchive/server/api/image/controller/ImageController.java index 8077a4d4..d643c3e4 100644 --- a/Api/src/main/java/allchive/server/api/image/controller/ImageController.java +++ b/Api/src/main/java/allchive/server/api/image/controller/ImageController.java @@ -4,7 +4,7 @@ import allchive.server.api.config.security.SecurityUtil; import allchive.server.api.image.model.dto.response.ImageUrlResponse; import allchive.server.infrastructure.s3.PresignedType; -import allchive.server.infrastructure.s3.S3PresignedUrlService; +import allchive.server.infrastructure.s3.service.S3PresignedUrlService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; diff --git a/Api/src/main/java/allchive/server/api/recycle/service/ClearDeletedObjectUseCase.java b/Api/src/main/java/allchive/server/api/recycle/service/ClearDeletedObjectUseCase.java index 453ecc90..85097dbe 100644 --- a/Api/src/main/java/allchive/server/api/recycle/service/ClearDeletedObjectUseCase.java +++ b/Api/src/main/java/allchive/server/api/recycle/service/ClearDeletedObjectUseCase.java @@ -8,12 +8,15 @@ import allchive.server.domain.domains.archiving.validator.ArchivingValidator; import allchive.server.domain.domains.content.adaptor.ContentAdaptor; import allchive.server.domain.domains.content.domain.Content; +import allchive.server.domain.domains.content.domain.enums.ContentType; import allchive.server.domain.domains.content.service.ContentDomainService; import allchive.server.domain.domains.content.service.ContentTagGroupDomainService; import allchive.server.domain.domains.content.validator.ContentValidator; import allchive.server.domain.domains.recycle.service.RecycleDomainService; import allchive.server.domain.domains.recycle.validator.RecycleValidator; +import allchive.server.domain.domains.report.service.ReportDomainService; import allchive.server.domain.domains.user.service.ScrapDomainService; +import allchive.server.infrastructure.s3.service.S3DeleteObjectService; import java.util.ArrayList; import java.util.List; import lombok.RequiredArgsConstructor; @@ -31,15 +34,36 @@ public class ClearDeletedObjectUseCase { private final ArchivingDomainService archivingDomainService; private final ContentDomainService contentDomainService; private final RecycleDomainService recycleDomainService; + private final ReportDomainService reportDomainService; + private final S3DeleteObjectService s3DeleteObjectService; - // TODO: report 지우기 @Transactional public void execute(ClearDeletedObjectRequest request) { Long userId = SecurityUtil.getCurrentUserId(); - recycleValidator.validateExist(request.getArchivingIds(), request.getContentIds(), userId); - archivingValidator.verifyUserInIdList(userId, request.getArchivingIds()); - contentValidator.verifyUserInIdList(userId, request.getContentIds()); + validateExecution(userId, request); List contents = contentAdaptor.findAllByArchivingIds(request.getArchivingIds()); + List contentsId = getContentsId(contents, request); + scrapDomainService.deleteAllByArchivingIdIn(request.getArchivingIds()); + contentTagGroupDomainService.deleteByContentIn(contents); + contentDomainService.deleteAllById(contentsId); + archivingDomainService.deleteAllById(request.getArchivingIds()); + recycleDomainService.deleteAllByUserIdAndArchivingIdInOrUserIdAndContentIdIn( + request.getArchivingIds(), request.getContentIds(), userId); + reportDomainService.deleteAllByArchivingIdInOrContentIdIn( + request.getArchivingIds(), request.getContentIds()); + deleteS3Object(contents); + } + + private void deleteS3Object(List contents) { + List imageKeys = + contents.stream() + .filter(content -> content.getContentType().equals(ContentType.IMAGE)) + .map(Content::getImageUrl) + .toList(); + s3DeleteObjectService.deleteS3Object(imageKeys); + } + + private List getContentsId(List contents, ClearDeletedObjectRequest request) { List contentsId = contents.stream().map(Content::getId).toList(); if (!request.getContentIds().isEmpty()) { if (contentsId.isEmpty()) { @@ -47,11 +71,12 @@ public void execute(ClearDeletedObjectRequest request) { } contentsId.addAll(request.getContentIds()); } - scrapDomainService.deleteAllByArchivingIdIn(request.getArchivingIds()); - contentTagGroupDomainService.deleteByContentIn(contents); - contentDomainService.deleteAllById(contentsId); - archivingDomainService.deleteAllById(request.getArchivingIds()); - recycleDomainService.deleteAllByUserIdAndArchivingIdOrUserIdAndContentId( - request.getArchivingIds(), request.getContentIds(), userId); + return contentsId; + } + + private void validateExecution(Long userId, ClearDeletedObjectRequest request) { + recycleValidator.validateExist(request.getArchivingIds(), request.getContentIds(), userId); + archivingValidator.verifyUserInIdList(userId, request.getArchivingIds()); + contentValidator.verifyUserInIdList(userId, request.getContentIds()); } } diff --git a/Api/src/main/java/allchive/server/api/recycle/service/ClearOldDeletedObjectUseCase.java b/Api/src/main/java/allchive/server/api/recycle/service/ClearOldDeletedObjectUseCase.java index 4e9ffea5..c673c9aa 100644 --- a/Api/src/main/java/allchive/server/api/recycle/service/ClearOldDeletedObjectUseCase.java +++ b/Api/src/main/java/allchive/server/api/recycle/service/ClearOldDeletedObjectUseCase.java @@ -5,13 +5,16 @@ import allchive.server.domain.domains.archiving.service.ArchivingDomainService; import allchive.server.domain.domains.content.adaptor.ContentAdaptor; import allchive.server.domain.domains.content.domain.Content; +import allchive.server.domain.domains.content.domain.enums.ContentType; import allchive.server.domain.domains.content.service.ContentDomainService; import allchive.server.domain.domains.content.service.ContentTagGroupDomainService; import allchive.server.domain.domains.recycle.adaptor.RecycleAdaptor; import allchive.server.domain.domains.recycle.domain.Recycle; import allchive.server.domain.domains.recycle.domain.enums.RecycleType; import allchive.server.domain.domains.recycle.service.RecycleDomainService; +import allchive.server.domain.domains.report.service.ReportDomainService; import allchive.server.domain.domains.user.service.ScrapDomainService; +import allchive.server.infrastructure.s3.service.S3DeleteObjectService; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -31,21 +34,46 @@ public class ClearOldDeletedObjectUseCase { private final ArchivingDomainService archivingDomainService; private final ContentDomainService contentDomainService; private final RecycleDomainService recycleDomainService; + private final ReportDomainService reportDomainService; + private final S3DeleteObjectService s3DeleteObjectService; /** 삭제 후 30일 지난 항목 제거 스케쥴러 매일 02:30에 수행 */ - // TODO: s3 asset 삭제 @Scheduled(cron = "0 30 2 * * *") @Transactional public void executeSchedule() { log.info("scheduler on"); LocalDateTime deleteStandard = LocalDateTime.now().minusDays(30); List recycles = recycleAdaptor.findAllByDeletedAtBefore(deleteStandard); + List archivingIds = getArchivingIds(recycles); + List contents = contentAdaptor.findAllByArchivingIds(archivingIds); + List contentIds = getContentsId(recycles, contents); + scrapDomainService.deleteAllByArchivingIdIn(archivingIds); + contentTagGroupDomainService.deleteByContentIn(contents); + contentDomainService.deleteAllById(contentIds); + archivingDomainService.deleteAllById(archivingIds); + recycleDomainService.deleteAll(recycles); + reportDomainService.deleteAllByArchivingIdInOrContentIdIn(archivingIds, contentIds); + deleteS3Object(contents); + log.info("scheduler off"); + } - List archivingIds = - recycles.stream() - .filter(recycle -> recycle.getRecycleType().equals(RecycleType.ARCHIVING)) - .map(Recycle::getArchivingId) + private void deleteS3Object(List contents) { + List imageKeys = + contents.stream() + .filter(content -> content.getContentType().equals(ContentType.IMAGE)) + .map(Content::getImageUrl) .toList(); + s3DeleteObjectService.deleteS3Object(imageKeys); + } + + private List getArchivingIds(List recycles) { + return recycles.stream() + .filter(recycle -> recycle.getRecycleType().equals(RecycleType.ARCHIVING)) + .map(Recycle::getArchivingId) + .toList(); + } + + private List getContentsId(List recycles, List contents) { List contentIds = recycles.stream() .filter(recycle -> recycle.getRecycleType().equals(RecycleType.CONTENT)) @@ -55,16 +83,9 @@ public void executeSchedule() { if (contentIds.isEmpty()) { contentIds = new ArrayList<>(); } - List contents = contentAdaptor.findAllByArchivingIds(archivingIds); for (Content content : contents) { contentIds.add(content.getId()); } - - scrapDomainService.deleteAllByArchivingIdIn(archivingIds); - contentTagGroupDomainService.deleteByContentIn(contents); - contentDomainService.deleteAllById(contentIds); - archivingDomainService.deleteAllById(archivingIds); - recycleDomainService.deleteAll(recycles); - log.info("scheduler off"); + return contentIds; } } diff --git a/Api/src/main/java/allchive/server/api/recycle/service/GetDeletedObjectUseCase.java b/Api/src/main/java/allchive/server/api/recycle/service/GetDeletedObjectUseCase.java index 733b5dff..f966f56f 100644 --- a/Api/src/main/java/allchive/server/api/recycle/service/GetDeletedObjectUseCase.java +++ b/Api/src/main/java/allchive/server/api/recycle/service/GetDeletedObjectUseCase.java @@ -31,21 +31,29 @@ public class GetDeletedObjectUseCase { public DeletedObjectResponse execute() { Long userId = SecurityUtil.getCurrentUserId(); List recycles = recycleAdaptor.findAllByUserId(userId); + List archivings = getArchivings(recycles); + List contents = getContents(recycles); + List contentTagGroups = + contentTagGroupAdaptor.queryContentTagGroupByContentIn(contents); + return recycleMapper.toDeletedObjectResponse( + archivings, userId, contents, contentTagGroups); + } + + private List getArchivings(List recycles) { List archivingIds = recycles.stream() .filter(recycle -> recycle.getRecycleType().equals(RecycleType.ARCHIVING)) .map(Recycle::getArchivingId) .toList(); + return archivingAdaptor.findAllByIdIn(archivingIds); + } + + private List getContents(List recycles) { List contentIds = recycles.stream() .filter(recycle -> recycle.getRecycleType().equals(RecycleType.CONTENT)) .map(Recycle::getContentId) .toList(); - List archivings = archivingAdaptor.findAllByIdIn(archivingIds); - List contents = contentAdaptor.findAllByIdIn(contentIds); - List contentTagGroups = - contentTagGroupAdaptor.queryContentTagGroupByContentIn(contents); - return recycleMapper.toDeletedObjectResponse( - archivings, userId, contents, contentTagGroups); + return contentAdaptor.findAllByIdIn(contentIds); } } diff --git a/Api/src/main/java/allchive/server/api/recycle/service/RestoreDeletedObjectUseCase.java b/Api/src/main/java/allchive/server/api/recycle/service/RestoreDeletedObjectUseCase.java index aa77aa15..8bbe8218 100644 --- a/Api/src/main/java/allchive/server/api/recycle/service/RestoreDeletedObjectUseCase.java +++ b/Api/src/main/java/allchive/server/api/recycle/service/RestoreDeletedObjectUseCase.java @@ -26,12 +26,16 @@ public class RestoreDeletedObjectUseCase { @Transactional public void execute(RestoreDeletedObjectRequest request) { Long userId = SecurityUtil.getCurrentUserId(); + validateExecution(request, userId); + archivingDomainService.restoreByIdIn(request.getArchivingIds()); + contentDomainService.restoreByIdIn(request.getContentIds()); + recycleDomainService.deleteAllByUserIdAndArchivingIdInOrUserIdAndContentIdIn( + request.getArchivingIds(), request.getContentIds(), userId); + } + + private void validateExecution(RestoreDeletedObjectRequest request, Long userId) { recycleValidator.validateExist(request.getArchivingIds(), request.getContentIds(), userId); archivingValidator.validateExistInIdList(request.getArchivingIds()); contentValidator.validateExistInIdList(request.getContentIds()); - archivingDomainService.restoreInIdList(request.getArchivingIds()); - contentDomainService.restoreInIdList(request.getContentIds()); - recycleDomainService.deleteAllByUserIdAndArchivingIdOrUserIdAndContentId( - request.getArchivingIds(), request.getContentIds(), userId); } } diff --git a/Core/src/main/java/allchive/server/core/error/GlobalErrorCode.java b/Core/src/main/java/allchive/server/core/error/GlobalErrorCode.java index 1ade62da..027c58ae 100644 --- a/Core/src/main/java/allchive/server/core/error/GlobalErrorCode.java +++ b/Core/src/main/java/allchive/server/core/error/GlobalErrorCode.java @@ -26,6 +26,9 @@ public enum GlobalErrorCode implements BaseErrorCode { EXPIRED_TOKEN(UNAUTHORIZED, "AUTH_401_3", "만료된 엑세스 토큰입니다"), EXPIRED_REFRESH_TOKEN(UNAUTHORIZED, "AUTH_403_1", "인증 시간이 만료되었습니다. 재 로그인 해주세요."), + /** s3 오류 */ + S3_OBJECT_NOT_FOUND(BAD_REQUEST, "S3_500_1", "s3 객체가 존재하지 않습니다."), + /** Feign Client 오류 */ OTHER_SERVER_BAD_REQUEST(BAD_REQUEST, "FEIGN_400_1", "Other server bad request"), OTHER_SERVER_UNAUTHORIZED(BAD_REQUEST, "FEIGN_400_2", "Other server unauthorized"), diff --git a/Core/src/main/java/allchive/server/core/error/exception/S3ObjectNotFoundException.java b/Core/src/main/java/allchive/server/core/error/exception/S3ObjectNotFoundException.java new file mode 100644 index 00000000..9dd31860 --- /dev/null +++ b/Core/src/main/java/allchive/server/core/error/exception/S3ObjectNotFoundException.java @@ -0,0 +1,14 @@ +package allchive.server.core.error.exception; + + +import allchive.server.core.error.BaseErrorException; +import allchive.server.core.error.GlobalErrorCode; + +public class S3ObjectNotFoundException extends BaseErrorException { + + public static final BaseErrorException EXCEPTION = new S3ObjectNotFoundException(); + + private S3ObjectNotFoundException() { + super(GlobalErrorCode.S3_OBJECT_NOT_FOUND); + } +} diff --git a/Domain/src/main/java/allchive/server/domain/domains/archiving/service/ArchivingDomainService.java b/Domain/src/main/java/allchive/server/domain/domains/archiving/service/ArchivingDomainService.java index f45bea0b..e55eaf9e 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/archiving/service/ArchivingDomainService.java +++ b/Domain/src/main/java/allchive/server/domain/domains/archiving/service/ArchivingDomainService.java @@ -50,7 +50,7 @@ public void softDeleteById(Long archivingId) { archivingAdaptor.save(archiving); } - public void restoreInIdList(List archivingIds) { + public void restoreByIdIn(List archivingIds) { List archivings = archivingAdaptor.findAllByIdIn(archivingIds); archivings.forEach(Archiving::restore); archivingAdaptor.saveAll(archivings); diff --git a/Domain/src/main/java/allchive/server/domain/domains/content/service/ContentDomainService.java b/Domain/src/main/java/allchive/server/domain/domains/content/service/ContentDomainService.java index 47c902ed..b8e639ab 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/content/service/ContentDomainService.java +++ b/Domain/src/main/java/allchive/server/domain/domains/content/service/ContentDomainService.java @@ -23,7 +23,7 @@ public void softDeleteById(Long contentId) { save(content); } - public void restoreInIdList(List contentIds) { + public void restoreByIdIn(List contentIds) { List contentList = contentAdaptor.findAllByIdIn(contentIds); contentList.forEach(Content::restore); contentAdaptor.saveAll(contentList); diff --git a/Domain/src/main/java/allchive/server/domain/domains/recycle/adaptor/RecycleAdaptor.java b/Domain/src/main/java/allchive/server/domain/domains/recycle/adaptor/RecycleAdaptor.java index b2055e21..3a1a585a 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/recycle/adaptor/RecycleAdaptor.java +++ b/Domain/src/main/java/allchive/server/domain/domains/recycle/adaptor/RecycleAdaptor.java @@ -17,9 +17,9 @@ public void save(Recycle recycle) { recycleRepository.save(recycle); } - public List queryRecycleByUserIdInArchivingIdListAndContentIdList( + public List queryRecycleByUserIdAndArchivingIdInOrUserIdAndContentIdIn( List archivingIds, List contentIds, Long userId) { - return recycleRepository.queryRecycleByUserIdInArchivingIdListAndContentIdList( + return recycleRepository.queryRecycleByUserIdAndArchivingIdInOrUserIdAndContentIdIn( archivingIds, contentIds, userId); } diff --git a/Domain/src/main/java/allchive/server/domain/domains/recycle/repository/RecycleCustomRepository.java b/Domain/src/main/java/allchive/server/domain/domains/recycle/repository/RecycleCustomRepository.java index 59d537b8..b52c9e50 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/recycle/repository/RecycleCustomRepository.java +++ b/Domain/src/main/java/allchive/server/domain/domains/recycle/repository/RecycleCustomRepository.java @@ -5,6 +5,6 @@ import java.util.List; public interface RecycleCustomRepository { - List queryRecycleByUserIdInArchivingIdListAndContentIdList( + List queryRecycleByUserIdAndArchivingIdInOrUserIdAndContentIdIn( List archivingIds, List contentIds, Long userId); } diff --git a/Domain/src/main/java/allchive/server/domain/domains/recycle/repository/RecycleCustomRepositoryImpl.java b/Domain/src/main/java/allchive/server/domain/domains/recycle/repository/RecycleCustomRepositoryImpl.java index 682ce446..4c6a0cff 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/recycle/repository/RecycleCustomRepositoryImpl.java +++ b/Domain/src/main/java/allchive/server/domain/domains/recycle/repository/RecycleCustomRepositoryImpl.java @@ -15,7 +15,7 @@ public class RecycleCustomRepositoryImpl implements RecycleCustomRepository { private final JPAQueryFactory queryFactory; @Override - public List queryRecycleByUserIdInArchivingIdListAndContentIdList( + public List queryRecycleByUserIdAndArchivingIdInOrUserIdAndContentIdIn( List archivingIds, List contentIds, Long userId) { return queryFactory .selectFrom(recycle) diff --git a/Domain/src/main/java/allchive/server/domain/domains/recycle/service/RecycleDomainService.java b/Domain/src/main/java/allchive/server/domain/domains/recycle/service/RecycleDomainService.java index 9763eae5..318089de 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/recycle/service/RecycleDomainService.java +++ b/Domain/src/main/java/allchive/server/domain/domains/recycle/service/RecycleDomainService.java @@ -16,10 +16,10 @@ public void save(Recycle recycle) { recycleAdaptor.save(recycle); } - public void deleteAllByUserIdAndArchivingIdOrUserIdAndContentId( + public void deleteAllByUserIdAndArchivingIdInOrUserIdAndContentIdIn( List archivingIds, List contentIds, Long userId) { List recycleList = - recycleAdaptor.queryRecycleByUserIdInArchivingIdListAndContentIdList( + recycleAdaptor.queryRecycleByUserIdAndArchivingIdInOrUserIdAndContentIdIn( archivingIds, contentIds, userId); recycleAdaptor.deleteAll(recycleList); } diff --git a/Domain/src/main/java/allchive/server/domain/domains/recycle/validator/RecycleValidator.java b/Domain/src/main/java/allchive/server/domain/domains/recycle/validator/RecycleValidator.java index 18c7e55e..385cd26a 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/recycle/validator/RecycleValidator.java +++ b/Domain/src/main/java/allchive/server/domain/domains/recycle/validator/RecycleValidator.java @@ -17,7 +17,7 @@ public class RecycleValidator { public void validateExist(List archivingIds, List contentIds, Long userId) { List recycleList = - recycleAdaptor.queryRecycleByUserIdInArchivingIdListAndContentIdList( + recycleAdaptor.queryRecycleByUserIdAndArchivingIdInOrUserIdAndContentIdIn( archivingIds, contentIds, userId); Long archivingCnt = recycleList.stream() diff --git a/Domain/src/main/java/allchive/server/domain/domains/report/adaptor/ReportAdaptor.java b/Domain/src/main/java/allchive/server/domain/domains/report/adaptor/ReportAdaptor.java index 16284ef0..6bab700e 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/report/adaptor/ReportAdaptor.java +++ b/Domain/src/main/java/allchive/server/domain/domains/report/adaptor/ReportAdaptor.java @@ -4,6 +4,7 @@ import allchive.server.core.annotation.Adaptor; import allchive.server.domain.domains.report.domain.Report; import allchive.server.domain.domains.report.repository.ReportRepository; +import java.util.List; import lombok.RequiredArgsConstructor; @Adaptor @@ -26,4 +27,9 @@ public Boolean queryReportExistByUserIdAndArchivingId(Long userId, Long archivin public void deleteAllByReportedUserId(Long userId) { reportRepository.deleteAllByReportedUserId(userId); } + + public void deleteAllByArchivingIdInOrContentIdIn( + List archivingIds, List contentIds) { + reportRepository.queryDeleteAllByArchivingIdInOrContentIdIn(archivingIds, contentIds); + } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/report/repository/ReportCustomRepository.java b/Domain/src/main/java/allchive/server/domain/domains/report/repository/ReportCustomRepository.java index 8c7a1f08..51df9782 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/report/repository/ReportCustomRepository.java +++ b/Domain/src/main/java/allchive/server/domain/domains/report/repository/ReportCustomRepository.java @@ -1,7 +1,12 @@ package allchive.server.domain.domains.report.repository; + +import java.util.List; + public interface ReportCustomRepository { Boolean queryReportExistByUserIdAndContentId(Long userId, Long contentId); Boolean queryReportExistByUserIdAndArchivingId(Long userId, Long archivingId); + + void queryDeleteAllByArchivingIdInOrContentIdIn(List archivingIds, List contentIds); } diff --git a/Domain/src/main/java/allchive/server/domain/domains/report/repository/ReportCustomRepositoryImpl.java b/Domain/src/main/java/allchive/server/domain/domains/report/repository/ReportCustomRepositoryImpl.java index d1ea0a1c..706de473 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/report/repository/ReportCustomRepositoryImpl.java +++ b/Domain/src/main/java/allchive/server/domain/domains/report/repository/ReportCustomRepositoryImpl.java @@ -4,6 +4,7 @@ import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQueryFactory; +import java.util.List; import lombok.RequiredArgsConstructor; @RequiredArgsConstructor @@ -32,6 +33,12 @@ public Boolean queryReportExistByUserIdAndArchivingId(Long userId, Long archivin return fetchOne != null; } + @Override + public void queryDeleteAllByArchivingIdInOrContentIdIn( + List archivingIds, List contentIds) { + queryFactory.delete(report).where(archivingIdInOrContentIdIn(archivingIds, contentIds)); + } + private BooleanExpression userIdEq(Long userId) { return report.userId.eq(userId); } @@ -43,4 +50,9 @@ private BooleanExpression contentIdEq(Long contentId) { private BooleanExpression archivingIdEq(Long archivingId) { return report.archivingId.eq(archivingId); } + + private BooleanExpression archivingIdInOrContentIdIn( + List archivingIds, List contentIds) { + return report.archivingId.in(archivingIds).or(report.contentId.in(contentIds)); + } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/report/service/ReportDomainService.java b/Domain/src/main/java/allchive/server/domain/domains/report/service/ReportDomainService.java index 00a0e4ad..957f59e9 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/report/service/ReportDomainService.java +++ b/Domain/src/main/java/allchive/server/domain/domains/report/service/ReportDomainService.java @@ -4,6 +4,7 @@ import allchive.server.core.annotation.DomainService; import allchive.server.domain.domains.report.adaptor.ReportAdaptor; import allchive.server.domain.domains.report.domain.Report; +import java.util.List; import lombok.RequiredArgsConstructor; @DomainService @@ -18,4 +19,9 @@ public void save(Report report) { public void deleteAllByReportedUserId(Long userId) { reportAdaptor.deleteAllByReportedUserId(userId); } + + public void deleteAllByArchivingIdInOrContentIdIn( + List archivingIds, List contentIds) { + reportAdaptor.deleteAllByArchivingIdInOrContentIdIn(archivingIds, contentIds); + } } diff --git a/Infrastructure/src/main/java/allchive/server/infrastructure/s3/service/S3DeleteObjectService.java b/Infrastructure/src/main/java/allchive/server/infrastructure/s3/service/S3DeleteObjectService.java new file mode 100644 index 00000000..c8a2c15d --- /dev/null +++ b/Infrastructure/src/main/java/allchive/server/infrastructure/s3/service/S3DeleteObjectService.java @@ -0,0 +1,32 @@ +package allchive.server.infrastructure.s3.service; + + +import allchive.server.core.error.exception.S3ObjectNotFoundException; +import com.amazonaws.services.s3.AmazonS3; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class S3DeleteObjectService { + private final AmazonS3 amazonS3; + + @Value("${aws.s3.bucket}") + private String bucket; + + public void deleteS3Object(List keys) { + keys.forEach( + key -> { + validateExistObject(key); + amazonS3.deleteObject(bucket, key); + }); + } + + private void validateExistObject(String key) { + if (!amazonS3.doesObjectExist(bucket, key)) { + throw S3ObjectNotFoundException.EXCEPTION; + } + } +} diff --git a/Infrastructure/src/main/java/allchive/server/infrastructure/s3/S3PresignedUrlService.java b/Infrastructure/src/main/java/allchive/server/infrastructure/s3/service/S3PresignedUrlService.java similarity index 93% rename from Infrastructure/src/main/java/allchive/server/infrastructure/s3/S3PresignedUrlService.java rename to Infrastructure/src/main/java/allchive/server/infrastructure/s3/service/S3PresignedUrlService.java index 78211363..c8f1186a 100644 --- a/Infrastructure/src/main/java/allchive/server/infrastructure/s3/S3PresignedUrlService.java +++ b/Infrastructure/src/main/java/allchive/server/infrastructure/s3/service/S3PresignedUrlService.java @@ -1,7 +1,9 @@ -package allchive.server.infrastructure.s3; +package allchive.server.infrastructure.s3.service; import allchive.server.core.error.exception.InternalServerError; +import allchive.server.infrastructure.s3.ImageUrlDto; +import allchive.server.infrastructure.s3.PresignedType; import com.amazonaws.HttpMethod; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.Headers; From ec87e9ec8cc8bf125ea3d57e15fe3ae22e15b03e Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Tue, 1 Aug 2023 10:19:17 +0900 Subject: [PATCH 10/34] =?UTF-8?q?[refac]=20report,=20block=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81=20(#75)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [refac] 차단하기 validation 정리 #74 * [refac] 차단 풀기 validation 추가 및 정리 #74 * [refac] 신고하기 함수 정리 #74 --- .../api/block/service/CreateBlockUseCase.java | 11 +++++++-- .../api/block/service/DeleteBlockUseCase.java | 9 +++++++- .../report/service/CreateReportUseCase.java | 23 +++++++++++++------ .../domains/user/adaptor/UserAdaptor.java | 4 ++++ .../domains/user/validator/UserValidator.java | 7 ++++++ 5 files changed, 44 insertions(+), 10 deletions(-) diff --git a/Api/src/main/java/allchive/server/api/block/service/CreateBlockUseCase.java b/Api/src/main/java/allchive/server/api/block/service/CreateBlockUseCase.java index fed85f8a..d8200001 100644 --- a/Api/src/main/java/allchive/server/api/block/service/CreateBlockUseCase.java +++ b/Api/src/main/java/allchive/server/api/block/service/CreateBlockUseCase.java @@ -10,12 +10,14 @@ import allchive.server.domain.domains.block.service.BlockDomainService; import allchive.server.domain.domains.block.validator.BlockValidator; import allchive.server.domain.domains.user.adaptor.UserAdaptor; +import allchive.server.domain.domains.user.validator.UserValidator; import lombok.RequiredArgsConstructor; import org.springframework.transaction.annotation.Transactional; @UseCase @RequiredArgsConstructor public class CreateBlockUseCase { + private final UserValidator userValidator; private final BlockValidator blockValidator; private final BlockMapper blockMapper; private final BlockDomainService blockDomainService; @@ -24,10 +26,15 @@ public class CreateBlockUseCase { @Transactional public BlockResponse execute(BlockRequest request) { Long userId = SecurityUtil.getCurrentUserId(); - blockValidator.validateNotDuplicate(userId, request.getUserId()); - blockValidator.validateNotMyself(userId, request.getUserId()); + validateExecution(userId, request); Block block = blockMapper.toEntity(userId, request.getUserId()); blockDomainService.save(block); return BlockResponse.from(userAdaptor.findById(request.getUserId()).getNickname()); } + + private void validateExecution(Long userId, BlockRequest request) { + userValidator.validateExist(request.getUserId()); + blockValidator.validateNotDuplicate(userId, request.getUserId()); + blockValidator.validateNotMyself(userId, request.getUserId()); + } } diff --git a/Api/src/main/java/allchive/server/api/block/service/DeleteBlockUseCase.java b/Api/src/main/java/allchive/server/api/block/service/DeleteBlockUseCase.java index 257ad370..f9b93d56 100644 --- a/Api/src/main/java/allchive/server/api/block/service/DeleteBlockUseCase.java +++ b/Api/src/main/java/allchive/server/api/block/service/DeleteBlockUseCase.java @@ -8,12 +8,14 @@ import allchive.server.domain.domains.block.service.BlockDomainService; import allchive.server.domain.domains.block.validator.BlockValidator; import allchive.server.domain.domains.user.adaptor.UserAdaptor; +import allchive.server.domain.domains.user.validator.UserValidator; import lombok.RequiredArgsConstructor; import org.springframework.transaction.annotation.Transactional; @UseCase @RequiredArgsConstructor public class DeleteBlockUseCase { + private final UserValidator userValidator; private final BlockValidator blockValidator; private final BlockDomainService blockDomainService; private final UserAdaptor userAdaptor; @@ -21,8 +23,13 @@ public class DeleteBlockUseCase { @Transactional public BlockResponse execute(BlockRequest request) { Long userId = SecurityUtil.getCurrentUserId(); - blockValidator.validateExist(userId, request.getUserId()); + validateExecution(userId, request); blockDomainService.deleteByBlockFromAndBlockUser(userId, request.getUserId()); return BlockResponse.from(userAdaptor.findById(request.getUserId()).getNickname()); } + + private void validateExecution(Long userId, BlockRequest request) { + userValidator.validateExist(request.getUserId()); + blockValidator.validateExist(userId, request.getUserId()); + } } diff --git a/Api/src/main/java/allchive/server/api/report/service/CreateReportUseCase.java b/Api/src/main/java/allchive/server/api/report/service/CreateReportUseCase.java index 07681e8b..4603f830 100644 --- a/Api/src/main/java/allchive/server/api/report/service/CreateReportUseCase.java +++ b/Api/src/main/java/allchive/server/api/report/service/CreateReportUseCase.java @@ -30,20 +30,29 @@ public class CreateReportUseCase { @Transactional public void execute(CreateReportRequest request, ReportObjectType type) { Long userId = SecurityUtil.getCurrentUserId(); - reportValidator.validateNotDuplicateReport(userId, request.getId(), type); + validateExecution(userId, request.getId(), type); + Long reportedUserId = getReportedUserId(request.getId(), type); + Report report = reportMapper.toEntity(request, type, userId, reportedUserId); + reportDomainService.save(report); + } + + private void validateExecution(Long userId, Long objId, ReportObjectType type) { + reportValidator.validateNotDuplicateReport(userId, objId, type); + } + + private Long getReportedUserId(Long objId, ReportObjectType type) { Long reportedUserId = 0L; switch (type) { case CONTENT -> { - contentValidator.validateExistById(request.getId()); - Long archivingId = contentAdaptor.findById(request.getId()).getArchivingId(); + contentValidator.validateExistById(objId); + Long archivingId = contentAdaptor.findById(objId).getArchivingId(); reportedUserId = archivingAdaptor.findById(archivingId).getUserId(); } case ARCHIVING -> { - archivingValidator.validateExistById(request.getId()); - reportedUserId = archivingAdaptor.findById(request.getId()).getUserId(); + archivingValidator.validateExistById(objId); + reportedUserId = archivingAdaptor.findById(objId).getUserId(); } } - Report report = reportMapper.toEntity(request, type, userId, reportedUserId); - reportDomainService.save(report); + return reportedUserId; } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/user/adaptor/UserAdaptor.java b/Domain/src/main/java/allchive/server/domain/domains/user/adaptor/UserAdaptor.java index b118c6ae..d800f01a 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/user/adaptor/UserAdaptor.java +++ b/Domain/src/main/java/allchive/server/domain/domains/user/adaptor/UserAdaptor.java @@ -39,4 +39,8 @@ public Boolean existsByNickname(String nickname) { public List findAllByIdIn(List userIds) { return userRepository.findAllByIdIn(userIds); } + + public Boolean existsById(Long userId) { + return userRepository.existsById(userId); + } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/user/validator/UserValidator.java b/Domain/src/main/java/allchive/server/domain/domains/user/validator/UserValidator.java index a79f04f3..d5d08514 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/user/validator/UserValidator.java +++ b/Domain/src/main/java/allchive/server/domain/domains/user/validator/UserValidator.java @@ -7,6 +7,7 @@ import allchive.server.domain.domains.user.domain.enums.UserState; import allchive.server.domain.domains.user.exception.exceptions.AlreadySignUpUserException; import allchive.server.domain.domains.user.exception.exceptions.ForbiddenUserException; +import allchive.server.domain.domains.user.exception.exceptions.UserNotFoundException; import lombok.RequiredArgsConstructor; @Validator @@ -27,4 +28,10 @@ public void validateUserStatusNormal(Long userId) { throw ForbiddenUserException.EXCEPTION; } } + + public void validateExist(Long userId) { + if (!userAdaptor.existsById(userId)) { + throw UserNotFoundException.EXCEPTION; + } + } } From a4ab7a66b9915e29a6a4d460cebab374e5521bb6 Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Tue, 1 Aug 2023 22:23:09 +0900 Subject: [PATCH 11/34] =?UTF-8?q?[fix]=20=EC=95=84=EC=B9=B4=EC=9D=B4?= =?UTF-8?q?=EB=B9=99=20=EC=8A=A4=ED=81=AC=EB=9E=A9=20=EC=95=88=EB=90=98?= =?UTF-8?q?=EB=8A=94=20=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0=20(#77)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [fix] scrap validation 수정 #76 * [fix] enum value 대문자로 변경 #76 --- .../service/UpdateArchivingScrapUseCase.java | 4 +++- .../model/dto/request/CreateContentRequest.java | 2 +- .../model/dto/request/UpdateContentRequest.java | 2 +- .../model/dto/request/CreateReportRequest.java | 2 +- .../content/domain/enums/ContentType.java | 4 ++-- .../recycle/domain/enums/RecycleType.java | 4 ++-- .../report/domain/enums/ReportObjectType.java | 4 ++-- .../report/domain/enums/ReportedType.java | 16 ++++++++-------- .../domains/user/adaptor/ScrapAdaptor.java | 4 ++++ .../domains/user/repository/ScrapRepository.java | 2 ++ .../domains/user/validator/ScrapValidator.java | 12 ++++++------ 11 files changed, 32 insertions(+), 24 deletions(-) diff --git a/Api/src/main/java/allchive/server/api/archiving/service/UpdateArchivingScrapUseCase.java b/Api/src/main/java/allchive/server/api/archiving/service/UpdateArchivingScrapUseCase.java index 9ff7468b..88ba1f21 100644 --- a/Api/src/main/java/allchive/server/api/archiving/service/UpdateArchivingScrapUseCase.java +++ b/Api/src/main/java/allchive/server/api/archiving/service/UpdateArchivingScrapUseCase.java @@ -40,8 +40,10 @@ public void execute(Long archivingId, Boolean cancel) { private void validateExecution(Long archivingId, Long userId, Boolean cancel) { archivingValidator.validateExistById(archivingId); archivingValidator.validateDeleteStatus(archivingId, userId); - if (!cancel) { + if (cancel) { scrapValidator.validateExistScrap(userId, archivingId); + } else { + scrapValidator.validateNotExistScrap(userId, archivingId); } } } diff --git a/Api/src/main/java/allchive/server/api/content/model/dto/request/CreateContentRequest.java b/Api/src/main/java/allchive/server/api/content/model/dto/request/CreateContentRequest.java index ead4b71f..00eddb9b 100644 --- a/Api/src/main/java/allchive/server/api/content/model/dto/request/CreateContentRequest.java +++ b/Api/src/main/java/allchive/server/api/content/model/dto/request/CreateContentRequest.java @@ -9,7 +9,7 @@ @Getter public class CreateContentRequest { - @Schema(defaultValue = "image", description = "컨텐츠 타입") + @Schema(defaultValue = "IMAGE", description = "컨텐츠 타입") @ValidEnum(target = ContentType.class) private ContentType contentType; diff --git a/Api/src/main/java/allchive/server/api/content/model/dto/request/UpdateContentRequest.java b/Api/src/main/java/allchive/server/api/content/model/dto/request/UpdateContentRequest.java index 0298614e..9d29def3 100644 --- a/Api/src/main/java/allchive/server/api/content/model/dto/request/UpdateContentRequest.java +++ b/Api/src/main/java/allchive/server/api/content/model/dto/request/UpdateContentRequest.java @@ -9,7 +9,7 @@ @Getter public class UpdateContentRequest { - @Schema(defaultValue = "image", description = "컨텐츠 타입") + @Schema(defaultValue = "IMAGE", description = "컨텐츠 타입") @ValidEnum(target = ContentType.class) private ContentType contentType; diff --git a/Api/src/main/java/allchive/server/api/report/model/dto/request/CreateReportRequest.java b/Api/src/main/java/allchive/server/api/report/model/dto/request/CreateReportRequest.java index de3d048f..a6f91ac0 100644 --- a/Api/src/main/java/allchive/server/api/report/model/dto/request/CreateReportRequest.java +++ b/Api/src/main/java/allchive/server/api/report/model/dto/request/CreateReportRequest.java @@ -11,7 +11,7 @@ public class CreateReportRequest { @Schema(defaultValue = "기타기타기타기타기타", description = "사유 ('기타'에만 해당)") private String reason; - @Schema(defaultValue = "spam", description = "신고 종류") + @Schema(defaultValue = "SPAM", description = "신고 종류") @ValidEnum(target = ReportedType.class) private ReportedType reportedType; diff --git a/Domain/src/main/java/allchive/server/domain/domains/content/domain/enums/ContentType.java b/Domain/src/main/java/allchive/server/domain/domains/content/domain/enums/ContentType.java index fbec1562..8cb6ebb8 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/content/domain/enums/ContentType.java +++ b/Domain/src/main/java/allchive/server/domain/domains/content/domain/enums/ContentType.java @@ -11,8 +11,8 @@ @Getter @AllArgsConstructor public enum ContentType { - IMAGE("image"), - LINK("link"); + IMAGE("IMAGE"), + LINK("LINK"); @JsonValue private String value; diff --git a/Domain/src/main/java/allchive/server/domain/domains/recycle/domain/enums/RecycleType.java b/Domain/src/main/java/allchive/server/domain/domains/recycle/domain/enums/RecycleType.java index 4b978a54..16ecaad8 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/recycle/domain/enums/RecycleType.java +++ b/Domain/src/main/java/allchive/server/domain/domains/recycle/domain/enums/RecycleType.java @@ -11,8 +11,8 @@ @Getter @AllArgsConstructor public enum RecycleType { - CONTENT("content"), - ARCHIVING("archiving"); + CONTENT("CONTENT"), + ARCHIVING("ARCHIVING"); @JsonValue private String value; diff --git a/Domain/src/main/java/allchive/server/domain/domains/report/domain/enums/ReportObjectType.java b/Domain/src/main/java/allchive/server/domain/domains/report/domain/enums/ReportObjectType.java index 5c90c3c7..46d895a3 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/report/domain/enums/ReportObjectType.java +++ b/Domain/src/main/java/allchive/server/domain/domains/report/domain/enums/ReportObjectType.java @@ -11,8 +11,8 @@ @Getter @AllArgsConstructor public enum ReportObjectType { - CONTENT("content"), - ARCHIVING("archiving"); + CONTENT("CONTENT"), + ARCHIVING("ARCHIVING"); @JsonValue private String value; diff --git a/Domain/src/main/java/allchive/server/domain/domains/report/domain/enums/ReportedType.java b/Domain/src/main/java/allchive/server/domain/domains/report/domain/enums/ReportedType.java index ad0f8cc4..abe43c72 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/report/domain/enums/ReportedType.java +++ b/Domain/src/main/java/allchive/server/domain/domains/report/domain/enums/ReportedType.java @@ -11,14 +11,14 @@ @Getter @AllArgsConstructor public enum ReportedType { - SPAM("spam"), // 스팸이에요 - OBSCENE("obscene"), // 음란성 컨텐츠를 담고있어요 - PERSONAL_INFO("personalInfo"), // 개인정보를 노출하고 있어요 - INTELLECTUAL_PROPERTY("intellectualProperty"), // 지식재산권을 침해해요 - VIOLENCE("violence"), // 혐오/폭력 컨텐츠를 담고 있어요 - ILLEGAL_INFO("illegalInformation"), // 불법 정보를 포함하고 있어요 - FRAUD("fraud"), // 사기 또는 피싱성 링크를 포함하고 있어요 - ETC("etc"); // 기타 + SPAM("SPAM"), // 스팸이에요 + OBSCENE("OBSCENE"), // 음란성 컨텐츠를 담고있어요 + PERSONAL_INFO("PERSONAL_INFO"), // 개인정보를 노출하고 있어요 + INTELLECTUAL_PROPERTY("INTELLECTUAL_PROPERTY"), // 지식재산권을 침해해요 + VIOLENCE("VIOLENCE"), // 혐오/폭력 컨텐츠를 담고 있어요 + ILLEGAL_INFO("ILLEGAL_INFO"), // 불법 정보를 포함하고 있어요 + FRAUD("FRAUD"), // 사기 또는 피싱성 링크를 포함하고 있어요 + ETC("ETC"); // 기타 @JsonValue private String value; diff --git a/Domain/src/main/java/allchive/server/domain/domains/user/adaptor/ScrapAdaptor.java b/Domain/src/main/java/allchive/server/domain/domains/user/adaptor/ScrapAdaptor.java index 533d97eb..2534f4eb 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/user/adaptor/ScrapAdaptor.java +++ b/Domain/src/main/java/allchive/server/domain/domains/user/adaptor/ScrapAdaptor.java @@ -39,4 +39,8 @@ public void deleteAllByArchivingIdIn(List archivingIds) { public void deleteAllByUser(User user) { scrapRepository.deleteAllByUser(user); } + + public boolean existsByUserAndArchivingId(User user, Long archivingId) { + return scrapRepository.existsByUserAndArchivingId(user, archivingId); + } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/user/repository/ScrapRepository.java b/Domain/src/main/java/allchive/server/domain/domains/user/repository/ScrapRepository.java index 4ccfba30..7600377c 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/user/repository/ScrapRepository.java +++ b/Domain/src/main/java/allchive/server/domain/domains/user/repository/ScrapRepository.java @@ -15,4 +15,6 @@ public interface ScrapRepository extends JpaRepository { void deleteAllByArchivingIdIn(List archivingId); void deleteAllByUser(User user); + + boolean existsByUserAndArchivingId(User user, Long archivingId); } diff --git a/Domain/src/main/java/allchive/server/domain/domains/user/validator/ScrapValidator.java b/Domain/src/main/java/allchive/server/domain/domains/user/validator/ScrapValidator.java index 153ee1e7..1ab5a89f 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/user/validator/ScrapValidator.java +++ b/Domain/src/main/java/allchive/server/domain/domains/user/validator/ScrapValidator.java @@ -16,13 +16,13 @@ public class ScrapValidator { public void validateExistScrap(Long userId, Long archivingId) { User user = userAdaptor.findById(userId); - if (isScrapExist(user, archivingId)) { - throw AlreadyExistScrapException.EXCEPTION; - } + scrapAdaptor.findByUserAndArchivingId(user, archivingId); } - private Boolean isScrapExist(User user, Long archivingId) { - scrapAdaptor.findByUserAndArchivingId(user, archivingId); - return Boolean.TRUE; + public void validateNotExistScrap(Long userId, Long archivingId) { + User user = userAdaptor.findById(userId); + if (scrapAdaptor.existsByUserAndArchivingId(user, archivingId)) { + throw AlreadyExistScrapException.EXCEPTION; + } } } From 17362d45a70fac3ed0b8ec61ed67d964911cc054 Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Wed, 2 Aug 2023 14:35:39 +0900 Subject: [PATCH 12/34] =?UTF-8?q?[feat]=20swagger=20=EB=B9=84=EB=B0=80?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EC=84=A4=EC=A0=95=20(#79)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [refac] 차단하기 validation 정리 #74 * [refac] 차단 풀기 validation 추가 및 정리 #74 * [refac] 신고하기 함수 정리 #74 * [feat] swagger 비밀번호 설정 #78 --- .../api/config/security/SecurityConfig.java | 26 +++++++++++++++++++ Api/src/main/resources/application.yml | 4 +++ .../core/helper/SpringEnvironmentHelper.java | 16 +++++++++--- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/Api/src/main/java/allchive/server/api/config/security/SecurityConfig.java b/Api/src/main/java/allchive/server/api/config/security/SecurityConfig.java index 236519ea..40746326 100644 --- a/Api/src/main/java/allchive/server/api/config/security/SecurityConfig.java +++ b/Api/src/main/java/allchive/server/api/config/security/SecurityConfig.java @@ -2,14 +2,19 @@ import static allchive.server.core.consts.AllchiveConst.SwaggerPatterns; +import allchive.server.core.helper.SpringEnvironmentHelper; import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler; @@ -17,6 +22,23 @@ @EnableWebSecurity() public class SecurityConfig { private final FilterConfig filterConfig; + private final SpringEnvironmentHelper springEnvironmentHelper; + + @Value("${swagger.user}") + private String swaggerUser; + + @Value("${swagger.password}") + private String swaggerPassword; + + @Bean + public InMemoryUserDetailsManager userDetailsService() { + UserDetails user = + User.withUsername(swaggerUser) + .password(passwordEncoder().encode(swaggerPassword)) + .roles("SWAGGER") + .build(); + return new InMemoryUserDetailsManager(user); + } @Bean public PasswordEncoder passwordEncoder() { @@ -30,6 +52,10 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); http.authorizeRequests().expressionHandler(expressionHandler()); + if (springEnvironmentHelper.isProdAndDevProfile()) { + http.authorizeRequests().mvcMatchers(SwaggerPatterns).authenticated().and().httpBasic(); + } + http.authorizeRequests() .antMatchers(SwaggerPatterns) .permitAll() diff --git a/Api/src/main/resources/application.yml b/Api/src/main/resources/application.yml index c4f14e91..33e428bb 100644 --- a/Api/src/main/resources/application.yml +++ b/Api/src/main/resources/application.yml @@ -19,6 +19,10 @@ springdoc: swagger-ui: tags-sorter: alpha +swagger: + user: ${SWAGGER_USER:user} + password: ${SWAGGER_PASSWORD:password} + --- spring: config: diff --git a/Core/src/main/java/allchive/server/core/helper/SpringEnvironmentHelper.java b/Core/src/main/java/allchive/server/core/helper/SpringEnvironmentHelper.java index 9016edfd..a3a92044 100644 --- a/Core/src/main/java/allchive/server/core/helper/SpringEnvironmentHelper.java +++ b/Core/src/main/java/allchive/server/core/helper/SpringEnvironmentHelper.java @@ -16,14 +16,22 @@ public class SpringEnvironmentHelper { private final Environment environment; public Boolean isProdProfile() { - String[] activeProfiles = environment.getActiveProfiles(); - List currentProfile = Arrays.stream(activeProfiles).toList(); + List currentProfile = getCurrentProfile(); return currentProfile.contains(PROD); } public Boolean isDevProfile() { - String[] activeProfiles = environment.getActiveProfiles(); - List currentProfile = Arrays.stream(activeProfiles).toList(); + List currentProfile = getCurrentProfile(); return currentProfile.contains(DEV); } + + public Boolean isProdAndDevProfile() { + List currentProfile = getCurrentProfile(); + return currentProfile.contains(PROD) || currentProfile.contains(DEV); + } + + private List getCurrentProfile() { + String[] activeProfiles = environment.getActiveProfiles(); + return Arrays.stream(activeProfiles).toList(); + } } From 4bd386143b50f64195e332ebed5762e78e7cb91d Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Wed, 2 Aug 2023 15:43:02 +0900 Subject: [PATCH 13/34] =?UTF-8?q?[fix]=20=EC=BB=A8=ED=85=90=EC=B8=A0=20?= =?UTF-8?q?=EA=B0=9C=EC=88=98=20=EA=B5=AC=ED=95=98=EA=B8=B0=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=88=98=EC=A0=95=20(#81)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/api/archiving/model/vo/TitleContentCntVo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Api/src/main/java/allchive/server/api/archiving/model/vo/TitleContentCntVo.java b/Api/src/main/java/allchive/server/api/archiving/model/vo/TitleContentCntVo.java index 7f658787..4154baab 100644 --- a/Api/src/main/java/allchive/server/api/archiving/model/vo/TitleContentCntVo.java +++ b/Api/src/main/java/allchive/server/api/archiving/model/vo/TitleContentCntVo.java @@ -27,7 +27,7 @@ private TitleContentCntVo(Long archivingId, String title, Long contentCnt) { public static TitleContentCntVo from(Archiving archiving) { return TitleContentCntVo.builder() .archivingId(archiving.getId()) - .contentCnt(archiving.getImgCnt() + archiving.getScrapCnt()) + .contentCnt(archiving.getImgCnt() + archiving.getLinkCnt()) .title(archiving.getTitle()) .build(); } From 7d24195ce91da112378d8781015e3ed3e832816d Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Wed, 2 Aug 2023 22:01:50 +0900 Subject: [PATCH 14/34] =?UTF-8?q?[fix]=20user=20=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?=EB=B6=88=EB=9F=AC=EC=98=A4=EA=B8=B0=20count=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=ED=95=B4=EA=B2=B0=20(#83)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../allchive/server/api/user/service/GetUserProfileUseCase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Api/src/main/java/allchive/server/api/user/service/GetUserProfileUseCase.java b/Api/src/main/java/allchive/server/api/user/service/GetUserProfileUseCase.java index 083d005a..fe42d2cc 100644 --- a/Api/src/main/java/allchive/server/api/user/service/GetUserProfileUseCase.java +++ b/Api/src/main/java/allchive/server/api/user/service/GetUserProfileUseCase.java @@ -27,7 +27,7 @@ public GetUserProfileResponse execute() { Long userId = SecurityUtil.getCurrentUserId(); validateExecution(userId); User user = userAdaptor.findById(userId); - List archivingList = archivingAdaptor.findAllByUserId(userId); + List archivingList = archivingAdaptor.queryArchivingByUserId(userId); return userMapper.toGetUserProfileResponse(archivingList, user); } From b8898610fcaf3f5654d15d31d3ec29d452d0acf1 Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Thu, 3 Aug 2023 00:20:36 +0900 Subject: [PATCH 15/34] =?UTF-8?q?[refac]=20validation=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=20(#85)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [fix] archiving 기능관련 쿼리 deleteStatus 조건 수정 #84 * [feat] 컨텐츠 삭제 validation 추가 #84 * [feat] 아카이빙 삭제하기 삭제 여부 validation 추가 #84 * [fix] 컨텐츠 가져오기 public validation 수정 #84 * [refac] tag validation 분리 #84 * [chore] spotless 적용 #84 --- .../service/DeleteArchivingUseCase.java | 1 + .../content/service/CreateContentUseCase.java | 2 +- .../content/service/DeleteContentUseCase.java | 1 + .../api/content/service/GetContentUseCase.java | 8 +++++--- .../api/tag/service/DeleteTagUseCase.java | 8 ++++++-- .../api/tag/service/UpdateTagUseCase.java | 6 +++++- .../domains/archiving/domain/Archiving.java | 6 ++++++ .../archiving/validator/ArchivingValidator.java | 8 ++++---- .../content/exception/ContentErrorCode.java | 2 ++ .../AlreadyDeletedContentException.java | 14 ++++++++++++++ .../exceptions/NotPublicContentException.java | 14 ++++++++++++++ .../repository/ContentCustomRepositoryImpl.java | 6 +++++- .../content/validator/ContentValidator.java | 17 +++++++++++++++++ 13 files changed, 81 insertions(+), 12 deletions(-) create mode 100644 Domain/src/main/java/allchive/server/domain/domains/content/exception/exceptions/AlreadyDeletedContentException.java create mode 100644 Domain/src/main/java/allchive/server/domain/domains/content/exception/exceptions/NotPublicContentException.java diff --git a/Api/src/main/java/allchive/server/api/archiving/service/DeleteArchivingUseCase.java b/Api/src/main/java/allchive/server/api/archiving/service/DeleteArchivingUseCase.java index d54ddd61..3f81f4fa 100644 --- a/Api/src/main/java/allchive/server/api/archiving/service/DeleteArchivingUseCase.java +++ b/Api/src/main/java/allchive/server/api/archiving/service/DeleteArchivingUseCase.java @@ -30,5 +30,6 @@ public void execute(Long archivingId) { private void validateExecution(Long archivingId, Long userId) { archivingValidator.verifyUser(userId, archivingId); + archivingValidator.validateNotDeleted(archivingId); } } diff --git a/Api/src/main/java/allchive/server/api/content/service/CreateContentUseCase.java b/Api/src/main/java/allchive/server/api/content/service/CreateContentUseCase.java index 3a525ffb..d65c3978 100644 --- a/Api/src/main/java/allchive/server/api/content/service/CreateContentUseCase.java +++ b/Api/src/main/java/allchive/server/api/content/service/CreateContentUseCase.java @@ -41,7 +41,7 @@ public void execute(CreateContentRequest request) { private void validateExecution(CreateContentRequest request) { Long userId = SecurityUtil.getCurrentUserId(); archivingValidator.validateExistById(request.getArchivingId()); - archivingValidator.validateArchivingUser(request.getArchivingId(), userId); + archivingValidator.verifyUser(request.getArchivingId(), userId); tagValidator.validateExistTagsAndUser(request.getTagIds(), userId); } diff --git a/Api/src/main/java/allchive/server/api/content/service/DeleteContentUseCase.java b/Api/src/main/java/allchive/server/api/content/service/DeleteContentUseCase.java index 97c4043c..865f9867 100644 --- a/Api/src/main/java/allchive/server/api/content/service/DeleteContentUseCase.java +++ b/Api/src/main/java/allchive/server/api/content/service/DeleteContentUseCase.java @@ -30,6 +30,7 @@ public void execute(Long contentId) { private void validateExecution(Long contentId, Long userId) { contentValidator.verifyUser(contentId, userId); + contentValidator.validateNotDelete(contentId); } private void createRecycle(Long userId, Long contentId) { diff --git a/Api/src/main/java/allchive/server/api/content/service/GetContentUseCase.java b/Api/src/main/java/allchive/server/api/content/service/GetContentUseCase.java index e61fc1d7..fcccb107 100644 --- a/Api/src/main/java/allchive/server/api/content/service/GetContentUseCase.java +++ b/Api/src/main/java/allchive/server/api/content/service/GetContentUseCase.java @@ -12,6 +12,7 @@ import allchive.server.domain.domains.content.adaptor.ContentTagGroupAdaptor; import allchive.server.domain.domains.content.domain.Content; import allchive.server.domain.domains.content.domain.ContentTagGroup; +import allchive.server.domain.domains.content.validator.ContentValidator; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.transaction.annotation.Transactional; @@ -20,6 +21,7 @@ @RequiredArgsConstructor public class GetContentUseCase { private final ArchivingValidator archivingValidator; + private final ContentValidator contentValidator; private final ContentAdaptor contentAdaptor; private final ContentTagGroupAdaptor contentTagGroupAdaptor; private final ContentMapper contentMapper; @@ -28,16 +30,16 @@ public class GetContentUseCase { @Transactional(readOnly = true) public ContentTagResponse execute(Long contentId) { Long userId = SecurityUtil.getCurrentUserId(); + validateExecution(contentId, userId); Content content = contentAdaptor.findById(contentId); - validateExecution(content.getArchivingId(), userId); List contentTagGroupList = contentTagGroupAdaptor.queryContentTagGroupByContentWithTag(content); Boolean isMine = calculateIsMine(content.getArchivingId(), userId); return contentMapper.toContentTagResponse(content, contentTagGroupList, isMine); } - private void validateExecution(Long archivingId, Long userId) { - archivingValidator.validatePublicStatus(archivingId, userId); + private void validateExecution(Long contentId, Long userId) { + contentValidator.validatePublic(contentId, userId); } private Boolean calculateIsMine(Long archivingId, Long userId) { diff --git a/Api/src/main/java/allchive/server/api/tag/service/DeleteTagUseCase.java b/Api/src/main/java/allchive/server/api/tag/service/DeleteTagUseCase.java index a34a8db3..63dc129a 100644 --- a/Api/src/main/java/allchive/server/api/tag/service/DeleteTagUseCase.java +++ b/Api/src/main/java/allchive/server/api/tag/service/DeleteTagUseCase.java @@ -21,10 +21,14 @@ public class DeleteTagUseCase { @Transactional public void execute(Long tagId) { - Long userId = SecurityUtil.getCurrentUserId(); - tagValidator.verifyUser(tagId, userId); + validateExecution(tagId); Tag tag = tagAdaptor.findById(tagId); contentTagGroupDomainService.deleteByTag(tag); tagDomainService.deleteById(tagId); } + + private void validateExecution(Long tagId) { + Long userId = SecurityUtil.getCurrentUserId(); + tagValidator.verifyUser(tagId, userId); + } } diff --git a/Api/src/main/java/allchive/server/api/tag/service/UpdateTagUseCase.java b/Api/src/main/java/allchive/server/api/tag/service/UpdateTagUseCase.java index 881ec389..80866d67 100644 --- a/Api/src/main/java/allchive/server/api/tag/service/UpdateTagUseCase.java +++ b/Api/src/main/java/allchive/server/api/tag/service/UpdateTagUseCase.java @@ -17,8 +17,12 @@ public class UpdateTagUseCase { @Transactional public void execute(Long tagId, UpdateTagRequest request) { + validateExecution(tagId); + tagDomainService.updateTag(tagId, request.getName()); + } + + private void validateExecution(Long tagId) { Long userId = SecurityUtil.getCurrentUserId(); tagValidator.verifyUser(tagId, userId); - tagDomainService.updateTag(tagId, request.getName()); } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/archiving/domain/Archiving.java b/Domain/src/main/java/allchive/server/domain/domains/archiving/domain/Archiving.java index 7529ec11..8504354e 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/archiving/domain/Archiving.java +++ b/Domain/src/main/java/allchive/server/domain/domains/archiving/domain/Archiving.java @@ -124,4 +124,10 @@ public void updateImgCnt(int i) { public void updateLinkCnt(int i) { this.linkCnt += i; } + + public void validateNotDelete() { + if (this.deleteStatus.equals(Boolean.TRUE)) { + throw DeletedArchivingException.EXCEPTION; + } + } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/archiving/validator/ArchivingValidator.java b/Domain/src/main/java/allchive/server/domain/domains/archiving/validator/ArchivingValidator.java index 0dd6ec08..befa4fd0 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/archiving/validator/ArchivingValidator.java +++ b/Domain/src/main/java/allchive/server/domain/domains/archiving/validator/ArchivingValidator.java @@ -46,10 +46,6 @@ public void validateNotPinStatus(Long archivingId, Long userId) { } } - public void validateArchivingUser(Long archivingId, Long userId) { - archivingAdaptor.findById(archivingId).validateUser(userId); - } - public void validateExistInIdList(List archivingIdList) { List archivingList = archivingAdaptor.findAllByIdIn(archivingIdList); if (archivingList.size() != archivingIdList.size()) { @@ -66,4 +62,8 @@ public void verifyUserInIdList(Long userId, List archivingIds) { } }); } + + public void validateNotDeleted(Long archivingId) { + archivingAdaptor.findById(archivingId).validateNotDelete(); + } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/content/exception/ContentErrorCode.java b/Domain/src/main/java/allchive/server/domain/domains/content/exception/ContentErrorCode.java index 58d96d31..97656cbd 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/content/exception/ContentErrorCode.java +++ b/Domain/src/main/java/allchive/server/domain/domains/content/exception/ContentErrorCode.java @@ -11,6 +11,8 @@ @Getter @AllArgsConstructor public enum ContentErrorCode implements BaseErrorCode { + ALREADY_DELETED_CONTENT(NOT_FOUND, "CONTENT_400_1", "이미 삭제된 컨텐츠입니다."), + NOT_PUBLIC_CONTENT(NOT_FOUND, "CONTENT_400_2", "공개되지않은 컨텐츠입니다."), CONTENT_NOT_FOUND(NOT_FOUND, "CONTENT_404_1", "카테고리를 찾을 수 없습니다."), NO_AUTHORITY_UPDATE_CONTENT(FORBIDDEN, "TAG_403_1", "컨텐츠 수정 권한이 없습니다."), diff --git a/Domain/src/main/java/allchive/server/domain/domains/content/exception/exceptions/AlreadyDeletedContentException.java b/Domain/src/main/java/allchive/server/domain/domains/content/exception/exceptions/AlreadyDeletedContentException.java new file mode 100644 index 00000000..619e6b0e --- /dev/null +++ b/Domain/src/main/java/allchive/server/domain/domains/content/exception/exceptions/AlreadyDeletedContentException.java @@ -0,0 +1,14 @@ +package allchive.server.domain.domains.content.exception.exceptions; + + +import allchive.server.core.error.BaseErrorException; +import allchive.server.domain.domains.content.exception.ContentErrorCode; + +public class AlreadyDeletedContentException extends BaseErrorException { + + public static final BaseErrorException EXCEPTION = new AlreadyDeletedContentException(); + + private AlreadyDeletedContentException() { + super(ContentErrorCode.ALREADY_DELETED_CONTENT); + } +} diff --git a/Domain/src/main/java/allchive/server/domain/domains/content/exception/exceptions/NotPublicContentException.java b/Domain/src/main/java/allchive/server/domain/domains/content/exception/exceptions/NotPublicContentException.java new file mode 100644 index 00000000..a71cb95e --- /dev/null +++ b/Domain/src/main/java/allchive/server/domain/domains/content/exception/exceptions/NotPublicContentException.java @@ -0,0 +1,14 @@ +package allchive.server.domain.domains.content.exception.exceptions; + + +import allchive.server.core.error.BaseErrorException; +import allchive.server.domain.domains.content.exception.ContentErrorCode; + +public class NotPublicContentException extends BaseErrorException { + + public static final BaseErrorException EXCEPTION = new NotPublicContentException(); + + private NotPublicContentException() { + super(ContentErrorCode.NOT_PUBLIC_CONTENT); + } +} diff --git a/Domain/src/main/java/allchive/server/domain/domains/content/repository/ContentCustomRepositoryImpl.java b/Domain/src/main/java/allchive/server/domain/domains/content/repository/ContentCustomRepositoryImpl.java index 91ffbc07..90edcb37 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/content/repository/ContentCustomRepositoryImpl.java +++ b/Domain/src/main/java/allchive/server/domain/domains/content/repository/ContentCustomRepositoryImpl.java @@ -22,7 +22,7 @@ public Slice querySliceContentByArchivingId(Long archivingId, Pageable List archivings = queryFactory .selectFrom(content) - .where(archivingIdEq(archivingId)) + .where(archivingIdEq(archivingId), deleteStatusFalse()) .orderBy(createdAtDesc()) .offset(pageable.getOffset()) .limit(pageable.getPageSize() + 1) @@ -46,6 +46,10 @@ public boolean queryContentExistById(Long id) { return fetchOne != null; } + private BooleanExpression deleteStatusFalse() { + return content.deleteStatus.eq(Boolean.FALSE); + } + private BooleanExpression archivingIdEq(Long archivingId) { return content.archivingId.eq(archivingId); } diff --git a/Domain/src/main/java/allchive/server/domain/domains/content/validator/ContentValidator.java b/Domain/src/main/java/allchive/server/domain/domains/content/validator/ContentValidator.java index 5aea2a35..6fc83f80 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/content/validator/ContentValidator.java +++ b/Domain/src/main/java/allchive/server/domain/domains/content/validator/ContentValidator.java @@ -6,8 +6,10 @@ import allchive.server.domain.domains.archiving.domain.Archiving; import allchive.server.domain.domains.content.adaptor.ContentAdaptor; import allchive.server.domain.domains.content.domain.Content; +import allchive.server.domain.domains.content.exception.exceptions.AlreadyDeletedContentException; import allchive.server.domain.domains.content.exception.exceptions.ContentNotFoundException; import allchive.server.domain.domains.content.exception.exceptions.NoAuthorityUpdateContentException; +import allchive.server.domain.domains.content.exception.exceptions.NotPublicContentException; import java.util.List; import lombok.RequiredArgsConstructor; @@ -52,4 +54,19 @@ public void verifyUser(Long contentId, Long userId) { throw NoAuthorityUpdateContentException.EXCEPTION; } } + + public void validateNotDelete(Long contentId) { + if (contentAdaptor.findById(contentId).isDeleteStatus()) { + throw AlreadyDeletedContentException.EXCEPTION; + } + } + + public void validatePublic(Long contentId, Long userId) { + Content content = contentAdaptor.findById(contentId); + Archiving archiving = archivingAdaptor.findById(content.getArchivingId()); + if (archiving.getPublicStatus().equals(Boolean.FALSE) + && !archiving.getUserId().equals(userId)) { + throw NotPublicContentException.EXCEPTION; + } + } } From 56a2cc161ae0f3fe306104ebc9d13de66abb7d6f Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Thu, 3 Aug 2023 16:43:21 +0900 Subject: [PATCH 16/34] =?UTF-8?q?[feat]=20=EC=BB=A8=ED=85=90=EC=B8=A0=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=88=98=EC=A0=95=EC=8B=9C=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=A0=20=EC=A0=95=EB=B3=B4=20=EA=B0=80=EC=A0=B8?= =?UTF-8?q?=EC=98=A4=EA=B8=B0=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?(#87)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [feat] 컨텐츠 정보 가져오기 기능 구현 #86 * [chore] spotless 적용 #86 --- .../content/controller/ContentController.java | 15 ++- .../dto/response/ContentTagInfoResponse.java | 96 +++++++++++++++++++ .../content/model/mapper/ContentMapper.java | 14 +++ .../service/GetContentInfoUseCase.java | 52 ++++++++++ .../content/service/GetContentUseCase.java | 2 - 5 files changed, 172 insertions(+), 7 deletions(-) create mode 100644 Api/src/main/java/allchive/server/api/content/model/dto/response/ContentTagInfoResponse.java create mode 100644 Api/src/main/java/allchive/server/api/content/service/GetContentInfoUseCase.java diff --git a/Api/src/main/java/allchive/server/api/content/controller/ContentController.java b/Api/src/main/java/allchive/server/api/content/controller/ContentController.java index 284e286e..e9357f64 100644 --- a/Api/src/main/java/allchive/server/api/content/controller/ContentController.java +++ b/Api/src/main/java/allchive/server/api/content/controller/ContentController.java @@ -3,11 +3,9 @@ import allchive.server.api.content.model.dto.request.CreateContentRequest; import allchive.server.api.content.model.dto.request.UpdateContentRequest; +import allchive.server.api.content.model.dto.response.ContentTagInfoResponse; import allchive.server.api.content.model.dto.response.ContentTagResponse; -import allchive.server.api.content.service.CreateContentUseCase; -import allchive.server.api.content.service.DeleteContentUseCase; -import allchive.server.api.content.service.GetContentUseCase; -import allchive.server.api.content.service.UpdateContentUseCase; +import allchive.server.api.content.service.*; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -24,6 +22,7 @@ public class ContentController { private final GetContentUseCase getContentUseCase; private final DeleteContentUseCase deleteContentUseCase; private final UpdateContentUseCase updateContentUseCase; + private final GetContentInfoUseCase getContentInfoUseCase; @Operation(summary = "컨텐츠를 생성합니다.") @PostMapping() @@ -33,7 +32,7 @@ public void createContent(@RequestBody CreateContentRequest createContentRequest @Operation(summary = "컨텐츠 내용을 가져옵니다.") @GetMapping(value = "/{contentId}") - public ContentTagResponse createContent(@PathVariable Long contentId) { + public ContentTagResponse getContent(@PathVariable Long contentId) { return getContentUseCase.execute(contentId); } @@ -49,4 +48,10 @@ public void updateContent( @PathVariable Long contentId, @RequestBody UpdateContentRequest request) { updateContentUseCase.execute(contentId, request); } + + @Operation(summary = "컨텐츠 정보 수정시 보여줄 정보를 가져옵니다.") + @GetMapping(value = "/{contentId}/info") + public ContentTagInfoResponse getContentInfo(@PathVariable Long contentId) { + return getContentInfoUseCase.execute(contentId); + } } diff --git a/Api/src/main/java/allchive/server/api/content/model/dto/response/ContentTagInfoResponse.java b/Api/src/main/java/allchive/server/api/content/model/dto/response/ContentTagInfoResponse.java new file mode 100644 index 00000000..1ab6ba09 --- /dev/null +++ b/Api/src/main/java/allchive/server/api/content/model/dto/response/ContentTagInfoResponse.java @@ -0,0 +1,96 @@ +package allchive.server.api.content.model.dto.response; + + +import allchive.server.api.common.util.UrlUtil; +import allchive.server.api.tag.model.dto.response.TagResponse; +import allchive.server.core.annotation.DateFormat; +import allchive.server.domain.domains.archiving.domain.Archiving; +import allchive.server.domain.domains.content.domain.Content; +import allchive.server.domain.domains.content.domain.enums.ContentType; +import io.swagger.v3.oas.annotations.media.Schema; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Builder; +import lombok.Getter; + +@Getter +public class ContentTagInfoResponse { + @Schema(description = "아카이빙 고유번호") + private Long archivingId; + + @Schema(description = "아카이빙 이름") + private String archivingTitle; + + @Schema(description = "컨텐츠 고유번호") + private Long contentId; + + @Schema(description = "컨텐츠 제목") + private String contentTitle; + + @Schema(description = "컨텐츠 종류") + private ContentType contentType; + + @Schema(description = "메모") + private String contentMemo; + + @Schema(defaultValue = "컨텐츠 링크", description = "컨텐츠 링크") + private String link; + + @Schema(defaultValue = "컨텐츠 이미지 url", description = "컨텐츠 이미지 url") + private String imgUrl; + + @Schema( + type = "string", + pattern = "yyyy.MM.dd", + defaultValue = "2023.07.02", + description = "컨텐츠 생성일자") + @DateFormat + private LocalDateTime contentCreatedAt; + + private List tagList; + + private Boolean isMine; + + @Builder + private ContentTagInfoResponse( + Long archivingId, + String archivingTitle, + Long contentId, + String contentTitle, + ContentType contentType, + String contentMemo, + String link, + String imgUrl, + LocalDateTime contentCreatedAt, + List tagList, + Boolean isMine) { + this.archivingId = archivingId; + this.archivingTitle = archivingTitle; + this.contentId = contentId; + this.contentTitle = contentTitle; + this.contentType = contentType; + this.contentMemo = contentMemo; + this.link = link; + this.imgUrl = imgUrl; + this.contentCreatedAt = contentCreatedAt; + this.tagList = tagList; + this.isMine = isMine; + } + + public static ContentTagInfoResponse of( + Archiving archiving, Content content, List tagList, Boolean isMine) { + return ContentTagInfoResponse.builder() + .archivingId(archiving.getId()) + .archivingTitle(archiving.getTitle()) + .contentId(content.getId()) + .contentTitle(content.getTitle()) + .contentType(content.getContentType()) + .contentMemo(content.getMemo()) + .link(content.getLinkUrl()) + .imgUrl(UrlUtil.toAssetUrl(content.getImageUrl())) + .contentCreatedAt(content.getCreatedAt()) + .tagList(tagList) + .isMine(isMine) + .build(); + } +} diff --git a/Api/src/main/java/allchive/server/api/content/model/mapper/ContentMapper.java b/Api/src/main/java/allchive/server/api/content/model/mapper/ContentMapper.java index f4dda5ed..c77faf34 100644 --- a/Api/src/main/java/allchive/server/api/content/model/mapper/ContentMapper.java +++ b/Api/src/main/java/allchive/server/api/content/model/mapper/ContentMapper.java @@ -4,9 +4,11 @@ import allchive.server.api.common.util.UrlUtil; import allchive.server.api.content.model.dto.request.CreateContentRequest; import allchive.server.api.content.model.dto.response.ContentResponse; +import allchive.server.api.content.model.dto.response.ContentTagInfoResponse; import allchive.server.api.content.model.dto.response.ContentTagResponse; import allchive.server.api.tag.model.dto.response.TagResponse; import allchive.server.core.annotation.Mapper; +import allchive.server.domain.domains.archiving.domain.Archiving; import allchive.server.domain.domains.content.domain.Content; import allchive.server.domain.domains.content.domain.ContentTagGroup; import allchive.server.domain.domains.content.domain.Tag; @@ -47,4 +49,16 @@ public ContentTagResponse toContentTagResponse( public List toContentTagGroupEntityList(Content content, List tags) { return tags.stream().map(tag -> ContentTagGroup.of(content, tag)).toList(); } + + public ContentTagInfoResponse toContentTagInfoResponse( + Archiving archiving, + Content content, + List contentTagGroupList, + Boolean isMine) { + List tagResponseList = + contentTagGroupList.stream() + .map(contentTagGroup -> TagResponse.from(contentTagGroup.getTag())) + .toList(); + return ContentTagInfoResponse.of(archiving, content, tagResponseList, isMine); + } } diff --git a/Api/src/main/java/allchive/server/api/content/service/GetContentInfoUseCase.java b/Api/src/main/java/allchive/server/api/content/service/GetContentInfoUseCase.java new file mode 100644 index 00000000..1229a76c --- /dev/null +++ b/Api/src/main/java/allchive/server/api/content/service/GetContentInfoUseCase.java @@ -0,0 +1,52 @@ +package allchive.server.api.content.service; + + +import allchive.server.api.config.security.SecurityUtil; +import allchive.server.api.content.model.dto.response.ContentTagInfoResponse; +import allchive.server.api.content.model.mapper.ContentMapper; +import allchive.server.core.annotation.UseCase; +import allchive.server.domain.domains.archiving.adaptor.ArchivingAdaptor; +import allchive.server.domain.domains.archiving.domain.Archiving; +import allchive.server.domain.domains.content.adaptor.ContentAdaptor; +import allchive.server.domain.domains.content.adaptor.ContentTagGroupAdaptor; +import allchive.server.domain.domains.content.domain.Content; +import allchive.server.domain.domains.content.domain.ContentTagGroup; +import allchive.server.domain.domains.content.validator.ContentValidator; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +@UseCase +@RequiredArgsConstructor +public class GetContentInfoUseCase { + private final ContentValidator contentValidator; + private final ContentAdaptor contentAdaptor; + private final ContentTagGroupAdaptor contentTagGroupAdaptor; + private final ContentMapper contentMapper; + private final ArchivingAdaptor archivingAdaptor; + + @Transactional(readOnly = true) + public ContentTagInfoResponse execute(Long contentId) { + Long userId = SecurityUtil.getCurrentUserId(); + validateExecution(contentId, userId); + Content content = contentAdaptor.findById(contentId); + Archiving archiving = archivingAdaptor.findById(content.getArchivingId()); + List contentTagGroupList = + contentTagGroupAdaptor.queryContentTagGroupByContentWithTag(content); + Boolean isMine = calculateIsMine(archiving, userId); + return contentMapper.toContentTagInfoResponse( + archiving, content, contentTagGroupList, isMine); + } + + private void validateExecution(Long contentId, Long userId) { + contentValidator.validatePublic(contentId, userId); + contentValidator.verifyUser(contentId, userId); + } + + private Boolean calculateIsMine(Archiving archiving, Long userId) { + if (archiving.getUserId().equals(userId)) { + return Boolean.TRUE; + } + return Boolean.FALSE; + } +} diff --git a/Api/src/main/java/allchive/server/api/content/service/GetContentUseCase.java b/Api/src/main/java/allchive/server/api/content/service/GetContentUseCase.java index fcccb107..93d24ead 100644 --- a/Api/src/main/java/allchive/server/api/content/service/GetContentUseCase.java +++ b/Api/src/main/java/allchive/server/api/content/service/GetContentUseCase.java @@ -7,7 +7,6 @@ import allchive.server.core.annotation.UseCase; import allchive.server.domain.domains.archiving.adaptor.ArchivingAdaptor; import allchive.server.domain.domains.archiving.domain.Archiving; -import allchive.server.domain.domains.archiving.validator.ArchivingValidator; import allchive.server.domain.domains.content.adaptor.ContentAdaptor; import allchive.server.domain.domains.content.adaptor.ContentTagGroupAdaptor; import allchive.server.domain.domains.content.domain.Content; @@ -20,7 +19,6 @@ @UseCase @RequiredArgsConstructor public class GetContentUseCase { - private final ArchivingValidator archivingValidator; private final ContentValidator contentValidator; private final ContentAdaptor contentAdaptor; private final ContentTagGroupAdaptor contentTagGroupAdaptor; From 971da20aff8b31d4793252d994ff72d55d3f8a01 Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Fri, 4 Aug 2023 12:37:48 +0900 Subject: [PATCH 17/34] =?UTF-8?q?[refac]=20exception=20=EC=84=B8=EB=B6=84?= =?UTF-8?q?=ED=99=94=20=EB=B0=8F=20validation=20=EC=A0=95=EB=A6=AC=20(#89)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [refac] archiving, content 소유자 response에 추가 #88 * [refac] archiving api validation exception 세분화 #88 * [refac] content api validation exception 세분화 #88 * [refac] recycle api validation exception 세분화 #88 * [refac] search api validation exception 세분화 #88 * [refac] user api validation exception 세분화 #88 * [refac] validation 정리 #88 * [chore] spotless 적용 #88 --- .../response/ArchivingContentsResponse.java | 6 +++++ .../service/GetArchivingContentsUseCase.java | 4 +-- .../service/GetArchivingInfoUseCase.java | 9 ++++--- .../service/UpdateArchivingPinUseCase.java | 9 ++----- .../service/UpdateArchivingScrapUseCase.java | 3 +-- .../dto/response/ContentTagResponse.java | 9 ++++++- .../content/model/mapper/ContentMapper.java | 7 +++-- .../content/service/CreateContentUseCase.java | 3 +-- .../content/service/GetContentUseCase.java | 3 ++- .../domains/archiving/domain/Archiving.java | 20 ++++++++++---- .../validator/ArchivingValidator.java | 26 +++++-------------- .../domains/content/domain/Content.java | 7 +++++ .../content/validator/ContentValidator.java | 5 +--- .../content/validator/TagValidator.java | 8 +----- .../domains/search/domain/LatestSearch.java | 7 +++++ .../validator/LatestSearchValidator.java | 8 +----- .../domain/domains/user/domain/User.java | 6 +++++ .../domains/user/validator/UserValidator.java | 6 +---- 18 files changed, 79 insertions(+), 67 deletions(-) diff --git a/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingContentsResponse.java b/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingContentsResponse.java index d4e14344..b25ee72e 100644 --- a/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingContentsResponse.java +++ b/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingContentsResponse.java @@ -21,6 +21,9 @@ public class ArchivingContentsResponse { @Schema(description = "아카이빙의 총 컨텐츠 개수") private Long totalContentsCount; + @Schema(description = "아카이빙 소유자 고유번호") + private Long ownerId; + @Schema(description = "유저 소유 여부") private Boolean isMine; @@ -30,11 +33,13 @@ private ArchivingContentsResponse( String archivingTitle, Long archivingId, Long totalContentsCount, + Long ownerId, Boolean isMine) { this.contents = contents; this.archivingTitle = archivingTitle; this.archivingId = archivingId; this.totalContentsCount = totalContentsCount; + this.ownerId = ownerId; this.isMine = isMine; } @@ -47,6 +52,7 @@ public static ArchivingContentsResponse of( .archivingTitle(archiving.getTitle()) .totalContentsCount(archiving.getScrapCnt() + archiving.getImgCnt()) .contents(contentResponseSlice) + .ownerId(archiving.getUserId()) .isMine(isMine) .build(); } diff --git a/Api/src/main/java/allchive/server/api/archiving/service/GetArchivingContentsUseCase.java b/Api/src/main/java/allchive/server/api/archiving/service/GetArchivingContentsUseCase.java index cc628be7..5dcb8aa7 100644 --- a/Api/src/main/java/allchive/server/api/archiving/service/GetArchivingContentsUseCase.java +++ b/Api/src/main/java/allchive/server/api/archiving/service/GetArchivingContentsUseCase.java @@ -43,8 +43,8 @@ public ArchivingContentsResponse execute(Long archivingId, Pageable pageable) { } private void validateExecution(Long archivingId, Long userId) { - archivingValidator.validatePublicStatus(archivingId, userId); - archivingValidator.validateDeleteStatus(archivingId, userId); + archivingValidator.validatePublic(archivingId, userId); + archivingValidator.validateNotDeleteExceptUser(archivingId, userId); } private Slice getContentResponseSlice(Long archivingId, Pageable pageable) { diff --git a/Api/src/main/java/allchive/server/api/archiving/service/GetArchivingInfoUseCase.java b/Api/src/main/java/allchive/server/api/archiving/service/GetArchivingInfoUseCase.java index 1107df6e..4da59f70 100644 --- a/Api/src/main/java/allchive/server/api/archiving/service/GetArchivingInfoUseCase.java +++ b/Api/src/main/java/allchive/server/api/archiving/service/GetArchivingInfoUseCase.java @@ -15,11 +15,14 @@ public class GetArchivingInfoUseCase { private final ArchivingValidator archivingValidator; private final ArchivingAdaptor archivingAdaptor; - @Transactional + @Transactional(readOnly = true) public ArchivingResponse execute(Long archivingId) { - archivingValidator.validateExistById(archivingId); - + validateExecution(archivingId); Archiving archiving = archivingAdaptor.findById(archivingId); return ArchivingResponse.of(archiving, Boolean.FALSE); } + + private void validateExecution(Long archivingId) { + archivingValidator.validateExistById(archivingId); + } } diff --git a/Api/src/main/java/allchive/server/api/archiving/service/UpdateArchivingPinUseCase.java b/Api/src/main/java/allchive/server/api/archiving/service/UpdateArchivingPinUseCase.java index 5108bc34..4534daf7 100644 --- a/Api/src/main/java/allchive/server/api/archiving/service/UpdateArchivingPinUseCase.java +++ b/Api/src/main/java/allchive/server/api/archiving/service/UpdateArchivingPinUseCase.java @@ -18,16 +18,11 @@ public class UpdateArchivingPinUseCase { public void execute(Long archivingId, Boolean cancel) { Long userId = SecurityUtil.getCurrentUserId(); validateExecution(archivingId, userId, cancel); - if (cancel) { - archivingDomainService.updatePin(archivingId, userId, false); - } else { - archivingDomainService.updatePin(archivingId, userId, true); - } + archivingDomainService.updatePin(archivingId, userId, !cancel); } private void validateExecution(Long archivingId, Long userId, Boolean cancel) { - archivingValidator.validateExistById(archivingId); - archivingValidator.validateDeleteStatus(archivingId, userId); + archivingValidator.validateNotDeleteExceptUser(archivingId, userId); if (cancel) { archivingValidator.validateNotPinStatus(archivingId, userId); } else { diff --git a/Api/src/main/java/allchive/server/api/archiving/service/UpdateArchivingScrapUseCase.java b/Api/src/main/java/allchive/server/api/archiving/service/UpdateArchivingScrapUseCase.java index 88ba1f21..5d6dbffe 100644 --- a/Api/src/main/java/allchive/server/api/archiving/service/UpdateArchivingScrapUseCase.java +++ b/Api/src/main/java/allchive/server/api/archiving/service/UpdateArchivingScrapUseCase.java @@ -38,8 +38,7 @@ public void execute(Long archivingId, Boolean cancel) { } private void validateExecution(Long archivingId, Long userId, Boolean cancel) { - archivingValidator.validateExistById(archivingId); - archivingValidator.validateDeleteStatus(archivingId, userId); + archivingValidator.validateNotDeleteExceptUser(archivingId, userId); if (cancel) { scrapValidator.validateExistScrap(userId, archivingId); } else { diff --git a/Api/src/main/java/allchive/server/api/content/model/dto/response/ContentTagResponse.java b/Api/src/main/java/allchive/server/api/content/model/dto/response/ContentTagResponse.java index 398b5259..e9cc6bf8 100644 --- a/Api/src/main/java/allchive/server/api/content/model/dto/response/ContentTagResponse.java +++ b/Api/src/main/java/allchive/server/api/content/model/dto/response/ContentTagResponse.java @@ -42,6 +42,10 @@ public class ContentTagResponse { private List tagList; + @Schema(description = "컨텐츠 소유자 고유번호") + private Long ownerId; + + @Schema(description = "유저 소유 여부") private Boolean isMine; @Builder @@ -54,6 +58,7 @@ private ContentTagResponse( String imgUrl, LocalDateTime contentCreatedAt, List tagList, + Long ownerId, Boolean isMine) { this.contentId = contentId; this.contentTitle = contentTitle; @@ -63,11 +68,12 @@ private ContentTagResponse( this.imgUrl = imgUrl; this.contentCreatedAt = contentCreatedAt; this.tagList = tagList; + this.ownerId = ownerId; this.isMine = isMine; } public static ContentTagResponse of( - Content content, List tagList, Boolean isMine) { + Content content, List tagList, Boolean isMine, Long ownerId) { return ContentTagResponse.builder() .contentId(content.getId()) .contentTitle(content.getTitle()) @@ -77,6 +83,7 @@ public static ContentTagResponse of( .imgUrl(UrlUtil.toAssetUrl(content.getImageUrl())) .contentCreatedAt(content.getCreatedAt()) .tagList(tagList) + .ownerId(ownerId) .isMine(isMine) .build(); } diff --git a/Api/src/main/java/allchive/server/api/content/model/mapper/ContentMapper.java b/Api/src/main/java/allchive/server/api/content/model/mapper/ContentMapper.java index c77faf34..987503bb 100644 --- a/Api/src/main/java/allchive/server/api/content/model/mapper/ContentMapper.java +++ b/Api/src/main/java/allchive/server/api/content/model/mapper/ContentMapper.java @@ -38,12 +38,15 @@ public Content toEntity(CreateContentRequest request) { } public ContentTagResponse toContentTagResponse( - Content content, List contentTagGroupList, Boolean isMine) { + Content content, + List contentTagGroupList, + Boolean isMine, + Long ownerId) { List tagResponseList = contentTagGroupList.stream() .map(contentTagGroup -> TagResponse.from(contentTagGroup.getTag())) .toList(); - return ContentTagResponse.of(content, tagResponseList, isMine); + return ContentTagResponse.of(content, tagResponseList, isMine, ownerId); } public List toContentTagGroupEntityList(Content content, List tags) { diff --git a/Api/src/main/java/allchive/server/api/content/service/CreateContentUseCase.java b/Api/src/main/java/allchive/server/api/content/service/CreateContentUseCase.java index d65c3978..14e3b58f 100644 --- a/Api/src/main/java/allchive/server/api/content/service/CreateContentUseCase.java +++ b/Api/src/main/java/allchive/server/api/content/service/CreateContentUseCase.java @@ -40,8 +40,7 @@ public void execute(CreateContentRequest request) { private void validateExecution(CreateContentRequest request) { Long userId = SecurityUtil.getCurrentUserId(); - archivingValidator.validateExistById(request.getArchivingId()); - archivingValidator.verifyUser(request.getArchivingId(), userId); + archivingValidator.verifyUser(userId, request.getArchivingId()); tagValidator.validateExistTagsAndUser(request.getTagIds(), userId); } diff --git a/Api/src/main/java/allchive/server/api/content/service/GetContentUseCase.java b/Api/src/main/java/allchive/server/api/content/service/GetContentUseCase.java index 93d24ead..819cac37 100644 --- a/Api/src/main/java/allchive/server/api/content/service/GetContentUseCase.java +++ b/Api/src/main/java/allchive/server/api/content/service/GetContentUseCase.java @@ -30,10 +30,11 @@ public ContentTagResponse execute(Long contentId) { Long userId = SecurityUtil.getCurrentUserId(); validateExecution(contentId, userId); Content content = contentAdaptor.findById(contentId); + Long ownerId = archivingAdaptor.findById(content.getArchivingId()).getUserId(); List contentTagGroupList = contentTagGroupAdaptor.queryContentTagGroupByContentWithTag(content); Boolean isMine = calculateIsMine(content.getArchivingId(), userId); - return contentMapper.toContentTagResponse(content, contentTagGroupList, isMine); + return contentMapper.toContentTagResponse(content, contentTagGroupList, isMine, ownerId); } private void validateExecution(Long contentId, Long userId) { diff --git a/Domain/src/main/java/allchive/server/domain/domains/archiving/domain/Archiving.java b/Domain/src/main/java/allchive/server/domain/domains/archiving/domain/Archiving.java index 8504354e..f5ddbb50 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/archiving/domain/Archiving.java +++ b/Domain/src/main/java/allchive/server/domain/domains/archiving/domain/Archiving.java @@ -3,9 +3,7 @@ import allchive.server.domain.common.model.BaseTimeEntity; import allchive.server.domain.domains.archiving.domain.enums.Category; -import allchive.server.domain.domains.archiving.exception.exceptions.DeletedArchivingException; -import allchive.server.domain.domains.archiving.exception.exceptions.NoAuthurityUpdateArchivingException; -import allchive.server.domain.domains.archiving.exception.exceptions.NotPublicArchivingException; +import allchive.server.domain.domains.archiving.exception.exceptions.*; import java.util.ArrayList; import java.util.List; import javax.persistence.*; @@ -85,13 +83,13 @@ public void validateUser(Long userId) { } } - public void validatePublicStatus(Long userId) { + public void validatePublic(Long userId) { if (!this.publicStatus && !this.userId.equals(userId)) { throw NotPublicArchivingException.EXCEPTION; } } - public void validateDeleteStatus(Long userId) { + public void validateNotDeleteExceptUser(Long userId) { if (this.deleteStatus && !this.userId.equals(userId)) { throw DeletedArchivingException.EXCEPTION; } @@ -130,4 +128,16 @@ public void validateNotDelete() { throw DeletedArchivingException.EXCEPTION; } } + + public void validateAlreadyPinStatus(Long userId) { + if (this.pinUserId.contains(userId)) { + throw AlreadyPinnedArchivingException.EXCEPTION; + } + } + + public void validateNotPinStatus(Long userId) { + if (!this.pinUserId.contains(userId)) { + throw NotPinnedArchivingException.EXCEPTION; + } + } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/archiving/validator/ArchivingValidator.java b/Domain/src/main/java/allchive/server/domain/domains/archiving/validator/ArchivingValidator.java index befa4fd0..f53e8c41 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/archiving/validator/ArchivingValidator.java +++ b/Domain/src/main/java/allchive/server/domain/domains/archiving/validator/ArchivingValidator.java @@ -4,10 +4,7 @@ import allchive.server.core.annotation.Validator; import allchive.server.domain.domains.archiving.adaptor.ArchivingAdaptor; import allchive.server.domain.domains.archiving.domain.Archiving; -import allchive.server.domain.domains.archiving.exception.exceptions.AlreadyPinnedArchivingException; import allchive.server.domain.domains.archiving.exception.exceptions.ArchivingNotFoundException; -import allchive.server.domain.domains.archiving.exception.exceptions.NoAuthurityUpdateArchivingException; -import allchive.server.domain.domains.archiving.exception.exceptions.NotPinnedArchivingException; import java.util.List; import lombok.RequiredArgsConstructor; @@ -20,12 +17,12 @@ public void verifyUser(Long userId, Long archivingId) { archivingAdaptor.findById(archivingId).validateUser(userId); } - public void validatePublicStatus(Long archivingId, Long userId) { - archivingAdaptor.findById(archivingId).validatePublicStatus(userId); + public void validatePublic(Long archivingId, Long userId) { + archivingAdaptor.findById(archivingId).validatePublic(userId); } - public void validateDeleteStatus(Long archivingId, Long userId) { - archivingAdaptor.findById(archivingId).validateDeleteStatus(userId); + public void validateNotDeleteExceptUser(Long archivingId, Long userId) { + archivingAdaptor.findById(archivingId).validateNotDeleteExceptUser(userId); } public void validateExistById(Long archivingId) { @@ -35,15 +32,11 @@ public void validateExistById(Long archivingId) { } public void validateAlreadyPinStatus(Long archivingId, Long userId) { - if (archivingAdaptor.findById(archivingId).getPinUserId().contains(userId)) { - throw AlreadyPinnedArchivingException.EXCEPTION; - } + archivingAdaptor.findById(archivingId).validateAlreadyPinStatus(userId); } public void validateNotPinStatus(Long archivingId, Long userId) { - if (!archivingAdaptor.findById(archivingId).getPinUserId().contains(userId)) { - throw NotPinnedArchivingException.EXCEPTION; - } + archivingAdaptor.findById(archivingId).validateNotPinStatus(userId); } public void validateExistInIdList(List archivingIdList) { @@ -55,12 +48,7 @@ public void validateExistInIdList(List archivingIdList) { public void verifyUserInIdList(Long userId, List archivingIds) { List archivingList = archivingAdaptor.findAllByIdIn(archivingIds); - archivingList.forEach( - archiving -> { - if (!archiving.getUserId().equals(userId)) { - throw NoAuthurityUpdateArchivingException.EXCEPTION; - } - }); + archivingList.forEach(archiving -> archiving.validateUser(userId)); } public void validateNotDeleted(Long archivingId) { diff --git a/Domain/src/main/java/allchive/server/domain/domains/content/domain/Content.java b/Domain/src/main/java/allchive/server/domain/domains/content/domain/Content.java index 7d1280d5..b33e3f29 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/content/domain/Content.java +++ b/Domain/src/main/java/allchive/server/domain/domains/content/domain/Content.java @@ -3,6 +3,7 @@ import allchive.server.domain.common.model.BaseTimeEntity; import allchive.server.domain.domains.content.domain.enums.ContentType; +import allchive.server.domain.domains.content.exception.exceptions.AlreadyDeletedContentException; import javax.persistence.*; import lombok.AccessLevel; import lombok.Builder; @@ -89,4 +90,10 @@ public void updateImageContent(Long archivingId, String imgUrl, String title, St this.title = title; this.memo = memo; } + + public void validateNotDelete() { + if (this.isDeleteStatus()) { + throw AlreadyDeletedContentException.EXCEPTION; + } + } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/content/validator/ContentValidator.java b/Domain/src/main/java/allchive/server/domain/domains/content/validator/ContentValidator.java index 6fc83f80..43b0413a 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/content/validator/ContentValidator.java +++ b/Domain/src/main/java/allchive/server/domain/domains/content/validator/ContentValidator.java @@ -6,7 +6,6 @@ import allchive.server.domain.domains.archiving.domain.Archiving; import allchive.server.domain.domains.content.adaptor.ContentAdaptor; import allchive.server.domain.domains.content.domain.Content; -import allchive.server.domain.domains.content.exception.exceptions.AlreadyDeletedContentException; import allchive.server.domain.domains.content.exception.exceptions.ContentNotFoundException; import allchive.server.domain.domains.content.exception.exceptions.NoAuthorityUpdateContentException; import allchive.server.domain.domains.content.exception.exceptions.NotPublicContentException; @@ -56,9 +55,7 @@ public void verifyUser(Long contentId, Long userId) { } public void validateNotDelete(Long contentId) { - if (contentAdaptor.findById(contentId).isDeleteStatus()) { - throw AlreadyDeletedContentException.EXCEPTION; - } + contentAdaptor.findById(contentId).validateNotDelete(); } public void validatePublic(Long contentId, Long userId) { diff --git a/Domain/src/main/java/allchive/server/domain/domains/content/validator/TagValidator.java b/Domain/src/main/java/allchive/server/domain/domains/content/validator/TagValidator.java index af25a203..305d7e89 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/content/validator/TagValidator.java +++ b/Domain/src/main/java/allchive/server/domain/domains/content/validator/TagValidator.java @@ -4,7 +4,6 @@ import allchive.server.core.annotation.Validator; import allchive.server.domain.domains.content.adaptor.TagAdaptor; import allchive.server.domain.domains.content.domain.Tag; -import allchive.server.domain.domains.content.exception.exceptions.NoAuthorityUpdateTagException; import allchive.server.domain.domains.content.exception.exceptions.TagNotFoundException; import java.util.List; import lombok.RequiredArgsConstructor; @@ -23,11 +22,6 @@ public void validateExistTagsAndUser(List tagIds, Long userId) { if (tagIds.size() != tags.size()) { throw TagNotFoundException.EXCEPTION; } - tags.forEach( - tag -> { - if (!tag.getUserId().equals(userId)) { - throw NoAuthorityUpdateTagException.EXCEPTION; - } - }); + tags.forEach(tag -> tag.validateUser(userId)); } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/search/domain/LatestSearch.java b/Domain/src/main/java/allchive/server/domain/domains/search/domain/LatestSearch.java index 78b88f36..6f36edbd 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/search/domain/LatestSearch.java +++ b/Domain/src/main/java/allchive/server/domain/domains/search/domain/LatestSearch.java @@ -2,6 +2,7 @@ import allchive.server.domain.common.model.BaseTimeEntity; +import allchive.server.domain.domains.search.exception.exceptions.NoAuthorityUpdateLatestSearchException; import javax.persistence.*; import lombok.AccessLevel; import lombok.Builder; @@ -30,4 +31,10 @@ private LatestSearch(String keyword, Long userId) { public static LatestSearch of(String keyword, Long userId) { return LatestSearch.builder().keyword(keyword).userId(userId).build(); } + + public void validateUser(Long userId) { + if (!this.userId.equals(userId)) { + throw NoAuthorityUpdateLatestSearchException.EXCEPTION; + } + } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/search/validator/LatestSearchValidator.java b/Domain/src/main/java/allchive/server/domain/domains/search/validator/LatestSearchValidator.java index 4829967c..7e26fd0a 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/search/validator/LatestSearchValidator.java +++ b/Domain/src/main/java/allchive/server/domain/domains/search/validator/LatestSearchValidator.java @@ -5,7 +5,6 @@ import allchive.server.domain.domains.search.adaptor.LatestSearchAdaptor; import allchive.server.domain.domains.search.domain.LatestSearch; import allchive.server.domain.domains.search.exception.exceptions.LatestSearchNotFoundException; -import allchive.server.domain.domains.search.exception.exceptions.NoAuthorityUpdateLatestSearchException; import java.util.List; import lombok.RequiredArgsConstructor; @@ -23,11 +22,6 @@ public void validateExistByIdIn(List ids) { public void verifyUserByIdIn(List ids, Long userId) { List searches = latestSearchAdaptor.findAllByIdIn(ids); - searches.forEach( - search -> { - if (!search.getUserId().equals(userId)) { - throw NoAuthorityUpdateLatestSearchException.EXCEPTION; - } - }); + searches.forEach(search -> search.validateUser(userId)); } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/user/domain/User.java b/Domain/src/main/java/allchive/server/domain/domains/user/domain/User.java index 16aa572e..1e253f05 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/user/domain/User.java +++ b/Domain/src/main/java/allchive/server/domain/domains/user/domain/User.java @@ -112,4 +112,10 @@ public void updateInfo(String name, String email, String nickname, String imgUrl this.nickname = nickname; this.profileImgUrl = imgUrl; } + + public void validateUserStateNormal() { + if (!this.userState.equals(UserState.NORMAL)) { + throw ForbiddenUserException.EXCEPTION; + } + } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/user/validator/UserValidator.java b/Domain/src/main/java/allchive/server/domain/domains/user/validator/UserValidator.java index d5d08514..866e67fb 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/user/validator/UserValidator.java +++ b/Domain/src/main/java/allchive/server/domain/domains/user/validator/UserValidator.java @@ -4,9 +4,7 @@ import allchive.server.core.annotation.Validator; import allchive.server.domain.domains.user.adaptor.UserAdaptor; import allchive.server.domain.domains.user.domain.enums.OauthInfo; -import allchive.server.domain.domains.user.domain.enums.UserState; import allchive.server.domain.domains.user.exception.exceptions.AlreadySignUpUserException; -import allchive.server.domain.domains.user.exception.exceptions.ForbiddenUserException; import allchive.server.domain.domains.user.exception.exceptions.UserNotFoundException; import lombok.RequiredArgsConstructor; @@ -24,9 +22,7 @@ public Boolean checkUserCanRegister(OauthInfo oauthInfo) { } public void validateUserStatusNormal(Long userId) { - if (!userAdaptor.findById(userId).getUserState().equals(UserState.NORMAL)) { - throw ForbiddenUserException.EXCEPTION; - } + userAdaptor.findById(userId).validateUserStateNormal(); } public void validateExist(Long userId) { From ba759cbef5ab3e918db7ed9225a32b781836a6cb Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Fri, 4 Aug 2023 16:06:35 +0900 Subject: [PATCH 18/34] =?UTF-8?q?[fix]=20=EC=BB=A8=ED=85=90=EC=B8=A0=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=EC=8B=9C=20=EC=95=84=EC=B9=B4=EC=9D=B4?= =?UTF-8?q?=EB=B9=99=20count=20=EA=B0=9C=EC=88=98=20=EC=95=88=EB=B3=80?= =?UTF-8?q?=ED=95=A8=20(#91)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [fix] 컨텐츠 수정 count 로직 추가 #90 * [chore] spotless 적용 #90 * [refac] const 적용 #90 --- .../service/UpdateArchivingScrapUseCase.java | 7 +++++-- .../content/service/CreateContentUseCase.java | 4 +++- .../content/service/UpdateContentUseCase.java | 17 +++++++++++++++++ .../api/user/model/mapper/UserMapper.java | 5 ++++- .../server/core/consts/AllchiveConst.java | 4 ++++ .../ArchivingCustomRepositoryImpl.java | 11 ++++++----- .../service/ArchivingDomainService.java | 11 +++++++---- 7 files changed, 46 insertions(+), 13 deletions(-) diff --git a/Api/src/main/java/allchive/server/api/archiving/service/UpdateArchivingScrapUseCase.java b/Api/src/main/java/allchive/server/api/archiving/service/UpdateArchivingScrapUseCase.java index 5d6dbffe..61ffb4fb 100644 --- a/Api/src/main/java/allchive/server/api/archiving/service/UpdateArchivingScrapUseCase.java +++ b/Api/src/main/java/allchive/server/api/archiving/service/UpdateArchivingScrapUseCase.java @@ -13,6 +13,9 @@ import lombok.RequiredArgsConstructor; import org.springframework.transaction.annotation.Transactional; +import static allchive.server.core.consts.AllchiveConst.MINUS_ONE; +import static allchive.server.core.consts.AllchiveConst.PLUS_ONE; + @UseCase @RequiredArgsConstructor public class UpdateArchivingScrapUseCase { @@ -29,11 +32,11 @@ public void execute(Long archivingId, Boolean cancel) { User user = userAdaptor.findById(userId); if (cancel) { scrapDomainService.deleteScrapByUserAndArchivingId(user, archivingId); - archivingDomainService.updateScrapCount(archivingId, -1); + archivingDomainService.updateScrapCount(archivingId, MINUS_ONE); } else { Scrap scrap = Scrap.of(user, archivingId); scrapDomainService.save(scrap); - archivingDomainService.updateScrapCount(archivingId, 1); + archivingDomainService.updateScrapCount(archivingId, PLUS_ONE); } } diff --git a/Api/src/main/java/allchive/server/api/content/service/CreateContentUseCase.java b/Api/src/main/java/allchive/server/api/content/service/CreateContentUseCase.java index 14e3b58f..b590ab8c 100644 --- a/Api/src/main/java/allchive/server/api/content/service/CreateContentUseCase.java +++ b/Api/src/main/java/allchive/server/api/content/service/CreateContentUseCase.java @@ -1,5 +1,6 @@ package allchive.server.api.content.service; +import static allchive.server.core.consts.AllchiveConst.PLUS_ONE; import allchive.server.api.config.security.SecurityUtil; import allchive.server.api.content.model.dto.request.CreateContentRequest; @@ -35,7 +36,8 @@ public void execute(CreateContentRequest request) { Content content = contentMapper.toEntity(request); createContentTagGroup(content, request.getTagIds()); contentDomainService.save(content); - archivingDomainService.updateContentCnt(request.getArchivingId(), request.getContentType()); + archivingDomainService.updateContentCnt( + request.getArchivingId(), request.getContentType(), PLUS_ONE); } private void validateExecution(CreateContentRequest request) { diff --git a/Api/src/main/java/allchive/server/api/content/service/UpdateContentUseCase.java b/Api/src/main/java/allchive/server/api/content/service/UpdateContentUseCase.java index b2286199..6f359b47 100644 --- a/Api/src/main/java/allchive/server/api/content/service/UpdateContentUseCase.java +++ b/Api/src/main/java/allchive/server/api/content/service/UpdateContentUseCase.java @@ -1,16 +1,21 @@ package allchive.server.api.content.service; +import static allchive.server.core.consts.AllchiveConst.MINUS_ONE; +import static allchive.server.core.consts.AllchiveConst.PLUS_ONE; import allchive.server.api.common.util.UrlUtil; import allchive.server.api.config.security.SecurityUtil; import allchive.server.api.content.model.dto.request.UpdateContentRequest; import allchive.server.api.content.model.mapper.ContentMapper; import allchive.server.core.annotation.UseCase; +import allchive.server.domain.domains.archiving.adaptor.ArchivingAdaptor; +import allchive.server.domain.domains.archiving.service.ArchivingDomainService; import allchive.server.domain.domains.content.adaptor.ContentAdaptor; import allchive.server.domain.domains.content.adaptor.TagAdaptor; import allchive.server.domain.domains.content.domain.Content; import allchive.server.domain.domains.content.domain.ContentTagGroup; import allchive.server.domain.domains.content.domain.Tag; +import allchive.server.domain.domains.content.domain.enums.ContentType; import allchive.server.domain.domains.content.service.ContentDomainService; import allchive.server.domain.domains.content.service.ContentTagGroupDomainService; import allchive.server.domain.domains.content.validator.ContentValidator; @@ -29,11 +34,14 @@ public class UpdateContentUseCase { private final ContentMapper contentMapper; private final ContentDomainService contentDomainService; private final ContentTagGroupDomainService contentTagGroupDomainService; + private final ArchivingDomainService archivingDomainService; + private final ArchivingAdaptor archivingAdaptor; @Transactional public void execute(Long contentId, UpdateContentRequest request) { validateExecution(contentId, request); regenerateContentTagGroup(contentId, request.getTagIds()); + updateArchiving(contentId, request.getArchivingId(), request.getContentType()); contentDomainService.update( contentId, request.getContentType(), @@ -44,6 +52,15 @@ public void execute(Long contentId, UpdateContentRequest request) { request.getTitle()); } + private void updateArchiving(Long contentId, Long newArchivingId, ContentType contentType) { + Content content = contentAdaptor.findById(contentId); + if (!content.getArchivingId().equals(newArchivingId)) { + archivingDomainService.updateContentCnt( + content.getArchivingId(), content.getContentType(), MINUS_ONE); + archivingDomainService.updateContentCnt(newArchivingId, contentType, PLUS_ONE); + } + } + private void validateExecution(Long contentId, UpdateContentRequest request) { Long userId = SecurityUtil.getCurrentUserId(); contentValidator.verifyUser(contentId, userId); diff --git a/Api/src/main/java/allchive/server/api/user/model/mapper/UserMapper.java b/Api/src/main/java/allchive/server/api/user/model/mapper/UserMapper.java index ebd1fe40..5254d912 100644 --- a/Api/src/main/java/allchive/server/api/user/model/mapper/UserMapper.java +++ b/Api/src/main/java/allchive/server/api/user/model/mapper/UserMapper.java @@ -7,6 +7,9 @@ import allchive.server.domain.domains.user.domain.User; import java.util.List; +import static allchive.server.core.consts.AllchiveConst.PLUS_ONE; +import static allchive.server.core.consts.AllchiveConst.ZERO; + @Mapper public class UserMapper { public GetUserProfileResponse toGetUserProfileResponse( @@ -15,7 +18,7 @@ public GetUserProfileResponse toGetUserProfileResponse( for (Archiving archiving : archivingList) { linkCount += archiving.getLinkCnt(); imgCount += archiving.getImgCnt(); - publicArchivingCount += archiving.getPublicStatus() ? 1 : 0; + publicArchivingCount += archiving.getPublicStatus() ? PLUS_ONE : ZERO; } return GetUserProfileResponse.of( user, linkCount, imgCount, publicArchivingCount, archivingList.size()); diff --git a/Core/src/main/java/allchive/server/core/consts/AllchiveConst.java b/Core/src/main/java/allchive/server/core/consts/AllchiveConst.java index 2a762c23..e5f1a45e 100644 --- a/Core/src/main/java/allchive/server/core/consts/AllchiveConst.java +++ b/Core/src/main/java/allchive/server/core/consts/AllchiveConst.java @@ -40,4 +40,8 @@ public class AllchiveConst { public static final String SEARCH_KEY = "ARCHIVING_TITLE"; public static final String ASTERISK = "*"; + + public static final int PLUS_ONE = 1; + public static final int MINUS_ONE = -1; + public static final int ZERO = 0; } diff --git a/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepositoryImpl.java b/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepositoryImpl.java index f1d64d47..806fad25 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepositoryImpl.java +++ b/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepositoryImpl.java @@ -1,5 +1,6 @@ package allchive.server.domain.domains.archiving.repository; +import static allchive.server.core.consts.AllchiveConst.PLUS_ONE; import static allchive.server.domain.domains.archiving.domain.QArchiving.archiving; import allchive.server.domain.common.util.SliceUtil; @@ -38,7 +39,7 @@ public Slice querySliceArchivingExceptBlock( deleteStatusFalse()) .orderBy(scrabListDesc(archivingIdList), scrapCntDesc(), createdAtDesc()) .offset(pageable.getOffset()) - .limit(pageable.getPageSize() + 1) + .limit(pageable.getPageSize() + PLUS_ONE) .fetch(); return SliceUtil.toSlice(archivings, pageable); } @@ -53,7 +54,7 @@ public Slice querySliceArchivingByUserId( .where(userIdEq(userId), categoryEq(category), deleteStatusFalse()) .orderBy(pinDesc(userId), scrapCntDesc(), createdAtDesc()) .offset(pageable.getOffset()) - .limit(pageable.getPageSize() + 1) + .limit(pageable.getPageSize() + PLUS_ONE) .fetch(); return SliceUtil.toSlice(archivings, pageable); } @@ -72,7 +73,7 @@ public Slice querySliceArchivingByIdIn( deleteStatusFalse()) .orderBy(scrapCntDesc(), createdAtDesc()) .offset(pageable.getOffset()) - .limit(pageable.getPageSize() + 1) + .limit(pageable.getPageSize() + PLUS_ONE) .fetch(); return SliceUtil.toSlice(archivings, pageable); } @@ -102,7 +103,7 @@ public Slice querySliceArchivingByUserIdAndKeywordsOrderByTagArchving .where(userIdEq(userId), titleContainOrIdIn(keyword, tagArchivingIds)) .orderBy(idIn(tagArchivingIds), createdAtDesc()) .offset(pageable.getOffset()) - .limit(pageable.getPageSize() + 1) + .limit(pageable.getPageSize() + PLUS_ONE) .fetch(); return SliceUtil.toSlice(archivings, pageable); } @@ -129,7 +130,7 @@ public Slice querySliceArchivingByKeywordExceptBlockOrderByTagArchvin scrapCntDesc(), createdAtDesc()) .offset(pageable.getOffset()) - .limit(pageable.getPageSize() + 1) + .limit(pageable.getPageSize() + PLUS_ONE) .fetch(); return SliceUtil.toSlice(archivings, pageable); } diff --git a/Domain/src/main/java/allchive/server/domain/domains/archiving/service/ArchivingDomainService.java b/Domain/src/main/java/allchive/server/domain/domains/archiving/service/ArchivingDomainService.java index e55eaf9e..d29c4a35 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/archiving/service/ArchivingDomainService.java +++ b/Domain/src/main/java/allchive/server/domain/domains/archiving/service/ArchivingDomainService.java @@ -9,6 +9,9 @@ import java.util.List; import lombok.RequiredArgsConstructor; +import static allchive.server.core.consts.AllchiveConst.MINUS_ONE; +import static allchive.server.core.consts.AllchiveConst.PLUS_ONE; + @DomainService @RequiredArgsConstructor public class ArchivingDomainService { @@ -41,7 +44,7 @@ public void updatePin(Long archivingId, Long userId, boolean pin) { } else { archiving.deletePinUserId(userId); } - archiving.updateScrapCnt(pin ? 1 : -1); + archiving.updateScrapCnt(pin ? PLUS_ONE : MINUS_ONE); } public void softDeleteById(Long archivingId) { @@ -60,12 +63,12 @@ public void deleteAllById(List archivingIds) { archivingAdaptor.deleteAllById(archivingIds); } - public void updateContentCnt(Long archivingId, ContentType contentType) { + public void updateContentCnt(Long archivingId, ContentType contentType, int i) { Archiving archiving = archivingAdaptor.findById(archivingId); if (contentType.equals(ContentType.IMAGE)) { - archiving.updateImgCnt(1); + archiving.updateImgCnt(i); } else { - archiving.updateLinkCnt(1); + archiving.updateLinkCnt(i); } } } From d18b1f464270492bc6db45d9e8b98995672bc6d9 Mon Sep 17 00:00:00 2001 From: wjdtkdgns Date: Fri, 4 Aug 2023 16:21:15 +0900 Subject: [PATCH 19/34] =?UTF-8?q?[fix]=20=EC=9C=A0=EC=A0=80=20presigned=20?= =?UTF-8?q?url=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/api/image/controller/ImageController.java | 3 +-- .../infrastructure/s3/service/S3PresignedUrlService.java | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Api/src/main/java/allchive/server/api/image/controller/ImageController.java b/Api/src/main/java/allchive/server/api/image/controller/ImageController.java index d643c3e4..8b18bcf4 100644 --- a/Api/src/main/java/allchive/server/api/image/controller/ImageController.java +++ b/Api/src/main/java/allchive/server/api/image/controller/ImageController.java @@ -38,8 +38,7 @@ public ImageUrlResponse getContentPresignedUrl() { @Operation(summary = "컨텐츠 관련 이미지 업로드 url 요청할수 있는 api 입니다.") @GetMapping(value = "/user/image") public ImageUrlResponse getUserPresignedUrl() { - Long userId = SecurityUtil.getCurrentUserId(); return ImageUrlResponse.from( - s3PresignedUrlService.getPreSignedUrl(userId, PresignedType.USER)); + s3PresignedUrlService.getPreSignedUrl(0L, PresignedType.USER)); } } diff --git a/Infrastructure/src/main/java/allchive/server/infrastructure/s3/service/S3PresignedUrlService.java b/Infrastructure/src/main/java/allchive/server/infrastructure/s3/service/S3PresignedUrlService.java index c8f1186a..81bd68ac 100644 --- a/Infrastructure/src/main/java/allchive/server/infrastructure/s3/service/S3PresignedUrlService.java +++ b/Infrastructure/src/main/java/allchive/server/infrastructure/s3/service/S3PresignedUrlService.java @@ -40,11 +40,11 @@ private String generateFileName(Long id, PresignedType presignedType) { String fileName; switch (presignedType) { case USER -> fileName = baseUrl + "/user/"; - case CONTENT -> fileName = baseUrl + "/content/"; - case ARCHIVING -> fileName = baseUrl + "/archiving/"; + case CONTENT -> fileName = baseUrl + "/content/" + id.toString(); + case ARCHIVING -> fileName = baseUrl + "/archiving/" + id.toString(); default -> throw InternalServerError.EXCEPTION; } - return fileName + id.toString() + "/" + UUID.randomUUID(); + return fileName + "/" + UUID.randomUUID(); } private GeneratePresignedUrlRequest getGeneratePreSignedUrlRequest(String fileName) { From 718b9622eb34bce0e069d068a2021beeda59c993 Mon Sep 17 00:00:00 2001 From: wjdtkdgns Date: Mon, 7 Aug 2023 12:38:03 +0900 Subject: [PATCH 20/34] =?UTF-8?q?[fix]=20asset=20url=20return=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../allchive/server/api/common/util/UrlUtil.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Api/src/main/java/allchive/server/api/common/util/UrlUtil.java b/Api/src/main/java/allchive/server/api/common/util/UrlUtil.java index 633c3347..a84654fa 100644 --- a/Api/src/main/java/allchive/server/api/common/util/UrlUtil.java +++ b/Api/src/main/java/allchive/server/api/common/util/UrlUtil.java @@ -16,13 +16,14 @@ private UrlUtil(SpringEnvironmentHelper springEnvironmentHelper) { } public static String toAssetUrl(String key) { - if (key.equals("")) { - return ""; - } - if (springEnvironmentHelper.isProdProfile()) { - return PROD_ASSET_URL + key; - } - return STAGING_ASSET_URL + key; +// if (key.equals("")) { +// return ""; +// } +// if (springEnvironmentHelper.isProdProfile()) { +// return PROD_ASSET_URL + key; +// } +// return STAGING_ASSET_URL + key; + return key; } public static String convertUrlToKey(String url) { From f9b8bc281c015218abf9a6230208e92566f65dc6 Mon Sep 17 00:00:00 2001 From: wjdtkdgns Date: Wed, 9 Aug 2023 00:36:23 +0900 Subject: [PATCH 21/34] =?UTF-8?q?[fix]=20=EC=BB=A8=ED=85=90=EC=B8=A0=20?= =?UTF-8?q?=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20#92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/content/service/UpdateContentUseCase.java | 1 - .../server/domain/domains/content/domain/Content.java | 10 ++-------- .../domains/content/service/ContentDomainService.java | 6 +----- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/Api/src/main/java/allchive/server/api/content/service/UpdateContentUseCase.java b/Api/src/main/java/allchive/server/api/content/service/UpdateContentUseCase.java index 6f359b47..480d82ec 100644 --- a/Api/src/main/java/allchive/server/api/content/service/UpdateContentUseCase.java +++ b/Api/src/main/java/allchive/server/api/content/service/UpdateContentUseCase.java @@ -44,7 +44,6 @@ public void execute(Long contentId, UpdateContentRequest request) { updateArchiving(contentId, request.getArchivingId(), request.getContentType()); contentDomainService.update( contentId, - request.getContentType(), request.getArchivingId(), request.getLink(), request.getMemo(), diff --git a/Domain/src/main/java/allchive/server/domain/domains/content/domain/Content.java b/Domain/src/main/java/allchive/server/domain/domains/content/domain/Content.java index b33e3f29..fcb5d4e8 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/content/domain/Content.java +++ b/Domain/src/main/java/allchive/server/domain/domains/content/domain/Content.java @@ -77,16 +77,10 @@ public void restore() { this.deleteStatus = Boolean.FALSE; } - public void updateLinkContent(Long archivingId, String link, String title, String memo) { - this.archivingId = archivingId; - this.linkUrl = link; - this.title = title; - this.memo = memo; - } - - public void updateImageContent(Long archivingId, String imgUrl, String title, String memo) { + public void updateContent(Long archivingId, String imgUrl, String link, String title, String memo) { this.archivingId = archivingId; this.imageUrl = imgUrl; + this.linkUrl = link; this.title = title; this.memo = memo; } diff --git a/Domain/src/main/java/allchive/server/domain/domains/content/service/ContentDomainService.java b/Domain/src/main/java/allchive/server/domain/domains/content/service/ContentDomainService.java index b8e639ab..5f8dc31b 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/content/service/ContentDomainService.java +++ b/Domain/src/main/java/allchive/server/domain/domains/content/service/ContentDomainService.java @@ -39,17 +39,13 @@ public void deleteAllByArchivingIdIn(List archivingId) { public void update( Long contentId, - ContentType contentType, Long archivingId, String link, String memo, String imgUrl, String title) { Content content = contentAdaptor.findById(contentId); - switch (contentType) { - case LINK -> content.updateLinkContent(archivingId, link, title, memo); - case IMAGE -> content.updateImageContent(archivingId, imgUrl, title, memo); - } + content.updateContent(archivingId, imgUrl, link, title, memo); contentAdaptor.save(content); } } From 987630e41a68eff83ab2c4c785172657294a2683 Mon Sep 17 00:00:00 2001 From: wjdtkdgns Date: Wed, 9 Aug 2023 00:37:15 +0900 Subject: [PATCH 22/34] =?UTF-8?q?[chore]=20spotless=20=EC=A0=81=EC=9A=A9?= =?UTF-8?q?=20#92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/UpdateArchivingScrapUseCase.java | 5 ++--- .../allchive/server/api/common/util/UrlUtil.java | 14 +++++++------- .../api/image/controller/ImageController.java | 3 +-- .../server/api/user/model/mapper/UserMapper.java | 5 ++--- .../archiving/service/ArchivingDomainService.java | 5 ++--- .../domain/domains/content/domain/Content.java | 3 ++- .../content/service/ContentDomainService.java | 1 - 7 files changed, 16 insertions(+), 20 deletions(-) diff --git a/Api/src/main/java/allchive/server/api/archiving/service/UpdateArchivingScrapUseCase.java b/Api/src/main/java/allchive/server/api/archiving/service/UpdateArchivingScrapUseCase.java index 61ffb4fb..6a29b529 100644 --- a/Api/src/main/java/allchive/server/api/archiving/service/UpdateArchivingScrapUseCase.java +++ b/Api/src/main/java/allchive/server/api/archiving/service/UpdateArchivingScrapUseCase.java @@ -1,5 +1,7 @@ package allchive.server.api.archiving.service; +import static allchive.server.core.consts.AllchiveConst.MINUS_ONE; +import static allchive.server.core.consts.AllchiveConst.PLUS_ONE; import allchive.server.api.config.security.SecurityUtil; import allchive.server.core.annotation.UseCase; @@ -13,9 +15,6 @@ import lombok.RequiredArgsConstructor; import org.springframework.transaction.annotation.Transactional; -import static allchive.server.core.consts.AllchiveConst.MINUS_ONE; -import static allchive.server.core.consts.AllchiveConst.PLUS_ONE; - @UseCase @RequiredArgsConstructor public class UpdateArchivingScrapUseCase { diff --git a/Api/src/main/java/allchive/server/api/common/util/UrlUtil.java b/Api/src/main/java/allchive/server/api/common/util/UrlUtil.java index a84654fa..ef4fbc07 100644 --- a/Api/src/main/java/allchive/server/api/common/util/UrlUtil.java +++ b/Api/src/main/java/allchive/server/api/common/util/UrlUtil.java @@ -16,13 +16,13 @@ private UrlUtil(SpringEnvironmentHelper springEnvironmentHelper) { } public static String toAssetUrl(String key) { -// if (key.equals("")) { -// return ""; -// } -// if (springEnvironmentHelper.isProdProfile()) { -// return PROD_ASSET_URL + key; -// } -// return STAGING_ASSET_URL + key; + // if (key.equals("")) { + // return ""; + // } + // if (springEnvironmentHelper.isProdProfile()) { + // return PROD_ASSET_URL + key; + // } + // return STAGING_ASSET_URL + key; return key; } diff --git a/Api/src/main/java/allchive/server/api/image/controller/ImageController.java b/Api/src/main/java/allchive/server/api/image/controller/ImageController.java index 8b18bcf4..5d3257d1 100644 --- a/Api/src/main/java/allchive/server/api/image/controller/ImageController.java +++ b/Api/src/main/java/allchive/server/api/image/controller/ImageController.java @@ -38,7 +38,6 @@ public ImageUrlResponse getContentPresignedUrl() { @Operation(summary = "컨텐츠 관련 이미지 업로드 url 요청할수 있는 api 입니다.") @GetMapping(value = "/user/image") public ImageUrlResponse getUserPresignedUrl() { - return ImageUrlResponse.from( - s3PresignedUrlService.getPreSignedUrl(0L, PresignedType.USER)); + return ImageUrlResponse.from(s3PresignedUrlService.getPreSignedUrl(0L, PresignedType.USER)); } } diff --git a/Api/src/main/java/allchive/server/api/user/model/mapper/UserMapper.java b/Api/src/main/java/allchive/server/api/user/model/mapper/UserMapper.java index 5254d912..d7ce03cd 100644 --- a/Api/src/main/java/allchive/server/api/user/model/mapper/UserMapper.java +++ b/Api/src/main/java/allchive/server/api/user/model/mapper/UserMapper.java @@ -1,5 +1,7 @@ package allchive.server.api.user.model.mapper; +import static allchive.server.core.consts.AllchiveConst.PLUS_ONE; +import static allchive.server.core.consts.AllchiveConst.ZERO; import allchive.server.api.user.model.dto.response.GetUserProfileResponse; import allchive.server.core.annotation.Mapper; @@ -7,9 +9,6 @@ import allchive.server.domain.domains.user.domain.User; import java.util.List; -import static allchive.server.core.consts.AllchiveConst.PLUS_ONE; -import static allchive.server.core.consts.AllchiveConst.ZERO; - @Mapper public class UserMapper { public GetUserProfileResponse toGetUserProfileResponse( diff --git a/Domain/src/main/java/allchive/server/domain/domains/archiving/service/ArchivingDomainService.java b/Domain/src/main/java/allchive/server/domain/domains/archiving/service/ArchivingDomainService.java index d29c4a35..3fae3b49 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/archiving/service/ArchivingDomainService.java +++ b/Domain/src/main/java/allchive/server/domain/domains/archiving/service/ArchivingDomainService.java @@ -1,5 +1,7 @@ package allchive.server.domain.domains.archiving.service; +import static allchive.server.core.consts.AllchiveConst.MINUS_ONE; +import static allchive.server.core.consts.AllchiveConst.PLUS_ONE; import allchive.server.core.annotation.DomainService; import allchive.server.domain.domains.archiving.adaptor.ArchivingAdaptor; @@ -9,9 +11,6 @@ import java.util.List; import lombok.RequiredArgsConstructor; -import static allchive.server.core.consts.AllchiveConst.MINUS_ONE; -import static allchive.server.core.consts.AllchiveConst.PLUS_ONE; - @DomainService @RequiredArgsConstructor public class ArchivingDomainService { diff --git a/Domain/src/main/java/allchive/server/domain/domains/content/domain/Content.java b/Domain/src/main/java/allchive/server/domain/domains/content/domain/Content.java index fcb5d4e8..8dab4301 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/content/domain/Content.java +++ b/Domain/src/main/java/allchive/server/domain/domains/content/domain/Content.java @@ -77,7 +77,8 @@ public void restore() { this.deleteStatus = Boolean.FALSE; } - public void updateContent(Long archivingId, String imgUrl, String link, String title, String memo) { + public void updateContent( + Long archivingId, String imgUrl, String link, String title, String memo) { this.archivingId = archivingId; this.imageUrl = imgUrl; this.linkUrl = link; diff --git a/Domain/src/main/java/allchive/server/domain/domains/content/service/ContentDomainService.java b/Domain/src/main/java/allchive/server/domain/domains/content/service/ContentDomainService.java index 5f8dc31b..20198c8e 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/content/service/ContentDomainService.java +++ b/Domain/src/main/java/allchive/server/domain/domains/content/service/ContentDomainService.java @@ -4,7 +4,6 @@ import allchive.server.core.annotation.DomainService; import allchive.server.domain.domains.content.adaptor.ContentAdaptor; import allchive.server.domain.domains.content.domain.Content; -import allchive.server.domain.domains.content.domain.enums.ContentType; import java.util.List; import lombok.RequiredArgsConstructor; From 8a0bd2aa2051d603176ca3b48391b25c7d5c5127 Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Sun, 13 Aug 2023 21:24:49 +0900 Subject: [PATCH 23/34] =?UTF-8?q?[fix]=20=EC=95=84=EC=B9=B4=EC=9D=B4?= =?UTF-8?q?=EB=B9=99=20=EC=BB=A8=ED=85=90=EC=B8=A0=20=EA=B0=9C=EC=88=98=20?= =?UTF-8?q?=EC=97=90=EB=9F=AC=20(#94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [feat] content 삭제시 archiving count 수정 로직 추가 #93 * [fix] 삭제 컨텐츠 복구시 archiving count 변경 로직 추가 #93 * [chore] spotless 적용 #93 * [fix] archiving response 변경 #93 --- .../model/dto/response/ArchivingResponse.java | 8 +++++++- .../content/service/DeleteContentUseCase.java | 13 +++++++++++++ .../service/RestoreDeletedObjectUseCase.java | 16 ++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingResponse.java b/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingResponse.java index c63ac0d1..359d6cf8 100644 --- a/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingResponse.java +++ b/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingResponse.java @@ -44,6 +44,9 @@ public class ArchivingResponse { @Schema(description = "아카이빙 스크랩/고정 여부, true == 스크랩/고정됨") private boolean markStatus; + @Schema(description = "아카이빙 공개 여부") + private boolean publicStatus; + @Builder private ArchivingResponse( Long archivingId, @@ -54,7 +57,8 @@ private ArchivingResponse( Long imgCnt, Long linkCnt, Long scrapCnt, - boolean markStatus) { + boolean markStatus, + boolean publicStatus) { this.archivingId = archivingId; this.title = title; this.imageUrl = imageUrl; @@ -64,6 +68,7 @@ private ArchivingResponse( this.linkCnt = linkCnt; this.scrapCnt = scrapCnt; this.markStatus = markStatus; + this.publicStatus = publicStatus; } public static ArchivingResponse of(Archiving archiving, boolean markStatus) { @@ -77,6 +82,7 @@ public static ArchivingResponse of(Archiving archiving, boolean markStatus) { .linkCnt(archiving.getLinkCnt()) .scrapCnt(archiving.getScrapCnt()) .markStatus(markStatus) + .publicStatus(archiving.getPublicStatus()) .build(); } } diff --git a/Api/src/main/java/allchive/server/api/content/service/DeleteContentUseCase.java b/Api/src/main/java/allchive/server/api/content/service/DeleteContentUseCase.java index 865f9867..7534bbc3 100644 --- a/Api/src/main/java/allchive/server/api/content/service/DeleteContentUseCase.java +++ b/Api/src/main/java/allchive/server/api/content/service/DeleteContentUseCase.java @@ -1,9 +1,13 @@ package allchive.server.api.content.service; +import static allchive.server.core.consts.AllchiveConst.MINUS_ONE; import allchive.server.api.config.security.SecurityUtil; import allchive.server.api.recycle.model.mapper.RecycleMapper; import allchive.server.core.annotation.UseCase; +import allchive.server.domain.domains.archiving.service.ArchivingDomainService; +import allchive.server.domain.domains.content.adaptor.ContentAdaptor; +import allchive.server.domain.domains.content.domain.Content; import allchive.server.domain.domains.content.service.ContentDomainService; import allchive.server.domain.domains.content.validator.ContentValidator; import allchive.server.domain.domains.recycle.domain.Recycle; @@ -19,6 +23,8 @@ public class DeleteContentUseCase { private final ContentDomainService contentDomainService; private final RecycleMapper recycleMapper; private final RecycleDomainService recycleDomainService; + private final ArchivingDomainService archivingDomainService; + private final ContentAdaptor contentAdaptor; @Transactional public void execute(Long contentId) { @@ -26,6 +32,7 @@ public void execute(Long contentId) { validateExecution(contentId, userId); contentDomainService.softDeleteById(contentId); createRecycle(userId, contentId); + decreaseArchivingCount(contentId); } private void validateExecution(Long contentId, Long userId) { @@ -38,4 +45,10 @@ private void createRecycle(Long userId, Long contentId) { recycleMapper.toContentRecycleEntity(userId, contentId, RecycleType.CONTENT); recycleDomainService.save(recycle); } + + private void decreaseArchivingCount(Long contentId) { + Content content = contentAdaptor.findById(contentId); + archivingDomainService.updateContentCnt( + content.getArchivingId(), content.getContentType(), MINUS_ONE); + } } diff --git a/Api/src/main/java/allchive/server/api/recycle/service/RestoreDeletedObjectUseCase.java b/Api/src/main/java/allchive/server/api/recycle/service/RestoreDeletedObjectUseCase.java index 8bbe8218..1219e2bf 100644 --- a/Api/src/main/java/allchive/server/api/recycle/service/RestoreDeletedObjectUseCase.java +++ b/Api/src/main/java/allchive/server/api/recycle/service/RestoreDeletedObjectUseCase.java @@ -1,15 +1,18 @@ package allchive.server.api.recycle.service; +import static allchive.server.core.consts.AllchiveConst.PLUS_ONE; import allchive.server.api.config.security.SecurityUtil; import allchive.server.api.recycle.model.dto.request.RestoreDeletedObjectRequest; import allchive.server.core.annotation.UseCase; import allchive.server.domain.domains.archiving.service.ArchivingDomainService; import allchive.server.domain.domains.archiving.validator.ArchivingValidator; +import allchive.server.domain.domains.content.adaptor.ContentAdaptor; import allchive.server.domain.domains.content.service.ContentDomainService; import allchive.server.domain.domains.content.validator.ContentValidator; import allchive.server.domain.domains.recycle.service.RecycleDomainService; import allchive.server.domain.domains.recycle.validator.RecycleValidator; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.transaction.annotation.Transactional; @@ -22,6 +25,7 @@ public class RestoreDeletedObjectUseCase { private final ArchivingDomainService archivingDomainService; private final ContentDomainService contentDomainService; private final RecycleDomainService recycleDomainService; + private final ContentAdaptor contentAdaptor; @Transactional public void execute(RestoreDeletedObjectRequest request) { @@ -29,10 +33,22 @@ public void execute(RestoreDeletedObjectRequest request) { validateExecution(request, userId); archivingDomainService.restoreByIdIn(request.getArchivingIds()); contentDomainService.restoreByIdIn(request.getContentIds()); + increaseArchivingCount(request.getContentIds()); recycleDomainService.deleteAllByUserIdAndArchivingIdInOrUserIdAndContentIdIn( request.getArchivingIds(), request.getContentIds(), userId); } + private void increaseArchivingCount(List contentIds) { + contentAdaptor + .findAllByIdIn(contentIds) + .forEach( + content -> + archivingDomainService.updateContentCnt( + content.getArchivingId(), + content.getContentType(), + PLUS_ONE)); + } + private void validateExecution(RestoreDeletedObjectRequest request, Long userId) { recycleValidator.validateExist(request.getArchivingIds(), request.getContentIds(), userId); archivingValidator.validateExistInIdList(request.getArchivingIds()); From 9127cebdb3ed807dfbb6fd7a13c775949e04bd2b Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Mon, 14 Aug 2023 00:09:38 +0900 Subject: [PATCH 24/34] =?UTF-8?q?[refac]=20=EA=B2=80=EC=83=89=ED=95=98?= =?UTF-8?q?=EA=B8=B0=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95=20(#98)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [refac] 검색하기 쿼리 변경 #95 * [chore] spotless 적용 #95 --- .../api/search/service/SearchArchivingUseCase.java | 9 +++++++-- .../archiving/adaptor/ArchivingAdaptor.java | 5 +++-- .../repository/ArchivingCustomRepository.java | 3 ++- .../repository/ArchivingCustomRepositoryImpl.java | 14 +++++++++++--- .../domain/domains/content/adaptor/TagAdaptor.java | 4 ++-- .../content/repository/TagCustomRepository.java | 2 ++ .../repository/TagCustomRepositoryImpl.java | 13 +++++++++++++ .../domains/content/repository/TagRepository.java | 2 -- 8 files changed, 40 insertions(+), 12 deletions(-) diff --git a/Api/src/main/java/allchive/server/api/search/service/SearchArchivingUseCase.java b/Api/src/main/java/allchive/server/api/search/service/SearchArchivingUseCase.java index dfb0a313..ddb55a13 100644 --- a/Api/src/main/java/allchive/server/api/search/service/SearchArchivingUseCase.java +++ b/Api/src/main/java/allchive/server/api/search/service/SearchArchivingUseCase.java @@ -69,7 +69,7 @@ private void validateExecution(String word) { } private Set getTagArchivingIds(Long userId, String word) { - List tags = tagAdaptor.findAllByUserIdAndName(userId, word); + List tags = tagAdaptor.queryTagByUserIdContainName(userId, word); return contentTagGroupAdaptor.queryContentTagGroupByTagInWithContent(tags).stream() .map(contentTagGroup -> contentTagGroup.getContent().getArchivingId()) .collect(Collectors.toSet()); @@ -112,7 +112,12 @@ private SliceResponse getCommunityArchivings( Slice archivingSlices = archivingAdaptor .querySliceArchivingByKeywordExceptBlockOrderByTagArchvingIds( - archivingIdList, blockList, keyword, pageable, tagArchivingIds) + archivingIdList, + blockList, + keyword, + pageable, + tagArchivingIds, + userId) .map(archiving -> ArchivingResponse.of(archiving, Boolean.FALSE)); return SliceResponse.of(archivingSlices); } diff --git a/Domain/src/main/java/allchive/server/domain/domains/archiving/adaptor/ArchivingAdaptor.java b/Domain/src/main/java/allchive/server/domain/domains/archiving/adaptor/ArchivingAdaptor.java index c887e32f..9d004fa2 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/archiving/adaptor/ArchivingAdaptor.java +++ b/Domain/src/main/java/allchive/server/domain/domains/archiving/adaptor/ArchivingAdaptor.java @@ -85,9 +85,10 @@ public Slice querySliceArchivingByKeywordExceptBlockOrderByTagArchvin List blockList, String keyword, Pageable pageable, - Set tagArchivingIds) { + Set tagArchivingIds, + Long userId) { return archivingRepository.querySliceArchivingByKeywordExceptBlockOrderByTagArchvingIds( - archivingIdList, blockList, keyword, pageable, tagArchivingIds); + archivingIdList, blockList, keyword, pageable, tagArchivingIds, userId); } public List findAllByPublicStatus(Boolean publicStatus) { diff --git a/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepository.java b/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepository.java index db4b6c53..95e3c554 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepository.java +++ b/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepository.java @@ -29,5 +29,6 @@ Slice querySliceArchivingByKeywordExceptBlockOrderByTagArchvingIds( List blockList, String keyword, Pageable pageable, - Set tagArchivingIds); + Set tagArchivingIds, + Long userId); } diff --git a/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepositoryImpl.java b/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepositoryImpl.java index 806fad25..4e765f48 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepositoryImpl.java +++ b/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepositoryImpl.java @@ -100,7 +100,10 @@ public Slice querySliceArchivingByUserIdAndKeywordsOrderByTagArchving List archivings = queryFactory .selectFrom(archiving) - .where(userIdEq(userId), titleContainOrIdIn(keyword, tagArchivingIds)) + .where( + userIdEq(userId), + titleContainOrIdIn(keyword, tagArchivingIds), + deleteStatusFalse()) .orderBy(idIn(tagArchivingIds), createdAtDesc()) .offset(pageable.getOffset()) .limit(pageable.getPageSize() + PLUS_ONE) @@ -114,14 +117,15 @@ public Slice querySliceArchivingByKeywordExceptBlockOrderByTagArchvin List blockList, String keyword, Pageable pageable, - Set tagArchivingIds) { + Set tagArchivingIds, + Long userId) { List archivings = queryFactory .select(archiving) .from(archiving) .where( userIdNotIn(blockList), - publicStatusTrue(), + userIdEqOrPublicStatusTrue(userId), deleteStatusFalse(), titleContainOrIdIn(keyword, tagArchivingIds)) .orderBy( @@ -170,6 +174,10 @@ private BooleanExpression titleContainOrIdIn(String keyword, Set tagArchiv return archiving.title.contains(keyword).or(archiving.id.in(tagArchivingIds)); } + private BooleanExpression userIdEqOrPublicStatusTrue(Long userId) { + return archiving.userId.eq(userId).or(archiving.publicStatus.eq(Boolean.TRUE)); + } + private OrderSpecifier scrabListDesc(List archivingIdList) { NumberExpression pinStatus = new CaseBuilder().when(archiving.id.in(archivingIdList)).then(1L).otherwise(0L); diff --git a/Domain/src/main/java/allchive/server/domain/domains/content/adaptor/TagAdaptor.java b/Domain/src/main/java/allchive/server/domain/domains/content/adaptor/TagAdaptor.java index 3a43feff..0b65c5be 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/content/adaptor/TagAdaptor.java +++ b/Domain/src/main/java/allchive/server/domain/domains/content/adaptor/TagAdaptor.java @@ -45,8 +45,8 @@ public void deleteAll(List tagList) { tagRepository.deleteAll(tagList); } - public List findAllByUserIdAndName(Long userId, String word) { - return tagRepository.findAllByUserIdAndName(userId, word); + public List queryTagByUserIdContainName(Long userId, String word) { + return tagRepository.queryTagByUserIdContainName(userId, word); } public List findAll() { diff --git a/Domain/src/main/java/allchive/server/domain/domains/content/repository/TagCustomRepository.java b/Domain/src/main/java/allchive/server/domain/domains/content/repository/TagCustomRepository.java index 3c93394b..8975dcee 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/content/repository/TagCustomRepository.java +++ b/Domain/src/main/java/allchive/server/domain/domains/content/repository/TagCustomRepository.java @@ -8,4 +8,6 @@ public interface TagCustomRepository { List queryTagByUserIdOrderByUsedAt(Long userId); List queryTagByTagIdIn(List tagIds); + + List queryTagByUserIdContainName(Long userId, String name); } diff --git a/Domain/src/main/java/allchive/server/domain/domains/content/repository/TagCustomRepositoryImpl.java b/Domain/src/main/java/allchive/server/domain/domains/content/repository/TagCustomRepositoryImpl.java index 5deb5775..a8f5b9ad 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/content/repository/TagCustomRepositoryImpl.java +++ b/Domain/src/main/java/allchive/server/domain/domains/content/repository/TagCustomRepositoryImpl.java @@ -28,6 +28,11 @@ public List queryTagByTagIdIn(List tagIds) { return queryFactory.selectFrom(tag).where(tagIdIn(tagIds)).fetch(); } + @Override + public List queryTagByUserIdContainName(Long userId, String name) { + return queryFactory.selectFrom(tag).where(userIdEq(userId), titleContain(name)).fetch(); + } + private BooleanExpression tagUserIdEq(Long userId) { return tag.userId.eq(userId); } @@ -40,6 +45,14 @@ private BooleanExpression tagIdIn(List tagIds) { return tag.id.in(tagIds); } + private BooleanExpression userIdEq(Long userId) { + return tag.userId.eq(userId); + } + + private BooleanExpression titleContain(String name) { + return tag.name.contains(name); + } + private OrderSpecifier createdAtDesc() { return tag.createdAt.desc(); } diff --git a/Domain/src/main/java/allchive/server/domain/domains/content/repository/TagRepository.java b/Domain/src/main/java/allchive/server/domain/domains/content/repository/TagRepository.java index 803a0528..50911c53 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/content/repository/TagRepository.java +++ b/Domain/src/main/java/allchive/server/domain/domains/content/repository/TagRepository.java @@ -9,6 +9,4 @@ public interface TagRepository extends JpaRepository, TagCustomReposi List findAllByUserIdOrderByCreatedAtDesc(Long userId); List findAllByUserId(Long userId); - - List findAllByUserIdAndName(Long userId, String name); } From 6893c31bf6ebd16e47dfbe6dc9a444728abcf0e0 Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Mon, 14 Aug 2023 15:52:09 +0900 Subject: [PATCH 25/34] =?UTF-8?q?[feat]=20=EC=9D=B8=EA=B8=B0=20=EC=95=84?= =?UTF-8?q?=EC=B9=B4=EC=9D=B4=EB=B9=99=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EB=B6=88=EB=9F=AC=EC=98=A4=EA=B8=B0=20(#99)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [fix] response 네이밍 변경 #96 * [feat] 인기 아카이빙 가져오기 기능 구현 #96 * [chore] spotless 적용 #96 * [fix] response 변경 #96 * [feat] custom jsonNaming strategy 적용 #96 --- .../controller/ArchivingController.java | 8 ++ .../dto/response/ArchivingTitleResponse.java | 93 ++++++++++--------- .../dto/response/ArchivingsResponse.java | 20 ++++ .../service/GetPopularArchivingUseCase.java | 25 +++++ .../common/json/naming/UpperCaseStrategy.java | 20 ++++ .../dto/response/GetUserInfoResponse.java | 13 ++- .../archiving/adaptor/ArchivingAdaptor.java | 4 + .../repository/ArchivingCustomRepository.java | 2 + .../ArchivingCustomRepositoryImpl.java | 10 ++ 9 files changed, 149 insertions(+), 46 deletions(-) create mode 100644 Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingsResponse.java create mode 100644 Api/src/main/java/allchive/server/api/archiving/service/GetPopularArchivingUseCase.java create mode 100644 Api/src/main/java/allchive/server/api/common/json/naming/UpperCaseStrategy.java diff --git a/Api/src/main/java/allchive/server/api/archiving/controller/ArchivingController.java b/Api/src/main/java/allchive/server/api/archiving/controller/ArchivingController.java index a1a2553e..dfdbc71e 100644 --- a/Api/src/main/java/allchive/server/api/archiving/controller/ArchivingController.java +++ b/Api/src/main/java/allchive/server/api/archiving/controller/ArchivingController.java @@ -6,6 +6,7 @@ import allchive.server.api.archiving.model.dto.response.ArchivingContentsResponse; import allchive.server.api.archiving.model.dto.response.ArchivingResponse; import allchive.server.api.archiving.model.dto.response.ArchivingTitleResponse; +import allchive.server.api.archiving.model.dto.response.ArchivingsResponse; import allchive.server.api.archiving.service.*; import allchive.server.api.common.slice.SliceResponse; import allchive.server.domain.domains.archiving.domain.enums.Category; @@ -35,6 +36,7 @@ public class ArchivingController { private final GetArchivingContentsUseCase getArchivingContentsUseCase; private final UpdateArchivingScrapUseCase updateArchivingScrapUseCase; private final UpdateArchivingPinUseCase updateArchivingPinUseCase; + private final GetPopularArchivingUseCase getPopularArchivingUseCase; @Operation(summary = "아카이빙을 생성합니다.") @PostMapping() @@ -98,6 +100,12 @@ public ArchivingTitleResponse getScrapArchiving() { return getArchivingTitleUseCase.execute(); } + @Operation(summary = "인기있는 아카이빙 5개를 가져옵니다") + @GetMapping(value = "/popular") + public ArchivingsResponse getPopularArchiving() { + return getPopularArchivingUseCase.execute(); + } + @Operation(summary = "아카이빙별 컨텐츠 리스트를 가져옵니다.") @GetMapping(value = "/{archivingId}/contents") public ArchivingContentsResponse getArchivingContents( diff --git a/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingTitleResponse.java b/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingTitleResponse.java index 038f4893..8f065bfc 100644 --- a/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingTitleResponse.java +++ b/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingTitleResponse.java @@ -2,92 +2,95 @@ import allchive.server.api.archiving.model.vo.TitleContentCntVo; +import allchive.server.api.common.json.naming.UpperCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; import java.util.ArrayList; import java.util.List; import lombok.Builder; import lombok.Getter; @Getter +@JsonNaming(UpperCaseStrategy.class) public class ArchivingTitleResponse { - private List food; - private List life; - private List homeLiving; - private List shopping; - private List sport; - private List selfImprovement; - private List tech; - private List design; - private List trend; + private List FOOD; + private List LIFE; + private List HOME_LIVING; + private List SHOPPING; + private List SPORT; + private List SELF_IMPROVEMENT; + private List TECH; + private List DESIGN; + private List TREND; @Builder private ArchivingTitleResponse( - List food, - List life, - List homeLiving, - List shopping, - List sport, - List selfImprovement, - List tech, - List design, - List trend) { - this.food = food; - this.life = life; - this.homeLiving = homeLiving; - this.shopping = shopping; - this.sport = sport; - this.selfImprovement = selfImprovement; - this.tech = tech; - this.design = design; - this.trend = trend; + List FOOD, + List LIFE, + List HOME_LIVING, + List SHOPPING, + List SPORT, + List SELF_IMPROVEMENT, + List TECH, + List DESIGN, + List TREND) { + this.FOOD = FOOD; + this.LIFE = LIFE; + this.HOME_LIVING = HOME_LIVING; + this.SHOPPING = SHOPPING; + this.SPORT = SPORT; + this.SELF_IMPROVEMENT = SELF_IMPROVEMENT; + this.TECH = TECH; + this.DESIGN = DESIGN; + this.TREND = TREND; } public static ArchivingTitleResponse init() { return ArchivingTitleResponse.builder() - .food(new ArrayList<>()) - .life(new ArrayList<>()) - .homeLiving(new ArrayList<>()) - .shopping(new ArrayList<>()) - .sport(new ArrayList<>()) - .selfImprovement(new ArrayList<>()) - .tech(new ArrayList<>()) - .design(new ArrayList<>()) - .trend(new ArrayList<>()) + .FOOD(new ArrayList<>()) + .LIFE(new ArrayList<>()) + .HOME_LIVING(new ArrayList<>()) + .SHOPPING(new ArrayList<>()) + .SPORT(new ArrayList<>()) + .SELF_IMPROVEMENT(new ArrayList<>()) + .TECH(new ArrayList<>()) + .DESIGN(new ArrayList<>()) + .TREND(new ArrayList<>()) .build(); } public void addFood(TitleContentCntVo vo) { - this.food.add(vo); + this.FOOD.add(vo); } public void addLife(TitleContentCntVo vo) { - this.life.add(vo); + this.LIFE.add(vo); } public void addHomeLiving(TitleContentCntVo vo) { - this.homeLiving.add(vo); + this.HOME_LIVING.add(vo); } public void addShopping(TitleContentCntVo vo) { - this.shopping.add(vo); + this.SHOPPING.add(vo); } public void addSport(TitleContentCntVo vo) { - this.sport.add(vo); + this.SPORT.add(vo); } public void addSelfImprovement(TitleContentCntVo vo) { - this.selfImprovement.add(vo); + this.SELF_IMPROVEMENT.add(vo); } public void addTech(TitleContentCntVo vo) { - this.tech.add(vo); + this.TECH.add(vo); } public void addDesign(TitleContentCntVo vo) { - this.design.add(vo); + this.DESIGN.add(vo); } public void addTrend(TitleContentCntVo vo) { - this.trend.add(vo); + this.TREND.add(vo); } } diff --git a/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingsResponse.java b/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingsResponse.java new file mode 100644 index 00000000..a86b4cf6 --- /dev/null +++ b/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingsResponse.java @@ -0,0 +1,20 @@ +package allchive.server.api.archiving.model.dto.response; + + +import java.util.List; +import lombok.Builder; +import lombok.Getter; + +@Getter +public class ArchivingsResponse { + List archivings; + + @Builder + private ArchivingsResponse(List archivings) { + this.archivings = archivings; + } + + public static ArchivingsResponse of(List archivings) { + return ArchivingsResponse.builder().archivings(archivings).build(); + } +} diff --git a/Api/src/main/java/allchive/server/api/archiving/service/GetPopularArchivingUseCase.java b/Api/src/main/java/allchive/server/api/archiving/service/GetPopularArchivingUseCase.java new file mode 100644 index 00000000..d95d7598 --- /dev/null +++ b/Api/src/main/java/allchive/server/api/archiving/service/GetPopularArchivingUseCase.java @@ -0,0 +1,25 @@ +package allchive.server.api.archiving.service; + + +import allchive.server.api.archiving.model.dto.response.ArchivingResponse; +import allchive.server.api.archiving.model.dto.response.ArchivingsResponse; +import allchive.server.core.annotation.UseCase; +import allchive.server.domain.domains.archiving.adaptor.ArchivingAdaptor; +import java.util.List; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; + +@UseCase +@RequiredArgsConstructor +public class GetPopularArchivingUseCase { + private final ArchivingAdaptor archivingAdaptor; + + public ArchivingsResponse execute() { + List archivingResponses = + archivingAdaptor.queryArchivingOrderByScrapCntLimit5().stream() + .filter(archiving -> archiving.getScrapCnt() > 0) + .map(archiving -> ArchivingResponse.of(archiving, Boolean.FALSE)) + .collect(Collectors.toList()); + return ArchivingsResponse.of(archivingResponses); + } +} diff --git a/Api/src/main/java/allchive/server/api/common/json/naming/UpperCaseStrategy.java b/Api/src/main/java/allchive/server/api/common/json/naming/UpperCaseStrategy.java new file mode 100644 index 00000000..d6587bed --- /dev/null +++ b/Api/src/main/java/allchive/server/api/common/json/naming/UpperCaseStrategy.java @@ -0,0 +1,20 @@ +package allchive.server.api.common.json.naming; + + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; + +public class UpperCaseStrategy extends PropertyNamingStrategy.PropertyNamingStrategyBase { + @Override + public String translate(String input) { + if (input == null || input.isEmpty()) { + return input; + } + StringBuilder sb = new StringBuilder(input); + for (int i = 0; i < input.length(); i++) { + char c = input.charAt(i); + char uc = Character.toUpperCase(c); + sb.setCharAt(i, uc); + } + return sb.toString(); + } +} diff --git a/Api/src/main/java/allchive/server/api/user/model/dto/response/GetUserInfoResponse.java b/Api/src/main/java/allchive/server/api/user/model/dto/response/GetUserInfoResponse.java index 7b4ce100..2425d001 100644 --- a/Api/src/main/java/allchive/server/api/user/model/dto/response/GetUserInfoResponse.java +++ b/Api/src/main/java/allchive/server/api/user/model/dto/response/GetUserInfoResponse.java @@ -3,6 +3,7 @@ import allchive.server.api.common.util.UrlUtil; import allchive.server.domain.domains.user.domain.User; +import allchive.server.domain.domains.user.domain.enums.OauthProvider; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Getter; @@ -21,12 +22,21 @@ public class GetUserInfoResponse { @Schema(defaultValue = "닉네임", description = "닉네임") private String nickname; + @Schema(defaultValue = "KAKAO", description = "oauth") + private OauthProvider oauthProvider; + @Builder - public GetUserInfoResponse(String imgUrl, String email, String name, String nickname) { + public GetUserInfoResponse( + String imgUrl, + String email, + String name, + String nickname, + OauthProvider oauthProvider) { this.imgUrl = imgUrl; this.email = email; this.name = name; this.nickname = nickname; + this.oauthProvider = oauthProvider; } public static GetUserInfoResponse from(User user) { @@ -35,6 +45,7 @@ public static GetUserInfoResponse from(User user) { .email(user.getEmail()) .name(user.getName()) .nickname(user.getNickname()) + .oauthProvider(user.getOauthInfo().getProvider()) .build(); } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/archiving/adaptor/ArchivingAdaptor.java b/Domain/src/main/java/allchive/server/domain/domains/archiving/adaptor/ArchivingAdaptor.java index 9d004fa2..baf05a7b 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/archiving/adaptor/ArchivingAdaptor.java +++ b/Domain/src/main/java/allchive/server/domain/domains/archiving/adaptor/ArchivingAdaptor.java @@ -94,4 +94,8 @@ public Slice querySliceArchivingByKeywordExceptBlockOrderByTagArchvin public List findAllByPublicStatus(Boolean publicStatus) { return archivingRepository.findAllByPublicStatus(publicStatus); } + + public List queryArchivingOrderByScrapCntLimit5() { + return archivingRepository.queryArchivingOrderByScrapCntLimit5(); + } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepository.java b/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepository.java index 95e3c554..af10a2e7 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepository.java +++ b/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepository.java @@ -31,4 +31,6 @@ Slice querySliceArchivingByKeywordExceptBlockOrderByTagArchvingIds( Pageable pageable, Set tagArchivingIds, Long userId); + + List queryArchivingOrderByScrapCntLimit5(); } diff --git a/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepositoryImpl.java b/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepositoryImpl.java index 4e765f48..e55765c3 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepositoryImpl.java +++ b/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepositoryImpl.java @@ -139,6 +139,16 @@ public Slice querySliceArchivingByKeywordExceptBlockOrderByTagArchvin return SliceUtil.toSlice(archivings, pageable); } + @Override + public List queryArchivingOrderByScrapCntLimit5() { + return queryFactory + .selectFrom(archiving) + .where(deleteStatusFalse(), publicStatusTrue()) + .orderBy(scrapCntDesc()) + .limit(5L) + .fetch(); + } + private BooleanExpression userIdNotIn(List blockList) { return archiving.userId.notIn(blockList); } From cb6d6b2e1c7790c4200da4b74274b2b17d22f98b Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Mon, 14 Aug 2023 20:37:06 +0900 Subject: [PATCH 26/34] =?UTF-8?q?[fix]=20apple=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0=20(#100)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [feat] kakao 로그인 app id 웹 앱 분리 #97 * [feat] apple 로그인 app id 웹 앱 분리 #97 --- .../api/auth/service/OauthLoginUseCase.java | 11 +++++++++- .../auth/service/helper/AppleOauthHelper.java | 21 +++++++++++++++++-- .../auth/service/helper/KakaoOauthHelper.java | 18 ++++++++++++++-- .../api/auth/service/helper/OauthHelper.java | 11 ++++++++++ .../core/properties/AppleOAuthProperties.java | 1 + .../core/properties/KakaoOAuthProperties.java | 2 ++ Core/src/main/resources/application-core.yml | 3 +++ 7 files changed, 62 insertions(+), 5 deletions(-) diff --git a/Api/src/main/java/allchive/server/api/auth/service/OauthLoginUseCase.java b/Api/src/main/java/allchive/server/api/auth/service/OauthLoginUseCase.java index 9ee94356..cb5f3edf 100644 --- a/Api/src/main/java/allchive/server/api/auth/service/OauthLoginUseCase.java +++ b/Api/src/main/java/allchive/server/api/auth/service/OauthLoginUseCase.java @@ -35,11 +35,20 @@ public OauthSignInResponse loginWithIdToken(OauthProvider provider, String idTok @Transactional public OauthSignInResponse devLogin(OauthProvider provider, String code) { final OauthTokenResponse oauthTokenResponse = oauthHelper.getCredentialDev(provider, code); - return processLoginWithIdToken(provider, oauthTokenResponse.getIdToken()); + return processLoginWithIdTokenDev(provider, oauthTokenResponse.getIdToken()); } private OauthSignInResponse processLoginWithIdToken(OauthProvider provider, String idToken) { final OauthInfo oauthInfo = oauthHelper.getOauthInfo(provider, idToken); + return checkUserCanLogin(oauthInfo, idToken); + } + + private OauthSignInResponse processLoginWithIdTokenDev(OauthProvider provider, String idToken) { + final OauthInfo oauthInfo = oauthHelper.getOauthInfoDev(provider, idToken); + return checkUserCanLogin(oauthInfo, idToken); + } + + private OauthSignInResponse checkUserCanLogin(OauthInfo oauthInfo, String idToken) { if (userDomainService.checkUserCanLogin(oauthInfo)) { User user = userDomainService.loginUser(oauthInfo); return tokenGenerateHelper.execute(user); diff --git a/Api/src/main/java/allchive/server/api/auth/service/helper/AppleOauthHelper.java b/Api/src/main/java/allchive/server/api/auth/service/helper/AppleOauthHelper.java index c8e5c7c7..225abe5a 100644 --- a/Api/src/main/java/allchive/server/api/auth/service/helper/AppleOauthHelper.java +++ b/Api/src/main/java/allchive/server/api/auth/service/helper/AppleOauthHelper.java @@ -36,7 +36,7 @@ public String getAppleOauthLinkDev() { return appleOAuthProperties.getBaseUrl() + String.format( APPLE_OAUTH_QUERY_STRING, - appleOAuthProperties.getClientId(), + appleOAuthProperties.getWebClientId(), appleOAuthProperties.getRedirectUrl()); } @@ -51,7 +51,7 @@ public AppleTokenResponse getAppleOAuthToken(String code, String referer) { public AppleTokenResponse getAppleOAuthTokenDev(String code) { return appleOAuthClient.appleAuth( - appleOAuthProperties.getClientId(), + appleOAuthProperties.getWebClientId(), appleOAuthProperties.getRedirectUrl(), code, this.getClientSecret()); @@ -66,6 +66,14 @@ public OauthInfo getAppleOAuthInfoByIdToken(String idToken) { .build(); } + public OauthInfo getAppleOAuthInfoByIdTokenDev(String idToken) { + OIDCDecodePayload oidcDecodePayload = this.getOIDCDecodePayloadDev(idToken); + return OauthInfo.builder() + .provider(OauthProvider.APPLE) + .oid(oidcDecodePayload.getSub()) + .build(); + } + /** oidc decode * */ public OIDCDecodePayload getOIDCDecodePayload(String token) { OIDCPublicKeysResponse oidcPublicKeysResponse = appleOIDCClient.getAppleOIDCOpenKeys(); @@ -76,6 +84,15 @@ public OIDCDecodePayload getOIDCDecodePayload(String token) { oidcPublicKeysResponse); } + public OIDCDecodePayload getOIDCDecodePayloadDev(String token) { + OIDCPublicKeysResponse oidcPublicKeysResponse = appleOIDCClient.getAppleOIDCOpenKeys(); + return oAuthOIDCHelper.getPayloadFromIdToken( + token, + appleOAuthProperties.getBaseUrl(), + appleOAuthProperties.getWebClientId(), + oidcPublicKeysResponse); + } + /** apple측 회원 탈퇴 * */ public void withdrawAppleOauthUser(String appleOAuthAccessToken) { if (appleOAuthAccessToken == null) { diff --git a/Api/src/main/java/allchive/server/api/auth/service/helper/KakaoOauthHelper.java b/Api/src/main/java/allchive/server/api/auth/service/helper/KakaoOauthHelper.java index c25e4752..37a3e8c9 100644 --- a/Api/src/main/java/allchive/server/api/auth/service/helper/KakaoOauthHelper.java +++ b/Api/src/main/java/allchive/server/api/auth/service/helper/KakaoOauthHelper.java @@ -40,7 +40,7 @@ public String getKaKaoOauthLinkDev() { return kakaoOauthProperties.getBaseUrl() + String.format( KAKAO_OAUTH_QUERY_STRING, - kakaoOauthProperties.getClientId(), + kakaoOauthProperties.getWebClientId(), kakaoOauthProperties.getRedirectUrl()); } @@ -55,7 +55,7 @@ public KakaoTokenResponse getKakaoOauthToken(String code, String referer) { public KakaoTokenResponse getKakaoOauthTokenDev(String code) { return kakaoOauthClient.kakaoAuth( - kakaoOauthProperties.getClientId(), + kakaoOauthProperties.getWebClientId(), kakaoOauthProperties.getRedirectUrl(), code, kakaoOauthProperties.getClientSecret()); @@ -67,6 +67,11 @@ public OauthInfo getKakaoOauthInfoByIdToken(String idToken) { return OauthInfo.of(OauthProvider.KAKAO, oidcDecodePayload.getSub()); } + public OauthInfo getKakaoOauthInfoByIdTokenDev(String idToken) { + OIDCDecodePayload oidcDecodePayload = getOIDCDecodePayloadDev(idToken); + return OauthInfo.of(OauthProvider.KAKAO, oidcDecodePayload.getSub()); + } + /** oidc decode * */ public OIDCDecodePayload getOIDCDecodePayload(String token) { OIDCPublicKeysResponse oidcPublicKeysResponse = kakaoOauthClient.getKakaoOIDCOpenKeys(); @@ -77,6 +82,15 @@ public OIDCDecodePayload getOIDCDecodePayload(String token) { oidcPublicKeysResponse); } + public OIDCDecodePayload getOIDCDecodePayloadDev(String token) { + OIDCPublicKeysResponse oidcPublicKeysResponse = kakaoOauthClient.getKakaoOIDCOpenKeys(); + return oauthOIDCHelper.getPayloadFromIdToken( + token, + kakaoOauthProperties.getBaseUrl(), + kakaoOauthProperties.getWebAppId(), + oidcPublicKeysResponse); + } + /** kakao측 회원 탈퇴 * */ public void withdrawKakaoOauthUser(String oid) { String kakaoAdminKey = kakaoOauthProperties.getAdminKey(); diff --git a/Api/src/main/java/allchive/server/api/auth/service/helper/OauthHelper.java b/Api/src/main/java/allchive/server/api/auth/service/helper/OauthHelper.java index b305be8c..e573b899 100644 --- a/Api/src/main/java/allchive/server/api/auth/service/helper/OauthHelper.java +++ b/Api/src/main/java/allchive/server/api/auth/service/helper/OauthHelper.java @@ -74,6 +74,17 @@ public OauthInfo getOauthInfo(OauthProvider provider, String idToken) { } } + public OauthInfo getOauthInfoDev(OauthProvider provider, String idToken) { + switch (provider) { + case KAKAO: + return kakaoOauthHelper.getKakaoOauthInfoByIdTokenDev(idToken); + case APPLE: + return appleOauthHelper.getAppleOAuthInfoByIdTokenDev(idToken); + default: + throw InvalidOauthProviderException.EXCEPTION; + } + } + /** 회원탈퇴 * */ public void withdraw(OauthProvider provider, String oid, String appleAccessToken) { switch (provider) { diff --git a/Core/src/main/java/allchive/server/core/properties/AppleOAuthProperties.java b/Core/src/main/java/allchive/server/core/properties/AppleOAuthProperties.java index b6f6837e..5aef1604 100644 --- a/Core/src/main/java/allchive/server/core/properties/AppleOAuthProperties.java +++ b/Core/src/main/java/allchive/server/core/properties/AppleOAuthProperties.java @@ -13,6 +13,7 @@ public class AppleOAuthProperties { private String baseUrl; private String clientId; + private String webClientId; private String keyId; private String redirectUrl; private String teamId; diff --git a/Core/src/main/java/allchive/server/core/properties/KakaoOAuthProperties.java b/Core/src/main/java/allchive/server/core/properties/KakaoOAuthProperties.java index 42d76217..7b9430c9 100644 --- a/Core/src/main/java/allchive/server/core/properties/KakaoOAuthProperties.java +++ b/Core/src/main/java/allchive/server/core/properties/KakaoOAuthProperties.java @@ -17,4 +17,6 @@ public class KakaoOAuthProperties { private String redirectUrl; private String appId; private String adminKey; + private String webClientId; + private String webAppId; } diff --git a/Core/src/main/resources/application-core.yml b/Core/src/main/resources/application-core.yml index f0e08718..75df114c 100644 --- a/Core/src/main/resources/application-core.yml +++ b/Core/src/main/resources/application-core.yml @@ -14,10 +14,13 @@ oauth: redirect-url: ${KAKAO_REDIRECT} app-id: ${KAKAO_APP_ID} admin-key: ${KAKAO_ADMIN_KEY} + web-client-id: ${KAKAO_WEB_CLIENT} + web-app-id: ${KAKAO_WEB_APP_ID} apple: baseUrl: ${APPLE_BASE_URL} clientId: ${APPLE_CLIENT_ID} + webClientId: ${APPLE_WEB_CLIENT_ID} keyId: ${APPLE_KEY_ID} redirectUrl: ${APPLE_REDIRECT} teamId: ${APPLE_TEAM_ID} From 5a46fc10eb01a129817d3af96c155ad6d2f0efeb Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Mon, 14 Aug 2023 20:54:38 +0900 Subject: [PATCH 27/34] =?UTF-8?q?[fix]=20apple=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0=20(#101)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [feat] kakao 로그인 app id 웹 앱 분리 #97 * [feat] apple 로그인 app id 웹 앱 분리 #97 * [fix] client secret 생성 개발용 서비스용 분리 #97 --- .../api/auth/service/helper/AppleOauthHelper.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Api/src/main/java/allchive/server/api/auth/service/helper/AppleOauthHelper.java b/Api/src/main/java/allchive/server/api/auth/service/helper/AppleOauthHelper.java index 225abe5a..2d0ca198 100644 --- a/Api/src/main/java/allchive/server/api/auth/service/helper/AppleOauthHelper.java +++ b/Api/src/main/java/allchive/server/api/auth/service/helper/AppleOauthHelper.java @@ -54,7 +54,7 @@ public AppleTokenResponse getAppleOAuthTokenDev(String code) { appleOAuthProperties.getWebClientId(), appleOAuthProperties.getRedirectUrl(), code, - this.getClientSecret()); + this.getClientSecretDev()); } /** idtoken 분석 * */ @@ -111,4 +111,13 @@ private String getClientSecret() { appleOAuthProperties.getAuthKey(), appleOAuthProperties.getBaseUrl()); } + + private String getClientSecretDev() { + return AppleLoginUtil.createClientSecret( + appleOAuthProperties.getTeamId(), + appleOAuthProperties.getWebClientId(), + appleOAuthProperties.getKeyId(), + appleOAuthProperties.getAuthKey(), + appleOAuthProperties.getBaseUrl()); + } } From caee094c4102dfdf40ad1c1b1a63d55c549ac73d Mon Sep 17 00:00:00 2001 From: wjdtkdgns Date: Mon, 14 Aug 2023 23:27:54 +0900 Subject: [PATCH 28/34] =?UTF-8?q?[add]=20=EC=97=90=EB=9F=AC=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=EC=9A=A9=20log=20=EC=B6=94=EA=B0=80=20#97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Core/src/main/java/allchive/server/core/jwt/JwtOIDCProvider.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/src/main/java/allchive/server/core/jwt/JwtOIDCProvider.java b/Core/src/main/java/allchive/server/core/jwt/JwtOIDCProvider.java index ca3f5d8a..d23c9b58 100644 --- a/Core/src/main/java/allchive/server/core/jwt/JwtOIDCProvider.java +++ b/Core/src/main/java/allchive/server/core/jwt/JwtOIDCProvider.java @@ -27,6 +27,7 @@ public String getKidFromUnsignedTokenHeader(String token, String iss, String aud private Jwt getUnsignedTokenClaims(String token, String iss, String aud) { try { + log.info("{} / {} / {}", token, iss, aud); return Jwts.parserBuilder() .requireAudience(aud) .requireIssuer(iss) From 59e5e14684e7e6dd64f297d5161c969e5d06ea97 Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Tue, 15 Aug 2023 14:24:14 +0900 Subject: [PATCH 29/34] =?UTF-8?q?[fix]=20archiving=20response=20=EC=8A=A4?= =?UTF-8?q?=ED=81=AC=EB=9E=A9=20=EC=97=AC=EB=B6=80=20=ED=8F=AC=ED=95=A8?= =?UTF-8?q?=ED=95=98=EA=B8=B0=20(#103)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [fix] archiving content response 변경 및 스크랩 여부 판별 로직 추가 #102 * [chore] auth 부분 log 지우기 #102 * [fix] archiving popular response 변경 및 스크랩 여부 판별 로직 추가 #102 * [chore] spotless 적용 #102 --- .../response/ArchivingContentsResponse.java | 34 +++++++++++++++++-- .../service/GetArchivingContentsUseCase.java | 18 +++++++++- .../service/GetPopularArchivingUseCase.java | 22 +++++++++++- .../server/core/jwt/JwtOIDCProvider.java | 1 - 4 files changed, 69 insertions(+), 6 deletions(-) diff --git a/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingContentsResponse.java b/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingContentsResponse.java index b25ee72e..22ce8d96 100644 --- a/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingContentsResponse.java +++ b/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingContentsResponse.java @@ -4,6 +4,8 @@ import allchive.server.api.common.slice.SliceResponse; import allchive.server.api.content.model.dto.response.ContentResponse; import allchive.server.domain.domains.archiving.domain.Archiving; +import allchive.server.domain.domains.archiving.domain.enums.Category; +import allchive.server.domain.domains.user.domain.User; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Getter; @@ -15,6 +17,9 @@ public class ArchivingContentsResponse { @Schema(description = "아카이빙 제목") private String archivingTitle; + @Schema(description = "아카이빙 카테고리") + private Category category; + @Schema(description = "아카이빙 고유번호") private Long archivingId; @@ -24,36 +29,59 @@ public class ArchivingContentsResponse { @Schema(description = "아카이빙 소유자 고유번호") private Long ownerId; + @Schema(description = "아카이빙 소유자 닉네임") + private String ownerNickname; + + @Schema(description = "아카이빙 소유자 프로픨 이미지") + private String ownerProfileImgUrl; + @Schema(description = "유저 소유 여부") private Boolean isMine; + @Schema(description = "아카이빙 스크랩 여부") + private Boolean isScrap; + @Builder private ArchivingContentsResponse( SliceResponse contents, String archivingTitle, + Category category, Long archivingId, Long totalContentsCount, Long ownerId, - Boolean isMine) { + String ownerNickname, + String ownerProfileImgUrl, + Boolean isMine, + Boolean isScrap) { this.contents = contents; this.archivingTitle = archivingTitle; + this.category = category; this.archivingId = archivingId; this.totalContentsCount = totalContentsCount; this.ownerId = ownerId; + this.ownerNickname = ownerNickname; + this.ownerProfileImgUrl = ownerProfileImgUrl; this.isMine = isMine; + this.isScrap = isScrap; } public static ArchivingContentsResponse of( SliceResponse contentResponseSlice, Archiving archiving, - Boolean isMine) { + User user, + Boolean isMine, + Boolean isScrap) { return ArchivingContentsResponse.builder() .archivingId(archiving.getId()) .archivingTitle(archiving.getTitle()) + .category(archiving.getCategory()) .totalContentsCount(archiving.getScrapCnt() + archiving.getImgCnt()) .contents(contentResponseSlice) - .ownerId(archiving.getUserId()) + .ownerId(user.getId()) + .ownerNickname(user.getNickname()) + .ownerProfileImgUrl(user.getProfileImgUrl()) .isMine(isMine) + .isScrap(isScrap) .build(); } } diff --git a/Api/src/main/java/allchive/server/api/archiving/service/GetArchivingContentsUseCase.java b/Api/src/main/java/allchive/server/api/archiving/service/GetArchivingContentsUseCase.java index 5dcb8aa7..e340d442 100644 --- a/Api/src/main/java/allchive/server/api/archiving/service/GetArchivingContentsUseCase.java +++ b/Api/src/main/java/allchive/server/api/archiving/service/GetArchivingContentsUseCase.java @@ -14,6 +14,9 @@ import allchive.server.domain.domains.content.adaptor.ContentTagGroupAdaptor; import allchive.server.domain.domains.content.domain.Content; import allchive.server.domain.domains.content.domain.ContentTagGroup; +import allchive.server.domain.domains.user.adaptor.ScrapAdaptor; +import allchive.server.domain.domains.user.adaptor.UserAdaptor; +import allchive.server.domain.domains.user.domain.User; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; @@ -28,18 +31,23 @@ public class GetArchivingContentsUseCase { private final ContentAdaptor contentAdaptor; private final ContentTagGroupAdaptor contentTagGroupAdaptor; private final ContentMapper contentMapper; + private final UserAdaptor userAdaptor; + private final ScrapAdaptor scrapAdaptor; @Transactional(readOnly = true) public ArchivingContentsResponse execute(Long archivingId, Pageable pageable) { Long userId = SecurityUtil.getCurrentUserId(); validateExecution(archivingId, userId); Archiving archiving = archivingAdaptor.findById(archivingId); + User owner = userAdaptor.findById(archiving.getUserId()); Slice contentResponseSlice = getContentResponseSlice(archivingId, pageable); return ArchivingContentsResponse.of( SliceResponse.of(contentResponseSlice), archiving, - calculateIsMine(archiving, userId)); + owner, + calculateIsMine(archiving, userId), + calculateIsScrap(archiving, userId)); } private void validateExecution(Long archivingId, Long userId) { @@ -62,4 +70,12 @@ private Boolean calculateIsMine(Archiving archiving, Long userId) { } return Boolean.FALSE; } + + private Boolean calculateIsScrap(Archiving archiving, Long userId) { + User user = userAdaptor.findById(userId); + if (scrapAdaptor.existsByUserAndArchivingId(user, archiving.getId())) { + return Boolean.TRUE; + } + return Boolean.FALSE; + } } diff --git a/Api/src/main/java/allchive/server/api/archiving/service/GetPopularArchivingUseCase.java b/Api/src/main/java/allchive/server/api/archiving/service/GetPopularArchivingUseCase.java index d95d7598..5eab76ec 100644 --- a/Api/src/main/java/allchive/server/api/archiving/service/GetPopularArchivingUseCase.java +++ b/Api/src/main/java/allchive/server/api/archiving/service/GetPopularArchivingUseCase.java @@ -3,8 +3,12 @@ import allchive.server.api.archiving.model.dto.response.ArchivingResponse; import allchive.server.api.archiving.model.dto.response.ArchivingsResponse; +import allchive.server.api.config.security.SecurityUtil; import allchive.server.core.annotation.UseCase; import allchive.server.domain.domains.archiving.adaptor.ArchivingAdaptor; +import allchive.server.domain.domains.archiving.domain.Archiving; +import allchive.server.domain.domains.user.adaptor.ScrapAdaptor; +import allchive.server.domain.domains.user.domain.Scrap; import java.util.List; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; @@ -13,13 +17,29 @@ @RequiredArgsConstructor public class GetPopularArchivingUseCase { private final ArchivingAdaptor archivingAdaptor; + private final ScrapAdaptor scrapAdaptor; public ArchivingsResponse execute() { + Long userId = SecurityUtil.getCurrentUserId(); + List scraps = scrapAdaptor.findAllByUserId(userId); List archivingResponses = archivingAdaptor.queryArchivingOrderByScrapCntLimit5().stream() .filter(archiving -> archiving.getScrapCnt() > 0) - .map(archiving -> ArchivingResponse.of(archiving, Boolean.FALSE)) + .map( + archiving -> + ArchivingResponse.of( + archiving, calculateIsScrap(scraps, archiving))) .collect(Collectors.toList()); return ArchivingsResponse.of(archivingResponses); } + + private Boolean calculateIsScrap(List scraps, Archiving archiving) { + if (scraps.stream() + .filter(scrap -> scrap.getArchivingId().equals(archiving.getId())) + .count() + == 1L) { + return Boolean.TRUE; + } + return Boolean.FALSE; + } } diff --git a/Core/src/main/java/allchive/server/core/jwt/JwtOIDCProvider.java b/Core/src/main/java/allchive/server/core/jwt/JwtOIDCProvider.java index d23c9b58..ca3f5d8a 100644 --- a/Core/src/main/java/allchive/server/core/jwt/JwtOIDCProvider.java +++ b/Core/src/main/java/allchive/server/core/jwt/JwtOIDCProvider.java @@ -27,7 +27,6 @@ public String getKidFromUnsignedTokenHeader(String token, String iss, String aud private Jwt getUnsignedTokenClaims(String token, String iss, String aud) { try { - log.info("{} / {} / {}", token, iss, aud); return Jwts.parserBuilder() .requireAudience(aud) .requireIssuer(iss) From 26be511fef21e933f92ce1b84068efb07a860cfd Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Tue, 15 Aug 2023 15:23:22 +0900 Subject: [PATCH 30/34] =?UTF-8?q?[feat]=20=EC=95=A0=ED=94=8C=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=ED=83=88=ED=87=B4=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?(#105)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [feat] apple 탈퇴 구현 #104 * [feat] 개발용 회원탈퇴 구현 #104 * [chore] spotless 적용 #104 --- .../api/auth/controller/AuthController.java | 13 ++- .../api/auth/controller/OauthController.java | 2 +- .../api/auth/service/WithdrawUserUseCase.java | 29 ++++- .../auth/service/helper/AppleOauthHelper.java | 24 +++- .../api/auth/service/helper/OauthHelper.java | 110 ++++++++---------- .../server/core/error/GlobalErrorCode.java | 2 +- ...ception.java => NoAppleCodeException.java} | 8 +- 7 files changed, 107 insertions(+), 81 deletions(-) rename Core/src/main/java/allchive/server/core/error/exception/{NoAppleAccessTokenException.java => NoAppleCodeException.java} (54%) diff --git a/Api/src/main/java/allchive/server/api/auth/controller/AuthController.java b/Api/src/main/java/allchive/server/api/auth/controller/AuthController.java index 1a68afd6..dd3491e9 100644 --- a/Api/src/main/java/allchive/server/api/auth/controller/AuthController.java +++ b/Api/src/main/java/allchive/server/api/auth/controller/AuthController.java @@ -24,9 +24,16 @@ public class AuthController { @Operation(summary = "회원탈퇴를 합니다.") @DeleteMapping("/withdrawal") public void withDrawUser( - @RequestParam(required = false, name = "appleAccessToken", value = "") - String appleAccessToken) { - withdrawUserUseCase.execute(appleAccessToken); + @RequestParam(required = false, name = "appleCode", value = "") String appleCode, + @RequestHeader(value = "referer", required = false) String referer) { + withdrawUserUseCase.execute(appleCode, referer); + } + + @Operation(summary = "회원탈퇴를 합니다. (개발용)", deprecated = true) + @DeleteMapping("/withdrawal/dev") + public void withDrawUserDev( + @RequestParam(required = false, name = "appleCode", value = "") String appleCode) { + withdrawUserUseCase.executeDev(appleCode); } @Operation(summary = "로그아웃을 합니다.") diff --git a/Api/src/main/java/allchive/server/api/auth/controller/OauthController.java b/Api/src/main/java/allchive/server/api/auth/controller/OauthController.java index 45232199..ccf41e44 100644 --- a/Api/src/main/java/allchive/server/api/auth/controller/OauthController.java +++ b/Api/src/main/java/allchive/server/api/auth/controller/OauthController.java @@ -82,7 +82,7 @@ public OauthSignInResponse oauthUserIdTokenLogin( public OauthRegisterResponse oauthUserRegister( @PathVariable("provider") OauthProvider provider, @RequestParam("idToken") String idToken, - @RequestParam("oauthAccessToken") String accessToken, + @RequestParam(value = "oauthAccessToken", required = false) String accessToken, @RequestBody RegisterRequest registerRequest) { return oauthRegisterUseCase.execute(provider, idToken, accessToken, registerRequest); } diff --git a/Api/src/main/java/allchive/server/api/auth/service/WithdrawUserUseCase.java b/Api/src/main/java/allchive/server/api/auth/service/WithdrawUserUseCase.java index 45fbff49..8a51428c 100644 --- a/Api/src/main/java/allchive/server/api/auth/service/WithdrawUserUseCase.java +++ b/Api/src/main/java/allchive/server/api/auth/service/WithdrawUserUseCase.java @@ -45,19 +45,38 @@ public class WithdrawUserUseCase { private final UserDomainService userDomainService; @Transactional - public void execute(String appleAccessToken) { + public void execute(String appleAccessToken, String referer) { Long userId = SecurityUtil.getCurrentUserId(); User user = userAdaptor.findById(userId); // oauth쪽 탈퇴 - withdrawOauth(user.getOauthInfo().getProvider(), appleAccessToken, user); + withdrawOauth(user.getOauthInfo().getProvider(), appleAccessToken, user, referer); // 우리쪽 탈퇴 withdrawService(userId, user); } - private void withdrawOauth(OauthProvider provider, String appleAccessToken, User user) { + @Transactional + public void executeDev(String appleAccessToken) { + Long userId = SecurityUtil.getCurrentUserId(); + User user = userAdaptor.findById(userId); + // oauth쪽 탈퇴 + withdrawOauthDev(user.getOauthInfo().getProvider(), appleAccessToken, user); + // 우리쪽 탈퇴 + withdrawService(userId, user); + } + + private void withdrawOauth( + OauthProvider provider, String appleAccessToken, User user, String referer) { + switch (provider) { + case KAKAO -> oauthHelper.withdraw(provider, user.getOauthInfo().getOid(), null, null); + case APPLE -> oauthHelper.withdraw(provider, null, appleAccessToken, referer); + default -> throw InvalidOauthProviderException.EXCEPTION; + } + } + + private void withdrawOauthDev(OauthProvider provider, String appleAccessToken, User user) { switch (provider) { - case KAKAO -> oauthHelper.withdraw(provider, user.getOauthInfo().getOid(), null); - case APPLE -> oauthHelper.withdraw(provider, null, appleAccessToken); + case KAKAO -> oauthHelper.withdrawDev(provider, user.getOauthInfo().getOid(), null); + case APPLE -> oauthHelper.withdrawDev(provider, null, appleAccessToken); default -> throw InvalidOauthProviderException.EXCEPTION; } } diff --git a/Api/src/main/java/allchive/server/api/auth/service/helper/AppleOauthHelper.java b/Api/src/main/java/allchive/server/api/auth/service/helper/AppleOauthHelper.java index 2d0ca198..4db26f04 100644 --- a/Api/src/main/java/allchive/server/api/auth/service/helper/AppleOauthHelper.java +++ b/Api/src/main/java/allchive/server/api/auth/service/helper/AppleOauthHelper.java @@ -4,7 +4,7 @@ import allchive.server.core.annotation.Helper; import allchive.server.core.dto.OIDCDecodePayload; -import allchive.server.core.error.exception.NoAppleAccessTokenException; +import allchive.server.core.error.exception.NoAppleCodeException; import allchive.server.core.properties.AppleOAuthProperties; import allchive.server.domain.domains.user.domain.enums.OauthInfo; import allchive.server.domain.domains.user.domain.enums.OauthProvider; @@ -94,12 +94,26 @@ public OIDCDecodePayload getOIDCDecodePayloadDev(String token) { } /** apple측 회원 탈퇴 * */ - public void withdrawAppleOauthUser(String appleOAuthAccessToken) { - if (appleOAuthAccessToken == null) { - throw NoAppleAccessTokenException.EXCEPTION; + public void withdrawAppleOauthUser(String code, String referer) { + if (code == null) { + throw NoAppleCodeException.EXCEPTION; } + AppleTokenResponse appleTokenResponse = getAppleOAuthToken(code, referer); appleOAuthClient.revoke( - appleOAuthProperties.getClientId(), appleOAuthAccessToken, this.getClientSecret()); + appleOAuthProperties.getClientId(), + appleTokenResponse.getAccessToken(), + this.getClientSecret()); + } + + public void withdrawAppleOauthUserDev(String code) { + if (code == null) { + throw NoAppleCodeException.EXCEPTION; + } + AppleTokenResponse appleTokenResponse = getAppleOAuthTokenDev(code); + appleOAuthClient.revoke( + appleOAuthProperties.getWebClientId(), + appleTokenResponse.getAccessToken(), + this.getClientSecret()); } /** client secret 가져오기 * */ diff --git a/Api/src/main/java/allchive/server/api/auth/service/helper/OauthHelper.java b/Api/src/main/java/allchive/server/api/auth/service/helper/OauthHelper.java index e573b899..62c9b57d 100644 --- a/Api/src/main/java/allchive/server/api/auth/service/helper/OauthHelper.java +++ b/Api/src/main/java/allchive/server/api/auth/service/helper/OauthHelper.java @@ -18,94 +18,80 @@ public class OauthHelper { /** oauth link 가져오기 * */ public OauthLoginLinkResponse getOauthLinkDev(OauthProvider provider) { - switch (provider) { - case KAKAO: - return new OauthLoginLinkResponse(kakaoOauthHelper.getKaKaoOauthLinkDev()); - case APPLE: - return new OauthLoginLinkResponse(appleOauthHelper.getAppleOauthLinkDev()); - default: - throw InvalidOauthProviderException.EXCEPTION; - } + return switch (provider) { + case KAKAO -> new OauthLoginLinkResponse(kakaoOauthHelper.getKaKaoOauthLinkDev()); + case APPLE -> new OauthLoginLinkResponse(appleOauthHelper.getAppleOauthLinkDev()); + default -> throw InvalidOauthProviderException.EXCEPTION; + }; } public OauthLoginLinkResponse getOauthLink(OauthProvider provider, String referer) { - switch (provider) { - case KAKAO: - return new OauthLoginLinkResponse(kakaoOauthHelper.getKaKaoOauthLink(referer)); - case APPLE: - return new OauthLoginLinkResponse(appleOauthHelper.getAppleOAuthLink(referer)); - default: - throw InvalidOauthProviderException.EXCEPTION; - } + return switch (provider) { + case KAKAO -> new OauthLoginLinkResponse(kakaoOauthHelper.getKaKaoOauthLink(referer)); + case APPLE -> new OauthLoginLinkResponse(appleOauthHelper.getAppleOAuthLink(referer)); + default -> throw InvalidOauthProviderException.EXCEPTION; + }; } /** idtoken 가져오기 * */ public OauthTokenResponse getCredential(OauthProvider provider, String code, String referer) { - switch (provider) { - case KAKAO: - return OauthTokenResponse.from(kakaoOauthHelper.getKakaoOauthToken(code, referer)); - case APPLE: - return OauthTokenResponse.from(appleOauthHelper.getAppleOAuthToken(code, referer)); - default: - throw InvalidOauthProviderException.EXCEPTION; - } + return switch (provider) { + case KAKAO -> OauthTokenResponse.from( + kakaoOauthHelper.getKakaoOauthToken(code, referer)); + case APPLE -> OauthTokenResponse.from( + appleOauthHelper.getAppleOAuthToken(code, referer)); + default -> throw InvalidOauthProviderException.EXCEPTION; + }; } public OauthTokenResponse getCredentialDev(OauthProvider provider, String code) { - switch (provider) { - case KAKAO: - return OauthTokenResponse.from(kakaoOauthHelper.getKakaoOauthTokenDev(code)); - case APPLE: - return OauthTokenResponse.from(appleOauthHelper.getAppleOAuthTokenDev(code)); - default: - throw InvalidOauthProviderException.EXCEPTION; - } + return switch (provider) { + case KAKAO -> OauthTokenResponse.from(kakaoOauthHelper.getKakaoOauthTokenDev(code)); + case APPLE -> OauthTokenResponse.from(appleOauthHelper.getAppleOAuthTokenDev(code)); + default -> throw InvalidOauthProviderException.EXCEPTION; + }; } /** idtoken 분석 * */ public OauthInfo getOauthInfo(OauthProvider provider, String idToken) { - switch (provider) { - case KAKAO: - return kakaoOauthHelper.getKakaoOauthInfoByIdToken(idToken); - case APPLE: - return appleOauthHelper.getAppleOAuthInfoByIdToken(idToken); - default: - throw InvalidOauthProviderException.EXCEPTION; - } + return switch (provider) { + case KAKAO -> kakaoOauthHelper.getKakaoOauthInfoByIdToken(idToken); + case APPLE -> appleOauthHelper.getAppleOAuthInfoByIdToken(idToken); + default -> throw InvalidOauthProviderException.EXCEPTION; + }; } public OauthInfo getOauthInfoDev(OauthProvider provider, String idToken) { + return switch (provider) { + case KAKAO -> kakaoOauthHelper.getKakaoOauthInfoByIdTokenDev(idToken); + case APPLE -> appleOauthHelper.getAppleOAuthInfoByIdTokenDev(idToken); + default -> throw InvalidOauthProviderException.EXCEPTION; + }; + } + + /** 회원탈퇴 * */ + public void withdraw( + OauthProvider provider, String oid, String appleAccessToken, String referer) { switch (provider) { - case KAKAO: - return kakaoOauthHelper.getKakaoOauthInfoByIdTokenDev(idToken); - case APPLE: - return appleOauthHelper.getAppleOAuthInfoByIdTokenDev(idToken); - default: - throw InvalidOauthProviderException.EXCEPTION; + case KAKAO -> kakaoOauthHelper.withdrawKakaoOauthUser(oid); + case APPLE -> appleOauthHelper.withdrawAppleOauthUser(appleAccessToken, referer); + default -> throw InvalidOauthProviderException.EXCEPTION; } } - /** 회원탈퇴 * */ - public void withdraw(OauthProvider provider, String oid, String appleAccessToken) { + public void withdrawDev(OauthProvider provider, String oid, String appleAccessToken) { switch (provider) { - case KAKAO: - kakaoOauthHelper.withdrawKakaoOauthUser(oid); - break; - case APPLE: - appleOauthHelper.withdrawAppleOauthUser(appleAccessToken); - break; - default: - throw InvalidOauthProviderException.EXCEPTION; + case KAKAO -> kakaoOauthHelper.withdrawKakaoOauthUser(oid); + case APPLE -> appleOauthHelper.withdrawAppleOauthUserDev(appleAccessToken); + default -> throw InvalidOauthProviderException.EXCEPTION; } } /** 유저 정보 가져오기 * */ public OauthUserInfoDto getUserInfo(OauthProvider provider, String oauthAccessToken) { - switch (provider) { - case KAKAO: - return kakaoOauthHelper.getUserInfo(oauthAccessToken); - default: - throw InvalidOauthProviderException.EXCEPTION; - } + return switch (provider) { + case KAKAO -> kakaoOauthHelper.getUserInfo(oauthAccessToken); + default -> throw InvalidOauthProviderException.EXCEPTION; + }; } } diff --git a/Core/src/main/java/allchive/server/core/error/GlobalErrorCode.java b/Core/src/main/java/allchive/server/core/error/GlobalErrorCode.java index 027c58ae..aff876e4 100644 --- a/Core/src/main/java/allchive/server/core/error/GlobalErrorCode.java +++ b/Core/src/main/java/allchive/server/core/error/GlobalErrorCode.java @@ -14,7 +14,7 @@ public enum GlobalErrorCode implements BaseErrorCode { /** Server 오류 * */ HTTP_MESSAGE_NOT_READABLE(BAD_REQUEST, "GLOBAL_400_1", "잘못된 형식의 값을 입력했습니다."), - NO_APPLE_ACCESS_TOKEN(BAD_REQUEST, "GLOBAL_400_2", "애플 엑세스 토큰이 필요합니다."), + NO_APPLE_CODE(BAD_REQUEST, "GLOBAL_400_2", "애플 코드가 필요합니다."), EMPTY_PARAM_VALUE(BAD_REQUEST, "GLOBAL_400_3", "빈 파람 값을 입력했습니다."), _INTERNAL_SERVER_ERROR(INTERNAL_SERVER, "GLOBAL_500_1", "서버 오류. 관리자에게 문의 부탁드립니다."), INVALID_OAUTH_PROVIDER(INTERNAL_SERVER, "GLOBAL_500_2", "지원하지 않는 OAuth Provider 입니다."), diff --git a/Core/src/main/java/allchive/server/core/error/exception/NoAppleAccessTokenException.java b/Core/src/main/java/allchive/server/core/error/exception/NoAppleCodeException.java similarity index 54% rename from Core/src/main/java/allchive/server/core/error/exception/NoAppleAccessTokenException.java rename to Core/src/main/java/allchive/server/core/error/exception/NoAppleCodeException.java index 09954b42..b8b60c03 100644 --- a/Core/src/main/java/allchive/server/core/error/exception/NoAppleAccessTokenException.java +++ b/Core/src/main/java/allchive/server/core/error/exception/NoAppleCodeException.java @@ -4,11 +4,11 @@ import allchive.server.core.error.BaseErrorException; import allchive.server.core.error.GlobalErrorCode; -public class NoAppleAccessTokenException extends BaseErrorException { +public class NoAppleCodeException extends BaseErrorException { - public static final BaseErrorException EXCEPTION = new NoAppleAccessTokenException(); + public static final BaseErrorException EXCEPTION = new NoAppleCodeException(); - private NoAppleAccessTokenException() { - super(GlobalErrorCode.NO_APPLE_ACCESS_TOKEN); + private NoAppleCodeException() { + super(GlobalErrorCode.NO_APPLE_CODE); } } From 1c2783f979a253e1cb8300d0386b141252eed77d Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Wed, 16 Aug 2023 16:19:29 +0900 Subject: [PATCH 31/34] =?UTF-8?q?[feat]=20=EA=B2=80=EC=83=89=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=20response=EC=97=90=20=EC=B4=9D=20=EA=B2=80=EC=83=89?= =?UTF-8?q?=20=EA=B2=B0=EA=B3=BC=20=EA=B0=9C=EC=88=98=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=20(#107)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [feat] 검색 response page로 전환 #106 * [chore] spotless 적용 #106 --- .../api/auth/service/WithdrawUserUseCase.java | 3 +++ .../server/api/common/page/PageResponse.java | 23 ++++++++++++++++ .../model/dto/response/SearchResponse.java | 16 +++++------- .../service/SearchArchivingUseCase.java | 20 +++++++------- .../server/domain/common/util/PageUtil.java | 26 +++++++++++++++++++ .../archiving/adaptor/ArchivingAdaptor.java | 5 ++-- .../repository/ArchivingCustomRepository.java | 5 ++-- .../ArchivingCustomRepositoryImpl.java | 19 ++++++++------ 8 files changed, 86 insertions(+), 31 deletions(-) create mode 100644 Api/src/main/java/allchive/server/api/common/page/PageResponse.java create mode 100644 Domain/src/main/java/allchive/server/domain/common/util/PageUtil.java diff --git a/Api/src/main/java/allchive/server/api/auth/service/WithdrawUserUseCase.java b/Api/src/main/java/allchive/server/api/auth/service/WithdrawUserUseCase.java index 8a51428c..28aaf10f 100644 --- a/Api/src/main/java/allchive/server/api/auth/service/WithdrawUserUseCase.java +++ b/Api/src/main/java/allchive/server/api/auth/service/WithdrawUserUseCase.java @@ -7,6 +7,7 @@ import allchive.server.core.error.exception.InvalidOauthProviderException; import allchive.server.domain.domains.archiving.adaptor.ArchivingAdaptor; import allchive.server.domain.domains.archiving.domain.Archiving; +import allchive.server.domain.domains.archiving.service.ArchivingDomainService; import allchive.server.domain.domains.block.service.BlockDomainService; import allchive.server.domain.domains.content.adaptor.TagAdaptor; import allchive.server.domain.domains.content.domain.Tag; @@ -43,6 +44,7 @@ public class WithdrawUserUseCase { private final RecycleDomainService recycleDomainService; private final ReportDomainService reportDomainService; private final UserDomainService userDomainService; + private final ArchivingDomainService archivingDomainService; @Transactional public void execute(String appleAccessToken, String referer) { @@ -94,6 +96,7 @@ private void withdrawService(Long userId, User user) { contentDomainService.deleteAllByArchivingIdIn(archivingId); recycleDomainService.deleteAllByUserId(userId); reportDomainService.deleteAllByReportedUserId(userId); + archivingDomainService.deleteAllById(archivingId); userDomainService.deleteUserById(userId); } } diff --git a/Api/src/main/java/allchive/server/api/common/page/PageResponse.java b/Api/src/main/java/allchive/server/api/common/page/PageResponse.java new file mode 100644 index 00000000..1617d1c5 --- /dev/null +++ b/Api/src/main/java/allchive/server/api/common/page/PageResponse.java @@ -0,0 +1,23 @@ +package allchive.server.api.common.page; + + +import java.util.List; +import org.springframework.data.domain.Page; + +public record PageResponse( + List content, + int page, + int size, + long totalElements, + int totalPages, + boolean hasNextPage) { + public static PageResponse of(Page page) { + return new PageResponse<>( + page.getContent(), + page.getNumber(), + page.getNumberOfElements(), + page.getTotalElements(), + page.getTotalPages(), + page.hasNext()); + } +} diff --git a/Api/src/main/java/allchive/server/api/search/model/dto/response/SearchResponse.java b/Api/src/main/java/allchive/server/api/search/model/dto/response/SearchResponse.java index 7d9c7f78..bafccfef 100644 --- a/Api/src/main/java/allchive/server/api/search/model/dto/response/SearchResponse.java +++ b/Api/src/main/java/allchive/server/api/search/model/dto/response/SearchResponse.java @@ -2,34 +2,32 @@ import allchive.server.api.archiving.model.dto.response.ArchivingResponse; -import allchive.server.api.common.slice.SliceResponse; +import allchive.server.api.common.page.PageResponse; import lombok.Builder; import lombok.Getter; @Getter public class SearchResponse { - SliceResponse archivings; - SliceResponse community; + PageResponse archivings; + PageResponse community; @Builder private SearchResponse( - SliceResponse archivings, - SliceResponse community) { + PageResponse archivings, PageResponse community) { this.archivings = archivings; this.community = community; } public static SearchResponse forAll( - SliceResponse archivings, - SliceResponse community) { + PageResponse archivings, PageResponse community) { return SearchResponse.builder().archivings(archivings).community(community).build(); } - public static SearchResponse forMy(SliceResponse archivings) { + public static SearchResponse forMy(PageResponse archivings) { return SearchResponse.builder().archivings(archivings).community(null).build(); } - public static SearchResponse forCommunity(SliceResponse community) { + public static SearchResponse forCommunity(PageResponse community) { return SearchResponse.builder().archivings(null).community(community).build(); } } diff --git a/Api/src/main/java/allchive/server/api/search/service/SearchArchivingUseCase.java b/Api/src/main/java/allchive/server/api/search/service/SearchArchivingUseCase.java index ddb55a13..168ca036 100644 --- a/Api/src/main/java/allchive/server/api/search/service/SearchArchivingUseCase.java +++ b/Api/src/main/java/allchive/server/api/search/service/SearchArchivingUseCase.java @@ -2,7 +2,7 @@ import allchive.server.api.archiving.model.dto.response.ArchivingResponse; -import allchive.server.api.common.slice.SliceResponse; +import allchive.server.api.common.page.PageResponse; import allchive.server.api.common.util.StringParamUtil; import allchive.server.api.config.security.SecurityUtil; import allchive.server.api.search.model.dto.response.SearchResponse; @@ -23,8 +23,8 @@ import java.util.Set; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Slice; import org.springframework.transaction.annotation.Transactional; @UseCase @@ -43,8 +43,8 @@ public SearchResponse execute(Pageable pageable, ArchivingType type, String word validateExecution(word); Long userId = SecurityUtil.getCurrentUserId(); Set tagArchivingIds = getTagArchivingIds(userId, word); - SliceResponse my; - SliceResponse community; + PageResponse my; + PageResponse community; renewalLatestSearch(userId, word); switch (type) { case ALL -> { @@ -93,23 +93,23 @@ private boolean isExistSearchKeyword(List searches, String keyword .isEmpty(); } - private SliceResponse getMyArchivings( + private PageResponse getMyArchivings( Long userId, String keyword, Pageable pageable, Set tagArchivingIds) { - Slice archivingSlices = + Page archivingPages = archivingAdaptor .querySliceArchivingByUserIdAndKeywordsOrderByTagArchvingIds( userId, keyword, pageable, tagArchivingIds) .map(archiving -> ArchivingResponse.of(archiving, Boolean.FALSE)); - return SliceResponse.of(archivingSlices); + return PageResponse.of(archivingPages); } - private SliceResponse getCommunityArchivings( + private PageResponse getCommunityArchivings( Long userId, String keyword, Pageable pageable, Set tagArchivingIds) { List archivingIdList = scrapAdaptor.findAllByUserId(userId).stream().map(Scrap::getArchivingId).toList(); List blockList = blockAdaptor.findByBlockFrom(userId).stream().map(Block::getBlockUser).toList(); - Slice archivingSlices = + Page archivingSlices = archivingAdaptor .querySliceArchivingByKeywordExceptBlockOrderByTagArchvingIds( archivingIdList, @@ -119,6 +119,6 @@ private SliceResponse getCommunityArchivings( tagArchivingIds, userId) .map(archiving -> ArchivingResponse.of(archiving, Boolean.FALSE)); - return SliceResponse.of(archivingSlices); + return PageResponse.of(archivingSlices); } } diff --git a/Domain/src/main/java/allchive/server/domain/common/util/PageUtil.java b/Domain/src/main/java/allchive/server/domain/common/util/PageUtil.java new file mode 100644 index 00000000..c725c81f --- /dev/null +++ b/Domain/src/main/java/allchive/server/domain/common/util/PageUtil.java @@ -0,0 +1,26 @@ +package allchive.server.domain.common.util; + + +import com.querydsl.core.QueryResults; +import java.util.List; +import org.springframework.data.domain.*; + +public class PageUtil { + public static Page toPage(QueryResults results, Pageable pageable) { + boolean hasNext = hasNext(results.getResults(), pageable); + return new PageImpl<>( + hasNext ? getContent(results.getResults(), pageable) : results.getResults(), + pageable, + results.getTotal()); + } + + // 다음 페이지 있는지 확인 + private static boolean hasNext(List content, Pageable pageable) { + return pageable.isPaged() && content.size() > pageable.getPageSize(); + } + + // 데이터 1개 빼고 반환 + private static List getContent(List content, Pageable pageable) { + return content.subList(0, pageable.getPageSize()); + } +} diff --git a/Domain/src/main/java/allchive/server/domain/domains/archiving/adaptor/ArchivingAdaptor.java b/Domain/src/main/java/allchive/server/domain/domains/archiving/adaptor/ArchivingAdaptor.java index baf05a7b..bf008e5f 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/archiving/adaptor/ArchivingAdaptor.java +++ b/Domain/src/main/java/allchive/server/domain/domains/archiving/adaptor/ArchivingAdaptor.java @@ -10,6 +10,7 @@ import java.util.List; import java.util.Set; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; @@ -74,13 +75,13 @@ public void deleteAllById(List archivingIds) { archivingRepository.deleteAllById(archivingIds); } - public Slice querySliceArchivingByUserIdAndKeywordsOrderByTagArchvingIds( + public Page querySliceArchivingByUserIdAndKeywordsOrderByTagArchvingIds( Long userId, String keyword, Pageable pageable, Set tagArchivingIds) { return archivingRepository.querySliceArchivingByUserIdAndKeywordsOrderByTagArchvingIds( userId, keyword, pageable, tagArchivingIds); } - public Slice querySliceArchivingByKeywordExceptBlockOrderByTagArchvingIds( + public Page querySliceArchivingByKeywordExceptBlockOrderByTagArchvingIds( List archivingIdList, List blockList, String keyword, diff --git a/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepository.java b/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepository.java index af10a2e7..90ff7449 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepository.java +++ b/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepository.java @@ -5,6 +5,7 @@ import allchive.server.domain.domains.archiving.domain.enums.Category; import java.util.List; import java.util.Set; +import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; @@ -21,10 +22,10 @@ Slice querySliceArchivingByIdIn( boolean queryArchivingExistById(Long archivingId); - Slice querySliceArchivingByUserIdAndKeywordsOrderByTagArchvingIds( + Page querySliceArchivingByUserIdAndKeywordsOrderByTagArchvingIds( Long userId, String keyword, Pageable pageable, Set tagArchivingIds); - Slice querySliceArchivingByKeywordExceptBlockOrderByTagArchvingIds( + Page querySliceArchivingByKeywordExceptBlockOrderByTagArchvingIds( List archivingIdList, List blockList, String keyword, diff --git a/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepositoryImpl.java b/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepositoryImpl.java index e55765c3..a5934c30 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepositoryImpl.java +++ b/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepositoryImpl.java @@ -3,9 +3,11 @@ import static allchive.server.core.consts.AllchiveConst.PLUS_ONE; import static allchive.server.domain.domains.archiving.domain.QArchiving.archiving; +import allchive.server.domain.common.util.PageUtil; import allchive.server.domain.common.util.SliceUtil; import allchive.server.domain.domains.archiving.domain.Archiving; import allchive.server.domain.domains.archiving.domain.enums.Category; +import com.querydsl.core.QueryResults; import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.core.types.dsl.CaseBuilder; @@ -15,6 +17,7 @@ import java.util.List; import java.util.Set; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; @@ -95,9 +98,9 @@ public boolean queryArchivingExistById(Long archivingId) { } @Override - public Slice querySliceArchivingByUserIdAndKeywordsOrderByTagArchvingIds( + public Page querySliceArchivingByUserIdAndKeywordsOrderByTagArchvingIds( Long userId, String keyword, Pageable pageable, Set tagArchivingIds) { - List archivings = + QueryResults results = queryFactory .selectFrom(archiving) .where( @@ -107,19 +110,19 @@ public Slice querySliceArchivingByUserIdAndKeywordsOrderByTagArchving .orderBy(idIn(tagArchivingIds), createdAtDesc()) .offset(pageable.getOffset()) .limit(pageable.getPageSize() + PLUS_ONE) - .fetch(); - return SliceUtil.toSlice(archivings, pageable); + .fetchResults(); + return PageUtil.toPage(results, pageable); } @Override - public Slice querySliceArchivingByKeywordExceptBlockOrderByTagArchvingIds( + public Page querySliceArchivingByKeywordExceptBlockOrderByTagArchvingIds( List archivingIdList, List blockList, String keyword, Pageable pageable, Set tagArchivingIds, Long userId) { - List archivings = + QueryResults archivings = queryFactory .select(archiving) .from(archiving) @@ -135,8 +138,8 @@ public Slice querySliceArchivingByKeywordExceptBlockOrderByTagArchvin createdAtDesc()) .offset(pageable.getOffset()) .limit(pageable.getPageSize() + PLUS_ONE) - .fetch(); - return SliceUtil.toSlice(archivings, pageable); + .fetchResults(); + return PageUtil.toPage(archivings, pageable); } @Override From 7797de4796525dc3dd3d5331c2bb7f77eb163604 Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Thu, 17 Aug 2023 11:13:26 +0900 Subject: [PATCH 32/34] =?UTF-8?q?[feat]=20=EA=B2=80=EC=83=89=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=88=98=EC=A0=95=20(#109)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [fix] 검색 로직 수정 #108 * [chore] spotless 적용 #108 * [feat] archiving response 변경 #108 --- .../model/dto/response/ArchivingContentsResponse.java | 9 ++++++++- .../repository/ArchivingCustomRepositoryImpl.java | 6 +++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingContentsResponse.java b/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingContentsResponse.java index 22ce8d96..f74ca7d3 100644 --- a/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingContentsResponse.java +++ b/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingContentsResponse.java @@ -7,6 +7,7 @@ import allchive.server.domain.domains.archiving.domain.enums.Category; import allchive.server.domain.domains.user.domain.User; import io.swagger.v3.oas.annotations.media.Schema; +import java.time.LocalDateTime; import lombok.Builder; import lombok.Getter; @@ -23,6 +24,9 @@ public class ArchivingContentsResponse { @Schema(description = "아카이빙 고유번호") private Long archivingId; + @Schema(description = "아카이빙 생성일") + private LocalDateTime createdAt; + @Schema(description = "아카이빙의 총 컨텐츠 개수") private Long totalContentsCount; @@ -47,6 +51,7 @@ private ArchivingContentsResponse( String archivingTitle, Category category, Long archivingId, + LocalDateTime createdAt, Long totalContentsCount, Long ownerId, String ownerNickname, @@ -57,6 +62,7 @@ private ArchivingContentsResponse( this.archivingTitle = archivingTitle; this.category = category; this.archivingId = archivingId; + this.createdAt = createdAt; this.totalContentsCount = totalContentsCount; this.ownerId = ownerId; this.ownerNickname = ownerNickname; @@ -73,9 +79,10 @@ public static ArchivingContentsResponse of( Boolean isScrap) { return ArchivingContentsResponse.builder() .archivingId(archiving.getId()) + .createdAt(archiving.getCreatedAt()) .archivingTitle(archiving.getTitle()) .category(archiving.getCategory()) - .totalContentsCount(archiving.getScrapCnt() + archiving.getImgCnt()) + .totalContentsCount(archiving.getLinkCnt() + archiving.getImgCnt()) .contents(contentResponseSlice) .ownerId(user.getId()) .ownerNickname(user.getNickname()) diff --git a/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepositoryImpl.java b/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepositoryImpl.java index a5934c30..6eb736aa 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepositoryImpl.java +++ b/Domain/src/main/java/allchive/server/domain/domains/archiving/repository/ArchivingCustomRepositoryImpl.java @@ -128,7 +128,7 @@ public Page querySliceArchivingByKeywordExceptBlockOrderByTagArchving .from(archiving) .where( userIdNotIn(blockList), - userIdEqOrPublicStatusTrue(userId), + userIdNeAndPublicStatusTrue(userId), deleteStatusFalse(), titleContainOrIdIn(keyword, tagArchivingIds)) .orderBy( @@ -191,6 +191,10 @@ private BooleanExpression userIdEqOrPublicStatusTrue(Long userId) { return archiving.userId.eq(userId).or(archiving.publicStatus.eq(Boolean.TRUE)); } + private BooleanExpression userIdNeAndPublicStatusTrue(Long userId) { + return archiving.userId.ne(userId).and(archiving.publicStatus.eq(Boolean.TRUE)); + } + private OrderSpecifier scrabListDesc(List archivingIdList) { NumberExpression pinStatus = new CaseBuilder().when(archiving.id.in(archivingIdList)).then(1L).otherwise(0L); From 43221ccd408423780f7a4b479a4f81e3bb7be442 Mon Sep 17 00:00:00 2001 From: wjdtkdgns Date: Thu, 17 Aug 2023 15:08:45 +0900 Subject: [PATCH 33/34] =?UTF-8?q?[feat]=20archiving=20content=20response?= =?UTF-8?q?=20dateFormating=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../archiving/model/dto/response/ArchivingContentsResponse.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingContentsResponse.java b/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingContentsResponse.java index f74ca7d3..6e17c9bf 100644 --- a/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingContentsResponse.java +++ b/Api/src/main/java/allchive/server/api/archiving/model/dto/response/ArchivingContentsResponse.java @@ -3,6 +3,7 @@ import allchive.server.api.common.slice.SliceResponse; import allchive.server.api.content.model.dto.response.ContentResponse; +import allchive.server.core.annotation.DateFormat; import allchive.server.domain.domains.archiving.domain.Archiving; import allchive.server.domain.domains.archiving.domain.enums.Category; import allchive.server.domain.domains.user.domain.User; @@ -24,6 +25,7 @@ public class ArchivingContentsResponse { @Schema(description = "아카이빙 고유번호") private Long archivingId; + @DateFormat @Schema(description = "아카이빙 생성일") private LocalDateTime createdAt; From 70ca231a5aa9744de6c09d820566ca5ed96cd333 Mon Sep 17 00:00:00 2001 From: Sanghoon Jeong <67852689+wjdtkdgns@users.noreply.github.com> Date: Fri, 18 Aug 2023 22:05:11 +0900 Subject: [PATCH 34/34] =?UTF-8?q?[feat]=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=EC=8B=9C=20=EC=9C=A0=EC=A0=80=20=EB=A7=88=EC=BC=80?= =?UTF-8?q?=ED=8C=85,=20=EC=95=8C=EB=9E=8C=20=EB=8F=99=EC=9D=98=20?= =?UTF-8?q?=EC=97=AC=EB=B6=80=20=ED=8F=AC=ED=95=A8=20(#111)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [feat] user 엔티티 마케팅 정보 동의 속성 추가, 회원가입 로직 수정 #110 * [chore] spotless 적용 #110 --- .../api/auth/controller/OauthController.java | 10 ++++++++++ .../auth/model/dto/request/RegisterRequest.java | 3 +++ .../server/api/auth/service/OauthLoginUseCase.java | 7 +++++++ .../api/auth/service/OauthRegisterUseCase.java | 14 ++++++++++++++ .../server/domain/domains/user/domain/User.java | 6 ++++++ .../domains/user/service/UserDomainService.java | 11 ++++++++++- 6 files changed, 50 insertions(+), 1 deletion(-) diff --git a/Api/src/main/java/allchive/server/api/auth/controller/OauthController.java b/Api/src/main/java/allchive/server/api/auth/controller/OauthController.java index ccf41e44..d3272f59 100644 --- a/Api/src/main/java/allchive/server/api/auth/controller/OauthController.java +++ b/Api/src/main/java/allchive/server/api/auth/controller/OauthController.java @@ -86,4 +86,14 @@ public OauthRegisterResponse oauthUserRegister( @RequestBody RegisterRequest registerRequest) { return oauthRegisterUseCase.execute(provider, idToken, accessToken, registerRequest); } + + @Operation(summary = "회원가입 (개발용)", deprecated = true) + @PostMapping("/register/{provider}/dev") + public OauthRegisterResponse oauthUserRegisterDev( + @PathVariable("provider") OauthProvider provider, + @RequestParam("idToken") String idToken, + @RequestParam(value = "oauthAccessToken", required = false) String accessToken, + @RequestBody RegisterRequest registerRequest) { + return oauthRegisterUseCase.executeDev(provider, idToken, accessToken, registerRequest); + } } diff --git a/Api/src/main/java/allchive/server/api/auth/model/dto/request/RegisterRequest.java b/Api/src/main/java/allchive/server/api/auth/model/dto/request/RegisterRequest.java index 8abf6ebb..4dd83eae 100644 --- a/Api/src/main/java/allchive/server/api/auth/model/dto/request/RegisterRequest.java +++ b/Api/src/main/java/allchive/server/api/auth/model/dto/request/RegisterRequest.java @@ -27,6 +27,9 @@ public class RegisterRequest { @ArraySchema(schema = @Schema(description = "관심 주제", defaultValue = "FOOD")) private List<@ValidEnum(target = Category.class) Category> categories; + @Schema(defaultValue = "false", description = "마케팅 정보 수신 동의 여부") + private boolean marketingAgreement; + @Schema(defaultValue = "이름", description = "이름, 애플 회원가입용") private String name; diff --git a/Api/src/main/java/allchive/server/api/auth/service/OauthLoginUseCase.java b/Api/src/main/java/allchive/server/api/auth/service/OauthLoginUseCase.java index cb5f3edf..a15974dd 100644 --- a/Api/src/main/java/allchive/server/api/auth/service/OauthLoginUseCase.java +++ b/Api/src/main/java/allchive/server/api/auth/service/OauthLoginUseCase.java @@ -6,19 +6,23 @@ import allchive.server.api.auth.service.helper.OauthHelper; import allchive.server.api.auth.service.helper.TokenGenerateHelper; import allchive.server.core.annotation.UseCase; +import allchive.server.core.helper.SpringEnvironmentHelper; import allchive.server.domain.domains.user.domain.User; import allchive.server.domain.domains.user.domain.enums.OauthInfo; import allchive.server.domain.domains.user.domain.enums.OauthProvider; import allchive.server.domain.domains.user.service.UserDomainService; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.transaction.annotation.Transactional; @UseCase +@Slf4j @RequiredArgsConstructor public class OauthLoginUseCase { private final OauthHelper oauthHelper; private final UserDomainService userDomainService; private final TokenGenerateHelper tokenGenerateHelper; + private final SpringEnvironmentHelper springEnvironmentHelper; @Transactional public OauthSignInResponse loginWithCode(OauthProvider provider, String code, String referer) { @@ -35,6 +39,9 @@ public OauthSignInResponse loginWithIdToken(OauthProvider provider, String idTok @Transactional public OauthSignInResponse devLogin(OauthProvider provider, String code) { final OauthTokenResponse oauthTokenResponse = oauthHelper.getCredentialDev(provider, code); + if (!springEnvironmentHelper.isProdProfile()) { + log.info("{}", oauthTokenResponse.getAccessToken()); + } return processLoginWithIdTokenDev(provider, oauthTokenResponse.getIdToken()); } diff --git a/Api/src/main/java/allchive/server/api/auth/service/OauthRegisterUseCase.java b/Api/src/main/java/allchive/server/api/auth/service/OauthRegisterUseCase.java index c06db03e..8bb08449 100644 --- a/Api/src/main/java/allchive/server/api/auth/service/OauthRegisterUseCase.java +++ b/Api/src/main/java/allchive/server/api/auth/service/OauthRegisterUseCase.java @@ -34,6 +34,18 @@ public OauthRegisterResponse execute( return OauthRegisterResponse.from(tokenGenerateHelper.execute(user)); } + @Transactional + public OauthRegisterResponse executeDev( + OauthProvider provider, + String idToken, + String oauthAccessToken, + RegisterRequest request) { + final OauthInfo oauthInfo = oauthHelper.getOauthInfoDev(provider, idToken); + final OauthUserInfoDto oauthUserInfoDto = getUserInfo(provider, oauthAccessToken); + final User user = registerUser(provider, oauthInfo, oauthUserInfoDto, request); + return OauthRegisterResponse.from(tokenGenerateHelper.execute(user)); + } + private User registerUser( OauthProvider provider, OauthInfo oauthInfo, @@ -47,6 +59,7 @@ private User registerUser( request.getNickname(), UrlUtil.convertUrlToKey(request.getProfileImgUrl()), request.getCategories(), + request.isMarketingAgreement(), oauthInfo); default: return userDomainService.registerUser( @@ -55,6 +68,7 @@ private User registerUser( request.getNickname(), UrlUtil.convertUrlToKey(request.getProfileImgUrl()), request.getCategories(), + request.isMarketingAgreement(), oauthInfo); } } diff --git a/Domain/src/main/java/allchive/server/domain/domains/user/domain/User.java b/Domain/src/main/java/allchive/server/domain/domains/user/domain/User.java index 1e253f05..016e069f 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/user/domain/User.java +++ b/Domain/src/main/java/allchive/server/domain/domains/user/domain/User.java @@ -46,6 +46,8 @@ public class User extends BaseTimeEntity { @Enumerated(EnumType.STRING) private UserRole userRole = UserRole.USER; + private boolean marketingAgreement = false; + @Convert(converter = StringListConverter.class) private List categories = new ArrayList<>(); @@ -56,12 +58,14 @@ private User( String nickname, String profileImgUrl, List categoryList, + boolean marketingAgreement, OauthInfo oauthInfo) { this.name = name; this.email = email; this.nickname = nickname; this.profileImgUrl = profileImgUrl; this.categories = categoryList; + this.marketingAgreement = marketingAgreement; this.oauthInfo = oauthInfo; this.lastLoginAt = LocalDateTime.now(); } @@ -72,6 +76,7 @@ public static User of( String nickname, String profileImgUrl, List categoryList, + boolean marketingAgreement, OauthInfo oauthInfo) { return User.builder() .name(name) @@ -79,6 +84,7 @@ public static User of( .nickname(nickname) .profileImgUrl(profileImgUrl) .categoryList(categoryList) + .marketingAgreement(marketingAgreement) .oauthInfo(oauthInfo) .build(); } diff --git a/Domain/src/main/java/allchive/server/domain/domains/user/service/UserDomainService.java b/Domain/src/main/java/allchive/server/domain/domains/user/service/UserDomainService.java index 0b14420e..e34cad15 100644 --- a/Domain/src/main/java/allchive/server/domain/domains/user/service/UserDomainService.java +++ b/Domain/src/main/java/allchive/server/domain/domains/user/service/UserDomainService.java @@ -29,9 +29,18 @@ public User registerUser( String nickname, String profileImgUrl, List categoryList, + boolean marketingAgreement, OauthInfo oauthInfo) { userValidator.validUserCanRegister(oauthInfo); - final User newUser = User.of(name, email, nickname, profileImgUrl, categoryList, oauthInfo); + final User newUser = + User.of( + name, + email, + nickname, + profileImgUrl, + categoryList, + marketingAgreement, + oauthInfo); userAdaptor.save(newUser); return newUser; }