diff --git a/archunit-baseline/4d025d0f-f5d7-4e6b-b9f8-e044d0950c24 b/archunit-baseline/4d025d0f-f5d7-4e6b-b9f8-e044d0950c24 index 9be28508..e69de29b 100644 --- a/archunit-baseline/4d025d0f-f5d7-4e6b-b9f8-e044d0950c24 +++ b/archunit-baseline/4d025d0f-f5d7-4e6b-b9f8-e044d0950c24 @@ -1,50 +0,0 @@ -Constructor (com.carecode.domain.user.repository.UserRepository)> has parameter of type in (CurrentUserFacade.java:0) -Constructor (com.carecode.domain.user.repository.UserRepository)> has parameter of type in (CustomUserDetailsService.java:0) -Constructor (com.carecode.domain.user.service.JwtService)> has parameter of type in (JwtAuthenticationFilter.java:0) -Field has type in (CurrentUserFacade.java:0) -Field has type in (CustomUserDetailsService.java:0) -Field has type in (JwtAuthenticationFilter.java:0) -Method calls method in (CustomizedResponseEntityExceptionHandler.java:114) -Method calls method in (CustomizedResponseEntityExceptionHandler.java:115) -Method calls method in (CustomizedResponseEntityExceptionHandler.java:113) -Method calls method in (CustomizedResponseEntityExceptionHandler.java:109) -Method calls method in (CustomizedResponseEntityExceptionHandler.java:113) -Method calls method in (CustomizedResponseEntityExceptionHandler.java:114) -Method calls method in (CustomizedResponseEntityExceptionHandler.java:115) -Method calls method in (CustomizedResponseEntityExceptionHandler.java:116) -Method has annotation member of type in (CustomizedResponseEntityExceptionHandler.java:0) -Method has parameter of type in (CustomizedResponseEntityExceptionHandler.java:0) -Method calls method in (CurrentUserFacade.java:58) -Method has generic return type > with type argument depending on in (CurrentUserFacade.java:0) -Method calls method in (CurrentUserFacade.java:115) -Method calls method in (CurrentUserFacade.java:115) -Method calls method in (CurrentUserFacade.java:112) -Method has parameter of type in (CurrentUserFacade.java:0) -Method calls method in (CurrentUserFacade.java:63) -Method has return type in (CurrentUserFacade.java:0) -Method calls method in (CurrentUserFacade.java:72) -Method calls method in (CurrentUserFacade.java:68) -Method calls method in (CurrentUserFacade.java:96) -Method has return type in (CurrentUserFacade.java:0) -Method has return type in (CurrentUserFacade.java:0) -Method calls method in (CustomUserDetailsService.java:27) -Method calls method in (CustomUserDetailsService.java:30) -Method calls method in (CustomUserDetailsService.java:22) -Method calls method in (CustomUserDetailsService.java:29) -Method calls method in (CustomUserDetailsService.java:29) -Method calls method in (CustomUserDetailsService.java:20) -Method calls method in (JwtAuthenticationFilter.java:71) -Method calls method in (JwtAuthenticationFilter.java:72) -Method calls method in (JwtAuthenticationFilter.java:70) -Method calls method in (JwtAuthenticationFilter.java:64) -Method calls method in (KakaoUtil.java:119) -Method calls method in (KakaoUtil.java:127) -Method calls method in (KakaoUtil.java:147) -Method calls method in (KakaoUtil.java:151) -Method has parameter of type in (KakaoUtil.java:0) -Method has return type in (KakaoUtil.java:0) -Method references class object in (KakaoUtil.java:145) -Method calls method in (KakaoUtil.java:99) -Method calls method in (KakaoUtil.java:99) -Method has return type in (KakaoUtil.java:0) -Method references class object in (KakaoUtil.java:97) diff --git a/archunit-baseline/a6b21c55-f3df-4514-8faa-c32628f81448 b/archunit-baseline/a6b21c55-f3df-4514-8faa-c32628f81448 index 419c90dc..37d68a02 100644 --- a/archunit-baseline/a6b21c55-f3df-4514-8faa-c32628f81448 +++ b/archunit-baseline/a6b21c55-f3df-4514-8faa-c32628f81448 @@ -54,7 +54,7 @@ admin → notification 리포지토리: Method (com.carecode.domain.user.repository.UserRepository, com.carecode.domain.health.repository.HospitalRepository, com.carecode.domain.policy.repository.PolicyRepository)> has parameter of type in (AdminDashboardService.java:0) admin → policy 리포지토리: Constructor (com.carecode.domain.policy.repository.PolicyRepository, com.carecode.domain.policy.repository.PolicyCategoryRepository, com.fasterxml.jackson.databind.ObjectMapper)> has parameter of type in (PolicyAdminService.java:0) admin → policy 리포지토리: Constructor (com.carecode.domain.policy.repository.PolicyRepository, com.carecode.domain.policy.repository.PolicyCategoryRepository, com.fasterxml.jackson.databind.ObjectMapper)> has parameter of type in (PolicyAdminService.java:0) -admin → policy 리포지토리: Constructor (com.carecode.domain.policy.repository.PolicyRepository, com.carecode.core.security.CurrentUserFacade)> has parameter of type in (PolicyVerificationService.java:0) +admin → policy 리포지토리: Constructor (com.carecode.domain.policy.repository.PolicyRepository, com.carecode.domain.user.app.CurrentUserFacade)> has parameter of type in (PolicyVerificationService.java:0) admin → policy 리포지토리: Field has type in (AdminDashboardService.java:0) admin → policy 리포지토리: Field has type in (PolicyAdminService.java:0) admin → policy 리포지토리: Field has type in (PolicyAdminService.java:0) @@ -111,8 +111,8 @@ chatbot → user 리포지토리: Field calls method in (ChatbotService.java:382) chatbot → user 리포지토리: Method calls method in (ChatbotService.java:381) community → user 리포지토리: Constructor (com.carecode.domain.community.repository.PostRepository, com.carecode.domain.community.repository.TagRepository, com.carecode.domain.user.repository.UserRepository, org.springframework.security.crypto.password.PasswordEncoder)> has parameter of type in (CommunityInitializationService.java:0) -community → user 리포지토리: Constructor (com.carecode.domain.community.repository.PostRepository, com.carecode.domain.community.repository.CommentRepository, com.carecode.domain.community.repository.TagRepository, com.carecode.domain.user.repository.UserRepository, com.carecode.domain.community.repository.PostLikeRepository, com.carecode.domain.community.repository.BookmarkRepository, com.carecode.domain.community.mapper.CommunityMapper, com.carecode.core.security.CurrentUserFacade)> has parameter of type in (CommunityService.java:0) -community → user 리포지토리: Constructor (com.carecode.domain.community.repository.ReportRepository, com.carecode.domain.community.repository.UserBlockRepository, com.carecode.domain.community.repository.PostRepository, com.carecode.domain.community.repository.CommentRepository, com.carecode.domain.user.repository.UserRepository, com.carecode.core.security.CurrentUserFacade)> has parameter of type in (ModerationService.java:0) +community → user 리포지토리: Constructor (com.carecode.domain.community.repository.PostRepository, com.carecode.domain.community.repository.CommentRepository, com.carecode.domain.community.repository.TagRepository, com.carecode.domain.user.repository.UserRepository, com.carecode.domain.community.repository.PostLikeRepository, com.carecode.domain.community.repository.BookmarkRepository, com.carecode.domain.community.mapper.CommunityMapper, com.carecode.domain.user.app.CurrentUserFacade)> has parameter of type in (CommunityService.java:0) +community → user 리포지토리: Constructor (com.carecode.domain.community.repository.ReportRepository, com.carecode.domain.community.repository.UserBlockRepository, com.carecode.domain.community.repository.PostRepository, com.carecode.domain.community.repository.CommentRepository, com.carecode.domain.user.repository.UserRepository, com.carecode.domain.user.app.CurrentUserFacade)> has parameter of type in (ModerationService.java:0) community → user 리포지토리: Field has type in (CommunityInitializationService.java:0) community → user 리포지토리: Field has type in (CommunityService.java:0) community → user 리포지토리: Field has type in (ModerationService.java:0) @@ -137,13 +137,13 @@ facility → user 리포지토리: Method calls method in (CareFacilityService.java:390) facility → user 리포지토리: Method calls method in (CareFacilityService.java:380) health → facility 리포지토리: Constructor (com.carecode.domain.health.repository.HealthRecordRepository, com.carecode.domain.health.service.HealthActorResolver, com.carecode.domain.user.app.ChildDirectory, com.carecode.domain.policy.repository.PolicyRepository, com.carecode.domain.facility.repository.CareFacilityRepository)> has parameter of type in (HealthInsightService.java:0) -health → facility 리포지토리: Constructor (com.carecode.domain.user.repository.ChildRepository, com.carecode.domain.health.repository.VaccinationScheduleRepository, com.carecode.domain.facility.repository.FacilityWaitlistRepository, com.carecode.domain.policy.repository.PolicyRepository, com.carecode.core.security.CurrentUserFacade)> has parameter of type in (SiblingOverviewService.java:0) +health → facility 리포지토리: Constructor (com.carecode.domain.user.repository.ChildRepository, com.carecode.domain.health.repository.VaccinationScheduleRepository, com.carecode.domain.facility.repository.FacilityWaitlistRepository, com.carecode.domain.policy.repository.PolicyRepository, com.carecode.domain.user.app.CurrentUserFacade)> has parameter of type in (SiblingOverviewService.java:0) health → facility 리포지토리: Field has type in (HealthInsightService.java:0) health → facility 리포지토리: Field has type in (SiblingOverviewService.java:0) health → facility 리포지토리: Method calls method in (HealthInsightService.java:113) health → facility 리포지토리: Method calls method in (SiblingOverviewService.java:91) health → policy 리포지토리: Constructor (com.carecode.domain.health.repository.HealthRecordRepository, com.carecode.domain.health.service.HealthActorResolver, com.carecode.domain.user.app.ChildDirectory, com.carecode.domain.policy.repository.PolicyRepository, com.carecode.domain.facility.repository.CareFacilityRepository)> has parameter of type in (HealthInsightService.java:0) -health → policy 리포지토리: Constructor (com.carecode.domain.user.repository.ChildRepository, com.carecode.domain.health.repository.VaccinationScheduleRepository, com.carecode.domain.facility.repository.FacilityWaitlistRepository, com.carecode.domain.policy.repository.PolicyRepository, com.carecode.core.security.CurrentUserFacade)> has parameter of type in (SiblingOverviewService.java:0) +health → policy 리포지토리: Constructor (com.carecode.domain.user.repository.ChildRepository, com.carecode.domain.health.repository.VaccinationScheduleRepository, com.carecode.domain.facility.repository.FacilityWaitlistRepository, com.carecode.domain.policy.repository.PolicyRepository, com.carecode.domain.user.app.CurrentUserFacade)> has parameter of type in (SiblingOverviewService.java:0) health → policy 리포지토리: Constructor (com.carecode.domain.health.service.ChildService, com.carecode.domain.health.repository.VaccinationScheduleRepository, com.carecode.domain.health.repository.HealthRecordRepository, com.carecode.domain.policy.repository.PolicyRepository)> has parameter of type in (ChildTimelineService.java:0) health → policy 리포지토리: Field has type in (HealthInsightService.java:0) health → policy 리포지토리: Field has type in (SiblingOverviewService.java:0) @@ -152,11 +152,11 @@ health → policy 리포지토리: Method calls method in (SiblingOverviewService.java:101) health → policy 리포지토리: Method calls method in (ChildTimelineService.java:180) health → user 리포지토리: Constructor (com.carecode.domain.health.service.HealthService, com.carecode.domain.health.service.HealthInsightService, com.carecode.domain.health.repository.HospitalRepository, com.carecode.core.ops.sync.SyncFreshnessService, com.carecode.domain.health.repository.HospitalLikeRepository, com.carecode.domain.health.repository.HospitalReviewRepository, com.carecode.domain.health.mapper.HospitalMapper, com.carecode.domain.health.mapper.HospitalReviewMapper, com.carecode.domain.user.repository.UserRepository)> has parameter of type in (HealthFacade.java:0) -health → user 리포지토리: Constructor (com.carecode.domain.user.repository.ChildRepository, com.carecode.domain.user.app.ChildDirectory, com.carecode.domain.health.mapper.ChildMapper, com.carecode.core.security.CurrentUserFacade, com.carecode.domain.health.service.VaccinationScheduleService, com.carecode.core.analytics.EventLogger)> has parameter of type in (ChildService.java:0) -health → user 리포지토리: Constructor (com.carecode.domain.user.repository.ChildRepository, com.carecode.domain.user.app.ChildDirectory, com.carecode.domain.health.repository.HealthRecordRepository, com.carecode.core.security.CurrentUserFacade)> has parameter of type in (GrowthChartService.java:0) +health → user 리포지토리: Constructor (com.carecode.domain.user.repository.ChildRepository, com.carecode.domain.user.app.ChildDirectory, com.carecode.domain.health.mapper.ChildMapper, com.carecode.domain.user.app.CurrentUserFacade, com.carecode.domain.health.service.VaccinationScheduleService, com.carecode.core.analytics.EventLogger)> has parameter of type in (ChildService.java:0) +health → user 리포지토리: Constructor (com.carecode.domain.user.repository.ChildRepository, com.carecode.domain.user.app.ChildDirectory, com.carecode.domain.health.repository.HealthRecordRepository, com.carecode.domain.user.app.CurrentUserFacade)> has parameter of type in (GrowthChartService.java:0) health → user 리포지토리: Constructor (com.carecode.domain.user.repository.UserRepository)> has parameter of type in (HealthActorResolver.java:0) health → user 리포지토리: Constructor (com.carecode.domain.health.repository.HealthRecordRepository, com.carecode.domain.user.service.ConsentGuard, com.carecode.domain.health.repository.HealthRecordAttachmentRepository, com.carecode.domain.health.service.HealthActorResolver, com.carecode.domain.user.repository.ChildRepository, com.carecode.domain.user.app.ChildDirectory, com.carecode.domain.health.mapper.HealthRecordMapper)> has parameter of type in (HealthService.java:0) -health → user 리포지토리: Constructor (com.carecode.domain.user.repository.ChildRepository, com.carecode.domain.health.repository.VaccinationScheduleRepository, com.carecode.domain.facility.repository.FacilityWaitlistRepository, com.carecode.domain.policy.repository.PolicyRepository, com.carecode.core.security.CurrentUserFacade)> has parameter of type in (SiblingOverviewService.java:0) +health → user 리포지토리: Constructor (com.carecode.domain.user.repository.ChildRepository, com.carecode.domain.health.repository.VaccinationScheduleRepository, com.carecode.domain.facility.repository.FacilityWaitlistRepository, com.carecode.domain.policy.repository.PolicyRepository, com.carecode.domain.user.app.CurrentUserFacade)> has parameter of type in (SiblingOverviewService.java:0) health → user 리포지토리: Constructor (com.carecode.domain.health.repository.VaccinationScheduleRepository, com.carecode.domain.user.repository.ChildRepository)> has parameter of type in (VaccinationScheduleService.java:0) health → user 리포지토리: Field has type in (HealthFacade.java:0) health → user 리포지토리: Field has type in (ChildService.java:0) @@ -229,9 +229,9 @@ policy → user 리포지토리: Method calls method in (PolicyDeadlineNotifier.java:101) policy → user 리포지토리: Method calls method in (PolicyService.java:264) policy → user 리포지토리: Method calls method in (PolicyService.java:263) -user → community 리포지토리: Constructor (com.carecode.domain.user.repository.UserConsentRepository, com.carecode.domain.user.repository.UserRepository, com.carecode.domain.user.repository.ChildRepository, com.carecode.domain.health.repository.HealthRecordRepository, com.carecode.domain.community.repository.PostRepository, com.carecode.core.security.CurrentUserFacade)> has parameter of type in (PrivacyService.java:0) +user → community 리포지토리: Constructor (com.carecode.domain.user.repository.UserConsentRepository, com.carecode.domain.user.repository.UserRepository, com.carecode.domain.user.repository.ChildRepository, com.carecode.domain.health.repository.HealthRecordRepository, com.carecode.domain.community.repository.PostRepository, com.carecode.domain.user.app.CurrentUserFacade)> has parameter of type in (PrivacyService.java:0) user → community 리포지토리: Field has type in (PrivacyService.java:0) user → community 리포지토리: Method calls method in (PrivacyService.java:109) -user → health 리포지토리: Constructor (com.carecode.domain.user.repository.UserConsentRepository, com.carecode.domain.user.repository.UserRepository, com.carecode.domain.user.repository.ChildRepository, com.carecode.domain.health.repository.HealthRecordRepository, com.carecode.domain.community.repository.PostRepository, com.carecode.core.security.CurrentUserFacade)> has parameter of type in (PrivacyService.java:0) +user → health 리포지토리: Constructor (com.carecode.domain.user.repository.UserConsentRepository, com.carecode.domain.user.repository.UserRepository, com.carecode.domain.user.repository.ChildRepository, com.carecode.domain.health.repository.HealthRecordRepository, com.carecode.domain.community.repository.PostRepository, com.carecode.domain.user.app.CurrentUserFacade)> has parameter of type in (PrivacyService.java:0) user → health 리포지토리: Field has type in (PrivacyService.java:0) user → health 리포지토리: Method calls method in (PrivacyService.java:108) diff --git a/archunit-baseline/74b2056c-4f0e-4cb3-af35-0cfdcc359eeb b/archunit-baseline/ef0b66c5-984e-4d22-8249-4d73a7a1a013 similarity index 100% rename from archunit-baseline/74b2056c-4f0e-4cb3-af35-0cfdcc359eeb rename to archunit-baseline/ef0b66c5-984e-4d22-8249-4d73a7a1a013 diff --git a/archunit-baseline/stored.rules b/archunit-baseline/stored.rules index 4e9db0e5..b9c699ab 100644 --- a/archunit-baseline/stored.rules +++ b/archunit-baseline/stored.rules @@ -1,11 +1,11 @@ # -#Mon Oct 05 01:50:57 KST 2026 +#Thu Oct 22 17:32:46 KST 2026 no\ classes\ that\ reside\ in\ a\ package\ '..entity..'\ should\ depend\ on\ classes\ that\ reside\ in\ any\ package\ ['..dto..',\ '..controller..'],\ because\ API\ \uBAA8\uC591\uC774\ \uBC14\uB014\ \uB54C\ \uD14C\uC774\uBE14\ \uB9E4\uD551\uC774\ \uD568\uAED8\ \uD754\uB4E4\uB9AC\uBA74\ \uC548\ \uB41C\uB2E4=87360be1-7d6d-4423-b366-16fa4fe6f6b6 +no\ classes\ that\ reside\ in\ a\ package\ 'com.carecode.domain..'\ and\ do\ not\ have\ fully\ qualified\ name\ 'com.carecode.domain.user.app.CurrentUserFacade'\ should\ depend\ on\ classes\ that\ have\ fully\ qualified\ name\ 'org.springframework.security.core.context.SecurityContextHolder',\ because\ \uD604\uC7AC\ \uC0AC\uC6A9\uC790\uB294\ CurrentUserFacade\ \uB85C\uB9CC\ \uC5BB\uB294\uB2E4=ef0b66c5-984e-4d22-8249-4d73a7a1a013 no\ classes\ that\ reside\ in\ a\ package\ 'com.carecode.core..'\ should\ be\ annotated\ with\ @RestController\ or\ should\ be\ annotated\ with\ @Controller,\ because\ API\ \uB294\ \uB3C4\uBA54\uC778\ \uD328\uD0A4\uC9C0\uC5D0\ \uB454\uB2E4.\ core\ \uC5D0\ \uC788\uC73C\uBA74\ \uC18C\uC18D\uC744\ \uC54C\ \uC218\ \uC5C6\uB2E4=ab7a1eba-4dd5-499e-95ed-0c71f0b6f61f classes\ that\ reside\ in\ a\ package\ 'com.carecode.domain..'\ should\ \uC18C\uBB38\uC790\ \uB3C4\uBA54\uC778\ \uD328\uD0A4\uC9C0\uC5D0\ \uC788\uB2E4,\ because\ \uD55C\ \uAD70\uB370\uB9CC\ \uB2E4\uB978\ \uADDC\uCE59\uC774\uBA74\ \uC0C8\uB85C\ \uB4E4\uC5B4\uC628\ \uC0AC\uB78C\uC774\ \uB458\ \uB2E4\ \uD749\uB0B4\ \uB0B8\uB2E4=05a7a88e-9a95-451a-b96f-4a8eb9be6c1e classes\ that\ reside\ in\ a\ package\ 'com.carecode.domain..'\ should\ \uB2E4\uB978\ \uB3C4\uBA54\uC778\uC758\ \uB9AC\uD3EC\uC9C0\uD1A0\uB9AC\uB97C\ \uC9C1\uC811\ \uCC38\uC870\uD558\uC9C0\ \uC54A\uB294\uB2E4,\ because\ \uB0A8\uC758\ \uB3C4\uBA54\uC778\ \uD14C\uC774\uBE14\uC744\ \uC9C1\uC811\ \uC77D\uC73C\uBA74\ \uADF8\ \uB3C4\uBA54\uC778\uC774\ \uC9C0\uD0A4\uB294\ \uADDC\uCE59(\uC18C\uC720\uAD8C\ \uAC80\uC99D\ \uB4F1)\uC744\ \uAC74\uB108\uB6F4\uB2E4=a6b21c55-f3df-4514-8faa-c32628f81448 no\ classes\ that\ reside\ in\ any\ package\ ['com.carecode.core.security..',\ 'com.carecode.core.web..',\ 'com.carecode.core.handler..',\ 'com.carecode.core.config..',\ 'com.carecode.core.storage..',\ 'com.carecode.core.util..',\ 'com.carecode.core.monitoring..',\ 'com.carecode.core.aspect..',\ 'com.carecode.core.annotation..',\ 'com.carecode.core.constants..',\ 'com.carecode.core.components..',\ 'com.carecode.core.ops..']\ should\ depend\ on\ classes\ that\ reside\ in\ a\ package\ 'com.carecode.domain..',\ because\ \uAE30\uBC18\ \uCF54\uB4DC\uAC00\ \uD2B9\uC815\ \uB3C4\uBA54\uC778\uC744\ \uC54C\uBA74\ \uADF8\ \uB3C4\uBA54\uC778\uC758\ \uC77C\uBD80\uC9C0,\ \uACF5\uD1B5\uC774\ \uC544\uB2C8\uB2E4=4d025d0f-f5d7-4e6b-b9f8-e044d0950c24 no\ classes\ that\ have\ simple\ name\ ending\ with\ 'Mapper'\ should\ depend\ on\ classes\ that\ have\ simple\ name\ ending\ with\ 'Repository',\ because\ \uBCC0\uD658\ \uD55C\ \uBC88\uC5D0\ \uCFFC\uB9AC\uAC00\ \uC228\uC5B4\ \uB4E4\uBA74\ N+1\ \uC744\ \uCD94\uC801\uD560\ \uC218\ \uC5C6\uB2E4=fb482b80-693f-4971-aa10-71da548d267d -no\ classes\ that\ reside\ in\ a\ package\ 'com.carecode.domain..'\ should\ depend\ on\ classes\ that\ have\ fully\ qualified\ name\ 'org.springframework.security.core.context.SecurityContextHolder',\ because\ \uD604\uC7AC\ \uC0AC\uC6A9\uC790\uB294\ CurrentUserFacade\ \uB85C\uB9CC\ \uC5BB\uB294\uB2E4=74b2056c-4f0e-4cb3-af35-0cfdcc359eeb no\ classes\ that\ have\ simple\ name\ ending\ with\ 'Controller'\ should\ depend\ on\ classes\ that\ have\ simple\ name\ ending\ with\ 'Repository',\ because\ \uAC80\uC99D\uACFC\ \uD2B8\uB79C\uC7AD\uC158\ \uACBD\uACC4\uB294\ \uC11C\uBE44\uC2A4\uC5D0\ \uB454\uB2E4=05a5820d-39ea-4db6-b8e7-f737ac6a90df no\ classes\ that\ reside\ in\ any\ package\ ['..service..',\ '..repository..']\ should\ depend\ on\ classes\ that\ reside\ in\ a\ package\ '..controller..',\ because\ \uD638\uCD9C\ \uBC29\uD5A5\uC740\ \uCEE8\uD2B8\uB864\uB7EC\ \u2192\ \uC11C\uBE44\uC2A4\ \u2192\ \uB9AC\uD3EC\uC9C0\uD1A0\uB9AC\ \uD55C\ \uCABD\uC774\uB2E4=d1434e17-b3a6-4ae9-a8f3-86c5e4bd1c05 diff --git a/docs/quality/architecture-rules.md b/docs/quality/architecture-rules.md index 6dda8640..c6c4d758 100644 --- a/docs/quality/architecture-rules.md +++ b/docs/quality/architecture-rules.md @@ -31,8 +31,8 @@ ArchUnit 의 `FreezingArchRule` 을 씁니다. ## 규칙과 현재 위반 -진척: **489건(0단계) → 391건(1b) → 364건(4a) → 357건(5b) → 331건(6) → 291건(7단계)**. 남은 것은 -도메인 경계(237)와 core 기반의 도메인 참조(50)입니다. **컨트롤러의 리포지토리 직접 사용은 0 이 됐습니다.** +진척: **489건(0단계) → 364건(4a) → 331건(6) → 291건(7) → 241건(8단계)**. 남은 것은 거의 전부 +도메인 경계(237)입니다. **컨트롤러의 리포지토리 직접 사용과 core 기반의 도메인 참조는 0 이 됐습니다.** > 세는 법: `archunit-baseline/` 에는 규칙별 위반 파일 외에 색인 파일 `stored.rules` 도 있습니다. > `cat archunit-baseline/* | wc -l` 은 색인 11줄을 함께 세므로 실제 위반보다 11 크게 나옵니다. @@ -42,10 +42,10 @@ ArchUnit 의 `FreezingArchRule` 을 씁니다. | 다른 도메인의 리포지토리를 직접 쓰지 않는다 | 237 | 남의 테이블을 직접 읽으면 그 도메인의 규칙(소유권 검증 등)을 건너뛴다 | | 도메인 패키지 이름은 소문자다 | **0** | `careFacility`→`facility` 로 해소 (1b 단계) | | 컨트롤러는 리포지토리를 직접 쓰지 않는다 | **0** | 7단계에서 해소 | 검증·트랜잭션 경계가 컨트롤러로 샌다 | -| core 기반 패키지는 domain 을 의존하지 않는다 | 50 | 기반 코드가 도메인을 알면 공통이 아니다 | +| core 기반 패키지는 domain 을 의존하지 않는다 | **0** | 8단계에서 해소 | | 매퍼는 리포지토리를 쓰지 않는다 | 3 | 변환 한 번에 숨은 쿼리가 생기면 N+1 을 추적할 수 없다 | | core 에는 컨트롤러가 없다 | **0** | 1a 에서 도메인으로 옮기고, 3a 에서 중복이라 삭제 | -| 도메인은 SecurityContextHolder 를 직접 쓰지 않는다 | 1 | principal 모양이 바뀌면 고칠 곳이 흩어진다(시설 API 500 의 원인) | +| 도메인은 SecurityContextHolder 를 직접 쓰지 않는다 | 1 (파사드 제외) | principal 모양이 바뀌면 고칠 곳이 흩어진다(시설 API 500 의 원인) | | 서비스·리포지토리는 컨트롤러를 의존하지 않는다 | **0** | 층 방향은 이미 지켜지고 있다 | | 엔티티는 DTO·컨트롤러를 의존하지 않는다 | **0** | 매핑 경계는 지켜지고 있다 | @@ -526,6 +526,53 @@ not to be equal to: "d14eb045@example.com" - 전체 테스트 **647개, 실패 0** - OpenAPI 경로·스키마 수 변화 없음(226 / 158) +## 기반 코드가 사용자 도메인을 알던 자리 (8단계) + +"core 기반 패키지는 domain 을 의존하지 않는다" 위반 50건은 **전부 인증·인가 기반 코드**였습니다. +다섯 덩어리였고, 각각 원인이 달랐습니다. + +| 어디 | 무엇을 알고 있었나 | 어떻게 끊었나 | +|------|---------------------|---------------| +| `CurrentUserFacade` (15) | `User`, `UserRepository` | **이 클래스가 곧 사용자 도메인의 입구**다. `domain/user/app` 으로 옮겼다 | +| `KakaoUtil` (11) | `KakaoOAuthToken`, `KakaoProfile` … | 카카오 **응답 형식**이 우리 API 응답 패키지(`user/dto/response`)에 있었다. 클라이언트와 DTO 6개를 `external/kakao` 로 옮겼다 | +| 전역 예외 핸들러 (10) | `ConsentGuard` | `ConsentRequiredException` 이 **서비스 안의 중첩 클래스**여서, 예외를 가리키려면 서비스를 import 해야 했다 | +| `CustomUserDetailsService` (8) | `User`, `UserRepository` | `domain/user/security` 로 옮기고, `SecurityConfig` 는 스프링의 `UserDetailsService` **인터페이스**로 받는다 | +| `JwtAuthenticationFilter` (6) | `JwtService` | 필터는 토큰 검증만 필요한데 그 서비스는 로그인 응답 DTO 까지 다룬다. `AccessTokenVerifier` 포트로 필요한 만큼만 끊었다 | + +### 옮기는 방향이 중요했다 + +세 건은 **core 에서 도메인으로** 옮겼습니다(`CurrentUserFacade`, `CustomUserDetailsService`, +카카오 DTO). 나머지 둘은 **반대로** 핸들러·필터가 도메인을 보지 않도록 경계를 세웠습니다 +(`core/exception` 의 예외, `core/security` 의 포트). + +기준은 "누가 그 규칙의 주인인가" 였습니다. 자격 증명으로 사용자를 찾는 일과 현재 사용자를 +꺼내는 일은 사용자 도메인의 규칙입니다. 반대로 토큰 서명 검증과 예외 → HTTP 상태 변환은 +기반 코드의 일이고, 그쪽이 도메인 타입을 알 필요가 없습니다. + +### 규칙도 한 줄 고쳤다 + +`CurrentUserFacade` 가 도메인으로 들어오자 "도메인은 `SecurityContextHolder` 를 직접 쓰지 +않는다" 에 걸렸습니다 — 그 클래스의 존재 이유가 바로 그 접근을 혼자 하는 것인데도요. +규칙의 `because` 가 이미 "현재 사용자는 CurrentUserFacade 로만 얻는다" 라고 적고 있으므로 +**파사드 자신만 예외**로 두었습니다. 남은 1건(`CommunityService` 가 직접 꺼내는 곳)은 그대로 +추적합니다. + +> 규칙 문구를 고치면 ArchUnit 이 새 키로 baseline 을 만들고 **옛 파일은 고아로 남습니다.** +> 자동으로 지워지지 않아 손으로 정리했습니다(`stored.rules` 의 줄 + 해당 파일). + +### 카카오 DTO 가 잘못된 자리에 있었던 것이 실제 문제였다 + +`KakaoProfile`·`KakaoAccount`·`KakaoProperties`·`KakaoProfileInfo`·`KakaoOAuthToken` 은 +**카카오가 주는 JSON 모양**입니다(필드명이 `connected_at`, `thumbnail_image_url` 처럼 snake_case +인 것이 그 증거). 그것이 `domain/user/dto/response` — 우리가 **프런트에 주는** 응답을 모아 둔 +패키지 — 에 섞여 있었습니다. 카카오가 응답을 바꾸면 우리 API 응답 패키지가 바뀌는 셈입니다. + +### 숫자 + +- **core 기반 → 도메인 참조 50 → 0** +- ArchUnit baseline 291 → **241** (고아 baseline 1개 정리 포함) +- 남은 241건 중 **237건이 도메인 경계** 한 규칙입니다 + ## 다음 단계 | 단계 | 내용 | 효과 | @@ -543,4 +590,5 @@ not to be equal to: "d14eb045@example.com" | ~~6. 어드민 컨트롤러의 리포지토리 사용~~ | ~~61건 전부가 어드민 컨트롤러에 있었다~~ | **완료** — 61 → 37, 버그 둘 | | 7. 식별 로직을 user 로 | `HealthActorResolver` 가 health 의 마지막 `UserRepository` 사용처다 | 결합 추가 해소 | | ~~7. 남은 컨트롤러 6개~~ | ~~대시보드·사용자·정책·검증·링크 2개~~ | **완료** — 37 → **0**, 버그 둘 | -| 8. 어드민 조회용 포트 | 도메인 경계 237건 중 어드민 몫. 각 도메인이 어드민 조회 입구를 내주면 사라진다 | 경계 완성 | +| ~~8. core 기반의 도메인 참조~~ | ~~인증·인가 기반 코드가 user 도메인을 알고 있었다~~ | **완료** — 50 → **0** | +| 9. 어드민 조회용 포트 | 도메인 경계 237건 중 어드민 몫. 각 도메인이 어드민 조회 입구를 내주면 사라진다 | 경계 완성 | diff --git a/src/main/java/com/carecode/core/exception/ConsentRequiredException.java b/src/main/java/com/carecode/core/exception/ConsentRequiredException.java new file mode 100644 index 00000000..cfce9ee5 --- /dev/null +++ b/src/main/java/com/carecode/core/exception/ConsentRequiredException.java @@ -0,0 +1,42 @@ +package com.carecode.core.exception; + +/** + * 동의가 없어 막혔음을 클라이언트가 구분할 수 있게 하는 예외. + * + *

