From d8dbf571363fff1a5a703026dd96427cdb8998fa Mon Sep 17 00:00:00 2001 From: Whitedoggy Date: Fri, 10 Oct 2025 10:04:41 +0900 Subject: [PATCH 1/5] =?UTF-8?q?fix/OPS-390=20:=20secret=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=EB=B0=8F=20=EC=88=98=EC=A0=95=20=EC=82=AC?= =?UTF-8?q?=ED=95=AD=EC=97=90=20=EB=A7=9E=EA=B2=8C=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EB=B3=80=EC=88=98=EB=AA=85=20=EB=B3=80=EA=B2=BD.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/handler/OAuth2FailureHandler.java | 2 +- .../auth/handler/OAuth2SuccessHandler.java | 2 +- .../application-secrets.yml.template | 70 +++++-------------- 3 files changed, 18 insertions(+), 56 deletions(-) diff --git a/src/main/java/org/tuna/zoopzoop/backend/domain/auth/handler/OAuth2FailureHandler.java b/src/main/java/org/tuna/zoopzoop/backend/domain/auth/handler/OAuth2FailureHandler.java index cb8f6dc5..5d823084 100644 --- a/src/main/java/org/tuna/zoopzoop/backend/domain/auth/handler/OAuth2FailureHandler.java +++ b/src/main/java/org/tuna/zoopzoop/backend/domain/auth/handler/OAuth2FailureHandler.java @@ -15,7 +15,7 @@ @Component @RequiredArgsConstructor public class OAuth2FailureHandler implements AuthenticationFailureHandler { - @Value("${front.redirect_domain}") + @Value("${REDIRECT_DOMAIN}") private String redirect_domain; @Override diff --git a/src/main/java/org/tuna/zoopzoop/backend/domain/auth/handler/OAuth2SuccessHandler.java b/src/main/java/org/tuna/zoopzoop/backend/domain/auth/handler/OAuth2SuccessHandler.java index 2e076056..051c34c8 100644 --- a/src/main/java/org/tuna/zoopzoop/backend/domain/auth/handler/OAuth2SuccessHandler.java +++ b/src/main/java/org/tuna/zoopzoop/backend/domain/auth/handler/OAuth2SuccessHandler.java @@ -38,7 +38,7 @@ public class OAuth2SuccessHandler extends SimpleUrlAuthenticationSuccessHandler private final RefreshTokenService refreshTokenService; private final AuthResult authResult; - @Value("${front.redirect_domain}") + @Value("${REDIRECT_DOMAIN}") private String redirect_domain; @Value("${spring.profiles.active:dev}") diff --git a/src/main/resources/application-secrets.yml.template b/src/main/resources/application-secrets.yml.template index 8f7e5116..97b5f5d3 100644 --- a/src/main/resources/application-secrets.yml.template +++ b/src/main/resources/application-secrets.yml.template @@ -1,55 +1,17 @@ -spring: - security: - oauth2: - client: - registration: - kakao: - client-id: {KAKAO_CLIENT_ID} - client-secret: "" - redirect-uri: {KAKAO_REDIRECT_URL} - scope: - - {SCOPE_LIST} - authorization-grant-type: {AUTHORIZATION_GRANT_TYPE} - google: - client-id: {GOOGLE_CLIENT_ID} - client-secret: {GOOGLE_SECRET} - redirect-uri: {GOOGLE_REDIRECT_URL} - scope: - - {SCOPE_LIST} - authorization-grant-type: {AUTHORIZATION_GRANT_TYPE} - provider: - kakao: - authorization-uri: https://kauth.kakao.com/oauth/authorize - token-uri: https://kauth.kakao.com/oauth/token - user-info-uri: https://kapi.kakao.com/v2/user/me - user-name-attribute: id - google: - authorization-uri: https://accounts.google.com/o/oauth2/v2/auth - token-uri: https://oauth2.googleapis.com/token - user-info-uri: https://www.googleapis.com/oauth2/v3/userinfo - user-name-attribute: sub - cloud: - aws: - credentials: - access-key: {AWS_ACCESS_KEY} - secret-key: {AWS_SECRET_KEY} - region: - static: {AWS_REGION} - s3: - bucket: {AWS_S3_BUCKET_NAME} - stack: - auto: false +OPENAI_API_KEY: {YOUR_VALUE} +KAKAO_CLIENT_ID: {YOUR_VALUE} +GOOGLE_CLIENT_ID: {YOUR_VALUE} +GOOGLE_CLIENT_SECRET: {YOUR_VALUE} +AWS_ACCESS_KEY_ID: {YOUR_VALUE} +AWS_SECRET_ACCESS_KEY: {YOUR_VALUE} +AWS_S3_BUCKET_NAME: {YOUR_VALUE} +SENTRY_DSN: {YOUR_VALUE} +JWT_SECRET_KEY: {YOUR_VALUE} +JWT_ACCESS_TOKEN_VALIDITY: {YOUR_VALUE} +JWT_REFRESH_TOKEN_VALIDITY: {YOUR_VALUE} +NAVER_CLIENT_ID: {YOUR_VALUE} +NAVER_CLIENT_SECRET: {YOUR_VALUE} +LIVEBLOCKS_SECRET_KEY: {YOUR_VALUE} +REDIRECT_DOMAIN: {YOUR_VALUE} -naver: - client_id: {NAVER_CLIENT_ID} - client_secret: {NAVER_CLIENT_SECRET} - -jwt: - secret-key: {JWT_SECRET_KEY} - access-token-validity: {ACCESSTOKEN_VALIDITY} - refresh-token-validity: {REFRESHTOKEN_VALIDITY} - -OPENAI_API_KEY: {OPENAI_API_KEY} - -liveblocks: - secret-key: {LIVEBLOCKS_SECRET_KEY} \ No newline at end of file +#SENTRY_AUTH_TOKEN -> 따로 시스템 환경 변수로 설정. \ No newline at end of file From a73c731dc58241282f5e712136eecfa552e77d93 Mon Sep 17 00:00:00 2001 From: Whitedoggy Date: Fri, 10 Oct 2025 10:36:06 +0900 Subject: [PATCH 2/5] =?UTF-8?q?feat/OPS-390:=20NEWS=20API=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EC=B6=94=EA=B0=80=20=EC=82=AC=ED=95=AD=20=EB=B0=98?= =?UTF-8?q?=EC=98=81.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../news/controller/ApiV1NewsController.java | 30 +++++++++++++++++++ .../domain/news/service/NewsService.java | 30 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/src/main/java/org/tuna/zoopzoop/backend/domain/news/controller/ApiV1NewsController.java b/src/main/java/org/tuna/zoopzoop/backend/domain/news/controller/ApiV1NewsController.java index 078ad563..4b4959e5 100644 --- a/src/main/java/org/tuna/zoopzoop/backend/domain/news/controller/ApiV1NewsController.java +++ b/src/main/java/org/tuna/zoopzoop/backend/domain/news/controller/ApiV1NewsController.java @@ -26,6 +26,7 @@ public class ApiV1NewsController { private final NewsAPIService newsSearchService; private final NewsService newsService; + /** * 최신 뉴스 목록을 조회하는 API * 한번에 100개를 조회 합니다. @@ -98,4 +99,33 @@ public Mono>> searchNewsByRecommends( response ))); } + + /** + * 공유 아카이브의 폴더 내부의 자료를 기반으로 키워드를 추천해서 검색하는 뉴스 API + * HTTP METHOD: GET + * 한번에 100개를 조회 합니다. + * @param userDetails 로그인한 사용자 + * @param spaceId 대상 스페이스 id + * @param folderId 대상 폴더 id + */ + @GetMapping("/recommends/shared/{spaceId}/{folderId}") + @Operation(summary = "개인 아카이브 뉴스 추천") + public Mono>> searchNewsByRecommends( + @AuthenticationPrincipal CustomUserDetails userDetails, + @PathVariable Integer spaceId, + @PathVariable Integer folderId + ) { + Member member = userDetails.getMember(); + List frequency = newsService.getTagFrequencyFromFilesInSharing(spaceId, member.getId(), folderId); + String query = String.join(" ", frequency); + + return newsSearchService.searchNews(query, "sim") + .map(response -> ResponseEntity + .status(HttpStatus.OK) + .body(new RsData<>( + "200", + "키워드 기반 뉴스 목록을 조회했습니다.", + response + ))); + } } diff --git a/src/main/java/org/tuna/zoopzoop/backend/domain/news/service/NewsService.java b/src/main/java/org/tuna/zoopzoop/backend/domain/news/service/NewsService.java index b6b89221..6613898d 100644 --- a/src/main/java/org/tuna/zoopzoop/backend/domain/news/service/NewsService.java +++ b/src/main/java/org/tuna/zoopzoop/backend/domain/news/service/NewsService.java @@ -5,6 +5,9 @@ import org.tuna.zoopzoop.backend.domain.archive.folder.service.PersonalArchiveFolderService; import org.tuna.zoopzoop.backend.domain.datasource.dto.FileSummary; import org.tuna.zoopzoop.backend.domain.datasource.dto.FolderFilesDto; +import org.tuna.zoopzoop.backend.domain.member.entity.Member; +import org.tuna.zoopzoop.backend.domain.member.service.MemberService; +import org.tuna.zoopzoop.backend.domain.space.archive.service.SpaceArchiveFolderService; import java.util.Comparator; import java.util.List; @@ -15,6 +18,8 @@ @RequiredArgsConstructor public class NewsService { private final PersonalArchiveFolderService folderService; + private final SpaceArchiveFolderService spaceArchiveFolderService; + private final MemberService memberService; public List getTagFrequencyFromFiles(Integer memberId, Integer folderId) { FolderFilesDto folderFilesDto = folderService.getFilesInFolder(memberId, folderId); @@ -39,4 +44,29 @@ public List getTagFrequencyFromFiles(Integer memberId, Integer folderId) return frequency; } + + public List getTagFrequencyFromFilesInSharing(Integer spaceId, Integer memberId, Integer folderId) { + Member member = memberService.findById(memberId); + FolderFilesDto folderFilesDto = spaceArchiveFolderService.getFilesInFolder(spaceId, member, folderId); + + List files = folderFilesDto.files(); + + Map tags = files.stream() + .flatMap(file -> { + List ts = file.tags(); + return (ts == null ? List.of() : ts).stream(); + }) + .collect(Collectors.groupingBy( + tagName -> tagName, + Collectors.counting() + )); + + List frequency = tags.entrySet().stream() + .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) + .limit(3) + .map(Map.Entry::getKey) + .toList(); + + return frequency; + } } From 81644be34437e92ffb32860e4b46f1e21b3a0846 Mon Sep 17 00:00:00 2001 From: Whitedoggy Date: Fri, 10 Oct 2025 11:35:11 +0900 Subject: [PATCH 3/5] =?UTF-8?q?feat/OPS-390:=20CI=20=EC=9B=8C=ED=81=AC?= =?UTF-8?q?=ED=94=8C=EB=A1=9C=EC=9A=B0=20=EC=9D=BC=EB=B6=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test-server-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test-server-ci.yml b/.github/workflows/test-server-ci.yml index d9b7c694..153b0789 100644 --- a/.github/workflows/test-server-ci.yml +++ b/.github/workflows/test-server-ci.yml @@ -68,6 +68,7 @@ jobs: - name: Test with Gradle # 테스트 단계에서 RabbitMQ 연결을 위한 환경 변수 설정 env: + SPRING_PROFILES_ACTIVE: test OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} SPRING_RABBITMQ_HOST: localhost SPRING_RABBITMQ_USERNAME: guest From cb34a6bc2967943ebad70ab3ec8575614042cd88 Mon Sep 17 00:00:00 2001 From: Whitedoggy Date: Fri, 10 Oct 2025 11:50:02 +0900 Subject: [PATCH 4/5] =?UTF-8?q?feat/OPS-390:=20=EC=9D=BC=EB=B6=80=20placeh?= =?UTF-8?q?olders=20=EC=88=98=EC=A0=95.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/auth/handler/OAuth2FailureHandler.java | 2 +- .../backend/domain/auth/handler/OAuth2SuccessHandler.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/tuna/zoopzoop/backend/domain/auth/handler/OAuth2FailureHandler.java b/src/main/java/org/tuna/zoopzoop/backend/domain/auth/handler/OAuth2FailureHandler.java index 5d823084..cb8f6dc5 100644 --- a/src/main/java/org/tuna/zoopzoop/backend/domain/auth/handler/OAuth2FailureHandler.java +++ b/src/main/java/org/tuna/zoopzoop/backend/domain/auth/handler/OAuth2FailureHandler.java @@ -15,7 +15,7 @@ @Component @RequiredArgsConstructor public class OAuth2FailureHandler implements AuthenticationFailureHandler { - @Value("${REDIRECT_DOMAIN}") + @Value("${front.redirect_domain}") private String redirect_domain; @Override diff --git a/src/main/java/org/tuna/zoopzoop/backend/domain/auth/handler/OAuth2SuccessHandler.java b/src/main/java/org/tuna/zoopzoop/backend/domain/auth/handler/OAuth2SuccessHandler.java index 051c34c8..2e076056 100644 --- a/src/main/java/org/tuna/zoopzoop/backend/domain/auth/handler/OAuth2SuccessHandler.java +++ b/src/main/java/org/tuna/zoopzoop/backend/domain/auth/handler/OAuth2SuccessHandler.java @@ -38,7 +38,7 @@ public class OAuth2SuccessHandler extends SimpleUrlAuthenticationSuccessHandler private final RefreshTokenService refreshTokenService; private final AuthResult authResult; - @Value("${REDIRECT_DOMAIN}") + @Value("${front.redirect_domain}") private String redirect_domain; @Value("${spring.profiles.active:dev}") From 5b0ce8c03e792ed5358c75fa9e2e7bee20dfa9b7 Mon Sep 17 00:00:00 2001 From: Whitedoggy Date: Fri, 10 Oct 2025 12:04:21 +0900 Subject: [PATCH 5/5] =?UTF-8?q?feat/OPS-390:=20=EC=9D=BC=EB=B6=80=20?= =?UTF-8?q?=EB=AC=B8=EC=84=9C=ED=99=94=20=ED=95=AD=EB=AA=A9=20=EC=88=98?= =?UTF-8?q?=EC=A0=95.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/news/controller/ApiV1NewsController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/tuna/zoopzoop/backend/domain/news/controller/ApiV1NewsController.java b/src/main/java/org/tuna/zoopzoop/backend/domain/news/controller/ApiV1NewsController.java index 4b4959e5..59d8fac8 100644 --- a/src/main/java/org/tuna/zoopzoop/backend/domain/news/controller/ApiV1NewsController.java +++ b/src/main/java/org/tuna/zoopzoop/backend/domain/news/controller/ApiV1NewsController.java @@ -109,7 +109,7 @@ public Mono>> searchNewsByRecommends( * @param folderId 대상 폴더 id */ @GetMapping("/recommends/shared/{spaceId}/{folderId}") - @Operation(summary = "개인 아카이브 뉴스 추천") + @Operation(summary = "공유 아카이브 뉴스 추천") public Mono>> searchNewsByRecommends( @AuthenticationPrincipal CustomUserDetails userDetails, @PathVariable Integer spaceId,