Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
8c5f6f4
[FEAT] [BVFH-198] Implements Create Private ChatRoom
Mongjo Jun 9, 2025
e38f543
[FIX] [BVFH-198] Fix createPrivateChatRoom Error Handling
Mongjo Jun 9, 2025
c280e2e
[FEAT] [BVFH-209] add websocket, kafka config
Mongjo Jun 9, 2025
f18ba90
[FEAT] [BVFH-209] implements connect websocket, send message
Mongjo Jun 10, 2025
d7f4d81
[FEAT] [BVFH-209] add WebSocket Interceptor of validation chatroom, m…
Mongjo Jun 10, 2025
e8eecf1
[FEAT] [BVFH-209] implements getMessagesHistory by Cursor-based Pagin…
Mongjo Jun 10, 2025
9688783
[FEAT] [BVFH-209] add nickname field to ChatMessageDocument
Mongjo Jun 11, 2025
386f0b1
[FEAT] [BVFH-209] add nickname field to ChatMessageDocument
Mongjo Jun 11, 2025
a7f5421
[FIX] [BVFH-209] change kafka topic name
Mongjo Jun 12, 2025
7e14ebd
Merge pull request #1 from Spharos-team1/BVFH-198-chatroom
Mongjo Jun 12, 2025
f7796f0
Merge pull request #2 from Spharos-team1/BVFH-209-chat-message-basic
Mongjo Jun 12, 2025
0396a54
[FEAT] [BVFH-244] add ChatReadCheckPoint Document, Dto, Repository
Mongjo Jun 13, 2025
4778612
[FEAT] [BVFH-244] add ChatReadCheckPoint Document, Dto, Repository
Mongjo Jun 13, 2025
9183efb
[REFACTOR] [BVFH-209] improve Kafka-WebSocket error handling and conf…
Mongjo Jun 15, 2025
a319045
Merge pull request #3 from Spharos-team1/BVFH-209-chat-message-basic
chuman0216 Jun 15, 2025
2904bdd
[MERGE] [BVFH-244] merge by develop
Mongjo Jun 15, 2025
da46823
[FEAT] [BVFH-244] implements Message Read CheckPoint
Mongjo Jun 16, 2025
b85b01b
Merge pull request #4 from Spharos-team1/BVFH-244-chat-read
chuman0216 Jun 16, 2025
94cc783
[FEAT] [BVFH-245] implements get member chatroom list
Mongjo Jun 17, 2025
2c1e4f1
[FEAT] [BVFH-245] implements update chatroom summary at message save,…
Mongjo Jun 17, 2025
ed0d3ac
[FEAT] [BVFH-245] implements get read check-point
Mongjo Jun 17, 2025
9407fe6
[FEAT] [BVFH-245] implements publish chatroom summary update event on…
Mongjo Jun 18, 2025
b73f0ec
Merge pull request #5 from Spharos-team1/BVFH-245-chat-room-list
chuman0216 Jun 18, 2025
b24f178
[CHORE] [BVFH-198] update swagger config, controller
Mongjo Jun 18, 2025
d998b28
Merge pull request #7 from Spharos-team1/BVFH-198-chatroom
Mongjo Jun 18, 2025
6ffb55b
[FEAT] [BVFH-286] implements get pre-signed-url api
Mongjo Jun 19, 2025
d6d6cec
[FEAT] [BVFH-286] implements send image chat
Mongjo Jun 19, 2025
ed87334
delete comment PreSignedUrlUtil.java
Mongjo Jun 19, 2025
a0e8f88
Merge pull request #8 from Spharos-team1/BVFH-286-chat-image
Mongjo Jun 19, 2025
5863b3a
[FEAT] [BVFH-290] implements exit chatroom
Mongjo Jun 19, 2025
31e0c3f
[FEAT] [BVFH-290] implements Get messages after chatroom exit time
Mongjo Jun 19, 2025
d7a36d4
Merge pull request #9 from Spharos-team1/BVFH-290-chatroom-exit
chuman0216 Jun 19, 2025
6fa3318
[DOCUMENT] [BVFH-290] add Dockerfile
Mongjo Jun 19, 2025
19f98bd
Merge pull request #10 from Spharos-team1/BVFH-290-chatroom-exit
Mongjo Jun 19, 2025
3b3fc06
Update Dockerfile
Mongjo Jun 19, 2025
44e1c2a
[DOCUMENT] [BVFH-290] update Dockerfile
Mongjo Jun 20, 2025
fc0a327
[CHORE] [BVFH-290] update application.yml
Mongjo Jun 20, 2025
934b7e8
Merge branch 'BVFH-170-develop' into BVFH-290-chatroom-exit
Mongjo Jun 20, 2025
3f4b856
Merge pull request #12 from Spharos-team1/BVFH-290-chatroom-exit
Mongjo Jun 20, 2025
0f892fb
Update application.yml
Mongjo Jun 20, 2025
a483e9f
Update application.yml
Mongjo Jun 20, 2025
11c9496
Update build.gradle
Mongjo Jun 20, 2025
a162787
[REFACTOR] [BVFH-290] add ZoneId in LocalDateTime
Mongjo Jun 20, 2025
8202b54
Merge branch 'BVFH-170-develop' of https://github.com/Spharos-team1/c…
Mongjo Jun 20, 2025
0c69aac
Merge pull request #14 from Spharos-team1/BVFH-290-chatroom-exit
Mongjo Jun 20, 2025
c2b1f1a
Update ChatReadCheckPointUpdater.java
Mongjo Jun 20, 2025
5122266
[FEAT] [BVFH-290] set websocket hearbeat
Mongjo Jun 20, 2025
850b176
[FEAT] [BVFH-290] set websocket hearbeat
Mongjo Jun 20, 2025
8805c6b
Update ChatMessageQueryController.java
Mongjo Jun 20, 2025
bf6857b
Update application.yml
Mongjo Jun 20, 2025
6363e20
Update application.yml
Mongjo Jun 20, 2025
92cb82b
Merge pull request #16 from Spharos-team1/BVFH-290-chatroom-exit
Mongjo Jun 20, 2025
90b38c2
[FIX] [BVFH-290] fix websocket hearbeat
Mongjo Jun 20, 2025
db446e3
Merge branch 'BVFH-170-develop' of https://github.com/Spharos-team1/c…
Mongjo Jun 20, 2025
5404509
Merge pull request #17 from Spharos-team1/BVFH-290-chatroom-exit
Mongjo Jun 20, 2025
b6aa6d1
Update SwaggerConfig.java
Mongjo Jun 20, 2025
dc75bf2
[CHORE] [BVFH-290] update swagger controller description
Mongjo Jun 20, 2025
36eaa05
Merge pull request #18 from Spharos-team1/BVFH-290-chatroom-exit
Mongjo Jun 20, 2025
152ad4b
[FEAT] [BVFH-198] implements get chatroom info
Mongjo Jun 21, 2025
b5208e4
Merge pull request #20 from Spharos-team1/BVFH-198-chatroom
chuman0216 Jun 21, 2025
a2eb38b
[FEAT] [BVFH-198] implements get chatroom uuid by postuuid
Mongjo Jun 22, 2025
67bb4b6
Merge pull request #21 from Spharos-team1/BVFH-198-chatroom
Mongjo Jun 22, 2025
0cd3cc8
[FEAT] [BVFH-307] implements send chat reply message
Mongjo Jun 22, 2025
11356f3
[FIX] [BVFH-307] include reply message fields in chat history response
Mongjo Jun 22, 2025
52079e5
[CHORE] [BVFH-307] update getMessagesHistory Controller Operation des…
Mongjo Jun 22, 2025
06d28dd
[CHORE] [BVFH-307] remove unused imports
Mongjo Jun 23, 2025
e91129e
Merge pull request #22 from Spharos-team1/BVFH-307-chat-comment
chuman0216 Jun 23, 2025
3989587
[FIX] [BVFH-307] add EnableJpaAuditing Annotation at main class
Mongjo Jun 23, 2025
271f40a
Merge pull request #23 from Spharos-team1/BVFH-307-chat-comment
Mongjo Jun 23, 2025
b64da66
Revert "[FIX] [BVFH-307] 시작 클래스에 @EnableJpaAuditing 추가"
Mongjo Jun 23, 2025
3724a90
Merge pull request #24 from Spharos-team1/revert-23-BVFH-307-chat-com…
Mongjo Jun 23, 2025
7e90f24
[CHORE] [BVFH-307] allowed all origins
Mongjo Jun 23, 2025
fc38dd5
[CHORE] [BVFH-307] allowed all origins
Mongjo Jun 23, 2025
301a060
Merge pull request #25 from Spharos-team1/BVFH-307-chat-comment
Mongjo Jun 23, 2025
193c788
[CHORE] [BVFH-311] update webconfig
Mongjo Jun 23, 2025
046d2fe
Merge pull request #26 from Spharos-team1/BVFH-311-chat-optimize
Mongjo Jun 23, 2025
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
Binary file added .DS_Store
Binary file not shown.
49 changes: 49 additions & 0 deletions .github/workflows/CI.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: CI

