Skip to content

Commit 6148225

Browse files
eastshine2741claude
andcommitted
어드민 이메일로 유저 검색 API 추가
본인 로그인 방법(소셜/로컬)을 까먹은 유저 문의 대응 용도. 이메일은 unique 하지 않으므로 다건 응답으로 반환. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent e30aadd commit 6148225

4 files changed

Lines changed: 70 additions & 0 deletions

File tree

api/src/main/kotlin/controller/AdminController.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import com.wafflestudio.snutt.popup.service.PopupService
2121
import com.wafflestudio.snutt.registrationperiod.data.RegistrationDate
2222
import com.wafflestudio.snutt.registrationperiod.data.SemesterRegistrationPeriod
2323
import com.wafflestudio.snutt.registrationperiod.service.SemesterRegistrationPeriodService
24+
import com.wafflestudio.snutt.users.dto.AdminUserSearchResponse
25+
import com.wafflestudio.snutt.users.service.UserService
2426
import notification.dto.InsertNotificationRequest
2527
import org.springframework.http.MediaType
2628
import org.springframework.web.bind.annotation.DeleteMapping
@@ -47,6 +49,7 @@ class AdminController(
4749
private val popupService: PopupService,
4850
private val diaryService: DiaryService,
4951
private val semesterRegistrationPeriodService: SemesterRegistrationPeriodService,
52+
private val userService: UserService,
5053
) {
5154
@PostMapping("/insert_noti")
5255
suspend fun insertNotification(
@@ -179,4 +182,9 @@ class AdminController(
179182
semesterRegistrationPeriodService.delete(year, semester)
180183
return OkResponse()
181184
}
185+
186+
@GetMapping("/users/search")
187+
suspend fun searchUsersByEmail(
188+
@RequestParam email: String,
189+
): List<AdminUserSearchResponse> = userService.getUsersByEmail(email).map { AdminUserSearchResponse.from(it) }
182190
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.wafflestudio.snutt.users.dto
2+
3+
import com.wafflestudio.snutt.auth.AuthProvider
4+
import com.wafflestudio.snutt.users.data.User
5+
import java.time.LocalDateTime
6+
7+
data class AdminUserSearchResponse(
8+
val id: String,
9+
val email: String?,
10+
val isEmailVerified: Boolean?,
11+
val nickname: String,
12+
val localId: String?,
13+
val isAdmin: Boolean,
14+
val active: Boolean,
15+
val regDate: LocalDateTime,
16+
val lastLoginTimestamp: Long,
17+
val authProviders: List<AuthProvider>,
18+
val socialAccounts: SocialAccounts,
19+
) {
20+
data class SocialAccounts(
21+
val googleEmail: String?,
22+
val kakaoEmail: String?,
23+
val appleEmail: String?,
24+
val facebookName: String?,
25+
)
26+
27+
companion object {
28+
fun from(user: User): AdminUserSearchResponse =
29+
AdminUserSearchResponse(
30+
id = user.id!!,
31+
email = user.email,
32+
isEmailVerified = user.isEmailVerified,
33+
nickname = user.nickname,
34+
localId = user.credential.localId,
35+
isAdmin = user.isAdmin,
36+
active = user.active,
37+
regDate = user.regDate,
38+
lastLoginTimestamp = user.lastLoginTimestamp,
39+
authProviders =
40+
listOfNotNull(
41+
user.credential.localId?.let { AuthProvider.LOCAL },
42+
user.credential.fbId?.let { AuthProvider.FACEBOOK },
43+
user.credential.googleSub?.let { AuthProvider.GOOGLE },
44+
user.credential.kakaoSub?.let { AuthProvider.KAKAO },
45+
user.credential.appleSub?.let { AuthProvider.APPLE },
46+
),
47+
socialAccounts =
48+
SocialAccounts(
49+
googleEmail = user.credential.googleEmail,
50+
kakaoEmail = user.credential.kakaoEmail,
51+
appleEmail = user.credential.appleEmail,
52+
facebookName = user.credential.fbName,
53+
),
54+
)
55+
}
56+
}

core/src/main/kotlin/users/repository/UserRepository.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ interface UserRepository : CoroutineCrudRepository<User, String> {
3434

3535
suspend fun findByEmailIgnoreCaseAndIsEmailVerifiedTrueAndActiveTrue(email: String): User?
3636

37+
suspend fun findAllByEmailIgnoreCaseAndActiveTrue(email: String): List<User>
38+
3739
suspend fun existsByCredentialFbIdAndActiveTrue(fbId: String): Boolean
3840

3941
suspend fun existsByCredentialGoogleSubAndActiveTrue(googleSub: String): Boolean

core/src/main/kotlin/users/service/UserService.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ interface UserService {
131131
newPassword: String,
132132
code: String,
133133
)
134+
135+
suspend fun getUsersByEmail(email: String): List<User>
134136
}
135137

136138
@Service
@@ -603,6 +605,8 @@ class UserServiceImpl(
603605
redisTemplate.delete(RESET_PASSWORD_CODE_PREFIX + user.id).subscribe()
604606
}
605607

608+
override suspend fun getUsersByEmail(email: String): List<User> = userRepository.findAllByEmailIgnoreCaseAndActiveTrue(email)
609+
606610
private suspend fun saveNewVerificationValue(
607611
email: String,
608612
code: String,

0 commit comments

Comments
 (0)