-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: 🔧 Migrating the Socket Module from Java to Kotlin (#211)
* rename: application file java to kotlin * chore: convert language from java to kotlin in the socket module * fix: change application file to kotlin style * fix: move @post-construct method function into the class * feat: add kotlin log util * refactor: convert auth_service from java to kotlin * refactor: convert chat_message_send_service from java to kotlin * refactor: convert stomp-message-util from java to kotlin * refactor: convert last-message-id-save-service from java to kotlin * refactor: convert status-service from java to kotlin * refactor: convert chat-message-relay-service from java to kotlin * refactor: convert auth-controller from java to kotlin * refactor: convert chat-message-controller from java to kotlin * refactor: convert status-controller from java to kotlin * refactor: convert pre-authorized-spel-parser & aspect from java to kotlin * refactor: convert user-principal from java to kotlin * fix: principal.expired cannot use(lombok compile time), so convert domain method * fix: add jvm-static annotation at create-method in the stomp-message-util * rename: add evaluate prameter name * fix: modify is_authenticated to static method * chore: modify kotlin compile option cause method parameter data lost * fix: divide evaluate logic from execution logic
- Loading branch information
1 parent
09336ff
commit 30524c5
Showing
29 changed files
with
640 additions
and
654 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 0 additions & 19 deletions
19
pennyway-socket/src/main/java/kr/co/pennyway/PennywaySocketApplication.java
This file was deleted.
Oops, something went wrong.
18 changes: 18 additions & 0 deletions
18
pennyway-socket/src/main/java/kr/co/pennyway/PennywaySocketApplication.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package kr.co.pennyway; | ||
|
||
import jakarta.annotation.PostConstruct | ||
import org.springframework.boot.autoconfigure.SpringBootApplication | ||
import org.springframework.boot.runApplication | ||
import java.util.* | ||
|
||
@SpringBootApplication | ||
class PennywaySocketApplication { | ||
@PostConstruct | ||
fun setDefaultTimeZone() { | ||
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Seoul")) | ||
} | ||
} | ||
|
||
fun main(args: Array<String>) { | ||
runApplication<PennywaySocketApplication>(*args) | ||
} |
74 changes: 0 additions & 74 deletions
74
pennyway-socket/src/main/java/kr/co/pennyway/socket/common/aop/PreAuthorizeAspect.java
This file was deleted.
Oops, something went wrong.
90 changes: 90 additions & 0 deletions
90
pennyway-socket/src/main/java/kr/co/pennyway/socket/common/aop/PreAuthorizeAspect.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package kr.co.pennyway.socket.common.aop; | ||
|
||
import kr.co.pennyway.socket.common.annotation.PreAuthorize | ||
import kr.co.pennyway.socket.common.exception.PreAuthorizeErrorCode | ||
import kr.co.pennyway.socket.common.exception.PreAuthorizeErrorException | ||
import kr.co.pennyway.socket.common.util.PreAuthorizeSpELParser | ||
import kr.co.pennyway.socket.common.util.logger | ||
import org.aspectj.lang.ProceedingJoinPoint | ||
import org.aspectj.lang.annotation.Around | ||
import org.aspectj.lang.annotation.Aspect | ||
import org.aspectj.lang.reflect.MethodSignature | ||
import org.springframework.context.ApplicationContext | ||
import org.springframework.stereotype.Component | ||
import java.lang.reflect.Method | ||
import java.security.Principal | ||
|
||
@Aspect | ||
@Component | ||
class PreAuthorizeAspect(private val applicationContext: ApplicationContext) { | ||
private val log = logger() | ||
|
||
/** | ||
* {@link PreAuthorize} 어노테이션이 붙은 메서드를 가로채고 인증/인가를 수행합니다. | ||
* | ||
* @param joinPoint 가로챈 메서드의 실행 지점 | ||
* @return 인증/인가가 성공하면 원래 메서드의 실행 결과, 실패하면 UnauthorizedResponse | ||
* @throws Throwable 메서드 실행 중 발생한 예외 | ||
*/ | ||
@Around("@annotation(kr.co.pennyway.socket.common.annotation.PreAuthorize)") | ||
fun execute(joinPoint: ProceedingJoinPoint): Any = with(joinPoint) { | ||
(signature as? MethodSignature) | ||
?.method | ||
?.let { method -> validateAccess(method, this) } | ||
?: throw IllegalStateException("PreAuthorize는 메서드에만 적용할 수 있습니다") | ||
} | ||
|
||
private fun validateAccess(method: Method, joinPoint: ProceedingJoinPoint): Any { | ||
val preAuthorize = method.requireAnnotation<PreAuthorize>() | ||
val principal = joinPoint.args.findPrincipal() | ||
|
||
evaluateAccess( | ||
principal = principal, | ||
preAuthorize = preAuthorize, | ||
method = method, | ||
args = joinPoint.args | ||
) | ||
|
||
return joinPoint.proceed() | ||
} | ||
|
||
private fun evaluateAccess( | ||
principal: Principal?, | ||
preAuthorize: PreAuthorize, | ||
method: Method, | ||
args: Array<Any> | ||
) = PreAuthorizeSpELParser | ||
.evaluate( | ||
expression = preAuthorize.value, | ||
method = method, | ||
args = args, | ||
applicationContext = applicationContext | ||
) | ||
.also { result -> handleEvaluationResult(result, principal) } | ||
|
||
private fun handleEvaluationResult( | ||
result: PreAuthorizeSpELParser.EvaluationResult, | ||
principal: Principal? | ||
) = when (result) { | ||
is PreAuthorizeSpELParser.EvaluationResult.Permitted -> Unit | ||
is PreAuthorizeSpELParser.EvaluationResult.Denied.Unauthenticated -> { | ||
log.warn("인증 실패: {}", principal) | ||
throw PreAuthorizeErrorException(PreAuthorizeErrorCode.UNAUTHENTICATED) | ||
} | ||
|
||
is PreAuthorizeSpELParser.EvaluationResult.Denied.Unauthorized -> { | ||
log.warn("인가 실패: {}", principal) | ||
throw PreAuthorizeErrorException(PreAuthorizeErrorCode.FORBIDDEN) | ||
} | ||
} | ||
|
||
private companion object { | ||
inline fun <reified T : Annotation> Method.requireAnnotation(): T = | ||
getAnnotation(T::class.java) | ||
?: throw IllegalStateException("Required annotation ${T::class.simpleName} not found") | ||
|
||
fun Array<Any>.findPrincipal(): Principal? = asSequence() | ||
.filterIsInstance<Principal>() | ||
.firstOrNull() | ||
} | ||
} |
97 changes: 0 additions & 97 deletions
97
...ocket/src/main/java/kr/co/pennyway/socket/common/security/authenticate/UserPrincipal.java
This file was deleted.
Oops, something went wrong.
48 changes: 48 additions & 0 deletions
48
...-socket/src/main/java/kr/co/pennyway/socket/common/security/authenticate/UserPrincipal.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package kr.co.pennyway.socket.common.security.authenticate; | ||
|
||
import kr.co.pennyway.domain.domains.user.domain.User | ||
import kr.co.pennyway.domain.domains.user.type.Role | ||
import java.security.Principal | ||
import java.time.LocalDateTime | ||
|
||
data class UserPrincipal( | ||
val userId: Long, | ||
private var _name: String, | ||
var username: String, | ||
var role: Role, | ||
var isChatNotify: Boolean, | ||
var expiresAt: LocalDateTime, | ||
var deviceId: String, | ||
var deviceName: String | ||
) : Principal { | ||
fun isAuthenticated(): Boolean = !isExpired() | ||
|
||
fun updateExpiresAt(newExpiresAt: LocalDateTime) { | ||
this.expiresAt = newExpiresAt | ||
} | ||
|
||
override fun getName(): String = userId.toString() | ||
|
||
fun getDefaultName(): String = _name | ||
|
||
private fun isExpired(): Boolean = LocalDateTime.now().isAfter(expiresAt) | ||
|
||
companion object { | ||
@JvmStatic | ||
fun of( | ||
user: User, | ||
expiresAt: LocalDateTime, | ||
deviceId: String, | ||
deviceName: String | ||
): UserPrincipal = UserPrincipal( | ||
userId = user.id, | ||
_name = user.name, | ||
username = user.username, | ||
role = user.role, | ||
isChatNotify = user.notifySetting.isChatNotify, | ||
expiresAt = expiresAt, | ||
deviceId = deviceId, | ||
deviceName = deviceName | ||
) | ||
} | ||
} |
Oops, something went wrong.