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
20 changes: 16 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,38 @@ configurations {

repositories {
mavenCentral()
// IPFS HTTP Client Library (JitPack)
maven { url 'https://jitpack.io' }
}

dependencies {
// Spring Boot
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'

// Security
implementation 'org.springframework.boot:spring-boot-starter-security'
testImplementation 'org.springframework.security:spring-security-test'

//JWT
// JWT
implementation 'io.jsonwebtoken:jjwt-api:0.12.5'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.5'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.5'

// OpenAPI (Swagger)
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.9'

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
// DB (MySQL)
implementation 'mysql:mysql-connector-java:8.0.33'

// Lombok
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'

// IPFS HTTP Client Library
implementation 'com.github.ipfs:java-ipfs-http-client:1.4.1'

// Test
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
Expand All @@ -56,4 +68,4 @@ bootJar {

jar {
enabled = false
}
}
3 changes: 3 additions & 0 deletions src/main/java/com/dasom/MemoReal/MemoRealApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@SpringBootApplication
// createAt, updatedAt 자동 빌드를 위한 어노테이션
@EnableJpaAuditing
public class MemoRealApplication {

public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.dasom.MemoReal.domain.capsule.controller;

import com.dasom.MemoReal.domain.capsule.dto.CapsuleDto.CapsuleRequestDto;
import com.dasom.MemoReal.domain.capsule.dto.CapsuleDto.CapsuleResponseDto;
import com.dasom.MemoReal.domain.capsule.service.CapsuleService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/capsules")
public class CapsuleController {

private final CapsuleService capsuleService;

@PostMapping
public ResponseEntity<CapsuleResponseDto> createCapsule(
@RequestBody CapsuleRequestDto requestDto
) {
CapsuleResponseDto responseDto = capsuleService.createCapsule(requestDto);
return ResponseEntity.status(HttpStatus.CREATED).body(responseDto);
}

@GetMapping("/{id}")
public ResponseEntity<CapsuleResponseDto> getCapsuleById(@PathVariable("id") Long id) {
CapsuleResponseDto responseDto = capsuleService.getCapsule(id);
return ResponseEntity.ok(responseDto);
}

@GetMapping
public ResponseEntity<List<CapsuleResponseDto>> getAllCapsules() {
List<CapsuleResponseDto> capsules = capsuleService.getAllCapsules();
return ResponseEntity.ok(capsules);
}

@PutMapping("/{id}")
public ResponseEntity<CapsuleResponseDto> updateCapsule(
@PathVariable("id") Long id,
@RequestBody CapsuleRequestDto requestDto
) {
CapsuleResponseDto responseDto = capsuleService.updateCapsule(id, requestDto);
return ResponseEntity.ok(responseDto);
}

@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteCapsule(@PathVariable("id") Long id) {
capsuleService.deleteCapsule(id);
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.dasom.MemoReal.domain.capsule.dto;

import com.dasom.MemoReal.domain.user.dto.UserDTO;
import com.dasom.MemoReal.domain.capsule.entity.Capsule;
import com.dasom.MemoReal.domain.capsule.entity.Media;
import com.dasom.MemoReal.domain.capsule.type.CapsuleType;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

public class CapsuleDto {

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class CapsuleRequestDto {
private String title;
private CapsuleType type;
private String content;
private LocalDate openDate;

public Capsule toEntity() {
return Capsule.builder()
.title(title)
.type(type)
.content(content)
.openDate(openDate)
.build();
}
}

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class CapsuleResponseDto {
private Long id;
private String title;
private CapsuleType type;
private String content;
private LocalDate openDate;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
private List<MediaDto> medias;

private UserDTO user; // 회원 정보 추가

public static CapsuleResponseDto toDto(Capsule capsule) {
List<MediaDto> mediaDtos = capsule.getMedia().stream()
.map(MediaDto::toDto)
.collect(Collectors.toList());

return CapsuleResponseDto.builder()
.id(capsule.getId())
.title(capsule.getTitle())
.type(capsule.getType())
.content(capsule.getContent())
.openDate(capsule.getOpenDate())
.createdAt(capsule.getCreatedAt())
.updatedAt(capsule.getUpdatedAt())
.medias(mediaDtos)
.user(UserDTO.toDto(capsule.getUser())) // user 변환 후 세팅
.build();
}
}
}
28 changes: 28 additions & 0 deletions src/main/java/com/dasom/MemoReal/domain/capsule/dto/MediaDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.dasom.MemoReal.domain.capsule.dto;

import com.dasom.MemoReal.domain.capsule.entity.Media;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class MediaDto {

private Long id;
private String cid;
private String originalFileName;

public static MediaDto toDto(Media media) {
String cid = media.getCid();

return MediaDto.builder()
.id(media.getId())
.cid(cid)
.originalFileName(media.getOriginalFileName())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.dasom.MemoReal.domain.capsule.entity;

import com.dasom.MemoReal.domain.capsule.type.CapsuleType;
import com.dasom.MemoReal.domain.user.entity.User;
import jakarta.persistence.*;
import lombok.*;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(name = "capsule")
@EntityListeners(AuditingEntityListener.class)
public class Capsule {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String title;

@Enumerated(EnumType.STRING)
private CapsuleType type;

private String content;

@Column(nullable = false)
private LocalDate openDate;

@CreatedDate
@Column(updatable = false)
private LocalDateTime createdAt;

@LastModifiedDate
private LocalDateTime updatedAt;

@OneToMany(mappedBy = "capsule", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Media> media = new ArrayList<>();

// User 연동 추가 부분
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
private User user;

@Builder
public Capsule(String title, CapsuleType type, String content, LocalDate openDate, User user) {
this.title = title;
this.type = type;
this.content = content;
this.openDate = openDate;
this.user = user;
}

public void update(String title, CapsuleType type, String content, LocalDate openDate) {
this.title = title;
this.type = type;
this.content = content;
this.openDate = openDate;
}

public void addMedia(Media media) {
this.media.add(media);
media.setCapsule(this);
}

public void clearMedias() {
this.media.clear();
}

}
29 changes: 29 additions & 0 deletions src/main/java/com/dasom/MemoReal/domain/capsule/entity/Media.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.dasom.MemoReal.domain.capsule.entity;

import jakarta.persistence.*;
import lombok.*;

@Entity
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Media {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String cid; // IPFS CID
private String originalFileName;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "capsule_id")
private Capsule capsule;

@Builder
public Media(String cid, String originalFileName) {
this.cid = cid;
this.originalFileName = originalFileName;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.dasom.MemoReal.domain.capsule.repository;

import com.dasom.MemoReal.domain.capsule.entity.Capsule;
import com.dasom.MemoReal.domain.user.entity.User; // User 엔티티 import
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository // 스프링 빈으로 등록
public interface CapsuleRepository extends JpaRepository<Capsule, Long> {
// JpaRepository를 상속받으면 save, findById, findAll, delete 등의 기본적인 CRUD 메서드가 자동으로 제공됩니다.
// 추가적인 쿼리 메서드가 필요하다면 여기에 선언할 수 있습니다.

// 특정 User에 속하는 모든 Capsule을 조회하기 위한 메서드 추가
// Spring Data JPA가 메서드 이름 규칙에 따라 자동으로 쿼리를 생성합니다.
List<Capsule> findByUser(User user);
}
Loading