diff --git a/src/main/java/kuit3/backend/common/argument_resolver/JwtAuthHandlerArgumentResolver.java b/src/main/java/kuit3/backend/common/argument_resolver/JwtAuthHandlerArgumentResolver.java index 474afa1..52bd715 100644 --- a/src/main/java/kuit3/backend/common/argument_resolver/JwtAuthHandlerArgumentResolver.java +++ b/src/main/java/kuit3/backend/common/argument_resolver/JwtAuthHandlerArgumentResolver.java @@ -1,6 +1,9 @@ package kuit3.backend.common.argument_resolver; import jakarta.servlet.http.HttpServletRequest; +import kuit3.backend.jwt.JwtUtil; +import kuit3.backend.service.AuthService; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.core.MethodParameter; import org.springframework.security.access.prepost.PreAuthorize; @@ -12,10 +15,13 @@ @Slf4j @Component +@RequiredArgsConstructor public class JwtAuthHandlerArgumentResolver implements HandlerMethodArgumentResolver { + private final JwtUtil jwtTokenUtil; + private final AuthService authService; @Override public boolean supportsParameter(MethodParameter parameter) { - boolean hasAnnotation = parameter.hasParameterAnnotation(PreAuthorize.class); + boolean hasAnnotation = parameter.hasParameterAnnotation(JwtAuthrize.class); boolean hasType = long.class.isAssignableFrom(parameter.getParameterType()); log.info("hasAnnotation={}, hasType={}, hasAnnotation && hasType={}", hasAnnotation, hasType, hasAnnotation&&hasType); return hasAnnotation && hasType; @@ -25,6 +31,16 @@ public boolean supportsParameter(MethodParameter parameter) { public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest(); log.info("userId={}", request.getAttribute("userId")); - return request.getAttribute("userId"); + + String accessToken = jwtTokenUtil.resolveAccessToken(request); + jwtTokenUtil.validateAccessToken(accessToken); + String email = jwtTokenUtil.getEmail(accessToken); + jwtTokenUtil.validatePayload(email); + long userId = authService.getUserIdByEmail(email); + + // HttpServletRequest에 userId 속성 설정 + //HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest(); + request.setAttribute("userId", userId); + return userId; } } \ No newline at end of file diff --git a/src/main/java/kuit3/backend/common/argument_resolver/JwtAuthrize.java b/src/main/java/kuit3/backend/common/argument_resolver/JwtAuthrize.java new file mode 100644 index 0000000..f0e6d05 --- /dev/null +++ b/src/main/java/kuit3/backend/common/argument_resolver/JwtAuthrize.java @@ -0,0 +1,11 @@ +package kuit3.backend.common.argument_resolver; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +public @interface JwtAuthrize { +} diff --git a/src/main/java/kuit3/backend/common/exception/ShopException.java b/src/main/java/kuit3/backend/common/exception/ShopException.java new file mode 100644 index 0000000..9d56aab --- /dev/null +++ b/src/main/java/kuit3/backend/common/exception/ShopException.java @@ -0,0 +1,22 @@ +package kuit3.backend.common.exception; + + +import kuit3.backend.common.response.status.ResponseStatus; +import lombok.Getter; + +@Getter +public class ShopException extends RuntimeException { + + private final ResponseStatus exceptionStatus; + + public ShopException(ResponseStatus exceptionStatus) { + super(exceptionStatus.getMessage()); + this.exceptionStatus = exceptionStatus; + } + + public ShopException(ResponseStatus exceptionStatus, String message) { + super(message); + this.exceptionStatus = exceptionStatus; + } + +} diff --git a/src/main/java/kuit3/backend/common/interceptor/JwtAuthInterceptor.java b/src/main/java/kuit3/backend/common/interceptor/JwtAuthInterceptor.java index 3196eaf..d1530b1 100644 --- a/src/main/java/kuit3/backend/common/interceptor/JwtAuthInterceptor.java +++ b/src/main/java/kuit3/backend/common/interceptor/JwtAuthInterceptor.java @@ -7,6 +7,7 @@ import kuit3.backend.common.exception.jwt.bad_request.JwtNoTokenException; import kuit3.backend.common.exception.jwt.bad_request.JwtUnsupportedTokenException; import kuit3.backend.jwt.JwtProvider; +import kuit3.backend.jwt.JwtUtil; import kuit3.backend.service.AuthService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -24,47 +25,48 @@ public class JwtAuthInterceptor implements HandlerInterceptor { private static final String JWT_TOKEN_PREFIX = "Bearer "; private final JwtProvider jwtProvider; + private final JwtUtil jwtUtil; private final AuthService authService; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { - String accessToken = resolveAccessToken(request); - validateAccessToken(accessToken); + String accessToken = jwtUtil.resolveAccessToken(request); + jwtUtil.validateAccessToken(accessToken); String email = jwtProvider.getPrincipal(accessToken); - validatePayload(email); + jwtUtil.validatePayload(email); long userId = authService.getUserIdByEmail(email); request.setAttribute("userId", userId); return true; } - private String resolveAccessToken(HttpServletRequest request) { - String token = request.getHeader(HttpHeaders.AUTHORIZATION); - validateToken(token); - return token.substring(JWT_TOKEN_PREFIX.length()); - } - - private void validateToken(String token) { - if (token == null) { - throw new JwtNoTokenException(TOKEN_NOT_FOUND); - } - if (!token.startsWith(JWT_TOKEN_PREFIX)) { - throw new JwtUnsupportedTokenException(UNSUPPORTED_TOKEN_TYPE); - } - } - - private void validateAccessToken(String accessToken) { - if (jwtProvider.isExpiredToken(accessToken)) { - throw new JwtExpiredTokenException(EXPIRED_TOKEN); - } - } - - private void validatePayload(String email) { - if (email == null) { - throw new JwtInvalidTokenException(INVALID_TOKEN); - } - } +// private String resolveAccessToken(HttpServletRequest request) { +// String token = request.getHeader(HttpHeaders.AUTHORIZATION); +// validateToken(token); +// return token.substring(JWT_TOKEN_PREFIX.length()); +// } +// +// private void validateToken(String token) { +// if (token == null) { +// throw new JwtNoTokenException(TOKEN_NOT_FOUND); +// } +// if (!token.startsWith(JWT_TOKEN_PREFIX)) { +// throw new JwtUnsupportedTokenException(UNSUPPORTED_TOKEN_TYPE); +// } +// } +// +// private void validateAccessToken(String accessToken) { +// if (jwtProvider.isExpiredToken(accessToken)) { +// throw new JwtExpiredTokenException(EXPIRED_TOKEN); +// } +// } +// +// private void validatePayload(String email) { +// if (email == null) { +// throw new JwtInvalidTokenException(INVALID_TOKEN); +// } +// } } \ No newline at end of file diff --git a/src/main/java/kuit3/backend/common/response/status/BaseExceptionResponseStatus.java b/src/main/java/kuit3/backend/common/response/status/BaseExceptionResponseStatus.java index 3354ad9..95bc065 100644 --- a/src/main/java/kuit3/backend/common/response/status/BaseExceptionResponseStatus.java +++ b/src/main/java/kuit3/backend/common/response/status/BaseExceptionResponseStatus.java @@ -45,8 +45,15 @@ public enum BaseExceptionResponseStatus implements ResponseStatus { USER_NOT_FOUND(4003, HttpStatus.BAD_REQUEST.value(), "존재하지 않는 회원입니다."), PASSWORD_NO_MATCH(4004, HttpStatus.BAD_REQUEST.value(), "비밀번호가 일치하지 않습니다."), INVALID_USER_STATUS(4005, HttpStatus.BAD_REQUEST.value(), "잘못된 회원 status 값입니다."), - EMAIL_NOT_FOUND(4006, HttpStatus.BAD_REQUEST.value(), "존재하지 않는 이메일입니다."); - + EMAIL_NOT_FOUND(4006, HttpStatus.BAD_REQUEST.value(), "존재하지 않는 이메일입니다."), + DUPLICATE_SHOP_NAME(4007,HttpStatus.BAD_REQUEST.value(),"이미 존재하는 가게 이름 입니다."), + FOODCATEGORY_NOT_MATCH(4008,HttpStatus.BAD_REQUEST.value(),"없는 카테고리 입니다."), + //WISH_LIST_INVALID(4009,HttpStatus.BAD_REQUEST.value(),"찜 목록 "), + INVALID_SHOP_VALUE(5000, HttpStatus.BAD_REQUEST.value(), "가게 등록 요청에서 잘못된 값이 존재합니다."), + INVALID_USER_ID(4009, HttpStatus.BAD_REQUEST.value(), "유효하지 않은 사용자 Id입니다"), + INVALID_SHOP_ID(4010, HttpStatus.BAD_REQUEST.value(), "유효하지 않는 가게 Id입니다."), + DUPLICATED_USER_ADDRESS(4011, HttpStatus.BAD_REQUEST.value(), "이미 존재하는 주소 입니다"), + INVALID_ADDRESS_INPUT(4010, HttpStatus.BAD_REQUEST.value(), "유효하지 않는 가게 Id입니다."),; private final int code; private final int status; private final String message; diff --git a/src/main/java/kuit3/backend/config/WebConfig.java b/src/main/java/kuit3/backend/config/WebConfig.java index 2f5ebf4..a0852af 100644 --- a/src/main/java/kuit3/backend/config/WebConfig.java +++ b/src/main/java/kuit3/backend/config/WebConfig.java @@ -21,7 +21,10 @@ public class WebConfig implements WebMvcConfigurer { public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(jwtAuthenticationInterceptor) .order(1) - .addPathPatterns("/auth/test"); + //.addPathPatterns("/auth/test") + .addPathPatterns("/auth/user-info") + .addPathPatterns("/users/**") + .excludePathPatterns("/users"); } @Override diff --git a/src/main/java/kuit3/backend/controller/AuthController.java b/src/main/java/kuit3/backend/controller/AuthController.java index 8d480ce..e68799f 100644 --- a/src/main/java/kuit3/backend/controller/AuthController.java +++ b/src/main/java/kuit3/backend/controller/AuthController.java @@ -1,5 +1,6 @@ package kuit3.backend.controller; +import kuit3.backend.common.argument_resolver.JwtAuthrize; import kuit3.backend.common.argument_resolver.PreAuthorize; import kuit3.backend.common.exception.UserException; import kuit3.backend.common.response.BaseResponse; @@ -41,5 +42,17 @@ public BaseResponse login(@Validated @RequestBody LoginRequest au public BaseResponse checkAuthorization(@PreAuthorize Long userId) { return new BaseResponse<>("userId=" + userId); } + @GetMapping("/test-jwt") + public BaseResponse checkJwtAuthorization(@JwtAuthrize long userId) { + return new BaseResponse<>("userId=" + userId); + } + @GetMapping("/user-info") + public BaseResponse getUserInfo(@RequestAttribute("userId") Long userId) { + // userId를 이용하여 비즈니스 로직 수행 + // 예: 사용자 정보를 데이터베이스에서 조회 + //authService.findUserById(userId); + + return new BaseResponse<>("userId=" + userId); + } } \ No newline at end of file diff --git a/src/main/java/kuit3/backend/controller/ShopController.java b/src/main/java/kuit3/backend/controller/ShopController.java new file mode 100644 index 0000000..fb9dd5f --- /dev/null +++ b/src/main/java/kuit3/backend/controller/ShopController.java @@ -0,0 +1,77 @@ +package kuit3.backend.controller; + + +import com.fasterxml.jackson.databind.annotation.JsonValueInstantiator; +import kuit3.backend.common.exception.ShopException; +import kuit3.backend.common.response.BaseResponse; +import kuit3.backend.dto.shop.*; +import kuit3.backend.service.ShopService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.validator.constraints.Range; +import org.springframework.validation.BindingResult; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static kuit3.backend.common.response.status.BaseExceptionResponseStatus.INVALID_SHOP_VALUE; +import static kuit3.backend.util.BindingResultUtils.getErrorMessages; + +@Slf4j +@RestController +@RequiredArgsConstructor +@RequestMapping("/shop") +public class ShopController { + private final ShopService shopService; + + /** + * shop 추가 + * */ + @PostMapping("") + public BaseResponse signUp(@Validated @RequestBody PostShopRequest postShopRequest, BindingResult bindingResult) { + log.info("[ShopController.addShop]"); + if (bindingResult.hasErrors()) { + throw new ShopException(INVALID_SHOP_VALUE, getErrorMessages(bindingResult)); + } + return new BaseResponse<>(shopService.addShop(postShopRequest)); + } + @GetMapping("/list") + public BaseResponse> getShops(@RequestParam(required = false) String category, @RequestParam(required = false) String address) { + if (category != null && address != null) { + // 카테고리와 주소로 가게 검색 + return new BaseResponse<>(shopService.getShopsByCategoryAndAddress(category, address)); + + } else if (category != null) { + // 카테고리로 가게 검색 + return new BaseResponse<>(shopService.getShopsByCategory(category)); + } else if (address != null) { + // 주소로 가게 검색 + return new BaseResponse<>(shopService.getShopsByAddress(address)); + } else { + // 카테고리와 주소가 주어지지 않은 경우 모든 가게 목록 반환 + return new BaseResponse<>( shopService.getAllShops()); + } + } + @GetMapping("/list-page") + public BaseResponse getShopPage(@Validated @RequestBody GetShopListRequest getShopListRequest) { + return new BaseResponse<>(shopService.getShopList(getShopListRequest)); + } + @GetMapping("/detail") + public BaseResponse> getShopDetail(@Validated @RequestParam long shopId, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new ShopException(INVALID_SHOP_VALUE, getErrorMessages(bindingResult)); + } + return new BaseResponse<>(shopService.getShopById(shopId)); + } + + @GetMapping("/food-categories") + public List getAllFoodCategories() { + return shopService.getAllFoodCategories(); + } + + @PostMapping("/food-categories/{foodCategory}") + public BaseResponse postAllFoodCategories(@Range(min=1,max=10) @PathVariable String foodCategory) { + return new BaseResponse<>(shopService.addFoodCategory(foodCategory)); + } +} diff --git a/src/main/java/kuit3/backend/controller/UserController.java b/src/main/java/kuit3/backend/controller/UserController.java index 70b712b..3c91620 100644 --- a/src/main/java/kuit3/backend/controller/UserController.java +++ b/src/main/java/kuit3/backend/controller/UserController.java @@ -1,19 +1,25 @@ package kuit3.backend.controller; +import jakarta.validation.constraints.NotNull; +import kuit3.backend.common.argument_resolver.JwtAuthrize; +import kuit3.backend.common.exception.BadRequestException; import kuit3.backend.common.exception.UserException; +import kuit3.backend.common.response.BaseErrorResponse; import kuit3.backend.common.response.BaseResponse; import kuit3.backend.dto.user.*; +import kuit3.backend.dto.user.address.GetUserAddressResponse; +import kuit3.backend.dto.user.address.PostUserAddressRequest; import kuit3.backend.service.UserService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.tomcat.websocket.AuthenticationException; import org.springframework.validation.BindingResult; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.List; -import static kuit3.backend.common.response.status.BaseExceptionResponseStatus.INVALID_USER_STATUS; -import static kuit3.backend.common.response.status.BaseExceptionResponseStatus.INVALID_USER_VALUE; +import static kuit3.backend.common.response.status.BaseExceptionResponseStatus.*; import static kuit3.backend.util.BindingResultUtils.getErrorMessages; @Slf4j @@ -39,7 +45,7 @@ public BaseResponse signUp(@Validated @RequestBody PostUserReq * 회원 휴면 */ @PatchMapping("/{userId}/dormant") - public BaseResponse modifyUserStatus_dormant(@PathVariable long userId) { + public BaseResponse modifyUserStatus_dormant(@NotNull @JwtAuthrize long userId) { userService.modifyUserStatus_dormant(userId); return new BaseResponse<>(null); } @@ -48,7 +54,7 @@ public BaseResponse modifyUserStatus_dormant(@PathVariable long userId) * 회원 탈퇴 */ @PatchMapping("/{userId}/deleted") - public BaseResponse modifyUserStatus_deleted(@PathVariable long userId) { + public BaseResponse modifyUserStatus_deleted(@NotNull @JwtAuthrize long userId) { userService.modifyUserStatus_deleted(userId); return new BaseResponse<>(null); } @@ -57,7 +63,7 @@ public BaseResponse modifyUserStatus_deleted(@PathVariable long userId) * 닉네임 변경 */ @PatchMapping("/{userId}/nickname") - public BaseResponse modifyNickname(@PathVariable long userId, + public BaseResponse modifyNickname(@NotNull @JwtAuthrize long userId, @Validated @RequestBody PatchNicknameRequest patchNicknameRequest, BindingResult bindingResult) { if (bindingResult.hasErrors()) { throw new UserException(INVALID_USER_VALUE, getErrorMessages(bindingResult)); @@ -74,9 +80,29 @@ public BaseResponse> getUsers( @RequestParam(required = false, defaultValue = "") String nickname, @RequestParam(required = false, defaultValue = "") String email, @RequestParam(required = false, defaultValue = "active") String status) { + log.info("[UserController.getUsers]"); if (!status.equals("active") && !status.equals("dormant") && !status.equals("deleted")) { throw new UserException(INVALID_USER_STATUS); } return new BaseResponse<>(userService.getUsers(nickname, email, status)); } + + @PostMapping("/address") + public BaseResponse addUserAddress + (@NotNull @JwtAuthrize long userId , @Validated @RequestBody PostUserAddressRequest postUserAddressRequest, BindingResult bindingResult){ + if (bindingResult.hasErrors()) { + throw new UserException(INVALID_ADDRESS_INPUT, getErrorMessages(bindingResult)); + } + postUserAddressRequest.setUserId(userId); + userService.addUserAddress(postUserAddressRequest); + return new BaseResponse<>(null); + } + + @GetMapping("/address/{userId}") + public BaseResponse> getUserAddress(/*@Validated @NotNull*/ @PathVariable("userId") long AskUserId,@RequestAttribute("userId") Long AuthUserId){ + if (AskUserId != AuthUserId) { + throw new BadRequestException(INVALID_USER_STATUS); + } + return new BaseResponse<>(userService.getUserAddress(AskUserId)); + } } \ No newline at end of file diff --git a/src/main/java/kuit3/backend/controller/WishlistController.java b/src/main/java/kuit3/backend/controller/WishlistController.java new file mode 100644 index 0000000..d13f138 --- /dev/null +++ b/src/main/java/kuit3/backend/controller/WishlistController.java @@ -0,0 +1,36 @@ +package kuit3.backend.controller; + + +import kuit3.backend.common.response.BaseResponse; +import kuit3.backend.dto.wishlist.GetWishlistRequest; +import kuit3.backend.dto.wishlist.PostWishlistRequest; +import kuit3.backend.dto.wishlist.PostWishlistResponse; +import kuit3.backend.service.WishlistService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.BindingResult; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import static kuit3.backend.util.BindingResultUtils.getErrorMessages; + + +@Slf4j +@RestController +@RequiredArgsConstructor +@RequestMapping("/wishlist") +public class WishlistController { + private final WishlistService wishlistService; + @PostMapping("") + public BaseResponse getWishlist(@Validated @RequestBody PostWishlistRequest wishLisRreq, BindingResult bindingResult){ + if (bindingResult.hasErrors()) { + throw new RuntimeException( getErrorMessages(bindingResult)); + } + return new BaseResponse<>(wishlistService.createWishlist(wishLisRreq)); + } + @GetMapping("") + public BaseResponse getWishlist(@Validated @RequestBody GetWishlistRequest wishLisRreq, BindingResult bindingResult){ + + return new BaseResponse<>(wishlistService.getWishlist(wishLisRreq)); + } +} diff --git a/src/main/java/kuit3/backend/dao/ShopDao.java b/src/main/java/kuit3/backend/dao/ShopDao.java new file mode 100644 index 0000000..48c2c6d --- /dev/null +++ b/src/main/java/kuit3/backend/dao/ShopDao.java @@ -0,0 +1,169 @@ +package kuit3.backend.dao; + + +import kuit3.backend.dto.shop.*; +import lombok.extern.slf4j.Slf4j; +import org.springframework.jdbc.core.BeanPropertyRowMapper; +import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.stereotype.Repository; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +@Slf4j +@Repository +public class ShopDao { + private final NamedParameterJdbcTemplate namedParameterJdbcTemplate; + + public ShopDao(NamedParameterJdbcTemplate namedParameterJdbcTemplate) { + this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; + } + + public long createShop(PostShopRequest shop) { + String sql = "INSERT INTO Shop (shop_name, shop_call_num, status, address, food_category) " + + "VALUES (:shopName, :shopCallNum, 'open', :address, :foodCategory)"; + +// Map paramMap = Map.of( +// "shopName", shop.getShopName(), +// "shopCallNum", shop.getPhoneNumber(), +//// "isOpenNow", shop.isOpenNow(), +// "address", shop.getAddress(), +// "foodCategory", shop.getFoodCategory() +// ); + SqlParameterSource param = new BeanPropertySqlParameterSource(shop); + KeyHolder keyHolder = new GeneratedKeyHolder(); + namedParameterJdbcTemplate.update(sql, param, keyHolder); + + return Objects.requireNonNull(keyHolder.getKey()).longValue(); + + //return namedParameterJdbcTemplate.update(sql, paramMap); + } + public void createFoodCategory(String foodCategory) { + String sql = "INSERT INTO `food_category` (`food_category`) " + + "VALUES (:foodCategory)"; + + SqlParameterSource param = new MapSqlParameterSource().addValue("foodCategory", foodCategory); + namedParameterJdbcTemplate.update(sql, param); + + //return namedParameterJdbcTemplate.update(sql, paramMap); + } + + public boolean hasDuplicateShopName(String shopName){ + String sql = "select exists(select shop_name from shop where shop_name=:shopName)"; + Map param = Map.of("shopName", shopName); + return Boolean.TRUE.equals(namedParameterJdbcTemplate.queryForObject(sql, param, boolean.class)); + } + + + + public List getShopsByAddress(String address) { + String sql = "SELECT * FROM Shop WHERE address = :address"; + Map paramMap = Collections.singletonMap("address", address); + + return namedParameterJdbcTemplate.query(sql, paramMap, (rs, rowNum) -> { + Shop shop = new Shop(); + shop.setShopId(rs.getLong("Shop_id")); + shop.setShopName(rs.getString("shop_name")); + shop.setShopCallNum(rs.getString("shop_call_num")); + shop.setOpenNow(rs.getBoolean("is_open_now")); + shop.setAddress(rs.getString("address")); + shop.setFoodCategory(rs.getString("food_category")); + return shop; + }); + } + + public List getAllShops() { + String sql = "SELECT * FROM Shop"; + return namedParameterJdbcTemplate.query(sql, (rs, rowNum) -> { + Shop shop = new Shop(); + shop.setShopId(rs.getLong("Shop_id")); + shop.setShopName(rs.getString("shop_name")); + shop.setShopCallNum(rs.getString("shop_call_num")); + shop.setOpenNow(rs.getBoolean("is_open_now")); + shop.setAddress(rs.getString("address")); + shop.setFoodCategory(rs.getString("food_category")); + return shop; + }); + } + + public List findShopsByStartShopId(GetShopListRequest getShopListRequest) { + String sql = "SELECT shop_name AS shopName, shop_call_num AS shopCallNumber, address,shop_id AS shopId " + + "FROM shop " + + "WHERE shop_id >= :startShopId and food_category= :foodCategory and address=:address " + + "LIMIT :limit"; + MapSqlParameterSource params = new MapSqlParameterSource() + .addValue("startShopId", getShopListRequest.getLastId()) + .addValue("foodCategory", getShopListRequest.getFoodCategory()) + .addValue("address", getShopListRequest.getAddress()) + .addValue("limit", getShopListRequest.getNumber()); + return namedParameterJdbcTemplate.query(sql, params, new BeanPropertyRowMapper<>(GetShopResponseEntity.class)); + } + + public List getShopById(long shopId) { + String sql = "SELECT * FROM Shop WHERE Shop_id = :shopId"; + Map paramMap = Collections.singletonMap("shopId", shopId); + + return namedParameterJdbcTemplate.query(sql, paramMap, (rs, rowNum) -> { + Shop shop = new Shop(); + shop.setShopId(rs.getLong("Shop_id")); + shop.setShopName(rs.getString("shop_name")); + shop.setShopCallNum(rs.getString("shop_call_num")); + shop.setOpenNow(rs.getBoolean("is_open_now")); + shop.setAddress(rs.getString("address")); + shop.setFoodCategory(rs.getString("food_category")); + return shop; + }); + } + public List getShopsByCategory(String category) { + String sql = "SELECT * FROM Shop WHERE food_category = :category"; + Map paramMap = Collections.singletonMap("category", category); + + return namedParameterJdbcTemplate.query(sql, paramMap, (rs, rowNum) -> mapRowToShop(rs)); + } + public boolean hasDuplicateFoodCategoryName(String foodCategory){ + String sql = "select exists(select food_category from food_category WHERE food_category=:foodCategory)"; + Map param = Map.of("foodCategory", foodCategory); + return Boolean.TRUE.equals(namedParameterJdbcTemplate.queryForObject(sql, param, boolean.class)); + } + + public List getShopsByCategoryAndAddress(String category, String address) { + String sql = "SELECT * FROM Shop WHERE food_category = :category AND address = :address"; + Map paramMap = Map.of("category", category, "address", address); + + return namedParameterJdbcTemplate.query(sql, paramMap, (rs, rowNum) -> mapRowToShop(rs)); + } + private Shop mapRowToShop(ResultSet rs) throws SQLException { + Shop shop = new Shop(); + shop.setShopId(rs.getLong("Shop_id")); + shop.setShopName(rs.getString("shop_name")); + shop.setShopCallNum(rs.getString("shop_call_num")); + shop.setOpenNow(rs.getBoolean("is_open_now")); + shop.setAddress(rs.getString("address")); + shop.setFoodCategory(rs.getString("food_category")); + return shop; + } + + public List getAllFoodCategories() { + String sql = "SELECT food_category FROM food_category"; + return namedParameterJdbcTemplate.query(sql, (rs, rowNum) -> { + FoodCategory foodCategory = new FoodCategory(); + foodCategory.setCategory(rs.getString("food_category")); + return foodCategory; + }); + } + public boolean isExistId(long shopId) { + String sql = "select exists(select Shop_id from shop where Shop_id=:shopId)"; + Map param = Map.of("shopId", shopId); + return Boolean.TRUE.equals(namedParameterJdbcTemplate.queryForObject(sql, param, boolean.class)); + } + +} diff --git a/src/main/java/kuit3/backend/dao/UserDao.java b/src/main/java/kuit3/backend/dao/UserDao.java index 4447633..95284c5 100644 --- a/src/main/java/kuit3/backend/dao/UserDao.java +++ b/src/main/java/kuit3/backend/dao/UserDao.java @@ -1,9 +1,13 @@ package kuit3.backend.dao; +import kuit3.backend.dto.shop.Shop; import kuit3.backend.dto.user.GetUserResponse; import kuit3.backend.dto.user.PostUserRequest; +import kuit3.backend.dto.user.address.GetUserAddressResponse; +import kuit3.backend.dto.user.address.PostUserAddressRequest; import lombok.extern.slf4j.Slf4j; import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.core.namedparam.SqlParameterSource; import org.springframework.jdbc.support.GeneratedKeyHolder; @@ -11,6 +15,8 @@ import org.springframework.stereotype.Repository; import javax.sql.DataSource; +import java.sql.ResultSet; +import java.sql.SQLException; import java.util.List; import java.util.Map; import java.util.Objects; @@ -31,6 +37,12 @@ public boolean hasDuplicateEmail(String email) { return Boolean.TRUE.equals(jdbcTemplate.queryForObject(sql, param, boolean.class)); } + public boolean isExistId(long userId) { + String sql = "select exists(select User_id from user where User_id=:userId)"; //and status in ('active', 'dormant'))"; + Map param = Map.of("userId", userId); + return Boolean.TRUE.equals(jdbcTemplate.queryForObject(sql, param, boolean.class)); + } + public boolean hasDuplicateNickName(String nickname) { String sql = "select exists(select email from user where nickname=:nickname and status in ('active', 'dormant'))"; Map param = Map.of("nickname", nickname); @@ -38,8 +50,8 @@ public boolean hasDuplicateNickName(String nickname) { } public long createUser(PostUserRequest postUserRequest) { - String sql = "insert into user(email, password, phone_number, nickname, profile_image) " + - "values(:email, :password, :phoneNumber, :nickname, :profileImage)"; + String sql = "insert into user(email, password, phone_number, nickname, profile_image,status) " + + "values(:email, :password, :phoneNumber, :nickname, :profileImage, 'active')"; SqlParameterSource param = new BeanPropertySqlParameterSource(postUserRequest); KeyHolder keyHolder = new GeneratedKeyHolder(); @@ -48,6 +60,30 @@ public long createUser(PostUserRequest postUserRequest) { return Objects.requireNonNull(keyHolder.getKey()).longValue(); } + public int modifyUserStatus_dormant(long userId) { + String sql = "update user set status=:status where user_id=:user_id"; + Map param = Map.of( + "status", "dormant", + "user_id", userId); + return jdbcTemplate.update(sql, param); + } + + public int modifyUserStatus_deleted(long userId) { + String sql = "update user set status=:status where user_id=:user_id"; + Map param = Map.of( + "status", "deleted", + "user_id", userId); + return jdbcTemplate.update(sql, param); + } + + public int modifyNickname(long userId, String nickname) { + String sql = "update user set nickname=:nickname where user_id=:user_id"; + Map param = Map.of( + "nickname", nickname, + "user_id", userId); + return jdbcTemplate.update(sql, param); + } + public List getUsers(String nickname, String email, String status) { String sql = "select email, phone_number, nickname, profile_image, status from user " + "where nickname like :nickname and email like :email and status=:status"; @@ -79,27 +115,40 @@ public String getPasswordByUserId(long userId) { return jdbcTemplate.queryForObject(sql, param, String.class); } - public int modifyUserStatus_dormant(long userId) { - String sql = "update user set status=:status where user_id=:user_id"; - Map param = Map.of( - "status", "dormant", - "user_id", userId); - return jdbcTemplate.update(sql, param); + public void createUserAddress(PostUserAddressRequest postUserAddressRequest) { + String sql = "insert into user_address(address_category,user_id,user_address) " + + "values(:addressCategory, :userId, :userAddress)"; + + SqlParameterSource param = new BeanPropertySqlParameterSource(postUserAddressRequest); + //KeyHolder keyHolder = new GeneratedKeyHolder(); + + jdbcTemplate.update(sql, param); + } - public int modifyUserStatus_deleted(long userId) { - String sql = "update user set status=:status where user_id=:user_id"; - Map param = Map.of( - "status", "deleted", - "user_id", userId); - return jdbcTemplate.update(sql, param); + + public List getUserAddress(long userId) { + String sql = "SELECT * FROM user_address WHERE user_id = :userId "; + Map paramMap = Map.of("userId",userId); + + return jdbcTemplate.query(sql, paramMap, (rs, rowNum) -> mapRowToShop(rs)); } + public boolean hasDuplicateUserAddress(PostUserAddressRequest postUserAddressRequest){ + String sql = "SELECT COUNT(*) FROM User_address WHERE address_category = :addressCategory AND user_address = :userAddress"; - public int modifyNickname(long userId, String nickname) { - String sql = "update user set nickname=:nickname where user_id=:user_id"; - Map param = Map.of( - "nickname", nickname, - "user_id", userId); - return jdbcTemplate.update(sql, param); + MapSqlParameterSource params = new MapSqlParameterSource(); + params.addValue("addressCategory", postUserAddressRequest.getAddressCategory()); + params.addValue("userAddress", postUserAddressRequest.getUserAddress()); + + int count = jdbcTemplate.queryForObject(sql, params, Integer.class); + + return count > 0; + } + private GetUserAddressResponse mapRowToShop(ResultSet rs) throws SQLException { + Shop shop = new Shop(); + GetUserAddressResponse userAddressResponse = new GetUserAddressResponse(); + userAddressResponse.setUserAddress(rs.getString("user_address")); + userAddressResponse.setAddressCategory(rs.getString("address_category")); + return userAddressResponse; } } \ No newline at end of file diff --git a/src/main/java/kuit3/backend/dao/WishlistDao.java b/src/main/java/kuit3/backend/dao/WishlistDao.java new file mode 100644 index 0000000..e394373 --- /dev/null +++ b/src/main/java/kuit3/backend/dao/WishlistDao.java @@ -0,0 +1,68 @@ +package kuit3.backend.dao; + + +import kuit3.backend.dto.wishlist.GetWishlistRequest; +import kuit3.backend.dto.wishlist.GetWishlistResponse; +import kuit3.backend.dto.wishlist.PostWishlistRequest; +import kuit3.backend.dto.wishlist.PostWishlistResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; +import org.springframework.stereotype.Repository; + +import javax.sql.DataSource; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; + +@Slf4j +@Repository + +public class WishlistDao { + private final NamedParameterJdbcTemplate jdbcTemplate; + public WishlistDao(DataSource dataSource) { + this.jdbcTemplate = new NamedParameterJdbcTemplate(dataSource); + } + + public PostWishlistResponse createWishlist(PostWishlistRequest postWishlistRequest) { + String sql = "insert into wish_list(User_id,Shop_id) " + + "values(:userId,:shopId)"; + + SqlParameterSource param = new BeanPropertySqlParameterSource(postWishlistRequest); + //KeyHolder keyHolder = new GeneratedKeyHolder(); + + jdbcTemplate.update(sql, param); + + PostWishlistResponse postWishlistResponse = new PostWishlistResponse(); + postWishlistResponse.setMessage("찜 목록에 추가 되었습니다."); + return postWishlistResponse; + } + + + public List findShopsByUserId(GetWishlistRequest getWishlistRequest) { + String FIND_SHOPS_BY_USER_ID_SQL = + "SELECT s.Shop_id, s.shop_name " + + "FROM wish_list w " + + "JOIN Shop s ON w.Shop_id = s.Shop_id " + + "WHERE w.User_id = :userId"; + + MapSqlParameterSource params = new MapSqlParameterSource(); + params.addValue("userId", getWishlistRequest.getUserId()); + + return jdbcTemplate.query(FIND_SHOPS_BY_USER_ID_SQL, params, new ShopRowMapper()); + } + + private static final class ShopRowMapper implements RowMapper { + @Override + public GetWishlistResponse mapRow(ResultSet rs, int rowNum) throws SQLException { + GetWishlistResponse shop = new GetWishlistResponse(); + shop.setShopId(rs.getLong("Shop_id")); + shop.setShopName(rs.getString("shop_name")); + return shop; + } + + } +} diff --git a/src/main/java/kuit3/backend/dto/shop/FoodCategory.java b/src/main/java/kuit3/backend/dto/shop/FoodCategory.java new file mode 100644 index 0000000..8759633 --- /dev/null +++ b/src/main/java/kuit3/backend/dto/shop/FoodCategory.java @@ -0,0 +1,14 @@ +package kuit3.backend.dto.shop; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@RequiredArgsConstructor +public class FoodCategory { + private String category; + + // 생성자, getter 및 setter 메서드 생략 +} diff --git a/src/main/java/kuit3/backend/dto/shop/GetShopListRequest.java b/src/main/java/kuit3/backend/dto/shop/GetShopListRequest.java new file mode 100644 index 0000000..7db00d1 --- /dev/null +++ b/src/main/java/kuit3/backend/dto/shop/GetShopListRequest.java @@ -0,0 +1,31 @@ +package kuit3.backend.dto.shop; + +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.NumberFormat; + +@Getter +@Setter +@RequiredArgsConstructor +public class GetShopListRequest { + @NotBlank(message = "foodCategory: {NotBlank}") + @Length(max = 10, message = "foodCategory: 최대 {max}자리까지 가능합니다") + private String foodCategory; + + @NotBlank(message = "address: {NotBlank}") + @Length(max = 50, message = "address: 최대 {max}자리까지 가능합니다") + private String address; + + @NotNull + private long lastId; + + @NotNull + @Min(value = 1, message = "Value must be greater than or equal to 1") + private int number = 10; +} diff --git a/src/main/java/kuit3/backend/dto/shop/GetShopListResponse.java b/src/main/java/kuit3/backend/dto/shop/GetShopListResponse.java new file mode 100644 index 0000000..9b84083 --- /dev/null +++ b/src/main/java/kuit3/backend/dto/shop/GetShopListResponse.java @@ -0,0 +1,15 @@ +package kuit3.backend.dto.shop; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +@RequiredArgsConstructor +public class GetShopListResponse { + private List shopList; + private boolean hasNextPage; +} diff --git a/src/main/java/kuit3/backend/dto/shop/GetShopResponseEntity.java b/src/main/java/kuit3/backend/dto/shop/GetShopResponseEntity.java new file mode 100644 index 0000000..2972589 --- /dev/null +++ b/src/main/java/kuit3/backend/dto/shop/GetShopResponseEntity.java @@ -0,0 +1,15 @@ +package kuit3.backend.dto.shop; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@RequiredArgsConstructor +public class GetShopResponseEntity { + private long shopId; + private String shopName; + private String shopCallNumber; + private String address; +} diff --git a/src/main/java/kuit3/backend/dto/shop/PostShopRequest.java b/src/main/java/kuit3/backend/dto/shop/PostShopRequest.java new file mode 100644 index 0000000..f6670d3 --- /dev/null +++ b/src/main/java/kuit3/backend/dto/shop/PostShopRequest.java @@ -0,0 +1,28 @@ +package kuit3.backend.dto.shop; + +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import org.hibernate.validator.constraints.Length; + +@Getter +@Setter +@RequiredArgsConstructor +public class PostShopRequest { + @NotBlank(message = "shopName: {NotBlank}") + @Length(min=2, max=20,message = "shopName: 최소 {min}자리 ~ 최대 {max}자리까지 가능합니다") + private String shopName; + + @NotBlank(message = "shop PhoneNumber: {NotBlank}") + @Length(max = 20, message = "phoneNumber: 최대 {max}자리까지 가능합니다") + private String shopCallNum; + + @NotBlank(message = "address: {NotBlank}") + @Length(max = 50, message = "address: 최대 {max}자리까지 가능합니다") + private String address; + + @NotBlank(message = "foodCategory: {NotBlank}") + @Length(max = 10, message = "foodCategory: 최대 {max}자리까지 가능합니다") + private String foodCategory; +} diff --git a/src/main/java/kuit3/backend/dto/shop/PostShopResponse.java b/src/main/java/kuit3/backend/dto/shop/PostShopResponse.java new file mode 100644 index 0000000..3bbf6c2 --- /dev/null +++ b/src/main/java/kuit3/backend/dto/shop/PostShopResponse.java @@ -0,0 +1,10 @@ +package kuit3.backend.dto.shop; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class PostShopResponse { + private long shopId; +} diff --git a/src/main/java/kuit3/backend/dto/shop/Shop.java b/src/main/java/kuit3/backend/dto/shop/Shop.java new file mode 100644 index 0000000..7ab8e12 --- /dev/null +++ b/src/main/java/kuit3/backend/dto/shop/Shop.java @@ -0,0 +1,21 @@ +package kuit3.backend.dto.shop; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@RequiredArgsConstructor +public class Shop { + private long shopId; + private String shopName; + private String shopCallNum; + private boolean isOpenNow; + private String address; + private String foodCategory; + + // 생성자, getter 및 setter 메서드 생략 + + +} diff --git a/src/main/java/kuit3/backend/dto/user/PostUserRequest.java b/src/main/java/kuit3/backend/dto/user/PostUserRequest.java index dddd102..3992b9c 100644 --- a/src/main/java/kuit3/backend/dto/user/PostUserRequest.java +++ b/src/main/java/kuit3/backend/dto/user/PostUserRequest.java @@ -30,7 +30,7 @@ public class PostUserRequest { @Length(max = 20, message = "phoneNumber: 최대 {max}자리까지 가능합니다") private String phoneNumber; - @Nullable + @NotBlank @Length(max = 25, message = "nickname: 최대 {max}자리까지 가능합니다") private String nickname; diff --git a/src/main/java/kuit3/backend/dto/user/address/GetUserAddressResponse.java b/src/main/java/kuit3/backend/dto/user/address/GetUserAddressResponse.java new file mode 100644 index 0000000..a2df065 --- /dev/null +++ b/src/main/java/kuit3/backend/dto/user/address/GetUserAddressResponse.java @@ -0,0 +1,14 @@ +package kuit3.backend.dto.user.address; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@RequiredArgsConstructor +public class GetUserAddressResponse { + private String addressCategory; + private String userAddress; + +} diff --git a/src/main/java/kuit3/backend/dto/user/address/PostUserAddressRequest.java b/src/main/java/kuit3/backend/dto/user/address/PostUserAddressRequest.java new file mode 100644 index 0000000..197990c --- /dev/null +++ b/src/main/java/kuit3/backend/dto/user/address/PostUserAddressRequest.java @@ -0,0 +1,26 @@ +package kuit3.backend.dto.user.address; + +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import kuit3.backend.common.argument_resolver.JwtAuthrize; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import org.hibernate.validator.constraints.Length; + +@Getter +@Setter +@RequiredArgsConstructor +public class PostUserAddressRequest { + @Nullable + private long userId; + + @NotBlank + @Length(max = 10) + private String userAddress; + + @NotBlank + @Length(max=20) + private String addressCategory; +} diff --git a/src/main/java/kuit3/backend/dto/wishlist/GetWishlistRequest.java b/src/main/java/kuit3/backend/dto/wishlist/GetWishlistRequest.java new file mode 100644 index 0000000..6aecaaf --- /dev/null +++ b/src/main/java/kuit3/backend/dto/wishlist/GetWishlistRequest.java @@ -0,0 +1,14 @@ +package kuit3.backend.dto.wishlist; + +import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@RequiredArgsConstructor +public class GetWishlistRequest { + @NotNull + private long userId; +} diff --git a/src/main/java/kuit3/backend/dto/wishlist/GetWishlistResponse.java b/src/main/java/kuit3/backend/dto/wishlist/GetWishlistResponse.java new file mode 100644 index 0000000..0ac8ea0 --- /dev/null +++ b/src/main/java/kuit3/backend/dto/wishlist/GetWishlistResponse.java @@ -0,0 +1,14 @@ +package kuit3.backend.dto.wishlist; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@RequiredArgsConstructor +public class GetWishlistResponse { + private long shopId; + private String shopName; + +} diff --git a/src/main/java/kuit3/backend/dto/wishlist/PostWishlistRequest.java b/src/main/java/kuit3/backend/dto/wishlist/PostWishlistRequest.java new file mode 100644 index 0000000..da24eb1 --- /dev/null +++ b/src/main/java/kuit3/backend/dto/wishlist/PostWishlistRequest.java @@ -0,0 +1,17 @@ +package kuit3.backend.dto.wishlist; + +import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; + + +@Getter +@Setter +@RequiredArgsConstructor +public class PostWishlistRequest { + @NotNull + private long userId; + @NotNull + private long shopId; +} diff --git a/src/main/java/kuit3/backend/dto/wishlist/PostWishlistResponse.java b/src/main/java/kuit3/backend/dto/wishlist/PostWishlistResponse.java new file mode 100644 index 0000000..189ac0e --- /dev/null +++ b/src/main/java/kuit3/backend/dto/wishlist/PostWishlistResponse.java @@ -0,0 +1,13 @@ +package kuit3.backend.dto.wishlist; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@RequiredArgsConstructor +public class PostWishlistResponse { + private String message; + +} diff --git a/src/main/java/kuit3/backend/jwt/JwtProvider.java b/src/main/java/kuit3/backend/jwt/JwtProvider.java index c1f1369..565390b 100644 --- a/src/main/java/kuit3/backend/jwt/JwtProvider.java +++ b/src/main/java/kuit3/backend/jwt/JwtProvider.java @@ -1,6 +1,7 @@ package kuit3.backend.jwt; import io.jsonwebtoken.*; +import io.jsonwebtoken.security.Keys; import kuit3.backend.common.exception.jwt.unauthorized.JwtInvalidTokenException; import kuit3.backend.common.exception.jwt.unauthorized.JwtMalformedTokenException; import kuit3.backend.common.exception.jwt.bad_request.JwtUnsupportedTokenException; @@ -8,6 +9,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import java.security.Key; import java.util.Date; import static kuit3.backend.common.response.status.BaseExceptionResponseStatus.*; @@ -15,13 +17,13 @@ @Slf4j @Component public class JwtProvider { - + @Value("${secret.jwt-expired-in}") + private long JWT_EXPIRED_IN; @Value("${secret.jwt-secret-key}") private String JWT_SECRET_KEY; - @Value("${secret.jwt-expired-in}") - private long JWT_EXPIRED_IN; + //private static final Key JWT_SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256); public String createToken(String principal, long userId) { log.info("JWT key={}", JWT_SECRET_KEY); diff --git a/src/main/java/kuit3/backend/jwt/JwtUtil.java b/src/main/java/kuit3/backend/jwt/JwtUtil.java new file mode 100644 index 0000000..91c9740 --- /dev/null +++ b/src/main/java/kuit3/backend/jwt/JwtUtil.java @@ -0,0 +1,56 @@ +package kuit3.backend.jwt; + +import jakarta.servlet.http.HttpServletRequest; +import kuit3.backend.common.exception.jwt.bad_request.JwtNoTokenException; +import kuit3.backend.common.exception.jwt.bad_request.JwtUnsupportedTokenException; +import kuit3.backend.common.exception.jwt.unauthorized.JwtExpiredTokenException; +import kuit3.backend.common.exception.jwt.unauthorized.JwtInvalidTokenException; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpHeaders; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.NativeWebRequest; + +import static kuit3.backend.common.response.status.BaseExceptionResponseStatus.*; +import static kuit3.backend.common.response.status.BaseExceptionResponseStatus.INVALID_TOKEN; +@Component +@RequiredArgsConstructor +public class JwtUtil { + private static final String JWT_TOKEN_PREFIX = "Bearer "; + + private final JwtProvider jwtProvider; + + public String resolveAccessToken(HttpServletRequest request) { + String token = request.getHeader(HttpHeaders.AUTHORIZATION); + validateToken(token); + return token.substring(JWT_TOKEN_PREFIX.length()); + } +// public String resolveAccessToken(NativeWebRequest webRequest) { +// String token = webRequest.getHeader(HttpHeaders.AUTHORIZATION); +// validateToken(token); +// return token.substring(JWT_TOKEN_PREFIX.length()); +// } + + public void validateToken(String token) { + if (token == null) { + throw new JwtNoTokenException(TOKEN_NOT_FOUND); + } + if (!token.startsWith(JWT_TOKEN_PREFIX)) { + throw new JwtUnsupportedTokenException(UNSUPPORTED_TOKEN_TYPE); + } + } + + public void validateAccessToken(String accessToken) { + if (jwtProvider.isExpiredToken(accessToken)) { + throw new JwtExpiredTokenException(EXPIRED_TOKEN); + } + } + + public void validatePayload(String email) { + if (email == null) { + throw new JwtInvalidTokenException(INVALID_TOKEN); + } + } + public String getEmail(String accessToken) { + return jwtProvider.getPrincipal(accessToken); + } +} diff --git a/src/main/java/kuit3/backend/service/ShopService.java b/src/main/java/kuit3/backend/service/ShopService.java new file mode 100644 index 0000000..38f12b4 --- /dev/null +++ b/src/main/java/kuit3/backend/service/ShopService.java @@ -0,0 +1,94 @@ +package kuit3.backend.service; + + +import kuit3.backend.common.exception.ShopException; +import kuit3.backend.dao.ShopDao; +import kuit3.backend.dto.shop.*; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; + +import static kuit3.backend.common.response.status.BaseExceptionResponseStatus.DUPLICATE_SHOP_NAME; +import static kuit3.backend.common.response.status.BaseExceptionResponseStatus.FOODCATEGORY_NOT_MATCH; + +@Slf4j +@Service +@RequiredArgsConstructor +public class ShopService { + private final ShopDao shopDAO; + + + public List getAllShops() { + return shopDAO.getAllShops(); + } + + public List getShopById(long shopId) { + return shopDAO.getShopById(shopId); + } + + public PostShopResponse addShop(PostShopRequest postShopRequest){ + log.info("[ShopController : add Shop]"); + validationShopName(postShopRequest.getShopName()); + + return new PostShopResponse(shopDAO.createShop(postShopRequest)); + } + public List getShopsByAddress(String address) { + return shopDAO.getShopsByAddress(address); + } + public List getShopsByCategoryAndAddress(String category, String address) { + if(!shopDAO.hasDuplicateFoodCategoryName(category)){ + throw new ShopException(FOODCATEGORY_NOT_MATCH); + } + return shopDAO.getShopsByCategoryAndAddress(category, address); + } + public List getShopsByCategory(String category) { + if(!shopDAO.hasDuplicateFoodCategoryName(category)){ + throw new ShopException(FOODCATEGORY_NOT_MATCH); + } + return shopDAO.getShopsByCategory(category); + } + public GetShopListResponse getShopList(GetShopListRequest getShopListRequest){ + int howManyInPage = getShopListRequest.getNumber(); + getShopListRequest.setLastId(getShopListRequest.getLastId()+1); + getShopListRequest.setNumber(howManyInPage+1); + GetShopListResponse getShopListResponse = new GetShopListResponse(); + List result=shopDAO.findShopsByStartShopId(getShopListRequest); + + int listSize = result.size(); + if(listSize>howManyInPage){ + getShopListResponse.setHasNextPage(true); + result.subList(howManyInPage, listSize).clear(); + }else { + getShopListResponse.setHasNextPage(false); + } + + getShopListResponse.setShopList(result); + return getShopListResponse; + + } + public List getAllFoodCategories() { + return shopDAO.getAllFoodCategories(); + } + public String addFoodCategory(String foodCategory){ + + if(shopDAO.hasDuplicateFoodCategoryName(foodCategory)){ + return "이미 존재하는 카테고리 입니다."; + } + shopDAO.createFoodCategory(foodCategory); + return "새로운 카테고리 생성에 성공하였습니다"; + } + + private void validationShopName(String shopName){ + if(shopDAO.hasDuplicateShopName(shopName)){ + throw new ShopException(DUPLICATE_SHOP_NAME); + } + } + private void validationFoodCategory(String shopName){ + if(shopDAO.hasDuplicateShopName(shopName)){ + throw new ShopException(DUPLICATE_SHOP_NAME); + } + } + +} diff --git a/src/main/java/kuit3/backend/service/UserService.java b/src/main/java/kuit3/backend/service/UserService.java index 7a8dabd..3de6c7a 100644 --- a/src/main/java/kuit3/backend/service/UserService.java +++ b/src/main/java/kuit3/backend/service/UserService.java @@ -4,6 +4,8 @@ import kuit3.backend.common.exception.UserException; import kuit3.backend.dao.UserDao; import kuit3.backend.dto.user.*; +import kuit3.backend.dto.user.address.GetUserAddressResponse; +import kuit3.backend.dto.user.address.PostUserAddressRequest; import kuit3.backend.jwt.JwtProvider; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -22,10 +24,11 @@ public class UserService { private final UserDao userDao; private final PasswordEncoder passwordEncoder; - private final JwtProvider jwtProvider; + private final JwtProvider jwtTokenProvider; + - @Transactional public PostUserResponse signUp(PostUserRequest postUserRequest) { + log.info("[UserService.createUser]"); // TODO: 1. validation (중복 검사) validateEmail(postUserRequest.getEmail()); @@ -42,26 +45,33 @@ public PostUserResponse signUp(PostUserRequest postUserRequest) { long userId = userDao.createUser(postUserRequest); // TODO: 4. JWT 토큰 생성 - String jwt = jwtProvider.createToken(postUserRequest.getEmail(), userId); + String jwt = jwtTokenProvider.createToken(postUserRequest.getEmail(), userId); +// =userDao.createUser(postUserRequest); return new PostUserResponse(userId, jwt); } - public void modifyUserStatus_deleted(long userId) { - int affectedRows = userDao.modifyUserStatus_deleted(userId); + public void modifyUserStatus_dormant(long userId) { + log.info("[UserService.modifyUserStatus_dormant]"); + + int affectedRows = userDao.modifyUserStatus_dormant(userId); if (affectedRows != 1) { throw new DatabaseException(DATABASE_ERROR); } } - public void modifyUserStatus_dormant(long userId) { - int affectedRows = userDao.modifyUserStatus_dormant(userId); + public void modifyUserStatus_deleted(long userId) { + log.info("[UserService.modifyUserStatus_deleted]"); + + int affectedRows = userDao.modifyUserStatus_deleted(userId); if (affectedRows != 1) { throw new DatabaseException(DATABASE_ERROR); } } public void modifyNickname(long userId, String nickname) { + log.info("[UserService.modifyNickname]"); + validateNickname(nickname); int affectedRows = userDao.modifyNickname(userId, nickname); if (affectedRows != 1) { @@ -70,6 +80,7 @@ public void modifyNickname(long userId, String nickname) { } public List getUsers(String nickname, String email, String status) { + log.info("[UserService.getUsers]"); return userDao.getUsers(nickname, email, status); } @@ -84,4 +95,23 @@ private void validateNickname(String nickname) { throw new UserException(DUPLICATE_NICKNAME); } } + + public void addUserAddress(PostUserAddressRequest postUserAddressRequest){ + if(!userDao.isExistId(postUserAddressRequest.getUserId())){ + throw new UserException(INVALID_USER_ID); + } + if(userDao.hasDuplicateUserAddress(postUserAddressRequest)){ + throw new UserException(DUPLICATED_USER_ADDRESS); + } + userDao.createUserAddress(postUserAddressRequest); + } + public List getUserAddress(long userId){ + if(!userDao.isExistId(userId)){ + throw new UserException(INVALID_USER_ID); + } + return userDao.getUserAddress(userId); + } + + + } \ No newline at end of file diff --git a/src/main/java/kuit3/backend/service/WishlistService.java b/src/main/java/kuit3/backend/service/WishlistService.java new file mode 100644 index 0000000..25fdc13 --- /dev/null +++ b/src/main/java/kuit3/backend/service/WishlistService.java @@ -0,0 +1,54 @@ +package kuit3.backend.service; + + +import kuit3.backend.common.exception.UserException; +import kuit3.backend.common.response.status.ResponseStatus; +import kuit3.backend.dao.ShopDao; +import kuit3.backend.dao.UserDao; +import kuit3.backend.dao.WishlistDao; +import kuit3.backend.dto.wishlist.GetWishlistRequest; +import kuit3.backend.dto.wishlist.GetWishlistResponse; +import kuit3.backend.dto.wishlist.PostWishlistRequest; +import kuit3.backend.dto.wishlist.PostWishlistResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; + +import static kuit3.backend.common.response.status.BaseExceptionResponseStatus.INVALID_SHOP_ID; +import static kuit3.backend.common.response.status.BaseExceptionResponseStatus.INVALID_USER_ID; + + +@Slf4j +@Service +@RequiredArgsConstructor +public class WishlistService { + + final private WishlistDao wishlistDao; + private final UserDao userDao; + private final ShopDao shopDao; + public void validationWishlistPost(PostWishlistRequest wishlistRequest){ + if(!userDao.isExistId(wishlistRequest.getUserId())){ + throw new UserException(INVALID_USER_ID); + } + if(!shopDao.isExistId(wishlistRequest.getShopId())){ + throw new UserException(INVALID_SHOP_ID); + } + } + + public PostWishlistResponse createWishlist(PostWishlistRequest wishlistRequest){ + validationWishlistPost(wishlistRequest); + return wishlistDao.createWishlist(wishlistRequest); + + } + + public List getWishlist(GetWishlistRequest wishlistRequest){ + if(!userDao.isExistId(wishlistRequest.getUserId())){ + throw new UserException(INVALID_USER_ID); + } + return wishlistDao.findShopsByUserId(wishlistRequest); + + } + //public void deleteWishlist() +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 2bf75e2..7ecf022 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,5 +1,6 @@ spring: profiles: + active: local group: "local": "localDB, devPort, secret, web-mvc" "dev": "devDB, devPort, secret, web-mvc" @@ -13,9 +14,9 @@ spring: on-profile: "localDB" datasource: - url: ${DATASOURCE_URL_LOCAL} - username: ${DATASOURCE_USERNAME} - password: ${DATASOURCE_PASSWORD} + url: application.yml + username: kuit + password: driver-class-name: com.mysql.cj.jdbc.Driver dbcp2: validation-query: select 1 @@ -41,6 +42,12 @@ spring: init: platform: mysql +logging: + level: + org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate: DEBUG + org.springframework.jdbc.core.JdbcTemplate: DEBUG + org.springframework.jdbc.datasource.DataSourceTransactionManager: DEBUG + org.springframework.transaction.interceptor.TransactionInterceptor: DEBUG --- spring: @@ -87,8 +94,8 @@ spring: on-profile: "secret" secret: - jwt-secret-key: ${JWT_SECRET_KEY} - jwt-expired-in: ${JWT_EXPIRED_IN} + jwt-secret-key: q8ZlTY3McB2+H1g7Tb2Y/h5jNTpVZ5u/bglWb0Otbh4= + jwt-expired-in: 36000000 --- @@ -97,9 +104,6 @@ spring: activate: on-profile: "web-mvc" - mvc: - throw-exception-if-no-handler-found: true - web: resources: add-mappings: false diff --git a/src/main/resources/application_backup.yml b/src/main/resources/application_backup.yml new file mode 100644 index 0000000..559c681 --- /dev/null +++ b/src/main/resources/application_backup.yml @@ -0,0 +1,111 @@ +spring: + profiles: + group: + "local": "localDB, devPort, secret, web-mvc" + "dev": "devDB, devPort, secret, web-mvc" + "prod": "prodDB, prodPort, secret, web-mvc" + +--- + +spring: + config: + activate: + on-profile: "localDB" + + datasource: + url: ${DATASOURCE_URL_LOCAL} + username: ${DATASOURCE_USERNAME} + password: ${DATASOURCE_PASSWORD} + driver-class-name: com.mysql.cj.jdbc.Driver + dbcp2: + validation-query: select 1 + sql: + init: + platform: mysql + +--- + +spring: + config: + activate: + on-profile: "devDB" + + datasource: + url: ${DATASOURCE_URL_DEV} + username: ${DATASOURCE_USERNAME} + password: ${DATASOURCE_PASSWORD} + driver-class-name: com.mysql.cj.jdbc.Driver + dbcp2: + validation-query: select 1 + sql: + init: + platform: mysql + +logging: + level: + org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate: DEBUG + org.springframework.jdbc.core.JdbcTemplate: DEBUG + org.springframework.jdbc.datasource.DataSourceTransactionManager: DEBUG + org.springframework.transaction.interceptor.TransactionInterceptor: DEBUG +--- + +spring: + config: + activate: + on-profile: "prodDB" + + datasource: + url: ${DATASOURCE_URL_PROD} + username: ${DATASOURCE_USERNAME} + password: ${DATASOURCE_PASSWORD} + driver-class-name: com.mysql.cj.jdbc.Driver + dbcp2: + validation-query: select 1 + sql: + init: + platform: mysql + +--- + +spring: + config: + activate: + on-profile: "devPort" + +server: + port: 9000 + +--- + +spring: + config: + activate: + on-profile: "prodPort" + +server: + port: 9001 + +--- + +spring: + config: + activate: + on-profile: "secret" + +secret: + jwt-secret-key: ${JWT_SECRET_KEY} + jwt-expired-in: ${JWT_EXPIRED_IN} + +--- + +spring: + config: + activate: + on-profile: "web-mvc" + + web: + resources: + add-mappings: false + + messages: + basename: errors \ No newline at end of file