Skip to content
Open
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 @@ -9,7 +9,6 @@ import com.auth0.universalcomponents.di.viewmodelfactory.AuthenticatorMethodView
import com.auth0.universalcomponents.di.viewmodelfactory.EnrollmentViewModelFactory
import com.auth0.universalcomponents.di.viewmodelfactory.MFAEnrolledItemViewModelFactory
import com.auth0.universalcomponents.di.viewmodelfactory.PasskeyViewModelFactory
import com.auth0.universalcomponents.domain.DispatcherProvider
import com.auth0.universalcomponents.domain.model.AuthenticatorType
import com.auth0.universalcomponents.domain.repository.MyAccountRepository
import com.auth0.universalcomponents.domain.repository.UserRepository
Expand All @@ -19,7 +18,6 @@ import com.auth0.universalcomponents.domain.usecase.GetEnabledAuthenticatorMetho
import com.auth0.universalcomponents.domain.usecase.GetEnrolledAuthenticatorsUseCase
import com.auth0.universalcomponents.domain.usecase.GetUserInfoUseCase
import com.auth0.universalcomponents.domain.usecase.VerifyAuthenticatorUseCase
import com.auth0.universalcomponents.helper.DispatcherProviderImpl

object UniversalComponentsModule {

Expand Down Expand Up @@ -63,36 +61,31 @@ object UniversalComponentsModule {
private fun provideEnabledAuthenticatorMethodsUseCase(): GetEnabledAuthenticatorMethodsUseCase {
return GetEnabledAuthenticatorMethodsUseCase(
repository = provideMyAccountRepository(),
dispatcherProvider = provideDispatcherProvider(),
)
}

private fun provideGetEnrolledAuthenticatorsUseCase(): GetEnrolledAuthenticatorsUseCase {
return GetEnrolledAuthenticatorsUseCase(
repository = provideMyAccountRepository(),
dispatcherProvider = provideDispatcherProvider()
repository = provideMyAccountRepository()
)
}

private fun provideDeleteAuthenticationMethodUseCase(): DeleteAuthenticationMethodUseCase {
return DeleteAuthenticationMethodUseCase(
repository = provideMyAccountRepository(),
dispatcherProvider = provideDispatcherProvider()
repository = provideMyAccountRepository()
)
}


private fun provideEnrollAuthenticatorUseCase(): EnrollAuthenticatorUseCase {
return EnrollAuthenticatorUseCase(
repository = provideMyAccountRepository(),
dispatcherProvider = provideDispatcherProvider()
repository = provideMyAccountRepository()
)
}

private fun provideVerifyAuthenticatorUseCase(): VerifyAuthenticatorUseCase {
return VerifyAuthenticatorUseCase(
repository = provideMyAccountRepository(),
dispatcherProvider = provideDispatcherProvider()
repository = provideMyAccountRepository()
)
}

Expand All @@ -114,8 +107,4 @@ object UniversalComponentsModule {
return TokenManager.getInstance()
}

private fun provideDispatcherProvider(): DispatcherProvider {
return DispatcherProviderImpl()
}

}
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
package com.auth0.universalcomponents.domain.usecase

import com.auth0.universalcomponents.domain.DispatcherProvider
import com.auth0.universalcomponents.domain.error.Auth0Error
import com.auth0.universalcomponents.domain.network.EmptyResult
import com.auth0.universalcomponents.domain.network.Result
import com.auth0.universalcomponents.domain.network.safeCall
import com.auth0.universalcomponents.domain.repository.MyAccountRepository
import kotlinx.coroutines.withContext

/**
* UseCase that handles deletion of an authentication method
* Fetches token and calls repository to delete the specified authentication method
*/
class DeleteAuthenticationMethodUseCase(
private val repository: MyAccountRepository,
private val dispatcherProvider: DispatcherProvider
private val repository: MyAccountRepository
) {
private companion object {
private const val REQUIRED_SCOPES = "delete:me:authentication_methods"
Expand All @@ -26,13 +23,11 @@ class DeleteAuthenticationMethodUseCase(
* @return Result indicating success or error
*/
suspend operator fun invoke(authenticationMethodId: String): EmptyResult<Auth0Error> =
withContext(dispatcherProvider.io) {
safeCall {
repository.deleteAuthenticationMethod(
authenticationMethodId,
REQUIRED_SCOPES
)
return@withContext Result.Success(Unit)
}
safeCall {
repository.deleteAuthenticationMethod(
authenticationMethodId,
REQUIRED_SCOPES
)
Result.Success(Unit)
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
package com.auth0.universalcomponents.domain.usecase

import com.auth0.universalcomponents.domain.DispatcherProvider
import com.auth0.universalcomponents.domain.error.Auth0Error
import com.auth0.universalcomponents.domain.model.AuthenticatorType
import com.auth0.universalcomponents.domain.model.EnrollmentInput
import com.auth0.universalcomponents.domain.model.EnrollmentResult
import com.auth0.universalcomponents.domain.network.Result
import com.auth0.universalcomponents.domain.network.safeCall
import com.auth0.universalcomponents.domain.repository.MyAccountRepository
import kotlinx.coroutines.withContext

/**
* UseCase for enrolling authenticators
* Handles TOTP, Push Notification, Recovery Code, Email, and Phone enrollments
*/
class EnrollAuthenticatorUseCase(
private val repository: MyAccountRepository,
private val dispatcherProvider: DispatcherProvider
private val repository: MyAccountRepository
) {
private companion object {
private const val REQUIRED_SCOPES = "create:me:authentication_methods"
Expand All @@ -31,8 +28,7 @@ class EnrollAuthenticatorUseCase(
suspend operator fun invoke(
authenticatorType: AuthenticatorType,
input: EnrollmentInput = EnrollmentInput.None
): Result<EnrollmentResult, Auth0Error> = withContext(dispatcherProvider.io) {
safeCall {
): Result<EnrollmentResult, Auth0Error> = safeCall {
val result = when (authenticatorType) {
AuthenticatorType.TOTP -> {
val challenge = repository.enrollTotp(REQUIRED_SCOPES)
Expand Down Expand Up @@ -95,5 +91,4 @@ class EnrollAuthenticatorUseCase(
}
result
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package com.auth0.universalcomponents.domain.usecase
import com.auth0.android.result.AuthenticationMethod
import com.auth0.android.result.Factor
import com.auth0.android.result.MfaAuthenticationMethod
import com.auth0.universalcomponents.domain.DispatcherProvider
import com.auth0.universalcomponents.domain.error.Auth0Error
import com.auth0.universalcomponents.domain.model.AuthenticatorMethod
import com.auth0.universalcomponents.domain.model.AuthenticatorType
Expand All @@ -14,37 +13,33 @@ import com.auth0.universalcomponents.domain.network.safeCall
import com.auth0.universalcomponents.domain.repository.MyAccountRepository
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.withContext

/**
* UseCase that fetches enabled primary and secondary authenticator methods
*/
class GetEnabledAuthenticatorMethodsUseCase(
private val repository: MyAccountRepository,
private val dispatcherProvider: DispatcherProvider,
) {
private companion object {
private const val REQUIRED_SCOPES_FACTORS = "read:me:factors"
private const val REQUIRED_SCOPES_AUTHENTICATION = "read:me:authentication_methods"
}

suspend operator fun invoke(): Result<AuthenticatorMethod, Auth0Error> =
withContext(dispatcherProvider.io) {
safeCall {
coroutineScope {
val factorsDeferred = async {
repository.getFactors(REQUIRED_SCOPES_FACTORS)
}
val authMethodsDeferred = async {
repository.getAuthenticatorMethods(REQUIRED_SCOPES_AUTHENTICATION)
}

val (factors, authMethods) = Pair(
factorsDeferred.await(),
authMethodsDeferred.await()
)
mapAuthenticatorMethods(factors, authMethods)
safeCall {
coroutineScope {
val factorsDeferred = async {
repository.getFactors(REQUIRED_SCOPES_FACTORS)
}
val authMethodsDeferred = async {
repository.getAuthenticatorMethods(REQUIRED_SCOPES_AUTHENTICATION)
}

val (factors, authMethods) = Pair(
factorsDeferred.await(),
authMethodsDeferred.await()
)
mapAuthenticatorMethods(factors, authMethods)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,19 @@ import com.auth0.android.result.PasskeyAuthenticationMethod
import com.auth0.android.result.PhoneAuthenticationMethod
import com.auth0.android.result.PushNotificationAuthenticationMethod
import com.auth0.android.result.TotpAuthenticationMethod
import com.auth0.universalcomponents.domain.DispatcherProvider
import com.auth0.universalcomponents.domain.error.Auth0Error
import com.auth0.universalcomponents.domain.model.AuthenticatorType
import com.auth0.universalcomponents.domain.model.EnrolledAuthenticationMethod
import com.auth0.universalcomponents.domain.network.Result
import com.auth0.universalcomponents.domain.network.safeCall
import com.auth0.universalcomponents.domain.repository.MyAccountRepository
import kotlinx.coroutines.withContext

/**
* UseCase that fetches and filters authentication methods by type
* Returns only confirmed methods for the specified authenticator type
*/
class GetEnrolledAuthenticatorsUseCase(
private val repository: MyAccountRepository,
private val dispatcherProvider: DispatcherProvider
private val repository: MyAccountRepository
) {
private companion object {
private const val REQUIRED_SCOPES = "read:me:authentication_methods"
Expand All @@ -34,11 +31,9 @@ class GetEnrolledAuthenticatorsUseCase(
* @return Result containing list of confirmed authentication methods
*/
suspend operator fun invoke(type: AuthenticatorType): Result<List<EnrolledAuthenticationMethod>, Auth0Error> =
withContext(dispatcherProvider.io) {
safeCall {
val authMethods = repository.getAuthenticatorMethods(REQUIRED_SCOPES)
filterEnrolledAuthenticationMethods(authMethods, type)
}
safeCall {
val authMethods = repository.getAuthenticatorMethods(REQUIRED_SCOPES)
filterEnrolledAuthenticationMethods(authMethods, type)
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
package com.auth0.universalcomponents.domain.usecase

import com.auth0.android.result.AuthenticationMethod
import com.auth0.universalcomponents.domain.DispatcherProvider
import com.auth0.universalcomponents.domain.error.Auth0Error
import com.auth0.universalcomponents.domain.model.VerificationInput
import com.auth0.universalcomponents.domain.network.Result
import com.auth0.universalcomponents.domain.network.safeCall
import com.auth0.universalcomponents.domain.repository.MyAccountRepository
import kotlinx.coroutines.withContext

/**
* UseCase for verifying enrolled authenticators
* Handles both OTP-based and non-OTP verifications
*/
class VerifyAuthenticatorUseCase(
private val repository: MyAccountRepository,
private val dispatcherProvider: DispatcherProvider
private val repository: MyAccountRepository
) {
private companion object {
private const val REQUIRED_SCOPES = "create:me:authentication_methods"
Expand All @@ -28,8 +25,7 @@ class VerifyAuthenticatorUseCase(
*/
suspend operator fun invoke(
input: VerificationInput
): Result<AuthenticationMethod, Auth0Error> = withContext(dispatcherProvider.io) {
safeCall {
): Result<AuthenticationMethod, Auth0Error> = safeCall {

val authMethod = when (input) {
is VerificationInput.WithOtp -> {
Expand All @@ -51,5 +47,4 @@ class VerifyAuthenticatorUseCase(
}
authMethod
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,31 @@ package com.auth0.universalcomponents.domain.usecase
import com.auth0.universalcomponents.domain.error.Auth0Error
import com.auth0.universalcomponents.domain.network.Result
import com.auth0.universalcomponents.domain.repository.MyAccountRepository
import com.auth0.universalcomponents.helpers.TestDispatcherProvider
import com.google.common.truth.Truth
import io.mockk.clearAllMocks
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.mockk
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import org.junit.After
import org.junit.Before
import org.junit.Test

@OptIn(ExperimentalCoroutinesApi::class)
class DeleteAuthenticationMethodUseCaseTest {

private lateinit var repository: MyAccountRepository
private lateinit var useCase: DeleteAuthenticationMethodUseCase

private val testDispatcher = StandardTestDispatcher()
private val dispatcherProvider = TestDispatcherProvider(testDispatcher)

@Before
fun setup() {
Dispatchers.setMain(testDispatcher)

repository = mockk()
useCase = DeleteAuthenticationMethodUseCase(
repository = repository,
dispatcherProvider = dispatcherProvider
repository = repository
)
}

@After
fun tearDown() {
Dispatchers.resetMain()
clearAllMocks()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,49 +7,35 @@ import com.auth0.universalcomponents.domain.model.EnrollmentInput
import com.auth0.universalcomponents.domain.model.EnrollmentResult
import com.auth0.universalcomponents.domain.network.Result
import com.auth0.universalcomponents.domain.repository.MyAccountRepository
import com.auth0.universalcomponents.helpers.TestDispatcherProvider
import com.google.common.truth.Truth
import io.mockk.clearAllMocks
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.mockk
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import org.junit.After
import org.junit.Assert
import org.junit.Before
import org.junit.Test

@OptIn(ExperimentalCoroutinesApi::class)
class EnrollAuthenticatorUseCaseTest {

private lateinit var repository: MyAccountRepository
private lateinit var useCase: EnrollAuthenticatorUseCase

private val testDispatcher = StandardTestDispatcher()
private val dispatcherProvider = TestDispatcherProvider(testDispatcher)

private val requiredScope = "create:me:authentication_methods"


@Before
fun setup() {
Dispatchers.setMain(testDispatcher)

repository = mockk()
useCase = EnrollAuthenticatorUseCase(
repository = repository,
dispatcherProvider = dispatcherProvider
repository = repository
)
}

@After
fun tearDown() {
Dispatchers.resetMain()
clearAllMocks()
}

Expand Down
Loading
Loading