diff --git a/src/main/java/kr/co/fastcampus/yanabada/common/config/EmailConfig.java b/src/main/java/kr/co/fastcampus/yanabada/common/config/EmailConfig.java index a252ab5b..86efbc15 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/common/config/EmailConfig.java +++ b/src/main/java/kr/co/fastcampus/yanabada/common/config/EmailConfig.java @@ -25,8 +25,8 @@ public class EmailConfig { public JavaMailSender mailSender() { JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); mailSender.setHost(host); - mailSender.setPort(port); //todo: 상수 분리 - mailSender.setUsername(user); //todo: 상수 분리 + mailSender.setPort(port); + mailSender.setUsername(user); mailSender.setPassword(password); Properties javaMailProperties = getMailProperties(); diff --git a/src/main/java/kr/co/fastcampus/yanabada/common/config/SecurityConfig.java b/src/main/java/kr/co/fastcampus/yanabada/common/config/SecurityConfig.java index f12bb496..0f4f7efe 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/common/config/SecurityConfig.java +++ b/src/main/java/kr/co/fastcampus/yanabada/common/config/SecurityConfig.java @@ -1,5 +1,8 @@ package kr.co.fastcampus.yanabada.common.config; +import static org.springframework.http.HttpMethod.GET; +import static org.springframework.http.HttpMethod.POST; + import java.util.List; import kr.co.fastcampus.yanabada.common.jwt.filter.JwtAuthFilter; import kr.co.fastcampus.yanabada.common.jwt.filter.JwtExceptionFilter; @@ -11,6 +14,7 @@ import org.springframework.boot.autoconfigure.security.servlet.PathRequest; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; @@ -34,8 +38,15 @@ public class SecurityConfig { private final Oauth2LoginFailureHandler oauth2LoginFailureHandler; private static final String[] PERMIT_PATHS = { - "/", - "/**" + "/auth", "/auth/**" + }; + + private static final String[] PERMIT_PATHS_POST_METHOD = { + "/accommodations/**", "/orders" + }; + + private static final String[] PERMIT_PATHS_GET_METHOD = { + "/products", "/products/**" }; @Bean @@ -49,8 +60,11 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { ); http.authorizeHttpRequests(authorize -> authorize - .requestMatchers(PERMIT_PATHS).permitAll() - .anyRequest().authenticated() + .requestMatchers(PERMIT_PATHS).permitAll() + .requestMatchers(POST, PERMIT_PATHS_POST_METHOD).permitAll() + .requestMatchers(GET, PERMIT_PATHS_GET_METHOD).permitAll() + .requestMatchers("/products/own").denyAll() + .anyRequest().authenticated() ); http.oauth2Login(oauth2 -> oauth2 @@ -73,7 +87,7 @@ CorsConfigurationSource corsConfigurationSource() { configuration.setAllowedMethods(List.of("*")); configuration.setAllowedHeaders(List.of("*")); configuration.addExposedHeader("Authorization"); - configuration.setAllowCredentials(true); //todo : 쿠키를 포함한 크로스 도메인 요청을 허용? 확인필요 + configuration.setAllowCredentials(true); //쿠키를 포함한 크로스 도메인 요청을 허용 configuration.setMaxAge(3600L); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); @@ -83,7 +97,7 @@ CorsConfigurationSource corsConfigurationSource() { @Bean @ConditionalOnProperty(name = "spring.h2.console.enabled", havingValue = "true") - public WebSecurityCustomizer configureH2ConsoleEnable() { // h2-console 화면설정 + public WebSecurityCustomizer configureH2ConsoleEnable() { return web -> web.ignoring() .requestMatchers(PathRequest.toH2Console()); } diff --git a/src/main/java/kr/co/fastcampus/yanabada/common/exception/NotMatchedProviderNameException.java b/src/main/java/kr/co/fastcampus/yanabada/common/exception/NotMatchedProviderNameException.java new file mode 100644 index 00000000..fed7e7c9 --- /dev/null +++ b/src/main/java/kr/co/fastcampus/yanabada/common/exception/NotMatchedProviderNameException.java @@ -0,0 +1,9 @@ +package kr.co.fastcampus.yanabada.common.exception; + +import static kr.co.fastcampus.yanabada.common.response.ErrorCode.NOT_MATCHED_PROVIDER_NAME; + +public class NotMatchedProviderNameException extends BaseException { + public NotMatchedProviderNameException() { + super(NOT_MATCHED_PROVIDER_NAME.getMessage()); + } +} diff --git a/src/main/java/kr/co/fastcampus/yanabada/common/exception/handler/GlobalExceptionHandler.java b/src/main/java/kr/co/fastcampus/yanabada/common/exception/handler/GlobalExceptionHandler.java index c18329a3..90b4762a 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/common/exception/handler/GlobalExceptionHandler.java +++ b/src/main/java/kr/co/fastcampus/yanabada/common/exception/handler/GlobalExceptionHandler.java @@ -12,6 +12,7 @@ import kr.co.fastcampus.yanabada.common.exception.FcmAccessTokenGetFailedException; import kr.co.fastcampus.yanabada.common.exception.FcmMessageSendFailedException; import kr.co.fastcampus.yanabada.common.exception.JsonProcessFailedException; +import kr.co.fastcampus.yanabada.common.exception.NotMatchedProviderNameException; import kr.co.fastcampus.yanabada.common.exception.OkHttp3RequestFailedException; import kr.co.fastcampus.yanabada.common.exception.TokenExpiredException; import kr.co.fastcampus.yanabada.common.jwt.dto.TokenExpiredResponse; @@ -177,4 +178,13 @@ public ResponseBody fcmAccessTokenGetFailedException( return ResponseBody.fail(e.getMessage()); } + @ExceptionHandler(NotMatchedProviderNameException.class) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + public ResponseBody notMatchedProviderNameException( + NotMatchedProviderNameException e + ) { + log.error("[NotMatchedProviderNameException] Message = {}", e.getMessage()); + return ResponseBody.fail(e.getMessage()); + } + } diff --git a/src/main/java/kr/co/fastcampus/yanabada/common/jwt/filter/JwtAuthFilter.java b/src/main/java/kr/co/fastcampus/yanabada/common/jwt/filter/JwtAuthFilter.java index 3c325842..14051dfe 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/common/jwt/filter/JwtAuthFilter.java +++ b/src/main/java/kr/co/fastcampus/yanabada/common/jwt/filter/JwtAuthFilter.java @@ -40,7 +40,7 @@ public class JwtAuthFilter extends OncePerRequestFilter { protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException { /* 토큰 로그인, 회원가입 경우 해당 필터 실행 안됨 */ return request.getRequestURI().contains("/sign-up") - || request.getRequestURI().contains("/login"); //todo: 로그아웃 추가 고민 + || request.getRequestURI().contains("/login"); } @Override diff --git a/src/main/java/kr/co/fastcampus/yanabada/common/response/ErrorCode.java b/src/main/java/kr/co/fastcampus/yanabada/common/response/ErrorCode.java index 143bef5d..00978fdb 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/common/response/ErrorCode.java +++ b/src/main/java/kr/co/fastcampus/yanabada/common/response/ErrorCode.java @@ -51,7 +51,9 @@ public enum ErrorCode { OKHTTP3_REQUEST_FAILED("okhttp3의 리퀘스트 생성이 실패하였습니다."), FCM_MESSAGE_SEND_FAILED("FCM 메세지 전송이 실패하였습니다."), - FCM_ACCESS_TOKEN_GET_FAILED("FCM 엑세스 토큰을 발급 받는 데 실패하였습니다.") + FCM_ACCESS_TOKEN_GET_FAILED("FCM 엑세스 토큰을 발급 받는 데 실패하였습니다."), + + NOT_MATCHED_PROVIDER_NAME("Provider 이름이 매칭이 안됩니다."), ; diff --git a/src/main/java/kr/co/fastcampus/yanabada/common/security/oauth/Oauth2Attribute.java b/src/main/java/kr/co/fastcampus/yanabada/common/security/oauth/Oauth2Attribute.java index 122b7541..2ac8077d 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/common/security/oauth/Oauth2Attribute.java +++ b/src/main/java/kr/co/fastcampus/yanabada/common/security/oauth/Oauth2Attribute.java @@ -4,6 +4,7 @@ import java.util.HashMap; import java.util.Map; +import kr.co.fastcampus.yanabada.common.exception.NotMatchedProviderNameException; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -28,7 +29,7 @@ static Oauth2Attribute of( return ofKakao(KAKAO.name(), "email", attributes); //todo: 다른 OAuth 구현 시 조건문 추가 } - throw new RuntimeException(); //todo: CustomEx + throw new NotMatchedProviderNameException(); } private static Oauth2Attribute ofKakao( diff --git a/src/main/java/kr/co/fastcampus/yanabada/common/security/oauth/Oauth2LoginFailureHandler.java b/src/main/java/kr/co/fastcampus/yanabada/common/security/oauth/Oauth2LoginFailureHandler.java index f0e5431b..a64b0125 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/common/security/oauth/Oauth2LoginFailureHandler.java +++ b/src/main/java/kr/co/fastcampus/yanabada/common/security/oauth/Oauth2LoginFailureHandler.java @@ -5,6 +5,7 @@ import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; import org.springframework.stereotype.Component; @@ -12,13 +13,16 @@ @Slf4j @Component public class Oauth2LoginFailureHandler extends SimpleUrlAuthenticationFailureHandler { + + @Value("${spring.login.root-url}") + String rootUrl; + @Override public void onAuthenticationFailure( HttpServletRequest request, HttpServletResponse response, AuthenticationException exception - ) throws IOException, ServletException { - response.sendRedirect("http://localhost:8080/"); - //todo: 환경 변수로 뺄 예정 + ) throws IOException { + response.sendRedirect(rootUrl); } } diff --git a/src/main/java/kr/co/fastcampus/yanabada/common/security/oauth/Oauth2LoginSuccessHandler.java b/src/main/java/kr/co/fastcampus/yanabada/common/security/oauth/Oauth2LoginSuccessHandler.java index 70bd02b4..57a32057 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/common/security/oauth/Oauth2LoginSuccessHandler.java +++ b/src/main/java/kr/co/fastcampus/yanabada/common/security/oauth/Oauth2LoginSuccessHandler.java @@ -15,6 +15,7 @@ import kr.co.fastcampus.yanabada.domain.member.entity.ProviderType; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.core.user.DefaultOAuth2User; import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; @@ -26,10 +27,14 @@ @RequiredArgsConstructor public class Oauth2LoginSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { - private final JwtProvider jwtProvider; - private final TokenService tokenService; private final AuthService authService; private final ObjectMapper objectMapper; + @Value("${spring.login.root-url}") + String rootUrl; + @Value("${spring.login.oauth2-redirect-url}") + String oauthRedirectUrl; + @Value("${spring.login.oauth2-password}") + String oauthPassword; @Override @Transactional @@ -48,7 +53,6 @@ public void onAuthenticationSuccess( if (isExist) { /* 바로 로그인 */ - String oauthPassword = "oauth-password"; //todo: 환경 변수 분리 LoginRequest loginRequest = new LoginRequest(email, oauthPassword); LoginResponse loginResponse = authService.loginOauth(loginRequest, ProviderType.valueOf(provider)); @@ -58,8 +62,9 @@ public void onAuthenticationSuccess( response.getWriter().write(loginResponseJson); } else { /* 회원 가입 필요 */ - //todo: url 변경 예정, 환경 변수(서버, 로컬) 분리 예정 - String redirectUrl = "http://localhost:8080/redirect-url" + //todo: url 변경 예정 + String redirectUrl = rootUrl + + oauthRedirectUrl + "?email=" + attribute.get("email") + "&provider=" + attribute.get("provider"); response.sendRedirect(redirectUrl); diff --git a/src/main/java/kr/co/fastcampus/yanabada/domain/auth/service/AuthService.java b/src/main/java/kr/co/fastcampus/yanabada/domain/auth/service/AuthService.java index 07d6875f..9d4a4432 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/domain/auth/service/AuthService.java +++ b/src/main/java/kr/co/fastcampus/yanabada/domain/auth/service/AuthService.java @@ -3,6 +3,7 @@ import static kr.co.fastcampus.yanabada.domain.member.entity.ProviderType.EMAIL; import static kr.co.fastcampus.yanabada.domain.member.entity.RoleType.ROLE_USER; +import java.util.Random; import kr.co.fastcampus.yanabada.common.exception.EmailDuplicatedException; import kr.co.fastcampus.yanabada.common.jwt.dto.TokenIssueResponse; import kr.co.fastcampus.yanabada.common.jwt.dto.TokenRefreshResponse; @@ -17,6 +18,7 @@ import kr.co.fastcampus.yanabada.domain.member.repository.MemberRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.crypto.password.PasswordEncoder; @@ -35,6 +37,8 @@ public class AuthService { private final JwtProvider jwtProvider; private final AuthenticationManagerBuilder authenticationManagerBuilder; private final TokenService tokenService; + @Value("${spring.login.oauth2-password}") + String oauthPassword; @Transactional public Long signUp(SignUpRequest signUpRequest) { @@ -43,14 +47,16 @@ public Long signUp(SignUpRequest signUpRequest) { } String encodedPassword = passwordEncoder.encode(signUpRequest.password()); + Member member = Member.builder() - .email(signUpRequest.email()) - .nickName(signUpRequest.nickName()) - .password(encodedPassword) - .phoneNumber(signUpRequest.phoneNumber()) - .roleType(ROLE_USER) - .providerType(EMAIL) - .build(); + .email(signUpRequest.email()) + .nickName(signUpRequest.nickName()) + .password(encodedPassword) + .phoneNumber(signUpRequest.phoneNumber()) + .roleType(ROLE_USER) + .image(getRandomProfileImage()) + .providerType(EMAIL) + .build(); Member savedMember = memberRepository.save(member); return savedMember.getId(); @@ -59,14 +65,14 @@ public Long signUp(SignUpRequest signUpRequest) { @Transactional public Long oauthSignUp(OauthSignUpRequest signUpRequest) { - String encodedPassword = passwordEncoder.encode("oauth-password"); - //todo: 패스워드 환경변수 분리 + String encodedPassword = passwordEncoder.encode(oauthPassword); Member member = Member.builder() .email(signUpRequest.email()) .nickName(signUpRequest.nickName()) .password(encodedPassword) .phoneNumber(signUpRequest.phoneNumber()) .roleType(ROLE_USER) + .image(getRandomProfileImage()) .providerType(signUpRequest.provider()) .build(); @@ -74,6 +80,12 @@ public Long oauthSignUp(OauthSignUpRequest signUpRequest) { return savedMember.getId(); } + private String getRandomProfileImage() { + Random random = new Random(); + int randomNumber = random.nextInt(5) + 1; + return randomNumber + "profile.png"; //todo: 환경 변수 분리 + } + @Transactional public LoginResponse login(LoginRequest loginRequest) { UsernamePasswordAuthenticationToken authenticationToken = loginRequest.toAuthentication(); diff --git a/src/main/java/kr/co/fastcampus/yanabada/domain/chat/dto/SendChatMessage.java b/src/main/java/kr/co/fastcampus/yanabada/domain/chat/dto/SendChatMessage.java index 76e04a74..31b00a91 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/domain/chat/dto/SendChatMessage.java +++ b/src/main/java/kr/co/fastcampus/yanabada/domain/chat/dto/SendChatMessage.java @@ -27,7 +27,7 @@ public static SendChatMessage from( .chatRoomCode(chatRoom.getCode()) .sendId(sender.getId()) .senderNickname(sender.getNickName()) - .senderProfileImage(sender.getImageUrl()) + .senderProfileImage(sender.getImage()) .content(content) .sendTime(sendTime) .build(); diff --git a/src/main/java/kr/co/fastcampus/yanabada/domain/chat/dto/response/ChatMessageInfoResponse.java b/src/main/java/kr/co/fastcampus/yanabada/domain/chat/dto/response/ChatMessageInfoResponse.java index b3c6ee3a..c4e4ce8c 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/domain/chat/dto/response/ChatMessageInfoResponse.java +++ b/src/main/java/kr/co/fastcampus/yanabada/domain/chat/dto/response/ChatMessageInfoResponse.java @@ -20,7 +20,7 @@ public static ChatMessageInfoResponse from( ) { return ChatMessageInfoResponse.builder() .senderId(sender.getId()) - .senderImage(sender.getImageUrl()) + .senderImage(sender.getImage()) .senderNickname(sender.getNickName()) .content(content) .sendDateTime(sendDateTime) diff --git a/src/main/java/kr/co/fastcampus/yanabada/domain/chat/dto/response/ChatRoomSummaryResponse.java b/src/main/java/kr/co/fastcampus/yanabada/domain/chat/dto/response/ChatRoomSummaryResponse.java index 7c52b406..9611850f 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/domain/chat/dto/response/ChatRoomSummaryResponse.java +++ b/src/main/java/kr/co/fastcampus/yanabada/domain/chat/dto/response/ChatRoomSummaryResponse.java @@ -29,7 +29,7 @@ public static ChatRoomSummaryResponse from( ) { return ChatRoomSummaryResponse.builder() .chatRoomCode(chatRoomCode) - .partnerImage(partner.getImageUrl()) + .partnerImage(partner.getImage()) .partnerNickname(partner.getNickName()) .lastChatMessage(message.getContent()) .lastSentMessageTime(message.getSendDateTime()) diff --git a/src/main/java/kr/co/fastcampus/yanabada/domain/member/controller/MemberController.java b/src/main/java/kr/co/fastcampus/yanabada/domain/member/controller/MemberController.java index 24cd81d6..14e28936 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/domain/member/controller/MemberController.java +++ b/src/main/java/kr/co/fastcampus/yanabada/domain/member/controller/MemberController.java @@ -4,7 +4,6 @@ import kr.co.fastcampus.yanabada.common.response.ResponseBody; import kr.co.fastcampus.yanabada.common.security.PrincipalDetails; import kr.co.fastcampus.yanabada.domain.member.dto.request.FcmTokenUpdateRequest; -import kr.co.fastcampus.yanabada.domain.member.dto.request.ImgUrlModifyRequest; import kr.co.fastcampus.yanabada.domain.member.dto.request.NickNameModifyRequest; import kr.co.fastcampus.yanabada.domain.member.dto.request.PasswordModifyRequest; import kr.co.fastcampus.yanabada.domain.member.dto.request.PhoneNumberModifyRequest; @@ -69,17 +68,6 @@ public ResponseBody modifyPhoneNumber( return ResponseBody.ok(); } - @PutMapping("/image") - public ResponseBody modifyImage( - @AuthenticationPrincipal PrincipalDetails principalDetails, - @RequestBody @Valid ImgUrlModifyRequest imgUrlRequest - ) { - memberService.modifyImageUrl( - imgUrlRequest, principalDetails.email(), principalDetails.provider() - ); - return ResponseBody.ok(); - } - @PutMapping("/fcm-token") public ResponseBody updateFcmToken( @AuthenticationPrincipal PrincipalDetails principalDetails, diff --git a/src/main/java/kr/co/fastcampus/yanabada/domain/member/dto/request/ImgUrlModifyRequest.java b/src/main/java/kr/co/fastcampus/yanabada/domain/member/dto/request/ImgUrlModifyRequest.java deleted file mode 100644 index 29dcc9ac..00000000 --- a/src/main/java/kr/co/fastcampus/yanabada/domain/member/dto/request/ImgUrlModifyRequest.java +++ /dev/null @@ -1,10 +0,0 @@ -package kr.co.fastcampus.yanabada.domain.member.dto.request; - -import jakarta.validation.constraints.NotEmpty; - -public record ImgUrlModifyRequest( - @NotEmpty(message = "패스워드가 비어있을 수 없습니다") - String imageUrl -) { -} - diff --git a/src/main/java/kr/co/fastcampus/yanabada/domain/member/dto/response/MemberDetailResponse.java b/src/main/java/kr/co/fastcampus/yanabada/domain/member/dto/response/MemberDetailResponse.java index 7eff71da..dacf01ca 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/domain/member/dto/response/MemberDetailResponse.java +++ b/src/main/java/kr/co/fastcampus/yanabada/domain/member/dto/response/MemberDetailResponse.java @@ -10,7 +10,7 @@ public record MemberDetailResponse( String email, String nickName, String phoneNumber, - String imageUrl, + String image, Integer point, ProviderType provider ) { @@ -20,7 +20,7 @@ public static MemberDetailResponse from(Member member) { .email(member.getEmail()) .nickName(member.getNickName()) .phoneNumber(member.getPhoneNumber()) - .imageUrl(member.getImageUrl()) + .image(member.getImage()) .point(member.getPoint()) .provider(member.getProviderType()) .build(); diff --git a/src/main/java/kr/co/fastcampus/yanabada/domain/member/dto/response/MemberSummaryResponse.java b/src/main/java/kr/co/fastcampus/yanabada/domain/member/dto/response/MemberSummaryResponse.java index dbaada2c..b6cbb7e9 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/domain/member/dto/response/MemberSummaryResponse.java +++ b/src/main/java/kr/co/fastcampus/yanabada/domain/member/dto/response/MemberSummaryResponse.java @@ -7,14 +7,14 @@ public record MemberSummaryResponse( Long id, String nickname, - String imageUrl + String image ) { public static MemberSummaryResponse from(Member member) { return MemberSummaryResponse.builder() .id(member.getId()) .nickname(member.getNickName()) - .imageUrl(member.getImageUrl()) + .image(member.getImage()) .build(); } } diff --git a/src/main/java/kr/co/fastcampus/yanabada/domain/member/entity/Member.java b/src/main/java/kr/co/fastcampus/yanabada/domain/member/entity/Member.java index 409e047c..89214bd2 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/domain/member/entity/Member.java +++ b/src/main/java/kr/co/fastcampus/yanabada/domain/member/entity/Member.java @@ -27,7 +27,7 @@ public class Member extends BaseEntity { private String nickName; private String password; private String phoneNumber; - private String imageUrl; + private String image; @Builder.Default private Integer point = 0; @Enumerated(EnumType.STRING) @@ -48,10 +48,6 @@ public void updatePhoneNumber(String phoneNumber) { this.phoneNumber = phoneNumber; } - public void updateImageUrl(String imageUrl) { - this.imageUrl = imageUrl; - } - public void subtractPoint(int point) { if (this.point < point) { throw new NotEnoughPointException(); diff --git a/src/main/java/kr/co/fastcampus/yanabada/domain/member/service/MemberService.java b/src/main/java/kr/co/fastcampus/yanabada/domain/member/service/MemberService.java index d0d79473..95d3fd47 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/domain/member/service/MemberService.java +++ b/src/main/java/kr/co/fastcampus/yanabada/domain/member/service/MemberService.java @@ -7,7 +7,6 @@ import kr.co.fastcampus.yanabada.domain.auth.dto.response.EmailAuthResponse; import kr.co.fastcampus.yanabada.domain.auth.service.MailAuthService; import kr.co.fastcampus.yanabada.domain.member.dto.request.FcmTokenUpdateRequest; -import kr.co.fastcampus.yanabada.domain.member.dto.request.ImgUrlModifyRequest; import kr.co.fastcampus.yanabada.domain.member.dto.request.NickNameDuplCheckRequest; import kr.co.fastcampus.yanabada.domain.member.dto.request.NickNameModifyRequest; import kr.co.fastcampus.yanabada.domain.member.dto.request.PasswordModifyRequest; @@ -67,16 +66,6 @@ public void modifyPhoneNumber( member.updatePhoneNumber(phoneNumberRequest.phoneNumber()); } - @Transactional - public void modifyImageUrl( - ImgUrlModifyRequest imgUrlRequest, - String email, - ProviderType providerType - ) { - Member member = memberRepository.getMember(email, providerType); - member.updateImageUrl(imgUrlRequest.imageUrl()); - } - @Transactional(readOnly = true) public EmailAuthResponse verifyEmail( EmailAuthRequest emailRequest diff --git a/src/main/java/kr/co/fastcampus/yanabada/domain/notification/controller/NotificationController.java b/src/main/java/kr/co/fastcampus/yanabada/domain/notification/controller/NotificationController.java new file mode 100644 index 00000000..86e3af29 --- /dev/null +++ b/src/main/java/kr/co/fastcampus/yanabada/domain/notification/controller/NotificationController.java @@ -0,0 +1,35 @@ +package kr.co.fastcampus.yanabada.domain.notification.controller; + +import kr.co.fastcampus.yanabada.common.response.ResponseBody; +import kr.co.fastcampus.yanabada.common.security.PrincipalDetails; +import kr.co.fastcampus.yanabada.domain.notification.dto.response.NotificationPageResponse; +import kr.co.fastcampus.yanabada.domain.notification.service.NotificationService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.web.PageableDefault; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Slf4j +@RestController +@RequiredArgsConstructor +@RequestMapping("/notifications") +public class NotificationController { + + private final NotificationService notificationService; + + @GetMapping + public ResponseBody getNotifications( + @AuthenticationPrincipal PrincipalDetails principalDetails, + @PageableDefault(sort = "registeredDate", direction = Sort.Direction.DESC) + Pageable pageable + ) { + return ResponseBody.ok( + notificationService.getNotifications(principalDetails.id(), pageable) + ); + } +} diff --git a/src/main/java/kr/co/fastcampus/yanabada/domain/notification/dto/ChatNotificationDto.java b/src/main/java/kr/co/fastcampus/yanabada/domain/notification/dto/ChatNotificationDto.java index 35c38360..267b63b9 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/domain/notification/dto/ChatNotificationDto.java +++ b/src/main/java/kr/co/fastcampus/yanabada/domain/notification/dto/ChatNotificationDto.java @@ -15,6 +15,7 @@ public record ChatNotificationDto( Member receiver, String accommodationName, String chatRoomCode, + String senderNickname, String image ) { @@ -35,6 +36,7 @@ public static ChatNotificationDto from( public String convertMapToJsonStr(ObjectMapper objectMapper) { Map contentMap = new HashMap<>(); + contentMap.put("senderNickname", senderNickname); contentMap.put("accommodationName", accommodationName); contentMap.put("chatRoomCode", chatRoomCode); try { diff --git a/src/main/java/kr/co/fastcampus/yanabada/domain/notification/dto/TradeNotificationDto.java b/src/main/java/kr/co/fastcampus/yanabada/domain/notification/dto/TradeNotificationDto.java index 2586eac8..4c24ed07 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/domain/notification/dto/TradeNotificationDto.java +++ b/src/main/java/kr/co/fastcampus/yanabada/domain/notification/dto/TradeNotificationDto.java @@ -6,11 +6,22 @@ import java.util.Map; import kr.co.fastcampus.yanabada.common.exception.JsonProcessFailedException; import kr.co.fastcampus.yanabada.domain.member.entity.Member; +import lombok.Builder; +@Builder public record TradeNotificationDto( Member receiver, String accommodationName ) { + public static TradeNotificationDto from( + Member receiver, + String accommodationName + ) { + return TradeNotificationDto.builder() + .receiver(receiver) + .accommodationName(accommodationName) + .build(); + } public String convertMapToJsonStr(ObjectMapper objectMapper) { Map contentMap = new HashMap<>(); diff --git a/src/main/java/kr/co/fastcampus/yanabada/domain/notification/dto/response/NotificationInfoResponse.java b/src/main/java/kr/co/fastcampus/yanabada/domain/notification/dto/response/NotificationInfoResponse.java new file mode 100644 index 00000000..cc70dc3d --- /dev/null +++ b/src/main/java/kr/co/fastcampus/yanabada/domain/notification/dto/response/NotificationInfoResponse.java @@ -0,0 +1,34 @@ +package kr.co.fastcampus.yanabada.domain.notification.dto.response; + +import com.fasterxml.jackson.annotation.JsonFormat; +import java.time.LocalDateTime; +import kr.co.fastcampus.yanabada.domain.notification.entity.NotificationHistory; +import kr.co.fastcampus.yanabada.domain.notification.entity.enums.NotificationType; +import lombok.Builder; + +@Builder +public record NotificationInfoResponse( + String senderNickname, + String accommodationName, + NotificationType type, + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + LocalDateTime registeredDate, + String image, + Boolean isRead +) { + + public static NotificationInfoResponse from( + String senderNickname, + String accommodationName, + NotificationHistory history + ) { + return NotificationInfoResponse.builder() + .senderNickname(senderNickname) + .accommodationName(accommodationName) + .type(history.getNotificationType()) + .registeredDate(history.getRegisteredDate()) + .image(history.getImage()) + .isRead(history.getIsRead()) + .build(); + } +} diff --git a/src/main/java/kr/co/fastcampus/yanabada/domain/notification/dto/response/NotificationPageResponse.java b/src/main/java/kr/co/fastcampus/yanabada/domain/notification/dto/response/NotificationPageResponse.java new file mode 100644 index 00000000..a4be8a6f --- /dev/null +++ b/src/main/java/kr/co/fastcampus/yanabada/domain/notification/dto/response/NotificationPageResponse.java @@ -0,0 +1,27 @@ +package kr.co.fastcampus.yanabada.domain.notification.dto.response; + +import java.util.List; +import lombok.Builder; +import org.springframework.data.domain.Page; + +@Builder +public record NotificationPageResponse( + List notifications, + int pageNum, + int pageSize, + int totalPages, + boolean isFirst, + boolean isLast +) { + + public static NotificationPageResponse from(Page responsePage) { + return NotificationPageResponse.builder() + .notifications(responsePage.getContent()) + .pageNum(responsePage.getNumber()) + .pageSize(responsePage.getSize()) + .totalPages(responsePage.getTotalPages()) + .isFirst(responsePage.isFirst()) + .isLast(responsePage.isLast()) + .build(); + } +} diff --git a/src/main/java/kr/co/fastcampus/yanabada/domain/notification/entity/NotificationHistory.java b/src/main/java/kr/co/fastcampus/yanabada/domain/notification/entity/NotificationHistory.java index 009ba890..887c20b6 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/domain/notification/entity/NotificationHistory.java +++ b/src/main/java/kr/co/fastcampus/yanabada/domain/notification/entity/NotificationHistory.java @@ -29,19 +29,29 @@ public class NotificationHistory extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "receiver_id") private Member receiver; + @Column(nullable = false) @Enumerated(EnumType.STRING) private NotificationType notificationType; + @Column(nullable = false) private String content; + @Column(nullable = false) private String image; + @Builder.Default - LocalDateTime registeredDate = LocalDateTime.now(); + private LocalDateTime registeredDate = LocalDateTime.now(); + @Builder.Default - private Boolean read = false; + private Boolean isRead = false; + + public void updateRead(boolean isRead) { + this.isRead = isRead; + } } diff --git a/src/main/java/kr/co/fastcampus/yanabada/domain/notification/repository/NotificationHistoryRepository.java b/src/main/java/kr/co/fastcampus/yanabada/domain/notification/repository/NotificationHistoryRepository.java index df9ef34a..75168d2d 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/domain/notification/repository/NotificationHistoryRepository.java +++ b/src/main/java/kr/co/fastcampus/yanabada/domain/notification/repository/NotificationHistoryRepository.java @@ -1,8 +1,12 @@ package kr.co.fastcampus.yanabada.domain.notification.repository; +import kr.co.fastcampus.yanabada.domain.member.entity.Member; import kr.co.fastcampus.yanabada.domain.notification.entity.NotificationHistory; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; public interface NotificationHistoryRepository extends JpaRepository { + Page findByReceiver(Member receiver, Pageable pageable); } diff --git a/src/main/java/kr/co/fastcampus/yanabada/domain/notification/service/NotificationService.java b/src/main/java/kr/co/fastcampus/yanabada/domain/notification/service/NotificationService.java index f762fa35..e16b4d86 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/domain/notification/service/NotificationService.java +++ b/src/main/java/kr/co/fastcampus/yanabada/domain/notification/service/NotificationService.java @@ -19,17 +19,25 @@ import static kr.co.fastcampus.yanabada.domain.notification.property.NotificationProperties.TRADE_REQUEST_CONTENT_POSTFIX; import static kr.co.fastcampus.yanabada.domain.notification.property.NotificationProperties.TRADE_REQUEST_TITLE; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import kr.co.fastcampus.yanabada.common.exception.JsonProcessFailedException; import kr.co.fastcampus.yanabada.common.firebase.dto.request.FcmMessageRequest.Data; import kr.co.fastcampus.yanabada.common.firebase.dto.request.FcmMessageRequest.Notification; import kr.co.fastcampus.yanabada.common.firebase.service.FcmService; import kr.co.fastcampus.yanabada.domain.member.entity.Member; +import kr.co.fastcampus.yanabada.domain.member.repository.MemberRepository; import kr.co.fastcampus.yanabada.domain.notification.dto.ChatNotificationDto; import kr.co.fastcampus.yanabada.domain.notification.dto.TradeNotificationDto; +import kr.co.fastcampus.yanabada.domain.notification.dto.response.NotificationInfoResponse; +import kr.co.fastcampus.yanabada.domain.notification.dto.response.NotificationPageResponse; import kr.co.fastcampus.yanabada.domain.notification.entity.NotificationHistory; import kr.co.fastcampus.yanabada.domain.notification.repository.NotificationHistoryRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -41,6 +49,7 @@ public class NotificationService { private final FcmService fcmService; private final NotificationHistoryRepository notificationHistoryRepository; private final ObjectMapper objectMapper; + private final MemberRepository memberRepository; @Transactional public void sendChatMessage(Member sender, Member receiver, String content) { @@ -75,24 +84,24 @@ public void sendChatCreated(ChatNotificationDto chatDto, String content) { } @Transactional - public void sendTradeRequest(TradeNotificationDto tradeApprovalDto) { + public void sendTradeRequest(TradeNotificationDto tradeNotificationDto) { Notification notification = Notification.builder() .title(TRADE_REQUEST_TITLE) .body( - getShortPhrase(tradeApprovalDto.accommodationName()) + getShortPhrase(tradeNotificationDto.accommodationName()) + TRADE_REQUEST_CONTENT_POSTFIX ) .build(); Data data = Data.builder().notificationType(TRADE_REQUEST.name()).build(); - fcmService.sendToMessage(tradeApprovalDto.receiver().getFcmToken(), notification, data); + fcmService.sendToMessage(tradeNotificationDto.receiver().getFcmToken(), notification, data); NotificationHistory notificationHistory = NotificationHistory.builder() - .receiver(tradeApprovalDto.receiver()) + .receiver(tradeNotificationDto.receiver()) .notificationType(TRADE_REQUEST) - .content(tradeApprovalDto.convertMapToJsonStr(objectMapper)) + .content(tradeNotificationDto.convertMapToJsonStr(objectMapper)) .image(TRADE_REQUEST.name().toLowerCase() + ".png") .build(); notificationHistoryRepository.save(notificationHistory); @@ -100,25 +109,25 @@ public void sendTradeRequest(TradeNotificationDto tradeApprovalDto) { } @Transactional - public void sendTradeCanceled(TradeNotificationDto tradeApprovalDto) { + public void sendTradeCanceled(TradeNotificationDto tradeNotificationDto) { Notification notification = Notification.builder() .title(TRADE_CANCELED_TITLE) .body( TRADE_CANCELED_CONTENT_PREFIX - + getShortPhrase(tradeApprovalDto.accommodationName()) + + getShortPhrase(tradeNotificationDto.accommodationName()) + TRADE_CANCELED_CONTENT_POSTFIX ) .build(); Data data = Data.builder().notificationType(TRADE_CANCELED.name()).build(); - fcmService.sendToMessage(tradeApprovalDto.receiver().getFcmToken(), notification, data); + fcmService.sendToMessage(tradeNotificationDto.receiver().getFcmToken(), notification, data); NotificationHistory notificationHistory = NotificationHistory.builder() - .receiver(tradeApprovalDto.receiver()) + .receiver(tradeNotificationDto.receiver()) .notificationType(TRADE_CANCELED) - .content(tradeApprovalDto.convertMapToJsonStr(objectMapper)) + .content(tradeNotificationDto.convertMapToJsonStr(objectMapper)) .image(TRADE_CANCELED.name().toLowerCase() + ".png") //todo: png 상수처리? .build(); notificationHistoryRepository.save(notificationHistory); @@ -126,24 +135,24 @@ public void sendTradeCanceled(TradeNotificationDto tradeApprovalDto) { } @Transactional - public void sendTradeApproval(TradeNotificationDto tradeApprovalDto) { + public void sendTradeApproval(TradeNotificationDto tradeNotificationDto) { Notification notification = Notification.builder() .title(TRADE_APPROVAL_TITLE) .body( - getShortPhrase(tradeApprovalDto.accommodationName()) + getShortPhrase(tradeNotificationDto.accommodationName()) + TRADE_APPROVAL_CONTENT_POSTFIX ) .build(); Data data = Data.builder().notificationType(TRADE_APPROVAL.name()).build(); - fcmService.sendToMessage(tradeApprovalDto.receiver().getFcmToken(), notification, data); + fcmService.sendToMessage(tradeNotificationDto.receiver().getFcmToken(), notification, data); NotificationHistory notificationHistory = NotificationHistory.builder() - .receiver(tradeApprovalDto.receiver()) + .receiver(tradeNotificationDto.receiver()) .notificationType(TRADE_APPROVAL) - .content(tradeApprovalDto.convertMapToJsonStr(objectMapper)) + .content(tradeNotificationDto.convertMapToJsonStr(objectMapper)) .image(TRADE_APPROVAL.name().toLowerCase() + ".png") .build(); notificationHistoryRepository.save(notificationHistory); @@ -151,24 +160,24 @@ public void sendTradeApproval(TradeNotificationDto tradeApprovalDto) { } @Transactional - public void sendTradeRejected(TradeNotificationDto tradeApprovalDto) { + public void sendTradeRejected(TradeNotificationDto tradeNotificationDto) { Notification notification = Notification.builder() .title(TRADE_REJECTED_TITLE) .body( - getShortPhrase(tradeApprovalDto.accommodationName()) + getShortPhrase(tradeNotificationDto.accommodationName()) + TRADE_REJECTED_CONTENT_POSTFIX ) .build(); Data data = Data.builder().notificationType(TRADE_REJECTED.name()).build(); - fcmService.sendToMessage(tradeApprovalDto.receiver().getFcmToken(), notification, data); + fcmService.sendToMessage(tradeNotificationDto.receiver().getFcmToken(), notification, data); NotificationHistory notificationHistory = NotificationHistory.builder() - .receiver(tradeApprovalDto.receiver()) + .receiver(tradeNotificationDto.receiver()) .notificationType(TRADE_REJECTED) - .content(tradeApprovalDto.convertMapToJsonStr(objectMapper)) + .content(tradeNotificationDto.convertMapToJsonStr(objectMapper)) .image(TRADE_REJECTED.name().toLowerCase() + ".png") .build(); notificationHistoryRepository.save(notificationHistory); @@ -181,4 +190,43 @@ private String getShortPhrase(String name) { } return name.substring(0, 7) + "..."; } + + @Transactional + public NotificationPageResponse getNotifications(Long memberId, Pageable pageable) { + Member member = memberRepository.getMember(memberId); + Page histories = + notificationHistoryRepository.findByReceiver(member, pageable); + Page responses = histories.map(history -> { + NotificationInfoResponse response; + if (history.getNotificationType().equals(CHAT)) { + String content = history.getContent(); + String senderNickname = convertJsonToString("senderNickname", content); + String accommodationName = convertJsonToString("accommodationName", content); + response = NotificationInfoResponse.from( + senderNickname, accommodationName, history + ); + + } else { + String content = history.getContent(); + String accommodationName = convertJsonToString("accommodationName", content); + response = NotificationInfoResponse.from( + null, accommodationName, history + ); + } + history.updateRead(true); + return response; + }); + + return NotificationPageResponse.from(responses); + + } + + private String convertJsonToString(String key, String content) { + try { + JsonNode node = objectMapper.readTree(content); + return node.get(key).asText(); + } catch (JsonProcessingException e) { + throw new JsonProcessFailedException(); + } + } } diff --git a/src/main/java/kr/co/fastcampus/yanabada/domain/order/controller/OrderController.java b/src/main/java/kr/co/fastcampus/yanabada/domain/order/controller/OrderController.java index b4ef094a..0168ed42 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/domain/order/controller/OrderController.java +++ b/src/main/java/kr/co/fastcampus/yanabada/domain/order/controller/OrderController.java @@ -2,24 +2,25 @@ import java.util.List; import kr.co.fastcampus.yanabada.common.response.ResponseBody; +import kr.co.fastcampus.yanabada.common.security.PrincipalDetails; import kr.co.fastcampus.yanabada.domain.order.dto.request.OrderSaveRequest; import kr.co.fastcampus.yanabada.domain.order.dto.response.OrderInfoResponse; import kr.co.fastcampus.yanabada.domain.order.dto.response.OrderSummaryResponse; import kr.co.fastcampus.yanabada.domain.order.service.OrderService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @Slf4j @RestController @RequiredArgsConstructor -@RequestMapping("orders") +@RequestMapping("/orders") public class OrderController { private final OrderService orderService; @@ -31,17 +32,19 @@ public ResponseBody addOrder(@RequestBody OrderSaveRequest request) { } @GetMapping("/can-sell") - public ResponseBody> getSellableOrders() { + public ResponseBody> getSellableOrders( + @AuthenticationPrincipal PrincipalDetails principalDetails + ) { return ResponseBody.ok( - orderService.getSellableOrders(1L) + orderService.getSellableOrders(principalDetails.id()) ); } @GetMapping("/{orderId}") public ResponseBody getOrderInfo( @PathVariable Long orderId, - @RequestParam Long currentUserId + @AuthenticationPrincipal PrincipalDetails principalDetails ) { - return ResponseBody.ok(orderService.getOrderInfo(orderId, currentUserId)); + return ResponseBody.ok(orderService.getOrderInfo(orderId, principalDetails.id())); } } diff --git a/src/main/java/kr/co/fastcampus/yanabada/domain/payment/controller/PaymentController.java b/src/main/java/kr/co/fastcampus/yanabada/domain/payment/controller/PaymentController.java index dff2ea1b..0b99f4c5 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/domain/payment/controller/PaymentController.java +++ b/src/main/java/kr/co/fastcampus/yanabada/domain/payment/controller/PaymentController.java @@ -2,6 +2,7 @@ import jakarta.validation.Valid; import kr.co.fastcampus.yanabada.common.response.ResponseBody; +import kr.co.fastcampus.yanabada.common.security.PrincipalDetails; import kr.co.fastcampus.yanabada.domain.payment.dto.request.YanoljaPayAmountRequest; import kr.co.fastcampus.yanabada.domain.payment.dto.request.YanoljaPayHistorySearchRequest; import kr.co.fastcampus.yanabada.domain.payment.dto.request.YanoljaPaySaveRequest; @@ -13,6 +14,7 @@ import kr.co.fastcampus.yanabada.domain.payment.dto.response.YanoljaPaySummaryResponse; import kr.co.fastcampus.yanabada.domain.payment.service.PaymentService; import lombok.RequiredArgsConstructor; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -28,48 +30,56 @@ public class PaymentController { private final PaymentService paymentService; @GetMapping("/summary") - public ResponseBody getYanoljaPaySummary() { - return ResponseBody.ok(paymentService.getYanoljaPaySummary(2L)); + public ResponseBody getYanoljaPaySummary( + @AuthenticationPrincipal PrincipalDetails principalDetails + ) { + return ResponseBody.ok(paymentService.getYanoljaPaySummary(principalDetails.id())); } @GetMapping - public ResponseBody getYanoljaPay() { - return ResponseBody.ok(paymentService.getYanoljaPay(2L)); + public ResponseBody getYanoljaPay( + @AuthenticationPrincipal PrincipalDetails principalDetails + ) { + return ResponseBody.ok(paymentService.getYanoljaPay(principalDetails.id())); } @PostMapping public ResponseBody saveYanoljaPay( + @AuthenticationPrincipal PrincipalDetails principalDetails, @RequestBody @Valid YanoljaPaySaveRequest request ) { - paymentService.saveYanoljaPay(2L, request); + paymentService.saveYanoljaPay(principalDetails.id(), request); return ResponseBody.ok(); } @PostMapping("/charge") public ResponseBody chargeYanoljaPay( + @AuthenticationPrincipal PrincipalDetails principalDetails, @RequestBody @Valid YanoljaPayAmountRequest request ) { return ResponseBody.ok( - paymentService.chargeYanoljaPay(2L, request) + paymentService.chargeYanoljaPay(principalDetails.id(), request) ); } @PostMapping("/disburse") public ResponseBody disburseYanoljaPay( + @AuthenticationPrincipal PrincipalDetails principalDetails, @RequestBody @Valid YanoljaPayAmountRequest request ) { return ResponseBody.ok( - paymentService.disburseYanoljaPay(2L, request) + paymentService.disburseYanoljaPay(principalDetails.id(), request) ); } @GetMapping("/histories") public ResponseBody getYanoljaPayHistories( + @AuthenticationPrincipal PrincipalDetails principalDetails, YanoljaPayHistorySearchRequest request ) { return ResponseBody.ok( paymentService.getYanoljaPayHistoriesBySearchRequest( - 2L, + principalDetails.id(), request ) ); @@ -77,11 +87,12 @@ public ResponseBody getYanoljaPayHistories @GetMapping("/histories/{historyId}") public ResponseBody getYanoljaPayHistory( + @AuthenticationPrincipal PrincipalDetails principalDetails, @PathVariable("historyId") Long historyId ) { return ResponseBody.ok( paymentService.getYanoljaPayHistory( - 2L, + principalDetails.id(), historyId ) ); diff --git a/src/main/java/kr/co/fastcampus/yanabada/domain/payment/controller/TradeController.java b/src/main/java/kr/co/fastcampus/yanabada/domain/payment/controller/TradeController.java index 5528725f..47766850 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/domain/payment/controller/TradeController.java +++ b/src/main/java/kr/co/fastcampus/yanabada/domain/payment/controller/TradeController.java @@ -1,6 +1,7 @@ package kr.co.fastcampus.yanabada.domain.payment.controller; import kr.co.fastcampus.yanabada.common.response.ResponseBody; +import kr.co.fastcampus.yanabada.common.security.PrincipalDetails; import kr.co.fastcampus.yanabada.domain.payment.dto.request.TradeSaveRequest; import kr.co.fastcampus.yanabada.domain.payment.dto.response.ApprovalTradeInfoResponse; import kr.co.fastcampus.yanabada.domain.payment.dto.response.ApprovalTradePageResponse; @@ -14,6 +15,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.web.PageableDefault; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -33,82 +35,91 @@ public class TradeController { @PostMapping public ResponseBody addTrade( + @AuthenticationPrincipal PrincipalDetails principalDetails, @RequestBody TradeSaveRequest request ) { return ResponseBody.ok( - tradeService.saveTrade(2L, request) + tradeService.saveTrade(principalDetails.id(), request) ); } @PostMapping("/{tradeId}/approve") public ResponseBody approveTrade( + @AuthenticationPrincipal PrincipalDetails principalDetails, @PathVariable("tradeId") Long tradeId ) { - tradeService.approveTrade(1L, tradeId); + tradeService.approveTrade(principalDetails.id(), tradeId); return ResponseBody.ok(); } @PostMapping("/{tradeId}/reject") public ResponseBody rejectTrade( + @AuthenticationPrincipal PrincipalDetails principalDetails, @PathVariable("tradeId") Long tradeId ) { - tradeService.rejectTrade(1L, tradeId); + tradeService.rejectTrade(principalDetails.id(), tradeId); return ResponseBody.ok(); } @PostMapping("/{tradeId}/cancel") public ResponseBody cancelTrade( + @AuthenticationPrincipal PrincipalDetails principalDetails, @PathVariable("tradeId") Long tradeId ) { - tradeService.cancelTrade(2L, tradeId); + tradeService.cancelTrade(principalDetails.id(), tradeId); return ResponseBody.ok(); } @GetMapping("/approvals/{tradeId}") public ResponseBody getApprovalTrade( + @AuthenticationPrincipal PrincipalDetails principalDetails, @PathVariable("tradeId") Long tradeId ) { return ResponseBody.ok( - tradeService.getApprovalTrade(1L, tradeId) + tradeService.getApprovalTrade(principalDetails.id(), tradeId) ); } @GetMapping("/approvals") public ResponseBody getApprovalTrades( + @AuthenticationPrincipal PrincipalDetails principalDetails, @RequestParam(name = "status", required = false) TradeStatus status, @PageableDefault(sort = "registeredDate", direction = Sort.Direction.DESC) Pageable pageable ) { return ResponseBody.ok( - tradeService.getApprovalTrades(1L, status, pageable) + tradeService.getApprovalTrades(principalDetails.id(), status, pageable) ); } @GetMapping("/purchases") public ResponseBody getPurchaseTrades( + @AuthenticationPrincipal PrincipalDetails principalDetails, @RequestParam(name = "status", required = false) TradeStatus status, @PageableDefault(sort = "registeredDate", direction = Sort.Direction.DESC) Pageable pageable ) { return ResponseBody.ok( - tradeService.getPurchaseTrades(2L, status, pageable) + tradeService.getPurchaseTrades(principalDetails.id(), status, pageable) ); } @GetMapping("/purchases/{tradeId}") public ResponseBody getPurchaseTrade( + @AuthenticationPrincipal PrincipalDetails principalDetails, @PathVariable("tradeId") Long tradeId ) { return ResponseBody.ok( - tradeService.getPurchaseTrade(2L, tradeId) + tradeService.getPurchaseTrade(principalDetails.id(), tradeId) ); } @DeleteMapping("/{tradeId}") public ResponseBody deleteTrade( + @AuthenticationPrincipal PrincipalDetails principalDetails, @PathVariable("tradeId") Long tradeId ) { - tradeService.deleteTrade(1L, tradeId); + tradeService.deleteTrade(principalDetails.id(), tradeId); return ResponseBody.ok(); } } diff --git a/src/main/java/kr/co/fastcampus/yanabada/domain/payment/service/TradeService.java b/src/main/java/kr/co/fastcampus/yanabada/domain/payment/service/TradeService.java index 0a0be201..6800c2cc 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/domain/payment/service/TradeService.java +++ b/src/main/java/kr/co/fastcampus/yanabada/domain/payment/service/TradeService.java @@ -27,6 +27,8 @@ import kr.co.fastcampus.yanabada.domain.accommodation.entity.Accommodation; import kr.co.fastcampus.yanabada.domain.member.entity.Member; import kr.co.fastcampus.yanabada.domain.member.repository.MemberRepository; +import kr.co.fastcampus.yanabada.domain.notification.dto.TradeNotificationDto; +import kr.co.fastcampus.yanabada.domain.notification.service.NotificationService; import kr.co.fastcampus.yanabada.domain.order.entity.Order; import kr.co.fastcampus.yanabada.domain.order.entity.enums.OrderStatus; import kr.co.fastcampus.yanabada.domain.order.entity.enums.PaymentType; @@ -69,6 +71,7 @@ public class TradeService { private final YanoljaPayRepository yanoljaPayRepository; private final YanoljaPayHistoryRepository yanoljaPayHistoryRepository; private final AdminPaymentRepository adminPaymentRepository; + private final NotificationService notificationService; @Transactional public TradeIdResponse saveTrade( @@ -91,7 +94,12 @@ public TradeIdResponse saveTrade( product.book(); - //TODO: Seller에게 알림 + notificationService.sendTradeRequest( + TradeNotificationDto.from( + seller, + product.getOrder().getRoom().getAccommodation().getName() + ) + ); return TradeIdResponse.from( tradeRepository.save(request.toEntity(product, seller, buyer)) @@ -117,7 +125,12 @@ public void approveTrade(Long sellerId, Long tradeId) { trade.getProduct().getOrder().trade(); orderRepository.save(createOrderFromTrade(trade)); - //TODO: Buyer에게 알림 + notificationService.sendTradeApproval( + TradeNotificationDto.from( + trade.getBuyer(), + trade.getProduct().getOrder().getRoom().getAccommodation().getName() + ) + ); } @Transactional @@ -135,7 +148,12 @@ public void rejectTrade(Long sellerId, Long tradeId) { trade.reject(); trade.getProduct().onSale(); - //TODO: Buyer에게 알림(Optional) + notificationService.sendTradeRejected( + TradeNotificationDto.from( + trade.getBuyer(), + trade.getProduct().getOrder().getRoom().getAccommodation().getName() + ) + ); } @Transactional @@ -153,7 +171,12 @@ public void cancelTrade(Long buyerId, Long tradeId) { trade.cancel(); trade.getProduct().onSale(); - //TODO: Seller에게 알림(Optional) + notificationService.sendTradeCanceled( + TradeNotificationDto.from( + trade.getSeller(), + trade.getProduct().getOrder().getRoom().getAccommodation().getName() + ) + ); } @Transactional(readOnly = true) diff --git a/src/main/java/kr/co/fastcampus/yanabada/domain/product/service/ProductService.java b/src/main/java/kr/co/fastcampus/yanabada/domain/product/service/ProductService.java index 1e557feb..1467bec6 100644 --- a/src/main/java/kr/co/fastcampus/yanabada/domain/product/service/ProductService.java +++ b/src/main/java/kr/co/fastcampus/yanabada/domain/product/service/ProductService.java @@ -26,6 +26,8 @@ import kr.co.fastcampus.yanabada.common.exception.UnavailableStatusQueryException; import kr.co.fastcampus.yanabada.domain.member.entity.Member; import kr.co.fastcampus.yanabada.domain.member.repository.MemberRepository; +import kr.co.fastcampus.yanabada.domain.notification.dto.TradeNotificationDto; +import kr.co.fastcampus.yanabada.domain.notification.service.NotificationService; import kr.co.fastcampus.yanabada.domain.order.entity.Order; import kr.co.fastcampus.yanabada.domain.order.entity.enums.OrderStatus; import kr.co.fastcampus.yanabada.domain.order.entity.enums.PaymentType; @@ -70,6 +72,7 @@ public class ProductService { private final YanoljaPayRepository yanoljaPayRepository; private final YanoljaPayHistoryRepository yanoljaPayHistoryRepository; private final AdminPaymentRepository adminPaymentRepository; + private final NotificationService notificationService; @Transactional public ProductIdResponse saveProduct( @@ -154,7 +157,7 @@ public void cancelProduct( validateProductCancelRequest(member, product); - cancelTradeRelatedToProduct(product); + rejectTradeRelatedToProduct(product); product.cancel(); } @@ -167,13 +170,13 @@ public void expireProducts() { if (product.getIsAutoCancel()) { product.getOrder().cancel(); } - cancelTradeRelatedToProduct(product); + rejectTradeRelatedToProduct(product); product.expire(); } ); } - private void cancelTradeRelatedToProduct(Product product) { + private void rejectTradeRelatedToProduct(Product product) { AdminPayment adminPayment = adminPaymentRepository.getAdminPayment(); tradeRepository.findByProduct(product) @@ -185,7 +188,13 @@ private void cancelTradeRelatedToProduct(Product product) { adminPayment.withdraw(bill); trade.reject(); - //TODO: Buyer에게 알림 (Optional) + + notificationService.sendTradeRejected( + TradeNotificationDto.from( + trade.getBuyer(), + trade.getProduct().getOrder().getRoom().getAccommodation().getName() + ) + ); } }); } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index c74bc014..33f452c1 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -40,6 +40,11 @@ spring: host: 127.0.0.1 port: 6379 + login: + oauth2-password: oauth2-password + oauth2-redirect-url: /redirect_url + root-url: http://localhost:8080 + jwt: secretKey: yanabadaSecretKeyyanabadaSecretKeyyanabadaSecretKey