관리자 - 회원리스트 API

This commit is contained in:
Klaus 2023-08-06 11:13:27 +09:00
parent 9b4e2fd192
commit cbcc63dc71
4 changed files with 229 additions and 0 deletions

View File

@ -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))
}

View File

@ -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
}
}

View File

@ -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()
}
}

View File

@ -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
)