on:
push:
branches:
- BVFH-170-develop


env:
AWS_REGION: ap-northeast-2
ECR_REPOSITORY: cabbage/chat-service
SERVICE_NAME: chat-service

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1

- name: Build Docker image
run: |
./gradlew bootJar
docker build -t ${{ env.ECR_REPOSITORY }}:latest -f Dockerfile .

- name: Tag & Push to ECR
run: |
REPO_URI=$(aws ecr describe-repositories --repository-names ${{ env.ECR_REPOSITORY }} --region ${{ env.AWS_REGION }} --query "repositories[0].repositoryUri" --output text)
docker tag ${{ env.ECR_REPOSITORY }}:latest $REPO_URI:latest
docker push $REPO_URI:latest

- name: Get image digest
id: digest
run: |
IMAGE_DIGEST=$(aws ecr describe-images --repository-name ${{ env.ECR_REPOSITORY }} --image-ids imageTag=latest --query 'imageDetails[0].imageDigest' --output text)
echo "Image digest: $IMAGE_DIGEST"
echo "digest=$IMAGE_DIGEST" >> $GITHUB_OUTPUT
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ bin/
!**/src/test/**/bin/

### IntelliJ IDEA ###
ChatMessageKafkaSendTestController.java
.idea
*.iws
*.iml
Expand All @@ -27,7 +28,6 @@ out/
!**/src/test/**/out/

