Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
@RequestMapping("/public/items")
public class PublicItemController {

private static final int TOP_LIMIT_10 = 10;
private static final int TOP_LIMIT_50 = 50;
private static final List<Integer> ALLOWED_LIMITS = List.of(TOP_LIMIT_10, TOP_LIMIT_50);

private final ItemService itemService;

@GetMapping("/{itemId}/details")
Expand All @@ -51,8 +55,8 @@ public ApiResponse<PageResponse<ItemSimpleResponse>> getItemPage(@Authentication
@GetMapping("/top")
public ApiResponse<List<ItemTopRankResponse>> getTopItemsByCategory(@RequestParam("category") Category category,
@RequestParam("limit") int limit) {
if (limit != 10 && limit != 50) {
throw new ApiException(ExceptionCode.INVALID_INPUT, "Limit 는 10 or 50 이어야합니다.");
if (!ALLOWED_LIMITS.contains(limit)) {
throw new ApiException(ExceptionCode.INVALID_INPUT, "Limit는 10 또는 50이어야 합니다.");
}

List<ItemTopRankResponse> topItemsResponse = itemService.getTopItemsResponseByCategory(category, limit);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
@RequiredArgsConstructor
public class ItemViewCountScheduler {

private static final int ONE_DAY = 1;

private final ItemViewCountRepository itemViewCountRepository;
private final ItemTopRankRepository itemTopRankRepository;

Expand All @@ -32,7 +34,7 @@ public void updateViewCounts() {
@Transactional
public void executeUpdateViewCounts() {
LocalDateTime now = LocalDateTime.now();
LocalDateTime startTime = now.minusDays(1);
LocalDateTime startTime = now.minusDays(ONE_DAY);

List<ItemViewCount> viewCounts = itemViewCountRepository.findViewCountsBetween(startTime, now);

Expand All @@ -48,7 +50,7 @@ public void executeUpdateViewCounts() {

// 새로운 순위 데이터를 삽입
categoryItemViewCounts.forEach((category, itemViewCounts) -> {
int rank = 1;
int rank = ONE_DAY;
for (Map.Entry<Item, Long> entry : itemViewCounts.entrySet()) {
ItemTopRank itemTopRank = ItemTopRank.builder()
.item(entry.getKey())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class BrandService {
private final BrandRepository brandRepository;
private final ItemRepository itemRepository;
Expand All @@ -52,27 +53,23 @@ public BrandResponse createBrand(String koreanName, String englishName, String b
return getBrandResponse(savedBrand);
}

@Transactional(readOnly = true)
public PageResponse<BrandInfoResponse> getBrandAndItem3Page(BasicSort sort, int page) {
Page<BrandInfoResponse> brandInfoPage = brandRepository.getBrandAndItem3Page(sort, PageRequest.of(page, API_PAGE_SIZE));
return new PageResponse<>(brandInfoPage.getContent(), brandInfoPage);
}

@Transactional(readOnly = true)
public List<BrandRecommendedResponse> getRecommendedBrands() {
return brandRepository.findTop10ByOrderByViewCountDesc()
.stream()
.map(brand -> new BrandRecommendedResponse(brand.getLogoImage(), brand.getKoreanName(), brand.getEnglishName()))
.collect(Collectors.toList());
}

@Transactional(readOnly = true)
public PageResponse<BrandItemResponse> getBrandItemPage(long brandId, BasicSort sort, int page) {
Page<BrandItemResponse> brandInfoPage = itemRepository.getBrandItemPage(brandId, sort, PageRequest.of(page, API_PAGE_SIZE));
return new PageResponse<>(brandInfoPage.getContent(), brandInfoPage);
}

@Transactional(readOnly = true)
public PageResponse<ReleaseInfoSimpleResponse> getBrandReleaseInfoPage(long brandId, int page) {
Page<ReleaseInfoSimpleResponse> releaseInfoInfoPage = releaseInfoRepository.getBrandReleaseInfoPage(brandId, PageRequest.of(page, API_PAGE_SIZE));
return new PageResponse<>(releaseInfoInfoPage.getContent(), releaseInfoInfoPage);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
@Transactional(readOnly = true)
@Slf4j
public class ItemService {

private static final int FIRST_PAGE = 0;
private static final int HOURS_TO_SUBTRACT = 9;

private final ItemRepository itemRepository;
private final BrandRepository brandRepository;
private final ItemImageRepository itemImageRepository;
Expand Down Expand Up @@ -89,34 +93,31 @@ public void increaseViewCount(Item item) {
.build());
}

@Transactional(readOnly = true)
public List<ItemSimpleResponse> getItem10List(Long userId, Section section, Category category) {
return switch (section) {
case DUE_TODAY, RELEASE_NOW, RELEASE_SCHEDULE ->
itemRepository.getItem10List(userId, LocalDateTime.now().minusHours(9), category, section); //HACK DB 시간 설정 전까지는 -9시간으로 비교해야 한다.
itemRepository.getItem10List(userId, LocalDateTime.now().minusHours(HOURS_TO_SUBTRACT), category, section); //HACK DB 시간 설정 전까지는 -9시간으로 비교해야 한다.
default -> throw new ApiException(INVALID_INPUT, SECTION_NOT_AVAILABLE_THIS_PAGE.getMessage());
};
}

@Transactional(readOnly = true)
public PageResponse<ItemSimpleResponse> getItemPage(Long userId, Section section, Category category, int page, String date) {
log.info("하늘:{}", date);
return switch (section) {
case RELEASE_SCHEDULE, CLOSED -> {
Page<ItemSimpleResponse> itemPageInfo = itemRepository.getItemPage(userId, LocalDateTime.now().minusHours(9), category, section, date, PageRequest.of(page, API_PAGE_SIZE)); //HACK DB 시간 설정 전까지는 -9시간으로 비교해야 한다.
Page<ItemSimpleResponse> itemPageInfo = itemRepository.getItemPage(userId, LocalDateTime.now().minusHours(HOURS_TO_SUBTRACT), category, section, date, PageRequest.of(page, API_PAGE_SIZE)); //HACK DB 시간 설정 전까지는 -9시간으로 비교해야 한다.
yield new PageResponse<>(itemPageInfo.getContent(), itemPageInfo);
}
default -> throw new ApiException(INVALID_INPUT, SECTION_NOT_AVAILABLE_THIS_PAGE.getMessage());
};
}

@Transactional(readOnly = true)
public List<ItemTopRankResponse> getTopItemsResponseByCategory(Category category, int limit) {
List<ItemTopRank> topItems;
if (category == Category.ALL) {
topItems = itemTopRankRepository.findTopItems(PageRequest.of(0, limit));
topItems = itemTopRankRepository.findTopItems(PageRequest.of(FIRST_PAGE, limit));
} else {
topItems = itemTopRankRepository.findTopItemsByCategory(category, PageRequest.of(0, limit));
topItems = itemTopRankRepository.findTopItemsByCategory(category, PageRequest.of(FIRST_PAGE, limit));
}
return convertToTopResponse(topItems);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.ward.ward_server.api.item.webCrawler;

import com.ward.ward_server.api.item.dto.WebProductData;
import com.ward.ward_server.global.config.CrawlerConfig;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
Expand All @@ -27,8 +28,8 @@ public class KasinaWebCrawler {
private WebDriver driver;

@Autowired
public KasinaWebCrawler(CrawlerProperties crawlerProperties) {
String chromeDriverPath = crawlerProperties.getChromeDriverPath();
public KasinaWebCrawler(CrawlerConfig crawlerConfig) {
String chromeDriverPath = crawlerConfig.getChromeDriverPath();
ChromeOptions chromeOptions = new ChromeOptions();
// chromeOptions.setBinary("/usr/bin/google-chrome"); // EC2 쓸 때 해제
chromeOptions.addArguments("--headless"); //헤드리스 모드로 실행, 실제 창이 표시되지 않는다.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.ward.ward_server.api.item.webCrawler;

import com.ward.ward_server.api.item.dto.WebProductData;
import com.ward.ward_server.global.config.CrawlerConfig;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
Expand All @@ -24,8 +25,8 @@ public class NikeWebCrawler {
private WebDriver driver;

@Autowired
public NikeWebCrawler(CrawlerProperties crawlerProperties) {
String chromeDriverPath = crawlerProperties.getChromeDriverPath();
public NikeWebCrawler(CrawlerConfig crawlerConfig) {
String chromeDriverPath = crawlerConfig.getChromeDriverPath();
ChromeOptions chromeOptions = new ChromeOptions();
// chromeOptions.setBinary("/usr/bin/google-chrome"); // EC2 쓸 때 해제
chromeOptions.addArguments("--headless"); //헤드리스 모드로 실행, 실제 창이 표시되지 않는다.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class ReleaseInfoService {
private final ReleaseInfoRepository releaseInfoRepository;
private final DrawPlatformRepository drawPlatformRepository;
Expand Down Expand Up @@ -70,21 +71,18 @@ public ReleaseInfoDetailResponse createReleaseInfo(Long itemId, String platformN
return getDetailResponse(item.getBrand(), item, platform, savedReleaseInfo);
}

@Transactional(readOnly = true)
public ReleaseInfoDetailResponse getReleaseInfo(Long releaseInfoId) {
ReleaseInfo releaseInfo = releaseInfoRepository.findById(releaseInfoId).orElseThrow(() -> new ApiException(RELEASE_INFO_NOT_FOUND));
return getDetailResponse(releaseInfo.getItem().getBrand(), releaseInfo.getItem(), releaseInfo.getDrawPlatform(), releaseInfo);
}

@Transactional(readOnly = true)
public List<ReleaseInfoSimpleResponse> getReleaseInfo10List(Long userId, Section section, Category category) {
return switch (section){
case DUE_TODAY, RELEASE_WISH, REGISTER_TODAY -> releaseInfoRepository.getReleaseInfo10List(userId, LocalDateTime.now().minusHours(9), category, section); //HACK DB 시간 설정 전까지는 -9시간으로 비교해야 한다.
default -> throw new ApiException(INVALID_INPUT, SECTION_NOT_AVAILABLE_THIS_PAGE.getMessage());
};
}

@Transactional(readOnly = true)
public PageResponse<ReleaseInfoSimpleResponse> getReleaseInfoPage(Long userId, Section section, Category category, int page) {
return switch (section){
case DUE_TODAY, RELEASE_NOW, REGISTER_TODAY ->{
Expand All @@ -95,14 +93,12 @@ public PageResponse<ReleaseInfoSimpleResponse> getReleaseInfoPage(Long userId, S
};
}

@Transactional(readOnly = true)
public Page<ReleaseInfo> getOngoingReleaseInfos(Long itemId, int page, int size) {
Item item = itemRepository.findById(itemId).orElseThrow(() -> new ApiException(ITEM_NOT_FOUND));
LocalDateTime now = LocalDateTime.now();
return releaseInfoRepository.findByItemAndDueDateAfter(item, now, PageRequest.of(page, size));
}

@Transactional(readOnly = true)
public Page<ReleaseInfo> getCompletedReleaseInfos(Long itemId, int page, int size) {
Item item = itemRepository.findById(itemId).orElseThrow(() -> new ApiException(ITEM_NOT_FOUND));
LocalDateTime now = LocalDateTime.now();
Expand Down Expand Up @@ -196,7 +192,6 @@ private ReleaseInfoDetailResponse getDetailResponse(Brand brand, Item item, Draw
releaseInfo.getNotificationMethod().getDesc(), releaseInfo.getReleaseMethod().getDesc(), releaseInfo.getDeliveryMethod().getDesc());
}

@Transactional(readOnly = true)
public List<ExpiringItemResponse> getExpiringItems(int limit) {
LocalDateTime now = LocalDateTime.now();
Pageable pageable = PageRequest.of(0, limit);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ public ApiResponse greeting(){

@GetMapping("/user/secured")
public ApiResponse secured(@AuthenticationPrincipal CustomUserDetails principal) {
String secured = "If you see this, then you're logged in as user " + principal.getEmail()
String secured = "User 권한으로 접근 성공 - " + principal.getEmail()
+ " User ID: " + principal.getUserId();
return ApiResponse.ok(secured);
}

@GetMapping("/admin")
public ApiResponse admin(@AuthenticationPrincipal CustomUserDetails principal) {
String admin = "If you see this, then you are an Admin. User ID: " + principal.getUserId();
String admin = "Admin 권한으로 접근 성공 - " + principal.getUserId();
return ApiResponse.ok(admin);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import jakarta.validation.constraints.NotBlank;

public record AddSocialLoginRequest(
@NotBlank(message = "Provider cannot be empty") String provider,
@NotBlank(message = "Provider ID cannot be empty") String providerId,
@Email(message = "Email should be valid") String email,
@NotBlank(message = "provider는 필수 항목입니다.") String provider,
@NotBlank(message = "providerId는 필수 항목입니다.") String providerId,
@Email(message = "유효한 이메일 주소를 입력해 주세요.") String email,
String appleRefreshToken
) {}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import jakarta.validation.constraints.NotBlank;

public record LoginRequest(
@NotBlank(message = "Provider cannot be empty") String provider,
@NotBlank(message = "Provider ID cannot be empty") String providerId,
@Email(message = "Email should be valid") String email
@NotBlank(message = "provider는 필수 항목입니다.") String provider,
@NotBlank(message = "providerId는 필수 항목입니다.") String providerId,
@Email(message = "유효한 이메일 주소를 입력해 주세요.") String email
) {}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,19 @@
import jakarta.validation.constraints.NotBlank;

public record RegisterRequest(
@NotBlank(message = "Provider cannot be empty") String provider,
@NotBlank(message = "Provider ID cannot be empty") String providerId,
@NotBlank(message = "Name cannot be empty") String name,
@Email(message = "Email should be valid") String email,
@NotBlank(message = "provider는 필수 항목입니다.") String provider,
@NotBlank(message = "providerId는 필수 항목입니다.") String providerId,
@NotBlank(message = "이름은 필수 항목입니다.") String name,
@Email(message = "유효한 이메일 주소를 입력해 주세요.") String email,
String appleRefreshToken,
@NotBlank(message = "Nickname cannot be empty") String nickname,
@NotBlank(message = "닉네임은 필수 항목입니다.") String nickname,
Boolean emailNotification,
Boolean appPushNotification,
Boolean snsNotification
) {}
) {
public RegisterRequest {
if (emailNotification == null) emailNotification = false;
if (appPushNotification == null) appPushNotification = false;
if (snsNotification == null) snsNotification = false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import jakarta.validation.constraints.NotBlank;

public record UserInfoUpdateRequest(
@NotBlank(message = "Provider cannot be empty") String provider,
@NotBlank(message = "Provider ID cannot be empty") String providerId,
@Email(message = "Email should be valid") String oldEmail,
@Email(message = "Email should be valid") String newEmail
@NotBlank(message = "provider는 필수 항목입니다.") String provider,
@NotBlank(message = "providerId는 필수 항목입니다.") String providerId,
@Email(message = "유효한 이전 이메일 주소를 입력해 주세요.") String oldEmail,
@Email(message = "유효한 새 이메일 주소를 입력해 주세요.") String newEmail
) {}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

@Service
@RequiredArgsConstructor
@Slf4j
Expand All @@ -19,43 +17,19 @@ public class AppleUserService {

private final SocialLoginRepository socialLoginRepository;

// @Transactional
// public void updateUserInfo(String provider, String providerId, String oldEmail, String newEmail) {
// // SocialLogin 테이블에서 사용자 정보를 찾습니다.
// Optional<SocialLogin> optionalSocialLogin = socialLoginRepository.findByProviderAndProviderIdAndEmail(provider, providerId, oldEmail);
//
// if (optionalSocialLogin.isPresent()) {
// // SocialLogin 정보를 통해 사용자 정보를 가져옵니다.
// SocialLogin socialLogin = optionalSocialLogin.get();
// User user = socialLogin.getUser();
//
// // 사용자 이메일 업데이트
// user.updateEmail(newEmail);
// log.info("사용자 정보 업데이트: {}", user);
//
// // 소셜 로그인 정보 이메일 업데이트
// socialLogin.updateEmail(newEmail);
// log.info("소셜 로그인 정보 업데이트: {}", socialLogin);
// } else {
// // SocialLogin 정보가 존재하지 않으면 로깅하여 알립니다.
// log.warn("해당 이메일을 가진 사용자를 찾을 수 없습니다: {}", oldEmail);
// }
// }
@Transactional
public void updateUserInfo(String provider, String providerId, String oldEmail, String newEmail) {
// SocialLogin 테이블에서 사용자 정보를 찾습니다.
Optional<SocialLogin> optionalSocialLogin = socialLoginRepository.findByProviderAndProviderIdAndEmail(provider, providerId, oldEmail);

if (optionalSocialLogin.isPresent()) {
// SocialLogin 정보를 통해 사용자 정보를 가져옵니다.
SocialLogin socialLogin = optionalSocialLogin.get();
socialLogin.updateEmail(newEmail);
// SocialLogin 테이블에서 사용자 정보를 찾고, 없으면 예외를 던집니다.
SocialLogin socialLogin = socialLoginRepository
.findByProviderAndProviderIdAndEmail(provider, providerId, oldEmail)
.orElseThrow(() -> {
log.warn("해당 이메일을 가진 사용자를 찾을 수 없습니다. Provider: {}, ProviderId: {}, OldEmail: {}", provider, providerId, oldEmail);
return new ApiException(ExceptionCode.NON_EXISTENT_EMAIL);
});

log.info("소셜 로그인 정보 업데이트: {}", socialLogin);
} else {
// SocialLogin 정보가 존재하지 않으면 로깅하여 알립니다.
log.warn("해당 이메일을 가진 사용자를 찾을 수 없습니다: {}", oldEmail);
throw new ApiException(ExceptionCode.NON_EXISTENT_EMAIL);
}
// 소셜 로그인 정보 이메일 업데이트
socialLogin.updateEmail(newEmail);
log.info("소셜 로그인 정보 업데이트: {}", socialLogin);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ private JwtTokens generateJwtTokens(User user) {
var accessToken = jwtIssuer.issueAccessToken(principal.getUserId(), principal.getEmail(), roles);
var refreshToken = jwtIssuer.issueRefreshToken();

refreshTokenService.saveRefreshToken(user, refreshToken);
refreshTokenService.saveNewRefreshToken(user, refreshToken);

return new JwtTokens(accessToken, refreshToken);
} catch (AuthenticationException e) {
Expand Down
Loading