Skip to content

Commit

Permalink
Merge branch 'kahluaband:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
yumzen authored Nov 11, 2024
2 parents cb7399d + f48da62 commit 5d2e32e
Show file tree
Hide file tree
Showing 21 changed files with 708 additions and 1 deletion.
4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ dependencies {
implementation 'software.amazon.awssdk:s3control:2.27.3'
implementation 'software.amazon.awssdk:s3outposts:2.27.3'


// Web Socket
implementation 'org.springframework.boot:spring-boot-starter-websocket'

//Webflux
implementation 'org.springframework.boot:spring-boot-starter-webflux'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,13 @@ public enum ErrorStatus implements BaseCode {
//지원하기 에러
ALREADY_EXIST_APPLICANT(HttpStatus.BAD_REQUEST, "ALREADY EXIST APPLICANT", "이미 존재하는 지원자입니다."),
APPLICANT_NOT_FOUND(HttpStatus.NOT_FOUND, "APPLICANT NOT FOUND", "존재하지 않는 지원자입니다."),
APPLY_INFO_NOT_FOUND(HttpStatus.NOT_FOUND, "APPLY INFO NOT FOUND", "존재하지 않는 지원정보 입니다." );
APPLY_INFO_NOT_FOUND(HttpStatus.NOT_FOUND, "APPLY INFO NOT FOUND", "존재하지 않는 지원정보 입니다." ),

// 웹소켓 에러
WEBSOCKET_SESSION_UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "WEBSOCKET SESSION UNAUTHORIZED", "웹소켓 연결에 실패했습니다."),

//게시판 에러
IMAGE_NOT_UPLOAD(HttpStatus.BAD_REQUEST, "IMAGE_NOT_UPLOAD", "이미지 업로드 개수를 초과하였습니다.");

private final HttpStatus httpStatus;
private final String code;
Expand Down
40 changes: 40 additions & 0 deletions src/main/java/kahlua/KahluaProject/config/WebSocketConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package kahlua.KahluaProject.config;

import kahlua.KahluaProject.websocket.StompHandler;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketTransportRegistration;

@EnableWebSocketMessageBroker
@Configuration
@RequiredArgsConstructor
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

private final StompHandler stompHandler; // STOMP 메세지 입출력 담당

@Override
public void registerStompEndpoints(StompEndpointRegistry registry) { // Web Socket 시작 endpoint 등록
registry.addEndpoint("/ws")
.setAllowedOrigins("http://localhost:8080", "http://kahluaband.com", "https://kahluaband.com", "http://localhost:3000",
"https://www.kahluaband.com/", "http://www.kahluaband.com/", "https://kahluabandver20-caminobelllos-projects.vercel.app",
"https://api.kahluaband.com/", "http://api.kahluaband.com/")
.withSockJS(); // Web Socket 지원하지 않는 브라우저에서도 웹 소켓 사용 가능
// ws, wss 대신 http, https를 통해 웹 소켓 연결하도록 함
}

@Override
public void configureMessageBroker(MessageBrokerRegistry registry) { // 메세지 브로커 설정
registry.setApplicationDestinationPrefixes("/app"); // 클라이언트가 서버로 전송하는 메세지의 경로 앞에 /app 붙임
registry.enableSimpleBroker("/topic"); // 메세지 브로커가 /topic 경로로 시작하는 메세지를 구독한 클라이언트들에게 보냄
}

@Override
public void configureClientInboundChannel(ChannelRegistration registration) { // 클라이언트로부터 들어오는 Web Socket 메세지 인터셉트
registration.interceptors(stompHandler);
}
}
34 changes: 34 additions & 0 deletions src/main/java/kahlua/KahluaProject/controller/PostController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package kahlua.KahluaProject.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import kahlua.KahluaProject.apipayload.ApiResponse;
import kahlua.KahluaProject.dto.post.request.PostCreateRequest;
import kahlua.KahluaProject.dto.post.response.PostCreateResponse;
import kahlua.KahluaProject.security.AuthDetails;
import kahlua.KahluaProject.service.PostService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@Tag(name = "게시판", description = "게시판 관련 API")
@RestController
@RequiredArgsConstructor
@RequestMapping("/v1/post")
public class PostController {

private final PostService postService;

@PostMapping("notice/create")
@Operation(summary = "공지사항 작성", description = "창립제, 악기 구비 등 깔루아 전체 공지 내용을 작성합니다.")
public ApiResponse<PostCreateResponse> createPost(@RequestBody PostCreateRequest postCreateRequest, @AuthenticationPrincipal AuthDetails authDetails) {
PostCreateResponse postCreateResponse = postService.createPost(postCreateRequest, authDetails.user());
return ApiResponse.onSuccess(postCreateResponse);
}


}
59 changes: 59 additions & 0 deletions src/main/java/kahlua/KahluaProject/converter/PostConverter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package kahlua.KahluaProject.converter;

import kahlua.KahluaProject.domain.post.Post;
import kahlua.KahluaProject.domain.post.PostImage;
import kahlua.KahluaProject.domain.user.User;
import kahlua.KahluaProject.dto.post.request.PostCreateRequest;
import kahlua.KahluaProject.dto.post.request.PostImageCreateRequest;
import kahlua.KahluaProject.dto.post.response.PostCreateResponse;
import kahlua.KahluaProject.dto.post.response.PostImageCreateResponse;

