diff --git a/dms-core/src/main/kotlin/team/aliens/dms/domain/room/service/RoomService.kt b/dms-core/src/main/kotlin/team/aliens/dms/domain/room/service/RoomService.kt index 12beb096f..e5c22d442 100644 --- a/dms-core/src/main/kotlin/team/aliens/dms/domain/room/service/RoomService.kt +++ b/dms-core/src/main/kotlin/team/aliens/dms/domain/room/service/RoomService.kt @@ -1,6 +1,6 @@ package team.aliens.dms.domain.room.service -import org.springframework.stereotype.Service +import team.aliens.dms.common.annotation.Service @Service class RoomService( diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/common/annotation/EncryptAnnotations.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/common/annotation/EncryptAnnotations.kt new file mode 100644 index 000000000..352c32c4f --- /dev/null +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/common/annotation/EncryptAnnotations.kt @@ -0,0 +1,47 @@ +package team.aliens.dms.common.annotation + +import java.lang.annotation.Inherited + +/** + * 저장시 암호화되는 컬럼을 명시해주기 위한 어노테이션 + */ +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.FIELD) +annotation class EncryptedColumn( + val type: EncryptType +) + +enum class EncryptType { + SYMMETRIC, + ASYMMETRIC +} + +/** + * 메서드의 반환값에서 EncryptedColmn이 붙은 필드을 암호화하는 어노테이션 + * @see EncryptedColumn + * @see team.aliens.dms.persistence.EncryptableGenericMapper + */ +@Inherited +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.FUNCTION) +annotation class Encrypt + +/** + * 메서드의 반환값에서 EncryptedColmn이 붙은 필드을 복호화하는 어노테이션 + * @see EncryptedColumn + */ +@Inherited +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.FUNCTION) +annotation class Decrypt + +/** + * 파라미터 전달시에 암호화된 엔티티를 복호화하는 어노테이션 + * @see team.aliens.dms.persistence.EncryptableGenericMapper + */ +@Inherited +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.VALUE_PARAMETER) +annotation class Decrypted( + val value: String = "" +) diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/EncryptableGenericMapper.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/EncryptableGenericMapper.kt new file mode 100644 index 000000000..4e10d0b43 --- /dev/null +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/EncryptableGenericMapper.kt @@ -0,0 +1,12 @@ +package team.aliens.dms.persistence + +import team.aliens.dms.common.annotation.Decrypted +import team.aliens.dms.common.annotation.Encrypt + +interface EncryptableGenericMapper : GenericMapper { + + override fun toDomain(@Decrypted entity: E?): D? + + @Encrypt + override fun toEntity(domain: D): E +} diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/notice/entity/NoticeJpaEntity.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/notice/entity/NoticeJpaEntity.kt index 1d20e6778..61583414f 100644 --- a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/notice/entity/NoticeJpaEntity.kt +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/notice/entity/NoticeJpaEntity.kt @@ -24,7 +24,7 @@ class NoticeJpaEntity( @Column(columnDefinition = "VARCHAR(100)", nullable = false) val title: String, - @Column(columnDefinition = "VARCHAR(1000)", nullable = false) + @Column(columnDefinition = "TEXT", nullable = false) val content: String, override val createdAt: LocalDateTime, diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/point/entity/PointHistoryJpaEntity.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/point/entity/PointHistoryJpaEntity.kt index 901e2bb3c..5548f8c2b 100644 --- a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/point/entity/PointHistoryJpaEntity.kt +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/point/entity/PointHistoryJpaEntity.kt @@ -1,8 +1,5 @@ package team.aliens.dms.persistence.point.entity -import team.aliens.dms.domain.point.model.PointType -import team.aliens.dms.persistence.BaseEntity -import team.aliens.dms.persistence.school.entity.SchoolJpaEntity import java.time.LocalDateTime import java.util.UUID import javax.persistence.Column @@ -13,6 +10,11 @@ import javax.persistence.FetchType import javax.persistence.JoinColumn import javax.persistence.ManyToOne import javax.persistence.Table +import team.aliens.dms.common.annotation.EncryptType +import team.aliens.dms.common.annotation.EncryptedColumn +import team.aliens.dms.domain.point.model.PointType +import team.aliens.dms.persistence.BaseEntity +import team.aliens.dms.persistence.school.entity.SchoolJpaEntity @Entity @Table(name = "tbl_point_history") @@ -20,10 +22,12 @@ class PointHistoryJpaEntity( id: UUID?, + @EncryptedColumn(type = EncryptType.SYMMETRIC) @Column(columnDefinition = "VARCHAR(30)", nullable = false) val studentName: String, - @Column(columnDefinition = "VARCHAR(5)", nullable = false) + @EncryptedColumn(type = EncryptType.SYMMETRIC) + @Column(columnDefinition = "TEXT", nullable = false) val studentGcn: String, @Column(columnDefinition = "INT", nullable = false) diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/point/mapper/PointHistoryMapper.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/point/mapper/PointHistoryMapper.kt index 18b0ceadb..9745627aa 100644 --- a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/point/mapper/PointHistoryMapper.kt +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/point/mapper/PointHistoryMapper.kt @@ -3,14 +3,14 @@ package team.aliens.dms.persistence.point.mapper import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Component import team.aliens.dms.domain.point.model.PointHistory -import team.aliens.dms.persistence.GenericMapper +import team.aliens.dms.persistence.EncryptableGenericMapper import team.aliens.dms.persistence.point.entity.PointHistoryJpaEntity import team.aliens.dms.persistence.school.repository.SchoolJpaRepository @Component class PointHistoryMapper( private val schoolRepository: SchoolJpaRepository -) : GenericMapper { +) : EncryptableGenericMapper { override fun toDomain(entity: PointHistoryJpaEntity?): PointHistory? { return entity?.let { diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/student/StudentPersistenceAdapter.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/student/StudentPersistenceAdapter.kt index dc89bbc90..a503204b7 100644 --- a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/student/StudentPersistenceAdapter.kt +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/student/StudentPersistenceAdapter.kt @@ -11,8 +11,10 @@ import com.querydsl.core.types.dsl.CaseBuilder import com.querydsl.core.types.dsl.Expressions import com.querydsl.jpa.JPAExpressions.select import com.querydsl.jpa.impl.JPAQueryFactory +import java.util.UUID import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Component +import team.aliens.dms.common.annotation.Decrypt import team.aliens.dms.domain.manager.dto.PointFilter import team.aliens.dms.domain.manager.dto.PointFilterType import team.aliens.dms.domain.manager.dto.Sort @@ -32,7 +34,6 @@ import team.aliens.dms.persistence.tag.entity.QStudentTagJpaEntity.studentTagJpa import team.aliens.dms.persistence.tag.entity.QTagJpaEntity.tagJpaEntity import team.aliens.dms.persistence.tag.mapper.TagMapper import team.aliens.dms.persistence.user.entity.QUserJpaEntity.userJpaEntity -import java.util.UUID @Component class StudentPersistenceAdapter( @@ -148,6 +149,7 @@ class StudentPersistenceAdapter( return tuple.toTypedArray() } + @Decrypt override fun queryStudentsByNameAndSortAndFilter( name: String?, sort: Sort, @@ -158,8 +160,7 @@ class StudentPersistenceAdapter( return queryFactory .selectFrom(studentJpaEntity) .join(studentJpaEntity.room, roomJpaEntity) - .join(studentJpaEntity.user, userJpaEntity) - .join(userJpaEntity.school, schoolJpaEntity) + .join(roomJpaEntity.school, schoolJpaEntity) .leftJoin(studentTagJpaEntity) .on(studentJpaEntity.id.eq(studentTagJpaEntity.student.id)).fetchJoin() .leftJoin(tagJpaEntity) @@ -167,7 +168,7 @@ class StudentPersistenceAdapter( .leftJoin(pointHistoryJpaEntity) .on(eqStudentRecentPointHistory()) .where( - userJpaEntity.school.id.eq(schoolId), + roomJpaEntity.school.id.eq(schoolId), nameContains(name), pointTotalBetween(pointFilter), hasAllTags(tagIds) @@ -194,22 +195,6 @@ class StudentPersistenceAdapter( ) ) ) - .map { - StudentWithTag( - id = it.id, - name = it.name, - grade = it.grade, - classRoom = it.classRoom, - number = it.number, - roomNumber = it.roomNumber, - profileImageUrl = it.profileImageUrl, - sex = it.sex, - tags = it.tags - .map { tag -> - tagMapper.toDomain(tag)!! - } - ) - } } private fun nameContains(name: String?) = name?.run { studentJpaEntity.name.contains(this) } @@ -294,6 +279,7 @@ class StudentPersistenceAdapter( } } + @Decrypt override fun queryStudentsWithPointHistory(studentIds: List): List { return queryFactory .select( @@ -314,16 +300,6 @@ class StudentPersistenceAdapter( studentJpaEntity.id.`in`(studentIds) ) .fetch() - .map { - StudentWithPointVO( - name = it.name, - grade = it.grade, - classRoom = it.classRoom, - number = it.number, - bonusTotal = it.bonusTotal ?: 0, - minusTotal = it.minusTotal ?: 0 - ) - } } private fun eqStudentRecentPointHistory(): BooleanExpression? { diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/student/entity/StudentJpaEntity.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/student/entity/StudentJpaEntity.kt index ee19349d7..0ca70ab60 100644 --- a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/student/entity/StudentJpaEntity.kt +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/student/entity/StudentJpaEntity.kt @@ -1,10 +1,5 @@ package team.aliens.dms.persistence.student.entity -import org.hibernate.annotations.Where -import team.aliens.dms.domain.student.model.Sex -import team.aliens.dms.persistence.BaseUUIDEntity -import team.aliens.dms.persistence.room.entity.RoomJpaEntity -import team.aliens.dms.persistence.user.entity.UserJpaEntity import java.time.LocalDateTime import java.util.UUID import javax.persistence.CascadeType @@ -17,6 +12,13 @@ import javax.persistence.JoinColumn import javax.persistence.ManyToOne import javax.persistence.OneToOne import javax.persistence.Table +import org.hibernate.annotations.Where +import team.aliens.dms.common.annotation.EncryptType +import team.aliens.dms.common.annotation.EncryptedColumn +import team.aliens.dms.domain.student.model.Sex +import team.aliens.dms.persistence.BaseUUIDEntity +import team.aliens.dms.persistence.room.entity.RoomJpaEntity +import team.aliens.dms.persistence.user.entity.UserJpaEntity @Entity @Table(name = "tbl_student") @@ -45,7 +47,8 @@ class StudentJpaEntity( @Column(columnDefinition = "TINYINT UNSIGNED", nullable = false) val number: Int, - @Column(columnDefinition = "VARCHAR(10)", nullable = false) + @EncryptedColumn(type = EncryptType.SYMMETRIC) + @Column(columnDefinition = "TEXT", nullable = false) val name: String, @Column(columnDefinition = "VARCHAR(500)", nullable = false) @@ -57,4 +60,5 @@ class StudentJpaEntity( @Column(columnDefinition = "DATETIME") val deletedAt: LocalDateTime? + ) : BaseUUIDEntity(id) diff --git a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/student/mapper/StudentMapper.kt b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/student/mapper/StudentMapper.kt index b204206da..944eb6aae 100644 --- a/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/student/mapper/StudentMapper.kt +++ b/dms-persistence/src/main/kotlin/team/aliens/dms/persistence/student/mapper/StudentMapper.kt @@ -3,7 +3,7 @@ package team.aliens.dms.persistence.student.mapper import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Component import team.aliens.dms.domain.student.model.Student -import team.aliens.dms.persistence.GenericMapper +import team.aliens.dms.persistence.EncryptableGenericMapper import team.aliens.dms.persistence.room.repository.RoomJpaRepository import team.aliens.dms.persistence.student.entity.StudentJpaEntity import team.aliens.dms.persistence.user.repository.UserJpaRepository @@ -12,7 +12,7 @@ import team.aliens.dms.persistence.user.repository.UserJpaRepository class StudentMapper( private val roomRepository: RoomJpaRepository, private val userRepository: UserJpaRepository -) : GenericMapper { +) : EncryptableGenericMapper { override fun toDomain(entity: StudentJpaEntity?): Student? { return entity?.let { @@ -47,7 +47,7 @@ class StudentMapper( classRoom = domain.classRoom, number = domain.number, name = domain.name, - profileImageUrl = domain.profileImageUrl!!, + profileImageUrl = domain.profileImageUrl, sex = domain.sex, deletedAt = domain.deletedAt )