Compare commits
No commits in common. "d9f6ac01f45cd4ba8f827ef73800c5486de8f6f3" and "16c5c5f6b66c99d815d716aa87d7c35764a0660d" have entirely different histories.
d9f6ac01f4
...
16c5c5f6b6
|
@ -41,9 +41,6 @@ data class Member(
|
||||||
@OneToMany(mappedBy = "creator")
|
@OneToMany(mappedBy = "creator")
|
||||||
var follower: MutableList<CreatorFollowing> = mutableListOf()
|
var follower: MutableList<CreatorFollowing> = mutableListOf()
|
||||||
|
|
||||||
@OneToMany(mappedBy = "member", cascade = [CascadeType.ALL])
|
|
||||||
val signOutReasons: MutableList<SignOut> = mutableListOf()
|
|
||||||
|
|
||||||
@OneToOne(mappedBy = "member", fetch = FetchType.LAZY)
|
@OneToOne(mappedBy = "member", fetch = FetchType.LAZY)
|
||||||
var notification: MemberNotification? = null
|
var notification: MemberNotification? = null
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ import kr.co.vividnext.sodalive.member.following.CreatorFollowRequest
|
||||||
import kr.co.vividnext.sodalive.member.login.LoginRequest
|
import kr.co.vividnext.sodalive.member.login.LoginRequest
|
||||||
import kr.co.vividnext.sodalive.member.notification.UpdateNotificationSettingRequest
|
import kr.co.vividnext.sodalive.member.notification.UpdateNotificationSettingRequest
|
||||||
import org.springframework.security.core.annotation.AuthenticationPrincipal
|
import org.springframework.security.core.annotation.AuthenticationPrincipal
|
||||||
import org.springframework.security.core.userdetails.User
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping
|
import org.springframework.web.bind.annotation.GetMapping
|
||||||
import org.springframework.web.bind.annotation.PostMapping
|
import org.springframework.web.bind.annotation.PostMapping
|
||||||
import org.springframework.web.bind.annotation.PutMapping
|
import org.springframework.web.bind.annotation.PutMapping
|
||||||
|
@ -41,15 +40,6 @@ class MemberController(private val service: MemberService) {
|
||||||
ApiResponse.ok(service.logout(token.removePrefix("Bearer "), member.id!!))
|
ApiResponse.ok(service.logout(token.removePrefix("Bearer "), member.id!!))
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/logout/all")
|
|
||||||
fun logoutAll(
|
|
||||||
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
|
|
||||||
) = run {
|
|
||||||
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
|
|
||||||
|
|
||||||
ApiResponse.ok(service.logoutAll(member.id!!))
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/info")
|
@GetMapping("/info")
|
||||||
fun getMemberInfo(
|
fun getMemberInfo(
|
||||||
@RequestParam container: String?,
|
@RequestParam container: String?,
|
||||||
|
@ -145,10 +135,4 @@ class MemberController(private val service: MemberService) {
|
||||||
|
|
||||||
ApiResponse.ok(service.searchMember(nickname = nickname, memberId = member.id!!))
|
ApiResponse.ok(service.searchMember(nickname = nickname, memberId = member.id!!))
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/sign_out")
|
|
||||||
fun signOut(
|
|
||||||
@RequestBody signOutRequest: SignOutRequest,
|
|
||||||
@AuthenticationPrincipal user: User
|
|
||||||
) = ApiResponse.ok(service.signOut(signOutRequest, user), "정상적으로 탈퇴 처리되었습니다.")
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,6 @@ import org.springframework.data.repository.findByIdOrNull
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
|
||||||
import org.springframework.security.core.context.SecurityContextHolder
|
import org.springframework.security.core.context.SecurityContextHolder
|
||||||
import org.springframework.security.core.userdetails.User
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails
|
import org.springframework.security.core.userdetails.UserDetails
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService
|
import org.springframework.security.core.userdetails.UserDetailsService
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException
|
import org.springframework.security.core.userdetails.UsernameNotFoundException
|
||||||
|
@ -52,7 +51,6 @@ class MemberService(
|
||||||
private val stipulationAgreeRepository: StipulationAgreeRepository,
|
private val stipulationAgreeRepository: StipulationAgreeRepository,
|
||||||
private val creatorFollowingRepository: CreatorFollowingRepository,
|
private val creatorFollowingRepository: CreatorFollowingRepository,
|
||||||
private val blockMemberRepository: BlockMemberRepository,
|
private val blockMemberRepository: BlockMemberRepository,
|
||||||
private val signOutRepository: SignOutRepository,
|
|
||||||
|
|
||||||
private val memberNotificationService: MemberNotificationService,
|
private val memberNotificationService: MemberNotificationService,
|
||||||
|
|
||||||
|
@ -378,36 +376,7 @@ class MemberService(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
|
||||||
fun logoutAll(memberId: Long) {
|
|
||||||
val member = repository.findByIdOrNull(memberId)
|
|
||||||
?: throw SodaException("로그인 정보를 확인해주세요.")
|
|
||||||
|
|
||||||
member.pushToken = null
|
|
||||||
|
|
||||||
val lock = getOrCreateLock(memberId = memberId)
|
|
||||||
lock.write { tokenRepository.deleteById(memberId) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getOrCreateLock(memberId: Long): ReentrantReadWriteLock {
|
private fun getOrCreateLock(memberId: Long): ReentrantReadWriteLock {
|
||||||
return tokenLocks.computeIfAbsent(memberId) { ReentrantReadWriteLock() }
|
return tokenLocks.computeIfAbsent(memberId) { ReentrantReadWriteLock() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
|
||||||
fun signOut(signOutRequest: SignOutRequest, user: User) {
|
|
||||||
val member = repository.findByEmail(user.username) ?: throw SodaException("로그인 정보를 확인해주세요.")
|
|
||||||
if (!passwordEncoder.matches(signOutRequest.password, member.password)) {
|
|
||||||
throw SodaException("비밀번호가 일치하지 않습니다.")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (signOutRequest.reason.isBlank()) {
|
|
||||||
throw SodaException("탈퇴하려는 이유를 입력해 주세요.")
|
|
||||||
}
|
|
||||||
|
|
||||||
member.isActive = false
|
|
||||||
|
|
||||||
val signOut = SignOut(reason = signOutRequest.reason)
|
|
||||||
signOut.member = member
|
|
||||||
signOutRepository.save(signOut)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
package kr.co.vividnext.sodalive.member
|
|
||||||
|
|
||||||
import kr.co.vividnext.sodalive.common.BaseEntity
|
|
||||||
import javax.persistence.Column
|
|
||||||
import javax.persistence.Entity
|
|
||||||
import javax.persistence.FetchType
|
|
||||||
import javax.persistence.JoinColumn
|
|
||||||
import javax.persistence.ManyToOne
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
data class SignOut(
|
|
||||||
@Column(columnDefinition = "TEXT", nullable = false)
|
|
||||||
val reason: String
|
|
||||||
) : BaseEntity() {
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
|
||||||
@JoinColumn(name = "member_id", nullable = false)
|
|
||||||
var member: Member? = null
|
|
||||||
set(value) {
|
|
||||||
value?.signOutReasons?.add(this)
|
|
||||||
field = value
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
package kr.co.vividnext.sodalive.member
|
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository
|
|
||||||
import org.springframework.stereotype.Repository
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
interface SignOutRepository : JpaRepository<SignOut, Long>
|
|
|
@ -1,6 +0,0 @@
|
||||||
package kr.co.vividnext.sodalive.member
|
|
||||||
|
|
||||||
data class SignOutRequest(
|
|
||||||
val reason: String,
|
|
||||||
val password: String
|
|
||||||
)
|
|
|
@ -1,10 +0,0 @@
|
||||||
package kr.co.vividnext.sodalive.notice
|
|
||||||
|
|
||||||
data class CreateNoticeRequest(
|
|
||||||
val title: String,
|
|
||||||
val content: String
|
|
||||||
) {
|
|
||||||
fun toEntity(): ServiceNotice {
|
|
||||||
return ServiceNotice(title, content)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
package kr.co.vividnext.sodalive.notice
|
|
||||||
|
|
||||||
data class GetNoticeResponse(
|
|
||||||
val totalCount: Int,
|
|
||||||
val noticeList: List<NoticeItem>
|
|
||||||
)
|
|
||||||
|
|
||||||
data class NoticeItem(
|
|
||||||
val id: Long,
|
|
||||||
val title: String,
|
|
||||||
val content: String,
|
|
||||||
val date: String
|
|
||||||
)
|
|
|
@ -1,15 +0,0 @@
|
||||||
package kr.co.vividnext.sodalive.notice
|
|
||||||
|
|
||||||
import kr.co.vividnext.sodalive.common.BaseEntity
|
|
||||||
import javax.persistence.Column
|
|
||||||
import javax.persistence.Entity
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
data class ServiceNotice(
|
|
||||||
@Column(nullable = false)
|
|
||||||
var title: String,
|
|
||||||
@Column(columnDefinition = "TEXT", nullable = false)
|
|
||||||
var content: String,
|
|
||||||
@Column(nullable = false)
|
|
||||||
var isActive: Boolean = true
|
|
||||||
) : BaseEntity()
|
|
|
@ -1,38 +0,0 @@
|
||||||
package kr.co.vividnext.sodalive.notice
|
|
||||||
|
|
||||||
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.DeleteMapping
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping
|
|
||||||
import org.springframework.web.bind.annotation.PutMapping
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping
|
|
||||||
import org.springframework.web.bind.annotation.RestController
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/notice")
|
|
||||||
class ServiceNoticeController(private val service: ServiceNoticeService) {
|
|
||||||
@PostMapping
|
|
||||||
@PreAuthorize("hasRole('ADMIN')")
|
|
||||||
fun createNotice(@RequestBody request: CreateNoticeRequest) = ApiResponse.ok(
|
|
||||||
service.save(request),
|
|
||||||
"등록되었습니다."
|
|
||||||
)
|
|
||||||
|
|
||||||
@PutMapping
|
|
||||||
@PreAuthorize("hasRole('ADMIN')")
|
|
||||||
fun updateNotice(@RequestBody request: UpdateNoticeRequest) = ApiResponse.ok(
|
|
||||||
service.update(request),
|
|
||||||
"수정되었습니다."
|
|
||||||
)
|
|
||||||
|
|
||||||
@DeleteMapping("/{id}")
|
|
||||||
@PreAuthorize("hasRole('ADMIN')")
|
|
||||||
fun deleteCoin(@PathVariable id: Long) = ApiResponse.ok(service.delete(id), "삭제되었습니다.")
|
|
||||||
|
|
||||||
@GetMapping
|
|
||||||
fun getNoticeList(pageable: Pageable, timezone: String) = ApiResponse.ok(service.getNoticeList(pageable, timezone))
|
|
||||||
}
|
|
|
@ -1,66 +0,0 @@
|
||||||
package kr.co.vividnext.sodalive.notice
|
|
||||||
|
|
||||||
import kr.co.vividnext.sodalive.common.SodaException
|
|
||||||
import org.springframework.data.domain.Pageable
|
|
||||||
import org.springframework.data.repository.findByIdOrNull
|
|
||||||
import org.springframework.stereotype.Service
|
|
||||||
import org.springframework.transaction.annotation.Transactional
|
|
||||||
import java.time.ZoneId
|
|
||||||
import java.time.format.DateTimeFormatter
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@Transactional(readOnly = true)
|
|
||||||
class ServiceNoticeService(private val repository: ServiceServiceNoticeRepository) {
|
|
||||||
@Transactional
|
|
||||||
fun save(request: CreateNoticeRequest): Long {
|
|
||||||
if (request.title.isBlank()) throw SodaException("제목을 입력하세요.")
|
|
||||||
if (request.content.isBlank()) throw SodaException("내용을 입력하세요.")
|
|
||||||
|
|
||||||
val notice = request.toEntity()
|
|
||||||
return repository.save(notice).id!!
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
fun update(request: UpdateNoticeRequest) {
|
|
||||||
if (request.id <= 0) throw SodaException("잘못된 요청입니다.")
|
|
||||||
if (request.title.isNullOrBlank() && request.content.isNullOrBlank()) {
|
|
||||||
throw SodaException("수정할 내용을 입력하세요.")
|
|
||||||
}
|
|
||||||
|
|
||||||
val notice = repository.findByIdOrNull(request.id)
|
|
||||||
?: throw SodaException("잘못된 요청입니다.")
|
|
||||||
|
|
||||||
if (!request.title.isNullOrBlank()) notice.title = request.title
|
|
||||||
if (!request.content.isNullOrBlank()) notice.content = request.content
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
fun delete(id: Long) {
|
|
||||||
if (id <= 0) throw SodaException("잘못된 요청입니다.")
|
|
||||||
val notice = repository.findByIdOrNull(id)
|
|
||||||
?: throw SodaException("잘못된 요청입니다.")
|
|
||||||
|
|
||||||
notice.isActive = false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getNoticeList(pageable: Pageable, timezone: String): GetNoticeResponse {
|
|
||||||
val totalCount = repository.getNoticeTotalCount()
|
|
||||||
val noticeList = repository.getNoticeList(pageable)
|
|
||||||
.asSequence()
|
|
||||||
.map {
|
|
||||||
val createdAt = it.createdAt!!
|
|
||||||
.atZone(ZoneId.of("UTC"))
|
|
||||||
.withZoneSameInstant(ZoneId.of(timezone))
|
|
||||||
|
|
||||||
NoticeItem(
|
|
||||||
it.id!!,
|
|
||||||
it.title,
|
|
||||||
it.content,
|
|
||||||
createdAt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.toList()
|
|
||||||
|
|
||||||
return GetNoticeResponse(totalCount, noticeList)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
package kr.co.vividnext.sodalive.notice
|
|
||||||
|
|
||||||
import com.querydsl.jpa.impl.JPAQueryFactory
|
|
||||||
import kr.co.vividnext.sodalive.notice.QServiceNotice.serviceNotice
|
|
||||||
import org.springframework.data.domain.Pageable
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository
|
|
||||||
import org.springframework.stereotype.Repository
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
interface ServiceServiceNoticeRepository : JpaRepository<ServiceNotice, Long>, ServiceNoticeQueryRepository
|
|
||||||
|
|
||||||
interface ServiceNoticeQueryRepository {
|
|
||||||
fun getNoticeTotalCount(): Int
|
|
||||||
fun getNoticeList(pageable: Pageable): List<ServiceNotice>
|
|
||||||
}
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
class ServiceNoticeQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : ServiceNoticeQueryRepository {
|
|
||||||
override fun getNoticeTotalCount(): Int {
|
|
||||||
return queryFactory
|
|
||||||
.select(serviceNotice.id)
|
|
||||||
.from(serviceNotice)
|
|
||||||
.where(serviceNotice.isActive.isTrue)
|
|
||||||
.fetch()
|
|
||||||
.size
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getNoticeList(pageable: Pageable): List<ServiceNotice> {
|
|
||||||
return queryFactory
|
|
||||||
.selectFrom(serviceNotice)
|
|
||||||
.where(serviceNotice.isActive.isTrue)
|
|
||||||
.offset(pageable.offset)
|
|
||||||
.limit(pageable.pageSize.toLong())
|
|
||||||
.orderBy(serviceNotice.id.desc())
|
|
||||||
.fetch()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
package kr.co.vividnext.sodalive.notice
|
|
||||||
|
|
||||||
data class UpdateNoticeRequest(
|
|
||||||
val id: Long,
|
|
||||||
val title: String? = null,
|
|
||||||
val content: String? = null
|
|
||||||
)
|
|
Loading…
Reference in New Issue