Skip to content

Commit 3d406e2

Browse files
Rajan MauryaRajan Maurya
authored andcommitted
feat(auth): Phase C Wave 2 — Login end-to-end Store5 migration
Second end-to-end feature wave. Adds the auth resource API + relocates the Login chain following the Wave 1 template. core/network/auth/api/AuthApi.kt (NEW) Suspend Ktorfit interface for Fineract authentication endpoints. Future auth-wave additions (OTP, refresh, logout) extend this same file. core/network/di/NetworkModule.kt + single { get<Ktorfit>().createAuthApi() } Method-level @deprecated on legacy login paths: - DataManagerAuth.login - ClientService.authenticate Both surfaces stay compileable for un-migrated callers; Phase D deletes them once nothing references them. core/data/auth/ (relocate + rewrite) git mv core/data/repository/LoginRepository.kt -> core/data/auth/LoginRepository.kt git mv core/data/repositoryImp/LoginRepositoryImp.kt -> core/data/auth/impl/LoginRepositoryImpl.kt (renamed) Impl now consumes AuthApi directly; no DataManagerAuth dependency. RepositoryModule import updated; binding remains in core/data. core/domain (delete pure-delegator use case) - useCases/LoginUseCase.kt (deleted) - di/UseCaseModule.kt: factoryOf(::LoginUseCase) removed Surviving use cases: UsernameValidationUseCase + PasswordValidationUseCase (validators — kept per the core/domain rule). feature/auth/{ui, di, navigation}/ (restructure with MVI triple) ui/ LoginState.kt — validation-error state (pre-submit gate) LoginAction.kt — sealed Submit / DismissError LoginEvent.kt — sealed NavigateToPasscode / ShowError(StringResource) LoginViewModel.kt — extends BaseViewModel<LoginState, LoginEvent, LoginAction> with SubmitHandler<PostAuthenticationResponse>. Submitted -> persist user via prefManager, emit NavigateToPasscode event. authenticated != true also routes to ShowError. Failed -> ShowError. LoginScreen.kt — uses MifosProgressIndicatorOverlay during submit; Snackbar for error events; passcode navigation on success. Includes 3 @Preview functions (Idle, Submitting, ValidationError) using org.jetbrains.compose.ui.tooling.preview.* (KMP-aware). di/AuthModule.kt — import updated to ui/ package; viewModelOf-only (Repository binding lives in core/data RepositoryModule per the Koin DI ownership boundary). navigation/ LoginRoute.kt — @serializable object (split from AuthNavigation) AuthNavigation.kt — NavGraphBuilder.authNavGraph + nav extensions No hardcoded user-facing strings: composeResources additions: feature_auth_update_server_configuration feature_auth_cd_arrow_forward feature_auth_cd_error_icon feature_auth_cd_password_visibility All button labels, content descriptions consume stringResource(...). feature/auth/build.gradle.kts + implementation(projects.core.ui) Other deps unchanged (core.data + core.domain for validators). Grep invariants pass: zero DataState, zero MifosProgressIndicator legacy imports, zero user-facing string literals, file layout matches plan.
1 parent 953f7b0 commit 3d406e2

21 files changed

Lines changed: 369 additions & 288 deletions

File tree

core/data/src/commonMain/kotlin/com/mifos/core/data/repository/LoginRepository.kt renamed to core/data/src/commonMain/kotlin/com/mifos/core/data/auth/LoginRepository.kt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,17 @@
77
*
88
* See https://github.com/openMF/mifos-x-field-officer-app/blob/master/LICENSE.md
99
*/
10-
package com.mifos.core.data.repository
10+
package com.mifos.core.data.auth
1111

1212
import com.mifos.core.network.model.PostAuthenticationResponse
1313

14-
/**
15-
* Created by Aditya Gupta on 06/08/23.
16-
*/
17-
1814
interface LoginRepository {
1915

16+
/**
17+
* Sends credentials to Fineract's `/authentication` endpoint. Returns the typed
18+
* response on success; throws on transport/HTTP failure (caller wraps in
19+
* `SubmitHandler.submit { ... }` for structured Submitting / Submitted / Failed
20+
* lifecycle).
21+
*/
2022
suspend fun login(username: String, password: String): PostAuthenticationResponse
2123
}

