diff --git a/src/main/kotlin/authentication/Auth.kt b/src/main/kotlin/authentication/Auth.kt new file mode 100644 index 0000000..9fcb8f3 --- /dev/null +++ b/src/main/kotlin/authentication/Auth.kt @@ -0,0 +1,18 @@ +package authentication + +import Secrets + +interface Auth { + suspend fun login( + email: String, + password: String, + ) + + suspend fun logout() + + suspend fun isLoggedIn(): Boolean + + class Factory { + fun create(): Auth = if (Secrets.USE_LOCAL_MOCKS) LocalAuth else RemoteAuth + } +} diff --git a/src/main/kotlin/authentication/Authentication.kt b/src/main/kotlin/authentication/Authentication.kt index 04a8d08..e190163 100644 --- a/src/main/kotlin/authentication/Authentication.kt +++ b/src/main/kotlin/authentication/Authentication.kt @@ -1,9 +1,9 @@ package authentication -import org.koin.core.module.dsl.singleOf import org.koin.dsl.module val authenticationModule = module { - singleOf(::Authenticator) + factory { Auth.Factory() } + factory { get().create() } } diff --git a/src/main/kotlin/authentication/Authenticator.kt b/src/main/kotlin/authentication/Authenticator.kt deleted file mode 100644 index 01265e8..0000000 --- a/src/main/kotlin/authentication/Authenticator.kt +++ /dev/null @@ -1,26 +0,0 @@ -package authentication - -import kotlinx.coroutines.delay -import kotlin.time.Duration.Companion.seconds - -class Authenticator { - private var isLoggedIn: Boolean = true - - suspend fun login( - username: String, - password: String, - ): Boolean { - delay(3.seconds.inWholeMilliseconds) - return (username in validUsers && password == PASSWORD).also { isLoggedIn = it } - } - - suspend fun isLoggedIn(): Boolean { - delay(1.seconds.inWholeMilliseconds) - return isLoggedIn - } - - companion object { - private val validUsers = listOf("Robert", "Dunia", "Tom", "Max", "Casper", "Ed", "Kai", "Laura", "Niamh") - private const val PASSWORD = "ILoveRoky" - } -} diff --git a/src/main/kotlin/authentication/LocalAuth.kt b/src/main/kotlin/authentication/LocalAuth.kt new file mode 100644 index 0000000..e9fe1a9 --- /dev/null +++ b/src/main/kotlin/authentication/LocalAuth.kt @@ -0,0 +1,31 @@ +package authentication + +import kotlinx.coroutines.delay +import kotlin.time.Duration.Companion.seconds + +object LocalAuth : Auth { + private var isLoggedIn: Boolean = false + + override suspend fun login( + email: String, + password: String, + ) { + delay(3.seconds) + println("local Auth login") + isLoggedIn = (email in validUsers && password == PASSWORD) + } + + override suspend fun logout() { + println("local Auth logout") + isLoggedIn = false + } + + override suspend fun isLoggedIn(): Boolean { + println("local local is logged in") + return isLoggedIn + } + + private val validUsers = + listOf("Robert", "Dunia", "Tom", "Max", "Casper", "Ed", "Kai", "Laura", "Niamh", "Sofia") + private const val PASSWORD = "ILoveRoky" +} diff --git a/src/main/kotlin/authentication/RemoteAuth.kt b/src/main/kotlin/authentication/RemoteAuth.kt new file mode 100644 index 0000000..f9a567c --- /dev/null +++ b/src/main/kotlin/authentication/RemoteAuth.kt @@ -0,0 +1,32 @@ +package authentication + +import kotlinx.coroutines.delay +import kotlin.time.Duration.Companion.seconds + +// SUPABASEEEE +object RemoteAuth : Auth { + private var isLoggedIn: Boolean = false + + override suspend fun login( + email: String, + password: String, + ) { + println("Remote Auth login") + delay(3.seconds) + isLoggedIn = (email in validUsers && password == PASSWORD) + } + + override suspend fun logout() { + println("Remote Auth logout") + isLoggedIn = false + } + + override suspend fun isLoggedIn(): Boolean { + println("Remote Auth is logged in") + return isLoggedIn + } + + private val validUsers = + listOf("Robert", "Dunia", "Tom", "Max", "Casper", "Ed", "Kai", "Laura", "Niamh", "Sofia") + private const val PASSWORD = "ILoveRoky" +} diff --git a/src/main/kotlin/login/LoginUseCase.kt b/src/main/kotlin/login/LoginUseCase.kt index b78af2e..3be8a5a 100644 --- a/src/main/kotlin/login/LoginUseCase.kt +++ b/src/main/kotlin/login/LoginUseCase.kt @@ -1,11 +1,11 @@ package login -import authentication.Authenticator +import authentication.Auth import login.LoginEvent.Login import login.LoginViewState.Idle class LoginUseCase( - private val authenticator: Authenticator, + private val authenticator: Auth, ) { suspend operator fun invoke(event: Login): LoginViewState = with(event) { @@ -13,7 +13,10 @@ class LoginUseCase( when { username.isBlank() -> ERROR_USERNAME password.isBlank() -> ERROR_PASSWORD - else -> if (authenticator.login(username, password)) LOGIN_SUCCESS else LOGIN_FAILURE + else -> { + authenticator.login(username, password) + if (authenticator.isLoggedIn()) LOGIN_SUCCESS else LOGIN_FAILURE + } } return Idle(userName = event.username, password = "", status = status) } diff --git a/src/main/kotlin/mainmenu/MainMenuPresenter.kt b/src/main/kotlin/mainmenu/MainMenuPresenter.kt index 3c0eb45..29d807f 100644 --- a/src/main/kotlin/mainmenu/MainMenuPresenter.kt +++ b/src/main/kotlin/mainmenu/MainMenuPresenter.kt @@ -3,7 +3,7 @@ package mainmenu import StopApp import arch.Presenter import arch.RokyDispatchers -import authentication.Authenticator +import authentication.Auth import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.launch @@ -15,7 +15,7 @@ import navigation.NavigateToAppWindow class MainMenuPresenter( private val quit: StopApp, private val navigate: NavigateToAppWindow, - private val authenticator: Authenticator, + private val authenticator: Auth, private val windowScope: CoroutineScope, dispatchers: RokyDispatchers, ) : Presenter(dispatchers) { diff --git a/src/test/kotlin/login/LoginUseCaseTest.kt b/src/test/kotlin/login/LoginUseCaseTest.kt index 59cdeb9..10a3ad6 100644 --- a/src/test/kotlin/login/LoginUseCaseTest.kt +++ b/src/test/kotlin/login/LoginUseCaseTest.kt @@ -1,13 +1,12 @@ package login -import authentication.Authenticator +import authentication.Auth import coAnswersDelayed import io.kotest.matchers.Matcher import io.kotest.matchers.MatcherResult import io.kotest.matchers.should import io.mockk.coEvery import io.mockk.mockk -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest import login.LoginEvent.Login import login.LoginUseCase.Companion.ERROR_PASSWORD @@ -17,15 +16,14 @@ import login.LoginUseCase.Companion.LOGIN_SUCCESS import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test -@OptIn(ExperimentalCoroutinesApi::class) class LoginUseCaseTest { private lateinit var logIn: LoginUseCase - private lateinit var authenticator: Authenticator + private lateinit var authenticator: Auth @BeforeEach fun setUp() { authenticator = mockk(relaxed = true) - coEvery { authenticator.login(any(), any()) } coAnswersDelayed { false } + coEvery { authenticator.isLoggedIn() } coAnswersDelayed { false } logIn = LoginUseCase(authenticator) } @@ -46,7 +44,7 @@ class LoginUseCaseTest { @Test fun `given username and password is present, when credentials are valid, then status is login success`() = runTest { - coEvery { authenticator.login(any(), any()) } coAnswersDelayed { true } + coEvery { authenticator.isLoggedIn() } coAnswersDelayed { true } val event = Login(username = "rob", password = "rob") logIn(event) should haveStatus(LOGIN_SUCCESS) } @@ -54,7 +52,7 @@ class LoginUseCaseTest { @Test fun `given username and password is present, when credentials are invalid, then status is login failure`() = runTest { - coEvery { authenticator.login(any(), any()) } coAnswersDelayed { false } + coEvery { authenticator.isLoggedIn() } coAnswersDelayed { false } val event = Login(username = "rob", password = "rob") logIn(event) should haveStatus(LOGIN_FAILURE) } diff --git a/src/test/kotlin/mainmenu/MainMenuPresenterTest.kt b/src/test/kotlin/mainmenu/MainMenuPresenterTest.kt index 6ba7dae..6f299ee 100644 --- a/src/test/kotlin/mainmenu/MainMenuPresenterTest.kt +++ b/src/test/kotlin/mainmenu/MainMenuPresenterTest.kt @@ -2,7 +2,7 @@ package mainmenu import StopApp import arch.RokyDispatchers -import authentication.Authenticator +import authentication.Auth import coAnswersDelayed import io.mockk.coEvery import io.mockk.every @@ -25,7 +25,7 @@ import org.junit.jupiter.api.Test @OptIn(ExperimentalCoroutinesApi::class) class MainMenuPresenterTest { private lateinit var quit: StopApp - private lateinit var authenticator: Authenticator + private lateinit var authenticator: Auth private lateinit var presenter: MainMenuPresenter private lateinit var navigate: NavigateToAppWindow private lateinit var view: MainMenuView