From 3ab23b5809c56cf0c42b745de436fb1fc9cbdefa Mon Sep 17 00:00:00 2001 From: yongyong213 Date: Tue, 19 May 2026 16:51:33 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20api?= =?UTF-8?q?=20=EB=A7=8C=EB=93=A4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 4 ++ .../Inquiry/exception/InquiryException.java | 4 +- .../exception/code/InquiryErrorCode.java | 2 +- src/main/java/umc/config/SecurityConfig.java | 48 +++++++++++++++++++ .../java/umc/food/exeption/FoodException.java | 4 +- .../umc/food/exeption/code/FoodErrorCode.java | 2 +- .../{ => global}/apiPayload/ApiResponse.java | 6 +-- .../apiPayload/code/BaseErrorCode.java | 2 +- .../apiPayload/code/BaseSuccessCode.java | 2 +- .../apiPayload/code/GeneralErrorCode.java | 2 +- .../apiPayload/code/GeneralSuccessCode.java | 2 +- .../exception/ProjectException.java | 4 +- .../handler/GeneralExceptionAdvice.java | 10 ++-- .../converter/BaseConverter.java | 4 +- .../dto/BaseResDTO.java | 2 +- .../entity/BaseEntity.java | 2 +- .../global/security/entity/AuthMember.java | 33 +++++++++++++ .../service/CustomUserDetailService.java | 28 +++++++++++ .../location/exception/LocationException.java | 4 +- .../exception/code/LocationErrorCode.java | 2 +- .../member/controller/MemberController.java | 5 +- .../umc/member/converter/MemberConverter.java | 3 +- src/main/java/umc/member/entity/Member.java | 5 +- .../umc/member/entity/mapping/MemberFood.java | 13 ++--- .../umc/member/entity/mapping/MemberTerm.java | 9 ++++ src/main/java/umc/member/enums/Gender.java | 2 - .../umc/member/exception/MemberException.java | 4 +- .../exception/code/MemberErrorCode.java | 9 ++-- .../exception/code/MemberSuccessCode.java | 2 +- .../repository/MemberFoodRepository.java | 7 +++ .../member/repository/MemberRepository.java | 3 ++ .../repository/MemberTermRepository.java | 7 +++ .../umc/member/service/MemberService.java | 47 +++++++++++++++++- .../mission/controller/MissionController.java | 8 ++-- .../mission/converter/MissionConverter.java | 2 +- .../mission/entity/Mapping/MemberMission.java | 2 +- src/main/java/umc/mission/entity/Mission.java | 4 +- .../mission/exception/MissionException.java | 4 +- .../exception/code/MissionErrorCode.java | 2 +- .../exception/code/MissionSuccessCode.java | 5 +- .../mission/service/MemberMissionService.java | 2 +- .../umc/mission/service/MissionService.java | 4 +- .../review/controller/ReviewController.java | 4 +- src/main/java/umc/review/entity/Reply.java | 3 +- src/main/java/umc/review/entity/Review.java | 2 +- .../umc/review/exception/ReviewException.java | 4 +- .../exception/code/ReviewErrorCode.java | 2 +- .../exception/code/ReviewSuccessCode.java | 2 +- .../umc/review/service/ReviewService.java | 7 +-- .../umc/store/exception/StoreException.java | 4 +- .../store/exception/code/StoreErrorCode.java | 2 +- .../umc/term/exception/TermException.java | 4 +- .../term/exception/code/TermErrorCode.java | 14 +++++- 53 files changed, 273 insertions(+), 91 deletions(-) create mode 100644 src/main/java/umc/config/SecurityConfig.java rename src/main/java/umc/{ => global}/apiPayload/ApiResponse.java (87%) rename src/main/java/umc/{ => global}/apiPayload/code/BaseErrorCode.java (81%) rename src/main/java/umc/{ => global}/apiPayload/code/BaseSuccessCode.java (81%) rename src/main/java/umc/{ => global}/apiPayload/code/GeneralErrorCode.java (96%) rename src/main/java/umc/{ => global}/apiPayload/code/GeneralSuccessCode.java (92%) rename src/main/java/umc/{ => global}/apiPayload/exception/ProjectException.java (68%) rename src/main/java/umc/{ => global}/apiPayload/handler/GeneralExceptionAdvice.java (87%) rename src/main/java/umc/{apiPayload => global}/converter/BaseConverter.java (86%) rename src/main/java/umc/{apiPayload => global}/dto/BaseResDTO.java (93%) rename src/main/java/umc/{apiPayload => global}/entity/BaseEntity.java (96%) create mode 100644 src/main/java/umc/global/security/entity/AuthMember.java create mode 100644 src/main/java/umc/global/security/service/CustomUserDetailService.java create mode 100644 src/main/java/umc/member/repository/MemberFoodRepository.java create mode 100644 src/main/java/umc/member/repository/MemberTermRepository.java diff --git a/build.gradle b/build.gradle index ae655d8..3817061 100644 --- a/build.gradle +++ b/build.gradle @@ -35,6 +35,10 @@ dependencies { implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:3.0.1' implementation 'org.springdoc:springdoc-openapi-starter-webmvc-api:3.0.1' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" + + // Security + implementation 'org.springframework.boot:spring-boot-starter-security' + testImplementation 'org.springframework.security:spring-security-test' } tasks.named('test') { diff --git a/src/main/java/umc/Inquiry/exception/InquiryException.java b/src/main/java/umc/Inquiry/exception/InquiryException.java index 31cc2dc..8676fe2 100644 --- a/src/main/java/umc/Inquiry/exception/InquiryException.java +++ b/src/main/java/umc/Inquiry/exception/InquiryException.java @@ -1,7 +1,7 @@ package umc.Inquiry.exception; -import umc.apiPayload.code.BaseErrorCode; -import umc.apiPayload.exception.ProjectException; +import umc.global.apiPayload.code.BaseErrorCode; +import umc.global.apiPayload.exception.ProjectException; public class InquiryException extends ProjectException { public InquiryException(BaseErrorCode errorCode) { diff --git a/src/main/java/umc/Inquiry/exception/code/InquiryErrorCode.java b/src/main/java/umc/Inquiry/exception/code/InquiryErrorCode.java index f12981c..4bd7e5f 100644 --- a/src/main/java/umc/Inquiry/exception/code/InquiryErrorCode.java +++ b/src/main/java/umc/Inquiry/exception/code/InquiryErrorCode.java @@ -3,7 +3,7 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; -import umc.apiPayload.code.BaseErrorCode; +import umc.global.apiPayload.code.BaseErrorCode; @Getter @RequiredArgsConstructor diff --git a/src/main/java/umc/config/SecurityConfig.java b/src/main/java/umc/config/SecurityConfig.java new file mode 100644 index 0000000..01e6ae1 --- /dev/null +++ b/src/main/java/umc/config/SecurityConfig.java @@ -0,0 +1,48 @@ +package umc.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; + +@EnableWebSecurity +@Configuration +public class SecurityConfig { + private final String[] allowUris = { + // Swagger 허용 + "/swagger-ui/**", + "/swagger-resources/**", + "/v3/api-docs/**", + "/auth/**", + "/api/v1/auth/signup" + }; + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception{ + http + .csrf(AbstractHttpConfigurer::disable) + .authorizeHttpRequests(requests -> requests + .requestMatchers(allowUris).permitAll() + .anyRequest().authenticated() + ) + .formLogin(form -> form + .defaultSuccessUrl("/swagger-ui/index.html", true) + .permitAll() + ) + .logout(logout -> logout + .logoutUrl("/logout") + .logoutSuccessUrl("/login?logout") + .permitAll() + ); + return http.build(); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} diff --git a/src/main/java/umc/food/exeption/FoodException.java b/src/main/java/umc/food/exeption/FoodException.java index e479019..ed8aed3 100644 --- a/src/main/java/umc/food/exeption/FoodException.java +++ b/src/main/java/umc/food/exeption/FoodException.java @@ -1,7 +1,7 @@ package umc.food.exeption; -import umc.apiPayload.code.BaseErrorCode; -import umc.apiPayload.exception.ProjectException; +import umc.global.apiPayload.code.BaseErrorCode; +import umc.global.apiPayload.exception.ProjectException; public class FoodException extends ProjectException { public FoodException(BaseErrorCode errorCode) { diff --git a/src/main/java/umc/food/exeption/code/FoodErrorCode.java b/src/main/java/umc/food/exeption/code/FoodErrorCode.java index 8b22651..672db59 100644 --- a/src/main/java/umc/food/exeption/code/FoodErrorCode.java +++ b/src/main/java/umc/food/exeption/code/FoodErrorCode.java @@ -3,7 +3,7 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; -import umc.apiPayload.code.BaseErrorCode; +import umc.global.apiPayload.code.BaseErrorCode; @Getter @RequiredArgsConstructor diff --git a/src/main/java/umc/apiPayload/ApiResponse.java b/src/main/java/umc/global/apiPayload/ApiResponse.java similarity index 87% rename from src/main/java/umc/apiPayload/ApiResponse.java rename to src/main/java/umc/global/apiPayload/ApiResponse.java index 03abdf0..ef4ee77 100644 --- a/src/main/java/umc/apiPayload/ApiResponse.java +++ b/src/main/java/umc/global/apiPayload/ApiResponse.java @@ -1,11 +1,11 @@ -package umc.apiPayload; +package umc.global.apiPayload; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import lombok.AllArgsConstructor; import lombok.Getter; -import umc.apiPayload.code.BaseErrorCode; -import umc.apiPayload.code.BaseSuccessCode; +import umc.global.apiPayload.code.BaseErrorCode; +import umc.global.apiPayload.code.BaseSuccessCode; @Getter @AllArgsConstructor diff --git a/src/main/java/umc/apiPayload/code/BaseErrorCode.java b/src/main/java/umc/global/apiPayload/code/BaseErrorCode.java similarity index 81% rename from src/main/java/umc/apiPayload/code/BaseErrorCode.java rename to src/main/java/umc/global/apiPayload/code/BaseErrorCode.java index 79273e9..f8c66fd 100644 --- a/src/main/java/umc/apiPayload/code/BaseErrorCode.java +++ b/src/main/java/umc/global/apiPayload/code/BaseErrorCode.java @@ -1,4 +1,4 @@ -package umc.apiPayload.code; +package umc.global.apiPayload.code; import org.springframework.http.HttpStatus; diff --git a/src/main/java/umc/apiPayload/code/BaseSuccessCode.java b/src/main/java/umc/global/apiPayload/code/BaseSuccessCode.java similarity index 81% rename from src/main/java/umc/apiPayload/code/BaseSuccessCode.java rename to src/main/java/umc/global/apiPayload/code/BaseSuccessCode.java index ab9b004..d14b40d 100644 --- a/src/main/java/umc/apiPayload/code/BaseSuccessCode.java +++ b/src/main/java/umc/global/apiPayload/code/BaseSuccessCode.java @@ -1,4 +1,4 @@ -package umc.apiPayload.code; +package umc.global.apiPayload.code; import org.springframework.http.HttpStatus; diff --git a/src/main/java/umc/apiPayload/code/GeneralErrorCode.java b/src/main/java/umc/global/apiPayload/code/GeneralErrorCode.java similarity index 96% rename from src/main/java/umc/apiPayload/code/GeneralErrorCode.java rename to src/main/java/umc/global/apiPayload/code/GeneralErrorCode.java index 4764997..74fa6ba 100644 --- a/src/main/java/umc/apiPayload/code/GeneralErrorCode.java +++ b/src/main/java/umc/global/apiPayload/code/GeneralErrorCode.java @@ -1,4 +1,4 @@ -package umc.apiPayload.code; +package umc.global.apiPayload.code; import lombok.Getter; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/umc/apiPayload/code/GeneralSuccessCode.java b/src/main/java/umc/global/apiPayload/code/GeneralSuccessCode.java similarity index 92% rename from src/main/java/umc/apiPayload/code/GeneralSuccessCode.java rename to src/main/java/umc/global/apiPayload/code/GeneralSuccessCode.java index 760498c..93fd8ee 100644 --- a/src/main/java/umc/apiPayload/code/GeneralSuccessCode.java +++ b/src/main/java/umc/global/apiPayload/code/GeneralSuccessCode.java @@ -1,4 +1,4 @@ -package umc.apiPayload.code; +package umc.global.apiPayload.code; import lombok.Getter; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/umc/apiPayload/exception/ProjectException.java b/src/main/java/umc/global/apiPayload/exception/ProjectException.java similarity index 68% rename from src/main/java/umc/apiPayload/exception/ProjectException.java rename to src/main/java/umc/global/apiPayload/exception/ProjectException.java index 91b4d72..6afdab9 100644 --- a/src/main/java/umc/apiPayload/exception/ProjectException.java +++ b/src/main/java/umc/global/apiPayload/exception/ProjectException.java @@ -1,8 +1,8 @@ -package umc.apiPayload.exception; +package umc.global.apiPayload.exception; import lombok.Getter; import lombok.RequiredArgsConstructor; -import umc.apiPayload.code.BaseErrorCode; +import umc.global.apiPayload.code.BaseErrorCode; @Getter @RequiredArgsConstructor diff --git a/src/main/java/umc/apiPayload/handler/GeneralExceptionAdvice.java b/src/main/java/umc/global/apiPayload/handler/GeneralExceptionAdvice.java similarity index 87% rename from src/main/java/umc/apiPayload/handler/GeneralExceptionAdvice.java rename to src/main/java/umc/global/apiPayload/handler/GeneralExceptionAdvice.java index 90107ea..d4b55e9 100644 --- a/src/main/java/umc/apiPayload/handler/GeneralExceptionAdvice.java +++ b/src/main/java/umc/global/apiPayload/handler/GeneralExceptionAdvice.java @@ -1,13 +1,13 @@ -package umc.apiPayload.handler; +package umc.global.apiPayload.handler; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; -import umc.apiPayload.ApiResponse; -import umc.apiPayload.code.BaseErrorCode; -import umc.apiPayload.code.GeneralErrorCode; -import umc.apiPayload.exception.ProjectException; +import umc.global.apiPayload.ApiResponse; +import umc.global.apiPayload.code.BaseErrorCode; +import umc.global.apiPayload.code.GeneralErrorCode; +import umc.global.apiPayload.exception.ProjectException; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/umc/apiPayload/converter/BaseConverter.java b/src/main/java/umc/global/converter/BaseConverter.java similarity index 86% rename from src/main/java/umc/apiPayload/converter/BaseConverter.java rename to src/main/java/umc/global/converter/BaseConverter.java index 4a7e8f8..6160335 100644 --- a/src/main/java/umc/apiPayload/converter/BaseConverter.java +++ b/src/main/java/umc/global/converter/BaseConverter.java @@ -1,6 +1,6 @@ -package umc.apiPayload.converter; +package umc.global.converter; -import umc.apiPayload.dto.BaseResDTO; +import umc.global.dto.BaseResDTO; import java.util.List; diff --git a/src/main/java/umc/apiPayload/dto/BaseResDTO.java b/src/main/java/umc/global/dto/BaseResDTO.java similarity index 93% rename from src/main/java/umc/apiPayload/dto/BaseResDTO.java rename to src/main/java/umc/global/dto/BaseResDTO.java index 2639ff7..ec1f600 100644 --- a/src/main/java/umc/apiPayload/dto/BaseResDTO.java +++ b/src/main/java/umc/global/dto/BaseResDTO.java @@ -1,4 +1,4 @@ -package umc.apiPayload.dto; +package umc.global.dto; import lombok.Builder; diff --git a/src/main/java/umc/apiPayload/entity/BaseEntity.java b/src/main/java/umc/global/entity/BaseEntity.java similarity index 96% rename from src/main/java/umc/apiPayload/entity/BaseEntity.java rename to src/main/java/umc/global/entity/BaseEntity.java index fb1f0dd..e855737 100644 --- a/src/main/java/umc/apiPayload/entity/BaseEntity.java +++ b/src/main/java/umc/global/entity/BaseEntity.java @@ -1,4 +1,4 @@ -package umc.apiPayload.entity; +package umc.global.entity; import jakarta.persistence.Column; import jakarta.persistence.EntityListeners; diff --git a/src/main/java/umc/global/security/entity/AuthMember.java b/src/main/java/umc/global/security/entity/AuthMember.java new file mode 100644 index 0000000..d8596b7 --- /dev/null +++ b/src/main/java/umc/global/security/entity/AuthMember.java @@ -0,0 +1,33 @@ +package umc.global.security.entity; + +import jakarta.annotation.Nullable; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import umc.member.entity.Member; + +import java.util.Collection; +import java.util.List; + +@Getter +@RequiredArgsConstructor +public class AuthMember implements UserDetails { + + private final Member member; + + @Override + public Collection getAuthorities(){ + return List.of(); + } + + @Override + public @Nullable String getPassword(){ + return member.getPassword(); + } + + @Override + public String getUsername(){ + return member.getEmail(); + } +} diff --git a/src/main/java/umc/global/security/service/CustomUserDetailService.java b/src/main/java/umc/global/security/service/CustomUserDetailService.java new file mode 100644 index 0000000..46f7d3c --- /dev/null +++ b/src/main/java/umc/global/security/service/CustomUserDetailService.java @@ -0,0 +1,28 @@ +package umc.global.security.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; +import umc.global.security.entity.AuthMember; +import umc.member.entity.Member; +import umc.member.exception.MemberException; +import umc.member.exception.code.MemberErrorCode; +import umc.member.repository.MemberRepository; + +@Service +@RequiredArgsConstructor +public class CustomUserDetailService implements UserDetailsService { + + private final MemberRepository memberRepository; + + @Override + public UserDetails loadUserByUsername( + String username + ) throws UsernameNotFoundException{ + Member member = memberRepository.findByEmail(username) + .orElseThrow(() -> new MemberException(MemberErrorCode.MEMBER_NOT_FOUND)); + return new AuthMember(member); + } +} diff --git a/src/main/java/umc/location/exception/LocationException.java b/src/main/java/umc/location/exception/LocationException.java index 1d77aa7..157c6c5 100644 --- a/src/main/java/umc/location/exception/LocationException.java +++ b/src/main/java/umc/location/exception/LocationException.java @@ -1,7 +1,7 @@ package umc.location.exception; -import umc.apiPayload.code.BaseErrorCode; -import umc.apiPayload.exception.ProjectException; +import umc.global.apiPayload.code.BaseErrorCode; +import umc.global.apiPayload.exception.ProjectException; public class LocationException extends ProjectException { public LocationException(BaseErrorCode errorCode) { diff --git a/src/main/java/umc/location/exception/code/LocationErrorCode.java b/src/main/java/umc/location/exception/code/LocationErrorCode.java index bb6edf2..63fb98f 100644 --- a/src/main/java/umc/location/exception/code/LocationErrorCode.java +++ b/src/main/java/umc/location/exception/code/LocationErrorCode.java @@ -3,7 +3,7 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; -import umc.apiPayload.code.BaseErrorCode; +import umc.global.apiPayload.code.BaseErrorCode; @Getter @RequiredArgsConstructor diff --git a/src/main/java/umc/member/controller/MemberController.java b/src/main/java/umc/member/controller/MemberController.java index abbcc5e..60bfb27 100644 --- a/src/main/java/umc/member/controller/MemberController.java +++ b/src/main/java/umc/member/controller/MemberController.java @@ -2,11 +2,10 @@ import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; -import umc.apiPayload.ApiResponse; -import umc.apiPayload.code.BaseSuccessCode; +import umc.global.apiPayload.ApiResponse; +import umc.global.apiPayload.code.BaseSuccessCode; import umc.member.dto.MemberReqDTO; import umc.member.dto.MemberResDTO; -import umc.member.entity.Member; import umc.member.exception.code.MemberSuccessCode; import umc.member.service.MemberService; import umc.mission.dto.MissionResDTO; diff --git a/src/main/java/umc/member/converter/MemberConverter.java b/src/main/java/umc/member/converter/MemberConverter.java index a2e0dc7..83e72c1 100644 --- a/src/main/java/umc/member/converter/MemberConverter.java +++ b/src/main/java/umc/member/converter/MemberConverter.java @@ -26,9 +26,10 @@ public static MemberResDTO.GetInfo toGetInfo( .build(); } - public static Member toMember(MemberReqDTO.SingUpDTO request){ + public static Member toMember(MemberReqDTO.SingUpDTO request, String password){ return Member.builder() .email(request.email()) + .password(password) .name(request.name()) .gender(Gender.valueOf(request.gender())) .birth(request.birth()) diff --git a/src/main/java/umc/member/entity/Member.java b/src/main/java/umc/member/entity/Member.java index 37a6a85..b1edf9d 100644 --- a/src/main/java/umc/member/entity/Member.java +++ b/src/main/java/umc/member/entity/Member.java @@ -5,7 +5,7 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import umc.apiPayload.entity.BaseEntity; +import umc.global.entity.BaseEntity; import umc.member.entity.mapping.MemberFood; import umc.member.entity.mapping.MemberTerm; import umc.member.enums.Gender; @@ -44,6 +44,9 @@ public class Member extends BaseEntity { @Column(name = "email", nullable = false) private String email; + @Column(name = "password") + private String password; + @Column(name = "point", nullable = false) private Integer point; diff --git a/src/main/java/umc/member/entity/mapping/MemberFood.java b/src/main/java/umc/member/entity/mapping/MemberFood.java index 003a5c0..13bb45b 100644 --- a/src/main/java/umc/member/entity/mapping/MemberFood.java +++ b/src/main/java/umc/member/entity/mapping/MemberFood.java @@ -29,15 +29,12 @@ public class MemberFood { @JoinColumn(name = "food_id") private Food food; - public void setMember(Member member) { - if (this.member != null) { - this.member.getMemberFoodList().remove(this); - } - + public void mappingMember(Member member){ this.member = member; + member.getMemberFoodList().add(this); + } - if (member != null) { - member.getMemberFoodList().add(this); - } + public void mappingFood(Food food){ + this.food = food; } } diff --git a/src/main/java/umc/member/entity/mapping/MemberTerm.java b/src/main/java/umc/member/entity/mapping/MemberTerm.java index ce4e87d..2e089c6 100644 --- a/src/main/java/umc/member/entity/mapping/MemberTerm.java +++ b/src/main/java/umc/member/entity/mapping/MemberTerm.java @@ -27,4 +27,13 @@ public class MemberTerm { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "term_id") private Term term; + + public void mappingMember(Member member){ + this.member = member; + member.getMemberTermList().add(this); + } + + public void mappingFood(Term term){ + this.term = term; + } } diff --git a/src/main/java/umc/member/enums/Gender.java b/src/main/java/umc/member/enums/Gender.java index ca06bf9..b7c4825 100644 --- a/src/main/java/umc/member/enums/Gender.java +++ b/src/main/java/umc/member/enums/Gender.java @@ -2,6 +2,4 @@ public enum Gender { MALE, FEMALE, NONE; - - } diff --git a/src/main/java/umc/member/exception/MemberException.java b/src/main/java/umc/member/exception/MemberException.java index ddd2565..24f7458 100644 --- a/src/main/java/umc/member/exception/MemberException.java +++ b/src/main/java/umc/member/exception/MemberException.java @@ -1,7 +1,7 @@ package umc.member.exception; -import umc.apiPayload.code.BaseErrorCode; -import umc.apiPayload.exception.ProjectException; +import umc.global.apiPayload.code.BaseErrorCode; +import umc.global.apiPayload.exception.ProjectException; public class MemberException extends ProjectException { public MemberException(BaseErrorCode errorCode) { diff --git a/src/main/java/umc/member/exception/code/MemberErrorCode.java b/src/main/java/umc/member/exception/code/MemberErrorCode.java index 0f5386f..7b42ab9 100644 --- a/src/main/java/umc/member/exception/code/MemberErrorCode.java +++ b/src/main/java/umc/member/exception/code/MemberErrorCode.java @@ -3,15 +3,16 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; -import umc.apiPayload.code.BaseErrorCode; +import umc.global.apiPayload.code.BaseErrorCode; @Getter @RequiredArgsConstructor public enum MemberErrorCode implements BaseErrorCode { - MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, - "MEMBER404_1", - "해당 사용자를 찾을 수 없습니다."); + MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, "MEMBER404_1", "해당 사용자를 찾을 수 없습니다."), + DUPLICATE_EMAIL(HttpStatus.CONFLICT, "MEMBER409_1", "중복된 이메일입니다."), + INVALID_GENDER_TYPE(HttpStatus.BAD_REQUEST, "GENDER400_1", "유효하지 않은 성별입니다."), + INVALID_SOCIAL_TYPE(HttpStatus.BAD_REQUEST, "SOCIAL400_1", "유효하지 않은 소셜 타입입니다."); private final HttpStatus status; private final String code; diff --git a/src/main/java/umc/member/exception/code/MemberSuccessCode.java b/src/main/java/umc/member/exception/code/MemberSuccessCode.java index 0665445..186c3ce 100644 --- a/src/main/java/umc/member/exception/code/MemberSuccessCode.java +++ b/src/main/java/umc/member/exception/code/MemberSuccessCode.java @@ -3,7 +3,7 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; -import umc.apiPayload.code.BaseSuccessCode; +import umc.global.apiPayload.code.BaseSuccessCode; @Getter @RequiredArgsConstructor diff --git a/src/main/java/umc/member/repository/MemberFoodRepository.java b/src/main/java/umc/member/repository/MemberFoodRepository.java new file mode 100644 index 0000000..efa68a1 --- /dev/null +++ b/src/main/java/umc/member/repository/MemberFoodRepository.java @@ -0,0 +1,7 @@ +package umc.member.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import umc.member.entity.mapping.MemberFood; + +public interface MemberFoodRepository extends JpaRepository { +} diff --git a/src/main/java/umc/member/repository/MemberRepository.java b/src/main/java/umc/member/repository/MemberRepository.java index 19d7aae..8fad35a 100644 --- a/src/main/java/umc/member/repository/MemberRepository.java +++ b/src/main/java/umc/member/repository/MemberRepository.java @@ -3,5 +3,8 @@ import org.springframework.data.jpa.repository.JpaRepository; import umc.member.entity.Member; +import java.util.Optional; + public interface MemberRepository extends JpaRepository { + Optional findByEmail(String username); } diff --git a/src/main/java/umc/member/repository/MemberTermRepository.java b/src/main/java/umc/member/repository/MemberTermRepository.java new file mode 100644 index 0000000..51926af --- /dev/null +++ b/src/main/java/umc/member/repository/MemberTermRepository.java @@ -0,0 +1,7 @@ +package umc.member.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import umc.member.entity.mapping.MemberTerm; + +public interface MemberTermRepository extends JpaRepository { +} diff --git a/src/main/java/umc/member/service/MemberService.java b/src/main/java/umc/member/service/MemberService.java index 232286f..04e4aa1 100644 --- a/src/main/java/umc/member/service/MemberService.java +++ b/src/main/java/umc/member/service/MemberService.java @@ -1,6 +1,8 @@ package umc.member.service; +import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import umc.food.entity.Food; import umc.food.exeption.FoodException; @@ -11,19 +13,31 @@ import umc.member.dto.MemberResDTO; import umc.member.entity.Member; import umc.member.entity.mapping.MemberFood; +import umc.member.entity.mapping.MemberTerm; +import umc.member.enums.Gender; +import umc.member.enums.SocialType; import umc.member.exception.MemberException; import umc.member.exception.code.MemberErrorCode; +import umc.member.repository.MemberFoodRepository; import umc.member.repository.MemberRepository; +import umc.member.repository.MemberTermRepository; +import umc.term.entity.Term; +import umc.term.exception.TermException; +import umc.term.exception.code.TermErrorCode; import umc.term.repository.TermRepository; +import java.util.Arrays; import java.util.List; @Service @RequiredArgsConstructor public class MemberService { private final MemberRepository memberRepository; + private final MemberTermRepository memberTermRepository; + private final MemberFoodRepository memberFoodRepository; private final FoodRepository foodRepository; private final TermRepository termRepository; + private final PasswordEncoder passwordEncoder; public MemberResDTO.GetInfo getInfo(MemberReqDTO.GetInfo dto) { Long memberId = dto.id(); @@ -34,8 +48,26 @@ public MemberResDTO.GetInfo getInfo(MemberReqDTO.GetInfo dto) { return MemberConverter.toGetInfo(member); } + @Transactional public MemberResDTO.AuthResDTO.SignUpResultDTO signUp(MemberReqDTO.SingUpDTO request) { - Member newMember = MemberConverter.toMember(request); + + Gender gender = Arrays.stream(Gender.values()) + .filter(g -> g.name().equalsIgnoreCase(request.gender())) + .findFirst() + .orElseThrow(() -> new MemberException(MemberErrorCode.INVALID_GENDER_TYPE)); + + SocialType socialType = Arrays.stream(SocialType.values()) + .filter(s -> s.name().equalsIgnoreCase(request.socailType())) + .findFirst() + .orElseThrow(() -> new MemberException(MemberErrorCode.INVALID_SOCIAL_TYPE)); + + if(memberRepository.findByEmail(request.email()).isPresent()){ + throw new MemberException(MemberErrorCode.DUPLICATE_EMAIL); + } + + String encordPassword = passwordEncoder.encode(request.password()); + + Member newMember = MemberConverter.toMember(request, encordPassword); List foodList = request.userFoods().stream() .map(foodId -> foodRepository.findById(foodId) @@ -43,10 +75,21 @@ public MemberResDTO.AuthResDTO.SignUpResultDTO signUp(MemberReqDTO.SingUpDTO req .toList(); List memberFoodList = MemberConverter.toMemberFoodList(foodList); - memberFoodList.forEach(memberFood -> memberFood.setMember(newMember)); + memberFoodList.forEach(memberFood -> memberFood.mappingMember(newMember)); + + List termList = request.agreedTerms().stream() + .map(termId -> termRepository.findById(termId) + .orElseThrow(() -> new TermException(TermErrorCode.TERM_NOT_FOUND))) + .toList(); + + List memberTermList = MemberConverter.toMemberTermList(termList); + memberTermList.forEach(memberTerm -> memberTerm.mappingMember(newMember)); Member savedMember = memberRepository.save(newMember); + memberFoodRepository.saveAll(memberFoodList); + memberTermRepository.saveAll(memberTermList); + return MemberConverter.toSignUpResultDTO(savedMember); } } diff --git a/src/main/java/umc/mission/controller/MissionController.java b/src/main/java/umc/mission/controller/MissionController.java index 6567adf..45517e0 100644 --- a/src/main/java/umc/mission/controller/MissionController.java +++ b/src/main/java/umc/mission/controller/MissionController.java @@ -2,17 +2,15 @@ import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; -import umc.apiPayload.ApiResponse; -import umc.apiPayload.code.BaseSuccessCode; -import umc.apiPayload.dto.BaseResDTO; +import umc.global.apiPayload.ApiResponse; +import umc.global.apiPayload.code.BaseSuccessCode; +import umc.global.dto.BaseResDTO; import umc.mission.dto.MissionReqDTO; import umc.mission.dto.MissionResDTO; import umc.mission.exception.code.MissionSuccessCode; import umc.mission.service.MemberMissionService; import umc.mission.service.MissionService; -import java.util.List; - @RestController @RequiredArgsConstructor @RequestMapping("/api") diff --git a/src/main/java/umc/mission/converter/MissionConverter.java b/src/main/java/umc/mission/converter/MissionConverter.java index 7217abc..72c45e8 100644 --- a/src/main/java/umc/mission/converter/MissionConverter.java +++ b/src/main/java/umc/mission/converter/MissionConverter.java @@ -1,7 +1,7 @@ package umc.mission.converter; import org.springframework.data.domain.Page; -import umc.apiPayload.dto.BaseResDTO; +import umc.global.dto.BaseResDTO; import umc.mission.dto.MissionReqDTO; import umc.mission.dto.MissionResDTO; import umc.mission.entity.Mapping.MemberMission; diff --git a/src/main/java/umc/mission/entity/Mapping/MemberMission.java b/src/main/java/umc/mission/entity/Mapping/MemberMission.java index 7de01cd..25c11dd 100644 --- a/src/main/java/umc/mission/entity/Mapping/MemberMission.java +++ b/src/main/java/umc/mission/entity/Mapping/MemberMission.java @@ -5,7 +5,7 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import umc.apiPayload.entity.BaseEntity; +import umc.global.entity.BaseEntity; import umc.member.entity.Member; import umc.mission.entity.Mission; import umc.mission.enums.MissionStatus; diff --git a/src/main/java/umc/mission/entity/Mission.java b/src/main/java/umc/mission/entity/Mission.java index 314814d..7abb9d0 100644 --- a/src/main/java/umc/mission/entity/Mission.java +++ b/src/main/java/umc/mission/entity/Mission.java @@ -5,11 +5,9 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import umc.apiPayload.entity.BaseEntity; +import umc.global.entity.BaseEntity; import umc.store.entity.Store; -import java.time.LocalDate; - @Entity @Getter @Builder diff --git a/src/main/java/umc/mission/exception/MissionException.java b/src/main/java/umc/mission/exception/MissionException.java index d57daa2..b7664fd 100644 --- a/src/main/java/umc/mission/exception/MissionException.java +++ b/src/main/java/umc/mission/exception/MissionException.java @@ -1,7 +1,7 @@ package umc.mission.exception; -import umc.apiPayload.code.BaseErrorCode; -import umc.apiPayload.exception.ProjectException; +import umc.global.apiPayload.code.BaseErrorCode; +import umc.global.apiPayload.exception.ProjectException; public class MissionException extends ProjectException { public MissionException(BaseErrorCode errorCode) { diff --git a/src/main/java/umc/mission/exception/code/MissionErrorCode.java b/src/main/java/umc/mission/exception/code/MissionErrorCode.java index 2acc91c..9a900c1 100644 --- a/src/main/java/umc/mission/exception/code/MissionErrorCode.java +++ b/src/main/java/umc/mission/exception/code/MissionErrorCode.java @@ -3,7 +3,7 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; -import umc.apiPayload.code.BaseErrorCode; +import umc.global.apiPayload.code.BaseErrorCode; @Getter @RequiredArgsConstructor diff --git a/src/main/java/umc/mission/exception/code/MissionSuccessCode.java b/src/main/java/umc/mission/exception/code/MissionSuccessCode.java index 558e2ac..0fb3de2 100644 --- a/src/main/java/umc/mission/exception/code/MissionSuccessCode.java +++ b/src/main/java/umc/mission/exception/code/MissionSuccessCode.java @@ -3,8 +3,7 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; -import umc.apiPayload.code.BaseErrorCode; -import umc.apiPayload.code.BaseSuccessCode; +import umc.global.apiPayload.code.BaseSuccessCode; @Getter @RequiredArgsConstructor @@ -12,7 +11,7 @@ public enum MissionSuccessCode implements BaseSuccessCode { OK(HttpStatus.OK, "MISSION200_1", "성공적으로 미션을 조회했습니다."), COMPLETE_OK(HttpStatus.OK, "MISSION200_2", "미션 성공 신청 완료."), - CREATED(HttpStatus.OK, "MISSION200_3", "성공적으로 미션 생성 완료."), + CREATED(HttpStatus.CREATED, "MISSION200_3", "성공적으로 미션 생성 완료."), HOME_OK(HttpStatus.OK, "HOME200", "홈 화면이 성공적으로 조회되었습니다."), USER_MISSION_OK(HttpStatus.OK, "USER_MISSION200", "내 미션이 성공적으로 조회되었습니다."); diff --git a/src/main/java/umc/mission/service/MemberMissionService.java b/src/main/java/umc/mission/service/MemberMissionService.java index 8ec4a20..1010c27 100644 --- a/src/main/java/umc/mission/service/MemberMissionService.java +++ b/src/main/java/umc/mission/service/MemberMissionService.java @@ -5,7 +5,7 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; -import umc.apiPayload.dto.BaseResDTO; +import umc.global.dto.BaseResDTO; import umc.mission.converter.MissionConverter; import umc.mission.dto.MissionResDTO; import umc.mission.entity.Mapping.MemberMission; diff --git a/src/main/java/umc/mission/service/MissionService.java b/src/main/java/umc/mission/service/MissionService.java index ad7b85a..9297c1f 100644 --- a/src/main/java/umc/mission/service/MissionService.java +++ b/src/main/java/umc/mission/service/MissionService.java @@ -6,7 +6,7 @@ import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import umc.apiPayload.dto.BaseResDTO; +import umc.global.dto.BaseResDTO; import umc.location.enums.LocationName; import umc.location.exception.LocationException; import umc.location.exception.code.LocationErrorCode; @@ -26,8 +26,6 @@ import umc.store.exception.code.StoreErrorCode; import umc.store.repository.StoreRepository; -import java.util.List; - @Service @RequiredArgsConstructor public class MissionService { diff --git a/src/main/java/umc/review/controller/ReviewController.java b/src/main/java/umc/review/controller/ReviewController.java index 1fc5eb6..c14f680 100644 --- a/src/main/java/umc/review/controller/ReviewController.java +++ b/src/main/java/umc/review/controller/ReviewController.java @@ -3,8 +3,8 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; -import umc.apiPayload.ApiResponse; -import umc.apiPayload.dto.BaseResDTO; +import umc.global.apiPayload.ApiResponse; +import umc.global.dto.BaseResDTO; import umc.review.dto.ReviewReqDTO; import umc.review.dto.ReviewResDTO; import umc.review.exception.code.ReviewSuccessCode; diff --git a/src/main/java/umc/review/entity/Reply.java b/src/main/java/umc/review/entity/Reply.java index d07e790..76fbca8 100644 --- a/src/main/java/umc/review/entity/Reply.java +++ b/src/main/java/umc/review/entity/Reply.java @@ -2,8 +2,7 @@ import jakarta.persistence.*; import lombok.*; -import umc.apiPayload.entity.BaseEntity; -import umc.mission.entity.Mapping.MemberMission; +import umc.global.entity.BaseEntity; @Entity @Getter diff --git a/src/main/java/umc/review/entity/Review.java b/src/main/java/umc/review/entity/Review.java index eefdda4..1f381b0 100644 --- a/src/main/java/umc/review/entity/Review.java +++ b/src/main/java/umc/review/entity/Review.java @@ -2,7 +2,7 @@ import jakarta.persistence.*; import lombok.*; -import umc.apiPayload.entity.BaseEntity; +import umc.global.entity.BaseEntity; import umc.member.entity.Member; import umc.store.entity.Store; diff --git a/src/main/java/umc/review/exception/ReviewException.java b/src/main/java/umc/review/exception/ReviewException.java index eb55638..a83c50d 100644 --- a/src/main/java/umc/review/exception/ReviewException.java +++ b/src/main/java/umc/review/exception/ReviewException.java @@ -1,7 +1,7 @@ package umc.review.exception; -import umc.apiPayload.code.BaseErrorCode; -import umc.apiPayload.exception.ProjectException; +import umc.global.apiPayload.code.BaseErrorCode; +import umc.global.apiPayload.exception.ProjectException; public class ReviewException extends ProjectException { public ReviewException(BaseErrorCode errorCode) { diff --git a/src/main/java/umc/review/exception/code/ReviewErrorCode.java b/src/main/java/umc/review/exception/code/ReviewErrorCode.java index a1d50cb..af3d8a1 100644 --- a/src/main/java/umc/review/exception/code/ReviewErrorCode.java +++ b/src/main/java/umc/review/exception/code/ReviewErrorCode.java @@ -3,7 +3,7 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; -import umc.apiPayload.code.BaseErrorCode; +import umc.global.apiPayload.code.BaseErrorCode; @Getter @RequiredArgsConstructor diff --git a/src/main/java/umc/review/exception/code/ReviewSuccessCode.java b/src/main/java/umc/review/exception/code/ReviewSuccessCode.java index b9499b6..7d4f914 100644 --- a/src/main/java/umc/review/exception/code/ReviewSuccessCode.java +++ b/src/main/java/umc/review/exception/code/ReviewSuccessCode.java @@ -3,7 +3,7 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; -import umc.apiPayload.code.BaseSuccessCode; +import umc.global.apiPayload.code.BaseSuccessCode; @Getter @RequiredArgsConstructor diff --git a/src/main/java/umc/review/service/ReviewService.java b/src/main/java/umc/review/service/ReviewService.java index dcd4a68..be41136 100644 --- a/src/main/java/umc/review/service/ReviewService.java +++ b/src/main/java/umc/review/service/ReviewService.java @@ -5,15 +5,12 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Slice; import org.springframework.stereotype.Service; -import org.springframework.web.bind.annotation.PostMapping; -import umc.apiPayload.converter.BaseConverter; -import umc.apiPayload.dto.BaseResDTO; +import umc.global.converter.BaseConverter; +import umc.global.dto.BaseResDTO; import umc.member.entity.Member; import umc.member.exception.MemberException; import umc.member.exception.code.MemberErrorCode; import umc.member.repository.MemberRepository; -import umc.mission.converter.MissionConverter; -import umc.mission.dto.MissionResDTO; import umc.review.converter.ReviewConverter; import umc.review.dto.ReviewReqDTO; import umc.review.dto.ReviewResDTO; diff --git a/src/main/java/umc/store/exception/StoreException.java b/src/main/java/umc/store/exception/StoreException.java index 1aa195d..a5bc945 100644 --- a/src/main/java/umc/store/exception/StoreException.java +++ b/src/main/java/umc/store/exception/StoreException.java @@ -1,7 +1,7 @@ package umc.store.exception; -import umc.apiPayload.code.BaseErrorCode; -import umc.apiPayload.exception.ProjectException; +import umc.global.apiPayload.code.BaseErrorCode; +import umc.global.apiPayload.exception.ProjectException; public class StoreException extends ProjectException { public StoreException(BaseErrorCode errorCode) { diff --git a/src/main/java/umc/store/exception/code/StoreErrorCode.java b/src/main/java/umc/store/exception/code/StoreErrorCode.java index ac19d00..c697118 100644 --- a/src/main/java/umc/store/exception/code/StoreErrorCode.java +++ b/src/main/java/umc/store/exception/code/StoreErrorCode.java @@ -3,7 +3,7 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; -import umc.apiPayload.code.BaseErrorCode; +import umc.global.apiPayload.code.BaseErrorCode; @Getter @RequiredArgsConstructor diff --git a/src/main/java/umc/term/exception/TermException.java b/src/main/java/umc/term/exception/TermException.java index bedb8a8..0039c03 100644 --- a/src/main/java/umc/term/exception/TermException.java +++ b/src/main/java/umc/term/exception/TermException.java @@ -1,7 +1,7 @@ package umc.term.exception; -import umc.apiPayload.code.BaseErrorCode; -import umc.apiPayload.exception.ProjectException; +import umc.global.apiPayload.code.BaseErrorCode; +import umc.global.apiPayload.exception.ProjectException; public class TermException extends ProjectException { public TermException(BaseErrorCode errorCode) { diff --git a/src/main/java/umc/term/exception/code/TermErrorCode.java b/src/main/java/umc/term/exception/code/TermErrorCode.java index ac1168e..191799f 100644 --- a/src/main/java/umc/term/exception/code/TermErrorCode.java +++ b/src/main/java/umc/term/exception/code/TermErrorCode.java @@ -1,4 +1,16 @@ package umc.term.exception.code; -public enum TermErrorCode { +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import umc.global.apiPayload.code.BaseErrorCode; + +@Getter +@RequiredArgsConstructor +public enum TermErrorCode implements BaseErrorCode { + TERM_NOT_FOUND(HttpStatus.NOT_FOUND, "TERM404_1", "존재하지 않는 약관입니다."); + + private final HttpStatus status; + private final String code; + private final String message; } From 24b4097abac6b0f207ffecf6b80900fbd910972a Mon Sep 17 00:00:00 2001 From: yongyong213 Date: Wed, 20 May 2026 00:54:17 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=EC=9D=B8=EC=A6=9D=20=EC=9D=B8?= =?UTF-8?q?=EA=B0=80=20=EC=8B=A4=ED=8C=A8=20=EC=9D=91=EB=8B=B5=20=ED=86=B5?= =?UTF-8?q?=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/umc/config/SecurityConfig.java | 16 +++++++++ .../security/handler/CustomAccessDenied.java | 36 +++++++++++++++++++ .../security/handler/CustomEntryPoint.java | 35 ++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 src/main/java/umc/global/security/handler/CustomAccessDenied.java create mode 100644 src/main/java/umc/global/security/handler/CustomEntryPoint.java diff --git a/src/main/java/umc/config/SecurityConfig.java b/src/main/java/umc/config/SecurityConfig.java index 01e6ae1..05d8bbd 100644 --- a/src/main/java/umc/config/SecurityConfig.java +++ b/src/main/java/umc/config/SecurityConfig.java @@ -8,6 +8,8 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; +import umc.global.security.handler.CustomAccessDenied; +import umc.global.security.handler.CustomEntryPoint; @EnableWebSecurity @Configuration @@ -37,6 +39,10 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .logoutUrl("/logout") .logoutSuccessUrl("/login?logout") .permitAll() + ) + .exceptionHandling(exception -> exception + .accessDeniedHandler(customAccessDenied()) + .authenticationEntryPoint(customEntryPoint()) ); return http.build(); } @@ -45,4 +51,14 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } + + @Bean + public CustomAccessDenied customAccessDenied(){ + return new CustomAccessDenied(); + } + + @Bean + public CustomEntryPoint customEntryPoint(){ + return new CustomEntryPoint(); + } } diff --git a/src/main/java/umc/global/security/handler/CustomAccessDenied.java b/src/main/java/umc/global/security/handler/CustomAccessDenied.java new file mode 100644 index 0000000..352cb90 --- /dev/null +++ b/src/main/java/umc/global/security/handler/CustomAccessDenied.java @@ -0,0 +1,36 @@ +package umc.global.security.handler; + +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.web.access.AccessDeniedHandler; +import umc.global.apiPayload.ApiResponse; +import umc.global.apiPayload.code.BaseErrorCode; +import umc.global.apiPayload.code.GeneralErrorCode; + +import java.io.IOException; + +public class CustomAccessDenied implements AccessDeniedHandler { + + @Override + public void handle( + HttpServletRequest request, + HttpServletResponse response, + AccessDeniedException accessDeniedException + ) throws IOException { + ObjectMapper objectMapper = new ObjectMapper(); + BaseErrorCode code = GeneralErrorCode.FORBIDDEN; + + // 응답 Content-Type, HTTP 상태코드 정의 + response.setContentType("application/json;charset=UTF-8"); + response.setStatus(code.getStatus().value()); + + // Response Body에 응답통일한 객체를 넣기 + ApiResponse errorResponse = ApiResponse.onFailure(code,null); + + // 실제 Response로 덮어쓰기 + objectMapper.writeValue(response.getOutputStream(), errorResponse); + } +} + diff --git a/src/main/java/umc/global/security/handler/CustomEntryPoint.java b/src/main/java/umc/global/security/handler/CustomEntryPoint.java new file mode 100644 index 0000000..7ca95e6 --- /dev/null +++ b/src/main/java/umc/global/security/handler/CustomEntryPoint.java @@ -0,0 +1,35 @@ +package umc.global.security.handler; + +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import umc.global.apiPayload.ApiResponse; +import umc.global.apiPayload.code.BaseErrorCode; +import umc.global.apiPayload.code.GeneralErrorCode; + +import java.io.IOException; + +public class CustomEntryPoint implements AuthenticationEntryPoint { + + @Override + public void commence( + HttpServletRequest request, + HttpServletResponse response, + AuthenticationException authException + ) throws IOException { + ObjectMapper objectMapper = new ObjectMapper(); + BaseErrorCode code = GeneralErrorCode.UNAUTHORIZED; + + // 응답 Content-Type, HTTP 상태코드 정의 + response.setContentType("application/json;charset=UTF-8"); + response.setStatus(code.getStatus().value()); + + // Response Body에 응답통일한 객체를 넣기 + ApiResponse errorResponse = ApiResponse.onFailure(code,null); + + // 실제 Response로 덮어쓰기 + objectMapper.writeValue(response.getOutputStream(), errorResponse); + } +} From 822db0cb1686cc23be0d1e1d4126642871f3b774 Mon Sep 17 00:00:00 2001 From: yongyong213 Date: Wed, 20 May 2026 01:07:04 +0900 Subject: [PATCH 3/3] =?UTF-8?q?feat:=20=EC=8A=A4=EC=9B=A8=EC=BB=A4=20?= =?UTF-8?q?=EC=84=A4=EB=AA=85=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/umc/member/controller/MemberController.java | 4 ++++ src/main/java/umc/mission/controller/MissionController.java | 6 ++++++ src/main/java/umc/review/controller/ReviewController.java | 3 +++ 3 files changed, 13 insertions(+) diff --git a/src/main/java/umc/member/controller/MemberController.java b/src/main/java/umc/member/controller/MemberController.java index 60bfb27..a3df2cd 100644 --- a/src/main/java/umc/member/controller/MemberController.java +++ b/src/main/java/umc/member/controller/MemberController.java @@ -1,5 +1,6 @@ package umc.member.controller; +import io.swagger.v3.oas.annotations.Operation; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import umc.global.apiPayload.ApiResponse; @@ -20,6 +21,7 @@ public class MemberController { private final MissionService missionService; @PostMapping("/v1/users/me") + @Operation(summary = "마이페이지 조회") public ApiResponse getInfo( @RequestBody MemberReqDTO.GetInfo dto ){ @@ -28,6 +30,7 @@ public ApiResponse getInfo( } @GetMapping("/v1/home") + @Operation(summary = "지역 미션 조회") public ApiResponse getHomeInfo( @RequestParam(name = "memberId") Long memberId, @RequestParam(name = "regionName") String regionName, @@ -37,6 +40,7 @@ public ApiResponse getHomeInfo( } @PostMapping("/v1/auth/signup") + @Operation(summary = "회원가입") public ApiResponse signUp( @RequestBody MemberReqDTO.SingUpDTO request ) { diff --git a/src/main/java/umc/mission/controller/MissionController.java b/src/main/java/umc/mission/controller/MissionController.java index 45517e0..0f80073 100644 --- a/src/main/java/umc/mission/controller/MissionController.java +++ b/src/main/java/umc/mission/controller/MissionController.java @@ -1,5 +1,6 @@ package umc.mission.controller; +import io.swagger.v3.oas.annotations.Operation; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import umc.global.apiPayload.ApiResponse; @@ -19,6 +20,7 @@ public class MissionController { private final MemberMissionService memberMissionService; @GetMapping("/v1/users/me/missions") + @Operation(summary = "미션 조회 옛날 버전") public ApiResponse getMyMissions( @RequestParam(name = "isComplete") Boolean isComplete, @RequestParam(name = "page") Integer page @@ -27,6 +29,7 @@ public ApiResponse getMyMissions( } @PatchMapping("/v1/users/user-missions/{userMissionId}") + @Operation(summary = "미션 성공 업데이트") public ApiResponse completeMission( @PathVariable(name = "userMissionId") Long userMissionId ) { @@ -34,6 +37,7 @@ public ApiResponse completeMission( } @PostMapping("/v1/stores/{storeId}/missions") + @Operation(summary = "가게 미션 생성") public ApiResponse createMission( @PathVariable Long storeId, @RequestBody MissionReqDTO.CreateMission dto @@ -43,6 +47,7 @@ public ApiResponse createMission( } @GetMapping("/v1/stores/{storeId}/missions") + @Operation(summary = "가게 미션 조회") public ApiResponse> getMissions( @PathVariable Long storeId, @RequestParam Integer pageSize, @@ -54,6 +59,7 @@ public ApiResponse> getMissions( } @GetMapping("/v1/missions/in-progress") + @Operation(summary = "진행 중/완료 한 미션 조회") public ApiResponse> getInProgressMissions( @RequestParam Long memberId, @RequestParam Integer pageSize, diff --git a/src/main/java/umc/review/controller/ReviewController.java b/src/main/java/umc/review/controller/ReviewController.java index c14f680..0e54994 100644 --- a/src/main/java/umc/review/controller/ReviewController.java +++ b/src/main/java/umc/review/controller/ReviewController.java @@ -1,5 +1,6 @@ package umc.review.controller; +import io.swagger.v3.oas.annotations.Operation; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; @@ -17,6 +18,7 @@ public class ReviewController { private final ReviewService reviewService; @PostMapping("/v1/stores/{storeId}/members/{memberId}/reviews") + @Operation(summary = "리뷰 작성") public ApiResponse createReview( @PathVariable(name = "storeId") Long storeId, @PathVariable(name = "memberId") Long memberId, @@ -28,6 +30,7 @@ public ApiResponse createReview( } @GetMapping("/v1/members/{memberId}/reviews") + @Operation(summary = "멤버의 리뷰 조회") public ApiResponse> getMyReviews( @PathVariable Long memberId, @RequestParam Integer pageSize,