core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/LoginRepositoryImp.kt renamed to core/data/src/commonMain/kotlin/com/mifos/core/data/auth/impl/LoginRepositoryImpl.kt

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,19 @@
77
*
88
* See https://github.com/openMF/mifos-x-field-officer-app/blob/master/LICENSE.md
99
*/
10-
package com.mifos.core.data.repositoryImp
10+
package com.mifos.core.data.auth.impl
1111

12-
import com.mifos.core.data.repository.LoginRepository
13-
import com.mifos.core.network.datamanager.DataManagerAuth
12+
import com.mifos.core.data.auth.LoginRepository
13+
import com.mifos.core.network.auth.api.AuthApi
14+
import com.mifos.core.network.model.PostAuthenticationRequest
1415
import com.mifos.core.network.model.PostAuthenticationResponse
1516

16-
/**
17-
* Created by Aditya Gupta on 06/08/23.
18-
*/
19-
20-
class LoginRepositoryImp(
21-
private val dataManagerAuth: DataManagerAuth,
17+
class LoginRepositoryImpl(
18+
private val authApi: AuthApi,
2219
) : LoginRepository {
2320

24-
override suspend fun login(username: String, password: String): PostAuthenticationResponse {
25-
return dataManagerAuth.login(username.trim(), password.trim())
26-
}
21+
override suspend fun login(username: String, password: String): PostAuthenticationResponse =
22+
authApi.authenticate(
23+
PostAuthenticationRequest(username = username.trim(), password = password.trim()),
24+
)
2725
}

core/data/src/commonMain/kotlin/com/mifos/core/data/di/RepositoryModule.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ import com.mifos.core.data.repository.LoanRepaymentRepository
5151
import com.mifos.core.data.repository.LoanRepaymentScheduleRepository
5252
import com.mifos.core.data.repository.LoanReschedulesRepository
5353
import com.mifos.core.data.repository.LoanTransactionsRepository
54-
import com.mifos.core.data.repository.LoginRepository
54+
import com.mifos.core.data.auth.LoginRepository
55+
import com.mifos.core.data.auth.impl.LoginRepositoryImpl
5556
import com.mifos.core.data.repository.NewIndividualCollectionSheetRepository
5657
import com.mifos.core.data.repository.NoteRepository
5758
import com.mifos.core.data.repository.OfflineDashboardRepository
@@ -119,7 +120,6 @@ import com.mifos.core.data.repositoryImp.LoanRepaymentRepositoryImp
119120
import com.mifos.core.data.repositoryImp.LoanRepaymentScheduleRepositoryImp
120121
import com.mifos.core.data.repositoryImp.LoanReschedulesRepositoryImpl
121122
import com.mifos.core.data.repositoryImp.LoanTransactionsRepositoryImp
122-
import com.mifos.core.data.repositoryImp.LoginRepositoryImp
123123
import com.mifos.core.data.repositoryImp.NewIndividualCollectionSheetRepositoryImp
124124
import com.mifos.core.data.repositoryImp.NoteRepositoryImp
125125
import com.mifos.core.data.repositoryImp.OfflineDashboardRepositoryImp
@@ -162,7 +162,7 @@ import org.mifos.authenticator.passcode.PasscodeStorageAdapter
162162
val RepositoryModule = module {
163163
single<CoroutineDispatcher> { get(named(MifosDispatchers.IO.name)) }
164164

165-
singleOf(::LoginRepositoryImp) bind LoginRepository::class
165+
singleOf(::LoginRepositoryImpl) bind LoginRepository::class
166166
singleOf(::SearchRepositoryImp) bind SearchRepository::class
167167

168168
// Client

core/domain/src/commonMain/kotlin/com/mifos/core/domain/di/UseCaseModule.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ import com.mifos.core.domain.useCases.GetStaffInOfficeUseCase
6767
import com.mifos.core.domain.useCases.GetUserPathTrackingUseCase
6868
import com.mifos.core.domain.useCases.GroupsListPagingDataSource
6969
import com.mifos.core.domain.useCases.LoadSavingsAccountsAndTemplateUseCase
70-
import com.mifos.core.domain.useCases.LoginUseCase
7170
import com.mifos.core.domain.useCases.PasswordValidationUseCase
7271
import com.mifos.core.domain.useCases.RejectCheckerUseCase
7372
import com.mifos.core.domain.useCases.RemoveDocumentUseCase
@@ -144,7 +143,6 @@ val UseCaseModule = module {
144143
factoryOf(::GetUserPathTrackingUseCase)
145144
factoryOf(::GroupsListPagingDataSource)
146145
factoryOf(::LoadSavingsAccountsAndTemplateUseCase)
147-
factoryOf(::LoginUseCase)
148146
factoryOf(::PasswordValidationUseCase)
149147
factoryOf(::RejectCheckerUseCase)
150148
factoryOf(::RemoveDocumentUseCase)

core/domain/src/commonMain/kotlin/com/mifos/core/domain/useCases/LoginUseCase.kt

Lines changed: 0 additions & 32 deletions
This file was deleted.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 2025 Mifos Initiative
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
7+
*
8+
* See https://github.com/openMF/mifos-x-field-officer-app/blob/master/LICENSE.md
9+
*/
10+
package com.mifos.core.network.auth.api
11+
12+
import com.mifos.core.network.model.PostAuthenticationRequest
13+
import com.mifos.core.network.model.PostAuthenticationResponse
14+
import de.jensklingenberg.ktorfit.http.Body
15+
import de.jensklingenberg.ktorfit.http.POST
16+
17+
/**
18+
* Fineract `authentication` endpoints. Future auth-feature waves (OTP, refresh, logout)
19+
* add more methods here.
20+
*/
21+
interface AuthApi {
22+
23+
@POST("authentication")
24+
suspend fun authenticate(
25+
@Body request: PostAuthenticationRequest,
26+
): PostAuthenticationResponse
27+
}

core/network/src/commonMain/kotlin/com/mifos/core/network/datamanager/DataManagerAuth.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ class DataManagerAuth(
2424
* @param password Password
2525
* @return Basic OAuth
2626
*/
27+
@Deprecated(
28+
message = "Use com.mifos.core.network.auth.api.AuthApi.authenticate instead",
29+
level = DeprecationLevel.WARNING,
30+
)
2731
suspend fun login(username: String, password: String): PostAuthenticationResponse {
2832
val body = PostAuthenticationRequest(username = username, password = password)
2933
return baseApiManager.clientService.authenticate(body)

core/network/src/commonMain/kotlin/com/mifos/core/network/di/NetworkModule.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import com.mifos.core.network.BaseApiManager
1414
import com.mifos.core.network.KtorHttpClient
1515
import com.mifos.core.network.KtorfitClient
1616
import com.mifos.core.network.MifosInterceptor
17+
import com.mifos.core.network.auth.api.createAuthApi
1718
import com.mifos.core.network.center.api.createCenterApi
1819
import com.mifos.core.network.client.api.createClientApi
1920
import com.mifos.core.network.group.api.createGroupApi
@@ -62,6 +63,7 @@ val NetworkModule = module {
6263
// Per-resource Api factories (template's per-feature `core/network/<resource>/api/` pattern).
6364
// Each feature wave adds methods to the matching resource's interface; this DI list grows
6465
// as new resource APIs are introduced.
66+
single { get<Ktorfit>().createAuthApi() }
6567
single { get<Ktorfit>().createClientApi() }
6668
single { get<Ktorfit>().createCenterApi() }
6769
single { get<Ktorfit>().createGroupApi() }

core/network/src/commonMain/kotlin/com/mifos/core/network/services/ClientService.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ import kotlinx.coroutines.flow.Flow
5252
*/
5353
interface ClientService {
5454

55+
@Deprecated(
56+
message = "Use com.mifos.core.network.auth.api.AuthApi.authenticate instead",
57+
level = DeprecationLevel.WARNING,
58+
)
5559
@POST("authentication")
5660
suspend fun authenticate(
5761
@Body postAuthenticationRequest: PostAuthenticationRequest,

feature/auth/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ kotlin {
2424
implementation(compose.ui)
2525
implementation(projects.core.data)
2626
implementation(projects.core.domain)
27+
implementation(projects.core.ui)
2728
implementation(compose.components.uiToolingPreview)
2829
}
2930
}

0 commit comments

Comments
 (0)