diff --git a/src/main/java/com/jangburich/domain/order/application/OrderService.java b/src/main/java/com/jangburich/domain/order/application/OrderService.java index b22a421..8e9a5a8 100644 --- a/src/main/java/com/jangburich/domain/order/application/OrderService.java +++ b/src/main/java/com/jangburich/domain/order/application/OrderService.java @@ -45,7 +45,7 @@ public Message addCart(String userProviderId, AddCartRequest addCartRequest) { .orElseThrow(() -> new NullPointerException()); Menu menu = menuRepository.findById(addCartRequest.menuId()) - .orElseThrow(() -> new IllegalArgumentException("등록된 메뉴를 찾을 수 없습니다.")); + .orElseThrow(() -> new IllegalArgumentException("등록된 메뉴를 찾을 수 없습니다. ")); System.out.println("menu.getId() = " + menu.getId()); System.out.println("user.getUserId() = " + user.getUserId()); diff --git a/src/main/java/com/jangburich/domain/store/domain/Store.java b/src/main/java/com/jangburich/domain/store/domain/Store.java index 9f57826..0bf97ae 100644 --- a/src/main/java/com/jangburich/domain/store/domain/Store.java +++ b/src/main/java/com/jangburich/domain/store/domain/Store.java @@ -115,6 +115,10 @@ public static Store of(Owner owner, StoreCreateRequestDTO storeCreateRequestDTO) newStore.setOpenTime(storeCreateRequestDTO.getOpenTime()); newStore.setCloseTime(storeCreateRequestDTO.getCloseTime()); newStore.setContactNumber(storeCreateRequestDTO.getContactNumber()); + newStore.setReservationAvailable(storeCreateRequestDTO.getReservationAvailable()); + newStore.setMaxReservation(storeCreateRequestDTO.getMaxReservation()); + newStore.setMinPrepayment(storeCreateRequestDTO.getMinPrepayment()); + newStore.setPrepaymentDuration(storeCreateRequestDTO.getPrepaymentDuration()); return newStore; } } diff --git a/src/main/java/com/jangburich/domain/store/domain/StoreCreateRequestDTO.java b/src/main/java/com/jangburich/domain/store/domain/StoreCreateRequestDTO.java index 0ff8a97..de78afb 100644 --- a/src/main/java/com/jangburich/domain/store/domain/StoreCreateRequestDTO.java +++ b/src/main/java/com/jangburich/domain/store/domain/StoreCreateRequestDTO.java @@ -4,6 +4,8 @@ import java.time.LocalTime; import java.util.List; +import com.jangburich.domain.menu.domain.MenuCreateRequestDTO; + import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; import lombok.Getter; @@ -34,4 +36,11 @@ public class StoreCreateRequestDTO { private List dayOfWeek; private LocalTime openTime; private LocalTime closeTime; + + private Boolean reservationAvailable; + private Long maxReservation; + private Long minPrepayment; + private Long prepaymentDuration; + + private List menuCreateRequestDTOS; } diff --git a/src/main/java/com/jangburich/domain/store/domain/controller/StoreController.java b/src/main/java/com/jangburich/domain/store/domain/controller/StoreController.java index e8da9bf..4413a9d 100644 --- a/src/main/java/com/jangburich/domain/store/domain/controller/StoreController.java +++ b/src/main/java/com/jangburich/domain/store/domain/controller/StoreController.java @@ -71,16 +71,6 @@ public ResponseCustom createStore( return ResponseCustom.OK(Message.builder().message("success").build()); } - @Operation(summary = "가게 추가정보 저장", description = "예약 가능 여부, 최소 선결제 금액, 선결제 사용 기간을 저장합니다.") - @PostMapping("/create/additionalInfo") - public ResponseCustom createAdditionalInfo( - Authentication authentication, - @RequestBody StoreAdditionalInfoCreateRequestDTO storeAdditionalInfoCreateRequestDTO) { - storeService.createAdditionalInfo(AuthenticationParser.parseUserId(authentication), - storeAdditionalInfoCreateRequestDTO); - return ResponseCustom.OK(Message.builder().message("success").build()); - } - @Operation(summary = "가게 정보 수정", description = "가게 정보를 수정합니다.") @PatchMapping("/update") public ResponseCustom updateStore( diff --git a/src/main/java/com/jangburich/domain/store/domain/service/StoreService.java b/src/main/java/com/jangburich/domain/store/domain/service/StoreService.java index 0589a00..2738656 100644 --- a/src/main/java/com/jangburich/domain/store/domain/service/StoreService.java +++ b/src/main/java/com/jangburich/domain/store/domain/service/StoreService.java @@ -5,6 +5,9 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import com.jangburich.domain.menu.domain.Menu; +import com.jangburich.domain.menu.domain.MenuCreateRequestDTO; +import com.jangburich.domain.menu.domain.repository.MenuRepository; import com.jangburich.domain.owner.domain.Owner; import com.jangburich.domain.owner.domain.repository.OwnerRepository; import com.jangburich.domain.payment.domain.TeamChargeHistoryResponse; @@ -43,6 +46,7 @@ public class StoreService { private final StoreTeamRepository storeTeamRepository; private final TeamRepository teamRepository; private final TeamChargeHistoryRepository teamChargeHistoryRepository; + private final MenuRepository menuRepository; @Transactional public void createStore(String authentication, StoreCreateRequestDTO storeCreateRequestDTO) { @@ -52,7 +56,12 @@ public void createStore(String authentication, StoreCreateRequestDTO storeCreate Owner owner = ownerRepository.findByUser(user) .orElseThrow(() -> new DefaultNullPointerException(ErrorCode.INVALID_AUTHENTICATION)); - storeRepository.save(Store.of(owner, storeCreateRequestDTO)); + Store store = storeRepository.save(Store.of(owner, storeCreateRequestDTO)); + + for (MenuCreateRequestDTO menuCreateRequestDTO : storeCreateRequestDTO.getMenuCreateRequestDTOS()) { + menuRepository.save(Menu.create(menuCreateRequestDTO.getName(), menuCreateRequestDTO.getDescription(), + menuCreateRequestDTO.getImage_url(), menuCreateRequestDTO.getPrice(), store)); + } } @Transactional diff --git a/src/main/java/com/jangburich/domain/user/controller/UserController.java b/src/main/java/com/jangburich/domain/user/controller/UserController.java index 25798c3..cbff6cf 100644 --- a/src/main/java/com/jangburich/domain/user/controller/UserController.java +++ b/src/main/java/com/jangburich/domain/user/controller/UserController.java @@ -12,17 +12,21 @@ import org.springframework.util.MultiValueMap; import org.springframework.web.bind.annotation.GetMapping; 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; import org.springframework.web.client.RestTemplate; +import com.jangburich.domain.user.domain.AdditionalInfoCreateDTO; import com.jangburich.domain.user.domain.KakaoApiResponseDTO; import com.jangburich.domain.user.domain.TokenResponseDTO; import com.jangburich.domain.user.service.UserService; +import com.jangburich.global.payload.Message; import com.jangburich.global.payload.ResponseCustom; import com.jangburich.utils.parser.AuthenticationParser; +import io.swagger.v3.oas.annotations.Operation; import lombok.RequiredArgsConstructor; @RestController @@ -33,29 +37,25 @@ public class UserController { private final UserService userService; @PostMapping("/login") - public ResponseCustom login( - @RequestParam String authorizationHeader) { + public ResponseCustom login(@RequestParam String authorizationHeader) { TokenResponseDTO login = userService.login(authorizationHeader); return ResponseCustom.OK(login); } @GetMapping("/user-info") - public ResponseEntity getUserInfo( - Authentication authentication) { + public ResponseEntity getUserInfo(Authentication authentication) { KakaoApiResponseDTO userInfo = userService.getUserInfo(AuthenticationParser.parseUserId(authentication)); return ResponseEntity.ok(userInfo); } @PostMapping("/join/user") - public ResponseCustom joinUser( - @RequestParam String authorizationHeader) { + public ResponseCustom joinUser(@RequestParam String authorizationHeader) { return ResponseCustom.OK(userService.joinUser(authorizationHeader)); } @PostMapping("/join/owner") - public ResponseCustom joinOwner( - @RequestParam String authorizationHeader) { + public ResponseCustom joinOwner(@RequestParam String authorizationHeader) { return ResponseCustom.OK(userService.joinOwner(authorizationHeader)); } @@ -91,4 +91,12 @@ public ResponseEntity> getAccessToken(@RequestParam("code") return ResponseEntity.ok(response.getBody()); } + @Operation(summary = "유저 추가정보 저장", description = "유저 추가정보 저장합니다.") + @PostMapping("/additionalInfo") + public ResponseCustom saveAdditionalInfo(Authentication authentication, + @RequestBody AdditionalInfoCreateDTO additionalInfoCreateDTO) { + userService.additionalInfo(AuthenticationParser.parseUserId(authentication), additionalInfoCreateDTO); + return ResponseCustom.OK(Message.builder().message("success").build()); + } + } diff --git a/src/main/java/com/jangburich/domain/user/domain/AdditionalInfoCreateDTO.java b/src/main/java/com/jangburich/domain/user/domain/AdditionalInfoCreateDTO.java new file mode 100644 index 0000000..60017c1 --- /dev/null +++ b/src/main/java/com/jangburich/domain/user/domain/AdditionalInfoCreateDTO.java @@ -0,0 +1,13 @@ +package com.jangburich.domain.user.domain; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public class AdditionalInfoCreateDTO { + private String name; + private String phoneNum; + private Boolean agreeMarketing; + private Boolean agreeAdvertisement; +} diff --git a/src/main/java/com/jangburich/domain/user/domain/User.java b/src/main/java/com/jangburich/domain/user/domain/User.java index 8a39769..3ccfa44 100644 --- a/src/main/java/com/jangburich/domain/user/domain/User.java +++ b/src/main/java/com/jangburich/domain/user/domain/User.java @@ -38,6 +38,9 @@ public class User extends BaseEntity { @Column(name = "nickname", nullable = false, unique = true) private String nickname; + @Column(name = "name") + private String name; + @Column(name = "profile_image_url") private String profileImageUrl; @@ -50,6 +53,12 @@ public class User extends BaseEntity { @Column(name = "refresh_token") private String refreshToken; + @Column(name = "agree_marketing") + private Boolean agreeMarketing; + + @Column(name = "agree_advertisement") + private Boolean agreeAdvertisement; + public void updateRefreshToken(String refreshToken) { this.refreshToken = refreshToken; } diff --git a/src/main/java/com/jangburich/domain/user/service/UserService.java b/src/main/java/com/jangburich/domain/user/service/UserService.java index 2ff94f2..6259e6f 100644 --- a/src/main/java/com/jangburich/domain/user/service/UserService.java +++ b/src/main/java/com/jangburich/domain/user/service/UserService.java @@ -13,10 +13,13 @@ import com.jangburich.domain.owner.domain.repository.OwnerRepository; import com.jangburich.domain.store.domain.Store; import com.jangburich.domain.store.domain.repository.StoreRepository; +import com.jangburich.domain.user.domain.AdditionalInfoCreateDTO; import com.jangburich.domain.user.domain.KakaoApiResponseDTO; import com.jangburich.domain.user.domain.TokenResponseDTO; import com.jangburich.domain.user.domain.User; import com.jangburich.domain.user.repository.UserRepository; +import com.jangburich.global.error.DefaultNullPointerException; +import com.jangburich.global.payload.ErrorCode; import com.jangburich.utils.JwtUtil; import lombok.RequiredArgsConstructor; @@ -81,9 +84,8 @@ public TokenResponseDTO joinOwner(String kakaoAccessToken) { User user = userRepository.findByProviderId("kakao_" + userInfo.getId()).orElse(null); if (user == null) { - user = userRepository.save( - User.create("kakao_" + userInfo.getId(), userInfo.getProperties().getNickname(), - userInfo.getKakaoAccount().getEmail(), userInfo.getProperties().getProfileImage(), "ROLE_OWNER")); + user = userRepository.save(User.create("kakao_" + userInfo.getId(), userInfo.getProperties().getNickname(), + userInfo.getKakaoAccount().getEmail(), userInfo.getProperties().getProfileImage(), "ROLE_OWNER")); Owner newOwner = ownerRepository.save(Owner.create(user)); storeRepository.save(Store.create(newOwner)); } @@ -137,4 +139,15 @@ public String reissueAccessToken(String refreshToken) { return jwtUtil.createAccessToken(user.getProviderId(), user.getRole()); } + @Transactional + public void additionalInfo(String userId, AdditionalInfoCreateDTO additionalInfoCreateDTO) { + User user = userRepository.findByProviderId(userId) + .orElseThrow(() -> new DefaultNullPointerException(ErrorCode.INVALID_AUTHENTICATION)); + + user.setName(additionalInfoCreateDTO.getName()); + user.setPhoneNumber(additionalInfoCreateDTO.getPhoneNum()); + user.setAgreeAdvertisement(additionalInfoCreateDTO.getAgreeAdvertisement()); + user.setAgreeMarketing(additionalInfoCreateDTO.getAgreeMarketing()); + } + } diff --git a/src/main/java/com/jangburich/global/config/security/SecurityConfig.java b/src/main/java/com/jangburich/global/config/security/SecurityConfig.java index 7909177..8d11979 100644 --- a/src/main/java/com/jangburich/global/config/security/SecurityConfig.java +++ b/src/main/java/com/jangburich/global/config/security/SecurityConfig.java @@ -19,7 +19,7 @@ @EnableWebSecurity public class SecurityConfig { - private final JwtUtil jwtUtil; + private final JwtFilter jwtFilter; @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { @@ -27,7 +27,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .httpBasic(AbstractHttpConfigurer::disable) .formLogin(AbstractHttpConfigurer::disable) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) - .addFilterBefore(new JwtFilter(jwtUtil), UsernamePasswordAuthenticationFilter.class) + .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class) .authorizeHttpRequests( request -> request.requestMatchers("/**", "/oauth2/**", "/login/**", "/swagger-ui/**", diff --git a/src/main/java/com/jangburich/utils/JwtFilter.java b/src/main/java/com/jangburich/utils/JwtFilter.java index 0be7452..9b339a1 100644 --- a/src/main/java/com/jangburich/utils/JwtFilter.java +++ b/src/main/java/com/jangburich/utils/JwtFilter.java @@ -2,9 +2,11 @@ import java.io.IOException; +import org.springframework.beans.factory.annotation.Value; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import com.jangburich.domain.oauth.domain.CustomOAuthUser; @@ -18,8 +20,15 @@ import lombok.extern.slf4j.Slf4j; @Slf4j +@Component public class JwtFilter extends OncePerRequestFilter { + @Value("${test.jwt.permanentUserToken}") + private String permanentUserToken; + + @Value("${test.jwt.permanentOwnerToken}") + private String permanentOwnerToken; + private final JwtUtil jwtUtil; public JwtFilter(JwtUtil jwtUtil) { @@ -29,7 +38,6 @@ public JwtFilter(JwtUtil jwtUtil) { @Override protected void doFilterInternal(HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull FilterChain filterChain) throws ServletException, IOException { - // Authorization 헤더를 찾음 String authorizationHeader = request.getHeader("Authorization"); if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) { @@ -37,35 +45,43 @@ protected void doFilterInternal(HttpServletRequest request, @NonNull HttpServlet return; } - // "Bearer " 이후의 토큰 부분만 추출 - String token = authorizationHeader.substring(7); + String token = authorizationHeader.substring(7); // "Bearer " 이후의 토큰 추출 try { - // 토큰 소멸 시간 검증 + if (token.equals(permanentUserToken)) { + log.info("Permanent user token detected. Skipping validation."); + setPermanentAuthentication("test-user", "ROLE_USER"); + filterChain.doFilter(request, response); + return; + } + + if (token.equals(permanentOwnerToken)) { + log.info("Permanent owner token detected. Skipping validation."); + setPermanentAuthentication("test-owner", "ROLE_OWNER"); + filterChain.doFilter(request, response); + return; + } + + // 일반 토큰 처리 if (jwtUtil.isTokenExpired(token)) { filterChain.doFilter(request, response); return; } - // 토큰에서 사용자 정보 획득 String userId = jwtUtil.getUserId(token); String role = jwtUtil.getRole(token); - // OAuth2UserDTO 생성 및 설정 OAuthUserDTO userDTO = new OAuthUserDTO(); userDTO.setUserId(userId); userDTO.setRole(role); - // CustomOAuth2User 생성 CustomOAuthUser customOAuth2User = new CustomOAuthUser(userDTO); - // 스프링 시큐리티 인증 토큰 생성 및 설정 Authentication authToken = new UsernamePasswordAuthenticationToken(customOAuth2User, null, customOAuth2User.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(authToken); } catch (Exception e) { - // 예외 발생 시 로그 출력 및 인증 정보 제거 SecurityContextHolder.clearContext(); response.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage()); return; @@ -74,4 +90,16 @@ protected void doFilterInternal(HttpServletRequest request, @NonNull HttpServlet filterChain.doFilter(request, response); } -} \ No newline at end of file + private void setPermanentAuthentication(String userId, String role) { + OAuthUserDTO userDTO = new OAuthUserDTO(); + userDTO.setUserId(userId); + userDTO.setRole(role); + + CustomOAuthUser customOAuth2User = new CustomOAuthUser(userDTO); + + Authentication authToken = new UsernamePasswordAuthenticationToken(customOAuth2User, null, + customOAuth2User.getAuthorities()); + SecurityContextHolder.getContext().setAuthentication(authToken); + } + +}