### Spring ###
application*.yml
.env
logs/
tmp/
Expand Down
6 changes: 6 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
FROM eclipse-temurin:17-jdk-alpine
WORKDIR /app
COPY build/libs/chatservice-0.0.1-SNAPSHOT.jar app.jar

# :흰색_확인_표시: ENTRYPOINT로 java만 실행
ENTRYPOINT ["java", "-jar", "app.jar"]
25 changes: 23 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
plugins {
id 'java'
id 'org.springframework.boot' version '3.5.0'
id 'org.springframework.boot' version '3.4.1'
id 'io.spring.dependency-management' version '1.1.7'
}

Expand All @@ -24,10 +24,25 @@ repositories {
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation'
//jpa
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
//mongoDB
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
implementation 'org.springframework.boot:spring-boot-starter-web'
//websocket
implementation 'org.springframework.boot:spring-boot-starter-websocket'
//kafka
implementation 'org.springframework.kafka:spring-kafka'
//swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.7.0'
//feign client
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
// S3
implementation 'com.amazonaws:aws-java-sdk-s3:1.12.281'
//actuator
implementation 'org.springframework.boot:spring-boot-starter-actuator'

compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
Expand All @@ -38,3 +53,9 @@ dependencies {
tasks.named('test') {
useJUnitPlatform()
}

dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:2024.0.1"
}
}
Binary file added src.zip
Binary file not shown.
Binary file added src/.DS_Store
Binary file not shown.
Binary file added src/main/.DS_Store
Binary file not shown.
Binary file added src/main/java/com/.DS_Store
Binary file not shown.
Binary file added src/main/java/com/chalnakchalnak/.DS_Store
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.chalnakchalnak.chatservice.chatmessage.adpater.in.mapper;

import com.chalnakchalnak.chatservice.chatmessage.adpater.in.vo.ReplyPreviewVo;
import com.chalnakchalnak.chatservice.chatmessage.adpater.in.vo.in.GetMessagesRequestVo;
import com.chalnakchalnak.chatservice.chatmessage.adpater.in.vo.in.GetReadCheckPointRequestVo;
import com.chalnakchalnak.chatservice.chatmessage.adpater.in.vo.out.GetMessagesResponseVo;
import com.chalnakchalnak.chatservice.chatmessage.adpater.in.vo.out.GetReadCheckPointResponseVo;
import com.chalnakchalnak.chatservice.chatmessage.application.dto.in.GetMessagesRequestDto;
import com.chalnakchalnak.chatservice.chatmessage.application.dto.in.GetReadCheckPointRequestDto;
import com.chalnakchalnak.chatservice.chatmessage.application.dto.out.GetMessagesResponseDto;
import com.chalnakchalnak.chatservice.chatmessage.application.dto.out.GetReadCheckPointResponseDto;
import org.springframework.stereotype.Component;

