refactor: more secure DataCopy.kt

This commit is contained in:
SOR
2026-07-25 14:35:25 +08:00
parent 999ce5a68a
commit 994b2ff5b3
2 changed files with 25 additions and 41 deletions
@@ -1,56 +1,39 @@
package club.itstudio.itmanager.entity package club.itstudio.itmanager.entity
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.reflect.KProperty import kotlin.reflect.KMutableProperty1
import kotlin.reflect.KProperty1
import kotlin.reflect.full.createInstance import kotlin.reflect.full.createInstance
import kotlin.reflect.full.declaredMemberProperties import kotlin.reflect.full.declaredMemberProperties
import kotlin.reflect.full.memberProperties import kotlin.reflect.full.memberProperties
import kotlin.reflect.jvm.javaField import kotlin.reflect.jvm.isAccessible
interface DataCopy { interface DataCopy {
fun <T : Any> toAnotherObject( fun <T : Any> toAnotherObject(
toClass: KClass<T>, toClass: KClass<T>,
otherProperties: Map<String, Any?> otherProperties: Map<String, Any?> = emptyMap()
): T { ): T {
try { @Suppress("UNCHECKED_CAST")
val voProperties = toClass.declaredMemberProperties val sourceProps = this::class.memberProperties
.associate { it.name to (it as KProperty1<Any, *>).get(this) }
return try {
val vo = toClass.createInstance() val vo = toClass.createInstance()
for (voProperty in voProperties) for (prop in toClass.declaredMemberProperties) {
copyFieldData(voProperty, otherProperties, vo) @Suppress("UNCHECKED_CAST")
return vo val mutableProp = prop as? KMutableProperty1<Any, Any?> ?: continue
val value = when {
sourceProps.containsKey(prop.name) -> sourceProps[prop.name]
otherProperties.containsKey(prop.name) -> otherProperties[prop.name]
else -> continue
}
mutableProp.isAccessible = true
mutableProp.set(vo, value)
}
vo
} catch (e: ReflectiveOperationException) { } catch (e: ReflectiveOperationException) {
throw RuntimeException( throw RuntimeException(
"${toClass.simpleName} has no fields.", "Failed to instantiate ${toClass.simpleName}. Does it have a no-arg constructor?", e
e
) )
} }
} }
private fun copyFieldData(
toProperty: KProperty<*>,
otherProperties: Map<String, Any?>,
another: Any
) {
try {
val thisProperty = this::class.memberProperties
.firstOrNull { it.name == toProperty.name }
val value =
if (thisProperty != null) {
thisProperty.getter.call(this)
} else if (otherProperties.containsKey(toProperty.name))
otherProperties[toProperty.name]
else
throw RuntimeException(
"Property ${toProperty.name} not found."
)
val field = toProperty.javaField!!
field.isAccessible = true
field.set(another, value)
} catch (e: Exception) {
e.printStackTrace()
}
}
} }
@@ -4,13 +4,14 @@ import reactor.core.publisher.Mono
object Const { object Const {
const val FLOW_LIMIT_ORDER = -101 const val FLOW_LIMIT_ORDER = -101
const val JWT_BLACK_LIST = "jwt:blacklist:" const val JWT_BLACK_LIST = "jwt:blacklist:"
const val VERIFY_EMAIL_LIMIT = "verify:email:limit:" const val VERIFY_EMAIL_LIMIT = "verify:email:limit:"
const val VERIFY_EMAIL_DATA = "verify:email:data:" const val VERIFY_EMAIL_DATA = "verify:email:data:"
const val FLOW_LIMIT_COUNTER = "flow:counter:" const val FLOW_LIMIT_COUNTER = "flow:counter:"
const val FLOW_LIMIT_BLOCK = "flow:block:" const val FLOW_LIMIT_BLOCK = "flow:block:"
val INTERNAL_ERROR_MONO = Mono.just("something went wrong. Please contact the administrator.") const val INTERNAL_ERROR_STR = "something went wrong. Please contact the administrator."
val INTERNAL_ERROR_MONO = Mono.just(INTERNAL_ERROR_STR)
} }