전역 예외 핸들러가 이것을 잡아 "어떤 동의가 필요한가" 를 응답에 담는다. 그래서 동의 종류를 + * 문자열로 들고 있다 — 열거형을 들고 있으면 {@code core/exception} 과 핸들러가 모두 + * 사용자 도메인의 {@code ConsentType} 을 알아야 한다. 응답은 JSON 이라 어차피 문자열이고, + * 종류를 추가하는 일은 도메인 쪽에서만 일어난다. + * + *

한때 이 예외는 {@code ConsentGuard} 안의 중첩 클래스였고, 그래서 웹 계층이 사용자 + * 도메인의 서비스를 import 해야 예외를 가리킬 수 있었다. + * + * @see com.carecode.domain.user.service.ConsentGuard + */ +public class ConsentRequiredException extends CareServiceException { + + private final String consentType; + private final String displayName; + private final boolean sensitive; + + public ConsentRequiredException(String consentType, String displayName, boolean sensitive) { + super(displayName + " 동의가 필요합니다."); + this.consentType = consentType; + this.displayName = displayName; + this.sensitive = sensitive; + } + + /** 동의 종류 코드. 클라이언트가 어떤 동의 화면을 띄울지 고르는 값이다. */ + public String getConsentType() { + return consentType; + } + + public String getDisplayName() { + return displayName; + } + + /** 민감정보 동의인지. 화면이 안내 문구를 다르게 띄운다. */ + public boolean isSensitive() { + return sensitive; + } +} diff --git a/src/main/java/com/carecode/core/handler/CustomizedResponseEntityExceptionHandler.java b/src/main/java/com/carecode/core/handler/CustomizedResponseEntityExceptionHandler.java index 106a386d..4ee28919 100644 --- a/src/main/java/com/carecode/core/handler/CustomizedResponseEntityExceptionHandler.java +++ b/src/main/java/com/carecode/core/handler/CustomizedResponseEntityExceptionHandler.java @@ -2,7 +2,7 @@ import com.carecode.core.exception.*; import com.carecode.core.ops.OperationalAlerter; -import com.carecode.domain.user.service.ConsentGuard; +import com.carecode.core.exception.ConsentRequiredException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; @@ -103,16 +103,16 @@ public ResponseEntity handleBusinessException(BusinessException e } /** 동의가 없어 막힌 경우. 클라이언트가 어떤 동의를 받아야 하는지 알아야 화면을 띄울 수 있다. */ - @ExceptionHandler(ConsentGuard.ConsentRequiredException.class) + @ExceptionHandler(ConsentRequiredException.class) public ResponseEntity> handleConsentRequired( - ConsentGuard.ConsentRequiredException ex, WebRequest request) { + ConsentRequiredException ex, WebRequest request) { log.info("동의 미완료로 접근 차단: {}", ex.getConsentType()); Map body = new LinkedHashMap<>(); body.put("error", "CONSENT_REQUIRED"); - body.put("consentType", ex.getConsentType().name()); - body.put("displayName", ex.getConsentType().getDisplayName()); - body.put("sensitive", ex.getConsentType().isSensitive()); + body.put("consentType", ex.getConsentType()); + body.put("displayName", ex.getDisplayName()); + body.put("sensitive", ex.isSensitive()); body.put("message", ex.getMessage()); body.put("path", request.getDescription(false)); diff --git a/src/main/java/com/carecode/core/security/AccessTokenClaims.java b/src/main/java/com/carecode/core/security/AccessTokenClaims.java new file mode 100644 index 00000000..a8649c17 --- /dev/null +++ b/src/main/java/com/carecode/core/security/AccessTokenClaims.java @@ -0,0 +1,11 @@ +package com.carecode.core.security; + +/** + * 액세스 토큰에서 꺼낸, 인증 필터가 쓰는 값들. + * + * @param userId 가입 시 발급한 사용자 코드 + * @param email principal 로 쓰는 값 + * @param role 권한 문자열 (ROLE_ 접두사 없음) + */ +public record AccessTokenClaims(String userId, String email, String role) { +} diff --git a/src/main/java/com/carecode/core/security/AccessTokenVerifier.java b/src/main/java/com/carecode/core/security/AccessTokenVerifier.java new file mode 100644 index 00000000..c9e6bc38 --- /dev/null +++ b/src/main/java/com/carecode/core/security/AccessTokenVerifier.java @@ -0,0 +1,25 @@ +package com.carecode.core.security; + +import java.util.Optional; + +/** + * 인증 필터가 토큰을 확인하는 통로. + * + *

필터는 토큰이 유효한지와 거기서 꺼낸 몇 개의 값만 필요하다. 그런데 구현 + * ({@code JwtService})은 사용자 도메인에 있고 로그인 응답 DTO({@code TokenDto} 등)까지 + * 다루므로, 필터가 그 클래스를 직접 쓰면 보안 기반 코드가 사용자 도메인의 API 응답 모양을 + * 알게 된다. 필요한 만큼만 이 인터페이스로 끊는다. + * + *

토큰 발급은 여기 없다. 발급은 로그인 흐름의 일부이고 응답 DTO 를 만들어야 하므로 + * 도메인에 남는다. + */ +public interface AccessTokenVerifier { + + /** + * 유효한 액세스 토큰이면 담긴 값을 돌려준다. + * + *

만료·서명 불일치·토큰 종류 불일치는 모두 {@link Optional#empty()} 다. 필터는 그 셋을 + * 구분할 필요가 없고, 구분해서 응답에 담으면 공격자에게 단서를 준다. + */ + Optional verifyAccessToken(String token); +} diff --git a/src/main/java/com/carecode/core/security/JwtAuthenticationFilter.java b/src/main/java/com/carecode/core/security/JwtAuthenticationFilter.java index 544c7b67..a60d4a10 100644 --- a/src/main/java/com/carecode/core/security/JwtAuthenticationFilter.java +++ b/src/main/java/com/carecode/core/security/JwtAuthenticationFilter.java @@ -1,6 +1,5 @@ package com.carecode.core.security; -import com.carecode.domain.user.service.JwtService; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; @@ -23,7 +22,7 @@ @RequiredArgsConstructor public class JwtAuthenticationFilter extends OncePerRequestFilter { - private final JwtService jwtService; + private final AccessTokenVerifier tokenVerifier; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) @@ -61,15 +60,16 @@ private void authenticateIfTokenPresent(HttpServletRequest request) { } // Access Token 만 허용한다. Refresh Token 으로는 API 인증이 되지 않아야 한다. - if (!jwtService.validateAccessToken(token)) { + AccessTokenClaims claims = tokenVerifier.verifyAccessToken(token).orElse(null); + if (claims == null) { log.debug("JWT 토큰이 유효하지 않음"); SecurityContextHolder.clearContext(); return; } - String userId = jwtService.getUserIdFromToken(token); - String email = jwtService.getEmailFromToken(token); - String role = jwtService.getRoleFromToken(token); + String userId = claims.userId(); + String email = claims.email(); + String role = claims.role(); if (!StringUtils.hasText(email) || !StringUtils.hasText(role)) { // role 이 없으면 "ROLE_null" 권한으로 인증되던 문제를 차단한다. diff --git a/src/main/java/com/carecode/core/security/SecurityConfig.java b/src/main/java/com/carecode/core/security/SecurityConfig.java index a4726b2e..cc317cd8 100644 --- a/src/main/java/com/carecode/core/security/SecurityConfig.java +++ b/src/main/java/com/carecode/core/security/SecurityConfig.java @@ -1,6 +1,7 @@ package com.carecode.core.security; import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; @@ -30,16 +31,21 @@ public class SecurityConfig { private final JwtAuthenticationFilter jwtAuthenticationFilter; - private final CustomUserDetailsService customUserDetailsService; + /** + * 스프링 시큐리티 인터페이스로 받는다. 구현({@code CustomUserDetailsService})은 사용자 + * 도메인에 있다 — 자격 증명으로 사용자를 찾는 일은 그 도메인의 규칙이다. 여기서 구현 + * 클래스를 직접 가리키면 보안 설정이 특정 도메인을 알게 된다. + */ + private final UserDetailsService userDetailsService; private final List allowedOrigins; private final Environment environment; public SecurityConfig(JwtAuthenticationFilter jwtAuthenticationFilter, - CustomUserDetailsService customUserDetailsService, + UserDetailsService userDetailsService, Environment environment, @Value("${app.security.cors.allowed-origins:http://localhost:3000,http://127.0.0.1:3000}") String allowedOrigins) { this.jwtAuthenticationFilter = jwtAuthenticationFilter; - this.customUserDetailsService = customUserDetailsService; + this.userDetailsService = userDetailsService; this.environment = environment; this.allowedOrigins = Arrays.stream(allowedOrigins.split(",")) .map(String::trim) @@ -64,7 +70,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .sessionManagement(session -> session .sessionCreationPolicy(SessionCreationPolicy.STATELESS) ) - .userDetailsService(customUserDetailsService) + .userDetailsService(userDetailsService) .exceptionHandling(exceptions -> exceptions .authenticationEntryPoint((request, response, authException) -> { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); diff --git a/src/main/java/com/carecode/domain/admin/service/PolicyVerificationService.java b/src/main/java/com/carecode/domain/admin/service/PolicyVerificationService.java index 18ba2fb4..ce15acd5 100644 --- a/src/main/java/com/carecode/domain/admin/service/PolicyVerificationService.java +++ b/src/main/java/com/carecode/domain/admin/service/PolicyVerificationService.java @@ -1,7 +1,7 @@ package com.carecode.domain.admin.service; import com.carecode.core.exception.ResourceNotFoundException; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.domain.admin.dto.response.PolicyVerificationResponse; import com.carecode.domain.admin.dto.response.RegionVerificationStatusResponse; import com.carecode.domain.policy.entity.Policy; diff --git a/src/main/java/com/carecode/domain/chatbot/controller/ChatbotController.java b/src/main/java/com/carecode/domain/chatbot/controller/ChatbotController.java index 97399deb..eccf0254 100644 --- a/src/main/java/com/carecode/domain/chatbot/controller/ChatbotController.java +++ b/src/main/java/com/carecode/domain/chatbot/controller/ChatbotController.java @@ -3,7 +3,7 @@ import com.carecode.core.annotation.LogExecutionTime; import com.carecode.core.annotation.RateLimit; import com.carecode.core.web.BaseController; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.core.exception.CareServiceException; import com.carecode.domain.chatbot.dto.request.ChatbotMessageRequest; import com.carecode.domain.chatbot.dto.response.ChatbotMessageResponse; diff --git a/src/main/java/com/carecode/domain/community/service/CommunityService.java b/src/main/java/com/carecode/domain/community/service/CommunityService.java index bc55df08..1bf4e099 100644 --- a/src/main/java/com/carecode/domain/community/service/CommunityService.java +++ b/src/main/java/com/carecode/domain/community/service/CommunityService.java @@ -4,7 +4,7 @@ import com.carecode.core.exception.CommentAccessDeniedException; import com.carecode.core.exception.PostAccessDeniedException; import com.carecode.core.exception.ResourceNotFoundException; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.domain.community.dto.request.CommunityCreatePostRequest; import com.carecode.domain.community.dto.request.CommunityUpdatePostRequest; import com.carecode.domain.community.dto.request.CommunityCreateCommentRequest; diff --git a/src/main/java/com/carecode/domain/community/service/ModerationService.java b/src/main/java/com/carecode/domain/community/service/ModerationService.java index da1a40c1..626bd6e6 100644 --- a/src/main/java/com/carecode/domain/community/service/ModerationService.java +++ b/src/main/java/com/carecode/domain/community/service/ModerationService.java @@ -3,7 +3,7 @@ import com.carecode.core.exception.BusinessException; import com.carecode.core.exception.ErrorCode; import com.carecode.core.exception.ResourceNotFoundException; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.domain.community.dto.request.ReportCreateRequest; import com.carecode.domain.community.dto.response.ReportResponse; import com.carecode.domain.community.entity.Comment; diff --git a/src/main/java/com/carecode/domain/facility/controller/CareFacilityController.java b/src/main/java/com/carecode/domain/facility/controller/CareFacilityController.java index 9f7dd6b2..6b19dfd7 100644 --- a/src/main/java/com/carecode/domain/facility/controller/CareFacilityController.java +++ b/src/main/java/com/carecode/domain/facility/controller/CareFacilityController.java @@ -4,7 +4,7 @@ import com.carecode.core.annotation.ValidateLocation; import com.carecode.core.annotation.ValidateChildAge; import com.carecode.core.web.BaseController; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.core.util.PageRequestUtil; import com.carecode.domain.facility.dto.request.CareFacilitySearchRequest; import com.carecode.domain.facility.dto.request.CareFacilityAdvancedSearchRequest; diff --git a/src/main/java/com/carecode/domain/facility/service/FacilityWaitlistService.java b/src/main/java/com/carecode/domain/facility/service/FacilityWaitlistService.java index f8ca2d25..75ff9b20 100644 --- a/src/main/java/com/carecode/domain/facility/service/FacilityWaitlistService.java +++ b/src/main/java/com/carecode/domain/facility/service/FacilityWaitlistService.java @@ -5,7 +5,7 @@ import com.carecode.core.exception.BusinessException; import com.carecode.core.exception.ErrorCode; import com.carecode.core.exception.ResourceNotFoundException; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.domain.facility.dto.request.WaitlistRequest; import com.carecode.domain.facility.dto.response.WaitlistStatsResponse; import com.carecode.domain.facility.entity.CareFacility; diff --git a/src/main/java/com/carecode/domain/health/controller/HealthController.java b/src/main/java/com/carecode/domain/health/controller/HealthController.java index d7c80b26..38eca306 100644 --- a/src/main/java/com/carecode/domain/health/controller/HealthController.java +++ b/src/main/java/com/carecode/domain/health/controller/HealthController.java @@ -3,7 +3,7 @@ import com.carecode.core.annotation.LogExecutionTime; import com.carecode.core.web.BaseController; import com.carecode.core.util.PageRequestUtil; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.domain.health.dto.request.HealthCreateHealthRecordRequest; import com.carecode.domain.health.dto.request.HealthRecordAttachmentRequest; import com.carecode.domain.health.dto.request.HealthUpdateHealthRecordRequest; diff --git a/src/main/java/com/carecode/domain/health/service/ChildService.java b/src/main/java/com/carecode/domain/health/service/ChildService.java index 69a6ff2e..05a4dade 100644 --- a/src/main/java/com/carecode/domain/health/service/ChildService.java +++ b/src/main/java/com/carecode/domain/health/service/ChildService.java @@ -3,7 +3,7 @@ import com.carecode.core.analytics.EventLogger; import com.carecode.core.analytics.EventType; import com.carecode.core.exception.ChildNotFoundException; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.domain.health.dto.request.ChildCreateRequest; import com.carecode.domain.health.dto.response.ChildInfoResponse; import com.carecode.domain.health.mapper.ChildMapper; diff --git a/src/main/java/com/carecode/domain/health/service/GrowthChartService.java b/src/main/java/com/carecode/domain/health/service/GrowthChartService.java index 4d5c2599..886406b5 100644 --- a/src/main/java/com/carecode/domain/health/service/GrowthChartService.java +++ b/src/main/java/com/carecode/domain/health/service/GrowthChartService.java @@ -1,7 +1,7 @@ package com.carecode.domain.health.service; import com.carecode.core.exception.ChildNotFoundException; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.domain.health.dto.response.GrowthPointResponse; import com.carecode.domain.health.entity.HealthRecord; import com.carecode.domain.health.growth.GrowthMetric; diff --git a/src/main/java/com/carecode/domain/health/service/HealthRecordAttachmentService.java b/src/main/java/com/carecode/domain/health/service/HealthRecordAttachmentService.java index e3d9b57d..37f34ab3 100644 --- a/src/main/java/com/carecode/domain/health/service/HealthRecordAttachmentService.java +++ b/src/main/java/com/carecode/domain/health/service/HealthRecordAttachmentService.java @@ -2,7 +2,7 @@ import com.carecode.core.exception.HealthRecordNotFoundException; import com.carecode.core.exception.ResourceNotFoundException; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.core.storage.FileStorageService; import com.carecode.domain.health.dto.response.AttachmentDownload; import com.carecode.core.storage.StoredFile; diff --git a/src/main/java/com/carecode/domain/health/service/SiblingOverviewService.java b/src/main/java/com/carecode/domain/health/service/SiblingOverviewService.java index 0b60c7e8..83677157 100644 --- a/src/main/java/com/carecode/domain/health/service/SiblingOverviewService.java +++ b/src/main/java/com/carecode/domain/health/service/SiblingOverviewService.java @@ -1,6 +1,6 @@ package com.carecode.domain.health.service; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.domain.facility.repository.FacilityWaitlistRepository; import com.carecode.domain.health.dto.response.SiblingOverviewResponse; import com.carecode.domain.health.entity.VaccinationSchedule; diff --git a/src/main/java/com/carecode/domain/notification/controller/NotificationController.java b/src/main/java/com/carecode/domain/notification/controller/NotificationController.java index 1cb2bbec..df201c07 100644 --- a/src/main/java/com/carecode/domain/notification/controller/NotificationController.java +++ b/src/main/java/com/carecode/domain/notification/controller/NotificationController.java @@ -3,7 +3,7 @@ import com.carecode.core.annotation.LogExecutionTime; import com.carecode.core.web.BaseController; import com.carecode.core.exception.CareServiceException; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.domain.notification.dto.request.NotificationCreateRequest; import com.carecode.domain.notification.dto.request.NotificationMarkAsReadRequest; import com.carecode.domain.notification.dto.request.NotificationRegisterPushTokenRequest; diff --git a/src/main/java/com/carecode/domain/notification/controller/NotificationLinkController.java b/src/main/java/com/carecode/domain/notification/controller/NotificationLinkController.java index 47a9fa6e..83945d6d 100644 --- a/src/main/java/com/carecode/domain/notification/controller/NotificationLinkController.java +++ b/src/main/java/com/carecode/domain/notification/controller/NotificationLinkController.java @@ -1,6 +1,6 @@ package com.carecode.domain.notification.controller; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.domain.notification.service.NotificationLinkService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; diff --git a/src/main/java/com/carecode/domain/policy/controller/BenefitLinkController.java b/src/main/java/com/carecode/domain/policy/controller/BenefitLinkController.java index d8838488..274cb5a9 100644 --- a/src/main/java/com/carecode/domain/policy/controller/BenefitLinkController.java +++ b/src/main/java/com/carecode/domain/policy/controller/BenefitLinkController.java @@ -1,6 +1,6 @@ package com.carecode.domain.policy.controller; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.domain.policy.service.BenefitLinkService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; diff --git a/src/main/java/com/carecode/domain/policy/controller/PolicyController.java b/src/main/java/com/carecode/domain/policy/controller/PolicyController.java index 68284a19..408018c4 100644 --- a/src/main/java/com/carecode/domain/policy/controller/PolicyController.java +++ b/src/main/java/com/carecode/domain/policy/controller/PolicyController.java @@ -4,7 +4,7 @@ import com.carecode.core.annotation.ValidateLocation; import com.carecode.core.web.BaseController; import com.carecode.core.util.PageRequestUtil; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.core.exception.CareServiceException; import com.carecode.core.exception.PolicyNotFoundException; import com.carecode.domain.policy.dto.request.BenefitAmountReportRequest; diff --git a/src/main/java/com/carecode/domain/policy/service/BenefitAmountReportService.java b/src/main/java/com/carecode/domain/policy/service/BenefitAmountReportService.java index 6d56d1ae..ad3ba281 100644 --- a/src/main/java/com/carecode/domain/policy/service/BenefitAmountReportService.java +++ b/src/main/java/com/carecode/domain/policy/service/BenefitAmountReportService.java @@ -3,7 +3,7 @@ import com.carecode.core.analytics.EventLogger; import com.carecode.core.analytics.EventType; import com.carecode.core.exception.ResourceNotFoundException; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.domain.policy.dto.request.BenefitAmountReportRequest; import com.carecode.domain.policy.dto.response.BenefitAmountConsensusResponse; import com.carecode.domain.policy.entity.BenefitAmountReport; diff --git a/src/main/java/com/carecode/domain/policy/service/MissedBenefitService.java b/src/main/java/com/carecode/domain/policy/service/MissedBenefitService.java index 22e2a107..ab7d2204 100644 --- a/src/main/java/com/carecode/domain/policy/service/MissedBenefitService.java +++ b/src/main/java/com/carecode/domain/policy/service/MissedBenefitService.java @@ -2,7 +2,7 @@ import com.carecode.core.analytics.EventLogger; import com.carecode.core.analytics.EventType; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.domain.policy.dto.response.MissedBenefitResponse; import com.carecode.domain.policy.dto.response.MissedBenefitSummaryResponse; import com.carecode.domain.policy.entity.Policy; diff --git a/src/main/java/com/carecode/domain/policy/service/PolicyRecommendationService.java b/src/main/java/com/carecode/domain/policy/service/PolicyRecommendationService.java index 172d6759..a828c1dc 100644 --- a/src/main/java/com/carecode/domain/policy/service/PolicyRecommendationService.java +++ b/src/main/java/com/carecode/domain/policy/service/PolicyRecommendationService.java @@ -2,7 +2,7 @@ import com.carecode.core.analytics.EventLogger; import com.carecode.core.analytics.EventType; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.domain.policy.dto.response.PersonalizedPolicyResponse; import com.carecode.domain.policy.entity.Policy; import com.carecode.domain.policy.mapper.PolicyMapper; diff --git a/src/main/java/com/carecode/domain/policy/service/RegionalBenefitComparisonService.java b/src/main/java/com/carecode/domain/policy/service/RegionalBenefitComparisonService.java index f5fd9fc2..0fc957b6 100644 --- a/src/main/java/com/carecode/domain/policy/service/RegionalBenefitComparisonService.java +++ b/src/main/java/com/carecode/domain/policy/service/RegionalBenefitComparisonService.java @@ -6,7 +6,7 @@ import com.carecode.core.exception.ResourceNotFoundException; import com.carecode.core.analytics.EventLogger; import com.carecode.core.analytics.EventType; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.domain.policy.dto.response.RegionalBenefitComparisonResponse; import com.carecode.domain.policy.dto.response.RegionalBenefitResponse; import com.carecode.domain.policy.entity.Policy; diff --git a/src/main/java/com/carecode/core/security/CurrentUserFacade.java b/src/main/java/com/carecode/domain/user/app/CurrentUserFacade.java similarity index 99% rename from src/main/java/com/carecode/core/security/CurrentUserFacade.java rename to src/main/java/com/carecode/domain/user/app/CurrentUserFacade.java index e567afa8..0e2690e9 100644 --- a/src/main/java/com/carecode/core/security/CurrentUserFacade.java +++ b/src/main/java/com/carecode/domain/user/app/CurrentUserFacade.java @@ -1,4 +1,4 @@ -package com.carecode.core.security; +package com.carecode.domain.user.app; import com.carecode.core.exception.CareServiceException; import com.carecode.domain.user.entity.User; diff --git a/src/main/java/com/carecode/domain/user/controller/AuthController.java b/src/main/java/com/carecode/domain/user/controller/AuthController.java index aed08448..7b519b04 100644 --- a/src/main/java/com/carecode/domain/user/controller/AuthController.java +++ b/src/main/java/com/carecode/domain/user/controller/AuthController.java @@ -3,7 +3,7 @@ import com.carecode.core.annotation.LogExecutionTime; import com.carecode.core.annotation.RateLimit; import com.carecode.core.web.BaseController; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.core.security.RefreshTokenCookieFactory; import com.carecode.core.exception.UserNotFoundException; import com.carecode.domain.user.dto.request.LoginRequestDto; diff --git a/src/main/java/com/carecode/domain/user/controller/KakaoAuthController.java b/src/main/java/com/carecode/domain/user/controller/KakaoAuthController.java index b5f73eb7..ceecfc51 100644 --- a/src/main/java/com/carecode/domain/user/controller/KakaoAuthController.java +++ b/src/main/java/com/carecode/domain/user/controller/KakaoAuthController.java @@ -3,9 +3,9 @@ import com.carecode.core.annotation.LogExecutionTime; import com.carecode.core.web.BaseController; import com.carecode.core.exception.UserNotFoundException; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.core.security.RefreshTokenCookieFactory; -import com.carecode.core.util.KakaoUtil; +import com.carecode.external.kakao.KakaoUtil; import com.carecode.domain.user.dto.request.KakaoRegistrationRequest; import com.carecode.domain.user.dto.response.KakaoLoginUrlResponse; import com.carecode.domain.user.dto.response.TokenDto; diff --git a/src/main/java/com/carecode/domain/user/controller/UserController.java b/src/main/java/com/carecode/domain/user/controller/UserController.java index 6e5def84..08f4d6e6 100644 --- a/src/main/java/com/carecode/domain/user/controller/UserController.java +++ b/src/main/java/com/carecode/domain/user/controller/UserController.java @@ -3,7 +3,7 @@ import com.carecode.core.annotation.LogExecutionTime; import com.carecode.core.web.BaseController; import com.carecode.core.handler.ApiSuccess; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.domain.user.app.UserFacade; import com.carecode.domain.user.dto.request.UserUpdateRequestDto; import com.carecode.domain.user.dto.response.ProfileImageResponse; diff --git a/src/main/java/com/carecode/core/security/CustomUserDetailsService.java b/src/main/java/com/carecode/domain/user/security/CustomUserDetailsService.java similarity index 97% rename from src/main/java/com/carecode/core/security/CustomUserDetailsService.java rename to src/main/java/com/carecode/domain/user/security/CustomUserDetailsService.java index 7e35d185..611e8b30 100644 --- a/src/main/java/com/carecode/core/security/CustomUserDetailsService.java +++ b/src/main/java/com/carecode/domain/user/security/CustomUserDetailsService.java @@ -1,4 +1,4 @@ -package com.carecode.core.security; +package com.carecode.domain.user.security; import com.carecode.domain.user.entity.User; import com.carecode.domain.user.repository.UserRepository; diff --git a/src/main/java/com/carecode/domain/user/service/ConsentGuard.java b/src/main/java/com/carecode/domain/user/service/ConsentGuard.java index 1055f6cf..14f0d53f 100644 --- a/src/main/java/com/carecode/domain/user/service/ConsentGuard.java +++ b/src/main/java/com/carecode/domain/user/service/ConsentGuard.java @@ -1,6 +1,6 @@ package com.carecode.domain.user.service; -import com.carecode.core.exception.CareServiceException; +import com.carecode.core.exception.ConsentRequiredException; import com.carecode.domain.user.entity.ConsentType; import com.carecode.domain.user.entity.UserConsent; import com.carecode.domain.user.repository.UserConsentRepository; @@ -21,7 +21,7 @@ public class ConsentGuard { /** 동의가 없거나 철회됐으면 접근을 막는다. */ public void require(Long userId, ConsentType type) { if (!hasConsent(userId, type)) { - throw new ConsentRequiredException(type); + throw new ConsentRequiredException(type.name(), type.getDisplayName(), type.isSensitive()); } } @@ -30,19 +30,4 @@ public boolean hasConsent(Long userId, ConsentType type) { .map(UserConsent::isGranted) .orElse(false); } - - /** 동의가 필요해서 막힌 것인지 클라이언트가 구분할 수 있게 별도 예외로 던진다. */ - public static class ConsentRequiredException extends CareServiceException { - - private final transient ConsentType consentType; - - public ConsentRequiredException(ConsentType consentType) { - super(consentType.getDisplayName() + " 동의가 필요합니다."); - this.consentType = consentType; - } - - public ConsentType getConsentType() { - return consentType; - } - } } diff --git a/src/main/java/com/carecode/domain/user/service/JwtService.java b/src/main/java/com/carecode/domain/user/service/JwtService.java index 172aaf42..80b44033 100644 --- a/src/main/java/com/carecode/domain/user/service/JwtService.java +++ b/src/main/java/com/carecode/domain/user/service/JwtService.java @@ -1,6 +1,8 @@ package com.carecode.domain.user.service; import com.carecode.core.exception.BusinessException; +import com.carecode.core.security.AccessTokenClaims; +import com.carecode.core.security.AccessTokenVerifier; import com.carecode.core.exception.ErrorCode; import com.carecode.domain.user.dto.response.TokenDto; import com.carecode.domain.user.dto.response.TokenValidationResponse; @@ -21,7 +23,7 @@ /** JWT 토큰 서비스 */ @Slf4j @Service -public class JwtService { +public class JwtService implements AccessTokenVerifier { /** 토큰 종류를 구분하는 클레임. Access Token 을 Refresh 로, 혹은 그 반대로 쓰는 것을 막습니다. */ public static final String CLAIM_TOKEN_TYPE = "typ"; @@ -180,6 +182,21 @@ public boolean validateToken(String token) { } // Access Token 전용 검증 - typ=access 인 토큰만 통과시킵니다. + /** + * {@link AccessTokenVerifier} 구현. 인증 필터는 이 메서드만 쓴다. + * + *

유효성 확인과 값 꺼내기를 한 번에 하는 이유: 필터가 따로 부르면 그 사이에 네 번 + * 파싱하게 되고, 유효성 확인 뒤에 값을 꺼내는 순서를 호출자가 지켜야 한다. + */ + @Override + public java.util.Optional verifyAccessToken(String token) { + if (!validateAccessToken(token)) { + return java.util.Optional.empty(); + } + return java.util.Optional.of(new AccessTokenClaims( + getUserIdFromToken(token), getEmailFromToken(token), getRoleFromToken(token))); + } + public boolean validateAccessToken(String token) { return validateTokenOfType(token, TOKEN_TYPE_ACCESS); } diff --git a/src/main/java/com/carecode/domain/user/service/PrivacyService.java b/src/main/java/com/carecode/domain/user/service/PrivacyService.java index cc7fcc22..407fac71 100644 --- a/src/main/java/com/carecode/domain/user/service/PrivacyService.java +++ b/src/main/java/com/carecode/domain/user/service/PrivacyService.java @@ -1,6 +1,6 @@ package com.carecode.domain.user.service; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.domain.community.repository.PostRepository; import com.carecode.domain.health.repository.HealthRecordRepository; import com.carecode.domain.user.dto.request.ConsentUpdateRequest; diff --git a/src/main/java/com/carecode/domain/user/service/impl/AuthServiceImpl.java b/src/main/java/com/carecode/domain/user/service/impl/AuthServiceImpl.java index ab15dad5..fff2afae 100644 --- a/src/main/java/com/carecode/domain/user/service/impl/AuthServiceImpl.java +++ b/src/main/java/com/carecode/domain/user/service/impl/AuthServiceImpl.java @@ -4,11 +4,11 @@ import com.carecode.core.exception.CareCodeException; import com.carecode.core.exception.CareServiceException; import com.carecode.core.exception.ErrorCode; -import com.carecode.core.util.KakaoUtil; -import com.carecode.domain.user.dto.response.KakaoOAuthToken; -import com.carecode.domain.user.dto.response.KakaoProfile; -import com.carecode.domain.user.dto.response.KakaoAccount; -import com.carecode.domain.user.dto.response.KakaoProperties; +import com.carecode.external.kakao.KakaoUtil; +import com.carecode.external.kakao.KakaoOAuthToken; +import com.carecode.external.kakao.KakaoProfile; +import com.carecode.external.kakao.KakaoAccount; +import com.carecode.external.kakao.KakaoProperties; import com.carecode.domain.user.dto.response.TokenDto; import com.carecode.domain.user.entity.User; import com.carecode.domain.user.entity.UserRole; diff --git a/src/main/java/com/carecode/domain/user/dto/response/KakaoAccount.java b/src/main/java/com/carecode/external/kakao/KakaoAccount.java similarity index 88% rename from src/main/java/com/carecode/domain/user/dto/response/KakaoAccount.java rename to src/main/java/com/carecode/external/kakao/KakaoAccount.java index a388dc0f..bd94ab5f 100644 --- a/src/main/java/com/carecode/domain/user/dto/response/KakaoAccount.java +++ b/src/main/java/com/carecode/external/kakao/KakaoAccount.java @@ -1,4 +1,4 @@ -package com.carecode.domain.user.dto.response; +package com.carecode.external.kakao; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import lombok.Data; diff --git a/src/main/java/com/carecode/domain/user/dto/response/KakaoOAuthToken.java b/src/main/java/com/carecode/external/kakao/KakaoOAuthToken.java similarity index 90% rename from src/main/java/com/carecode/domain/user/dto/response/KakaoOAuthToken.java rename to src/main/java/com/carecode/external/kakao/KakaoOAuthToken.java index fd4ddcae..bfbe8194 100644 --- a/src/main/java/com/carecode/domain/user/dto/response/KakaoOAuthToken.java +++ b/src/main/java/com/carecode/external/kakao/KakaoOAuthToken.java @@ -1,4 +1,4 @@ -package com.carecode.domain.user.dto.response; +package com.carecode.external.kakao; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import lombok.Data; diff --git a/src/main/java/com/carecode/domain/user/dto/response/KakaoProfile.java b/src/main/java/com/carecode/external/kakao/KakaoProfile.java similarity index 87% rename from src/main/java/com/carecode/domain/user/dto/response/KakaoProfile.java rename to src/main/java/com/carecode/external/kakao/KakaoProfile.java index b45191f2..af7a0699 100644 --- a/src/main/java/com/carecode/domain/user/dto/response/KakaoProfile.java +++ b/src/main/java/com/carecode/external/kakao/KakaoProfile.java @@ -1,4 +1,4 @@ -package com.carecode.domain.user.dto.response; +package com.carecode.external.kakao; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import lombok.Data; diff --git a/src/main/java/com/carecode/domain/user/dto/response/KakaoProfileInfo.java b/src/main/java/com/carecode/external/kakao/KakaoProfileInfo.java similarity index 88% rename from src/main/java/com/carecode/domain/user/dto/response/KakaoProfileInfo.java rename to src/main/java/com/carecode/external/kakao/KakaoProfileInfo.java index b6f4d778..37f42c36 100644 --- a/src/main/java/com/carecode/domain/user/dto/response/KakaoProfileInfo.java +++ b/src/main/java/com/carecode/external/kakao/KakaoProfileInfo.java @@ -1,4 +1,4 @@ -package com.carecode.domain.user.dto.response; +package com.carecode.external.kakao; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import lombok.Data; diff --git a/src/main/java/com/carecode/domain/user/dto/response/KakaoProperties.java b/src/main/java/com/carecode/external/kakao/KakaoProperties.java similarity index 86% rename from src/main/java/com/carecode/domain/user/dto/response/KakaoProperties.java rename to src/main/java/com/carecode/external/kakao/KakaoProperties.java index 88cafacc..967f04ee 100644 --- a/src/main/java/com/carecode/domain/user/dto/response/KakaoProperties.java +++ b/src/main/java/com/carecode/external/kakao/KakaoProperties.java @@ -1,4 +1,4 @@ -package com.carecode.domain.user.dto.response; +package com.carecode.external.kakao; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import lombok.Data; diff --git a/src/main/java/com/carecode/core/util/KakaoUtil.java b/src/main/java/com/carecode/external/kakao/KakaoUtil.java similarity index 98% rename from src/main/java/com/carecode/core/util/KakaoUtil.java rename to src/main/java/com/carecode/external/kakao/KakaoUtil.java index 5f155024..ef8e3adb 100644 --- a/src/main/java/com/carecode/core/util/KakaoUtil.java +++ b/src/main/java/com/carecode/external/kakao/KakaoUtil.java @@ -1,7 +1,5 @@ -package com.carecode.core.util; +package com.carecode.external.kakao; -import com.carecode.domain.user.dto.response.KakaoOAuthToken; -import com.carecode.domain.user.dto.response.KakaoProfile; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/src/test/java/com/carecode/architecture/ArchitectureRulesTest.java b/src/test/java/com/carecode/architecture/ArchitectureRulesTest.java index b9995b97..f00ab4e8 100644 --- a/src/test/java/com/carecode/architecture/ArchitectureRulesTest.java +++ b/src/test/java/com/carecode/architecture/ArchitectureRulesTest.java @@ -134,6 +134,10 @@ void innerLayersDoNotDependOnControllers() { void domainsUseCurrentUserFacade() { check(noClasses() .that().resideInAPackage("com.carecode.domain..") + // 파사드 자신은 예외다. 이 규칙의 목적이 "모든 접근을 한 클래스로 모으는 것" 이고, + // 그 한 클래스가 바로 여기다. (한때 core/security 에 있어 이 규칙에 걸리지 않았는데, + // 그 자리에 있으면 기반 코드가 사용자 도메인을 알게 돼서 도메인으로 옮겼다.) + .and().doNotHaveFullyQualifiedName("com.carecode.domain.user.app.CurrentUserFacade") .should().dependOnClassesThat() .haveFullyQualifiedName("org.springframework.security.core.context.SecurityContextHolder") .because("현재 사용자는 CurrentUserFacade 로만 얻는다")); diff --git a/src/test/java/com/carecode/domain/chatbot/controller/ChatbotControllerOwnershipTest.java b/src/test/java/com/carecode/domain/chatbot/controller/ChatbotControllerOwnershipTest.java index df1629cf..64a181f0 100644 --- a/src/test/java/com/carecode/domain/chatbot/controller/ChatbotControllerOwnershipTest.java +++ b/src/test/java/com/carecode/domain/chatbot/controller/ChatbotControllerOwnershipTest.java @@ -1,6 +1,6 @@ package com.carecode.domain.chatbot.controller; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.domain.chatbot.app.ChatbotFacade; import com.carecode.domain.chatbot.entity.ChatMessage; import com.carecode.domain.chatbot.entity.ChatSession; diff --git a/src/test/java/com/carecode/domain/community/service/CommunityServiceHiddenPostTest.java b/src/test/java/com/carecode/domain/community/service/CommunityServiceHiddenPostTest.java index 5198a3f2..259deb88 100644 --- a/src/test/java/com/carecode/domain/community/service/CommunityServiceHiddenPostTest.java +++ b/src/test/java/com/carecode/domain/community/service/CommunityServiceHiddenPostTest.java @@ -53,7 +53,7 @@ class CommunityServiceHiddenPostTest { @Mock private PostLikeRepository postLikeRepository; @Mock private BookmarkRepository bookmarkRepository; @Mock private CommunityMapper communityMapper; - @Mock private com.carecode.core.security.CurrentUserFacade currentUserFacade; + @Mock private com.carecode.domain.user.app.CurrentUserFacade currentUserFacade; @InjectMocks private CommunityService communityService; diff --git a/src/test/java/com/carecode/domain/community/service/CommunityServiceOwnershipTest.java b/src/test/java/com/carecode/domain/community/service/CommunityServiceOwnershipTest.java index 00c7a18c..6b4df199 100644 --- a/src/test/java/com/carecode/domain/community/service/CommunityServiceOwnershipTest.java +++ b/src/test/java/com/carecode/domain/community/service/CommunityServiceOwnershipTest.java @@ -56,7 +56,7 @@ class CommunityServiceOwnershipTest { @Mock private PostLikeRepository postLikeRepository; @Mock private BookmarkRepository bookmarkRepository; @Mock private CommunityMapper communityMapper; - @Mock private com.carecode.core.security.CurrentUserFacade currentUserFacade; + @Mock private com.carecode.domain.user.app.CurrentUserFacade currentUserFacade; @InjectMocks private CommunityService communityService; diff --git a/src/test/java/com/carecode/domain/health/service/HealthRecordAttachmentServiceTest.java b/src/test/java/com/carecode/domain/health/service/HealthRecordAttachmentServiceTest.java index b80a73be..14581d9c 100644 --- a/src/test/java/com/carecode/domain/health/service/HealthRecordAttachmentServiceTest.java +++ b/src/test/java/com/carecode/domain/health/service/HealthRecordAttachmentServiceTest.java @@ -2,7 +2,7 @@ import com.carecode.core.exception.HealthRecordNotFoundException; import com.carecode.core.exception.ResourceNotFoundException; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.core.storage.FileStorageService; import com.carecode.domain.health.dto.response.AttachmentDownload; import com.carecode.domain.health.entity.HealthRecord; diff --git a/src/test/java/com/carecode/domain/policy/service/BenefitAmountReportServiceTest.java b/src/test/java/com/carecode/domain/policy/service/BenefitAmountReportServiceTest.java index 9e4c8b3e..62c20071 100644 --- a/src/test/java/com/carecode/domain/policy/service/BenefitAmountReportServiceTest.java +++ b/src/test/java/com/carecode/domain/policy/service/BenefitAmountReportServiceTest.java @@ -1,6 +1,6 @@ package com.carecode.domain.policy.service; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.domain.policy.dto.request.BenefitAmountReportRequest; import com.carecode.domain.policy.dto.response.BenefitAmountConsensusResponse; import com.carecode.domain.policy.entity.BenefitAmountReport; diff --git a/src/test/java/com/carecode/domain/policy/service/MissedBenefitServiceTest.java b/src/test/java/com/carecode/domain/policy/service/MissedBenefitServiceTest.java index 87f0fa28..79bf62e2 100644 --- a/src/test/java/com/carecode/domain/policy/service/MissedBenefitServiceTest.java +++ b/src/test/java/com/carecode/domain/policy/service/MissedBenefitServiceTest.java @@ -1,6 +1,6 @@ package com.carecode.domain.policy.service; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.domain.policy.dto.response.MissedBenefitSummaryResponse; import com.carecode.domain.policy.entity.Policy; import com.carecode.domain.policy.repository.PolicyRepository; diff --git a/src/test/java/com/carecode/domain/policy/service/RegionalBenefitComparisonServiceTest.java b/src/test/java/com/carecode/domain/policy/service/RegionalBenefitComparisonServiceTest.java index c122fa19..ae97ae48 100644 --- a/src/test/java/com/carecode/domain/policy/service/RegionalBenefitComparisonServiceTest.java +++ b/src/test/java/com/carecode/domain/policy/service/RegionalBenefitComparisonServiceTest.java @@ -2,7 +2,7 @@ import com.carecode.domain.policy.benefit.BenefitProjectionCalculator; import com.carecode.core.exception.BusinessException; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.domain.policy.dto.response.RegionalBenefitComparisonResponse; import com.carecode.domain.policy.dto.response.RegionalBenefitResponse; import com.carecode.domain.policy.entity.Policy; diff --git a/src/test/java/com/carecode/core/security/CurrentUserFacadeTest.java b/src/test/java/com/carecode/domain/user/app/CurrentUserFacadeTest.java similarity index 99% rename from src/test/java/com/carecode/core/security/CurrentUserFacadeTest.java rename to src/test/java/com/carecode/domain/user/app/CurrentUserFacadeTest.java index b7a111cc..b1bf7858 100644 --- a/src/test/java/com/carecode/core/security/CurrentUserFacadeTest.java +++ b/src/test/java/com/carecode/domain/user/app/CurrentUserFacadeTest.java @@ -1,4 +1,4 @@ -package com.carecode.core.security; +package com.carecode.domain.user.app; import com.carecode.core.exception.CareServiceException; import com.carecode.domain.user.entity.User; diff --git a/src/test/java/com/carecode/domain/user/service/ConsentGuardTest.java b/src/test/java/com/carecode/domain/user/service/ConsentGuardTest.java index 0841b224..65819c3e 100644 --- a/src/test/java/com/carecode/domain/user/service/ConsentGuardTest.java +++ b/src/test/java/com/carecode/domain/user/service/ConsentGuardTest.java @@ -1,5 +1,6 @@ package com.carecode.domain.user.service; +import com.carecode.core.exception.ConsentRequiredException; import com.carecode.domain.user.entity.ConsentType; import com.carecode.domain.user.entity.UserConsent; import com.carecode.domain.user.repository.UserConsentRepository; @@ -34,7 +35,7 @@ void blocksWithoutConsent() { when(repository.findLatest(anyLong(), eq(ConsentType.HEALTH_DATA))).thenReturn(Optional.empty()); assertThatThrownBy(() -> guard.require(1L, ConsentType.HEALTH_DATA)) - .isInstanceOf(ConsentGuard.ConsentRequiredException.class) + .isInstanceOf(ConsentRequiredException.class) .hasMessageContaining("건강정보"); } @@ -48,7 +49,7 @@ void blocksWhenRevoked() { assertThat(guard.hasConsent(1L, ConsentType.HEALTH_DATA)).isFalse(); assertThatThrownBy(() -> guard.require(1L, ConsentType.HEALTH_DATA)) - .isInstanceOf(ConsentGuard.ConsentRequiredException.class); + .isInstanceOf(ConsentRequiredException.class); } @Test @@ -68,8 +69,8 @@ void exposesRequiredConsentType() { when(repository.findLatest(anyLong(), eq(ConsentType.HEALTH_DATA))).thenReturn(Optional.empty()); assertThatThrownBy(() -> guard.require(1L, ConsentType.HEALTH_DATA)) - .isInstanceOfSatisfying(ConsentGuard.ConsentRequiredException.class, - e -> assertThat(e.getConsentType()).isEqualTo(ConsentType.HEALTH_DATA)); + .isInstanceOfSatisfying(ConsentRequiredException.class, + e -> assertThat(e.getConsentType()).isEqualTo(ConsentType.HEALTH_DATA.name())); } @Test diff --git a/src/test/java/com/carecode/domain/user/service/impl/AuthServiceImplKakaoTest.java b/src/test/java/com/carecode/domain/user/service/impl/AuthServiceImplKakaoTest.java index 6be9aabd..6b24679a 100644 --- a/src/test/java/com/carecode/domain/user/service/impl/AuthServiceImplKakaoTest.java +++ b/src/test/java/com/carecode/domain/user/service/impl/AuthServiceImplKakaoTest.java @@ -2,11 +2,11 @@ import com.carecode.core.exception.CareCodeException; import com.carecode.core.exception.ErrorCode; -import com.carecode.core.util.KakaoUtil; -import com.carecode.domain.user.dto.response.KakaoAccount; -import com.carecode.domain.user.dto.response.KakaoOAuthToken; -import com.carecode.domain.user.dto.response.KakaoProfile; -import com.carecode.domain.user.dto.response.KakaoProfileInfo; +import com.carecode.external.kakao.KakaoUtil; +import com.carecode.external.kakao.KakaoAccount; +import com.carecode.external.kakao.KakaoOAuthToken; +import com.carecode.external.kakao.KakaoProfile; +import com.carecode.external.kakao.KakaoProfileInfo; import com.carecode.domain.user.dto.response.TokenDto; import com.carecode.domain.user.entity.User; import com.carecode.domain.user.entity.UserRole; diff --git a/src/test/java/com/carecode/integration/SampleDataScenarioTest.java b/src/test/java/com/carecode/integration/SampleDataScenarioTest.java index ee7e926c..55a2f1ed 100644 --- a/src/test/java/com/carecode/integration/SampleDataScenarioTest.java +++ b/src/test/java/com/carecode/integration/SampleDataScenarioTest.java @@ -3,7 +3,7 @@ import com.carecode.CareCodeApplication; import com.carecode.devtools.SampleFacilitySeeder; import com.carecode.devtools.SamplePolicySeeder; -import com.carecode.core.security.CurrentUserFacade; +import com.carecode.domain.user.app.CurrentUserFacade; import com.carecode.domain.facility.dto.response.AdmissionForecastResponse; import com.carecode.domain.facility.dto.response.FacilityPopularityResponse; import com.carecode.domain.facility.entity.CareFacility;