Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

๐Ÿ”€ :: 161 - ๋กœ๊ทธ์ธ ์š”์ฒญ ๋งŽ์ด ๋“ค์–ด์˜ฌ๋•Œ ๊ณ„์ • ์ •์ง€ #162

Merged
merged 9 commits into from
May 30, 2023
Merged
17 changes: 17 additions & 0 deletions src/main/kotlin/com/msg/gauth/domain/auth/MinuteSignInCount.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.msg.gauth.domain.auth

import org.springframework.data.annotation.Id
import org.springframework.data.redis.core.RedisHash
import org.springframework.data.redis.core.index.Indexed

@RedisHash(value = "minuteSignInCount", timeToLive = 60)
class MinuteSignInCount(
@Id
@Indexed
val email: String,
) {
var count: Int = 0
private set
fun addCount() =
count++
}
17 changes: 17 additions & 0 deletions src/main/kotlin/com/msg/gauth/domain/auth/SecondSignInCount.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.msg.gauth.domain.auth

import org.springframework.data.annotation.Id
import org.springframework.data.redis.core.RedisHash
import org.springframework.data.redis.core.index.Indexed

@RedisHash(value = "secondSignInCount", timeToLive = 5)
class SecondSignInCount(
esperar marked this conversation as resolved.
Show resolved Hide resolved
@Id
@Indexed
val email: String,
) {
var count: Int = 0
private set
fun addCount() =
count++
}
12 changes: 12 additions & 0 deletions src/main/kotlin/com/msg/gauth/domain/auth/TempSignInBan.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.msg.gauth.domain.auth

import org.springframework.data.annotation.Id
import org.springframework.data.redis.core.RedisHash
import org.springframework.data.redis.core.index.Indexed

