Skip to content

Commit 9342649

Browse files
authored
Merge pull request GoodSpace-Kr#180 from kjoon418/main
feat: ID를 통해 회원 정보를 조회하는 API 구현
2 parents 6771141 + 135414c commit 9342649

File tree

10 files changed

+78
-26
lines changed

10 files changed

+78
-26
lines changed

src/main/kotlin/goodspace/teaming/chat/domain/mapper/SenderSummaryMapper.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ import org.springframework.stereotype.Component
1010
class SenderSummaryMapper(
1111
private val urlProvider: CdnStorageUrlProvider
1212
) {
13-
fun map(user: User, size: Int = 64): SenderSummaryResponseDto {
13+
fun map(user: User?, size: Int = 64): SenderSummaryResponseDto? {
14+
if (user == null) {
15+
return null
16+
}
17+
1418
return SenderSummaryResponseDto(
1519
id = user.id,
1620
name = user.name,

src/main/kotlin/goodspace/teaming/chat/dto/ChatMessageResponseDto.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ data class ChatMessageResponseDto(
1010
val type: MessageType,
1111
val content: String?,
1212
val createdAt: Instant,
13-
val sender: SenderSummaryResponseDto,
13+
val sender: SenderSummaryResponseDto?,
1414
val attachments: List<MessageAttachmentResponseDto> = emptyList()
1515
)

src/main/kotlin/goodspace/teaming/chat/dto/LastMessagePreviewResponseDto.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ data class LastMessagePreviewResponseDto(
77
val id: Long,
88
val type: MessageType,
99
val content: String?,
10-
val sender: SenderSummaryResponseDto,
10+
val sender: SenderSummaryResponseDto?,
1111
val createdAt: Instant
1212
)

src/main/kotlin/goodspace/teaming/global/entity/room/Message.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ import org.hibernate.annotations.SQLRestriction
2323
@SQLRestriction("deleted = false")
2424
class Message(
2525
@ManyToOne(fetch = LAZY)
26-
@JoinColumn(name = "sender_id", nullable = false)
27-
val sender: User,
26+
@JoinColumn(name = "sender_id")
27+
val sender: User?,
2828

2929
@ManyToOne(fetch = LAZY)
3030
@JoinColumn(nullable = false)

src/main/kotlin/goodspace/teaming/user/controller/UserController.kt

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@ package goodspace.teaming.user.controller
33
import goodspace.teaming.authorization.dto.AccessTokenReissueRequestDto
44
import goodspace.teaming.authorization.dto.AccessTokenResponseDto
55
import goodspace.teaming.global.security.userId
6-
import goodspace.teaming.user.dto.UpdateEmailRequestDto
7-
import goodspace.teaming.user.dto.UpdateNameRequestDto
8-
import goodspace.teaming.user.dto.UpdatePasswordRequestDto
9-
import goodspace.teaming.user.dto.UserInfoResponseDto
6+
import goodspace.teaming.user.dto.*
107
import goodspace.teaming.user.service.TokenManagementService
118
import goodspace.teaming.user.service.UserService
129
import io.swagger.v3.oas.annotations.Operation
@@ -18,7 +15,7 @@ import java.security.Principal
1815
private val NO_CONTENT = ResponseEntity.noContent().build<Void>()
1916

2017
@RestController
21-
@RequestMapping("/users/me")
18+
@RequestMapping("/users")
2219
@Tag(
2320
name = "회원 API",
2421
description = "회원 정보 조회 및 삭제 기능(아바타 수정은 파일 API에서 담당합니다)"
@@ -27,7 +24,7 @@ class UserController(
2724
private val userService: UserService,
2825
private val tokenManagementService: TokenManagementService
2926
) {
30-
@GetMapping
27+
@GetMapping("/me")
3128
@Operation(
3229
summary = "회원 정보 조회"
3330
)
@@ -41,7 +38,20 @@ class UserController(
4138
return ResponseEntity.ok(response)
4239
}
4340

44-
@PatchMapping("/email")
41+
@GetMapping
42+
@Operation(
43+
summary = "다른 회원 정보 조회",
44+
description = "ID를 기반으로 다른 회원의 정보를 조회합니다. (방을 탈퇴한 멤버의 정보를 조회할 때 사용)"
45+
)
46+
fun getOtherInfo(
47+
@RequestBody requestDto: UserInfoRequestDto
48+
): ResponseEntity<List<UserInfoResponseDto>> {
49+
val response = userService.getUserInfo(requestDto)
50+
51+
return ResponseEntity.ok(response)
52+
}
53+
54+
@PatchMapping("/me/email")
4555
@Operation(
4656
summary = "이메일 수정",
4757
description = "이메일을 수정합니다. 새롭게 등록할 이메일이 인증되어 있어야 합니다."
@@ -57,7 +67,7 @@ class UserController(
5767
return NO_CONTENT
5868
}
5969

60-
@PatchMapping("/password")
70+
@PatchMapping("/me/password")
6171
@Operation(
6272
summary = "비밀번호 수정",
6373
description = "비밀번호를 수정합니다. 기존 비밀번호가 올바라야 합니다."
@@ -73,7 +83,7 @@ class UserController(
7383
return NO_CONTENT
7484
}
7585

76-
@PatchMapping("/name")
86+
@PatchMapping("/me/name")
7787
@Operation(
7888
summary = "이름 수정",
7989
)
@@ -88,7 +98,7 @@ class UserController(
8898
return NO_CONTENT
8999
}
90100

91-
@PostMapping("/access-token")
101+
@PostMapping("/me/access-token")
92102
@Operation(
93103
summary = "엑세스 토큰 재발급",
94104
description = "리프레쉬 토큰을 통해 엑세스 토큰을 재발급합니다."
@@ -101,7 +111,7 @@ class UserController(
101111
return ResponseEntity.ok(response)
102112
}
103113

104-
@DeleteMapping("/log-out")
114+
@DeleteMapping("/me/log-out")
105115
@Operation(
106116
summary = "로그아웃(리프레쉬 토큰 만료)",
107117
description = "리프레쉬 토큰을 만료시킵니다. 엑세스 토큰은 클라이언트 단에서 직접 처분해야 합니다."
@@ -116,7 +126,7 @@ class UserController(
116126
return NO_CONTENT
117127
}
118128

119-
@DeleteMapping("/withdraw")
129+
@DeleteMapping("/me/withdraw")
120130
@Operation(
121131
summary = "회원 탈퇴",
122132
description = "회원을 삭제합니다. 결제한 금액을 환불받지 못함을 고지해야 합니다."
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package goodspace.teaming.user.dto
2+
3+
data class UserInfoRequestDto(
4+
val ids: List<Long>
5+
)

src/main/kotlin/goodspace/teaming/user/service/UserService.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ interface UserService {
77
userId: Long
88
): UserInfoResponseDto
99

10+
fun getUserInfo(
11+
requestDto: UserInfoRequestDto
12+
): List<UserInfoResponseDto>
13+
1014
fun updateEmail(
1115
userId: Long,
1216
requestDto: UpdateEmailRequestDto

src/main/kotlin/goodspace/teaming/user/service/UserServiceImpl.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ class UserServiceImpl(
2828
return userInfoMapper.map(user)
2929
}
3030

31+
@Transactional(readOnly = true)
32+
override fun getUserInfo(requestDto: UserInfoRequestDto): List<UserInfoResponseDto> {
33+
return requestDto.ids.stream()
34+
.map { findUser(it) }
35+
.map { userInfoMapper.map(it) }
36+
.toList()
37+
}
38+
3139
@Transactional
3240
override fun updateEmail(userId: Long, requestDto: UpdateEmailRequestDto) {
3341
val user = findUser(userId)

src/test/kotlin/goodspace/teaming/chat/domain/mapper/SenderSummaryMapperTest.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class SenderSummaryMapperTest {
4848
)
4949

5050
// when
51-
val result = mapper.map(user, DEFAULT_SIZE)
51+
val result = mapper.map(user, DEFAULT_SIZE)!!
5252

5353
// then
5454
assertThat(result.id).isEqualTo(DEFAULT_USER_ID)
@@ -70,7 +70,7 @@ class SenderSummaryMapperTest {
7070
)
7171

7272
// when
73-
val result = mapper.map(user, size = CUSTOM_SIZE)
73+
val result = mapper.map(user, size = CUSTOM_SIZE)!!
7474

7575
// then
7676
assertThat(result.avatarUrl).isEqualTo(DEFAULT_PUBLIC_URL)
@@ -93,7 +93,7 @@ class SenderSummaryMapperTest {
9393
)
9494

9595
// when
96-
val result = mapper.map(user)
96+
val result = mapper.map(user)!!
9797

9898
// then
9999
assertThat(result.avatarUrl).isNull()

src/test/kotlin/goodspace/teaming/user/service/UserServiceTest.kt

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package goodspace.teaming.user.service
33
import goodspace.teaming.fixture.*
44
import goodspace.teaming.global.entity.email.EmailVerification
55
import goodspace.teaming.global.entity.user.TeamingUser
6+
import goodspace.teaming.global.entity.user.User
67
import goodspace.teaming.global.entity.user.UserType
78
import goodspace.teaming.global.exception.NOT_VERIFIED_EMAIL
89
import goodspace.teaming.global.exception.OAUTH_USER_CANNOT_CHANGE_PASSWORD
@@ -11,10 +12,7 @@ import goodspace.teaming.global.password.PasswordValidatorImpl
1112
import goodspace.teaming.global.repository.EmailVerificationRepository
1213
import goodspace.teaming.global.repository.UserRepository
1314
import goodspace.teaming.user.domain.mapper.UserInfoMapper
14-
import goodspace.teaming.user.dto.UpdateEmailRequestDto
15-
import goodspace.teaming.user.dto.UpdateNameRequestDto
16-
import goodspace.teaming.user.dto.UpdatePasswordRequestDto
17-
import goodspace.teaming.user.dto.UserInfoResponseDto
15+
import goodspace.teaming.user.dto.*
1816
import goodspace.teaming.util.createEmailVerification
1917
import goodspace.teaming.util.createRoom
2018
import goodspace.teaming.util.createUser
@@ -46,7 +44,7 @@ class UserServiceTest {
4644
private val emailVerificationRepository = mockk<EmailVerificationRepository>(relaxed = true)
4745
private val passwordEncoder = mockk<PasswordEncoder>()
4846
private val passwordValidator = mockk<PasswordValidatorImpl>()
49-
private val userInfoMapper = mockk<UserInfoMapper>()
47+
private val userInfoMapper = mockk<UserInfoMapper>(relaxed = true)
5048

5149
private val userService = UserServiceImpl(
5250
userRepository = userRepository,
@@ -60,7 +58,7 @@ class UserServiceTest {
6058
@DisplayName("getUserInfo")
6159
inner class GetUserInfo {
6260
@Test
63-
fun `회원 정보를 DTO로 매핑해 반환한다`() {
61+
fun `ID에 대한 회원 정보를 반환한다`() {
6462
// given
6563
val user = createUser(id = USER_ID)
6664
val userId = user.id!!
@@ -75,6 +73,29 @@ class UserServiceTest {
7573
// then
7674
assertThat(actualResponse).isEqualTo(expectedResponse)
7775
}
76+
77+
@Test
78+
fun `ID 목록에 대한 회원 정보 목록을 반환한다`() {
79+
// given
80+
val user1 = createUser(id = 1)
81+
val user2 = createUser(id = 2)
82+
val user3 = createUser(id = 3)
83+
val userIds = listOf(user1.id!!, user2.id!!, user3.id!!)
84+
85+
every { userRepository.findById(user1.id!!) } returns Optional.of(user1)
86+
every { userRepository.findById(user2.id!!) } returns Optional.of(user2)
87+
every { userRepository.findById(user3.id!!) } returns Optional.of(user3)
88+
89+
val requestDto = UserInfoRequestDto(
90+
ids = userIds
91+
)
92+
93+
// when
94+
val response = userService.getUserInfo(requestDto)
95+
96+
// then
97+
assertThat(response).hasSameSizeAs(userIds)
98+
}
7899
}
79100

80101
@Nested

0 commit comments

Comments
 (0)