mirror of
https://github.com/cna-bootcamp/lifesub.git
synced 2026-06-12 20:49:09 +00:00
release
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
dependencies {
|
||||
implementation project(':common')
|
||||
implementation project(':mysub-biz')
|
||||
runtimeOnly 'org.postgresql:postgresql'
|
||||
}
|
||||
bootJar {
|
||||
archiveFileName = "mysub.jar"
|
||||
}
|
||||
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,26 @@
|
||||
server:
|
||||
port: ${SERVER_PORT:8082}
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: mysub-service
|
||||
datasource:
|
||||
url: ${POSTGRES_URL}
|
||||
username: ${POSTGRES_USER}
|
||||
password: ${POSTGRES_PASSWORD}
|
||||
driver-class-name: org.postgresql.Driver
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: ${JPA_DDL_AUTO:validate}
|
||||
show-sql: ${JPA_SHOW_SQL:false}
|
||||
properties:
|
||||
hibernate:
|
||||
format_sql: true
|
||||
|
||||
allowedorigins: ${ALLOWED_ORIGINS:*}
|
||||
|
||||
springdoc:
|
||||
swagger-ui:
|
||||
path: /swagger-ui.html
|
||||
api-docs:
|
||||
path: /api-docs
|
||||
Binary file not shown.
@@ -0,0 +1,11 @@
|
||||
package com.unicorn.lifesub.mysub.infra;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class MySubApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(MySubApplication.class, args);
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
package com.unicorn.lifesub.mysub.infra.adapter;
|
||||
|
||||
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 lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class MySubscriptionAdapter implements MySubscriptionReader, MySubscriptionWriter {
|
||||
private final MySubscriptionJpaRepository mySubscriptionRepository;
|
||||
private final SubscriptionJpaRepository subscriptionRepository;
|
||||
|
||||
@Override
|
||||
public List<MySubscription> findByUserId(String userId) {
|
||||
return mySubscriptionRepository.findByUserId(userId).stream()
|
||||
.map(MySubscriptionEntity::toDomain)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<MySubscription> findById(Long id) {
|
||||
return mySubscriptionRepository.findById(id)
|
||||
.map(MySubscriptionEntity::toDomain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MySubscription save(String userId, Long subscriptionId) {
|
||||
SubscriptionEntity subscription = subscriptionRepository.findById(subscriptionId)
|
||||
.orElseThrow(() -> new BusinessException(ErrorCode.SUBSCRIPTION_NOT_FOUND));
|
||||
|
||||
MySubscriptionEntity entity = MySubscriptionEntity.builder()
|
||||
.userId(userId)
|
||||
.subscription(subscription)
|
||||
.build();
|
||||
|
||||
return mySubscriptionRepository.save(entity).toDomain();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Long id) {
|
||||
mySubscriptionRepository.deleteById(id);
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package com.unicorn.lifesub.mysub.infra.adapter;
|
||||
|
||||
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 lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class SubscriptionAdapter implements SubscriptionReader {
|
||||
private final SubscriptionJpaRepository subscriptionRepository;
|
||||
private final CategoryJpaRepository categoryRepository;
|
||||
|
||||
@Override
|
||||
public Optional<Subscription> findById(Long id) {
|
||||
return subscriptionRepository.findById(id)
|
||||
.map(SubscriptionEntity::toDomain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Subscription> findByCategory(String categoryId) {
|
||||
return subscriptionRepository.findByCategory(categoryId).stream()
|
||||
.map(SubscriptionEntity::toDomain)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Category> findAllCategories() {
|
||||
return categoryRepository.findAll().stream()
|
||||
.map(CategoryEntity::toDomain)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.unicorn.lifesub.mysub.infra.config;
|
||||
|
||||
import com.unicorn.lifesub.mysub.infra.config.jwt.JwtAuthenticationFilter;
|
||||
import com.unicorn.lifesub.mysub.infra.config.jwt.JwtTokenProvider;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@SuppressWarnings("unused")
|
||||
public class SecurityConfig {
|
||||
protected final JwtTokenProvider jwtTokenProvider;
|
||||
|
||||
@Value("${allowedorigins}")
|
||||
private String allowedOrigins;
|
||||
|
||||
public SecurityConfig(JwtTokenProvider jwtTokenProvider) {
|
||||
this.jwtTokenProvider = jwtTokenProvider;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.cors(cors -> cors
|
||||
.configurationSource(corsConfigurationSource())
|
||||
)
|
||||
.csrf(AbstractHttpConfigurer::disable)
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers("/swagger-ui.html", "/swagger-ui/**", "/v3/api-docs.yaml", "/v3/api-docs/**").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.sessionManagement(session -> session
|
||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||
)
|
||||
.addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider), UsernamePasswordAuthenticationFilter.class);
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
protected CorsConfigurationSource corsConfigurationSource() {
|
||||
CorsConfiguration configuration = new CorsConfiguration();
|
||||
configuration.setAllowedOrigins(Arrays.asList(allowedOrigins.split(",")));
|
||||
configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
|
||||
configuration.setAllowedHeaders(List.of("*"));
|
||||
configuration.setAllowCredentials(true);
|
||||
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
source.registerCorsConfiguration("/**", configuration);
|
||||
return source;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.unicorn.lifesub.mysub.infra.config;
|
||||
|
||||
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityScheme;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.info.Info;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@SuppressWarnings("unused")
|
||||
@SecurityScheme(
|
||||
name = "bearerAuth",
|
||||
type = SecuritySchemeType.HTTP,
|
||||
bearerFormat = "JWT",
|
||||
scheme = "bearer"
|
||||
)
|
||||
public class SwaggerConfig {
|
||||
|
||||
@Bean
|
||||
public OpenAPI openAPI() {
|
||||
return new OpenAPI()
|
||||
.info(new Info()
|
||||
.title("마이구독 서비스 API")
|
||||
.version("v1.0.0")
|
||||
.description("마이구독 서비스 API 명세서입니다."));
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
// CommonJwtAuthenticationFilter.java
|
||||
package com.unicorn.lifesub.mysub.infra.config.jwt;
|
||||
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.NonNull;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
private final JwtTokenProvider jwtTokenProvider;
|
||||
|
||||
public JwtAuthenticationFilter(JwtTokenProvider jwtTokenProvider) {
|
||||
this.jwtTokenProvider = jwtTokenProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(@NonNull HttpServletRequest request,
|
||||
@NonNull HttpServletResponse response,
|
||||
@NonNull FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
String token = resolveToken(request);
|
||||
|
||||
if (token != null && jwtTokenProvider.validateToken(token)) {
|
||||
SecurityContextHolder.getContext().setAuthentication(jwtTokenProvider.getAuthentication(token));
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
private String resolveToken(HttpServletRequest request) {
|
||||
String bearerToken = request.getHeader("Authorization");
|
||||
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
|
||||
return bearerToken.substring(7);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
// CommonJwtTokenProvider.java
|
||||
package com.unicorn.lifesub.mysub.infra.config.jwt;
|
||||
|
||||
import com.auth0.jwt.JWT;
|
||||
import com.auth0.jwt.JWTVerifier;
|
||||
import com.auth0.jwt.algorithms.Algorithm;
|
||||
import com.auth0.jwt.exceptions.JWTVerificationException;
|
||||
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||
import com.unicorn.lifesub.common.exception.ErrorCode;
|
||||
import com.unicorn.lifesub.common.exception.InfraException;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class JwtTokenProvider {
|
||||
private final Algorithm algorithm;
|
||||
|
||||
public JwtTokenProvider(@Value("${jwt.secret}") String secretKey) {
|
||||
this.algorithm = Algorithm.HMAC512(secretKey);
|
||||
}
|
||||
|
||||
public Authentication getAuthentication(String token) {
|
||||
try {
|
||||
DecodedJWT decodedJWT = JWT.decode(token);
|
||||
String username = decodedJWT.getSubject();
|
||||
String[] authStrings = decodedJWT.getClaim("auth").asArray(String.class);
|
||||
Collection<? extends GrantedAuthority> authorities = Arrays.stream(authStrings)
|
||||
.map(SimpleGrantedAuthority::new)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
UserDetails userDetails = new User(username, "", authorities);
|
||||
|
||||
return new UsernamePasswordAuthenticationToken(userDetails, "", authorities);
|
||||
} catch (Exception e) {
|
||||
throw new InfraException(ErrorCode.INVALID_CREDENTIALS);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean validateToken(String token) {
|
||||
try {
|
||||
JWTVerifier verifier = JWT.require(algorithm).build();
|
||||
verifier.verify(token);
|
||||
return true;
|
||||
} catch (JWTVerificationException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package com.unicorn.lifesub.mysub.infra.controller;
|
||||
|
||||
import com.unicorn.lifesub.common.dto.ApiResponse;
|
||||
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.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "구독 카테고리 API", description = "구독 카테고리 관련 API")
|
||||
@RestController
|
||||
@RequestMapping("/api/mysub")
|
||||
@RequiredArgsConstructor
|
||||
public class CategoryController {
|
||||
private final CategoryUseCase categoryUseCase;
|
||||
|
||||
@Operation(summary = "전체 카테고리 목록 조회")
|
||||
@GetMapping("/categories")
|
||||
public ResponseEntity<ApiResponse<List<CategoryResponse>>> getAllCategories() {
|
||||
return ResponseEntity.ok(ApiResponse.success(categoryUseCase.getAllCategories()));
|
||||
}
|
||||
|
||||
@Operation(summary = "카테고리별 서비스 목록 조회")
|
||||
@GetMapping("/services")
|
||||
public ResponseEntity<ApiResponse<List<ServiceListResponse>>> getServicesByCategory(
|
||||
@RequestParam String categoryId) {
|
||||
return ResponseEntity.ok(ApiResponse.success(categoryUseCase.getServicesByCategory(categoryId)));
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package com.unicorn.lifesub.mysub.infra.controller;
|
||||
|
||||
import com.unicorn.lifesub.common.dto.ApiResponse;
|
||||
import com.unicorn.lifesub.mysub.biz.dto.MySubResponse;
|
||||
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.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "마이구독 API", description = "마이구독 관련 API")
|
||||
@RestController
|
||||
@RequestMapping("/api/mysub")
|
||||
@RequiredArgsConstructor
|
||||
public class MySubController {
|
||||
private final TotalFeeUseCase totalFeeUseCase;
|
||||
private final MySubscriptionsUseCase mySubscriptionsUseCase;
|
||||
|
||||
@Operation(summary = "총 구독료 조회", description = "사용자의 총 구독료를 조회합니다.")
|
||||
@GetMapping("/total-fee")
|
||||
public ResponseEntity<ApiResponse<TotalFeeResponse>> getTotalFee(@RequestParam String userId) {
|
||||
TotalFeeResponse response = totalFeeUseCase.getTotalFee(userId);
|
||||
return ResponseEntity.ok(ApiResponse.success(response));
|
||||
}
|
||||
|
||||
@Operation(summary = "구독 목록 조회", description = "사용자의 구독 서비스 목록을 조회합니다.")
|
||||
@GetMapping("/list")
|
||||
public ResponseEntity<ApiResponse<List<MySubResponse>>> getMySubscriptions(@RequestParam String userId) {
|
||||
List<MySubResponse> response = mySubscriptionsUseCase.getMySubscriptions(userId);
|
||||
return ResponseEntity.ok(ApiResponse.success(response));
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
package com.unicorn.lifesub.mysub.infra.controller;
|
||||
|
||||
import com.unicorn.lifesub.common.dto.ApiResponse;
|
||||
import com.unicorn.lifesub.mysub.biz.dto.SubDetailResponse;
|
||||
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.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Tag(name = "구독 서비스 API", description = "구독 서비스 관련 API")
|
||||
@RestController
|
||||
@RequestMapping("/api/mysub/services")
|
||||
@RequiredArgsConstructor
|
||||
public class ServiceController {
|
||||
private final SubscriptionDetailUseCase subscriptionDetailUseCase;
|
||||
private final SubscribeUseCase subscribeUseCase;
|
||||
private final CancelSubscriptionUseCase cancelSubscriptionUseCase;
|
||||
|
||||
@Operation(summary = "구독 서비스 상세 조회")
|
||||
@GetMapping("/{subscriptionId}")
|
||||
public ResponseEntity<ApiResponse<SubDetailResponse>> getSubscriptionDetail(
|
||||
@PathVariable Long subscriptionId) {
|
||||
return ResponseEntity.ok(ApiResponse.success(
|
||||
subscriptionDetailUseCase.getSubscriptionDetail(subscriptionId)));
|
||||
}
|
||||
|
||||
@Operation(summary = "구독 신청")
|
||||
@PostMapping("/{subscriptionId}/subscribe")
|
||||
public ResponseEntity<ApiResponse<Void>> subscribe(
|
||||
@PathVariable Long subscriptionId,
|
||||
@RequestParam String userId) {
|
||||
subscribeUseCase.subscribe(subscriptionId, userId);
|
||||
return ResponseEntity.ok(ApiResponse.success(null));
|
||||
}
|
||||
|
||||
@Operation(summary = "구독 취소")
|
||||
@DeleteMapping("/{subscriptionId}")
|
||||
public ResponseEntity<ApiResponse<Void>> cancel(
|
||||
@PathVariable Long subscriptionId) {
|
||||
cancelSubscriptionUseCase.cancel(subscriptionId);
|
||||
return ResponseEntity.ok(ApiResponse.success(null));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.unicorn.lifesub.mysub.infra.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 lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
@Entity
|
||||
@Table(name = "categories")
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
public class CategoryEntity extends BaseTimeEntity {
|
||||
@Id
|
||||
private String categoryId;
|
||||
private String name;
|
||||
|
||||
@Builder
|
||||
public CategoryEntity(String categoryId, String name) {
|
||||
this.categoryId = categoryId;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Category toDomain() {
|
||||
return Category.builder()
|
||||
.categoryId(categoryId)
|
||||
.name(name)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package com.unicorn.lifesub.mysub.infra.entity;
|
||||
|
||||
import com.unicorn.lifesub.mysub.biz.domain.MySubscription;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Entity
|
||||
@Table(name = "my_subscriptions")
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
public class MySubscriptionEntity {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String userId;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "subscription_id")
|
||||
private SubscriptionEntity subscription;
|
||||
|
||||
@Builder
|
||||
public MySubscriptionEntity(Long id, String userId, SubscriptionEntity subscription) {
|
||||
this.id = id;
|
||||
this.userId = userId;
|
||||
this.subscription = subscription;
|
||||
}
|
||||
|
||||
public MySubscription toDomain() {
|
||||
return MySubscription.builder()
|
||||
.id(id)
|
||||
.userId(userId)
|
||||
.subscription(subscription.toDomain())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package com.unicorn.lifesub.mysub.infra.entity;
|
||||
|
||||
import com.unicorn.lifesub.common.entity.BaseTimeEntity;
|
||||
import com.unicorn.lifesub.mysub.biz.domain.Subscription;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Entity
|
||||
@Table(name = "subscriptions")
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
public class SubscriptionEntity extends BaseTimeEntity {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
private String description;
|
||||
private String category;
|
||||
private int price;
|
||||
private int maxSharedUsers;
|
||||
private String logoUrl;
|
||||
|
||||
@Builder
|
||||
public SubscriptionEntity(Long id, String name, String description, String category,
|
||||
int price, int maxSharedUsers, String logoUrl) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.category = category;
|
||||
this.price = price;
|
||||
this.maxSharedUsers = maxSharedUsers;
|
||||
this.logoUrl = logoUrl;
|
||||
}
|
||||
|
||||
public Subscription toDomain() {
|
||||
return Subscription.builder()
|
||||
.id(id)
|
||||
.name(name)
|
||||
.description(description)
|
||||
.category(category)
|
||||
.price(price)
|
||||
.maxSharedUsers(maxSharedUsers)
|
||||
.logoUrl(logoUrl)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package com.unicorn.lifesub.mysub.infra.repository;
|
||||
|
||||
import com.unicorn.lifesub.mysub.infra.entity.CategoryEntity;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface CategoryJpaRepository extends JpaRepository<CategoryEntity, String> {
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.unicorn.lifesub.mysub.infra.repository;
|
||||
|
||||
import com.unicorn.lifesub.mysub.infra.entity.MySubscriptionEntity;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import java.util.List;
|
||||
|
||||
public interface MySubscriptionJpaRepository extends JpaRepository<MySubscriptionEntity, Long> {
|
||||
List<MySubscriptionEntity> findByUserId(String userId);
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package com.unicorn.lifesub.mysub.infra.repository;
|
||||
|
||||
import com.unicorn.lifesub.mysub.infra.entity.SubscriptionEntity;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
// SubscriptionJpaRepository.java에 메서드 추가
|
||||
public interface SubscriptionJpaRepository extends JpaRepository<SubscriptionEntity, Long> {
|
||||
List<SubscriptionEntity> findByCategory(String category);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
server:
|
||||
port: ${SERVER_PORT:8082}
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: mysub-service
|
||||
datasource:
|
||||
url: jdbc:postgresql://${POSTGRES_HOST:localhost}:${POSTGRES_PORT:5432}/${POSTGRES_DB:mysub}
|
||||
username: ${POSTGRES_USER:postgres}
|
||||
password: ${POSTGRES_PASSWORD:postgres}
|
||||
driver-class-name: org.postgresql.Driver
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: ${JPA_DDL_AUTO:validate}
|
||||
show-sql: ${JPA_SHOW_SQL:false}
|
||||
properties:
|
||||
hibernate:
|
||||
format_sql: true
|
||||
|
||||
allowedorigins: ${ALLOWED_ORIGINS:*}
|
||||
|
||||
springdoc:
|
||||
swagger-ui:
|
||||
path: /swagger-ui.html
|
||||
api-docs:
|
||||
path: /api-docs
|
||||
Reference in New Issue
Block a user