@RedisHash(value = "tempSignInBan", timeToLive = 60)
class TempSignInBan (
@Id
@Indexed
val email: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.msg.gauth.domain.auth.exception

import com.msg.gauth.global.exception.ErrorCode
import com.msg.gauth.global.exception.exceptions.BasicException

class SignInBanException : BasicException(ErrorCode.SIGN_IN_BAN) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.msg.gauth.domain.auth.exception

import com.msg.gauth.global.exception.ErrorCode
import com.msg.gauth.global.exception.exceptions.BasicException

class SignInMinuteCountOverException : BasicException(ErrorCode.MANY_REQUEST_SIGN_IN_MINUTE) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.msg.gauth.domain.auth.exception

import com.msg.gauth.global.exception.ErrorCode
import com.msg.gauth.global.exception.exceptions.BasicException

class SignInSecondCountOverException : BasicException(ErrorCode.MANY_REQUEST_SIGN_IN_SECOND) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.msg.gauth.domain.auth.exception

import com.msg.gauth.global.exception.ErrorCode
import com.msg.gauth.global.exception.exceptions.BasicException

class TempSignInBanException : BasicException(ErrorCode.TEMP_BAN) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.msg.gauth.domain.auth.repository

import com.msg.gauth.domain.auth.MinuteSignInCount
import org.springframework.data.repository.CrudRepository

interface MinuteSignInCountRepository : CrudRepository<MinuteSignInCount, String> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.msg.gauth.domain.auth.repository

import com.msg.gauth.domain.auth.SecondSignInCount
import org.springframework.data.repository.CrudRepository

interface SecondSignInCountRepository : CrudRepository<SecondSignInCount, String> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.msg.gauth.domain.auth.repository

import com.msg.gauth.domain.auth.TempSignInBan
import org.springframework.data.repository.CrudRepository

interface TempSignInBanRepository : CrudRepository<TempSignInBan, String> {
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package com.msg.gauth.domain.auth.service

import com.msg.gauth.domain.auth.RefreshToken
import com.msg.gauth.domain.auth.TempSignInBan
import com.msg.gauth.domain.auth.exception.PasswordMismatchException
import com.msg.gauth.domain.auth.exception.SignInBanException
import com.msg.gauth.domain.auth.exception.TempSignInBanException
import com.msg.gauth.domain.auth.exception.UserIsPendingException
import com.msg.gauth.domain.auth.presentation.dto.request.SigninRequestDto
import com.msg.gauth.domain.auth.presentation.dto.response.SigninResponseDto
import com.msg.gauth.domain.auth.repository.RefreshTokenRepository
import com.msg.gauth.domain.auth.repository.TempSignInBanRepository
import com.msg.gauth.domain.auth.util.TooManyRequestValidUtil
import com.msg.gauth.domain.user.User
import com.msg.gauth.domain.user.enums.UserState
import com.msg.gauth.domain.user.exception.UserNotFoundException
Expand All @@ -14,18 +19,26 @@ import com.msg.gauth.global.annotation.service.TransactionalService
import com.msg.gauth.global.security.jwt.JwtTokenProvider
import org.springframework.security.crypto.password.PasswordEncoder

@TransactionalService
@TransactionalService(noRollbackFor = [PasswordMismatchException::class])
class SignInService(
private val jwtTokenProvider: JwtTokenProvider,
private val userRepository: UserRepository,
private val refreshTokenRepository: RefreshTokenRepository,
private val passwordEncoder: PasswordEncoder
private val passwordEncoder: PasswordEncoder,
private val tooManyRequestValidUtil: TooManyRequestValidUtil,
private val tempSignInBanRepository: TempSignInBanRepository
) {
fun execute(dto: SigninRequestDto): SigninResponseDto {
val user: User = userRepository.findByEmail(dto.email) ?: throw UserNotFoundException()

if (!passwordEncoder.matches(dto.password, user.password))
isUserBan(user)

tooManyRequestValidUtil.validRequest(dto.email)

if (!passwordEncoder.matches(dto.password, user.password)) {
validWrongCount(user)
throw PasswordMismatchException()
}

if(user.state != UserState.CREATED)
throw UserIsPendingException()
Expand All @@ -38,4 +51,19 @@ class SignInService(
refreshTokenRepository.save(RefreshToken(user.id, refresh))
return SigninResponseDto(access, refresh, expiresAt)
}

private fun isUserBan(user: User) {
when {
user.state == UserState.SIGN_IN_BAN -> throw SignInBanException()
tempSignInBanRepository.existsById(user.email) -> throw TempSignInBanException()
}
}

private fun validWrongCount(user: User) {
val updatedUser = userRepository.save(user.updateWrongPasswordCount(user.wrongPasswordCount + 1))
if (updatedUser.wrongPasswordCount >= 5) {
tempSignInBanRepository.save(TempSignInBan(user.email))
userRepository.save(user.updateWrongPasswordCount(0))
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.msg.gauth.domain.auth.util

import com.msg.gauth.domain.auth.MinuteSignInCount
import com.msg.gauth.domain.auth.SecondSignInCount
import com.msg.gauth.domain.auth.exception.SignInMinuteCountOverException
import com.msg.gauth.domain.auth.exception.SignInSecondCountOverException
import com.msg.gauth.domain.auth.repository.MinuteSignInCountRepository
import com.msg.gauth.domain.auth.repository.SecondSignInCountRepository
import com.msg.gauth.domain.user.enums.UserState
import com.msg.gauth.domain.user.exception.UserNotFoundException
import com.msg.gauth.domain.user.repository.UserRepository
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Component

@Component
class TooManyRequestValidUtil(
private val minuteSignInCountRepository: MinuteSignInCountRepository,
private val secondSignInCountRepository: SecondSignInCountRepository,
private val userRepository: UserRepository
) {
fun validRequest(email: String){
val secondSignInCount = (secondSignInCountRepository.findByIdOrNull(email)
?: secondSignInCountRepository.save(SecondSignInCount(email)))
if (secondSignInCount.count >= 20) {
val user = userRepository.findByEmail(email)
?: throw UserNotFoundException()
userRepository.save(user.updateUserState(UserState.SIGN_IN_BAN))
throw SignInSecondCountOverException()
}
secondSignInCount.addCount()
secondSignInCountRepository.save(secondSignInCount)
val minuteSignInCount = (minuteSignInCountRepository.findByIdOrNull(email)
?: minuteSignInCountRepository.save(MinuteSignInCount(email)))
if (minuteSignInCount.count >= 10) {
val user = userRepository.findByEmail(email)
?: throw UserNotFoundException()
userRepository.save(user.updateUserState(UserState.SIGN_IN_BAN))
throw SignInMinuteCountOverException()
}
minuteSignInCount.addCount()
minuteSignInCountRepository.save(minuteSignInCount)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.msg.gauth.domain.oauth

import org.springframework.data.annotation.Id
import org.springframework.data.redis.core.RedisHash
import org.springframework.data.redis.core.index.Indexed

@RedisHash(value = "minuteOAuthSignInCount", timeToLive = 60)
class MinuteOAuthSignInCount(
@Id
@Indexed
val email: String,
) {
var count: Int = 0
private set
fun addCount() =
count++
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.msg.gauth.domain.oauth

import org.springframework.data.annotation.Id
import org.springframework.data.redis.core.RedisHash
import org.springframework.data.redis.core.index.Indexed

@RedisHash(value = "secondOAuthSignInCount", timeToLive = 5)
class SecondOAuthSignInCount(
@Id
@Indexed
val email: String,
) {
var count: Int = 0
private set
fun addCount() =
count++
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.msg.gauth.domain.oauth

import org.springframework.data.annotation.Id
import org.springframework.data.redis.core.RedisHash
import org.springframework.data.redis.core.index.Indexed

@RedisHash(value = "tempOAuthSignInBan", timeToLive = 60)
class TempOAuthSignInBan (
@Id
@Indexed
val email: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.msg.gauth.domain.oauth.exception

import com.msg.gauth.global.exception.ErrorCode
import com.msg.gauth.global.exception.exceptions.BasicException

class OAuthSignInBanException : BasicException(ErrorCode.OAUTH_SIGN_IN_BAN) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.msg.gauth.domain.oauth.exception

import com.msg.gauth.global.exception.ErrorCode
import com.msg.gauth.global.exception.exceptions.BasicException

class OAuthSignInMinuteOverException : BasicException(ErrorCode.MANY_REQUEST_OAUTH_SIGN_IN_MINUTE) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.msg.gauth.domain.oauth.exception

import com.msg.gauth.global.exception.ErrorCode
import com.msg.gauth.global.exception.exceptions.BasicException

class OAuthSignInSecondOverException : BasicException(ErrorCode.MANY_REQUEST_OAUTH_SIGN_IN_SECOND) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.msg.gauth.domain.oauth.exception

import com.msg.gauth.global.exception.ErrorCode
import com.msg.gauth.global.exception.exceptions.BasicException

class TempOAuthSignInBanException : BasicException(ErrorCode.TEMP_BAN) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.msg.gauth.domain.oauth.repository

import com.msg.gauth.domain.oauth.MinuteOAuthSignInCount
import org.springframework.data.repository.CrudRepository

interface MinuteOAuthSignInCountRepository : CrudRepository<MinuteOAuthSignInCount, String> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.msg.gauth.domain.oauth.repository

import com.msg.gauth.domain.oauth.SecondOAuthSignInCount
import org.springframework.data.repository.CrudRepository

interface SecondOAuthSignInCountRepository : CrudRepository<SecondOAuthSignInCount, String> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.msg.gauth.domain.oauth.repository

import com.msg.gauth.domain.oauth.TempOAuthSignInBan
import org.springframework.data.repository.CrudRepository

interface TempOAuthSignInBanRepository : CrudRepository<TempOAuthSignInBan, String> {
}
Loading