import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class PostConverter {

public static Post toPost(PostCreateRequest postCreateRequest) {
return Post.builder()
.title(postCreateRequest.getTitle())
.content(postCreateRequest.getContent())
.build();
}

public static PostCreateResponse toPostCreateResponse(Post post, User user, List<PostImageCreateResponse> imageUrls) {
return PostCreateResponse.builder()
.id(post.getId())
.title(post.getTitle())
.content(post.getContent())
.writer(user.getEmail())
.likes(post.getLikes())
.imageUrls(imageUrls)
.created_at(post.getCreatedAt())
.created_at(post.getUpdatedAt())
.build();
}

public static List<PostImage> toPostImage(List<PostImageCreateRequest> postImageCreateRequests, Post post) {
return Optional.ofNullable(postImageCreateRequests)
.orElse(Collections.emptyList())
.stream()
.map((PostImageCreateRequest imageRequest) -> PostImage.builder()
.url(imageRequest.getUrl())
.post(post)
.build())
.collect(Collectors.toList());
}

public static List<PostImageCreateResponse> toPostImageCreateResponse(List<PostImage> postImage) {
List<PostImageCreateResponse> imageUrlResponses = postImage.stream()
.map(postImage1 -> PostImageCreateResponse.builder()
.id(postImage1.getId())
.url(postImage1.getUrl())
.build())
.collect(Collectors.toList());

return imageUrlResponses;
}
}
46 changes: 46 additions & 0 deletions src/main/java/kahlua/KahluaProject/domain/post/Comment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package kahlua.KahluaProject.domain.post;

import jakarta.persistence.*;
import kahlua.KahluaProject.domain.BaseEntity;
import kahlua.KahluaProject.domain.user.User;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;

@Entity
@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "comment")
public class Comment extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "comment_id")
private Long id;

@Column(nullable = false)
private String content;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "post_id")
private Post post;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;

// 부모 댓글
@ManyToOne
@JoinColumn(name = "parent_comment_id")
private Comment parentComment;

// 자식 댓글
@OneToMany(mappedBy = "parentComment")
private List<Comment> childComments = new ArrayList<>();
}
51 changes: 51 additions & 0 deletions src/main/java/kahlua/KahluaProject/domain/post/Post.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package kahlua.KahluaProject.domain.post;

import jakarta.persistence.*;
import kahlua.KahluaProject.domain.BaseEntity;
import kahlua.KahluaProject.domain.user.User;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.ColumnDefault;

import java.util.ArrayList;
import java.util.List;

@Entity
@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "post")
public class Post extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="post_id")
private Long id;

@Column(nullable = false)
private String title;

@Column(nullable = false)
private String content;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;

@ColumnDefault("0")
private int likes; // likes 필드와 연결 필요

@OneToMany(mappedBy = "post", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<PostImage> ImageUrls = new ArrayList<>();

@OneToMany(mappedBy = "post", cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
private List<Comment> comments = new ArrayList<>();

public void addImage(PostImage postImage) {
postImage = new PostImage(postImage.getUrl(), this);
ImageUrls.add(postImage);
}
}
33 changes: 33 additions & 0 deletions src/main/java/kahlua/KahluaProject/domain/post/PostImage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package kahlua.KahluaProject.domain.post;

import jakarta.persistence.*;
import kahlua.KahluaProject.domain.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor
@Table(name = "postImages")
public class PostImage extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="image_id")
private Long id;

@Column(nullable = false)
private String url;

@ManyToOne
@JoinColumn(name = "post_id", nullable = false)
private Post post;

@Builder
public PostImage(String url, Post post) {
this.url = url;
this.post = post;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package kahlua.KahluaProject.dto.post.request;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Service;

@Getter
@AllArgsConstructor
@NoArgsConstructor
public class CommentsCreateRequest {

@Schema(description = "댓글 내용", example = "감사합니다.")
private String content;

@Schema(description = "대댓글인 경우 부모 댓글 id", example = "네 수고하세요.")
private Long parentCommentId;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package kahlua.KahluaProject.dto.post.request;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.List;

@Getter
@AllArgsConstructor
@NoArgsConstructor
public class PostCreateRequest {

@Schema(description = "게시글 제목", example = "2024년 9월 정기공연")
private String title;

@Schema(description = "게시글 내용", example = "안녕하세요 깔루아 기장입니다. 감사합니다.")
private String content;

@Schema(description = "게시글 사진 리스트", example = "https://bucketname.s3.region.amazonaws.com/image1.jpg")
private List<PostImageCreateRequest> imageUrls;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package kahlua.KahluaProject.dto.post.request;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@AllArgsConstructor
@NoArgsConstructor
public class PostImageCreateRequest {

@Schema(description = "image url")
private String url;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package kahlua.KahluaProject.dto.post.response;

import io.swagger.v3.oas.annotations.media.Schema;
import kahlua.KahluaProject.domain.post.PostImage;
import lombok.Builder;
import lombok.Getter;

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

@Getter
@Builder
public class PostCreateResponse {

@Schema(description = "아이디(번호)", example = "1")
private Long id;

@Schema(description = "게시글 제목", example = "2024년 9월 정기공연")
private String title;

@Schema(description = "게시글 내용", example = "안녕하세요 깔루아 기장입니다. 감사합니다.")
private String content;

@Schema(description = "게시글 작성자", example = "관리자")
private String writer;

@Schema(description = "게시글 좋아요 수", example = "13")
private int likes;

@Schema(description = "게시글 사진 리스트", example = "https://bucketname.s3.region.amazonaws.com/image1.jpg")
private List<PostImageCreateResponse> imageUrls;

@Schema(description = "작성한 날짜", example = "2024-08-01T00:00:00")
private LocalDateTime created_at;

@Schema(description = "수정한 날짜", example = "2024-08-10T00:00:00")
private LocalDateTime updated_at;
}
Loading

0 comments on commit 5d2e32e

Please sign in to comment.