@Component
public class ChatMessageQueryVoMapper {

public GetMessagesRequestDto toGetMessagesRequestDto(GetMessagesRequestVo getMessagesRequestVo, String memberUuid) {
return GetMessagesRequestDto.builder()
.chatRoomUuid(getMessagesRequestVo.getChatRoomUuid())
.memberUuid(memberUuid)
.lastMessageId(getMessagesRequestVo.getLastMessageId())
.limit(getMessagesRequestVo.getLimit() != null ? getMessagesRequestVo.getLimit() : 20)
.build();
}

public GetMessagesResponseVo toGetMessagesResponseVo(GetMessagesResponseDto getMessagesResponseDto) {
return GetMessagesResponseVo.builder()
.messageUuid(getMessagesResponseDto.getMessageUuid())
.chatRoomUuid(getMessagesResponseDto.getChatRoomUuid())
.senderUuid(getMessagesResponseDto.getSenderUuid())
.message(getMessagesResponseDto.getMessage())
.messageType(getMessagesResponseDto.getMessageType())
.sentAt(getMessagesResponseDto.getSentAt().toString())
.replyToMessageUuid(getMessagesResponseDto.getReplyToMessageUuid())
.replyPreview(getMessagesResponseDto.getReplyPreview() != null ?
ReplyPreviewVo.builder()
.senderUuid(getMessagesResponseDto.getReplyPreview().getSenderUuid())
.message(getMessagesResponseDto.getReplyPreview().getMessage())
.messageType(getMessagesResponseDto.getReplyPreview().getMessageType())
.build()
: null)
.build();
}

public GetReadCheckPointRequestDto toGetReadCheckPointRequestDto(GetReadCheckPointRequestVo getReadCheckPointRequestVo) {
return GetReadCheckPointRequestDto.builder()
.chatRoomUuid(getReadCheckPointRequestVo.getChatRoomUuid())
.memberUuid(getReadCheckPointRequestVo.getMemberUuid())
.build();
}

public GetReadCheckPointResponseVo toGetReadCheckPointResponseVo(GetReadCheckPointResponseDto getReadCheckPointResponseDto) {
return GetReadCheckPointResponseVo.builder()
.lastReadMessageSentAt(getReadCheckPointResponseDto.getLastReadMessageSentAt().toString())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.chalnakchalnak.chatservice.chatmessage.adpater.in.mapper;

import com.chalnakchalnak.chatservice.chatmessage.adpater.in.vo.in.ReadMessageRequestVo;
import com.chalnakchalnak.chatservice.chatmessage.adpater.in.vo.in.SendMessageRequestVo;
import com.chalnakchalnak.chatservice.chatmessage.application.dto.in.ReadMessageRequestDto;
import com.chalnakchalnak.chatservice.chatmessage.application.dto.in.SendMessageRequestDto;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.ZoneId;

@Component
public class ChatMessageVoMapper {

public SendMessageRequestDto toSendMessageRequestDto(SendMessageRequestVo sendMessageRequestVo) {
return SendMessageRequestDto.builder()
.chatRoomUuid(sendMessageRequestVo.getChatRoomUuid())
.senderUuid(sendMessageRequestVo.getSenderUuid())
.message(sendMessageRequestVo.getMessage())
.messageType(sendMessageRequestVo.getMessageType())
.sentAt(LocalDateTime.now(ZoneId.of("Asia/Seoul")))
.replyToMessageUuid(sendMessageRequestVo.getReplyToMessageUuid())
.build();
}

public ReadMessageRequestDto toReadMessageRequestDto(ReadMessageRequestVo readMessageRequestVo) {
return ReadMessageRequestDto.builder()
.chatRoomUuid(readMessageRequestVo.getChatRoomUuid())
.memberUuid(readMessageRequestVo.getMemberUuid())
.lastReadMessageSentAt(readMessageRequestVo.getLastReadMessageSentAt())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.chalnakchalnak.chatservice.chatmessage.adpater.in.mapper;

import com.chalnakchalnak.chatservice.chatmessage.adpater.in.vo.in.PreSignedUrlRequestVo;
import com.chalnakchalnak.chatservice.chatmessage.adpater.in.vo.out.PreSignedUrlResponseVo;
import com.chalnakchalnak.chatservice.chatmessage.application.dto.in.PreSignedUrlRequestDto;
import com.chalnakchalnak.chatservice.chatmessage.application.dto.out.PreSignedUrlResponseDto;
import org.springframework.stereotype.Component;

@Component
public class PreSignedUrlVoMapper {

public PreSignedUrlRequestDto toPreSignedUrlRequestDto(PreSignedUrlRequestVo preSignedUrlRequestVo, String memberUuid) {
return PreSignedUrlRequestDto.builder()
.memberUuid(memberUuid)
.contentType(preSignedUrlRequestVo.getContentType())
.build();
}

public PreSignedUrlResponseVo toPreSignedUrlResponseVo(PreSignedUrlResponseDto preSignedUrlResponseDto) {
return PreSignedUrlResponseVo.builder()
.url(preSignedUrlResponseDto.getUrl())
.fields(preSignedUrlResponseDto.getFields())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.chalnakchalnak.chatservice.chatmessage.adpater.in.vo;

import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Builder;
import lombok.Getter;

@Getter
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ReplyPreviewVo {
private String senderUuid;
private String message;
private String messageType;

@Builder
public ReplyPreviewVo(String senderUuid, String message, String messageType) {
this.senderUuid = senderUuid;
this.message = message;
this.messageType = messageType;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.chalnakchalnak.chatservice.chatmessage.adpater.in.vo.in;

import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class GetMessagesRequestVo {

@NotBlank(message = "채팅방 UUID는 필수입니다.")
private String chatRoomUuid;

private String lastMessageId;

private Integer limit;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.chalnakchalnak.chatservice.chatmessage.adpater.in.vo.in;

import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class GetReadCheckPointRequestVo {

@NotBlank(message = "chatRoomUuid는 필수 값입니다.")
private String chatRoomUuid;

@NotBlank(message = "memberUuid는 필수 값입니다.")
private String memberUuid;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.chalnakchalnak.chatservice.chatmessage.adpater.in.vo.in;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class PreSignedUrlRequestVo {

@NotBlank(message = "파일 형식은 필수입니다.")
@Pattern(
regexp = "image/(png|jpeg|webp|bmp)",
message = "지원하지 않는 이미지 형식입니다."
)
private String contentType;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.chalnakchalnak.chatservice.chatmessage.adpater.in.vo.in;

import jakarta.validation.constraints.NotBlank;
import lombok.Getter;

import java.time.LocalDateTime;

@Getter
public class ReadMessageRequestVo {

@NotBlank(message = "chatRoomUuid 는 필수 값입니다.")
private String chatRoomUuid;

@NotBlank(message = "memberUuid 는 필수 값입니다.")
private String memberUuid;

private LocalDateTime lastReadMessageSentAt;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.chalnakchalnak.chatservice.chatmessage.adpater.in.vo.in;

import com.chalnakchalnak.chatservice.chatmessage.domain.MessageType;
import jakarta.validation.constraints.AssertTrue;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Getter;

@Getter
public class SendMessageRequestVo {

@NotBlank(message = "ChatRoomUuid는 필수 입력값입니다.")
private String chatRoomUuid;

@NotBlank(message = "SenderUuid는 필수 입력값입니다.")
private String senderUuid;

@NotBlank(message = "Message는 필수 입력값입니다.")
@Size(max = 5000, message = "메시지는 최대 5000자까지 입력 가능합니다.")
private String message;

@NotNull(message = "MessageType은 필수 입력값입니다.")
private MessageType messageType;

private String replyToMessageUuid;

@AssertTrue(message = "REPLY 타입일 경우 replyToMessageId는 필수입니다.")
private boolean isValidReplyCondition() {
if (messageType == null) return true;
if (messageType == MessageType.REPLY) {
return replyToMessageUuid != null && !replyToMessageUuid.isBlank();
} else {
return replyToMessageUuid == null || replyToMessageUuid.isBlank();
}
}
}
Loading
Loading