214 lines
7.1 KiB
Kotlin
214 lines
7.1 KiB
Kotlin
/*
|
|
* Copyright (c) 2023 Proton AG
|
|
* This file is part of Proton AG and ProtonCore.
|
|
*
|
|
* ProtonCore is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* ProtonCore is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
package me.proton.core.auth.domain.usecase.signup
|
|
|
|
import io.mockk.MockKAnnotations
|
|
import io.mockk.coEvery
|
|
import io.mockk.coVerify
|
|
import io.mockk.every
|
|
import io.mockk.impl.annotations.MockK
|
|
import io.mockk.mockk
|
|
import io.mockk.slot
|
|
import kotlinx.coroutines.test.runTest
|
|
import me.proton.core.account.domain.repository.AccountRepository
|
|
import me.proton.core.auth.domain.entity.Modulus
|
|
import me.proton.core.auth.domain.repository.AuthRepository
|
|
import me.proton.core.auth.domain.usecase.GetPrimaryUser
|
|
import me.proton.core.challenge.domain.ChallengeManager
|
|
import me.proton.core.crypto.common.keystore.EncryptedString
|
|
import me.proton.core.crypto.common.keystore.KeyStoreCrypto
|
|
import me.proton.core.crypto.common.srp.Auth
|
|
import me.proton.core.crypto.common.srp.SrpCrypto
|
|
import me.proton.core.domain.entity.UserId
|
|
import me.proton.core.network.domain.ApiException
|
|
import me.proton.core.network.domain.session.SessionProvider
|
|
import me.proton.core.user.domain.entity.CreateUserType
|
|
import me.proton.core.user.domain.entity.Type
|
|
import me.proton.core.user.domain.entity.User
|
|
import me.proton.core.user.domain.repository.UserRepository
|
|
import org.junit.Assert.assertEquals
|
|
import org.junit.Assert.assertNotNull
|
|
import org.junit.Before
|
|
import org.junit.Test
|
|
import kotlin.test.assertFailsWith
|
|
import kotlin.test.assertSame
|
|
|
|
class PerformCreateExternalEmailUserTest {
|
|
// region mocks
|
|
private val authRepository = mockk<AuthRepository>(relaxed = true)
|
|
private val userRepository = mockk<UserRepository>(relaxed = true)
|
|
private val srpCrypto = mockk<SrpCrypto>(relaxed = true)
|
|
private val keyStoreCrypto = mockk<KeyStoreCrypto>(relaxed = true)
|
|
private val challengeManager = mockk<ChallengeManager>(relaxed = true)
|
|
|
|
@MockK(relaxed = true)
|
|
private lateinit var getPrimaryUser: GetPrimaryUser
|
|
@MockK(relaxed = true)
|
|
private lateinit var sessionProvider: SessionProvider
|
|
// endregion
|
|
|
|
// region test data
|
|
private val testPassword = "test-password"
|
|
private val testEncryptedPassword = "encrypted-$testPassword"
|
|
private val testEmail = "test-email"
|
|
private val testModulus = Modulus(modulusId = "test-id", modulus = "test-modulus")
|
|
private val testAuth = Auth(
|
|
version = 0,
|
|
modulusId = testModulus.modulusId,
|
|
salt = "test-salt",
|
|
verifier = "test-verifier"
|
|
)
|
|
private val testUserId = UserId("user_id")
|
|
|
|
// endregion
|
|
private val signupChallengeConfig = SignupChallengeConfig()
|
|
private lateinit var useCase: PerformCreateExternalEmailUser
|
|
|
|
@Before
|
|
fun beforeEveryTest() {
|
|
// GIVEN
|
|
MockKAnnotations.init(this)
|
|
|
|
useCase = PerformCreateExternalEmailUser(
|
|
authRepository,
|
|
userRepository,
|
|
sessionProvider,
|
|
srpCrypto,
|
|
keyStoreCrypto,
|
|
challengeManager,
|
|
signupChallengeConfig,
|
|
getPrimaryUser
|
|
)
|
|
coEvery {
|
|
srpCrypto.calculatePasswordVerifier(testEmail, any(), any(), any())
|
|
} returns testAuth
|
|
every { keyStoreCrypto.decrypt(any<String>()) } returns testPassword
|
|
every { keyStoreCrypto.encrypt(any<String>()) } returns testEncryptedPassword
|
|
|
|
coEvery { authRepository.randomModulus(null) } returns testModulus
|
|
coEvery { sessionProvider.getSessionId(null) } returns null
|
|
|
|
coEvery {
|
|
userRepository.createExternalEmailUser(any(), any(), any(), any(), any(), any())
|
|
} returns mockk {
|
|
every { userId } returns testUserId
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun `create external user success`() = runTest {
|
|
// WHEN
|
|
useCase.invoke(
|
|
testEmail,
|
|
keyStoreCrypto.encrypt(testPassword),
|
|
referrer = null
|
|
)
|
|
|
|
// THEN
|
|
coVerify(exactly = 1) { authRepository.randomModulus(null) }
|
|
coVerify(exactly = 1) {
|
|
srpCrypto.calculatePasswordVerifier(
|
|
username = testEmail,
|
|
password = any(),
|
|
modulusId = testModulus.modulusId,
|
|
modulus = testModulus.modulus
|
|
)
|
|
}
|
|
val emailSlot = slot<String>()
|
|
val passwordSlot = slot<EncryptedString>()
|
|
val typeSlot = slot<CreateUserType>()
|
|
coVerify(exactly = 1) {
|
|
userRepository.createExternalEmailUser(
|
|
capture(emailSlot),
|
|
capture(passwordSlot),
|
|
any(),
|
|
capture(typeSlot),
|
|
any(),
|
|
any(),
|
|
null
|
|
)
|
|
}
|
|
assertEquals(testEmail, emailSlot.captured)
|
|
assertEquals("encrypted-$testPassword", passwordSlot.captured)
|
|
assertEquals(CreateUserType.Normal, typeSlot.captured)
|
|
}
|
|
|
|
@Test
|
|
fun `create external user from credential-less`() = runTest {
|
|
// GIVEN
|
|
coEvery { getPrimaryUser() } returns mockk<User> {
|
|
every { userId } returns testUserId
|
|
every { type } returns Type.CredentialLess
|
|
}
|
|
|
|
// WHEN
|
|
useCase.invoke(
|
|
testEmail,
|
|
keyStoreCrypto.encrypt(testPassword),
|
|
referrer = null
|
|
)
|
|
|
|
// THEN
|
|
coVerify(exactly = 1) {
|
|
userRepository.createExternalEmailUser(
|
|
any(),
|
|
any(),
|
|
any(),
|
|
any(),
|
|
any(),
|
|
any(),
|
|
sessionUserId = testUserId // userId of credential-less is passed
|
|
)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun `create external user empty email`() = runTest {
|
|
val throwable = assertFailsWith<IllegalArgumentException> {
|
|
useCase.invoke(
|
|
" ",
|
|
keyStoreCrypto.encrypt(testPassword),
|
|
referrer = null
|
|
)
|
|
}
|
|
assertNotNull(throwable)
|
|
assertEquals(
|
|
"Email must not be empty.",
|
|
throwable.message
|
|
)
|
|
}
|
|
|
|
@Test
|
|
fun `user already exists`() = runTest {
|
|
val apiException = mockk<ApiException>()
|
|
coEvery {
|
|
userRepository.createExternalEmailUser(any(), any(), any(), any(), any(), any(), null)
|
|
} throws apiException
|
|
|
|
val result = assertFailsWith(ApiException::class) {
|
|
useCase.invoke(
|
|
testEmail,
|
|
keyStoreCrypto.encrypt(testPassword),
|
|
referrer = null
|
|
)
|
|
}
|
|
assertSame(apiException, result)
|
|
}
|
|
}
|