mirror of
https://github.com/cna-bootcamp/lifesub.git
synced 2026-06-12 20:49:09 +00:00
release
This commit is contained in:
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1 @@
|
||||
com.unicorn.lifesub.mysub.infra.MySubApplication
|
||||
@@ -5,22 +5,30 @@ spring:
|
||||
application:
|
||||
name: mysub-service
|
||||
datasource:
|
||||
url: ${POSTGRES_URL}
|
||||
username: ${POSTGRES_USER}
|
||||
password: ${POSTGRES_PASSWORD}
|
||||
url: jdbc:postgresql://${POSTGRES_HOST:localhost}:${POSTGRES_PORT:5432}/${POSTGRES_DB:mysub}
|
||||
username: ${POSTGRES_USER:admin}
|
||||
password: ${POSTGRES_PASSWORD:Passw0rd}
|
||||
driver-class-name: org.postgresql.Driver
|
||||
# JPA 설정
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: ${JPA_DDL_AUTO:validate}
|
||||
show-sql: ${JPA_SHOW_SQL:false}
|
||||
ddl-auto: ${JPA_DDL_AUTO:update}
|
||||
show-sql: ${JPA_SHOW_SQL:true}
|
||||
properties:
|
||||
hibernate:
|
||||
format_sql: true
|
||||
dialect: org.hibernate.dialect.PostgreSQLDialect
|
||||
|
||||
allowedorigins: ${ALLOWED_ORIGINS:*}
|
||||
jwt:
|
||||
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
|
||||
|
||||
Binary file not shown.
@@ -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