diff --git a/.gitignore b/.gitignore index 1ad9c4d..610082a 100644 --- a/.gitignore +++ b/.gitignore @@ -108,4 +108,6 @@ hs_err_pid* # mac .DS_Store -src/main/resources/application.yml +.idea/workspace.xml +.idea/workspace.xml +.idea/workspace.xml diff --git a/.idea/dataSources.local.xml b/.idea/dataSources.local.xml new file mode 100644 index 0000000..f7cf746 --- /dev/null +++ b/.idea/dataSources.local.xml @@ -0,0 +1,20 @@ + + + + + + #@ + ` + true + + + master_key + root + + + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index d8d6635..b86ed64 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,6 @@ plugins { id 'java' + id 'war' id 'org.springframework.boot' version '3.2.5' id 'io.spring.dependency-management' version '1.1.4' } @@ -34,6 +35,10 @@ dependencies { implementation 'io.jsonwebtoken:jjwt-impl:0.11.5' implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5' + implementation 'org.springframework.boot:spring-boot-starter-websocket' + implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' + implementation 'com.amazonaws:aws-java-sdk-s3:1.12.265' + implementation 'software.amazon.ion:ion-java:1.0.3' developmentOnly 'org.springframework.boot:spring-boot-devtools' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.mysql:mysql-connector-j' @@ -41,6 +46,7 @@ dependencies { testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat' } tasks.named('test') { diff --git a/src/main/java/meltingpot/server/ServerApplication.java b/src/main/java/meltingpot/server/ServerApplication.java index 56b5843..48816d5 100644 --- a/src/main/java/meltingpot/server/ServerApplication.java +++ b/src/main/java/meltingpot/server/ServerApplication.java @@ -2,11 +2,18 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; @SpringBootApplication @EnableJpaAuditing -public class ServerApplication { +public class ServerApplication extends SpringBootServletInitializer { + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(ServerApplication.class); + } public static void main(String[] args) { SpringApplication.run(ServerApplication.class, args); diff --git a/src/main/java/meltingpot/server/chat/controller/ChatController.java b/src/main/java/meltingpot/server/chat/controller/ChatController.java new file mode 100644 index 0000000..874670b --- /dev/null +++ b/src/main/java/meltingpot/server/chat/controller/ChatController.java @@ -0,0 +1,26 @@ +package meltingpot.server.chat.controller; + +import lombok.RequiredArgsConstructor; +import meltingpot.server.chat.dto.ChatMessageCreateResponse; +import meltingpot.server.chat.dto.ChatMessageCreateRequest; +import meltingpot.server.chat.service.ChatService; +import org.springframework.messaging.handler.annotation.DestinationVariable; +import org.springframework.messaging.handler.annotation.MessageMapping; +import org.springframework.messaging.handler.annotation.Payload; +import org.springframework.messaging.handler.annotation.SendTo; +import org.springframework.stereotype.Controller; + +@Controller +@RequiredArgsConstructor +public class ChatController { + private final ChatService chatService; + + @MessageMapping("/chat/rooms/{chatRoomId}/send") // <- 해당 경로로 들어오면 메서드 호출 + @SendTo("/topic/public/rooms/{chatRoomId}") // 구독 중인 장소로 메세지 전달 + public ChatMessageCreateResponse sendMessage( + @DestinationVariable Long chatRoomId, + @Payload ChatMessageCreateRequest request) { + ChatMessageCreateResponse response = chatService.createChatMessage(chatRoomId, request); + return response; + } +} diff --git a/src/main/java/meltingpot/server/chat/controller/ChatRoomController.java b/src/main/java/meltingpot/server/chat/controller/ChatRoomController.java new file mode 100644 index 0000000..5d4a1b2 --- /dev/null +++ b/src/main/java/meltingpot/server/chat/controller/ChatRoomController.java @@ -0,0 +1,82 @@ +package meltingpot.server.chat.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import lombok.RequiredArgsConstructor; +import meltingpot.server.chat.dto.*; +import meltingpot.server.chat.service.ChatRoomQueryService; +import meltingpot.server.chat.service.ChatRoomService; +import meltingpot.server.util.PageResponse; +import meltingpot.server.util.ResponseData; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static meltingpot.server.util.ResponseCode.SIGNIN_SUCCESS; + +@RestController +@RequestMapping("/api/v1/chatRooms") +@RequiredArgsConstructor +public class ChatRoomController { + private final ChatRoomQueryService chatRoomQueryService; + private final ChatRoomService chatRoomService; + + // [CHECK] /{userId}, PageResponse, param + @GetMapping("/{userId}") + @Operation(summary = "채팅방 전체 목록 조회") + @ApiResponse(responseCode = "100", description = "요청에 성공하였습니다.", content = @Content(mediaType = "application/json")) + @Parameter(name = "userId", description = "사용자 ID", required = true, example = "1") + public ResponseEntity>>> getChatRooms( + @PathVariable Long userId, + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "5") int size + ) { + return ResponseData.toResponseEntity(SIGNIN_SUCCESS, chatRoomQueryService.getChatRooms()); + } + + // [CHECK] /{userId} + @PatchMapping("/alarm/{chatRoomId}/{userId}") + @Operation(summary = "채팅방 알람 설정 변경") + @ApiResponse(responseCode = "1000", description = "요청에 성공하였습니다.", content = @Content(mediaType = "application/json")) + @Parameters({ + @Parameter(name = "chatRoomId", description = "채팅룸 ID", required = true, example = "1"), + @Parameter(name = "userId", description = "사용자 ID", required = true, example = "1") + }) + public ResponseEntity updateAlarmStatus( + @PathVariable Long userId, + @PathVariable Long chatRoomId + ) { + chatRoomService.updateAlarmStatus(userId, chatRoomId); + return ResponseData.toResponseEntity(SIGNIN_SUCCESS); + } + + // [CHECK] PageResponse + @GetMapping("{chatRoomId}") + @Operation(summary = "채팅방 채팅 내역 조회") + @ApiResponse(responseCode = "1000", description = "요청에 성공하였습니다.", content = @Content(mediaType = "application/json")) + @Parameter(name = "chatRoomId", description = "채팅룸 ID", required = true, example = "1") + public ResponseEntity>>> getChatMessage( + @PathVariable Long chatRoomId, + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "5") int size + ) { + ChatMessageListQuery query = ChatMessageListQuery.builder() + .chatRoomId(chatRoomId) + .page(page) + .size(size) + .build(); + return ResponseData.toResponseEntity(SIGNIN_SUCCESS, chatRoomQueryService.getChatMessage(query)); + } + + @GetMapping("{chatRoomId}/detail") + @Operation(summary = "채팅방 상단") + @ApiResponse(responseCode = "1000", description = "요청에 성공하였습니다.", content = @Content(mediaType = "application/json")) + @Parameter(description = "채팅룸 ID", required = true, example = "1") + public ResponseEntity> getChatRoomDetail(@PathVariable Long chatRoomId) { + return ResponseData.toResponseEntity(SIGNIN_SUCCESS, chatRoomQueryService.getRoomDetail(chatRoomId)); + } +} diff --git a/src/main/java/meltingpot/server/chat/dto/ChatMessageCreateRequest.java b/src/main/java/meltingpot/server/chat/dto/ChatMessageCreateRequest.java new file mode 100644 index 0000000..031955a --- /dev/null +++ b/src/main/java/meltingpot/server/chat/dto/ChatMessageCreateRequest.java @@ -0,0 +1,8 @@ +package meltingpot.server.chat.dto; + +public record ChatMessageCreateRequest( + Long userId, + String content, + Long chatRoomId +) { +} diff --git a/src/main/java/meltingpot/server/chat/dto/ChatMessageCreateResponse.java b/src/main/java/meltingpot/server/chat/dto/ChatMessageCreateResponse.java new file mode 100644 index 0000000..9943957 --- /dev/null +++ b/src/main/java/meltingpot/server/chat/dto/ChatMessageCreateResponse.java @@ -0,0 +1,9 @@ +package meltingpot.server.chat.dto; + +import lombok.Builder; + +@Builder +public record ChatMessageCreateResponse( + Long chatId +) { +} diff --git a/src/main/java/meltingpot/server/chat/dto/ChatMessageGetResponse.java b/src/main/java/meltingpot/server/chat/dto/ChatMessageGetResponse.java new file mode 100644 index 0000000..dd7d69a --- /dev/null +++ b/src/main/java/meltingpot/server/chat/dto/ChatMessageGetResponse.java @@ -0,0 +1,19 @@ +package meltingpot.server.chat.dto; + +import meltingpot.server.domain.entity.chat.ChatMessage; +import meltingpot.server.domain.entity.chat.enums.Role; +import org.springframework.data.domain.Slice; + +public record ChatMessageGetResponse( + Long chatId, + String content, + Role role +) { + public static ChatMessageGetResponse from(ChatMessage chatMessage) { + return new ChatMessageGetResponse( + chatMessage.getId(), + chatMessage.getContent(), + chatMessage.getRole() + ); + } +} diff --git a/src/main/java/meltingpot/server/chat/dto/ChatMessageListQuery.java b/src/main/java/meltingpot/server/chat/dto/ChatMessageListQuery.java new file mode 100644 index 0000000..2df5d93 --- /dev/null +++ b/src/main/java/meltingpot/server/chat/dto/ChatMessageListQuery.java @@ -0,0 +1,11 @@ +package meltingpot.server.chat.dto; + +import lombok.Builder; + +@Builder +public record ChatMessageListQuery( + Long chatRoomId, + int page, + int size +) { +} diff --git a/src/main/java/meltingpot/server/chat/dto/ChatRoomAlarmUpdateResponse.java b/src/main/java/meltingpot/server/chat/dto/ChatRoomAlarmUpdateResponse.java new file mode 100644 index 0000000..2892e00 --- /dev/null +++ b/src/main/java/meltingpot/server/chat/dto/ChatRoomAlarmUpdateResponse.java @@ -0,0 +1,6 @@ +package meltingpot.server.chat.dto; + +public record ChatRoomAlarmUpdateResponse( + String status +) { +} diff --git a/src/main/java/meltingpot/server/chat/dto/ChatRoomDetailGetResponse.java b/src/main/java/meltingpot/server/chat/dto/ChatRoomDetailGetResponse.java new file mode 100644 index 0000000..fd9c88d --- /dev/null +++ b/src/main/java/meltingpot/server/chat/dto/ChatRoomDetailGetResponse.java @@ -0,0 +1,19 @@ +package meltingpot.server.chat.dto; + +import meltingpot.server.domain.entity.party.Party; + +public record ChatRoomDetailGetResponse( + String imageKey, + String title, + Integer userCnt +) { + public static ChatRoomDetailGetResponse of(Party party, int userCnt) { + return new ChatRoomDetailGetResponse( + // [CHECK] 프로필 이미지 + // party.getUser().getProfileImages(), + "", + party.getPartySubject(), + userCnt + ); + } +} diff --git a/src/main/java/meltingpot/server/chat/dto/ChatRoomsGetResponse.java b/src/main/java/meltingpot/server/chat/dto/ChatRoomsGetResponse.java new file mode 100644 index 0000000..60bb368 --- /dev/null +++ b/src/main/java/meltingpot/server/chat/dto/ChatRoomsGetResponse.java @@ -0,0 +1,32 @@ +package meltingpot.server.chat.dto; + +import meltingpot.server.domain.entity.party.Party; + +import java.time.LocalDateTime; + +public record ChatRoomsGetResponse( + Long chatRoomId, + String leaderName, + String imageKey, + String partySubject, + String partyStatus, + String partyLocationAddress, + LocalDateTime partyStartTime, + int userCnt, + int messageCnt +) { + // [CHECK] 유저 프로필 이미지 + public static ChatRoomsGetResponse of(Party party, int userCnt, int messageCnt) { +// return new ChatRoomsGetResponse( +// party.getChatRoom().getId(), +// party.getUser().getUsername(), +// party.getUser().getProfileImages(), +// party.getPartySubject(), +// party.getPartyLocationAddress(), +// party.getPartyStartTime(), +// userCnt, +// messageCnt +// ); + return null; + } +} diff --git a/src/main/java/meltingpot/server/chat/service/ChatRoomQueryService.java b/src/main/java/meltingpot/server/chat/service/ChatRoomQueryService.java new file mode 100644 index 0000000..7dbe8be --- /dev/null +++ b/src/main/java/meltingpot/server/chat/service/ChatRoomQueryService.java @@ -0,0 +1,51 @@ +package meltingpot.server.chat.service; + +import lombok.RequiredArgsConstructor; +import meltingpot.server.chat.dto.ChatMessageGetResponse; +import meltingpot.server.chat.dto.ChatMessageListQuery; +import meltingpot.server.chat.dto.ChatRoomDetailGetResponse; +import meltingpot.server.chat.dto.ChatRoomsGetResponse; +import meltingpot.server.domain.entity.chat.ChatRoom; +import meltingpot.server.domain.entity.party.Party; +import meltingpot.server.domain.repository.chat.ChatMessageRepository; +import meltingpot.server.domain.repository.chat.ChatRoomRepository; +import meltingpot.server.domain.repository.chat.ChatRoomUserRepository; +import meltingpot.server.domain.repository.party.PartyRepository; +import meltingpot.server.util.PageResponse; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@Transactional(readOnly = true) +@RequiredArgsConstructor +public class ChatRoomQueryService { + private final ChatRoomUserRepository chatRoomUserRepository; + private final ChatRoomRepository chatRoomRepository; + private final ChatMessageRepository chatMessageRepository; + private final PartyRepository partyRepository; + + public ChatRoomDetailGetResponse getRoomDetail(Long chatRoomId) { + Party party = partyRepository.findByChatRoomId(chatRoomId); + return ChatRoomDetailGetResponse.of(party, chatRoomUserRepository.countChatRoomUsersByChatRoomId(chatRoomId)); + } + + // [CHECK] + public PageResponse> getChatMessage(ChatMessageListQuery query) { + ChatRoom chatRoom = chatRoomRepository.findById(query.chatRoomId()) + .orElseThrow(() -> new IllegalArgumentException("ChatRoom not found")); + PageRequest pageRequest = PageRequest.of(query.page(), query.size(), Sort.by("chatMessageId").descending()); + List chatMessages = chatMessageRepository.findAllByChatRoom(chatRoom, pageRequest) + .stream().map(ChatMessageGetResponse::from).toList(); + + // return PageResponse.of(chatMessages, pageRequest); + return null; + } + + public PageResponse> getChatRooms() { + return null; + } +} diff --git a/src/main/java/meltingpot/server/chat/service/ChatRoomService.java b/src/main/java/meltingpot/server/chat/service/ChatRoomService.java new file mode 100644 index 0000000..f70419b --- /dev/null +++ b/src/main/java/meltingpot/server/chat/service/ChatRoomService.java @@ -0,0 +1,21 @@ +package meltingpot.server.chat.service; + +import lombok.RequiredArgsConstructor; +import meltingpot.server.domain.entity.chat.ChatRoomUser; +import meltingpot.server.domain.repository.chat.ChatRoomUserRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class ChatRoomService { + private final ChatRoomUserRepository chatRoomUserRepository; + + public void updateAlarmStatus(Long userId, Long chatRoomId) { + ChatRoomUser chatRoomUser = chatRoomUserRepository.findChatRoomUserByUserIdAndChatRoomId(userId, chatRoomId) + .orElseThrow(() -> new IllegalArgumentException("ChatRoomUser not found")); + chatRoomUser.toggleAlarm(); + chatRoomUserRepository.save(chatRoomUser); + } +} diff --git a/src/main/java/meltingpot/server/chat/service/ChatService.java b/src/main/java/meltingpot/server/chat/service/ChatService.java new file mode 100644 index 0000000..7b754eb --- /dev/null +++ b/src/main/java/meltingpot/server/chat/service/ChatService.java @@ -0,0 +1,43 @@ +package meltingpot.server.chat.service; + +import lombok.RequiredArgsConstructor; +import meltingpot.server.chat.dto.ChatMessageCreateRequest; +import meltingpot.server.chat.dto.ChatMessageCreateResponse; +import meltingpot.server.domain.entity.chat.ChatMessage; +import meltingpot.server.domain.entity.chat.ChatRoom; +import meltingpot.server.domain.entity.chat.enums.Role; +import meltingpot.server.domain.repository.chat.ChatMessageRepository; +import meltingpot.server.domain.repository.chat.ChatRoomRepository; +import meltingpot.server.domain.repository.party.PartyRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional(readOnly = true) +@RequiredArgsConstructor +public class ChatService { + private final ChatMessageRepository chatMessageRepository; + private final ChatRoomRepository chatRoomRepository; + private final PartyRepository partyRepository; + + @Transactional + public ChatMessageCreateResponse createChatMessage(Long chatRoomId, ChatMessageCreateRequest request) { + ChatRoom chatRoom = chatRoomRepository.findById(chatRoomId) + .orElseThrow(() -> new IllegalArgumentException("error")); + + + Role role = (partyRepository.findByChatRoomId(chatRoomId).getAccount().getId().equals(request.userId())) + ? Role.LEADER + : Role.MEMBER; + + ChatMessage newChatMessage = ChatMessage.builder() + .chatRoom(chatRoom) + .content(request.content()) + .userId(request.userId()) + .role(role) + .build(); + + ChatMessage chatMessageEntity = chatMessageRepository.save(newChatMessage); + return new ChatMessageCreateResponse(chatMessageEntity.getId()); + } +} diff --git a/src/main/java/meltingpot/server/config/AmazonConfig.java b/src/main/java/meltingpot/server/config/AmazonConfig.java new file mode 100644 index 0000000..8bf803c --- /dev/null +++ b/src/main/java/meltingpot/server/config/AmazonConfig.java @@ -0,0 +1,52 @@ +package meltingpot.server.config; + +import com.amazonaws.auth.*; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import jakarta.annotation.PostConstruct; +import lombok.Getter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@Getter +public class AmazonConfig { + + private AWSCredentials awsCredentials; + + @Value("${cloud.aws.credentials.accessKey}") + private String accessKey; + + @Value("${cloud.aws.credentials.secretKey}") + private String secretKey; + + @Value("${cloud.aws.region.static}") + private String region; + + @Value("${cloud.aws.s3.bucket}") + private String bucket; + + @Value("${cloud.aws.s3.path.post}") + private String postPath; + + @PostConstruct + public void init() { + this.awsCredentials = new BasicAWSCredentials(accessKey, secretKey); + } + + @Bean + public AmazonS3 amazonS3() { + AWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey); + return AmazonS3ClientBuilder.standard() + .withRegion(region) + .withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) + .build(); + } + + @Bean + public AWSCredentialsProvider awsCredentialsProvider() { + return new AWSStaticCredentialsProvider(awsCredentials); + } +} + diff --git a/src/main/java/meltingpot/server/config/WebSocketConfig.java b/src/main/java/meltingpot/server/config/WebSocketConfig.java new file mode 100644 index 0000000..e18d762 --- /dev/null +++ b/src/main/java/meltingpot/server/config/WebSocketConfig.java @@ -0,0 +1,26 @@ +package meltingpot.server.config; + +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Configuration; +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; + +@Configuration +@RequiredArgsConstructor +@EnableWebSocketMessageBroker +public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { + @Override + public void configureMessageBroker(MessageBrokerRegistry registry) { + registry.setApplicationDestinationPrefixes("/app"); // 클라이언트에서 보낸 메세지를 받을 prefix + registry.enableSimpleBroker("/topic"); // 해당 주소를 구독하고 있는 클라이언트들에게 메세지 전달 + } + + @Override + public void registerStompEndpoints(StompEndpointRegistry registry) { + // 주소 : ws://localhost:8080/chat + registry.addEndpoint("/chat") // socket 연결 url + .setAllowedOriginPatterns("*"); // CORS 허용 범위 + } +} diff --git a/src/main/java/meltingpot/server/domain/entity/AccountProfileImage.java b/src/main/java/meltingpot/server/domain/entity/AccountProfileImage.java index bdbf7a3..e451a94 100644 --- a/src/main/java/meltingpot/server/domain/entity/AccountProfileImage.java +++ b/src/main/java/meltingpot/server/domain/entity/AccountProfileImage.java @@ -36,4 +36,4 @@ public class AccountProfileImage { @JoinColumn(name = "account_id") private Account account; -} +} \ No newline at end of file diff --git a/src/main/java/meltingpot/server/domain/entity/Post.java b/src/main/java/meltingpot/server/domain/entity/Post.java index a0b355a..e4929fb 100644 --- a/src/main/java/meltingpot/server/domain/entity/Post.java +++ b/src/main/java/meltingpot/server/domain/entity/Post.java @@ -4,7 +4,7 @@ import jakarta.persistence.*; import lombok.*; import meltingpot.server.domain.entity.common.BaseEntity; -import meltingpot.server.domain.entity.enums.Type; +import meltingpot.server.domain.entity.enums.PostType; import java.util.ArrayList; import java.util.List; @@ -15,6 +15,7 @@ @AllArgsConstructor(access = AccessLevel.PROTECTED) @Builder @Getter +@Setter public class Post extends BaseEntity { @Id @@ -27,7 +28,7 @@ public class Post extends BaseEntity { private String content; @Enumerated(EnumType.STRING) - private Type type; + private PostType postType; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") @@ -36,10 +37,11 @@ public class Post extends BaseEntity { @OneToMany(mappedBy = "post") private List comments = new ArrayList<>(); - @OneToMany(mappedBy = "post") - private List Images = new ArrayList<>(); + @OneToMany(mappedBy = "post", cascade = CascadeType.ALL) + private List postImages = new ArrayList<>(); @OneToMany(mappedBy = "post") private List reports = new ArrayList<>(); -} + + } diff --git a/src/main/java/meltingpot/server/domain/entity/Image.java b/src/main/java/meltingpot/server/domain/entity/PostImage.java similarity index 89% rename from src/main/java/meltingpot/server/domain/entity/Image.java rename to src/main/java/meltingpot/server/domain/entity/PostImage.java index b7b297a..2039d6c 100644 --- a/src/main/java/meltingpot/server/domain/entity/Image.java +++ b/src/main/java/meltingpot/server/domain/entity/PostImage.java @@ -9,7 +9,7 @@ @AllArgsConstructor(access = AccessLevel.PROTECTED) @Builder @Getter -public class Image extends BaseEntity { +public class PostImage extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -17,7 +17,7 @@ public class Image extends BaseEntity { private Long id; @Column(name = "image_url") - private String imageURl; + private String imageUrl; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "post_id") diff --git a/src/main/java/meltingpot/server/domain/entity/chat/ChatMessage.java b/src/main/java/meltingpot/server/domain/entity/chat/ChatMessage.java new file mode 100644 index 0000000..cacec9d --- /dev/null +++ b/src/main/java/meltingpot/server/domain/entity/chat/ChatMessage.java @@ -0,0 +1,37 @@ +package meltingpot.server.domain.entity.chat; + +import jakarta.persistence.*; +import lombok.*; +import meltingpot.server.domain.entity.chat.enums.Role; +import org.springframework.data.annotation.CreatedDate; + +import java.time.LocalDateTime; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Table(name = "chat_message") +public class ChatMessage { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "chat_message_id") + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "chat_room_id") + private ChatRoom chatRoom; + + @Column(name = "content") + private String content; + + @Column(name = "user_id") + private Long userId; + + @Column(name = "is_leader") + private Role role; + + @CreatedDate + private LocalDateTime createdAt; +} diff --git a/src/main/java/meltingpot/server/domain/entity/chat/ChatRoom.java b/src/main/java/meltingpot/server/domain/entity/chat/ChatRoom.java index 76a0d90..b47d49a 100644 --- a/src/main/java/meltingpot/server/domain/entity/chat/ChatRoom.java +++ b/src/main/java/meltingpot/server/domain/entity/chat/ChatRoom.java @@ -13,18 +13,23 @@ @Builder @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor +@Table(name = "chat_room") public class ChatRoom extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne(fetch = FetchType.LAZY) + @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "party_id") private Party party; @OneToMany(mappedBy = "chatRoom", cascade = CascadeType.ALL) - private List chatUserList = new ArrayList<>(); + private List chatRoomUserList = new ArrayList<>(); @OneToMany(mappedBy = "chatRoom", cascade = CascadeType.ALL) - private List chatList = new ArrayList<>(); + private List chatMessageList = new ArrayList<>(); + + public void createMessage(ChatMessage chatMessage){ + chatMessageList.add(chatMessage); + } } diff --git a/src/main/java/meltingpot/server/domain/entity/chat/ChatUser.java b/src/main/java/meltingpot/server/domain/entity/chat/ChatRoomUser.java similarity index 74% rename from src/main/java/meltingpot/server/domain/entity/chat/ChatUser.java rename to src/main/java/meltingpot/server/domain/entity/chat/ChatRoomUser.java index fd7c634..4d52194 100644 --- a/src/main/java/meltingpot/server/domain/entity/chat/ChatUser.java +++ b/src/main/java/meltingpot/server/domain/entity/chat/ChatRoomUser.java @@ -11,12 +11,15 @@ @Builder @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor -public class ChatUser extends BaseEntity { +@Table(name = "chat_room_user") +public class ChatRoomUser extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "chat_room_user_id") private Long id; @Enumerated(EnumType.STRING) + @Column(name = "chat_room_alarm_status") private Alarm alarm; @ManyToOne(fetch = FetchType.LAZY) @@ -26,4 +29,8 @@ public class ChatUser extends BaseEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "chat_room_id") private ChatRoom chatRoom; + + public void toggleAlarm() { + this.alarm = this.alarm.toggle(); + } } diff --git a/src/main/java/meltingpot/server/domain/entity/chat/enums/Alarm.java b/src/main/java/meltingpot/server/domain/entity/chat/enums/Alarm.java index c245200..4f4868c 100644 --- a/src/main/java/meltingpot/server/domain/entity/chat/enums/Alarm.java +++ b/src/main/java/meltingpot/server/domain/entity/chat/enums/Alarm.java @@ -1,5 +1,8 @@ package meltingpot.server.domain.entity.chat.enums; public enum Alarm { - ON, OFF + ON, OFF; + public Alarm toggle() { + return this == ON ? OFF : ON; + } } diff --git a/src/main/java/meltingpot/server/domain/entity/chat/enums/Role.java b/src/main/java/meltingpot/server/domain/entity/chat/enums/Role.java new file mode 100644 index 0000000..d5dac71 --- /dev/null +++ b/src/main/java/meltingpot/server/domain/entity/chat/enums/Role.java @@ -0,0 +1,5 @@ +package meltingpot.server.domain.entity.chat.enums; + +public enum Role { + LEADER, MEMBER +} diff --git a/src/main/java/meltingpot/server/domain/entity/common/AmazonS3Manager.java b/src/main/java/meltingpot/server/domain/entity/common/AmazonS3Manager.java new file mode 100644 index 0000000..6ecc6b5 --- /dev/null +++ b/src/main/java/meltingpot/server/domain/entity/common/AmazonS3Manager.java @@ -0,0 +1,59 @@ +package meltingpot.server.domain.entity.common; + +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.ObjectMetadata; +import com.amazonaws.services.s3.model.PutObjectRequest; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import meltingpot.server.config.AmazonConfig; +import meltingpot.server.util.apiPayload.code.ErrorStatus; +import meltingpot.server.util.apiPayload.exception.S3Exception; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; + +@Slf4j +@Component +@RequiredArgsConstructor +public class AmazonS3Manager { + private final AmazonS3 amazonS3; + private final AmazonConfig amazonConfig; + private final UuidRepository uuidRepository; + + public String uploadFile(String keyName, MultipartFile file) { + ObjectMetadata metadata = new ObjectMetadata(); + metadata.setContentLength(file.getSize()); + try { + amazonS3.putObject(new PutObjectRequest(amazonConfig.getBucket(), keyName, file.getInputStream(), metadata)); + } catch (IOException e) { + log.error("error at AmazonS3Manager uploadFile : {}", (Object) e.getStackTrace()); + } + + return amazonS3.getUrl(amazonConfig.getBucket(), keyName).toString(); + } + + public void deleteFile(String keyName) throws S3Exception { + try { + String modifiedKeyName = modifyDeleteKeyName(keyName); + System.out.println(modifiedKeyName); + if (amazonS3.doesObjectExist(amazonConfig.getBucket(), modifiedKeyName)) { + amazonS3.deleteObject(amazonConfig.getBucket(), modifiedKeyName); + } else { + throw new IOException(); + } + } catch (Exception e) { + throw new S3Exception(ErrorStatus.S3_OBJECT_NOT_FOUND); + } + } + + private String modifyDeleteKeyName(String keyName) { + return keyName.split("/")[3] + '/' + keyName.split("/")[4]; + } + + + public String generatePostKeyName(Uuid uuid, String filename) { + return amazonConfig.getPostPath() + '/' + uuid.getUuid() + "_" + filename; + } +} diff --git a/src/main/java/meltingpot/server/domain/entity/common/BaseEntity.java b/src/main/java/meltingpot/server/domain/entity/common/BaseEntity.java index 1d29e97..a88f6be 100644 --- a/src/main/java/meltingpot/server/domain/entity/common/BaseEntity.java +++ b/src/main/java/meltingpot/server/domain/entity/common/BaseEntity.java @@ -2,6 +2,7 @@ import jakarta.persistence.EntityListeners; import jakarta.persistence.MappedSuperclass; +import lombok.Builder; import lombok.Getter; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedBy; @@ -13,6 +14,7 @@ @MappedSuperclass @EntityListeners(AuditingEntityListener.class) @Getter + public class BaseEntity { @CreatedDate diff --git a/src/main/java/meltingpot/server/domain/entity/common/Uuid.java b/src/main/java/meltingpot/server/domain/entity/common/Uuid.java new file mode 100644 index 0000000..499bdb8 --- /dev/null +++ b/src/main/java/meltingpot/server/domain/entity/common/Uuid.java @@ -0,0 +1,26 @@ +package meltingpot.server.domain.entity.common; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Builder +@Getter +@AllArgsConstructor(access = AccessLevel.PROTECTED) +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Uuid extends BaseEntity { + + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(unique = true) + private String uuid; +} \ No newline at end of file diff --git a/src/main/java/meltingpot/server/domain/entity/common/UuidRepository.java b/src/main/java/meltingpot/server/domain/entity/common/UuidRepository.java new file mode 100644 index 0000000..f23f16e --- /dev/null +++ b/src/main/java/meltingpot/server/domain/entity/common/UuidRepository.java @@ -0,0 +1,6 @@ +package meltingpot.server.domain.entity.common; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UuidRepository extends JpaRepository { +} diff --git a/src/main/java/meltingpot/server/domain/entity/enums/Type.java b/src/main/java/meltingpot/server/domain/entity/enums/PostType.java similarity index 75% rename from src/main/java/meltingpot/server/domain/entity/enums/Type.java rename to src/main/java/meltingpot/server/domain/entity/enums/PostType.java index a5af1df..9e1a8f5 100644 --- a/src/main/java/meltingpot/server/domain/entity/enums/Type.java +++ b/src/main/java/meltingpot/server/domain/entity/enums/PostType.java @@ -1,5 +1,5 @@ package meltingpot.server.domain.entity.enums; -public enum Type { +public enum PostType { POSTING,QUESTION } diff --git a/src/main/java/meltingpot/server/domain/repository/AccountRepositroy.java b/src/main/java/meltingpot/server/domain/repository/AccountRepositroy.java new file mode 100644 index 0000000..25641d0 --- /dev/null +++ b/src/main/java/meltingpot/server/domain/repository/AccountRepositroy.java @@ -0,0 +1,8 @@ +package meltingpot.server.domain.repository; + +import meltingpot.server.domain.entity.Account; +import org.springframework.data.jpa.repository.JpaRepository; + +// post 구현때문에 만들어놓은 것이니 마음대로 수정하셔도 됩니다,,! +public interface AccountRepositroy extends JpaRepository { +} diff --git a/src/main/java/meltingpot/server/domain/repository/PostImageRepository.java b/src/main/java/meltingpot/server/domain/repository/PostImageRepository.java new file mode 100644 index 0000000..3b6219c --- /dev/null +++ b/src/main/java/meltingpot/server/domain/repository/PostImageRepository.java @@ -0,0 +1,7 @@ +package meltingpot.server.domain.repository; + +import meltingpot.server.domain.entity.PostImage; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PostImageRepository extends JpaRepository { +} diff --git a/src/main/java/meltingpot/server/domain/repository/PostRepository.java b/src/main/java/meltingpot/server/domain/repository/PostRepository.java new file mode 100644 index 0000000..e26e09a --- /dev/null +++ b/src/main/java/meltingpot/server/domain/repository/PostRepository.java @@ -0,0 +1,8 @@ +package meltingpot.server.domain.repository; + +import meltingpot.server.domain.entity.Post; +import meltingpot.server.domain.entity.PostImage; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PostRepository extends JpaRepository { +} diff --git a/src/main/java/meltingpot/server/domain/repository/chat/ChatMessageRepository.java b/src/main/java/meltingpot/server/domain/repository/chat/ChatMessageRepository.java new file mode 100644 index 0000000..b8c040f --- /dev/null +++ b/src/main/java/meltingpot/server/domain/repository/chat/ChatMessageRepository.java @@ -0,0 +1,13 @@ +package meltingpot.server.domain.repository.chat; + +import meltingpot.server.domain.entity.chat.ChatMessage; +import meltingpot.server.domain.entity.chat.ChatRoom; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Slice; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface ChatMessageRepository extends JpaRepository { + Slice findAllByChatRoom(ChatRoom chatRoom, PageRequest pageRequest); +} diff --git a/src/main/java/meltingpot/server/domain/repository/chat/ChatRoomRepository.java b/src/main/java/meltingpot/server/domain/repository/chat/ChatRoomRepository.java new file mode 100644 index 0000000..6be8f58 --- /dev/null +++ b/src/main/java/meltingpot/server/domain/repository/chat/ChatRoomRepository.java @@ -0,0 +1,7 @@ +package meltingpot.server.domain.repository.chat; + +import meltingpot.server.domain.entity.chat.ChatRoom; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ChatRoomRepository extends JpaRepository { +} diff --git a/src/main/java/meltingpot/server/domain/repository/chat/ChatRoomUserRepository.java b/src/main/java/meltingpot/server/domain/repository/chat/ChatRoomUserRepository.java new file mode 100644 index 0000000..b8130b4 --- /dev/null +++ b/src/main/java/meltingpot/server/domain/repository/chat/ChatRoomUserRepository.java @@ -0,0 +1,11 @@ +package meltingpot.server.domain.repository.chat; + +import meltingpot.server.domain.entity.chat.ChatRoomUser; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface ChatRoomUserRepository extends JpaRepository { + int countChatRoomUsersByChatRoomId(Long chatRoomId); + Optional findChatRoomUserByUserIdAndChatRoomId(Long userId, Long chatRoomId); +} diff --git a/src/main/java/meltingpot/server/domain/repository/party/PartyParticipantRepository.java b/src/main/java/meltingpot/server/domain/repository/party/PartyParticipantRepository.java new file mode 100644 index 0000000..7c47c24 --- /dev/null +++ b/src/main/java/meltingpot/server/domain/repository/party/PartyParticipantRepository.java @@ -0,0 +1,13 @@ +package meltingpot.server.domain.repository.party; + +import meltingpot.server.domain.entity.party.Party; +import meltingpot.server.domain.entity.party.PartyParticipant; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface PartyParticipantRepository extends JpaRepository { + int countByPartyId(Long partyId); + int countByUserId(Long userId); + List findAllByUserId(Long userId); +} diff --git a/src/main/java/meltingpot/server/domain/repository/party/PartyRepository.java b/src/main/java/meltingpot/server/domain/repository/party/PartyRepository.java new file mode 100644 index 0000000..3242e92 --- /dev/null +++ b/src/main/java/meltingpot/server/domain/repository/party/PartyRepository.java @@ -0,0 +1,9 @@ +package meltingpot.server.domain.repository.party; + +import meltingpot.server.domain.entity.party.Party; +import meltingpot.server.domain.entity.party.PartyParticipant; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PartyRepository extends JpaRepository { + Party findByChatRoomId(Long chatRoomId); +} diff --git a/src/main/java/meltingpot/server/post/controller/PostController.java b/src/main/java/meltingpot/server/post/controller/PostController.java new file mode 100644 index 0000000..e8b6f6e --- /dev/null +++ b/src/main/java/meltingpot/server/post/controller/PostController.java @@ -0,0 +1,33 @@ +package meltingpot.server.post.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import lombok.RequiredArgsConstructor; +import meltingpot.server.post.dto.PostRequestDto; +import meltingpot.server.post.dto.PostResponseDto; +import meltingpot.server.post.service.PostService; +import meltingpot.server.util.ResponseCode; +import meltingpot.server.util.ResponseData; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +import static meltingpot.server.util.ResponseCode.CREATE_POST_SUCCESS; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/posts") +public class PostController { + private final PostService postService; + + @Operation(summary = "게시물 작성") + @PostMapping("") + public ResponseEntity createPost( @RequestBody PostRequestDto.CreatePostDTO createPostDTO) { + postService.createPost(createPostDTO); + return ResponseData.toResponseEntity(ResponseCode.CREATE_POST_SUCCESS); + } +} diff --git a/src/main/java/meltingpot/server/post/converter/PostConverter.java b/src/main/java/meltingpot/server/post/converter/PostConverter.java new file mode 100644 index 0000000..59c1286 --- /dev/null +++ b/src/main/java/meltingpot/server/post/converter/PostConverter.java @@ -0,0 +1,28 @@ +package meltingpot.server.post.converter; + +import meltingpot.server.domain.entity.Post; +import meltingpot.server.post.dto.PostImageDto; +import meltingpot.server.post.dto.PostRequestDto; + +import java.util.List; +import java.util.stream.Collectors; + +public class PostConverter { + public static Post toPost(PostRequestDto.CreatePostDTO createPostDTO) { + + return Post.builder() + .title(createPostDTO.getTitle()) + .content(createPostDTO.getContent()) + .postType(createPostDTO.getPostType()) + .build(); + } + + public static List toPostImageDto(Post post) { + return post.getPostImages().stream() + .map(p -> PostImageDto.builder() + .id(p.getId()) + .imgUrl(p.getImageUrl()) + .build()) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/meltingpot/server/post/converter/PostImageConverter.java b/src/main/java/meltingpot/server/post/converter/PostImageConverter.java new file mode 100644 index 0000000..70fdc21 --- /dev/null +++ b/src/main/java/meltingpot/server/post/converter/PostImageConverter.java @@ -0,0 +1,14 @@ +package meltingpot.server.post.converter; + +import meltingpot.server.domain.entity.Post; +import meltingpot.server.domain.entity.PostImage; +import org.springframework.web.multipart.MultipartFile; + +public class PostImageConverter { + public static PostImage toPostImage(Post post, MultipartFile file, String pictureUrl) { + return PostImage.builder() + .post(post) + .imageUrl(pictureUrl) + .build(); + } +} diff --git a/src/main/java/meltingpot/server/post/dto/PostImageDto.java b/src/main/java/meltingpot/server/post/dto/PostImageDto.java new file mode 100644 index 0000000..8856b4e --- /dev/null +++ b/src/main/java/meltingpot/server/post/dto/PostImageDto.java @@ -0,0 +1,16 @@ +package meltingpot.server.post.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class PostImageDto { + @JsonProperty("id") + private Long id; + + @JsonProperty("imgUrl") + private String imgUrl; + +} diff --git a/src/main/java/meltingpot/server/post/dto/PostRequestDto.java b/src/main/java/meltingpot/server/post/dto/PostRequestDto.java new file mode 100644 index 0000000..821962f --- /dev/null +++ b/src/main/java/meltingpot/server/post/dto/PostRequestDto.java @@ -0,0 +1,18 @@ +package meltingpot.server.post.dto; + +import lombok.Getter; +import meltingpot.server.domain.entity.PostImage; +import meltingpot.server.domain.entity.enums.PostType; + +import java.util.List; + +public class PostRequestDto { + + @Getter + public static class CreatePostDTO { + private String title; + private String content; + private PostType postType; +// private List postImageList; + } +} diff --git a/src/main/java/meltingpot/server/post/dto/PostResponseDto.java b/src/main/java/meltingpot/server/post/dto/PostResponseDto.java new file mode 100644 index 0000000..b102f0d --- /dev/null +++ b/src/main/java/meltingpot/server/post/dto/PostResponseDto.java @@ -0,0 +1,19 @@ +package meltingpot.server.post.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +public class PostResponseDto { + @Getter + @AllArgsConstructor + @NoArgsConstructor + @Builder + public static class CreatePostResultDTO { + private Long postId; + private LocalDateTime createAt; + } +} diff --git a/src/main/java/meltingpot/server/post/service/PostService.java b/src/main/java/meltingpot/server/post/service/PostService.java new file mode 100644 index 0000000..6759d66 --- /dev/null +++ b/src/main/java/meltingpot/server/post/service/PostService.java @@ -0,0 +1,16 @@ +package meltingpot.server.post.service; + +import meltingpot.server.domain.entity.Account; +import meltingpot.server.domain.repository.AccountRepositroy; +import meltingpot.server.post.dto.PostRequestDto; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +public interface PostService { + + void createPost (PostRequestDto.CreatePostDTO createPostDTO); + } + + + diff --git a/src/main/java/meltingpot/server/post/service/PostServiceImpl.java b/src/main/java/meltingpot/server/post/service/PostServiceImpl.java new file mode 100644 index 0000000..1f8067d --- /dev/null +++ b/src/main/java/meltingpot/server/post/service/PostServiceImpl.java @@ -0,0 +1,57 @@ +package meltingpot.server.post.service; + +import lombok.RequiredArgsConstructor; +import meltingpot.server.domain.entity.Account; +import meltingpot.server.domain.entity.Post; +import meltingpot.server.domain.entity.PostImage; +import meltingpot.server.domain.entity.common.AmazonS3Manager; +import meltingpot.server.domain.entity.common.Uuid; +import meltingpot.server.domain.entity.common.UuidRepository; +import meltingpot.server.domain.repository.AccountRepositroy; +import meltingpot.server.domain.repository.PostImageRepository; +import meltingpot.server.domain.repository.PostRepository; +import meltingpot.server.post.converter.PostImageConverter; +import meltingpot.server.post.dto.PostRequestDto; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; +import java.util.UUID; + +import static meltingpot.server.post.converter.PostConverter.toPost; + +@Service +@RequiredArgsConstructor +@Transactional +public class PostServiceImpl implements PostService { + private final AccountRepositroy accountRepositroy; + private final PostRepository postRepository; + private final PostImageRepository postImageRepository; + private final UuidRepository uuidRepository; + private final AmazonS3Manager s3Manager; + + @Override + public void createPost(PostRequestDto.CreatePostDTO createPostDTO){ + + Post post = toPost(createPostDTO); + Post savedPost = postRepository.save(post); + +// for (MultipartFile file : multipartFileList) { +// String uuid = UUID.randomUUID().toString(); +// Uuid savedUuid = uuidRepository.save(Uuid.builder() +// .uuid(uuid).build()); +// +// String pictureUrl = s3Manager.uploadFile(s3Manager.generatePostKeyName(savedUuid, file.getOriginalFilename()), file); +// +// PostImage postImage = PostImageConverter.toPostImage(savedPost, file, pictureUrl); +// postImageRepository.save(postImage); +// } + } + + private Account findAccountById(Long accountId) { + return accountRepositroy.findById(accountId) + .orElseThrow(() -> new RuntimeException("사용자를 찾을 수 없습니다.")); + } +} + diff --git a/src/main/java/meltingpot/server/util/PageResponse.java b/src/main/java/meltingpot/server/util/PageResponse.java new file mode 100644 index 0000000..1bc587e --- /dev/null +++ b/src/main/java/meltingpot/server/util/PageResponse.java @@ -0,0 +1,23 @@ +package meltingpot.server.util; + +import org.springframework.data.domain.Page; + +import java.util.List; + +public record PageResponse( + List content, + int page, + int size, + int totalPage, + long totalCount +) { + public static PageResponse of(Page data) { + return new PageResponse<>( + data.getContent(), + data.getPageable().getPageNumber(), + data.getSize(), + data.getTotalPages(), + data.getTotalElements() + ); + } +} diff --git a/src/main/java/meltingpot/server/util/ResponseCode.java b/src/main/java/meltingpot/server/util/ResponseCode.java index d26991f..79536d2 100644 --- a/src/main/java/meltingpot/server/util/ResponseCode.java +++ b/src/main/java/meltingpot/server/util/ResponseCode.java @@ -20,6 +20,7 @@ public enum ResponseCode { /* 201 CREATED : 요청 성공, 자원 생성 */ SIGNUP_SUCCESS(CREATED, "회원가입 성공"), CREATE_CHAT_ROOM_SUCCESS(CREATED, "채팅방 생성 성공"), + CREATE_POST_SUCCESS(CREATED,"게시물 작성 성공"), /* 400 BAD_REQUEST : 잘못된 요청 */ @@ -42,7 +43,7 @@ public enum ResponseCode { BLACKLIST_MEMBER(FORBIDDEN, "접근할 수 없는 계정입니다"), HOLDING_WITHDRAWAL(FORBIDDEN, "30일 이내에 탈퇴한 계정입니다"), SIGNOUT_FAIL_REFRESH_TOKEN(FORBIDDEN, "본인의 REFRESH 토큰으로만 로그아웃할 수 있습니다"), - + S3_OBJECT_NOT_FOUND(NOT_FOUND, "REFRESH 토큰 정보를 찾을 수 없습니다"), /* 404 NOT_FOUND : Resource 를 찾을 수 없음 */ ACCOUNT_NOT_FOUND(NOT_FOUND, "계정 정보를 찾을 수 없습니다"), @@ -58,4 +59,5 @@ public enum ResponseCode { private final HttpStatus httpStatus; private final String detail; + } \ No newline at end of file diff --git a/src/main/java/meltingpot/server/util/ResponseData.java b/src/main/java/meltingpot/server/util/ResponseData.java index e3e9d2e..bf2cf63 100644 --- a/src/main/java/meltingpot/server/util/ResponseData.java +++ b/src/main/java/meltingpot/server/util/ResponseData.java @@ -71,4 +71,8 @@ public static ResponseEntity> toResponseEntity(ResponseCode ); } + + + + } \ No newline at end of file diff --git a/src/main/java/meltingpot/server/util/apiPayload/ErrorReasonDTO.java b/src/main/java/meltingpot/server/util/apiPayload/ErrorReasonDTO.java new file mode 100644 index 0000000..2ceaef1 --- /dev/null +++ b/src/main/java/meltingpot/server/util/apiPayload/ErrorReasonDTO.java @@ -0,0 +1,14 @@ +package meltingpot.server.util.apiPayload; + +import lombok.Builder; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@Builder +public class ErrorReasonDTO { + private final HttpStatus httpStatus; + private final String code; + private final String message; + private final boolean isSuccess; +} diff --git a/src/main/java/meltingpot/server/util/apiPayload/code/BaseErrorCode.java b/src/main/java/meltingpot/server/util/apiPayload/code/BaseErrorCode.java new file mode 100644 index 0000000..63c9c1b --- /dev/null +++ b/src/main/java/meltingpot/server/util/apiPayload/code/BaseErrorCode.java @@ -0,0 +1,10 @@ +package meltingpot.server.util.apiPayload.code; + +import meltingpot.server.util.apiPayload.ErrorReasonDTO; + +public interface BaseErrorCode { + + public ErrorReasonDTO getReason(); + + public ErrorReasonDTO getReasonHttpStatus(); +} \ No newline at end of file diff --git a/src/main/java/meltingpot/server/util/apiPayload/code/ErrorStatus.java b/src/main/java/meltingpot/server/util/apiPayload/code/ErrorStatus.java new file mode 100644 index 0000000..9ad7941 --- /dev/null +++ b/src/main/java/meltingpot/server/util/apiPayload/code/ErrorStatus.java @@ -0,0 +1,33 @@ +package meltingpot.server.util.apiPayload.code; + + +import lombok.AllArgsConstructor; +import lombok.Getter; +import meltingpot.server.util.apiPayload.ErrorReasonDTO; +import org.springframework.http.HttpStatus; + +@Getter +@AllArgsConstructor +public enum ErrorStatus implements BaseErrorCode { + + //S3 관련 + S3_OBJECT_NOT_FOUND(HttpStatus.NOT_FOUND, "이미지가 존재하지 않습니다."); + + private final HttpStatus httpStatus; + private final String detail; + + + @Override + public ErrorReasonDTO getReason() { + return ErrorReasonDTO.builder().message(detail).isSuccess(false).build(); + } + @Override + public ErrorReasonDTO getReasonHttpStatus() { + return ErrorReasonDTO.builder() + .code(name()) + .message(detail) + .isSuccess(false) + .httpStatus(httpStatus) + .build(); + } +} diff --git a/src/main/java/meltingpot/server/util/apiPayload/exception/GeneralException.java b/src/main/java/meltingpot/server/util/apiPayload/exception/GeneralException.java new file mode 100644 index 0000000..ab8323e --- /dev/null +++ b/src/main/java/meltingpot/server/util/apiPayload/exception/GeneralException.java @@ -0,0 +1,21 @@ +package meltingpot.server.util.apiPayload.exception; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import meltingpot.server.util.apiPayload.ErrorReasonDTO; +import meltingpot.server.util.apiPayload.code.BaseErrorCode; + +@Getter +@AllArgsConstructor +public class GeneralException extends RuntimeException { + + private BaseErrorCode code; + + public ErrorReasonDTO getErrorReason() { + return this.code.getReason(); + } + + public ErrorReasonDTO getErrorReasonHttpStatus() { + return this.code.getReasonHttpStatus(); + } +} diff --git a/src/main/java/meltingpot/server/util/apiPayload/exception/S3Exception.java b/src/main/java/meltingpot/server/util/apiPayload/exception/S3Exception.java new file mode 100644 index 0000000..546f08c --- /dev/null +++ b/src/main/java/meltingpot/server/util/apiPayload/exception/S3Exception.java @@ -0,0 +1,10 @@ +package meltingpot.server.util.apiPayload.exception; +import meltingpot.server.util.apiPayload.code.BaseErrorCode; + + +public class S3Exception extends GeneralException{ + + public S3Exception(BaseErrorCode code) { + super(code); + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 90fd980..54b8145 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -26,3 +26,16 @@ jwt: # token-validity-in-seconds: 86400 token-validity-in-seconds: 1209600 # 테스트용 14일 유효기간 +cloud: + aws: + s3: + bucket: meltingpot + path: + post : post + region: + static: ap-northeast-2 + stack: + auto: false + credentials: + accessKey: ${AWS_ACCESS_KEY} + secretKey: ${AWS_SECRET_KEY}