Skip to content

Commit

Permalink
feat: (#490) EntityEncryptAspect
Browse files Browse the repository at this point in the history
  • Loading branch information
rlaisqls committed May 10, 2023
1 parent faf7bbc commit d223fa9
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ enum class GlobalErrorCode(
BAD_REQUEST(ErrorStatus.BAD_REQUEST, "Bad Request", 3),
INVALID_FILE(ErrorStatus.BAD_REQUEST, "Invalid File", 4),
BAD_EXCEL_FORMAT(ErrorStatus.BAD_REQUEST, "%s행 등 %s개 행의 데이터 형식이 잘못되었습니다.", 5),
KEY_MANAGEMENT_SERVICE(ErrorStatus.BAD_REQUEST, "Key processing failed", 6),

EXTENSION_MISMATCH(401, "File Extension Mismatch", 1),

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package team.aliens.dms.thirdparty.encrypt.aop

import org.aspectj.lang.JoinPoint
import org.aspectj.lang.ProceedingJoinPoint
import org.aspectj.lang.annotation.AfterReturning
import org.aspectj.lang.annotation.Around
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.reflect.MethodSignature
import team.aliens.dms.common.annotation.Decrypted
import team.aliens.dms.common.annotation.EncryptType
import team.aliens.dms.common.annotation.EncryptedColumn
import team.aliens.dms.common.annotation.UseCase
import team.aliens.dms.common.spi.EncryptPort
import team.aliens.dms.common.spi.SchoolSecretPort
import team.aliens.dms.common.spi.SecurityPort
import team.aliens.dms.domain.school.exception.SchoolNotFoundException
import java.lang.reflect.Field
import java.util.function.Consumer
import java.util.function.Function

@UseCase
@Aspect
class EntityEncryptAspect(
private val securityPort: SecurityPort,
private val schoolSecretPort: SchoolSecretPort,
private val encryptPort: EncryptPort
) {

@AfterReturning(
"@annotation(team.aliens.dms.common.annotation.Encrypt)",
returning = "ret"
)
fun encryptReturnValue(joinPoint: JoinPoint, ret: Any) {
if (ret is List<*>) ret.map { obj ->
doOnEncryptedColumn(obj!!) { field ->
setEncryptedValue(obj, field)
}
} else {
doOnEncryptedColumn(ret) { field ->
setEncryptedValue(ret, field)
}
}
}

@AfterReturning(
"@annotation(team.aliens.dms.common.annotation.Decrypt)",
returning = "ret"
)
fun decryptReturnValue(joinPoint: JoinPoint, ret: Any) {
if (ret is List<*>) ret.map { obj ->
doOnEncryptedColumn(obj!!) { field ->
setDecryptedValue(obj, field)
}
} else {
doOnEncryptedColumn(ret) { field ->
setDecryptedValue(ret, field)
}
}
}

@Around("execution(* *(.., @team.aliens.dms.common.annotation.Decrypted() *, ..))+")
fun decryptParameterValue(joinPoint: ProceedingJoinPoint) {
(joinPoint.signature as MethodSignature).method.parameters
.forEachIndexed { idx, param ->
if (param.annotations.contains(Decrypted::class as Annotation)) {
doOnEncryptedColumn(joinPoint.args[idx]) { field ->
setDecryptedValue(joinPoint.args[idx], field)
}
}
}
}

private fun doOnEncryptedColumn(obj: Any, behavior: Consumer<Field>) {
obj::class.java.declaredFields.map { field: Field ->
if (field.isAnnotationPresent(EncryptedColumn::class.java)) {
behavior.accept(field)
}
}
}

private fun setEncryptedValue(obj: Any, field: Field) {
getAnnotationAndSet(obj, field) { f ->
when (f.getAnnotation(EncryptedColumn::class.java).type) {
EncryptType.SYMMETRIC -> encryptPort.symmetricEncrypt(
secretKey = getSchoolKey(),
plainText = f.get(obj) as String
)
EncryptType.ASYMMETRIC -> encryptPort.asymmetricEncrypt(
plainText = f.get(obj) as String
)
}
}
}

private fun setDecryptedValue(obj: Any, field: Field) {
getAnnotationAndSet(obj, field) { f ->
when (f.getAnnotation(EncryptedColumn::class.java).type) {
EncryptType.SYMMETRIC -> encryptPort.symmetricDecrypt(
secretKey = getSchoolKey(),
cipherText = f.get(obj) as String
)
EncryptType.ASYMMETRIC -> encryptPort.asymmetricDecrypt(
cipherText = f.get(obj) as String
)
}
}
}

private fun getAnnotationAndSet(obj: Any, field: Field, function: Function<Field, String>) {
field.run {
check(type == String::class.java)
isAccessible = true
set(obj, function.apply(this))
}
}

private fun getSchoolKey(): String {
val schoolId = securityPort.getCurrentUserSchoolId()
val schoolSecret = schoolSecretPort.querySchoolSecretBySchoolId(schoolId) ?: throw SchoolNotFoundException
return encryptPort.asymmetricDecrypt(schoolSecret.secretKey)
}
}

0 comments on commit d223fa9

Please sign in to comment.