diff --git a/src/main/kotlin/upbrella/be/BeApplication.kt b/src/main/kotlin/upbrella/be/BeApplication.kt index c3a8cf3c..0d813cca 100644 --- a/src/main/kotlin/upbrella/be/BeApplication.kt +++ b/src/main/kotlin/upbrella/be/BeApplication.kt @@ -2,7 +2,9 @@ package upbrella.be import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication +import org.springframework.data.jpa.repository.config.EnableJpaAuditing +@EnableJpaAuditing @SpringBootApplication class BeApplication diff --git a/src/main/kotlin/upbrella/be/user/dto/response/AllUsersInfoResponse.kt b/src/main/kotlin/upbrella/be/user/dto/response/AllUsersInfoResponse.kt index bb87b4aa..b6360455 100644 --- a/src/main/kotlin/upbrella/be/user/dto/response/AllUsersInfoResponse.kt +++ b/src/main/kotlin/upbrella/be/user/dto/response/AllUsersInfoResponse.kt @@ -4,9 +4,9 @@ import upbrella.be.user.entity.User data class AllUsersInfoResponse(val users: List) { companion object { - fun fromUsers(users: List): AllUsersInfoResponse { + fun fromUsers(users: List): AllUsersInfoResponse { return AllUsersInfoResponse( - users = users.map { SingleUserInfoResponse.fromUser(it!!) } + users = users.map { SingleUserInfoResponse.fromUser(it) } ) } } diff --git a/src/main/kotlin/upbrella/be/user/dto/response/SingleUserInfoResponse.kt b/src/main/kotlin/upbrella/be/user/dto/response/SingleUserInfoResponse.kt index 1447d638..f8078979 100644 --- a/src/main/kotlin/upbrella/be/user/dto/response/SingleUserInfoResponse.kt +++ b/src/main/kotlin/upbrella/be/user/dto/response/SingleUserInfoResponse.kt @@ -1,6 +1,7 @@ package upbrella.be.user.dto.response import upbrella.be.user.entity.User +import java.time.LocalDateTime data class SingleUserInfoResponse( val id: Long, @@ -9,7 +10,8 @@ data class SingleUserInfoResponse( val email: String, val bank: String?, val accountNumber: String?, - val adminStatus: Boolean + val adminStatus: Boolean, + val createdAt: LocalDateTime, ) { companion object { fun fromUser(user: User): SingleUserInfoResponse { @@ -20,7 +22,8 @@ data class SingleUserInfoResponse( email = user.email, bank = user.bank, accountNumber = user.accountNumber, - adminStatus = user.adminStatus + adminStatus = user.adminStatus, + createdAt = user.createdAt!! ) } } diff --git a/src/main/kotlin/upbrella/be/user/entity/User.kt b/src/main/kotlin/upbrella/be/user/entity/User.kt index 5738a9dc..49eb6d1b 100644 --- a/src/main/kotlin/upbrella/be/user/entity/User.kt +++ b/src/main/kotlin/upbrella/be/user/entity/User.kt @@ -3,6 +3,7 @@ package upbrella.be.user.entity import upbrella.be.user.dto.request.JoinRequest import upbrella.be.user.dto.response.KakaoLoginResponse import upbrella.be.util.AesEncryptor +import upbrella.be.util.BaseTimeEntity import javax.persistence.Entity import javax.persistence.GeneratedValue import javax.persistence.GenerationType @@ -20,7 +21,7 @@ class User( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) val id: Long? = null, -) { +) : BaseTimeEntity() { companion object { fun createNewUser( @@ -64,17 +65,9 @@ class User( this.accountNumber = null } - fun decryptData(aesEncryptor: AesEncryptor): User { - return User( - socialId = socialId, - name = name, - phoneNumber = phoneNumber, - email = email, - adminStatus = adminStatus, - bank = aesEncryptor.decrypt(bank), - accountNumber = aesEncryptor.decrypt(accountNumber), - id = id - ) + fun decryptData(aesEncryptor: AesEncryptor) { + this.bank = aesEncryptor.decrypt(bank) + this.accountNumber = aesEncryptor.decrypt(accountNumber) } fun deleteBankAccount() { diff --git a/src/main/kotlin/upbrella/be/user/service/UserService.kt b/src/main/kotlin/upbrella/be/user/service/UserService.kt index 607289e1..4a33229d 100644 --- a/src/main/kotlin/upbrella/be/user/service/UserService.kt +++ b/src/main/kotlin/upbrella/be/user/service/UserService.kt @@ -31,7 +31,7 @@ class UserService( ) { fun login(socialId: Long): SessionUser { - val foundUser = userReader.findBySocialId(socialId) + val foundUser = userReader.findBySocialId(socialId.hashCode().toLong()) return SessionUser.fromUser(foundUser) } @@ -56,7 +56,7 @@ class UserService( fun findUsers(): AllUsersInfoResponse { val users = userReader.findAll() - .map { it.decryptData(aesEncryptor) } + users.forEach { it.decryptData(aesEncryptor) } return AllUsersInfoResponse.fromUsers(users) } @@ -100,9 +100,12 @@ class UserService( fun findDecryptedUserById(sessionUser: SessionUser): User { val id = sessionUser.id - return userRepository.findById(id) + val user = userRepository.findById(id) .orElseThrow { NonExistingMemberException("[ERROR] 존재하지 않는 회원입니다.") } - .decryptData(aesEncryptor) + + user.decryptData(aesEncryptor) + + return user } @Transactional @@ -110,6 +113,7 @@ class UserService( val foundUser = userReader.findUserById(id) foundUser.deleteBankAccount() } + @Transactional fun updateAdminStatus(id: Long) { val foundUser = userReader.findUserById(id) diff --git a/src/main/kotlin/upbrella/be/util/BaseTimeEntity.kt b/src/main/kotlin/upbrella/be/util/BaseTimeEntity.kt new file mode 100644 index 00000000..19a1e600 --- /dev/null +++ b/src/main/kotlin/upbrella/be/util/BaseTimeEntity.kt @@ -0,0 +1,26 @@ +package upbrella.be.util + +import org.springframework.data.annotation.CreatedDate +import org.springframework.data.annotation.LastModifiedDate +import org.springframework.data.jpa.domain.support.AuditingEntityListener +import java.time.LocalDateTime +import javax.persistence.Column +import javax.persistence.EntityListeners +import javax.persistence.MappedSuperclass + +@MappedSuperclass +@EntityListeners(AuditingEntityListener::class) +abstract class BaseTimeEntity { + @CreatedDate + @Column(updatable = false) + var createdAt: LocalDateTime? = null + + @LastModifiedDate + var updatedAt: LocalDateTime? = null + + var deletedAt: LocalDateTime? = null + + fun softDelete() { + deletedAt = LocalDateTime.now() + } +} \ No newline at end of file diff --git a/src/main/resources/db/add_time.sql b/src/main/resources/db/add_time.sql new file mode 100644 index 00000000..826070c5 --- /dev/null +++ b/src/main/resources/db/add_time.sql @@ -0,0 +1,4 @@ +ALTER TABLE user + ADD COLUMN created_at DATETIME NOT NULL DEFAULT NOW() COMMENT '생성일', + ADD COLUMN updated_at DATETIME NOT NULL DEFAULT NOW() ON UPDATE NOW() COMMENT '수정일', + ADD COLUMN deleted_at DATETIME NULL COMMENT '삭제일'; \ No newline at end of file diff --git a/src/test/kotlin/upbrella/be/user/controller/UserControllerTest.kt b/src/test/kotlin/upbrella/be/user/controller/UserControllerTest.kt index c19d48d1..3ad23dc8 100644 --- a/src/test/kotlin/upbrella/be/user/controller/UserControllerTest.kt +++ b/src/test/kotlin/upbrella/be/user/controller/UserControllerTest.kt @@ -78,10 +78,10 @@ class UserControllerTest ( val user = FixtureBuilderFactory.builderUser(aesEncryptor).sample() session.setAttribute("user", sessionUser) - val decryptedUser = user.decryptData(aesEncryptor) + user.decryptData(aesEncryptor) given(userService.findDecryptedUserById(sessionUser)) - .willReturn(decryptedUser) + .willReturn(user) // when & then mockMvc.perform( @@ -461,9 +461,12 @@ class UserControllerTest ( users.add(FixtureBuilderFactory.builderUser(aesEncryptor).sample()) } + users.forEach { user -> user.createdAt = LocalDateTime.now()} + users.forEach { user -> user.decryptData(aesEncryptor) + } + val allUsersInfoResponse = AllUsersInfoResponse( users = users.stream() - .map { user -> user.decryptData(aesEncryptor) } .map { SingleUserInfoResponse.fromUser(it) } .toList() ) @@ -499,7 +502,10 @@ class UserControllerTest ( .optional() .description("사용자 계좌 번호"), fieldWithPath("users[].adminStatus").type(JsonFieldType.BOOLEAN) - .description("관리자 여부") + .description("관리자 여부"), + fieldWithPath("users[].createdAt").type(JsonFieldType.ARRAY) + .description("사용자 생성일") + ) ) ) diff --git a/src/test/kotlin/upbrella/be/user/entity/UserTest.kt b/src/test/kotlin/upbrella/be/user/entity/UserTest.kt index b0958d0a..bb258dc1 100644 --- a/src/test/kotlin/upbrella/be/user/entity/UserTest.kt +++ b/src/test/kotlin/upbrella/be/user/entity/UserTest.kt @@ -110,12 +110,12 @@ class UserTest { accountNumber = aesEncryptor.encrypt("accountNumber") ) // when - val decryptedUser = user.decryptData(aesEncryptor) + user.decryptData(aesEncryptor) // then assertAll( - { assertThat(decryptedUser.bank).isEqualTo("bank") }, - { assertThat(decryptedUser.accountNumber).isEqualTo("accountNumber") } + { assertThat(user.bank).isEqualTo("bank") }, + { assertThat(user.accountNumber).isEqualTo("accountNumber") } ) } diff --git a/src/test/kotlin/upbrella/be/user/service/UserServiceTest.kt b/src/test/kotlin/upbrella/be/user/service/UserServiceTest.kt index 6719fdad..04caacb4 100644 --- a/src/test/kotlin/upbrella/be/user/service/UserServiceTest.kt +++ b/src/test/kotlin/upbrella/be/user/service/UserServiceTest.kt @@ -224,93 +224,6 @@ class UserServiceTest { } } - @Nested - @DisplayName("사용자는") - inner class FindUsersTest { - - private val users: MutableList = ArrayList() - private val expectedUsers: MutableList = ArrayList() - - @BeforeEach - fun setUp() { - for (i in 0 until 1) { - val sample = User( - 1L, - "사용자", - "010-1234-5678", - "", - false, - aesEncryptor.encrypt("농협"), - aesEncryptor.encrypt("123-456-789"), - 1L - ) - val expectedSample = User( - 1L, - "사용자", - "010-1234-5678", - "", - false, - aesEncryptor.encrypt("농협"), - aesEncryptor.encrypt("123-456-789"), - 1L - ) - - users.add(sample) - expectedUsers.add(expectedSample) - } - } - - @Test - @DisplayName("회원 목록을 조회할 수 있다.") - fun success() { - // given - val expected = AllUsersInfoResponse( - users = expectedUsers.stream() - .map { user -> user.decryptData(aesEncryptor) } - .map { decrypted -> SingleUserInfoResponse.fromUser(decrypted) } - .toList() - ) - - given(userReader.findAll()).willReturn(users) - - // when - val allUsersInfoResponse = userService.findUsers() - - // then - assertAll( - { - assertThat(allUsersInfoResponse) - .usingRecursiveComparison() - .isEqualTo(expected) - }, - { - then(userReader).should(times(1)).findAll() - } - ) - } - - @Test - @DisplayName("존재하는 회원이 없으면 빈 목록이 반환된다.") - fun nonExistingUser() { - // given - given(userReader.findAll()) - .willReturn(listOf()) - - // when - val allUsersInfoResponse = userService.findUsers() - - // then - assertAll( - { - assertThat(allUsersInfoResponse.users.size).isEqualTo(0) - }, - { - then(userReader).should(times(1)).findAll() - } - ) - } - } - @Test @DisplayName("사용자는 자신의 은행 정보를 수정할 수 있다.") fun updateBankTest() {