Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ spring:
- RemoveRequestHeader=Cookie
- RewritePath=/users/(?<segment>.*), /$\{segment}

- id: chat-server-swagger
uri: lb://CHAT-SERVER
predicates:
- Path=/chats/swagger-ui/**, /chats/v3/api-docs/**, /chats/swagger-resources/**, /chats/webjars/**
filters:
- RemoveRequestHeader=Cookie
- RewritePath=/chats/(?<segment>.*), /$\{segment}

- id: guild-server
uri: lb://GUILD-SERVER
predicates:
Expand Down Expand Up @@ -108,6 +116,15 @@ spring:
- RemoveRequestHeader=Cookie
- RewritePath=/signalings/(?<segment>.*), /$\{segment}

- id: chat-server
uri: lb://CHAT-SERVER
predicates:
- Path=/chats/**
filters:
- RemoveRequestHeader=Cookie
- RewritePath=/chats/(?<segment>.*), /$\{segment}
- AuthorizationHeaderFilter

default-filters:
- DedupeResponseHeader=Access-Control-Allow-Origin Access-Control-Allow-Credentials
globalcors:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ spring:
- RemoveRequestHeader=Cookie
- RewritePath=/users/(?<segment>.*), /$\{segment}

- id: chat-server-swagger
uri: lb://CHAT-SERVER
predicates:
- Path=/guilds/swagger-ui/**, /guilds/v3/api-docs/**, /guilds/swagger-resources/**, /guilds/webjars/**
filters:
- RemoveRequestHeader=Cookie
- RewritePath=/guilds/(?<segment>.*), /$\{segment}

- id: guild-server
uri: lb://GUILD-SERVER
predicates:
Expand Down Expand Up @@ -108,6 +116,15 @@ spring:
- RemoveRequestHeader=Cookie
- RewritePath=/signalings/(?<segment>.*), /$\{segment}

- id: chat-server
uri: lb://CHAT-SERVER
predicates:
- Path=/chats/**
filters:
- RemoveRequestHeader=Cookie
- RewritePath=/users/(?<segment>.*), /$\{segment}
- AuthorizationHeaderFilter

default-filters:
- DedupeResponseHeader=Access-Control-Allow-Origin Access-Control-Allow-Credentials
globalcors:
Expand Down
3 changes: 3 additions & 0 deletions src/backend/chat-server/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ dependencies {
implementation("org.springframework.kafka:spring-kafka")

implementation("org.springframework.boot:spring-boot-starter-data-mongodb")

// Swagger
implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.7.0")
}

dependencyManagement {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.asyncgate.chat_server.controller

import com.asyncgate.chat_server.controller.docs.DirectControllerDocs
import com.asyncgate.chat_server.domain.ReadStatus
import com.asyncgate.chat_server.filter.JwtTokenProvider
import com.asyncgate.chat_server.service.DirectService
Expand All @@ -20,7 +21,7 @@ import org.springframework.web.bind.annotation.ResponseBody
class DirectController(
private val directService: DirectService,
private val jwtTokenProvider: JwtTokenProvider,
) {
) : DirectControllerDocs {

@MessageMapping("/chat/direct/send-message")
fun direct(@Payload directMessageCreate: DirectMessageCreate, message: Message<*>) {
Expand All @@ -36,23 +37,23 @@ class DirectController(
}

@MessageMapping("/chat/direct/typing")
fun typing(@Payload directTyping: DirectMessageTyping, message: Message<*>) {
fun typing(@Payload directTyping: DirectMessageTypingRequest, message: Message<*>) {
val jwtToken = CustomSecurityContext.extractJwtTokenForStomp(message)
val userId = jwtTokenProvider.extract(jwtToken)
val directMessage = directTyping.toDomain(userId)
directService.typing(directMessage)
}

@MessageMapping("/chat/direct/edit")
fun edit(@Payload directEdit: DirectMessageEdit, message: Message<*>) {
fun edit(@Payload directEdit: DirectMessageEditRequest, message: Message<*>) {
val jwtToken = CustomSecurityContext.extractJwtTokenForStomp(message)
val userId = jwtTokenProvider.extract(jwtToken)
val directMessage = directEdit.toDomain(userId)
directService.edit(directMessage)
}

@MessageMapping("/chat/direct/delete")
fun sendDeleteMessage(@Payload directDelete: DirectMessageDelete, message: Message<*>) {
fun sendDeleteMessage(@Payload directDelete: DirectMessageDeleteRequest, message: Message<*>) {
val jwtToken = CustomSecurityContext.extractJwtTokenForStomp(message)
val userId = jwtTokenProvider.extract(jwtToken)
val directMessage = directDelete.toDomain(userId)
Expand All @@ -61,7 +62,7 @@ class DirectController(

@ResponseBody
@PostMapping("/chat/direct/file")
fun uploadFile(@ModelAttribute fileRequest: FileRequest, servletRequest: HttpServletRequest): SuccessResponse<FileUploadResponse> {
override fun uploadFile(@ModelAttribute fileRequest: FileRequest, servletRequest: HttpServletRequest): SuccessResponse<FileUploadResponse> {
val jwtToken = CustomSecurityContext.extractJwtTokenForHttp(servletRequest)
val userId = jwtTokenProvider.extract(jwtToken)
val response = directService.upload(fileRequest, userId)
Expand All @@ -70,12 +71,25 @@ class DirectController(

@ResponseBody
@GetMapping("chat/direct")
fun readPaging(
override fun readPaging(
@RequestParam("page", defaultValue = "0") page: Int,
@RequestParam("size", defaultValue = "10") size: Int,
@RequestParam("channel-id") channelId: String,
): SuccessResponse<DirectPagingResponse> {
val response = directService.readPaging(channelId, page, size)
return SuccessResponse.ok(response)
}

// Just Docs
override fun directJustDocs(directMessageCreate: DirectMessageCreate, message: Message<*>) {
}

override fun typingJustDocs(directTyping: DirectMessageTypingRequest, message: Message<*>) {
}

override fun editJustDocs(directEdit: DirectMessageEditRequest, message: Message<*>) {
}

override fun sendDeleteMessageJustDocs(directDelete: DirectMessageDeleteRequest, message: Message<*>) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,36 @@ import com.asyncgate.chat_server.domain.DirectMessage
import com.asyncgate.chat_server.domain.DirectMessageType
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import com.fasterxml.jackson.databind.annotation.JsonSerialize
import io.swagger.v3.oas.annotations.media.Schema
import org.springframework.web.multipart.MultipartFile
import java.io.Serializable

@Schema(description = "Direct 메시지 생성 요청 DTO")
@JsonSerialize
@JsonDeserialize
data class DirectMessageCreate(
@Schema(description = "채널 ID, 다이렉트 채팅방 생성 후 id. DirectId와 같음", example = "channel-12345")
val channelId: String,

@Schema(description = "프로필 이미지 URL", example = "http://example.com/image.png")
val profileImage: String,

@Schema(description = "사용자 이름", example = "John Doe")
val name: String,

@Schema(description = "메시지 내용", example = "Hello!")
val content: String,

@Schema(description = "썸네일 URL", example = "http://example.com/thumbnail.png", nullable = true)
val thumbnail: String? = null,

@Schema(description = "부모 메시지 ID", example = "msg-12345", nullable = true)
val parentId: String? = null,

@Schema(description = "부모 메시지 작성자 이름", example = "Jane Doe", nullable = true)
val parentName: String? = null,

@Schema(description = "부모 메시지 내용", example = "Previous message content", nullable = true)
val parentContent: String? = null,
) : Serializable {
fun toDomain(userId: String): DirectMessage {
Expand All @@ -37,12 +52,22 @@ data class DirectMessageCreate(
}
}

data class DirectMessageEdit(
@Schema(description = "Direct 메시지 수정 요청 DTO")
@JsonSerialize
@JsonDeserialize
data class DirectMessageEditRequest(
@Schema(description = "메시지 ID", example = "msg-12345")
val id: String,

@Schema(description = "채널 ID", example = "channel-12345")
val channelId: String,

@Schema(description = "사용자 이름", example = "John Doe")
val name: String,

@Schema(description = "메시지 내용", example = "Hello, edited!")
val content: String,
) {
) : Serializable {
fun toDomain(userId: String): DirectMessage {
return DirectMessage(
channelId = channelId,
Expand All @@ -54,10 +79,16 @@ data class DirectMessageEdit(
}
}

data class DirectMessageDelete(
@Schema(description = "Direct 메시지 삭제 요청 DTO")
@JsonSerialize
@JsonDeserialize
data class DirectMessageDeleteRequest(
@Schema(description = "채널 ID", example = "channel-12345")
val channelId: String,

@Schema(description = "메시지 ID", example = "msg-12345")
val id: String,
) {
) : Serializable {
fun toDomain(userId: String): DirectMessage {
return DirectMessage(
id = id,
Expand All @@ -68,11 +99,19 @@ data class DirectMessageDelete(
}
}

data class DirectMessageTyping(
@Schema(description = "Direct 메시지 타이핑 요청 DTO")
@JsonSerialize
@JsonDeserialize
data class DirectMessageTypingRequest(
@Schema(description = "채널 ID", example = "channel-12345")
val channelId: String,

@Schema(description = "타이핑 중 메시지 내용", example = "User is typing...")
val content: String,

@Schema(description = "사용자 이름", example = "John Doe")
val name: String,
) {
) : Serializable {
fun toDomain(userId: String): DirectMessage {
return DirectMessage(
channelId = channelId,
Expand All @@ -83,16 +122,34 @@ data class DirectMessageTyping(
}
}

@Schema(description = "파일 업로드 요청 DTO")
@JsonSerialize
@JsonDeserialize
data class FileRequest(
@Schema(description = "업로드 이미지 파일", nullable = true)
val image: MultipartFile? = null,

@Schema(description = "썸네일 이미지 파일", nullable = true)
val thumbnail: MultipartFile? = null,

@Schema(description = "사용자 ID", example = "12345")
val userId: Long,

@Schema(description = "사용자 이름", example = "John Doe")
val name: String,

@Schema(description = "메시지 내용", example = "파일 메시지", nullable = true)
val content: String? = null,

@Schema(description = "프로필 이미지 URL", example = "http://example.com/profile.png")
val profileImage: String,

@Schema(description = "채널 ID", example = "channel-12345")
val channelId: String,

@Schema(description = "메시지 타입", example = "FILE")
val fileType: DirectMessageType,
) {
) : Serializable {
fun toDomain(userId: String, type: DirectMessageType): DirectMessage {
return DirectMessage(
userId = userId,
Expand Down
Loading
Loading