Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,16 @@ class FirebaseTokenAuthenticationFilter(
filterChain: FilterChain
) {
verifyToken(request)
markVisit()
filterChain.doFilter(request, response)
}

private fun markVisit() {
if (SecurityContextHolder.getContext().authentication != null) {
userAccountService.markVisitForCurrentUser()
}
}

private fun verifyToken(request: HttpServletRequest) {
val token: String? = tokenHelperUtils.getBearerToken(request)
try {
Expand Down
1 change: 1 addition & 0 deletions src/main/kotlin/com/epam/brn/model/UserAccount.kt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ data class UserAccount(
@OneToMany(mappedBy = "userAccount", cascade = [CascadeType.ALL], fetch = FetchType.LAZY)
var headphones: MutableSet<Headphones> = hashSetOf()
) {
var lastVisit: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC)
Comment thread
ElenaSpb marked this conversation as resolved.
var password: String? = null

@Column(name = "is_firebase_error")
Expand Down
2 changes: 2 additions & 0 deletions src/main/kotlin/com/epam/brn/service/UserAccountService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,6 @@ interface UserAccountService {
fun updateDoctorForPatient(userId: Long, doctorId: Long): UserAccount
fun removeDoctorFromPatient(userId: Long): UserAccount
fun getPatientsForDoctor(doctorId: Long): List<UserAccountDto>

fun markVisitForCurrentUser()
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.epam.brn.model.UserAccount
import com.epam.brn.repo.UserAccountRepository
import com.epam.brn.service.HeadphonesService
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.data.domain.Pageable
Expand All @@ -24,7 +25,8 @@ import java.security.Principal
class UserAccountServiceImpl(
private val userAccountRepository: UserAccountRepository,
private val roleService: RoleService,
private val headphonesService: HeadphonesService
private val headphonesService: HeadphonesService,
private val timeService: TimeService
) : UserAccountService {

override fun findUserByEmail(email: String): UserAccountDto =
Expand Down Expand Up @@ -73,6 +75,13 @@ class UserAccountServiceImpl(
.orElseThrow { EntityNotFoundException("No user was found for email=$email") }
}

override fun markVisitForCurrentUser() {
getCurrentUser().let {
it.lastVisit = timeService.now()
userAccountRepository.save(it)
}
}

override fun getCurrentUserDto(): UserAccountDto =
getCurrentUser().toDto()

Expand Down
1 change: 1 addition & 0 deletions src/main/resources/db/migration/V220230119_2406.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
alter table user_account add column if not exists last_visit timestamp;
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import io.mockk.every
import io.mockk.impl.annotations.InjectMockKs
import io.mockk.impl.annotations.MockK
import io.mockk.junit5.MockKExtension
import io.mockk.justRun
import io.mockk.mockk
import io.mockk.verify
import org.amshove.kluent.shouldBeInstanceOf
Expand Down Expand Up @@ -85,6 +86,8 @@ internal class FirebaseTokenAuthenticationFilterTest {
every { firebaseAuth.verifyIdToken(token, true) } returns firebaseTokenMock
every { firebaseTokenMock.email } returns email
every { brainUpUserDetailsService.loadUserByUsername(email) } returns customUserDetailsMock
justRun { userAccountService.markVisitForCurrentUser() }

// WHEN
firebaseTokenAuthenticationFilter.doFilter(request, response, filterChain)
// THEN
Expand All @@ -97,6 +100,7 @@ internal class FirebaseTokenAuthenticationFilterTest {
verify(exactly = 1) { tokenHelperUtils.getBearerToken(request) }
verify(exactly = 1) { firebaseAuth.verifyIdToken(token, true) }
verify(exactly = 1) { brainUpUserDetailsService.loadUserByUsername(email) }
verify(exactly = 1) { userAccountService.markVisitForCurrentUser() }
verify(exactly = 0) { firebaseUserService.getUserByUuid(any()) }
verify(exactly = 0) { userAccountService.createUser(any()) }
}
Expand Down Expand Up @@ -124,6 +128,7 @@ internal class FirebaseTokenAuthenticationFilterTest {
gender = null,
name = fullName
)
justRun { userAccountService.markVisitForCurrentUser() }

// WHEN
firebaseTokenAuthenticationFilter.doFilter(requestMock, responseMock, filterChain)
Expand All @@ -139,6 +144,7 @@ internal class FirebaseTokenAuthenticationFilterTest {
verify(exactly = 2) { brainUpUserDetailsService.loadUserByUsername(email) }
verify(exactly = 1) { firebaseUserService.getUserByUuid(uuid) }
verify(exactly = 1) { userAccountService.createUser(any()) }
verify(exactly = 1) { userAccountService.markVisitForCurrentUser() }
}

@Test
Expand All @@ -163,6 +169,7 @@ internal class FirebaseTokenAuthenticationFilterTest {
verify(exactly = 0) { brainUpUserDetailsService.loadUserByUsername(any()) }
verify(exactly = 0) { firebaseUserService.getUserByUuid(any()) }
verify(exactly = 0) { userAccountService.createUser(any()) }
verify(exactly = 0) { userAccountService.markVisitForCurrentUser() }
}

@Test
Expand All @@ -187,6 +194,7 @@ internal class FirebaseTokenAuthenticationFilterTest {
verify(exactly = 0) { brainUpUserDetailsService.loadUserByUsername(any()) }
verify(exactly = 0) { firebaseUserService.getUserByUuid(any()) }
verify(exactly = 0) { userAccountService.createUser(any()) }
verify(exactly = 0) { userAccountService.markVisitForCurrentUser() }
}

@Test
Expand Down Expand Up @@ -216,6 +224,7 @@ internal class FirebaseTokenAuthenticationFilterTest {
verify(exactly = 1) { firebaseAuth.verifyIdToken(tokenMock, true) }
verify(exactly = 1) { brainUpUserDetailsService.loadUserByUsername(email) }
verify(exactly = 1) { firebaseUserService.getUserByUuid(uuid) }
verify(exactly = 0) { userAccountService.markVisitForCurrentUser() }
verify(exactly = 0) { userAccountService.createUser(any()) }
}

Expand Down
40 changes: 40 additions & 0 deletions src/test/kotlin/com/epam/brn/service/UserAccountServiceTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import org.springframework.security.core.Authentication
import org.springframework.security.core.context.SecurityContext
import org.springframework.security.core.context.SecurityContextHolder
import java.time.LocalDateTime
import java.time.ZoneOffset
import java.util.Optional
import kotlin.test.assertFailsWith
import kotlin.test.assertNotNull
Expand Down Expand Up @@ -78,6 +79,9 @@ internal class UserAccountServiceTest {
@MockK
lateinit var pageable: Pageable

@MockK
lateinit var timeService: TimeService

@Nested
@DisplayName("Tests for getting users")
inner class GetUserAccounts {
Expand Down Expand Up @@ -295,6 +299,42 @@ internal class UserAccountServiceTest {
assertThat(userForSave.fullName).isEqualTo("newName")
assertThat(userForSave.id).isEqualTo(userAccount.id)
}

@Test
fun `should mark visit current session user`() {
// GIVEN
val email = "test@test.ru"
val userAccount = UserAccount(
id = 1L,
fullName = "testUserFirstName",
email = email,
gender = BrnGender.MALE.toString(),
bornYear = 2000,
changed = LocalDateTime.now().minusMinutes(5),
avatar = null
)
val userAccountUpdated = userAccount.copy()
val now = LocalDateTime.now(ZoneOffset.UTC)
userAccountUpdated.lastVisit = now
val userArgumentCaptor = slot<UserAccount>()

SecurityContextHolder.setContext(securityContext)
every { securityContext.authentication } returns authentication
every { authentication.name } returns email
every { userAccountRepository.findUserAccountByEmail(email) } returns Optional.of(userAccount)
every { userAccountRepository.save(ofType(UserAccount::class)) } returns userAccountUpdated
every { userAccountRepository.save(capture(userArgumentCaptor)) } returns userAccount
every { timeService.now() } returns now
// WHEN
userAccountService.markVisitForCurrentUser()
// THEN
verify { userAccountRepository.findUserAccountByEmail(email) }
verify { userAccountRepository.save(userArgumentCaptor.captured) }
val userForSave = userArgumentCaptor.captured
assertThat(userForSave.lastVisit).isEqualTo(now)
assertThat(userForSave.id).isEqualTo(userAccount.id)
assertThat(userForSave.fullName).isEqualTo(userAccount.fullName)
}
}

@Nested
Expand Down