diff --git a/src/main/kotlin/com/epam/brn/controller/UserDetailController.kt b/src/main/kotlin/com/epam/brn/controller/UserDetailController.kt index ba4dbc47b..1f7b67637 100644 --- a/src/main/kotlin/com/epam/brn/controller/UserDetailController.kt +++ b/src/main/kotlin/com/epam/brn/controller/UserDetailController.kt @@ -126,4 +126,16 @@ class UserDetailController( @Operation(summary = "Delete doctor from patient") fun deleteDoctorFromPatient(@PathVariable patientId: Long) = doctorService.deleteDoctorFromPatientAsPatient(patientId) + + @DeleteMapping("/del") + @Operation(summary = "Delete all auto test users") + @ResponseStatus(HttpStatus.OK) + fun deleteAutoTestUsers() = ResponseEntity.ok() + .body(userAccountService.deleteAutoTestUsers()) + + @DeleteMapping("/del/{email}") + @Operation(summary = "Delete all auto test users") + @ResponseStatus(HttpStatus.OK) + fun deleteAutoTestUserByEmail(@PathVariable("email") email: String) = ResponseEntity.ok() + .body(userAccountService.deleteAutoTestUserByEmail(email)) } diff --git a/src/main/kotlin/com/epam/brn/dto/UserDeletionDto.kt b/src/main/kotlin/com/epam/brn/dto/UserDeletionDto.kt new file mode 100644 index 000000000..f5611ec6d --- /dev/null +++ b/src/main/kotlin/com/epam/brn/dto/UserDeletionDto.kt @@ -0,0 +1,8 @@ +package com.epam.brn.dto + +/** + * UserDeletionDto. + * + * @author Andrey Samoylov + */ +data class UserDeletionDto(val count: Long) diff --git a/src/main/kotlin/com/epam/brn/model/StudyHistory.kt b/src/main/kotlin/com/epam/brn/model/StudyHistory.kt index 653db23e9..67a693acf 100644 --- a/src/main/kotlin/com/epam/brn/model/StudyHistory.kt +++ b/src/main/kotlin/com/epam/brn/model/StudyHistory.kt @@ -25,7 +25,7 @@ data class StudyHistory( val id: Long? = null, @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") + @JoinColumn(name = "user_id", insertable = true, updatable = false) var userAccount: UserAccount, @ManyToOne(fetch = FetchType.LAZY) @@ -44,7 +44,7 @@ data class StudyHistory( ) { override fun toString() = - "StudyHistory(id=$id, userAccount=$userAccount, exercise=$exercise, startTime=$startTime, endTime=$endTime, spentTime=$spentTimeInSeconds, tasksCount=$tasksCount, wrongAnswers=$wrongAnswers)" + "StudyHistory(id=$id, userAccount=$userAccount, startTime=$startTime, endTime=$endTime, spentTime=$spentTimeInSeconds, tasksCount=$tasksCount, wrongAnswers=$wrongAnswers)" fun toDto() = StudyHistoryDto( id = this.id, diff --git a/src/main/kotlin/com/epam/brn/repo/UserAccountRepository.kt b/src/main/kotlin/com/epam/brn/repo/UserAccountRepository.kt index a77062d28..2783e9d84 100644 --- a/src/main/kotlin/com/epam/brn/repo/UserAccountRepository.kt +++ b/src/main/kotlin/com/epam/brn/repo/UserAccountRepository.kt @@ -61,4 +61,14 @@ interface UserAccountRepository : JpaRepository { where u.email = :email""" ) fun updateLastVisitByEmail(email: String, lastVisit: LocalDateTime) + + fun countByEmailStartsWith(prefix: String): Long + + fun countByEmailIs(email: String): Long + + @Transactional + fun deleteUserAccountsByEmailStartsWith(prefix: String) + + @Transactional + fun deleteUserAccountByEmailIs(email: String) } diff --git a/src/main/kotlin/com/epam/brn/service/UserAccountService.kt b/src/main/kotlin/com/epam/brn/service/UserAccountService.kt index 4a4ca2627..7a9704c55 100644 --- a/src/main/kotlin/com/epam/brn/service/UserAccountService.kt +++ b/src/main/kotlin/com/epam/brn/service/UserAccountService.kt @@ -1,8 +1,9 @@ package com.epam.brn.service import com.epam.brn.dto.HeadphonesDto -import com.epam.brn.dto.request.UserAccountChangeRequest import com.epam.brn.dto.UserAccountDto +import com.epam.brn.dto.UserDeletionDto +import com.epam.brn.dto.request.UserAccountChangeRequest import com.epam.brn.model.UserAccount import com.google.firebase.auth.UserRecord import org.springframework.data.domain.Pageable @@ -36,4 +37,6 @@ interface UserAccountService { fun getPatientsForDoctor(doctorId: Long): List fun markVisitForCurrentUser() + fun deleteAutoTestUsers(): UserDeletionDto + fun deleteAutoTestUserByEmail(email: String): UserDeletionDto } diff --git a/src/main/kotlin/com/epam/brn/service/impl/UserAccountServiceImpl.kt b/src/main/kotlin/com/epam/brn/service/impl/UserAccountServiceImpl.kt index a06e58998..01b5ab42f 100644 --- a/src/main/kotlin/com/epam/brn/service/impl/UserAccountServiceImpl.kt +++ b/src/main/kotlin/com/epam/brn/service/impl/UserAccountServiceImpl.kt @@ -2,6 +2,7 @@ package com.epam.brn.service.impl import com.epam.brn.dto.HeadphonesDto import com.epam.brn.dto.UserAccountDto +import com.epam.brn.dto.UserDeletionDto import com.epam.brn.dto.request.UserAccountChangeRequest import com.epam.brn.enums.BrnRole import com.epam.brn.exception.EntityNotFoundException @@ -14,6 +15,7 @@ import com.epam.brn.service.RoleService import com.epam.brn.service.TimeService import com.epam.brn.service.UserAccountService import com.google.firebase.auth.UserRecord +import org.springframework.beans.factory.annotation.Value import org.springframework.data.domain.Pageable import org.springframework.security.core.Authentication import org.springframework.security.core.context.SecurityContextHolder @@ -26,8 +28,10 @@ class UserAccountServiceImpl( private val userAccountRepository: UserAccountRepository, private val roleService: RoleService, private val headphonesService: HeadphonesService, - private val timeService: TimeService + private val timeService: TimeService, ) : UserAccountService { + @Value("\${users.delete.prefix}") + private lateinit var prefix: String override fun findUserByEmail(email: String): UserAccountDto = userAccountRepository.findUserAccountByEmail(email) @@ -172,4 +176,16 @@ class UserAccountServiceImpl( private fun getDefaultRoleSet(): MutableSet = setOf(BrnRole.USER).mapTo(mutableSetOf()) { roleService.findByName(it) } + + override fun deleteAutoTestUsers(): UserDeletionDto { + val usersCountBefore = userAccountRepository.countByEmailStartsWith(prefix) + userAccountRepository.deleteUserAccountsByEmailStartsWith(prefix) + return UserDeletionDto(usersCountBefore) + } + + override fun deleteAutoTestUserByEmail(email: String): UserDeletionDto { + val count = userAccountRepository.countByEmailIs(email) + userAccountRepository.deleteUserAccountByEmailIs(email) + return UserDeletionDto(count) + } } diff --git a/src/main/kotlin/com/epam/brn/service/load/InitialDataLoader.kt b/src/main/kotlin/com/epam/brn/service/load/InitialDataLoader.kt index 4246cc23c..b6382b88f 100644 --- a/src/main/kotlin/com/epam/brn/service/load/InitialDataLoader.kt +++ b/src/main/kotlin/com/epam/brn/service/load/InitialDataLoader.kt @@ -108,7 +108,9 @@ class InitialDataLoader( val autoTestUser = createUser("autoTestUser", AUTO_TEST_USER_EMAIL, setOf(userRole)) val autoTestSpecialist = createUser("autoTestSpecialist", AUTO_TEST_SPECIALIST_EMAIL, setOf(userRole, specialistRole)) - val listOfUsers = listOf(admin, firstUser, secondUser, autoTestUser, autoTestSpecialist) + + val listOfUsers = + listOf(admin, firstUser, secondUser, autoTestUser, autoTestSpecialist) userAccountRepository.saveAll(listOfUsers) } else { try { diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index b63ea671a..17b233a4e 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -143,7 +143,7 @@ github.contributors.sync.repository-names=brn, mobile, mobile-ios, mobile-androi github.contributors.default-page-size=30 github.contributors.bot-logins=dependabot-preview[bot],snyk-bot,dependabot[bot] github.api.type-token=${API_GITHUB_TYPE_TOKEN:token} -github.api.token=${API_GITHUB_TOKEN} +github.api.token= github.api.codec-max-size=16777216 github.api.logging-enabled=false github.api.connection-timeout=15000 @@ -152,6 +152,8 @@ github.api.url.base=https://api.github.com github.api.url.path.contributors=/repos/{OWNER}/{REPO}/contributors github.api.url.path.users=/users/{username} +users.delete.prefix=autotest + # Swagger springdoc.swagger-ui.tagsSorter=alpha springdoc.writer-with-order-by-keys=true \ No newline at end of file diff --git a/src/test/kotlin/com/epam/brn/integration/StudyHistoryIT.kt b/src/test/kotlin/com/epam/brn/integration/StudyHistoryIT.kt index 9f8be77d7..c5a3f29cf 100644 --- a/src/test/kotlin/com/epam/brn/integration/StudyHistoryIT.kt +++ b/src/test/kotlin/com/epam/brn/integration/StudyHistoryIT.kt @@ -1,9 +1,9 @@ package com.epam.brn.integration +import com.epam.brn.enums.BrnGender import com.epam.brn.enums.BrnRole import com.epam.brn.model.Exercise import com.epam.brn.model.ExerciseGroup -import com.epam.brn.enums.BrnGender import com.epam.brn.model.Series import com.epam.brn.model.StudyHistory import com.epam.brn.model.SubGroup @@ -14,6 +14,7 @@ import com.epam.brn.repo.SeriesRepository import com.epam.brn.repo.StudyHistoryRepository import com.epam.brn.repo.SubGroupRepository import com.epam.brn.repo.UserAccountRepository +import com.epam.brn.service.UserAccountService import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired @@ -54,6 +55,12 @@ class StudyHistoryIT : BaseIT() { @Autowired lateinit var exerciseGroupRepository: ExerciseGroupRepository +// @Autowired +// lateinit var roleRepository: RoleRepository + + @Autowired + lateinit var userAccountService: UserAccountService + @AfterEach fun deleteAfterTest() { studyHistoryRepository.deleteAll() @@ -62,6 +69,7 @@ class StudyHistoryIT : BaseIT() { seriesRepository.deleteAll() exerciseGroupRepository.deleteAll() userAccountRepository.deleteAll() + // roleRepository.deleteAll() } @Test @@ -226,6 +234,115 @@ class StudyHistoryIT : BaseIT() { assertEquals(0, result) } +// @Test +// fun `test delete study history when delete autotest users`() { +// // GIVEN +// val roleUser = insertRole(BrnRole.USER) +// +// val user1 = UserAccount( +// fullName = "autotest_n1", +// email = "autotest_n@1704819771.8820736.com", +// gender = BrnGender.MALE.toString(), +// bornYear = 2000, +// active = true, +// ) +// user1.roleSet = mutableSetOf(roleUser) +// +// val user2 = UserAccount( +// fullName = "autotest_n1", +// email = "autotest_n@170472339.1784415.com", +// gender = BrnGender.MALE.toString(), +// bornYear = 2000, +// active = true, +// ) +// user2.roleSet = mutableSetOf(roleUser) +// +// userAccountRepository.saveAll(listOf(user1, user2)) +// +// val existingSeries = insertSeries() +// val subGroup = insertSubGroup(existingSeries) +// val existingExerciseFirst = insertExercise("FirstName", subGroup) +// val existingExerciseSecond = insertExercise("SecondName", subGroup) +// val now = LocalDateTime.now().truncatedTo(ChronoUnit.DAYS) +// val historyFirstExerciseOne = insertStudyHistory(user1, existingExerciseFirst, now) +// val historySecondExerciseOne = insertStudyHistory(user2, existingExerciseSecond, now) +// +// studyHistoryRepository +// .saveAll( +// listOf( +// historyFirstExerciseOne, +// historySecondExerciseOne, +// ) +// ) +// +// // WHEN +// userAccountService.deleteAutoTestUsers() +// +// val result1 = user1.id?.let { +// studyHistoryRepository.findLastByUserAccountIdAndExercises( +// it, +// listOf(existingExerciseFirst.id!!) +// ) +// } +// +// val result2 = user1.id?.let { +// studyHistoryRepository.findLastByUserAccountIdAndExercises( +// it, +// listOf(existingExerciseFirst.id!!) +// ) +// } +// +// // THEN +// assertEquals(0, result1?.size) +// assertEquals(0, result2?.size) +// } +// +// @Test +// fun `test delete study history when delete single autotest user`() { +// // GIVEN +// val roleUser = insertRole(BrnRole.USER) +// +// val user1 = UserAccount( +// fullName = "autotest_n1", +// email = "autotest_n@1704819771.8820736.com", +// gender = BrnGender.MALE.toString(), +// bornYear = 2000, +// active = true, +// ) +// user1.roleSet = mutableSetOf(roleUser) +// userAccountRepository.save(user1) +// +// val exerciseFirstName = "FirstName" +// val existingSeries = insertSeries() +// val subGroup = insertSubGroup(existingSeries) +// val existingExerciseFirst = insertExercise(exerciseFirstName, subGroup) +// val now = LocalDateTime.now().truncatedTo(ChronoUnit.DAYS) +// val historyFirstExerciseTwo = insertStudyHistory(user1, existingExerciseFirst, now) +// +// studyHistoryRepository.save(historyFirstExerciseTwo) +// +// // WHEN +// userAccountService.deleteAutoTestUsers() +// +// val result1 = user1.id?.let { +// studyHistoryRepository.findLastByUserAccountIdAndExercises( +// it, +// listOf(existingExerciseFirst.id!!) +// ) +// } +// +// val result2 = user1.id?.let { +// studyHistoryRepository.findLastByUserAccountIdAndExercises( +// it, +// listOf(existingExerciseFirst.id!!) +// ) +// } +// +// // THEN +// assertEquals(0, result1?.size) +// assertEquals(0, result2?.size) +// } + private fun insertStudyHistory( existingUser: UserAccount, existingExercise: Exercise, @@ -289,4 +406,12 @@ class StudyHistoryIT : BaseIT() { ) ) } + +// private fun insertRole(roleName: String): Role { +// return roleRepository.save( +// Role( +// name = roleName +// ) +// ) +// } } diff --git a/src/test/kotlin/com/epam/brn/integration/UserDetailsControllerIT.kt b/src/test/kotlin/com/epam/brn/integration/UserDetailsControllerIT.kt index 928f22117..64708a9dc 100644 --- a/src/test/kotlin/com/epam/brn/integration/UserDetailsControllerIT.kt +++ b/src/test/kotlin/com/epam/brn/integration/UserDetailsControllerIT.kt @@ -1,17 +1,17 @@ package com.epam.brn.integration import com.epam.brn.dto.HeadphonesDto +import com.epam.brn.dto.UserAccountDto import com.epam.brn.dto.request.UserAccountChangeRequest import com.epam.brn.dto.response.BrnResponse -import com.epam.brn.dto.UserAccountDto +import com.epam.brn.enums.BrnGender import com.epam.brn.enums.BrnRole import com.epam.brn.enums.HeadphonesType -import com.epam.brn.model.Role -import com.epam.brn.enums.BrnGender import com.epam.brn.model.Headphones +import com.epam.brn.model.Role import com.epam.brn.model.UserAccount -import com.epam.brn.repo.RoleRepository import com.epam.brn.repo.HeadphonesRepository +import com.epam.brn.repo.RoleRepository import com.epam.brn.repo.UserAccountRepository import com.fasterxml.jackson.core.type.TypeReference import com.google.gson.Gson @@ -22,14 +22,15 @@ import org.assertj.core.api.Assertions import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.annotation.Value import org.springframework.security.test.context.support.WithMockUser import org.springframework.test.web.servlet.ResultActions import org.springframework.test.web.servlet.request.MockMvcRequestBuilders -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status import java.nio.charset.StandardCharsets @@ -48,6 +49,9 @@ class UserDetailsControllerIT : BaseIT() { @Autowired lateinit var roleRepository: RoleRepository + @Value("\${users.delete.prefix}") + private lateinit var prefix: String + internal val email: String = "test@test.test" private val baseUrl = "/users" private val currentUserBaseUrl = "$baseUrl/current" @@ -323,6 +327,76 @@ class UserDetailsControllerIT : BaseIT() { users.size shouldBe 1 } + @Test + fun `deleteAutoTestUsers should delete all auto test users`() { + // GIVEN + val roleUser = insertRole(BrnRole.USER) + + val user1 = UserAccount( + fullName = "autotest_n1", + email = "autotest_n@1704819771.8820736.com", + gender = BrnGender.MALE.toString(), + bornYear = 2000, + active = true, + ) + user1.roleSet = mutableSetOf(roleUser) + + val user2 = UserAccount( + fullName = "autotest_n1", + email = "autotest_n@170472339.1784415.com", + gender = BrnGender.MALE.toString(), + bornYear = 2000, + active = true, + ) + user2.roleSet = mutableSetOf(roleUser) + + userAccountRepository.save(user1) + userAccountRepository.save(user2) + + userAccountRepository.countByEmailStartsWith(prefix) shouldBe 2 + + // WHEN + val resultAction = mockMvc.perform( + delete("$baseUrl/del") + .contentType("application/json") + ) + + resultAction + .andExpect(status().isOk) + + // THEN + userAccountRepository.countByEmailStartsWith(prefix) shouldBe 0 + } + + @Test + fun `deleteAutoTestUserByEmail should delete auto test user y email`() { + // GIVEN + val roleUser = insertRole(BrnRole.USER) + + val user1 = UserAccount( + fullName = "autotest_n1", + email = "autotest_n@1704819771.8820736.com", + gender = BrnGender.MALE.toString(), + bornYear = 2000, + active = true, + ) + user1.roleSet = mutableSetOf(roleUser) + userAccountRepository.save(user1) + val email = "autotest_n@1704819771.8820736.com" + userAccountRepository.countByEmailIs(email) shouldBe 1 + + // WHEN + val resultAction = mockMvc.perform( + delete("$baseUrl/del/$email") + .contentType("application/json") + ) + + resultAction + .andExpect(status().isOk) + + // THEN + userAccountRepository.countByEmailIs(email) shouldBe 0 + } @AfterEach fun deleteAfterTest() { userAccountRepository.deleteAll() diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties index 8b85fd421..8b4f9b73a 100644 --- a/src/test/resources/application.properties +++ b/src/test/resources/application.properties @@ -130,3 +130,5 @@ github.api.read-timeout=30000 github.api.url.base=https://api.github.com github.api.url.path.contributors=/repos/{OWNER}/{REPO}/contributors github.api.url.path.users=/users/{username} + +users.delete.prefix=autotest \ No newline at end of file