mirror of
https://github.com/cna-bootcamp/lifesub.git
synced 2026-06-13 04:59:10 +00:00
release
This commit is contained in:
@@ -2,8 +2,14 @@ package com.unicorn.lifesub.mysub.infra;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
|
||||
|
||||
@SpringBootApplication
|
||||
@SpringBootApplication(
|
||||
scanBasePackages = {
|
||||
"com.unicorn.lifesub.mysub",
|
||||
"com.unicorn.lifesub.common"
|
||||
}
|
||||
)
|
||||
public class MySubApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(MySubApplication.class, args);
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
// File: lifesub/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/config/DataLoader.java
|
||||
package com.unicorn.lifesub.mysub.infra.config;
|
||||
|
||||
import com.unicorn.lifesub.mysub.infra.gateway.entity.CategoryEntity;
|
||||
import com.unicorn.lifesub.mysub.infra.gateway.entity.SubscriptionEntity;
|
||||
import com.unicorn.lifesub.mysub.infra.gateway.repository.CategoryJpaRepository;
|
||||
import com.unicorn.lifesub.mysub.infra.gateway.repository.SubscriptionJpaRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class DataLoader implements CommandLineRunner {
|
||||
|
||||
private final CategoryJpaRepository categoryRepository;
|
||||
private final SubscriptionJpaRepository subscriptionRepository;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void run(String... args) {
|
||||
if (categoryRepository.count() == 0) {
|
||||
loadCategories();
|
||||
}
|
||||
|
||||
if (subscriptionRepository.count() == 0) {
|
||||
loadSubscriptions();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadCategories() {
|
||||
log.info("Loading sample categories...");
|
||||
|
||||
List<CategoryEntity> categories = Arrays.asList(
|
||||
CategoryEntity.builder()
|
||||
.categoryId("OTT")
|
||||
.name("OTT/동영상")
|
||||
.build(),
|
||||
CategoryEntity.builder()
|
||||
.categoryId("MUSIC")
|
||||
.name("음악")
|
||||
.build(),
|
||||
CategoryEntity.builder()
|
||||
.categoryId("FOOD")
|
||||
.name("식품")
|
||||
.build(),
|
||||
CategoryEntity.builder()
|
||||
.categoryId("LIFE")
|
||||
.name("생활")
|
||||
.build(),
|
||||
CategoryEntity.builder()
|
||||
.categoryId("BEAUTY")
|
||||
.name("뷰티")
|
||||
.build(),
|
||||
CategoryEntity.builder()
|
||||
.categoryId("EDU")
|
||||
.name("교육")
|
||||
.build()
|
||||
);
|
||||
|
||||
categoryRepository.saveAll(categories);
|
||||
log.info("Sample categories loaded");
|
||||
}
|
||||
|
||||
private void loadSubscriptions() {
|
||||
log.info("Loading sample subscriptions...");
|
||||
|
||||
// 카테고리별 서비스 매핑
|
||||
Map<String, List<SubscriptionEntity>> subscriptionsByCategory = Map.of(
|
||||
"OTT", Arrays.asList(
|
||||
createSubscription("넷플릭스", "전세계 최대 OTT 서비스", "OTT", 17000, 4, "/images/netflix.png"),
|
||||
createSubscription("티빙", "국내 실시간 방송과 예능/드라마 VOD", "OTT", 13900, 4, "/images/tving.png"),
|
||||
createSubscription("디즈니플러스", "디즈니, 픽사, 마블, 스타워즈 콘텐츠", "OTT", 9900, 4, "/images/disney.png")
|
||||
),
|
||||
"MUSIC", Arrays.asList(
|
||||
createSubscription("멜론", "국내 최대 음원 스트리밍", "MUSIC", 10900, 1, "/images/melon.png"),
|
||||
createSubscription("스포티파이", "전세계 음악 스트리밍", "MUSIC", 10900, 6, "/images/spotify.png"),
|
||||
createSubscription("유튜브 뮤직", "유튜브 음원 스트리밍", "MUSIC", 8900, 5, "/images/youtube-music.png")
|
||||
),
|
||||
"FOOD", Arrays.asList(
|
||||
createSubscription("쿠팡이츠", "식품 정기배송", "FOOD", 4900, 1, "/images/coupang-eats.png"),
|
||||
createSubscription("마켓컬리", "신선식품 새벽배송", "FOOD", 4900, 1, "/images/kurly.png"),
|
||||
createSubscription("배민", "배달음식 구독", "FOOD", 5900, 1, "/images/baemin.png")
|
||||
),
|
||||
"LIFE", Arrays.asList(
|
||||
createSubscription("당근", "중고거래 프리미엄", "LIFE", 3900, 1, "/images/karrot.png"),
|
||||
createSubscription("쿠팡 로켓와우", "무료배송 구독", "LIFE", 4900, 4, "/images/coupang.png"),
|
||||
createSubscription("밀리의 서재", "전자책 구독", "LIFE", 9900, 1, "/images/millie.png")
|
||||
),
|
||||
"BEAUTY", Arrays.asList(
|
||||
createSubscription("올리브영", "뷰티 정기구독", "BEAUTY", 15900, 1, "/images/oliveyoung.png"),
|
||||
createSubscription("시코르", "화장품 구독박스", "BEAUTY", 29900, 1, "/images/chicor.png"),
|
||||
createSubscription("롭스", "뷰티 멤버십", "BEAUTY", 19900, 1, "/images/lohbs.png")
|
||||
),
|
||||
"EDU", Arrays.asList(
|
||||
createSubscription("클래스101", "취미/교양 클래스", "EDU", 19900, 1, "/images/class101.png"),
|
||||
createSubscription("탈잉", "원데이 클래스", "EDU", 29900, 1, "/images/taling.png"),
|
||||
createSubscription("캐치", "IT 실무 교육", "EDU", 99000, 1, "/images/catch.png")
|
||||
)
|
||||
);
|
||||
|
||||
// 모든 서비스 저장
|
||||
subscriptionsByCategory.values().stream()
|
||||
.flatMap(List::stream)
|
||||
.forEach(subscriptionRepository::save);
|
||||
|
||||
log.info("Sample subscriptions loaded");
|
||||
}
|
||||
|
||||
private SubscriptionEntity createSubscription(String name, String description, String category,
|
||||
int price, int maxSharedUsers, String logoUrl) {
|
||||
return SubscriptionEntity.builder()
|
||||
.name(name)
|
||||
.description(description)
|
||||
.category(category)
|
||||
.price(price)
|
||||
.maxSharedUsers(maxSharedUsers)
|
||||
.logoUrl(logoUrl)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -24,7 +24,7 @@ import java.util.List;
|
||||
public class SecurityConfig {
|
||||
protected final JwtTokenProvider jwtTokenProvider;
|
||||
|
||||
@Value("${allowedorigins}")
|
||||
@Value("${allowed-origins}")
|
||||
private String allowedOrigins;
|
||||
|
||||
public SecurityConfig(JwtTokenProvider jwtTokenProvider) {
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ import java.util.stream.Collectors;
|
||||
public class JwtTokenProvider {
|
||||
private final Algorithm algorithm;
|
||||
|
||||
public JwtTokenProvider(@Value("${jwt.secret}") String secretKey) {
|
||||
public JwtTokenProvider(@Value("${jwt.secret-key}") String secretKey) {
|
||||
this.algorithm = Algorithm.HMAC512(secretKey);
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -5,6 +5,7 @@ import com.unicorn.lifesub.mysub.biz.dto.CategoryResponse;
|
||||
import com.unicorn.lifesub.mysub.biz.dto.ServiceListResponse;
|
||||
import com.unicorn.lifesub.mysub.biz.usecase.in.CategoryUseCase;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -17,6 +18,7 @@ import java.util.List;
|
||||
|
||||
@Tag(name = "구독 카테고리 API", description = "구독 카테고리 관련 API")
|
||||
@RestController
|
||||
@SecurityRequirement(name = "bearerAuth") //이 어노테이션이 없으면 요청 헤더에 Authorization헤더가 안 생김
|
||||
@RequestMapping("/api/mysub")
|
||||
@RequiredArgsConstructor
|
||||
public class CategoryController {
|
||||
|
||||
+2
@@ -6,6 +6,7 @@ import com.unicorn.lifesub.mysub.biz.dto.TotalFeeResponse;
|
||||
import com.unicorn.lifesub.mysub.biz.usecase.in.MySubscriptionsUseCase;
|
||||
import com.unicorn.lifesub.mysub.biz.usecase.in.TotalFeeUseCase;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -15,6 +16,7 @@ import java.util.List;
|
||||
|
||||
@Tag(name = "마이구독 API", description = "마이구독 관련 API")
|
||||
@RestController
|
||||
@SecurityRequirement(name = "bearerAuth") //이 어노테이션이 없으면 요청 헤더에 Authorization헤더가 안 생김
|
||||
@RequestMapping("/api/mysub")
|
||||
@RequiredArgsConstructor
|
||||
public class MySubController {
|
||||
|
||||
+2
@@ -6,6 +6,7 @@ import com.unicorn.lifesub.mysub.biz.usecase.in.CancelSubscriptionUseCase;
|
||||
import com.unicorn.lifesub.mysub.biz.usecase.in.SubscribeUseCase;
|
||||
import com.unicorn.lifesub.mysub.biz.usecase.in.SubscriptionDetailUseCase;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -13,6 +14,7 @@ import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Tag(name = "구독 서비스 API", description = "구독 서비스 관련 API")
|
||||
@RestController
|
||||
@SecurityRequirement(name = "bearerAuth") //이 어노테이션이 없으면 요청 헤더에 Authorization헤더가 안 생김
|
||||
@RequestMapping("/api/mysub/services")
|
||||
@RequiredArgsConstructor
|
||||
public class ServiceController {
|
||||
|
||||
+6
-6
@@ -1,14 +1,14 @@
|
||||
package com.unicorn.lifesub.mysub.infra.adapter;
|
||||
package com.unicorn.lifesub.mysub.infra.gateway;
|
||||
|
||||
import com.unicorn.lifesub.common.exception.BusinessException;
|
||||
import com.unicorn.lifesub.common.exception.ErrorCode;
|
||||
import com.unicorn.lifesub.mysub.biz.domain.MySubscription;
|
||||
import com.unicorn.lifesub.mysub.biz.usecase.out.MySubscriptionReader;
|
||||
import com.unicorn.lifesub.mysub.biz.usecase.out.MySubscriptionWriter;
|
||||
import com.unicorn.lifesub.mysub.infra.entity.MySubscriptionEntity;
|
||||
import com.unicorn.lifesub.mysub.infra.entity.SubscriptionEntity;
|
||||
import com.unicorn.lifesub.mysub.infra.repository.MySubscriptionJpaRepository;
|
||||
import com.unicorn.lifesub.mysub.infra.repository.SubscriptionJpaRepository;
|
||||
import com.unicorn.lifesub.mysub.infra.gateway.entity.MySubscriptionEntity;
|
||||
import com.unicorn.lifesub.mysub.infra.gateway.entity.SubscriptionEntity;
|
||||
import com.unicorn.lifesub.mysub.infra.gateway.repository.MySubscriptionJpaRepository;
|
||||
import com.unicorn.lifesub.mysub.infra.gateway.repository.SubscriptionJpaRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -18,7 +18,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class MySubscriptionAdapter implements MySubscriptionReader, MySubscriptionWriter {
|
||||
public class MySubscriptionGateway implements MySubscriptionReader, MySubscriptionWriter {
|
||||
private final MySubscriptionJpaRepository mySubscriptionRepository;
|
||||
private final SubscriptionJpaRepository subscriptionRepository;
|
||||
|
||||
+6
-8
@@ -1,14 +1,12 @@
|
||||
package com.unicorn.lifesub.mysub.infra.adapter;
|
||||
package com.unicorn.lifesub.mysub.infra.gateway;
|
||||
|
||||
import com.unicorn.lifesub.common.exception.BusinessException;
|
||||
import com.unicorn.lifesub.common.exception.ErrorCode;
|
||||
import com.unicorn.lifesub.mysub.biz.domain.Subscription;
|
||||
import com.unicorn.lifesub.mysub.biz.domain.Category;
|
||||
import com.unicorn.lifesub.mysub.biz.usecase.out.SubscriptionReader;
|
||||
import com.unicorn.lifesub.mysub.infra.entity.SubscriptionEntity;
|
||||
import com.unicorn.lifesub.mysub.infra.entity.CategoryEntity;
|
||||
import com.unicorn.lifesub.mysub.infra.repository.SubscriptionJpaRepository;
|
||||
import com.unicorn.lifesub.mysub.infra.repository.CategoryJpaRepository;
|
||||
import com.unicorn.lifesub.mysub.infra.gateway.entity.SubscriptionEntity;
|
||||
import com.unicorn.lifesub.mysub.infra.gateway.entity.CategoryEntity;
|
||||
import com.unicorn.lifesub.mysub.infra.gateway.repository.SubscriptionJpaRepository;
|
||||
import com.unicorn.lifesub.mysub.infra.gateway.repository.CategoryJpaRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -18,7 +16,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class SubscriptionAdapter implements SubscriptionReader {
|
||||
public class SubscriptionGateway implements SubscriptionReader {
|
||||
private final SubscriptionJpaRepository subscriptionRepository;
|
||||
private final CategoryJpaRepository categoryRepository;
|
||||
|
||||
+2
-2
@@ -1,13 +1,13 @@
|
||||
package com.unicorn.lifesub.mysub.infra.entity;
|
||||
package com.unicorn.lifesub.mysub.infra.gateway.entity;
|
||||
|
||||
import com.unicorn.lifesub.common.entity.BaseTimeEntity;
|
||||
import com.unicorn.lifesub.mysub.biz.domain.Category;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.Id;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
@Entity
|
||||
@Table(name = "categories")
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.unicorn.lifesub.mysub.infra.entity;
|
||||
package com.unicorn.lifesub.mysub.infra.gateway.entity;
|
||||
|
||||
import com.unicorn.lifesub.mysub.biz.domain.MySubscription;
|
||||
import jakarta.persistence.*;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.unicorn.lifesub.mysub.infra.entity;
|
||||
package com.unicorn.lifesub.mysub.infra.gateway.entity;
|
||||
|
||||
import com.unicorn.lifesub.common.entity.BaseTimeEntity;
|
||||
import com.unicorn.lifesub.mysub.biz.domain.Subscription;
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
package com.unicorn.lifesub.mysub.infra.repository;
|
||||
package com.unicorn.lifesub.mysub.infra.gateway.repository;
|
||||
|
||||
import com.unicorn.lifesub.mysub.infra.entity.CategoryEntity;
|
||||
import com.unicorn.lifesub.mysub.infra.gateway.entity.CategoryEntity;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface CategoryJpaRepository extends JpaRepository<CategoryEntity, String> {
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
package com.unicorn.lifesub.mysub.infra.repository;
|
||||
package com.unicorn.lifesub.mysub.infra.gateway.repository;
|
||||
|
||||
import com.unicorn.lifesub.mysub.infra.entity.MySubscriptionEntity;
|
||||
import com.unicorn.lifesub.mysub.infra.gateway.entity.MySubscriptionEntity;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import java.util.List;
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
package com.unicorn.lifesub.mysub.infra.repository;
|
||||
package com.unicorn.lifesub.mysub.infra.gateway.repository;
|
||||
|
||||
import com.unicorn.lifesub.mysub.infra.entity.SubscriptionEntity;
|
||||
import com.unicorn.lifesub.mysub.infra.gateway.entity.SubscriptionEntity;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
@@ -9,21 +9,26 @@ spring:
|
||||
username: ${POSTGRES_USER:admin}
|
||||
password: ${POSTGRES_PASSWORD:Passw0rd}
|
||||
driver-class-name: org.postgresql.Driver
|
||||
# JPA 설정
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: ${JPA_DDL_AUTO:update}
|
||||
show-sql: ${JPA_SHOW_SQL:false}
|
||||
show-sql: ${JPA_SHOW_SQL:true}
|
||||
properties:
|
||||
hibernate:
|
||||
format_sql: true
|
||||
|
||||
allowedorigins: ${ALLOWED_ORIGINS:*}
|
||||
dialect: org.hibernate.dialect.PostgreSQLDialect
|
||||
|
||||
jwt:
|
||||
secret: ${JWT_SECRET:8O2HQ13etL2BWZvYOiWsJ5uWFoLi6NBUG8divYVoCgtHVvlk3dqRksMl16toztDUeBTSIuOOPvHIrYq11G2BwQ==}
|
||||
secret-key: ${JWT_SECRET_KEY:8O2HQ13etL2BWZvYOiWsJ5uWFoLi6NBUG8divYVoCgtHVvlk3dqRksMl16toztDUeBTSIuOOPvHIrYq11G2BwQ}
|
||||
|
||||
allowed-origins: ${ALLOWED_ORIGINS:*}
|
||||
|
||||
springdoc:
|
||||
swagger-ui:
|
||||
path: /swagger-ui.html
|
||||
api-docs:
|
||||
path: /api-docs
|
||||
|
||||
logging:
|
||||
level:
|
||||
com.unicorn: DEBUG
|
||||
org.hibernate.SQL: TRACE
|
||||
|
||||
Reference in New Issue
Block a user