관리자 - 회원리스트 API
This commit is contained in:
parent
9b4e2fd192
commit
cbcc63dc71
|
@ -0,0 +1,23 @@
|
||||||
|
package kr.co.vividnext.sodalive.admin.member
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.common.ApiResponse
|
||||||
|
import org.springframework.data.domain.Pageable
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam
|
||||||
|
import org.springframework.web.bind.annotation.RestController
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/admin/member")
|
||||||
|
class AdminMemberController(private val service: AdminMemberService) {
|
||||||
|
@GetMapping("/list")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
fun getMemberList(pageable: Pageable) = ApiResponse.ok(service.getMemberList(pageable))
|
||||||
|
|
||||||
|
@GetMapping("/search")
|
||||||
|
fun searchMember(
|
||||||
|
@RequestParam(value = "search_word") searchWord: String,
|
||||||
|
pageable: Pageable
|
||||||
|
) = ApiResponse.ok(service.searchMember(searchWord, pageable))
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
package kr.co.vividnext.sodalive.admin.member
|
||||||
|
|
||||||
|
import com.querydsl.jpa.impl.JPAQueryFactory
|
||||||
|
import kr.co.vividnext.sodalive.member.Member
|
||||||
|
import kr.co.vividnext.sodalive.member.MemberRole
|
||||||
|
import kr.co.vividnext.sodalive.member.QMember.member
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository
|
||||||
|
|
||||||
|
interface AdminMemberRepository : JpaRepository<Member, Long>, AdminMemberQueryRepository
|
||||||
|
|
||||||
|
interface AdminMemberQueryRepository {
|
||||||
|
fun getMemberTotalCount(role: MemberRole? = null): Int
|
||||||
|
fun getMemberList(offset: Long, limit: Long, role: MemberRole? = null): List<Member>
|
||||||
|
fun searchMember(searchWord: String, offset: Long, limit: Long, role: MemberRole? = null): List<Member>
|
||||||
|
|
||||||
|
fun searchMemberTotalCount(searchWord: String, role: MemberRole? = null): Int
|
||||||
|
}
|
||||||
|
|
||||||
|
class AdminMemberQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : AdminMemberQueryRepository {
|
||||||
|
override fun getMemberList(offset: Long, limit: Long, role: MemberRole?): List<Member> {
|
||||||
|
return queryFactory
|
||||||
|
.selectFrom(member)
|
||||||
|
.where(
|
||||||
|
member.role.ne(MemberRole.ADMIN)
|
||||||
|
.and(
|
||||||
|
if (role != null) {
|
||||||
|
member.role.eq(role)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.offset(offset)
|
||||||
|
.limit(limit)
|
||||||
|
.orderBy(member.id.desc())
|
||||||
|
.fetch()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getMemberTotalCount(role: MemberRole?): Int {
|
||||||
|
return queryFactory
|
||||||
|
.select(member.id)
|
||||||
|
.from(member)
|
||||||
|
.where(
|
||||||
|
member.id.gt(1)
|
||||||
|
.and(
|
||||||
|
if (role != null) {
|
||||||
|
member.role.eq(role)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.fetch()
|
||||||
|
.size
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun searchMember(searchWord: String, offset: Long, limit: Long, role: MemberRole?): List<Member> {
|
||||||
|
return queryFactory
|
||||||
|
.selectFrom(member)
|
||||||
|
.where(
|
||||||
|
member.nickname.contains(searchWord)
|
||||||
|
.or(member.email.contains(searchWord))
|
||||||
|
.and(
|
||||||
|
if (role != null) {
|
||||||
|
member.role.eq(role)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.offset(offset)
|
||||||
|
.limit(limit)
|
||||||
|
.orderBy(member.id.desc())
|
||||||
|
.fetch()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun searchMemberTotalCount(searchWord: String, role: MemberRole?): Int {
|
||||||
|
return queryFactory
|
||||||
|
.select(member.id)
|
||||||
|
.from(member)
|
||||||
|
.where(
|
||||||
|
member.nickname.contains(searchWord)
|
||||||
|
.or(member.email.contains(searchWord))
|
||||||
|
.and(
|
||||||
|
if (role != null) {
|
||||||
|
member.role.eq(role)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.fetch()
|
||||||
|
.size
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
package kr.co.vividnext.sodalive.admin.member
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaException
|
||||||
|
import kr.co.vividnext.sodalive.member.Member
|
||||||
|
import kr.co.vividnext.sodalive.member.MemberRole
|
||||||
|
import org.springframework.beans.factory.annotation.Value
|
||||||
|
import org.springframework.data.domain.Pageable
|
||||||
|
import org.springframework.stereotype.Service
|
||||||
|
import java.time.ZoneId
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
|
@Service
|
||||||
|
class AdminMemberService(
|
||||||
|
private val repository: AdminMemberRepository,
|
||||||
|
|
||||||
|
@Value("\${cloud.aws.cloud-front.host}")
|
||||||
|
private val cloudFrontHost: String
|
||||||
|
) {
|
||||||
|
fun getMemberList(pageable: Pageable): GetAdminMemberListResponse {
|
||||||
|
val totalCount = repository.getMemberTotalCount()
|
||||||
|
val memberList = processMemberListToGetAdminMemberListResponseItemList(
|
||||||
|
memberList = repository.getMemberList(
|
||||||
|
offset = pageable.offset,
|
||||||
|
limit = pageable.pageSize.toLong()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return GetAdminMemberListResponse(totalCount, memberList)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun searchMember(searchWord: String, pageable: Pageable): GetAdminMemberListResponse {
|
||||||
|
if (searchWord.length < 2) throw SodaException("2글자 이상 입력하세요.")
|
||||||
|
val totalCount = repository.searchMemberTotalCount(searchWord = searchWord)
|
||||||
|
val memberList = processMemberListToGetAdminMemberListResponseItemList(
|
||||||
|
memberList = repository.searchMember(
|
||||||
|
searchWord = searchWord,
|
||||||
|
offset = pageable.offset,
|
||||||
|
limit = pageable.pageSize.toLong()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return GetAdminMemberListResponse(totalCount, memberList)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun processMemberListToGetAdminMemberListResponseItemList(
|
||||||
|
memberList: List<Member>
|
||||||
|
): List<GetAdminMemberListResponseItem> {
|
||||||
|
return memberList
|
||||||
|
.asSequence()
|
||||||
|
.map {
|
||||||
|
val userType = when (it.role) {
|
||||||
|
MemberRole.ADMIN -> "관리자"
|
||||||
|
MemberRole.USER -> "일반회원"
|
||||||
|
MemberRole.CREATOR -> "요즘친구"
|
||||||
|
MemberRole.AGENT -> "에이전트"
|
||||||
|
MemberRole.BOT -> "봇"
|
||||||
|
}
|
||||||
|
|
||||||
|
val signUpDate = it.createdAt!!
|
||||||
|
.atZone(ZoneId.of("UTC"))
|
||||||
|
.withZoneSameInstant(ZoneId.of("Asia/Seoul"))
|
||||||
|
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"))
|
||||||
|
|
||||||
|
val signOutDate = if (it.signOutReasons.isNotEmpty()) {
|
||||||
|
it.signOutReasons.last().createdAt!!
|
||||||
|
.atZone(ZoneId.of("UTC"))
|
||||||
|
.withZoneSameInstant(ZoneId.of("Asia/Seoul"))
|
||||||
|
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"))
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
|
||||||
|
GetAdminMemberListResponseItem(
|
||||||
|
id = it.id!!,
|
||||||
|
email = it.email,
|
||||||
|
nickname = it.nickname,
|
||||||
|
profileUrl = if (it.profileImage != null) {
|
||||||
|
"$cloudFrontHost/${it.profileImage}"
|
||||||
|
} else {
|
||||||
|
"$cloudFrontHost/profile/default-profile.png"
|
||||||
|
},
|
||||||
|
userType = userType,
|
||||||
|
container = it.container,
|
||||||
|
auth = it.auth != null,
|
||||||
|
signUpDate = signUpDate,
|
||||||
|
signOutDate = signOutDate,
|
||||||
|
isActive = it.isActive
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.toList()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package kr.co.vividnext.sodalive.admin.member
|
||||||
|
|
||||||
|
data class GetAdminMemberListResponse(
|
||||||
|
val totalCount: Int,
|
||||||
|
val items: List<GetAdminMemberListResponseItem>
|
||||||
|
)
|
||||||
|
|
||||||
|
data class GetAdminMemberListResponseItem(
|
||||||
|
val id: Long,
|
||||||
|
val email: String,
|
||||||
|
val nickname: String,
|
||||||
|
val profileUrl: String,
|
||||||
|
val userType: String,
|
||||||
|
val container: String,
|
||||||
|
val auth: Boolean,
|
||||||
|
val signUpDate: String,
|
||||||
|
val signOutDate: String,
|
||||||
|
val isActive: Boolean
|
||||||
|
)
|
Loading…
Reference in New Issue