feature cambiar password y refactor
This commit is contained in:
parent
e33d1c279a
commit
381274a1b6
14
app/src/main/java/com/isolaatti/auth/AuthUtils.kt
Normal file
14
app/src/main/java/com/isolaatti/auth/AuthUtils.kt
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package com.isolaatti.auth
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.Uri
|
||||||
|
import androidx.browser.customtabs.CustomTabsIntent
|
||||||
|
import com.isolaatti.BuildConfig
|
||||||
|
|
||||||
|
const val RecoverPasswordRelativePath = "/recuperacion_cuenta"
|
||||||
|
fun openForgotPassword(context: Context) {
|
||||||
|
CustomTabsIntent.Builder()
|
||||||
|
.setShowTitle(true)
|
||||||
|
.build()
|
||||||
|
.launchUrl(context, Uri.parse("${BuildConfig.backend}$RecoverPasswordRelativePath"))
|
||||||
|
}
|
||||||
@ -1,6 +1,8 @@
|
|||||||
package com.isolaatti.auth.domain
|
package com.isolaatti.auth.domain
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import com.isolaatti.MainActivity
|
||||||
import com.isolaatti.auth.data.local.TokenStorage
|
import com.isolaatti.auth.data.local.TokenStorage
|
||||||
import com.isolaatti.settings.domain.AccountSettingsRepository
|
import com.isolaatti.settings.domain.AccountSettingsRepository
|
||||||
import dagger.hilt.android.qualifiers.ActivityContext
|
import dagger.hilt.android.qualifiers.ActivityContext
|
||||||
@ -8,10 +10,14 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
class SignOutUC @Inject constructor(
|
class SignOutUC @Inject constructor(
|
||||||
@ActivityContext private val context: Context,
|
@ActivityContext private val context: Context,
|
||||||
private val tokenStorage: TokenStorage,
|
private val tokenStorage: TokenStorage
|
||||||
private val accountSettingsRepository: AccountSettingsRepository
|
|
||||||
) {
|
) {
|
||||||
operator fun invoke() {
|
operator fun invoke() {
|
||||||
|
tokenStorage.removeToken()
|
||||||
|
val loginIntent = Intent(context, MainActivity::class.java).apply {
|
||||||
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||||
|
}
|
||||||
|
context.startActivity(loginIntent)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
4
app/src/main/java/com/isolaatti/common/ResultDto.kt
Normal file
4
app/src/main/java/com/isolaatti/common/ResultDto.kt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
package com.isolaatti.common
|
||||||
|
|
||||||
|
@JvmInline
|
||||||
|
value class ResultDto<T>(val result: T)
|
||||||
@ -1,18 +1,16 @@
|
|||||||
package com.isolaatti.login
|
package com.isolaatti.login
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.OnBackPressedCallback
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.browser.customtabs.CustomTabsIntent
|
|
||||||
import androidx.core.widget.doOnTextChanged
|
import androidx.core.widget.doOnTextChanged
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.isolaatti.BuildConfig
|
|
||||||
import com.isolaatti.R
|
import com.isolaatti.R
|
||||||
|
import com.isolaatti.auth.openForgotPassword
|
||||||
import com.isolaatti.databinding.ActivityLoginBinding
|
import com.isolaatti.databinding.ActivityLoginBinding
|
||||||
import com.isolaatti.sign_up.ui.SignUpActivity
|
import com.isolaatti.sign_up.ui.SignUpActivity
|
||||||
import com.isolaatti.utils.Resource
|
import com.isolaatti.utils.Resource
|
||||||
@ -92,7 +90,7 @@ class LogInActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
viewBinding.forgotPasswordBtn.setOnClickListener {
|
viewBinding.forgotPasswordBtn.setOnClickListener {
|
||||||
openForgotPassword()
|
openForgotPassword(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
viewBinding.signUpBtn.setOnClickListener {
|
viewBinding.signUpBtn.setOnClickListener {
|
||||||
@ -101,17 +99,12 @@ class LogInActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun openForgotPassword() {
|
|
||||||
CustomTabsIntent.Builder()
|
|
||||||
.setShowTitle(true)
|
|
||||||
.build()
|
|
||||||
.launchUrl(this, Uri.parse("${BuildConfig.backend}/recuperacion_cuenta"))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showWrongPasswordErrorMessage() {
|
private fun showWrongPasswordErrorMessage() {
|
||||||
MaterialAlertDialogBuilder(this)
|
MaterialAlertDialogBuilder(this)
|
||||||
.setMessage(R.string.wrong_password)
|
.setMessage(R.string.wrong_password)
|
||||||
.setNeutralButton(R.string.forgot_password) {_,_ -> openForgotPassword()}
|
.setNeutralButton(R.string.forgot_password) {_,_ -> openForgotPassword(this)}
|
||||||
.setPositiveButton(R.string.dismiss, null)
|
.setPositiveButton(R.string.dismiss, null)
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,7 +33,7 @@ class Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
fun provideAccountSettingsRepository(tokenStorage: TokenStorage, accountSettingsApi: AccountSettingsApi): AccountSettingsRepository {
|
fun provideAccountSettingsRepository(accountSettingsApi: AccountSettingsApi): AccountSettingsRepository {
|
||||||
return AccountSettingsRepositoryImpl(tokenStorage, accountSettingsApi)
|
return AccountSettingsRepositoryImpl(accountSettingsApi)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
package com.isolaatti.settings.data.remote
|
package com.isolaatti.settings.data.remote
|
||||||
|
|
||||||
|
import com.isolaatti.common.ResultDto
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
@ -15,7 +16,7 @@ interface AccountSettingsApi {
|
|||||||
@Body changePasswordDto: ChangePasswordDto,
|
@Body changePasswordDto: ChangePasswordDto,
|
||||||
@Query("signOut") signOut: Boolean,
|
@Query("signOut") signOut: Boolean,
|
||||||
@Query("signOutCurrent") signOutCurrent: Boolean
|
@Query("signOutCurrent") signOutCurrent: Boolean
|
||||||
): Call<ChangePasswordResponseDto>
|
): Call<ResultDto<ChangePasswordResponseDto>>
|
||||||
|
|
||||||
@POST("account/sign_out")
|
@POST("account/sign_out")
|
||||||
fun signOut(): Call<Any>
|
fun signOut(): Call<Any>
|
||||||
|
|||||||
@ -5,7 +5,6 @@ data class ChangePasswordResponseDto(
|
|||||||
val reason: String?
|
val reason: String?
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
const val ReasonUserDoesNotExist = "user_does_not_exist";
|
|
||||||
const val ReasonOldPasswordMismatch = "old_password_mismatch";
|
const val ReasonOldPasswordMismatch = "old_password_mismatch";
|
||||||
const val ReasonNewPasswordInvalid = "new_password_invalid";
|
const val ReasonNewPasswordInvalid = "new_password_invalid";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
package com.isolaatti.settings.data.repository
|
package com.isolaatti.settings.data.repository
|
||||||
|
|
||||||
import com.isolaatti.auth.data.local.TokenStorage
|
|
||||||
import com.isolaatti.settings.data.remote.AccountSettingsApi
|
import com.isolaatti.settings.data.remote.AccountSettingsApi
|
||||||
import com.isolaatti.settings.data.remote.ChangePasswordDto
|
import com.isolaatti.settings.data.remote.ChangePasswordDto
|
||||||
import com.isolaatti.settings.data.remote.ChangePasswordResponseDto
|
import com.isolaatti.settings.data.remote.ChangePasswordResponseDto
|
||||||
@ -14,7 +13,6 @@ import retrofit2.awaitResponse
|
|||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class AccountSettingsRepositoryImpl @Inject constructor(
|
class AccountSettingsRepositoryImpl @Inject constructor(
|
||||||
private val tokenStorage: TokenStorage,
|
|
||||||
private val accountSettingsApi: AccountSettingsApi
|
private val accountSettingsApi: AccountSettingsApi
|
||||||
) : AccountSettingsRepository {
|
) : AccountSettingsRepository {
|
||||||
override fun logout(): Flow<Resource<Boolean>> = flow {
|
override fun logout(): Flow<Resource<Boolean>> = flow {
|
||||||
@ -26,8 +24,6 @@ class AccountSettingsRepositoryImpl @Inject constructor(
|
|||||||
} else {
|
} else {
|
||||||
emit(Resource.Error(Resource.Error.mapErrorCode(response.code())))
|
emit(Resource.Error(Resource.Error.mapErrorCode(response.code())))
|
||||||
}
|
}
|
||||||
tokenStorage.removeToken()
|
|
||||||
|
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
emit(Resource.Error(Resource.Error.ErrorType.NetworkError))
|
emit(Resource.Error(Resource.Error.ErrorType.NetworkError))
|
||||||
}
|
}
|
||||||
@ -66,7 +62,7 @@ class AccountSettingsRepositoryImpl @Inject constructor(
|
|||||||
try {
|
try {
|
||||||
val response = accountSettingsApi.changePassword(ChangePasswordDto(oldPassword, newPassword), signOut, signOutCurrent).awaitResponse()
|
val response = accountSettingsApi.changePassword(ChangePasswordDto(oldPassword, newPassword), signOut, signOutCurrent).awaitResponse()
|
||||||
if(response.isSuccessful) {
|
if(response.isSuccessful) {
|
||||||
emit(Resource.Success(response.body()))
|
emit(Resource.Success(response.body()?.result))
|
||||||
} else {
|
} else {
|
||||||
emit(Resource.Error(Resource.Error.mapErrorCode(response.code())))
|
emit(Resource.Error(Resource.Error.mapErrorCode(response.code())))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,17 +9,20 @@ import androidx.fragment.app.Fragment
|
|||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.isolaatti.MainActivity
|
|
||||||
import com.isolaatti.R
|
import com.isolaatti.R
|
||||||
|
import com.isolaatti.auth.domain.SignOutUC
|
||||||
import com.isolaatti.databinding.FragmentAccountSettingsBinding
|
import com.isolaatti.databinding.FragmentAccountSettingsBinding
|
||||||
import com.isolaatti.settings.presentation.AccountSettingsViewModel
|
import com.isolaatti.settings.presentation.AccountSettingsViewModel
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class AccountSettingsFragment : Fragment() {
|
class AccountSettingsFragment : Fragment() {
|
||||||
private lateinit var binding: FragmentAccountSettingsBinding
|
private lateinit var binding: FragmentAccountSettingsBinding
|
||||||
private val viewModel: AccountSettingsViewModel by viewModels()
|
private val viewModel: AccountSettingsViewModel by viewModels()
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var signOutUC: SignOutUC
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
@ -51,10 +54,7 @@ class AccountSettingsFragment : Fragment() {
|
|||||||
|
|
||||||
viewModel.loggedOut.observe(viewLifecycleOwner) {
|
viewModel.loggedOut.observe(viewLifecycleOwner) {
|
||||||
if(it) {
|
if(it) {
|
||||||
val loginIntent = Intent(requireContext(), MainActivity::class.java).apply {
|
signOutUC()
|
||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
|
||||||
}
|
|
||||||
startActivity(loginIntent)
|
|
||||||
viewModel.loggedOut.value = false
|
viewModel.loggedOut.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,9 @@ import androidx.navigation.fragment.findNavController
|
|||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.isolaatti.R
|
import com.isolaatti.R
|
||||||
import com.isolaatti.auth.domain.SignOutUC
|
import com.isolaatti.auth.domain.SignOutUC
|
||||||
|
import com.isolaatti.auth.openForgotPassword
|
||||||
import com.isolaatti.databinding.FragmentSettingsChangePasswordBinding
|
import com.isolaatti.databinding.FragmentSettingsChangePasswordBinding
|
||||||
|
import com.isolaatti.settings.data.remote.ChangePasswordResponseDto
|
||||||
import com.isolaatti.settings.presentation.ChangePasswordViewModel
|
import com.isolaatti.settings.presentation.ChangePasswordViewModel
|
||||||
import com.isolaatti.utils.Resource
|
import com.isolaatti.utils.Resource
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
@ -109,8 +111,8 @@ class ChangePasswordFragment : Fragment() {
|
|||||||
viewBinding.newPasswordInputText.error = if(valid) null else getString(R.string.password_req)
|
viewBinding.newPasswordInputText.error = if(valid) null else getString(R.string.password_req)
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.passwordChangeResource.observe(viewLifecycleOwner) {
|
viewModel.passwordChangeResource.observe(viewLifecycleOwner) { resource ->
|
||||||
when(it) {
|
when(resource) {
|
||||||
is Resource.Loading -> {
|
is Resource.Loading -> {
|
||||||
lockControls(true)
|
lockControls(true)
|
||||||
showLoadingDialog()
|
showLoadingDialog()
|
||||||
@ -124,14 +126,62 @@ class ChangePasswordFragment : Fragment() {
|
|||||||
is Resource.Success -> {
|
is Resource.Success -> {
|
||||||
loadingDialog?.dismiss()
|
loadingDialog?.dismiss()
|
||||||
loadingDialog = null
|
loadingDialog = null
|
||||||
if(viewModel.signOutCurrent) {
|
if(resource.data?.success == true) {
|
||||||
signOut()
|
handlePasswordChangeSuccess()
|
||||||
} else {
|
} else {
|
||||||
|
handlePasswordChangeError(resource.data?.reason)
|
||||||
findNavController().popBackStack()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun handlePasswordChangeSuccess() {
|
||||||
|
if(viewModel.signOutCurrent) {
|
||||||
|
signOut()
|
||||||
|
} else {
|
||||||
|
findNavController().popBackStack()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handlePasswordChangeError(error: String?) {
|
||||||
|
when(error) {
|
||||||
|
ChangePasswordResponseDto.ReasonOldPasswordMismatch -> {
|
||||||
|
viewBinding.switcher.showNext()
|
||||||
|
showOldPasswordIsNotCorrectDialog()
|
||||||
|
}
|
||||||
|
ChangePasswordResponseDto.ReasonNewPasswordInvalid -> {
|
||||||
|
showNewPasswordIsInvalid()
|
||||||
|
}
|
||||||
|
// No special handling for "user_does_not_exist" as this
|
||||||
|
// error should not be faced by app user
|
||||||
|
else -> {
|
||||||
|
showUnknownErrorDialog()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showOldPasswordIsNotCorrectDialog() {
|
||||||
|
MaterialAlertDialogBuilder(requireContext())
|
||||||
|
.setMessage(R.string.old_password_not_correct)
|
||||||
|
.setNeutralButton(R.string.recover_password){_, _ ->
|
||||||
|
openForgotPassword(requireContext())
|
||||||
|
}
|
||||||
|
.setPositiveButton(R.string.dismiss, null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showNewPasswordIsInvalid() {
|
||||||
|
MaterialAlertDialogBuilder(requireContext())
|
||||||
|
.setMessage(R.string.new_password_is_invalid)
|
||||||
|
.setPositiveButton(R.string.dismiss, null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showUnknownErrorDialog() {
|
||||||
|
MaterialAlertDialogBuilder(requireContext())
|
||||||
|
.setMessage(R.string.unknown_error)
|
||||||
|
.setPositiveButton(R.string.dismiss, null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -142,7 +142,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/sign_out_this_device"
|
android:text="@string/sign_out_this_device"
|
||||||
android:layout_marginHorizontal="16dp"
|
android:layout_marginHorizontal="16dp"
|
||||||
android:enabled="false"
|
android:enabled="true"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintHorizontal_bias="1.0"
|
app:layout_constraintHorizontal_bias="1.0"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
|||||||
@ -162,4 +162,7 @@
|
|||||||
<string name="continuar">Continue</string>
|
<string name="continuar">Continue</string>
|
||||||
<string name="password_req">Password must contain at least 8 characters an have the following: 1–9, a-z, A-Z, special character.</string>
|
<string name="password_req">Password must contain at least 8 characters an have the following: 1–9, a-z, A-Z, special character.</string>
|
||||||
<string name="changing_password">Changing password…</string>
|
<string name="changing_password">Changing password…</string>
|
||||||
|
<string name="recover_password">Recover password</string>
|
||||||
|
<string name="old_password_not_correct">Password not changed, old password did not match. If you don\'t remember your password, you can always recover it.</string>
|
||||||
|
<string name="new_password_is_invalid">New password is invalid. Please check it meets the requirements</string>
|
||||||
</resources>
|
</resources>
|
||||||
Loading…
x
Reference in New Issue
Block a user