From 5761895fa2489a26ba6b3a8bbdeef23ac9fab6fe Mon Sep 17 00:00:00 2001 From: MajoritySky2496 Date: Sun, 24 Mar 2024 18:01:50 +0500 Subject: [PATCH 01/19] 71-Password-Recovery Made: 1. api 2. response 3. dto 4. DataMapper 5. Exception mapper --- .../NetworkToResetPasswordExceptionMapper.kt | 114 ++++++++++++++++++ .../authorization/data/ResetDataMapper.kt | 56 +++++++++ .../data/api/ResetPasswordApi.kt | 27 +++++ .../data/api/ResetPasswordRemoteDataSource.kt | 14 +++ ...irmResetPasswordByEmailWithCodeInputDto.kt | 5 + ...rmResetPasswordByEmailWithCodeOutputDto.kt | 8 ++ .../data/models/ResetPasswordInputDto.kt | 7 ++ .../data/models/ResetPasswordOutputDto.kt | 7 ++ .../data/models/SaveNewPasswordInputDto.kt | 7 ++ .../data/models/SaveNewPasswordOutputDto.kt | 6 + .../ResetPasswordConfirmByEmailRequest.kt | 8 ++ .../models/request/ResetPasswordRequest.kt | 9 ++ .../models/request/SaveNewPasswordRequest.kt | 11 ++ .../response/ConfirmResetPasswordResponse.kt | 11 ++ .../ResetPasswordConfirmationResponse.kt | 10 ++ .../response/SaveNewPasswordResponse.kt | 11 ++ .../exceptions/ResetPasswordException.kt | 76 ++++++++++++ 17 files changed, 387 insertions(+) create mode 100644 app/src/main/java/app/cashadvisor/authorization/data/NetworkToResetPasswordExceptionMapper.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/data/ResetDataMapper.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/data/api/ResetPasswordApi.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/data/api/ResetPasswordRemoteDataSource.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/data/models/ConfirmResetPasswordByEmailWithCodeInputDto.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/data/models/ConfirmResetPasswordByEmailWithCodeOutputDto.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/data/models/ResetPasswordInputDto.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/data/models/ResetPasswordOutputDto.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/data/models/SaveNewPasswordInputDto.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/data/models/SaveNewPasswordOutputDto.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/data/models/request/ResetPasswordConfirmByEmailRequest.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/data/models/request/ResetPasswordRequest.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/data/models/request/SaveNewPasswordRequest.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/data/models/response/ConfirmResetPasswordResponse.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/data/models/response/ResetPasswordConfirmationResponse.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/data/models/response/SaveNewPasswordResponse.kt create mode 100644 app/src/main/java/app/cashadvisor/common/utill/exceptions/ResetPasswordException.kt diff --git a/app/src/main/java/app/cashadvisor/authorization/data/NetworkToResetPasswordExceptionMapper.kt b/app/src/main/java/app/cashadvisor/authorization/data/NetworkToResetPasswordExceptionMapper.kt new file mode 100644 index 00000000..982d2cfc --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/data/NetworkToResetPasswordExceptionMapper.kt @@ -0,0 +1,114 @@ +package app.cashadvisor.authorization.data + +import app.cashadvisor.authorization.data.models.response.customError.ErrorWrongConfirmationCodeResponse +import app.cashadvisor.common.data.models.ErrorResponse +import app.cashadvisor.common.utill.exceptions.LoginException +import app.cashadvisor.common.utill.exceptions.NetworkException +import app.cashadvisor.common.utill.exceptions.ResetPasswordException +import javax.inject.Inject +import kotlinx.serialization.json.Json + +class NetworkToResetPasswordExceptionMapper @Inject constructor( + private val json: Json +) { + fun handleConfirmResetPasswordByEmailWithCode(exception: NetworkException):ResetPasswordException{ + return when(exception){ + is NetworkException.BadRequest -> { + val errorResponse = handleErrorResponse(exception.errorBody) + ResetPasswordException.ConfirmResetPasswordByEmailWithCode.BadRequestInvalidCodeOrMissingContentTypeHeader( + message = errorResponse.message, + statusCode = errorResponse.statusCode + ) + } + is NetworkException.Unauthorized -> { + val errorResponse = handleErrorResponse(exception.errorBody) + ResetPasswordException.ConfirmResetPasswordByEmailWithCode.UnauthorizedInvalidTokenOrMissingContentTypeHeader( + remainingAttempts = errorResponse.remainingAttempts, + lockDuration = errorResponse.lockDuration, + message = errorResponse.error, + statusCode = errorResponse.statusCode + ) + } + is NetworkException.InternalServerError -> { + val errorResponse = handleErrorResponse(exception.errorBody) + ResetPasswordException.ConfirmResetPasswordByEmailWithCode.InternalServerErrorFailedToConfirmResetPassword( + message = errorResponse.error, + statusCode = errorResponse.statusCode + ) + } + else -> handleCommonException(exception) + } + + } + fun handleConfirmEmailToResetPassword(exception: NetworkException):ResetPasswordException{ + return when(exception){ + is NetworkException.BadRequest -> { + val errorResponse = handleErrorResponse(exception.errorBody) + ResetPasswordException.ConfirmEmailToResetPassword.BadRequestInvalidEmailOrMissingContentTypeHeader( + message = errorResponse.message, + statusCode = errorResponse.statusCode + ) + } + is NetworkException.InternalServerError -> { + val errorResponse = handleErrorResponse(exception.errorBody) + ResetPasswordException.ConfirmEmailToResetPassword.InternalServerErrorFailedToGenerateTokenOrSendEmail( + message = errorResponse.message, + statusCode = errorResponse.statusCode + ) + } + else -> handleCommonException(exception) + } + + } + fun handleSaveNewPassword(exception: NetworkException):ResetPasswordException{ + return when(exception){ + is NetworkException.BadRequest -> { + val errorResponse = handleErrorResponse(exception.errorBody) + ResetPasswordException.SaveNewPassword.BadRequestInvalidPasswordOrMissingContentTypeHeader( + message = errorResponse.message, + statusCode = errorResponse.statusCode + ) + } + is NetworkException.Unauthorized -> { + val errorResponse = handleErrorResponse(exception.errorBody) + ResetPasswordException.SaveNewPassword.UnauthorizedInvalidTokenOrMissingContentTypeHeader( + message = errorResponse.error, + statusCode = errorResponse.statusCode + ) + } + is NetworkException.InternalServerError -> { + val errorResponse = handleErrorResponse(exception.errorBody) + ResetPasswordException.SaveNewPassword.InternalServerErrorFailedToResetPassword( + message = errorResponse.message, + statusCode = errorResponse.statusCode + ) + } + else -> handleCommonException(exception) + } + } + + private fun handleCommonException(exception: NetworkException): ResetPasswordException { + return when (exception) { + is NetworkException.NoInternetConnection -> { + val errorResponse = handleErrorResponse(exception.errorBody) + ResetPasswordException.NoConnection(errorResponse.message) + } + + is NetworkException.Undefined -> { + ResetPasswordException.Undefined() + } + + else -> { + ResetPasswordException.Undefined() + } + } + } + private inline fun handleErrorResponse(errorMessage: String): T { + try { + return json.decodeFromString(errorMessage) + + } catch (e: Exception) { + throw LoginException.Undefined() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/authorization/data/ResetDataMapper.kt b/app/src/main/java/app/cashadvisor/authorization/data/ResetDataMapper.kt new file mode 100644 index 00000000..eb04c1cb --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/data/ResetDataMapper.kt @@ -0,0 +1,56 @@ +package app.cashadvisor.authorization.data + +import app.cashadvisor.authorization.data.models.ConfirmResetPasswordByEmailWithCodeInputDto +import app.cashadvisor.authorization.data.models.ConfirmResetPasswordByEmailWithCodeOutputDto +import app.cashadvisor.authorization.data.models.ResetPasswordInputDto +import app.cashadvisor.authorization.data.models.ResetPasswordOutputDto +import app.cashadvisor.authorization.data.models.SaveNewPasswordInputDto +import app.cashadvisor.authorization.data.models.SaveNewPasswordOutputDto +import app.cashadvisor.authorization.data.models.request.ResetPasswordConfirmByEmailRequest +import app.cashadvisor.authorization.data.models.request.ResetPasswordRequest +import app.cashadvisor.authorization.data.models.request.SaveNewPasswordRequest +import app.cashadvisor.authorization.data.models.response.ConfirmResetPasswordResponse +import app.cashadvisor.authorization.data.models.response.ResetPasswordConfirmationResponse +import app.cashadvisor.authorization.data.models.response.SaveNewPasswordResponse +import javax.inject.Inject + +class ResetDataMapper @Inject constructor() { + + fun toResetPasswordConfirmByEmailRequest(inputDto: ConfirmResetPasswordByEmailWithCodeInputDto): ResetPasswordConfirmByEmailRequest { + return ResetPasswordConfirmByEmailRequest( + email = inputDto.email + ) + } + fun toConfirmResetPasswordByEmailWithCodeOutputDto(response:ConfirmResetPasswordResponse): ConfirmResetPasswordByEmailWithCodeOutputDto{ + return ConfirmResetPasswordByEmailWithCodeOutputDto( + message = response.message, + token = response.token, + statusCode = response.statusCode + ) + } + fun toResetPasswordRequest(inputDto:ResetPasswordInputDto):ResetPasswordRequest{ + return ResetPasswordRequest( + code = inputDto.code, + token = inputDto.token + ) + } + fun toResetPasswordOutputDto(response:ResetPasswordConfirmationResponse):ResetPasswordOutputDto{ + return ResetPasswordOutputDto( + message = response.message, + statusCode = response.statusCode + ) + } + fun toSaveNewPasswordRequest(inputDto:SaveNewPasswordInputDto):SaveNewPasswordRequest{ + return SaveNewPasswordRequest( + email = inputDto.email, + password = inputDto.password, + resetToken = inputDto.resetToken + ) + } + fun toSaveNewPasswordOutputDto(response: SaveNewPasswordResponse):SaveNewPasswordOutputDto{ + return SaveNewPasswordOutputDto( + message = response.message, + statusCode = response.statusCode + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/authorization/data/api/ResetPasswordApi.kt b/app/src/main/java/app/cashadvisor/authorization/data/api/ResetPasswordApi.kt new file mode 100644 index 00000000..3b57eb39 --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/data/api/ResetPasswordApi.kt @@ -0,0 +1,27 @@ +package app.cashadvisor.authorization.data.api + +import app.cashadvisor.authorization.data.models.request.ResetPasswordRequest +import app.cashadvisor.authorization.data.models.request.ResetPasswordConfirmByEmailRequest +import app.cashadvisor.authorization.data.models.request.SaveNewPasswordRequest +import app.cashadvisor.authorization.data.models.response.ConfirmResetPasswordResponse +import app.cashadvisor.authorization.data.models.response.ResetPasswordConfirmationResponse +import app.cashadvisor.authorization.data.models.response.SaveNewPasswordResponse +import retrofit2.http.Body +import retrofit2.http.Headers +import retrofit2.http.POST + +interface ResetPasswordApi { + + @Headers("Content-Type: application/json") + @POST("/auth/login/reset/password/confirm") + suspend fun resetPassword(@Body passworResetRequest: ResetPasswordRequest ):ResetPasswordConfirmationResponse + + @Headers("Content-Type: application/json") + @POST("/auth/login/reset/password/") + suspend fun resetPasswordConfirm(@Body resetPasswordConfirmByEmailRequest: ResetPasswordConfirmByEmailRequest):ConfirmResetPasswordResponse + + @Headers("Content-Type: application/json") + @POST("/auth/login/reset/password/") + suspend fun saveNewPassword(@Body saveNewPasswordRequest: SaveNewPasswordRequest):SaveNewPasswordResponse + +} \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/authorization/data/api/ResetPasswordRemoteDataSource.kt b/app/src/main/java/app/cashadvisor/authorization/data/api/ResetPasswordRemoteDataSource.kt new file mode 100644 index 00000000..e561f5cf --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/data/api/ResetPasswordRemoteDataSource.kt @@ -0,0 +1,14 @@ +package app.cashadvisor.authorization.data.api + +import app.cashadvisor.authorization.data.models.ConfirmResetPasswordByEmailWithCodeInputDto +import app.cashadvisor.authorization.data.models.ConfirmResetPasswordByEmailWithCodeOutputDto +import app.cashadvisor.authorization.data.models.ResetPasswordInputDto +import app.cashadvisor.authorization.data.models.ResetPasswordOutputDto +import app.cashadvisor.authorization.data.models.SaveNewPasswordInputDto +import app.cashadvisor.authorization.data.models.SaveNewPasswordOutputDto + +interface ResetPasswordRemoteDataSource { + suspend fun resetPassword(inputDto: ResetPasswordInputDto):ResetPasswordOutputDto + suspend fun confirmResetPasswordByEmailWithCode(inputDto:ConfirmResetPasswordByEmailWithCodeInputDto):ConfirmResetPasswordByEmailWithCodeOutputDto + suspend fun saveNewPassword(inputDto:SaveNewPasswordInputDto):SaveNewPasswordOutputDto +} \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/authorization/data/models/ConfirmResetPasswordByEmailWithCodeInputDto.kt b/app/src/main/java/app/cashadvisor/authorization/data/models/ConfirmResetPasswordByEmailWithCodeInputDto.kt new file mode 100644 index 00000000..b870e8e8 --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/data/models/ConfirmResetPasswordByEmailWithCodeInputDto.kt @@ -0,0 +1,5 @@ +package app.cashadvisor.authorization.data.models + +data class ConfirmResetPasswordByEmailWithCodeInputDto( + val email:String +) diff --git a/app/src/main/java/app/cashadvisor/authorization/data/models/ConfirmResetPasswordByEmailWithCodeOutputDto.kt b/app/src/main/java/app/cashadvisor/authorization/data/models/ConfirmResetPasswordByEmailWithCodeOutputDto.kt new file mode 100644 index 00000000..87168e8e --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/data/models/ConfirmResetPasswordByEmailWithCodeOutputDto.kt @@ -0,0 +1,8 @@ +package app.cashadvisor.authorization.data.models + + +data class ConfirmResetPasswordByEmailWithCodeOutputDto( + val message:String, + val token:Int, + val statusCode: Int +) diff --git a/app/src/main/java/app/cashadvisor/authorization/data/models/ResetPasswordInputDto.kt b/app/src/main/java/app/cashadvisor/authorization/data/models/ResetPasswordInputDto.kt new file mode 100644 index 00000000..4daf7fa8 --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/data/models/ResetPasswordInputDto.kt @@ -0,0 +1,7 @@ +package app.cashadvisor.authorization.data.models + + +data class ResetPasswordInputDto( + val code: String, + val token: String +) diff --git a/app/src/main/java/app/cashadvisor/authorization/data/models/ResetPasswordOutputDto.kt b/app/src/main/java/app/cashadvisor/authorization/data/models/ResetPasswordOutputDto.kt new file mode 100644 index 00000000..9f0e2fc2 --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/data/models/ResetPasswordOutputDto.kt @@ -0,0 +1,7 @@ +package app.cashadvisor.authorization.data.models + + +data class ResetPasswordOutputDto( + val message:String, + val statusCode: Int +) diff --git a/app/src/main/java/app/cashadvisor/authorization/data/models/SaveNewPasswordInputDto.kt b/app/src/main/java/app/cashadvisor/authorization/data/models/SaveNewPasswordInputDto.kt new file mode 100644 index 00000000..b7f2ee85 --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/data/models/SaveNewPasswordInputDto.kt @@ -0,0 +1,7 @@ +package app.cashadvisor.authorization.data.models + +data class SaveNewPasswordInputDto( + val email:String, + val password:String, + val resetToken:String +) \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/authorization/data/models/SaveNewPasswordOutputDto.kt b/app/src/main/java/app/cashadvisor/authorization/data/models/SaveNewPasswordOutputDto.kt new file mode 100644 index 00000000..58a71afb --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/data/models/SaveNewPasswordOutputDto.kt @@ -0,0 +1,6 @@ +package app.cashadvisor.authorization.data.models + +data class SaveNewPasswordOutputDto( + val message:String, + val statusCode: Int +) diff --git a/app/src/main/java/app/cashadvisor/authorization/data/models/request/ResetPasswordConfirmByEmailRequest.kt b/app/src/main/java/app/cashadvisor/authorization/data/models/request/ResetPasswordConfirmByEmailRequest.kt new file mode 100644 index 00000000..147ea114 --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/data/models/request/ResetPasswordConfirmByEmailRequest.kt @@ -0,0 +1,8 @@ +package app.cashadvisor.authorization.data.models.request + +import kotlinx.serialization.Serializable + +@Serializable +data class ResetPasswordConfirmByEmailRequest( + val email:String +) diff --git a/app/src/main/java/app/cashadvisor/authorization/data/models/request/ResetPasswordRequest.kt b/app/src/main/java/app/cashadvisor/authorization/data/models/request/ResetPasswordRequest.kt new file mode 100644 index 00000000..ca3e528c --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/data/models/request/ResetPasswordRequest.kt @@ -0,0 +1,9 @@ +package app.cashadvisor.authorization.data.models.request + +import kotlinx.serialization.Serializable + +@Serializable +data class ResetPasswordRequest( + val code: String, + val token: String +) diff --git a/app/src/main/java/app/cashadvisor/authorization/data/models/request/SaveNewPasswordRequest.kt b/app/src/main/java/app/cashadvisor/authorization/data/models/request/SaveNewPasswordRequest.kt new file mode 100644 index 00000000..23b9f25e --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/data/models/request/SaveNewPasswordRequest.kt @@ -0,0 +1,11 @@ +package app.cashadvisor.authorization.data.models.request + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class SaveNewPasswordRequest( + val email:String, + val password:String, + @SerialName("reset_token") val resetToken:String +) \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/authorization/data/models/response/ConfirmResetPasswordResponse.kt b/app/src/main/java/app/cashadvisor/authorization/data/models/response/ConfirmResetPasswordResponse.kt new file mode 100644 index 00000000..18f10a8f --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/data/models/response/ConfirmResetPasswordResponse.kt @@ -0,0 +1,11 @@ +package app.cashadvisor.authorization.data.models.response + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class ConfirmResetPasswordResponse( + val message:String, + val token:Int, + @SerialName("status_code") val statusCode: Int = 0 +) diff --git a/app/src/main/java/app/cashadvisor/authorization/data/models/response/ResetPasswordConfirmationResponse.kt b/app/src/main/java/app/cashadvisor/authorization/data/models/response/ResetPasswordConfirmationResponse.kt new file mode 100644 index 00000000..a0637298 --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/data/models/response/ResetPasswordConfirmationResponse.kt @@ -0,0 +1,10 @@ +package app.cashadvisor.authorization.data.models.response + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class ResetPasswordConfirmationResponse( + val message:String, + @SerialName("status_code") val statusCode: Int = 0 + ) diff --git a/app/src/main/java/app/cashadvisor/authorization/data/models/response/SaveNewPasswordResponse.kt b/app/src/main/java/app/cashadvisor/authorization/data/models/response/SaveNewPasswordResponse.kt new file mode 100644 index 00000000..31eba0d2 --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/data/models/response/SaveNewPasswordResponse.kt @@ -0,0 +1,11 @@ +package app.cashadvisor.authorization.data.models.response + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class SaveNewPasswordResponse( + val message:String, + @SerialName("status_code") val statusCode: Int = 0 + +) diff --git a/app/src/main/java/app/cashadvisor/common/utill/exceptions/ResetPasswordException.kt b/app/src/main/java/app/cashadvisor/common/utill/exceptions/ResetPasswordException.kt new file mode 100644 index 00000000..47fda8f2 --- /dev/null +++ b/app/src/main/java/app/cashadvisor/common/utill/exceptions/ResetPasswordException.kt @@ -0,0 +1,76 @@ +package app.cashadvisor.common.utill.exceptions + +import java.io.IOException + +sealed class ResetPasswordException( + override val message: String +) : IOException(message) { + + data class NoConnection( + override val message: String = NO_INTERNET_CONNECTION + ) : ResetPasswordException(message = message) + + data class Undefined(override val message: String = UNDEFINED_MESSAGE) : + ResetPasswordException(message = message) + + sealed class ConfirmResetPasswordByEmailWithCode( + message: String + ):ResetPasswordException(message){ + class BadRequestInvalidCodeOrMissingContentTypeHeader( + override val message: String, + val statusCode: Int + ) : ConfirmResetPasswordByEmailWithCode(message = message) + + class UnauthorizedInvalidTokenOrMissingContentTypeHeader( + override val message: String, + val remainingAttempts:Int, + val lockDuration:Int, + val statusCode: Int + ):ConfirmResetPasswordByEmailWithCode(message = message) + + class InternalServerErrorFailedToConfirmResetPassword( + override val message: String, + val statusCode: Int + ) : ConfirmResetPasswordByEmailWithCode(message = message) + + } + + sealed class ConfirmEmailToResetPassword( + message: String + ):ResetPasswordException(message){ + class BadRequestInvalidEmailOrMissingContentTypeHeader( + override val message: String, + val statusCode: Int + ) : ConfirmEmailToResetPassword(message = message) + + class InternalServerErrorFailedToGenerateTokenOrSendEmail( + override val message: String, + val statusCode: Int + ) : ConfirmEmailToResetPassword(message= message) + } + + sealed class SaveNewPassword( + message: String + ):ConfirmEmailToResetPassword(message){ + class BadRequestInvalidPasswordOrMissingContentTypeHeader( + override val message: String, + val statusCode: Int + ) : SaveNewPassword(message = message) + + class UnauthorizedInvalidTokenOrMissingContentTypeHeader( + override val message: String, + val statusCode: Int + ) : SaveNewPassword(message = message) + + class InternalServerErrorFailedToResetPassword( + override val message: String, + val statusCode: Int + ) : SaveNewPassword(message= message) + + } + + companion object { + const val NO_INTERNET_CONNECTION = "No internet connection" + const val UNDEFINED_MESSAGE = "Undefined" + } +} \ No newline at end of file From 194065a32f52cb4b2d1908b6779694383eb00c9b Mon Sep 17 00:00:00 2001 From: MajoritySky2496 Date: Tue, 2 Apr 2024 09:32:38 +0500 Subject: [PATCH 02/19] 71-Password-Recovery Made: 1. di 2. Repository 3. Interactor 4. DomainMapper 5. Data 6. State 7.ExceptionToErrorMapper --- .../authorization/data/ResetDataMapper.kt | 15 +- ...swordApi.kt => ResetPasswordApiService.kt} | 6 +- .../data/api/ResetPasswordRemoteDataSource.kt | 2 +- .../impl/ResetPasswordRemoteDataSourceImpl.kt | 53 ++++++++ .../data/impl/ResetPasswordRepositoryImpl.kt | 128 ++++++++++++++++++ ...irmResetPasswordByEmailWithCodeInputDto.kt | 3 +- ...rmResetPasswordByEmailWithCodeOutputDto.kt | 1 - .../data/models/ResetPasswordInputDto.kt | 3 +- .../data/models/ResetPasswordOutputDto.kt | 1 + ...=> ResetPasswordByEmailWithCodeRequest.kt} | 5 +- .../models/request/ResetPasswordRequest.kt | 3 +- .../ResetPasswordConfirmationResponse.kt | 1 + .../di/AuthenticationDataModule.kt | 30 ++++ .../di/AuthenticationDomainModule.kt | 7 + .../di/AuthenticationNetworkModule.kt | 9 +- .../authorization/domain/ResetDomainMapper.kt | 61 +++++++++ .../ResetPaaswordExceptionToErrorMapper.kt | 76 +++++++++++ .../domain/api/ResetPasswordInteractor.kt | 19 +++ .../domain/api/ResetPasswordRepository.kt | 27 ++++ .../impl/ResetPasswordInteractorImpl.kt | 62 +++++++++ ...ConfirmResetPasswordByEmailWithCodeData.kt | 6 + .../domain/models/ResetPasswordData.kt | 6 + .../domain/models/ResetPasswordState.kt | 10 ++ .../domain/models/SaveNewPasswordData.kt | 6 + .../PasswordRecoveryViewModel.kt | 39 ++++++ .../models/PasswordRecoveryState.kt | 14 ++ .../common/domain/model/ErrorEntity.kt | 36 +++++ .../exceptions/ResetPasswordException.kt | 2 +- 28 files changed, 610 insertions(+), 21 deletions(-) rename app/src/main/java/app/cashadvisor/authorization/data/api/{ResetPasswordApi.kt => ResetPasswordApiService.kt} (84%) create mode 100644 app/src/main/java/app/cashadvisor/authorization/data/impl/ResetPasswordRemoteDataSourceImpl.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/data/impl/ResetPasswordRepositoryImpl.kt rename app/src/main/java/app/cashadvisor/authorization/data/models/request/{ResetPasswordConfirmByEmailRequest.kt => ResetPasswordByEmailWithCodeRequest.kt} (56%) create mode 100644 app/src/main/java/app/cashadvisor/authorization/domain/ResetDomainMapper.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/domain/ResetPaaswordExceptionToErrorMapper.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/domain/api/ResetPasswordInteractor.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/domain/api/ResetPasswordRepository.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/domain/impl/ResetPasswordInteractorImpl.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/domain/models/ConfirmResetPasswordByEmailWithCodeData.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/domain/models/ResetPasswordData.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/domain/models/ResetPasswordState.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/domain/models/SaveNewPasswordData.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/PasswordRecoveryViewModel.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/models/PasswordRecoveryState.kt diff --git a/app/src/main/java/app/cashadvisor/authorization/data/ResetDataMapper.kt b/app/src/main/java/app/cashadvisor/authorization/data/ResetDataMapper.kt index eb04c1cb..d9d2cebb 100644 --- a/app/src/main/java/app/cashadvisor/authorization/data/ResetDataMapper.kt +++ b/app/src/main/java/app/cashadvisor/authorization/data/ResetDataMapper.kt @@ -1,13 +1,13 @@ package app.cashadvisor.authorization.data import app.cashadvisor.authorization.data.models.ConfirmResetPasswordByEmailWithCodeInputDto -import app.cashadvisor.authorization.data.models.ConfirmResetPasswordByEmailWithCodeOutputDto import app.cashadvisor.authorization.data.models.ResetPasswordInputDto +import app.cashadvisor.authorization.data.models.ConfirmResetPasswordByEmailWithCodeOutputDto import app.cashadvisor.authorization.data.models.ResetPasswordOutputDto import app.cashadvisor.authorization.data.models.SaveNewPasswordInputDto import app.cashadvisor.authorization.data.models.SaveNewPasswordOutputDto -import app.cashadvisor.authorization.data.models.request.ResetPasswordConfirmByEmailRequest import app.cashadvisor.authorization.data.models.request.ResetPasswordRequest +import app.cashadvisor.authorization.data.models.request.ResetPasswordByEmailWithCodeRequest import app.cashadvisor.authorization.data.models.request.SaveNewPasswordRequest import app.cashadvisor.authorization.data.models.response.ConfirmResetPasswordResponse import app.cashadvisor.authorization.data.models.response.ResetPasswordConfirmationResponse @@ -16,20 +16,20 @@ import javax.inject.Inject class ResetDataMapper @Inject constructor() { - fun toResetPasswordConfirmByEmailRequest(inputDto: ConfirmResetPasswordByEmailWithCodeInputDto): ResetPasswordConfirmByEmailRequest { - return ResetPasswordConfirmByEmailRequest( + fun toResetPasswordRequest(inputDto: ResetPasswordInputDto): ResetPasswordRequest { + return ResetPasswordRequest( email = inputDto.email + ) } fun toConfirmResetPasswordByEmailWithCodeOutputDto(response:ConfirmResetPasswordResponse): ConfirmResetPasswordByEmailWithCodeOutputDto{ return ConfirmResetPasswordByEmailWithCodeOutputDto( message = response.message, - token = response.token, statusCode = response.statusCode ) } - fun toResetPasswordRequest(inputDto:ResetPasswordInputDto):ResetPasswordRequest{ - return ResetPasswordRequest( + fun toResetPasswordByEmailWithCodeRequest(inputDto: ConfirmResetPasswordByEmailWithCodeInputDto):ResetPasswordByEmailWithCodeRequest{ + return ResetPasswordByEmailWithCodeRequest( code = inputDto.code, token = inputDto.token ) @@ -37,6 +37,7 @@ class ResetDataMapper @Inject constructor() { fun toResetPasswordOutputDto(response:ResetPasswordConfirmationResponse):ResetPasswordOutputDto{ return ResetPasswordOutputDto( message = response.message, + token = response.token, statusCode = response.statusCode ) } diff --git a/app/src/main/java/app/cashadvisor/authorization/data/api/ResetPasswordApi.kt b/app/src/main/java/app/cashadvisor/authorization/data/api/ResetPasswordApiService.kt similarity index 84% rename from app/src/main/java/app/cashadvisor/authorization/data/api/ResetPasswordApi.kt rename to app/src/main/java/app/cashadvisor/authorization/data/api/ResetPasswordApiService.kt index 3b57eb39..7b48c66a 100644 --- a/app/src/main/java/app/cashadvisor/authorization/data/api/ResetPasswordApi.kt +++ b/app/src/main/java/app/cashadvisor/authorization/data/api/ResetPasswordApiService.kt @@ -1,7 +1,7 @@ package app.cashadvisor.authorization.data.api +import app.cashadvisor.authorization.data.models.request.ResetPasswordByEmailWithCodeRequest import app.cashadvisor.authorization.data.models.request.ResetPasswordRequest -import app.cashadvisor.authorization.data.models.request.ResetPasswordConfirmByEmailRequest import app.cashadvisor.authorization.data.models.request.SaveNewPasswordRequest import app.cashadvisor.authorization.data.models.response.ConfirmResetPasswordResponse import app.cashadvisor.authorization.data.models.response.ResetPasswordConfirmationResponse @@ -10,7 +10,7 @@ import retrofit2.http.Body import retrofit2.http.Headers import retrofit2.http.POST -interface ResetPasswordApi { +interface ResetPasswordApiService { @Headers("Content-Type: application/json") @POST("/auth/login/reset/password/confirm") @@ -18,7 +18,7 @@ interface ResetPasswordApi { @Headers("Content-Type: application/json") @POST("/auth/login/reset/password/") - suspend fun resetPasswordConfirm(@Body resetPasswordConfirmByEmailRequest: ResetPasswordConfirmByEmailRequest):ConfirmResetPasswordResponse + suspend fun resetPasswordConfirm(@Body resetPasswordRequest: ResetPasswordByEmailWithCodeRequest):ConfirmResetPasswordResponse @Headers("Content-Type: application/json") @POST("/auth/login/reset/password/") diff --git a/app/src/main/java/app/cashadvisor/authorization/data/api/ResetPasswordRemoteDataSource.kt b/app/src/main/java/app/cashadvisor/authorization/data/api/ResetPasswordRemoteDataSource.kt index e561f5cf..605fc455 100644 --- a/app/src/main/java/app/cashadvisor/authorization/data/api/ResetPasswordRemoteDataSource.kt +++ b/app/src/main/java/app/cashadvisor/authorization/data/api/ResetPasswordRemoteDataSource.kt @@ -9,6 +9,6 @@ import app.cashadvisor.authorization.data.models.SaveNewPasswordOutputDto interface ResetPasswordRemoteDataSource { suspend fun resetPassword(inputDto: ResetPasswordInputDto):ResetPasswordOutputDto - suspend fun confirmResetPasswordByEmailWithCode(inputDto:ConfirmResetPasswordByEmailWithCodeInputDto):ConfirmResetPasswordByEmailWithCodeOutputDto + suspend fun confirmResetPasswordByEmailWithCode(inputDto: ConfirmResetPasswordByEmailWithCodeInputDto):ConfirmResetPasswordByEmailWithCodeOutputDto suspend fun saveNewPassword(inputDto:SaveNewPasswordInputDto):SaveNewPasswordOutputDto } \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/authorization/data/impl/ResetPasswordRemoteDataSourceImpl.kt b/app/src/main/java/app/cashadvisor/authorization/data/impl/ResetPasswordRemoteDataSourceImpl.kt new file mode 100644 index 00000000..b5074aaa --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/data/impl/ResetPasswordRemoteDataSourceImpl.kt @@ -0,0 +1,53 @@ +package app.cashadvisor.authorization.data.impl + +import app.cashadvisor.authorization.data.NetworkToResetPasswordExceptionMapper +import app.cashadvisor.authorization.data.ResetDataMapper +import app.cashadvisor.authorization.data.api.ResetPasswordApiService +import app.cashadvisor.authorization.data.api.ResetPasswordRemoteDataSource +import app.cashadvisor.authorization.data.models.ConfirmResetPasswordByEmailWithCodeInputDto +import app.cashadvisor.authorization.data.models.ResetPasswordInputDto +import app.cashadvisor.authorization.data.models.ConfirmResetPasswordByEmailWithCodeOutputDto +import app.cashadvisor.authorization.data.models.ResetPasswordOutputDto +import app.cashadvisor.authorization.data.models.SaveNewPasswordInputDto +import app.cashadvisor.authorization.data.models.SaveNewPasswordOutputDto +import app.cashadvisor.common.utill.exceptions.NetworkException +import javax.inject.Inject + +class ResetPasswordRemoteDataSourceImpl @Inject constructor( + private val resetDataMapper: ResetDataMapper, + private val resetPasswordApiService: ResetPasswordApiService, + private val networkToResetPasswordExceptionMapper: NetworkToResetPasswordExceptionMapper):ResetPasswordRemoteDataSource { + + override suspend fun resetPassword(inputDto: ResetPasswordInputDto): ResetPasswordOutputDto { + return try { + val response = resetPasswordApiService.resetPassword( + passworResetRequest = resetDataMapper.toResetPasswordRequest(inputDto) + ) + resetDataMapper.toResetPasswordOutputDto(response) + }catch (exception: NetworkException){ + throw networkToResetPasswordExceptionMapper.handleConfirmEmailToResetPassword(exception) + } + } + + override suspend fun confirmResetPasswordByEmailWithCode(inputDto: ConfirmResetPasswordByEmailWithCodeInputDto): ConfirmResetPasswordByEmailWithCodeOutputDto { + return try { + val response = resetPasswordApiService.resetPasswordConfirm( + resetPasswordRequest = resetDataMapper.toResetPasswordByEmailWithCodeRequest(inputDto) + ) + resetDataMapper.toConfirmResetPasswordByEmailWithCodeOutputDto(response) + }catch (exception: NetworkException){ + throw networkToResetPasswordExceptionMapper.handleConfirmResetPasswordByEmailWithCode(exception) + } + } + + override suspend fun saveNewPassword(inputDto: SaveNewPasswordInputDto): SaveNewPasswordOutputDto { + return try { + val response = resetPasswordApiService.saveNewPassword( + saveNewPasswordRequest = resetDataMapper.toSaveNewPasswordRequest(inputDto) + ) + resetDataMapper.toSaveNewPasswordOutputDto(response) + }catch (exception: NetworkException){ + throw networkToResetPasswordExceptionMapper.handleSaveNewPassword(exception) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/authorization/data/impl/ResetPasswordRepositoryImpl.kt b/app/src/main/java/app/cashadvisor/authorization/data/impl/ResetPasswordRepositoryImpl.kt new file mode 100644 index 00000000..4c5b5cc7 --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/data/impl/ResetPasswordRepositoryImpl.kt @@ -0,0 +1,128 @@ +package app.cashadvisor.authorization.data.impl + +import app.cashadvisor.authorization.data.api.ResetPasswordRemoteDataSource +import app.cashadvisor.authorization.di.ResetPasswordExceptionMapper +import app.cashadvisor.authorization.domain.ResetDomainMapper +import app.cashadvisor.authorization.domain.api.ResetPasswordRepository +import app.cashadvisor.authorization.domain.models.ConfirmCode +import app.cashadvisor.authorization.domain.models.ConfirmResetPasswordByEmailWithCodeData +import app.cashadvisor.authorization.domain.models.Email +import app.cashadvisor.authorization.domain.models.Password +import app.cashadvisor.authorization.domain.models.ResetPasswordData +import app.cashadvisor.authorization.domain.models.ResetPasswordState +import app.cashadvisor.authorization.domain.models.SaveNewPasswordData +import app.cashadvisor.common.domain.BaseExceptionToErrorMapper +import app.cashadvisor.common.domain.Resource +import app.cashadvisor.common.domain.model.ErrorEntity +import javax.inject.Inject +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.update + +class ResetPasswordRepositoryImpl @Inject constructor( + private val resetPasswordRemoteDataSource: ResetPasswordRemoteDataSource, + @ResetPasswordExceptionMapper private val exceptionToErrorMapper: BaseExceptionToErrorMapper, + private val resetDomainMapper: ResetDomainMapper + +):ResetPasswordRepository { + private val _state: MutableStateFlow = MutableStateFlow(ResetPasswordState()) + private val state = _state.asStateFlow() + private val currentState: ResetPasswordState + get() = state.replayCache.firstOrNull() ?: ResetPasswordState(ResetPasswordState.State.Initial) + + override suspend fun confirmEmailForPasswordReset(email: Email): Resource { + return try { + val data = resetPasswordRemoteDataSource.resetPassword( + inputDto = resetDomainMapper.toResetPasswordInputDto(email)) + + _state.update { + it.copy(state = ResetPasswordState.State.InProcess(codeToken = data.token)) + } + Resource.Success( + data = resetDomainMapper.toResetPasswordData(data) + ) + }catch (exception: Exception){ + _state.update { it.copy(state = ResetPasswordState.State.Initial) } + Resource.Error( + exceptionToErrorMapper.handleException(exception) + ) + } + } + + override suspend fun resetPasswordConfirmWithCode(code: ConfirmCode): Resource { + return try { + val token:String + when(val state = currentState.state){ + is ResetPasswordState.State.InProcess -> { + token = state.codeToken + } + else -> { + return Resource.Error( + ErrorEntity.ConfirmResetPasswordByEmailWithCode.InvalidInput( + WRONG_STATE_ERROR + ) + ) + } + } + val data = resetPasswordRemoteDataSource.confirmResetPasswordByEmailWithCode( + resetDomainMapper.toConfirmResetPasswordByEmailWithCodeInputDto( + code, + token + ) + ) + + Resource.Success( + data = resetDomainMapper.toConfirmResetPasswordByEmailWithCodeData(data) + ) + }catch (exception: Exception){ + Resource.Error( + exceptionToErrorMapper.handleException(exception) + ) + } + } + + override suspend fun saveNewPassword( + email: Email, + password: Password + ): Resource { + return try { + val token:String + when(val state = currentState.state){ + is ResetPasswordState.State.InProcess -> { + token = state.codeToken + } + else -> { + return Resource.Error( + ErrorEntity.ConfirmResetPasswordByEmailWithCode.InvalidInput( + WRONG_STATE_ERROR + ) + ) + } + } + val data = resetPasswordRemoteDataSource.saveNewPassword(resetDomainMapper.toSaveNewPasswordInputDto( + email, + password, + token + ) + ) + _state.update { it.copy(state = ResetPasswordState.State.Initial) } + Resource.Success( + data = resetDomainMapper.toSaveNewPasswordData(data) + ) + }catch (exception:Exception){ + Resource.Error( + exceptionToErrorMapper.handleException(exception) + ) + } + } + + override fun isLoginInProgress(): Flow { + return state.map { it.state is ResetPasswordState.State.InProcess } + } + + companion object { + const val WRONG_STATE_ERROR = "ResetPassword is not in progress" + } +} \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/authorization/data/models/ConfirmResetPasswordByEmailWithCodeInputDto.kt b/app/src/main/java/app/cashadvisor/authorization/data/models/ConfirmResetPasswordByEmailWithCodeInputDto.kt index b870e8e8..44561d33 100644 --- a/app/src/main/java/app/cashadvisor/authorization/data/models/ConfirmResetPasswordByEmailWithCodeInputDto.kt +++ b/app/src/main/java/app/cashadvisor/authorization/data/models/ConfirmResetPasswordByEmailWithCodeInputDto.kt @@ -1,5 +1,6 @@ package app.cashadvisor.authorization.data.models data class ConfirmResetPasswordByEmailWithCodeInputDto( - val email:String + val code:String, + val token:String ) diff --git a/app/src/main/java/app/cashadvisor/authorization/data/models/ConfirmResetPasswordByEmailWithCodeOutputDto.kt b/app/src/main/java/app/cashadvisor/authorization/data/models/ConfirmResetPasswordByEmailWithCodeOutputDto.kt index 87168e8e..04a2027e 100644 --- a/app/src/main/java/app/cashadvisor/authorization/data/models/ConfirmResetPasswordByEmailWithCodeOutputDto.kt +++ b/app/src/main/java/app/cashadvisor/authorization/data/models/ConfirmResetPasswordByEmailWithCodeOutputDto.kt @@ -3,6 +3,5 @@ package app.cashadvisor.authorization.data.models data class ConfirmResetPasswordByEmailWithCodeOutputDto( val message:String, - val token:Int, val statusCode: Int ) diff --git a/app/src/main/java/app/cashadvisor/authorization/data/models/ResetPasswordInputDto.kt b/app/src/main/java/app/cashadvisor/authorization/data/models/ResetPasswordInputDto.kt index 4daf7fa8..f90d8e6f 100644 --- a/app/src/main/java/app/cashadvisor/authorization/data/models/ResetPasswordInputDto.kt +++ b/app/src/main/java/app/cashadvisor/authorization/data/models/ResetPasswordInputDto.kt @@ -2,6 +2,5 @@ package app.cashadvisor.authorization.data.models data class ResetPasswordInputDto( - val code: String, - val token: String + val email:String ) diff --git a/app/src/main/java/app/cashadvisor/authorization/data/models/ResetPasswordOutputDto.kt b/app/src/main/java/app/cashadvisor/authorization/data/models/ResetPasswordOutputDto.kt index 9f0e2fc2..0b16c695 100644 --- a/app/src/main/java/app/cashadvisor/authorization/data/models/ResetPasswordOutputDto.kt +++ b/app/src/main/java/app/cashadvisor/authorization/data/models/ResetPasswordOutputDto.kt @@ -3,5 +3,6 @@ package app.cashadvisor.authorization.data.models data class ResetPasswordOutputDto( val message:String, + val token:String, val statusCode: Int ) diff --git a/app/src/main/java/app/cashadvisor/authorization/data/models/request/ResetPasswordConfirmByEmailRequest.kt b/app/src/main/java/app/cashadvisor/authorization/data/models/request/ResetPasswordByEmailWithCodeRequest.kt similarity index 56% rename from app/src/main/java/app/cashadvisor/authorization/data/models/request/ResetPasswordConfirmByEmailRequest.kt rename to app/src/main/java/app/cashadvisor/authorization/data/models/request/ResetPasswordByEmailWithCodeRequest.kt index 147ea114..73b0dc4d 100644 --- a/app/src/main/java/app/cashadvisor/authorization/data/models/request/ResetPasswordConfirmByEmailRequest.kt +++ b/app/src/main/java/app/cashadvisor/authorization/data/models/request/ResetPasswordByEmailWithCodeRequest.kt @@ -3,6 +3,7 @@ package app.cashadvisor.authorization.data.models.request import kotlinx.serialization.Serializable @Serializable -data class ResetPasswordConfirmByEmailRequest( - val email:String +data class ResetPasswordByEmailWithCodeRequest( + val code: String, + val token: String ) diff --git a/app/src/main/java/app/cashadvisor/authorization/data/models/request/ResetPasswordRequest.kt b/app/src/main/java/app/cashadvisor/authorization/data/models/request/ResetPasswordRequest.kt index ca3e528c..6ef19ca1 100644 --- a/app/src/main/java/app/cashadvisor/authorization/data/models/request/ResetPasswordRequest.kt +++ b/app/src/main/java/app/cashadvisor/authorization/data/models/request/ResetPasswordRequest.kt @@ -4,6 +4,5 @@ import kotlinx.serialization.Serializable @Serializable data class ResetPasswordRequest( - val code: String, - val token: String + val email:String ) diff --git a/app/src/main/java/app/cashadvisor/authorization/data/models/response/ResetPasswordConfirmationResponse.kt b/app/src/main/java/app/cashadvisor/authorization/data/models/response/ResetPasswordConfirmationResponse.kt index a0637298..2c1ed6b5 100644 --- a/app/src/main/java/app/cashadvisor/authorization/data/models/response/ResetPasswordConfirmationResponse.kt +++ b/app/src/main/java/app/cashadvisor/authorization/data/models/response/ResetPasswordConfirmationResponse.kt @@ -6,5 +6,6 @@ import kotlinx.serialization.Serializable @Serializable data class ResetPasswordConfirmationResponse( val message:String, + val token:String, @SerialName("status_code") val statusCode: Int = 0 ) diff --git a/app/src/main/java/app/cashadvisor/authorization/di/AuthenticationDataModule.kt b/app/src/main/java/app/cashadvisor/authorization/di/AuthenticationDataModule.kt index 3353be28..41e9a2ed 100644 --- a/app/src/main/java/app/cashadvisor/authorization/di/AuthenticationDataModule.kt +++ b/app/src/main/java/app/cashadvisor/authorization/di/AuthenticationDataModule.kt @@ -2,14 +2,19 @@ package app.cashadvisor.authorization.di import app.cashadvisor.authorization.data.api.LoginRemoteDataSource import app.cashadvisor.authorization.data.api.RegisterRemoteDataSource +import app.cashadvisor.authorization.data.api.ResetPasswordRemoteDataSource import app.cashadvisor.authorization.data.impl.LoginRemoteDataSourceImpl import app.cashadvisor.authorization.data.impl.LoginRepositoryImpl import app.cashadvisor.authorization.data.impl.RegisterRemoteDataSourceImpl import app.cashadvisor.authorization.data.impl.RegisterRepositoryImpl +import app.cashadvisor.authorization.data.impl.ResetPasswordRemoteDataSourceImpl +import app.cashadvisor.authorization.data.impl.ResetPasswordRepositoryImpl import app.cashadvisor.authorization.domain.LoginExceptionToErrorMapper import app.cashadvisor.authorization.domain.RegisterExceptionToErrorMapper +import app.cashadvisor.authorization.domain.ResetPasswordExceptionToErrorMapper import app.cashadvisor.authorization.domain.api.LoginRepository import app.cashadvisor.authorization.domain.api.RegisterRepository +import app.cashadvisor.authorization.domain.api.ResetPasswordRepository import app.cashadvisor.common.domain.BaseExceptionToErrorMapper import dagger.Binds import dagger.Module @@ -26,6 +31,10 @@ annotation class RegisterExceptionMapper @Retention(AnnotationRetention.BINARY) annotation class LoginExceptionMapper +@Qualifier +@Retention(AnnotationRetention.BINARY) +annotation class ResetPasswordExceptionMapper + @Module @InstallIn(SingletonComponent::class) interface LoginAndRegisterDataModule { @@ -66,4 +75,25 @@ interface LoginAndRegisterDataModule { impl: LoginExceptionToErrorMapper ): BaseExceptionToErrorMapper +} +@Module +@InstallIn(SingletonComponent::class) +interface ResetPasswordDataModule{ + @Singleton + @Binds + fun bindResetPasswordDataSource( + impl: ResetPasswordRemoteDataSourceImpl + ):ResetPasswordRemoteDataSource + + @Singleton + @Binds + fun bindResetPasswordRepository( + impl:ResetPasswordRepositoryImpl + ):ResetPasswordRepository + + @ResetPasswordExceptionMapper + @Binds + fun bindResetPasswordExceptionToErrorMapper( + impl:ResetPasswordExceptionToErrorMapper + ):BaseExceptionToErrorMapper } \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/authorization/di/AuthenticationDomainModule.kt b/app/src/main/java/app/cashadvisor/authorization/di/AuthenticationDomainModule.kt index fbdd845c..f1264610 100644 --- a/app/src/main/java/app/cashadvisor/authorization/di/AuthenticationDomainModule.kt +++ b/app/src/main/java/app/cashadvisor/authorization/di/AuthenticationDomainModule.kt @@ -3,9 +3,11 @@ package app.cashadvisor.authorization.di import app.cashadvisor.authorization.domain.api.InputValidationInteractor import app.cashadvisor.authorization.domain.api.LoginInteractor import app.cashadvisor.authorization.domain.api.RegisterInteractor +import app.cashadvisor.authorization.domain.api.ResetPasswordInteractor import app.cashadvisor.authorization.domain.impl.InputValidationInteractorImpl import app.cashadvisor.authorization.domain.impl.LoginInteractorImpl import app.cashadvisor.authorization.domain.impl.RegisterInteractorImpl +import app.cashadvisor.authorization.domain.impl.ResetPasswordInteractorImpl import dagger.Binds import dagger.Module import dagger.hilt.InstallIn @@ -30,4 +32,9 @@ interface AuthenticationDomainModule { impl: InputValidationInteractorImpl ): InputValidationInteractor + @Binds + fun bindResetPasswordInteractor( + impl: ResetPasswordInteractorImpl + ):ResetPasswordInteractor + } \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/authorization/di/AuthenticationNetworkModule.kt b/app/src/main/java/app/cashadvisor/authorization/di/AuthenticationNetworkModule.kt index 3d5c4f73..df46d0b5 100644 --- a/app/src/main/java/app/cashadvisor/authorization/di/AuthenticationNetworkModule.kt +++ b/app/src/main/java/app/cashadvisor/authorization/di/AuthenticationNetworkModule.kt @@ -2,12 +2,13 @@ package app.cashadvisor.authorization.di import app.cashadvisor.authorization.data.api.LoginApiService import app.cashadvisor.authorization.data.api.RegisterApiService +import app.cashadvisor.authorization.data.api.ResetPasswordApiService import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent -import retrofit2.Retrofit import javax.inject.Singleton +import retrofit2.Retrofit @Module @@ -24,4 +25,10 @@ class AuthenticationNetworkModule { fun provideLoginApiService(retrofit: Retrofit): LoginApiService { return retrofit.create(LoginApiService::class.java) } + + @Provides + @Singleton + fun provideResetPasswordApiService(retrofit: Retrofit):ResetPasswordApiService{ + return retrofit.create(ResetPasswordApiService::class.java) + } } \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/authorization/domain/ResetDomainMapper.kt b/app/src/main/java/app/cashadvisor/authorization/domain/ResetDomainMapper.kt new file mode 100644 index 00000000..9bce54b2 --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/domain/ResetDomainMapper.kt @@ -0,0 +1,61 @@ +package app.cashadvisor.authorization.domain + +import app.cashadvisor.authorization.data.models.ConfirmResetPasswordByEmailWithCodeInputDto +import app.cashadvisor.authorization.data.models.ResetPasswordInputDto +import app.cashadvisor.authorization.data.models.ConfirmResetPasswordByEmailWithCodeOutputDto +import app.cashadvisor.authorization.data.models.ResetPasswordOutputDto +import app.cashadvisor.authorization.data.models.SaveNewPasswordInputDto +import app.cashadvisor.authorization.data.models.SaveNewPasswordOutputDto +import app.cashadvisor.authorization.domain.models.ConfirmCode +import app.cashadvisor.authorization.domain.models.ConfirmResetPasswordByEmailWithCodeData +import app.cashadvisor.authorization.domain.models.Email +import app.cashadvisor.authorization.domain.models.Password +import app.cashadvisor.authorization.domain.models.ResetPasswordData +import app.cashadvisor.authorization.domain.models.SaveNewPasswordData +import javax.inject.Inject + +class ResetDomainMapper @Inject constructor() { + + fun toResetPasswordInputDto(email: Email): ResetPasswordInputDto { + return ResetPasswordInputDto( + email = email.value + ) + } + + fun toConfirmResetPasswordByEmailWithCodeInputDto(code: ConfirmCode, token: String): ConfirmResetPasswordByEmailWithCodeInputDto { + return ConfirmResetPasswordByEmailWithCodeInputDto( + code = code.value, + token = token + ) + } + + fun toSaveNewPasswordInputDto( + email: Email, + password: Password, + resetToken: String + ): SaveNewPasswordInputDto { + return SaveNewPasswordInputDto( + email = email.value, + password = password.value, + resetToken = resetToken + ) + } + fun toConfirmResetPasswordByEmailWithCodeData(data:ConfirmResetPasswordByEmailWithCodeOutputDto):ConfirmResetPasswordByEmailWithCodeData{ + return ConfirmResetPasswordByEmailWithCodeData( + message = data.message, + statusCode = data.statusCode + ) + } + fun toResetPasswordData(data:ResetPasswordOutputDto):ResetPasswordData{ + return ResetPasswordData( + message = data.message, + statusCode = data.statusCode + ) + } + fun toSaveNewPasswordData(data:SaveNewPasswordOutputDto):SaveNewPasswordData{ + return SaveNewPasswordData( + message = data.message, + statusCode = data.statusCode + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/authorization/domain/ResetPaaswordExceptionToErrorMapper.kt b/app/src/main/java/app/cashadvisor/authorization/domain/ResetPaaswordExceptionToErrorMapper.kt new file mode 100644 index 00000000..89d7c3e8 --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/domain/ResetPaaswordExceptionToErrorMapper.kt @@ -0,0 +1,76 @@ +package app.cashadvisor.authorization.domain + +import app.cashadvisor.common.domain.BaseExceptionToErrorMapper +import app.cashadvisor.common.domain.model.ErrorEntity +import app.cashadvisor.common.utill.exceptions.ResetPasswordException +import javax.inject.Inject + +class ResetPasswordExceptionToErrorMapper @Inject constructor():BaseExceptionToErrorMapper() { + override fun handleSpecificException(exception: Exception): ErrorEntity { + return when (exception){ + is ResetPasswordException.ConfirmEmailToResetPassword ->handleConfirmEmailToResetPasswordException(exception) + is ResetPasswordException.SaveNewPassword -> handleSaveNewPasswordException(exception) + is ResetPasswordException.ConfirmResetPasswordByEmailWithCode -> handleConfirmResetPasswordByEmailWithCode(exception) + else -> handleUnknownError(exception) + } + } + private fun handleConfirmEmailToResetPasswordException(exception: ResetPasswordException.ConfirmEmailToResetPassword):ErrorEntity{ + return when(exception){ + is ResetPasswordException.ConfirmEmailToResetPassword.BadRequestInvalidEmailOrMissingContentTypeHeader -> { + ErrorEntity.ConfirmEmailToResetPassword.InvalidInput( + exception.message + ) + } + is ResetPasswordException.ConfirmEmailToResetPassword.InternalServerErrorFailedToGenerateTokenOrSendEmail ->{ + ErrorEntity.ConfirmEmailToResetPassword.FailedToGenerateTokenOrSendEmail( + exception.message + ) + } + } + } + private fun handleSaveNewPasswordException(exception: ResetPasswordException.SaveNewPassword):ErrorEntity{ + return when(exception){ + is ResetPasswordException.SaveNewPassword.BadRequestInvalidPasswordOrMissingContentTypeHeader -> { + ErrorEntity.SaveNewPassword.InvalidInput( + exception.message + ) + } + is ResetPasswordException.SaveNewPassword.UnauthorizedInvalidTokenOrMissingContentTypeHeader -> { + ErrorEntity.SaveNewPassword.InvalidToken( + exception.message + ) + } + is ResetPasswordException.SaveNewPassword.InternalServerErrorFailedToResetPassword -> { + ErrorEntity.SaveNewPassword.FailedToResetPassword( + exception.message + ) + } + } + + } + private fun handleConfirmResetPasswordByEmailWithCode(exception: ResetPasswordException.ConfirmResetPasswordByEmailWithCode):ErrorEntity{ + return when(exception){ + is ResetPasswordException.ConfirmResetPasswordByEmailWithCode.BadRequestInvalidCodeOrMissingContentTypeHeader -> { + ErrorEntity.ConfirmResetPasswordByEmailWithCode.InvalidInput( + exception.message + ) + } + is ResetPasswordException.ConfirmResetPasswordByEmailWithCode.UnauthorizedInvalidTokenOrMissingContentTypeHeader -> { + ErrorEntity.ConfirmResetPasswordByEmailWithCode.WrongConfirmationCode( + exception.message, + exception.remainingAttempts, + exception.lockDuration + ) + } + is ResetPasswordException.ConfirmResetPasswordByEmailWithCode.InternalServerErrorFailedToConfirmResetPassword -> { + ErrorEntity.ConfirmResetPasswordByEmailWithCode.FailedToConfirmPasswordReset( + exception.message + ) + } + + } + + } + + +} \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/authorization/domain/api/ResetPasswordInteractor.kt b/app/src/main/java/app/cashadvisor/authorization/domain/api/ResetPasswordInteractor.kt new file mode 100644 index 00000000..0a1e12c6 --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/domain/api/ResetPasswordInteractor.kt @@ -0,0 +1,19 @@ +package app.cashadvisor.authorization.domain.api + +import app.cashadvisor.authorization.domain.models.ConfirmCode +import app.cashadvisor.authorization.domain.models.Email +import app.cashadvisor.authorization.domain.models.Password +import app.cashadvisor.authorization.domain.models.ResetPasswordData +import app.cashadvisor.authorization.domain.models.SaveNewPasswordData +import app.cashadvisor.common.domain.Resource +import kotlinx.coroutines.flow.Flow + +interface ResetPasswordInteractor { + suspend fun confirmEmailForPasswordReset(email: Email): Resource + + suspend fun resetPasswordConfirmWithCode(code: ConfirmCode): Resource + + suspend fun saveNewPassword(email: Email, password: Password): Resource + + fun isResetPasswordInProgress(): Flow +} \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/authorization/domain/api/ResetPasswordRepository.kt b/app/src/main/java/app/cashadvisor/authorization/domain/api/ResetPasswordRepository.kt new file mode 100644 index 00000000..d2d7adbe --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/domain/api/ResetPasswordRepository.kt @@ -0,0 +1,27 @@ +package app.cashadvisor.authorization.domain.api + +import app.cashadvisor.authorization.domain.models.ConfirmCode +import app.cashadvisor.authorization.domain.models.ConfirmResetPasswordByEmailWithCodeData +import app.cashadvisor.authorization.domain.models.Email +import app.cashadvisor.authorization.domain.models.Password +import app.cashadvisor.authorization.domain.models.ResetPasswordData +import app.cashadvisor.authorization.domain.models.SaveNewPasswordData +import app.cashadvisor.common.domain.Resource +import kotlinx.coroutines.flow.Flow + +interface ResetPasswordRepository { + suspend fun confirmEmailForPasswordReset( + email:Email + ):Resource + + suspend fun resetPasswordConfirmWithCode( + code: ConfirmCode, + ):Resource + + suspend fun saveNewPassword( + email: Email, + password:Password, + ):Resource + + fun isLoginInProgress(): Flow +} \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/authorization/domain/impl/ResetPasswordInteractorImpl.kt b/app/src/main/java/app/cashadvisor/authorization/domain/impl/ResetPasswordInteractorImpl.kt new file mode 100644 index 00000000..f7276ac0 --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/domain/impl/ResetPasswordInteractorImpl.kt @@ -0,0 +1,62 @@ +package app.cashadvisor.authorization.domain.impl + +import app.cashadvisor.authorization.domain.api.CredentialsRepository +import app.cashadvisor.authorization.domain.api.ResetPasswordInteractor +import app.cashadvisor.authorization.domain.api.ResetPasswordRepository +import app.cashadvisor.authorization.domain.models.ConfirmCode +import app.cashadvisor.authorization.domain.models.Email +import app.cashadvisor.authorization.domain.models.Password +import app.cashadvisor.authorization.domain.models.ResetPasswordData +import app.cashadvisor.authorization.domain.models.SaveNewPasswordData +import app.cashadvisor.common.domain.Resource +import javax.inject.Inject +import kotlinx.coroutines.flow.Flow + +class ResetPasswordInteractorImpl @Inject constructor( + private val resetPasswordRepository: ResetPasswordRepository, + private val credentialsRepository: CredentialsRepository +):ResetPasswordInteractor { + override suspend fun confirmEmailForPasswordReset(email: Email): Resource { + val result = resetPasswordRepository.confirmEmailForPasswordReset(email) + return when(result){ + is Resource.Success -> { + Resource.Success(data = result.data) + } + is Resource.Error -> { + Resource.Error(error = result.error) + } + } + } + + override suspend fun resetPasswordConfirmWithCode(code: ConfirmCode): Resource { + val result = resetPasswordRepository.resetPasswordConfirmWithCode(code) + return when(result){ + is Resource.Success -> { + Resource.Success(data = result.data.message) + } + is Resource.Error -> { + Resource.Error(error = result.error) + } + } + + } + + override suspend fun saveNewPassword( + email: Email, + password: Password + ): Resource { + val result = resetPasswordRepository.saveNewPassword(email, password) + return when(result){ + is Resource.Success -> { + Resource.Success(data = result.data) + } + is Resource.Error -> { + Resource.Error(error = result.error) + } + } + } + + override fun isResetPasswordInProgress(): Flow { + return resetPasswordRepository.isLoginInProgress() + } +} \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/authorization/domain/models/ConfirmResetPasswordByEmailWithCodeData.kt b/app/src/main/java/app/cashadvisor/authorization/domain/models/ConfirmResetPasswordByEmailWithCodeData.kt new file mode 100644 index 00000000..9a947c2b --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/domain/models/ConfirmResetPasswordByEmailWithCodeData.kt @@ -0,0 +1,6 @@ +package app.cashadvisor.authorization.domain.models + +data class ConfirmResetPasswordByEmailWithCodeData( + val message:String, + val statusCode: Int +) diff --git a/app/src/main/java/app/cashadvisor/authorization/domain/models/ResetPasswordData.kt b/app/src/main/java/app/cashadvisor/authorization/domain/models/ResetPasswordData.kt new file mode 100644 index 00000000..824194bd --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/domain/models/ResetPasswordData.kt @@ -0,0 +1,6 @@ +package app.cashadvisor.authorization.domain.models + +data class ResetPasswordData( + val message:String, + val statusCode: Int +) diff --git a/app/src/main/java/app/cashadvisor/authorization/domain/models/ResetPasswordState.kt b/app/src/main/java/app/cashadvisor/authorization/domain/models/ResetPasswordState.kt new file mode 100644 index 00000000..4100def2 --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/domain/models/ResetPasswordState.kt @@ -0,0 +1,10 @@ +package app.cashadvisor.authorization.domain.models + +data class ResetPasswordState( + val state: ResetPasswordState.State = ResetPasswordState.State.Initial +){ + sealed interface State { + data object Initial : State + data class InProcess(val codeToken: String) : State + } +} diff --git a/app/src/main/java/app/cashadvisor/authorization/domain/models/SaveNewPasswordData.kt b/app/src/main/java/app/cashadvisor/authorization/domain/models/SaveNewPasswordData.kt new file mode 100644 index 00000000..103b0b50 --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/domain/models/SaveNewPasswordData.kt @@ -0,0 +1,6 @@ +package app.cashadvisor.authorization.domain.models + +data class SaveNewPasswordData( + val message:String, + val statusCode: Int +) diff --git a/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/PasswordRecoveryViewModel.kt b/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/PasswordRecoveryViewModel.kt new file mode 100644 index 00000000..d482c974 --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/PasswordRecoveryViewModel.kt @@ -0,0 +1,39 @@ +package app.cashadvisor.authorization.presentation.viewmodel.passwordrecovery + +import app.cashadvisor.authorization.domain.api.InputValidationInteractor +import app.cashadvisor.authorization.domain.api.LoginInteractor +import app.cashadvisor.authorization.presentation.viewmodel.passwordrecovery.models.PasswordRecoveryState +import app.cashadvisor.common.ui.BaseViewModel +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow + +@HiltViewModel +class PasswordRecoveryViewModel @Inject constructor( + private val loginInteractor: LoginInteractor, + private val inputValidationInteractor: InputValidationInteractor +) : BaseViewModel() { + + private val _state: MutableStateFlow = MutableStateFlow( + PasswordRecoveryState() + ) + private val state: StateFlow = _state.asStateFlow() + private val currentState get() = state.replayCache.firstOrNull() ?: PasswordRecoveryState() + + + private fun setEmail(email: String) { + + } + private fun setPassword(password :String){ + + } + + private fun sendEmailConfirmCode() { + + } + private fun setEmailConfirmCode(){ + + } +} \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/models/PasswordRecoveryState.kt b/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/models/PasswordRecoveryState.kt new file mode 100644 index 00000000..390503e2 --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/models/PasswordRecoveryState.kt @@ -0,0 +1,14 @@ +package app.cashadvisor.authorization.presentation.viewmodel.passwordrecovery.models + +import app.cashadvisor.authorization.domain.models.ConfirmCode +import app.cashadvisor.authorization.domain.models.Email +import app.cashadvisor.authorization.domain.models.Password + +data class PasswordRecoveryState( + val email: Email = Email(""), + val emailCode: ConfirmCode = ConfirmCode(""), + val password: Password = Password("password"), + val recoveryCode: ConfirmCode = ConfirmCode(""), + val isEmailValid: Boolean = false, + val isEmailCodeValid: Boolean = false, +) diff --git a/app/src/main/java/app/cashadvisor/common/domain/model/ErrorEntity.kt b/app/src/main/java/app/cashadvisor/common/domain/model/ErrorEntity.kt index c1230224..0e3f9556 100644 --- a/app/src/main/java/app/cashadvisor/common/domain/model/ErrorEntity.kt +++ b/app/src/main/java/app/cashadvisor/common/domain/model/ErrorEntity.kt @@ -50,6 +50,42 @@ sealed class ErrorEntity(open val message: String) { RegisterConfirmationWithCode(message) } + sealed class ConfirmEmailToResetPassword(override val message: String) : + ErrorEntity(message) { + data class InvalidInput(override val message: String) : ConfirmEmailToResetPassword(message) + data class FailedToGenerateTokenOrSendEmail(override val message: String) : + ConfirmEmailToResetPassword(message) + + } + + sealed class ConfirmResetPasswordByEmailWithCode(override val message: String) : + ErrorEntity(message) { + data class InvalidInput(override val message: String) : + ConfirmResetPasswordByEmailWithCode(message) + + data class WrongConfirmationCode( + override val message: String, + val remainingAttempts:Int, + val lockDuration:Int + ) : ConfirmResetPasswordByEmailWithCode(message) + + data class FailedToConfirmPasswordReset(override val message: String) : + ConfirmResetPasswordByEmailWithCode(message) + } + + sealed class SaveNewPassword(override val message: String) : ErrorEntity(message) { + + data class InvalidInput(override val message: String) : + SaveNewPassword(message) + + data class InvalidToken(override val message: String) : + SaveNewPassword(message) + + data class FailedToResetPassword(override val message: String) : + SaveNewPassword(message) + } + + companion object { const val BLANC_ERROR = "" } diff --git a/app/src/main/java/app/cashadvisor/common/utill/exceptions/ResetPasswordException.kt b/app/src/main/java/app/cashadvisor/common/utill/exceptions/ResetPasswordException.kt index 47fda8f2..bac2fe07 100644 --- a/app/src/main/java/app/cashadvisor/common/utill/exceptions/ResetPasswordException.kt +++ b/app/src/main/java/app/cashadvisor/common/utill/exceptions/ResetPasswordException.kt @@ -51,7 +51,7 @@ sealed class ResetPasswordException( sealed class SaveNewPassword( message: String - ):ConfirmEmailToResetPassword(message){ + ):ResetPasswordException(message){ class BadRequestInvalidPasswordOrMissingContentTypeHeader( override val message: String, val statusCode: Int From 50ff55dba3fd79e71b5045aa746c8c6e2e996d0c Mon Sep 17 00:00:00 2001 From: MajoritySky2496 Date: Sun, 7 Apr 2024 17:05:44 +0500 Subject: [PATCH 03/19] 71-Password-Recovery Made: 1. PasswordRecoveryViewModel 2. State --- .../ui/PasswordRecoveryFragment.kt | 37 +-- .../PasswordRecoveryViewModel.kt | 220 +++++++++++++++++- .../RecoveryPasswordScreenEvent.kt | 10 + .../passwordrecovery/RecoverySideEffect.kt | 5 + .../models/PasswordRecoveryState.kt | 2 + .../models/PasswordRecoveryUiState.kt | 8 + 6 files changed, 248 insertions(+), 34 deletions(-) create mode 100644 app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/RecoveryPasswordScreenEvent.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/RecoverySideEffect.kt create mode 100644 app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/models/PasswordRecoveryUiState.kt diff --git a/app/src/main/java/app/cashadvisor/authorization/presentation/ui/PasswordRecoveryFragment.kt b/app/src/main/java/app/cashadvisor/authorization/presentation/ui/PasswordRecoveryFragment.kt index 6631c9d1..b5754a72 100644 --- a/app/src/main/java/app/cashadvisor/authorization/presentation/ui/PasswordRecoveryFragment.kt +++ b/app/src/main/java/app/cashadvisor/authorization/presentation/ui/PasswordRecoveryFragment.kt @@ -5,41 +5,22 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels import androidx.navigation.fragment.findNavController import app.cashadvisor.R +import app.cashadvisor.authorization.presentation.viewmodel.passwordrecovery.PasswordRecoveryViewModel +import app.cashadvisor.common.ui.BaseFragment import app.cashadvisor.databinding.FragmentPasswordRecoveryBinding -class PasswordRecoveryFragment : Fragment() { - - private var _binding: FragmentPasswordRecoveryBinding? = null - private val binding get() = _binding!! - - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - arguments?.let { - - } +class PasswordRecoveryFragment() : BaseFragment(FragmentPasswordRecoveryBinding::inflate) { + override val viewModel: PasswordRecoveryViewModel by viewModels() + override fun onConfigureViews() { + TODO("Not yet implemented") } - override fun onCreateView( - inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - _binding = FragmentPasswordRecoveryBinding.inflate(layoutInflater, container, false) - return binding.root + override fun onSubscribe() { + TODO("Not yet implemented") } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding.btnVerification.setOnClickListener { - findNavController().navigate(R.id.action_passwordRecoveryFragment_to_entryVerificationFragment) - } - } - - override fun onDestroyView() { - super.onDestroyView() - _binding = null - } } \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/PasswordRecoveryViewModel.kt b/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/PasswordRecoveryViewModel.kt index d482c974..480f1336 100644 --- a/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/PasswordRecoveryViewModel.kt +++ b/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/PasswordRecoveryViewModel.kt @@ -1,39 +1,247 @@ package app.cashadvisor.authorization.presentation.viewmodel.passwordrecovery +import androidx.lifecycle.viewModelScope import app.cashadvisor.authorization.domain.api.InputValidationInteractor -import app.cashadvisor.authorization.domain.api.LoginInteractor +import app.cashadvisor.authorization.domain.api.ResetPasswordInteractor +import app.cashadvisor.authorization.domain.models.states.ConfirmCodeValidationState +import app.cashadvisor.authorization.domain.models.states.EmailValidationState +import app.cashadvisor.authorization.domain.models.states.PasswordValidationState import app.cashadvisor.authorization.presentation.viewmodel.passwordrecovery.models.PasswordRecoveryState +import app.cashadvisor.authorization.presentation.viewmodel.passwordrecovery.models.PasswordRecoveryUiState +import app.cashadvisor.common.domain.Resource +import app.cashadvisor.common.domain.model.ErrorEntity import app.cashadvisor.common.ui.BaseViewModel +import app.cashadvisor.common.utill.extensions.logDebugMessage import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject +import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch @HiltViewModel class PasswordRecoveryViewModel @Inject constructor( - private val loginInteractor: LoginInteractor, + private val resetPasswordInteractor: ResetPasswordInteractor, private val inputValidationInteractor: InputValidationInteractor ) : BaseViewModel() { + private val _uiState:MutableStateFlow = MutableStateFlow( + PasswordRecoveryUiState() + ) + val uiState:StateFlow = _uiState.asStateFlow() + private val _state: MutableStateFlow = MutableStateFlow( PasswordRecoveryState() ) private val state: StateFlow = _state.asStateFlow() + + private val _sideEffects: MutableSharedFlow = MutableSharedFlow() + + val sideEffect: SharedFlow = _sideEffects.asSharedFlow() private val currentState get() = state.replayCache.firstOrNull() ?: PasswordRecoveryState() + fun init(){ + viewModelScope.launch { + state.collect{ state -> + _uiState.update { uiState -> + uiState.copy( + emailIsValid = state.isEmailValid, + confirmEmailCodeIsValid = state.isEmailCodeValid && state.isRecoveryPasswordInProgress, + newPasswordIsValid = state.isNewPasswordValid && state.isRecoveryPasswordInProgress + ) + } - private fun setEmail(email: String) { + } + } } - private fun setPassword(password :String){ + fun handleEvent(event: RecoveryPasswordScreenEvent){ + when(event){ + is RecoveryPasswordScreenEvent.SetEmail -> setEmail(event.email) + RecoveryPasswordScreenEvent.Recovery -> recovery() + is RecoveryPasswordScreenEvent.SetEmailConfirmCode -> setEmailConfirmCode(event.code) + RecoveryPasswordScreenEvent.ConfirmEmail -> sendEmailConfirmCode() + is RecoveryPasswordScreenEvent.SetPassword -> setPassword(event.password) + RecoveryPasswordScreenEvent.ConfirmNewPassword -> sendNewPassword() + } + } + private fun setEmail(email:String){ + viewModelScope.launch { + val result = inputValidationInteractor.validateEmail(email) + when (result) { + is EmailValidationState.Success -> { + _state.update { + it.copy(email = result.email, isEmailValid = true) + } + } + is EmailValidationState.Error -> { + _state.update { + it.copy(email = result.email, isEmailValid = false) + } + } + } + } + } + private fun recovery(){ + viewModelScope.launch{ + resetPasswordInteractor.isResetPasswordInProgress().collect{ isInProgress -> + _state.update { + it.copy( + isRecoveryPasswordInProgress = isInProgress + ) + } + + } + } + viewModelScope.launch{ + val result = resetPasswordInteractor.confirmEmailForPasswordReset( + currentState.email + ) + when(result){ + is Resource.Success -> { + logDebugMessage("Message recovery ${result.data.message}") + viewModelScope.launch { + _sideEffects.emit(RecoverySideEffect.ShowMessage(message = result.data.message)) + } + } + is Resource.Error -> { + viewModelScope.launch{ + _sideEffects.emit(RecoverySideEffect.ShowMessage(message = "Error: ${result.error.message}")) + } + when (result.error) { + + is ErrorEntity.NetworksError.NoInternet -> { + logDebugMessage("NoInternet ${result.error.message}") + } + is ErrorEntity.ConfirmEmailToResetPassword -> { + when (result.error) { + is ErrorEntity.ConfirmEmailToResetPassword.FailedToGenerateTokenOrSendEmail -> { + logDebugMessage("FailedToGenerateTokenOrSendEmail ${result.error.message}") + } + + is ErrorEntity.ConfirmEmailToResetPassword.InvalidInput -> { + logDebugMessage("InvalidEmail ${result.error.message}") + + } + } + } + + else -> { + logDebugMessage("Something went wrong ${result.error.message}") + } + } + } + } + } + } + private fun setEmailConfirmCode(code:String){ + viewModelScope.launch { + val result = inputValidationInteractor.validateConfirmationCode(code) + when(result){ + is ConfirmCodeValidationState.Success -> { + _state.update { + it.copy(emailCode = result.confirmCode, isEmailCodeValid = true) + } + } + is ConfirmCodeValidationState.Error -> { + _state.update { + it.copy(emailCode = result.confirmCode, isEmailCodeValid = false) + } + } + } + } } + private fun sendEmailConfirmCode(){ + viewModelScope.launch { + val result = resetPasswordInteractor.resetPasswordConfirmWithCode(currentState.emailCode) + when(result){ + is Resource.Success -> { + viewModelScope.launch{ + _sideEffects.emit(RecoverySideEffect.ShowMessage(message = result.data)) + } + } + is Resource.Error -> { + viewModelScope.launch{ + _sideEffects.emit(RecoverySideEffect.ShowMessage(message = result.error.message)) + } + when(result.error){ + is ErrorEntity.ConfirmResetPasswordByEmailWithCode.InvalidInput -> { + logDebugMessage("FailedToConfirmEmailOrRegisterUser ${result.error.message}") + } + is ErrorEntity.ConfirmResetPasswordByEmailWithCode.WrongConfirmationCode -> { - private fun sendEmailConfirmCode() { + logDebugMessage("InvalidToken ${result.error.message}") + } + is ErrorEntity.ConfirmResetPasswordByEmailWithCode.FailedToConfirmPasswordReset ->{ + logDebugMessage("WrongConfirmationCode ${result.error.message}") + } + is ErrorEntity.NetworksError.NoInternet ->{ + logDebugMessage("NoInternet ${result.error.message}") + + } + else -> {} + } + } + + } + } + } + private fun setPassword(password:String){ + viewModelScope.launch{ + val result = inputValidationInteractor.validatePassword(password) + when(result){ + is PasswordValidationState.Success -> { + _state.update { + it.copy(password = result.password, isNewPasswordValid = true) + } + } + is PasswordValidationState.Error -> { + _state.update { + it.copy(password = result.password, isNewPasswordValid = false) + } + } + } + } } - private fun setEmailConfirmCode(){ + private fun sendNewPassword(){ + viewModelScope.launch { + val result = resetPasswordInteractor.saveNewPassword(currentState.email, currentState.password) + when(result){ + is Resource.Success -> { + viewModelScope.launch{ + _sideEffects.emit(RecoverySideEffect.ShowMessage(message = result.data.message)) + } + } + is Resource.Error -> { + viewModelScope.launch{ + _sideEffects.emit(RecoverySideEffect.ShowMessage(message = result.error.message)) + } + when(result.error){ + is ErrorEntity.SaveNewPassword.InvalidInput ->{ + logDebugMessage("InvalidInput ${result.error.message}") + } + is ErrorEntity.SaveNewPassword.InvalidToken -> { + logDebugMessage("InvalidToken ${result.error.message}") + } + is ErrorEntity.SaveNewPassword.FailedToResetPassword -> { + logDebugMessage("FailedToResetPassword ${result.error.message}") + } + is ErrorEntity.NetworksError.NoInternet -> { + logDebugMessage("NoInternet ${result.error.message}") + } + else -> { + logDebugMessage("Something went wrong ${result.error.message}") + } + } + } + } + } } } \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/RecoveryPasswordScreenEvent.kt b/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/RecoveryPasswordScreenEvent.kt new file mode 100644 index 00000000..077420b2 --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/RecoveryPasswordScreenEvent.kt @@ -0,0 +1,10 @@ +package app.cashadvisor.authorization.presentation.viewmodel.passwordrecovery + +sealed interface RecoveryPasswordScreenEvent { + class SetEmail(val email: String) : RecoveryPasswordScreenEvent + data object Recovery:RecoveryPasswordScreenEvent + class SetEmailConfirmCode(val code:String) : RecoveryPasswordScreenEvent + data object ConfirmEmail:RecoveryPasswordScreenEvent + class SetPassword(val password:String): RecoveryPasswordScreenEvent + data object ConfirmNewPassword: RecoveryPasswordScreenEvent +} \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/RecoverySideEffect.kt b/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/RecoverySideEffect.kt new file mode 100644 index 00000000..3393df30 --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/RecoverySideEffect.kt @@ -0,0 +1,5 @@ +package app.cashadvisor.authorization.presentation.viewmodel.passwordrecovery + +sealed interface RecoverySideEffect { + data class ShowMessage(val message:String):RecoverySideEffect +} \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/models/PasswordRecoveryState.kt b/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/models/PasswordRecoveryState.kt index 390503e2..7da4ea33 100644 --- a/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/models/PasswordRecoveryState.kt +++ b/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/models/PasswordRecoveryState.kt @@ -11,4 +11,6 @@ data class PasswordRecoveryState( val recoveryCode: ConfirmCode = ConfirmCode(""), val isEmailValid: Boolean = false, val isEmailCodeValid: Boolean = false, + val isNewPasswordValid: Boolean = false, + val isRecoveryPasswordInProgress:Boolean = false ) diff --git a/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/models/PasswordRecoveryUiState.kt b/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/models/PasswordRecoveryUiState.kt new file mode 100644 index 00000000..9aa6474a --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/models/PasswordRecoveryUiState.kt @@ -0,0 +1,8 @@ +package app.cashadvisor.authorization.presentation.viewmodel.passwordrecovery.models + +data class PasswordRecoveryUiState( + val emailIsValid:Boolean = false, + val confirmEmailCodeIsValid:Boolean = false, + val newPasswordIsValid:Boolean = false, + val message:String = "" +) From 4cac51f7b2a2c21d56e2bcc47046c5283779e4c4 Mon Sep 17 00:00:00 2001 From: MajoritySky2496 Date: Sat, 13 Apr 2024 14:15:46 +0500 Subject: [PATCH 04/19] 71-Password-Recovery Made: --- .../request/ConfirmLoginByEmailRequest.kt | 1 + .../models/states}/PasswordRecoveryState.kt | 2 +- .../models/states}/PasswordRecoveryUiState.kt | 2 +- .../ui/PasswordRecoveryFragment.kt | 60 ++++- .../ui/models/RecoverySideEffect.kt | 5 + .../PasswordRecoveryViewModel.kt | 14 +- .../RecoveryPasswordScreenEvent.kt | 6 +- .../passwordrecovery/RecoverySideEffect.kt | 5 - .../common/domain/model/ErrorEntity.kt | 2 +- .../exceptions/ResetPasswordException.kt | 2 +- .../res/layout/fragment_password_recovery.xml | 247 +++++++++++++++++- uikit/src/main/res/values/strings.xml | 8 + uikit/src/main/res/values/styles.xml | 7 + 13 files changed, 326 insertions(+), 35 deletions(-) rename app/src/main/java/app/cashadvisor/authorization/{presentation/viewmodel/passwordrecovery/models => domain/models/states}/PasswordRecoveryState.kt (87%) rename app/src/main/java/app/cashadvisor/authorization/{presentation/viewmodel/passwordrecovery/models => domain/models/states}/PasswordRecoveryUiState.kt (69%) create mode 100644 app/src/main/java/app/cashadvisor/authorization/presentation/ui/models/RecoverySideEffect.kt rename app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/{passwordrecovery => }/PasswordRecoveryViewModel.kt (95%) rename app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/{passwordrecovery => models}/RecoveryPasswordScreenEvent.kt (63%) delete mode 100644 app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/RecoverySideEffect.kt diff --git a/app/src/main/java/app/cashadvisor/authorization/data/models/request/ConfirmLoginByEmailRequest.kt b/app/src/main/java/app/cashadvisor/authorization/data/models/request/ConfirmLoginByEmailRequest.kt index 716c37db..dc44bf0d 100644 --- a/app/src/main/java/app/cashadvisor/authorization/data/models/request/ConfirmLoginByEmailRequest.kt +++ b/app/src/main/java/app/cashadvisor/authorization/data/models/request/ConfirmLoginByEmailRequest.kt @@ -2,6 +2,7 @@ package app.cashadvisor.authorization.data.models.request import kotlinx.serialization.Serializable + @Serializable data class ConfirmLoginByEmailRequest( val email:String, diff --git a/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/models/PasswordRecoveryState.kt b/app/src/main/java/app/cashadvisor/authorization/domain/models/states/PasswordRecoveryState.kt similarity index 87% rename from app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/models/PasswordRecoveryState.kt rename to app/src/main/java/app/cashadvisor/authorization/domain/models/states/PasswordRecoveryState.kt index 7da4ea33..bfb723ed 100644 --- a/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/models/PasswordRecoveryState.kt +++ b/app/src/main/java/app/cashadvisor/authorization/domain/models/states/PasswordRecoveryState.kt @@ -1,4 +1,4 @@ -package app.cashadvisor.authorization.presentation.viewmodel.passwordrecovery.models +package app.cashadvisor.authorization.domain.models.states import app.cashadvisor.authorization.domain.models.ConfirmCode import app.cashadvisor.authorization.domain.models.Email diff --git a/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/models/PasswordRecoveryUiState.kt b/app/src/main/java/app/cashadvisor/authorization/domain/models/states/PasswordRecoveryUiState.kt similarity index 69% rename from app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/models/PasswordRecoveryUiState.kt rename to app/src/main/java/app/cashadvisor/authorization/domain/models/states/PasswordRecoveryUiState.kt index 9aa6474a..73636df2 100644 --- a/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/models/PasswordRecoveryUiState.kt +++ b/app/src/main/java/app/cashadvisor/authorization/domain/models/states/PasswordRecoveryUiState.kt @@ -1,4 +1,4 @@ -package app.cashadvisor.authorization.presentation.viewmodel.passwordrecovery.models +package app.cashadvisor.authorization.domain.models.states data class PasswordRecoveryUiState( val emailIsValid:Boolean = false, diff --git a/app/src/main/java/app/cashadvisor/authorization/presentation/ui/PasswordRecoveryFragment.kt b/app/src/main/java/app/cashadvisor/authorization/presentation/ui/PasswordRecoveryFragment.kt index b5754a72..2380cb44 100644 --- a/app/src/main/java/app/cashadvisor/authorization/presentation/ui/PasswordRecoveryFragment.kt +++ b/app/src/main/java/app/cashadvisor/authorization/presentation/ui/PasswordRecoveryFragment.kt @@ -1,25 +1,65 @@ package app.cashadvisor.authorization.presentation.ui -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.fragment.app.Fragment +import androidx.core.widget.addTextChangedListener +import androidx.core.widget.doOnTextChanged import androidx.fragment.app.viewModels -import androidx.navigation.fragment.findNavController -import app.cashadvisor.R -import app.cashadvisor.authorization.presentation.viewmodel.passwordrecovery.PasswordRecoveryViewModel +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import app.cashadvisor.authorization.domain.models.ResetPasswordState +import app.cashadvisor.authorization.domain.models.states.PasswordRecoveryState +import app.cashadvisor.authorization.presentation.viewmodel.PasswordRecoveryViewModel +import app.cashadvisor.authorization.presentation.viewmodel.models.RecoveryPasswordScreenEvent import app.cashadvisor.common.ui.BaseFragment import app.cashadvisor.databinding.FragmentPasswordRecoveryBinding +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.launch class PasswordRecoveryFragment() : BaseFragment(FragmentPasswordRecoveryBinding::inflate) { override val viewModel: PasswordRecoveryViewModel by viewModels() override fun onConfigureViews() { - TODO("Not yet implemented") + with(binding){ + btnGetCode.setOnClickListener{ + viewModel.handleEvent(RecoveryPasswordScreenEvent.Recovery) + } + btnGetCode.setOnClickListener{ + viewModel.handleEvent(RecoveryPasswordScreenEvent.ConfirmEmail) + } + btnSendNewPassword.setOnClickListener { + viewModel.handleEvent(RecoveryPasswordScreenEvent.ConfirmNewPassword) + } + etEmailInput.doOnTextChanged { text, _, _, _-> + viewModel.handleEvent(RecoveryPasswordScreenEvent.SetEmail(text.toString())) + } + etConfirmationCode.doOnTextChanged{ text, _, _, _ -> + viewModel.handleEvent(RecoveryPasswordScreenEvent.SetEmailConfirmCode(text.toString())) + } + etPasswordInput.doOnTextChanged{text, _, _, _ -> + viewModel.handleEvent(RecoveryPasswordScreenEvent.SetPassword(text.toString())) + } + } } override fun onSubscribe() { - TODO("Not yet implemented") + viewLifecycleOwner.lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.STARTED){ + viewModel.uiState.collect{ uiState -> + + } + + } + } + viewLifecycleOwner.lifecycleScope.launch{ + repeatOnLifecycle(Lifecycle.State.STARTED){ + viewModel.sideEffect.collect{ + + } + } + } + viewModel.init() + } + private fun updateUi(state:PasswordRecoveryState){ + } diff --git a/app/src/main/java/app/cashadvisor/authorization/presentation/ui/models/RecoverySideEffect.kt b/app/src/main/java/app/cashadvisor/authorization/presentation/ui/models/RecoverySideEffect.kt new file mode 100644 index 00000000..1c7c4c65 --- /dev/null +++ b/app/src/main/java/app/cashadvisor/authorization/presentation/ui/models/RecoverySideEffect.kt @@ -0,0 +1,5 @@ +package app.cashadvisor.authorization.presentation.ui.models + +sealed interface RecoverySideEffect { + data class ShowMessage(val message:String): RecoverySideEffect +} \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/PasswordRecoveryViewModel.kt b/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/PasswordRecoveryViewModel.kt similarity index 95% rename from app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/PasswordRecoveryViewModel.kt rename to app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/PasswordRecoveryViewModel.kt index 480f1336..0ad44604 100644 --- a/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/PasswordRecoveryViewModel.kt +++ b/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/PasswordRecoveryViewModel.kt @@ -1,4 +1,4 @@ -package app.cashadvisor.authorization.presentation.viewmodel.passwordrecovery +package app.cashadvisor.authorization.presentation.viewmodel import androidx.lifecycle.viewModelScope import app.cashadvisor.authorization.domain.api.InputValidationInteractor @@ -6,8 +6,10 @@ import app.cashadvisor.authorization.domain.api.ResetPasswordInteractor import app.cashadvisor.authorization.domain.models.states.ConfirmCodeValidationState import app.cashadvisor.authorization.domain.models.states.EmailValidationState import app.cashadvisor.authorization.domain.models.states.PasswordValidationState -import app.cashadvisor.authorization.presentation.viewmodel.passwordrecovery.models.PasswordRecoveryState -import app.cashadvisor.authorization.presentation.viewmodel.passwordrecovery.models.PasswordRecoveryUiState +import app.cashadvisor.authorization.presentation.ui.models.RecoverySideEffect +import app.cashadvisor.authorization.presentation.viewmodel.models.RecoveryPasswordScreenEvent +import app.cashadvisor.authorization.domain.models.states.PasswordRecoveryState +import app.cashadvisor.authorization.domain.models.states.PasswordRecoveryUiState import app.cashadvisor.common.domain.Resource import app.cashadvisor.common.domain.model.ErrorEntity import app.cashadvisor.common.ui.BaseViewModel @@ -83,6 +85,9 @@ class PasswordRecoveryViewModel @Inject constructor( it.copy(email = result.email, isEmailValid = false) } } + EmailValidationState.Default -> { + + } } } } @@ -206,6 +211,9 @@ class PasswordRecoveryViewModel @Inject constructor( it.copy(password = result.password, isNewPasswordValid = false) } } + PasswordValidationState.Default -> { + + } } } } diff --git a/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/RecoveryPasswordScreenEvent.kt b/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/models/RecoveryPasswordScreenEvent.kt similarity index 63% rename from app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/RecoveryPasswordScreenEvent.kt rename to app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/models/RecoveryPasswordScreenEvent.kt index 077420b2..290149a2 100644 --- a/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/RecoveryPasswordScreenEvent.kt +++ b/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/models/RecoveryPasswordScreenEvent.kt @@ -1,10 +1,10 @@ -package app.cashadvisor.authorization.presentation.viewmodel.passwordrecovery +package app.cashadvisor.authorization.presentation.viewmodel.models sealed interface RecoveryPasswordScreenEvent { class SetEmail(val email: String) : RecoveryPasswordScreenEvent - data object Recovery:RecoveryPasswordScreenEvent + data object Recovery: RecoveryPasswordScreenEvent class SetEmailConfirmCode(val code:String) : RecoveryPasswordScreenEvent - data object ConfirmEmail:RecoveryPasswordScreenEvent + data object ConfirmEmail: RecoveryPasswordScreenEvent class SetPassword(val password:String): RecoveryPasswordScreenEvent data object ConfirmNewPassword: RecoveryPasswordScreenEvent } \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/RecoverySideEffect.kt b/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/RecoverySideEffect.kt deleted file mode 100644 index 3393df30..00000000 --- a/app/src/main/java/app/cashadvisor/authorization/presentation/viewmodel/passwordrecovery/RecoverySideEffect.kt +++ /dev/null @@ -1,5 +0,0 @@ -package app.cashadvisor.authorization.presentation.viewmodel.passwordrecovery - -sealed interface RecoverySideEffect { - data class ShowMessage(val message:String):RecoverySideEffect -} \ No newline at end of file diff --git a/app/src/main/java/app/cashadvisor/common/domain/model/ErrorEntity.kt b/app/src/main/java/app/cashadvisor/common/domain/model/ErrorEntity.kt index 892ae031..89c5f153 100644 --- a/app/src/main/java/app/cashadvisor/common/domain/model/ErrorEntity.kt +++ b/app/src/main/java/app/cashadvisor/common/domain/model/ErrorEntity.kt @@ -66,7 +66,7 @@ sealed class ErrorEntity(open val message: String) { data class WrongConfirmationCode( override val message: String, val remainingAttempts:Int, - val lockDuration:Int + val lockDuration:Long ) : ConfirmResetPasswordByEmailWithCode(message) data class FailedToConfirmPasswordReset(override val message: String) : diff --git a/app/src/main/java/app/cashadvisor/common/utill/exceptions/ResetPasswordException.kt b/app/src/main/java/app/cashadvisor/common/utill/exceptions/ResetPasswordException.kt index bac2fe07..9e22bcd4 100644 --- a/app/src/main/java/app/cashadvisor/common/utill/exceptions/ResetPasswordException.kt +++ b/app/src/main/java/app/cashadvisor/common/utill/exceptions/ResetPasswordException.kt @@ -24,7 +24,7 @@ sealed class ResetPasswordException( class UnauthorizedInvalidTokenOrMissingContentTypeHeader( override val message: String, val remainingAttempts:Int, - val lockDuration:Int, + val lockDuration:Long, val statusCode: Int ):ConfirmResetPasswordByEmailWithCode(message = message) diff --git a/app/src/main/res/layout/fragment_password_recovery.xml b/app/src/main/res/layout/fragment_password_recovery.xml index d47c3e72..b0551d28 100644 --- a/app/src/main/res/layout/fragment_password_recovery.xml +++ b/app/src/main/res/layout/fragment_password_recovery.xml @@ -1,30 +1,257 @@ - + + + + app:layout_constraintTop_toBottomOf="@id/custom_steps" /> + + + + + + + + + + +