로그아웃 추가
서블릿 필터에서 Exception 발생시 처리
This commit is contained in:
@@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.GetMapping
|
||||
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.RequestHeader
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RequestParam
|
||||
import org.springframework.web.bind.annotation.RequestPart
|
||||
@@ -29,6 +30,16 @@ class MemberController(private val service: MemberService) {
|
||||
@PostMapping("/login")
|
||||
fun login(@RequestBody loginRequest: LoginRequest) = service.login(loginRequest)
|
||||
|
||||
@PostMapping("/logout")
|
||||
fun logout(
|
||||
@RequestHeader("Authorization") token: String,
|
||||
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
|
||||
) = run {
|
||||
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
|
||||
|
||||
ApiResponse.ok(service.logout(token.removePrefix("Bearer "), member.id!!))
|
||||
}
|
||||
|
||||
@GetMapping("/info")
|
||||
fun getMemberInfo(
|
||||
@RequestParam container: String?,
|
||||
|
@@ -25,6 +25,7 @@ import kr.co.vividnext.sodalive.member.stipulation.StipulationAgree
|
||||
import kr.co.vividnext.sodalive.member.stipulation.StipulationAgreeRepository
|
||||
import kr.co.vividnext.sodalive.member.stipulation.StipulationIds
|
||||
import kr.co.vividnext.sodalive.member.stipulation.StipulationRepository
|
||||
import kr.co.vividnext.sodalive.member.token.MemberTokenRepository
|
||||
import kr.co.vividnext.sodalive.utils.generateFileName
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.data.repository.findByIdOrNull
|
||||
@@ -38,11 +39,14 @@ import org.springframework.security.crypto.password.PasswordEncoder
|
||||
import org.springframework.stereotype.Service
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
import org.springframework.web.multipart.MultipartFile
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||
import kotlin.concurrent.write
|
||||
|
||||
@Service
|
||||
@Transactional(readOnly = true)
|
||||
class MemberService(
|
||||
private val repository: MemberRepository,
|
||||
private val tokenRepository: MemberTokenRepository,
|
||||
private val stipulationRepository: StipulationRepository,
|
||||
private val stipulationAgreeRepository: StipulationAgreeRepository,
|
||||
private val creatorFollowingRepository: CreatorFollowingRepository,
|
||||
@@ -64,6 +68,9 @@ class MemberService(
|
||||
@Value("\${cloud.aws.cloud-front.host}")
|
||||
private val cloudFrontHost: String
|
||||
) : UserDetailsService {
|
||||
|
||||
private val tokenLocks: MutableMap<Long, ReentrantReadWriteLock> = mutableMapOf()
|
||||
|
||||
@Transactional
|
||||
fun signUp(
|
||||
profileImage: MultipartFile?,
|
||||
@@ -349,4 +356,27 @@ class MemberService(
|
||||
}
|
||||
.toList()
|
||||
}
|
||||
|
||||
@Transactional
|
||||
fun logout(token: String, memberId: Long) {
|
||||
val member = repository.findByIdOrNull(memberId)
|
||||
?: throw SodaException("로그인 정보를 확인해주세요.")
|
||||
|
||||
member.pushToken = null
|
||||
|
||||
val lock = getOrCreateLock(memberId = memberId)
|
||||
lock.write {
|
||||
val memberToken = tokenRepository.findByIdOrNull(memberId)
|
||||
?: throw SodaException("로그인 정보를 확인해주세요.")
|
||||
|
||||
val memberTokenSet = memberToken.tokenList.toMutableSet()
|
||||
memberTokenSet.remove(token)
|
||||
memberToken.tokenList = memberTokenSet.toList()
|
||||
tokenRepository.save(memberToken)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getOrCreateLock(memberId: Long): ReentrantReadWriteLock {
|
||||
return tokenLocks.computeIfAbsent(memberId) { ReentrantReadWriteLock() }
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user