Skip to content

Commit

Permalink
Merge pull request #256 from boostcampwm2023/feat/and/find-password
Browse files Browse the repository at this point in the history
비밀번호 찾기 기능 구현
  • Loading branch information
ootr47 authored Mar 4, 2024
2 parents 2e38c0c + 9e0a81a commit d388230
Show file tree
Hide file tree
Showing 33 changed files with 1,079 additions and 5 deletions.
3 changes: 3 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@
<activity
android:name=".ui.home.mypage.DeleteAccountActivity"
android:exported="false" />
<activity
android:name=".ui.login.findpassword.FindPasswordActivity"
android:exported="false" />

<service
android:name=".service.PriceGuardFirebaseMessagingService"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package app.priceguard.data.dto.password

import kotlinx.serialization.Serializable

@Serializable
data class ResetPasswordRequest(
val password: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package app.priceguard.data.dto.password

import kotlinx.serialization.Serializable

@Serializable
data class ResetPasswordResponse(
val statusCode: Int,
val message: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package app.priceguard.data.dto.verifyemail

import kotlinx.serialization.Serializable

@Serializable
data class RequestVerificationCodeRequest(
val email: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package app.priceguard.data.dto.verifyemail

import kotlinx.serialization.Serializable

@Serializable
data class RequestVerificationCodeResponse(
val statusCode: Int,
val message: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package app.priceguard.data.dto.verifyemail

import kotlinx.serialization.Serializable

@Serializable
data class VerifyEmailRequest(
val email: String,
val verificationCode: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package app.priceguard.data.dto.verifyemail

import kotlinx.serialization.Serializable

@Serializable
data class VerifyEmailResponse(
val statusCode: Int,
val message: String,
val verifyToken: String? = null
)
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
package app.priceguard.data.network

import app.priceguard.data.dto.renew.RenewResponse
import app.priceguard.data.dto.verifyemail.VerifyEmailRequest
import app.priceguard.data.dto.verifyemail.VerifyEmailResponse
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.POST

interface AuthAPI {

@GET("refreshJWT")
suspend fun renewTokens(
@Header("Authorization") authToken: String
): Response<RenewResponse>

@POST("verify/email")
suspend fun verifyEmail(
@Body verifyEmailRequest: VerifyEmailRequest
): Response<VerifyEmailResponse>
}
15 changes: 15 additions & 0 deletions android/app/src/main/java/app/priceguard/data/network/UserAPI.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ import app.priceguard.data.dto.firebase.FirebaseTokenUpdateRequest
import app.priceguard.data.dto.firebase.FirebaseTokenUpdateResponse
import app.priceguard.data.dto.login.LoginRequest
import app.priceguard.data.dto.login.LoginResponse
import app.priceguard.data.dto.password.ResetPasswordRequest
import app.priceguard.data.dto.password.ResetPasswordResponse
import app.priceguard.data.dto.signup.SignupRequest
import app.priceguard.data.dto.signup.SignupResponse
import app.priceguard.data.dto.verifyemail.RequestVerificationCodeRequest
import app.priceguard.data.dto.verifyemail.RequestVerificationCodeResponse
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.Header
Expand Down Expand Up @@ -36,4 +40,15 @@ interface UserAPI {
@Header("Authorization") authToken: String,
@Body request: FirebaseTokenUpdateRequest
): Response<FirebaseTokenUpdateResponse>

@POST("email/verification")
suspend fun requestVerificationCode(
@Body requestVerificationCodeRequest: RequestVerificationCodeRequest
): Response<RequestVerificationCodeResponse>

@POST("password")
suspend fun resetPassword(
@Header("Authorization") token: String,
@Body resetPasswordRequest: ResetPasswordRequest
): Response<ResetPasswordResponse>
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ package app.priceguard.data.repository.auth

enum class AuthErrorState {
INVALID_REQUEST,
UNAUTHORIZED,
DUPLICATED_EMAIL,
NOT_FOUND,
EXPIRE,
OVER_LIMIT,
UNDEFINED_ERROR
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,8 @@ interface AuthRepository {
suspend fun login(email: String, password: String): RepositoryResult<LoginResult, AuthErrorState>

suspend fun deleteAccount(email: String, password: String): RepositoryResult<Boolean, AuthErrorState>

suspend fun requestVerificationCode(email: String): RepositoryResult<Boolean, AuthErrorState>

suspend fun resetPassword(password: String, verifyToken: String): RepositoryResult<Boolean, AuthErrorState>
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package app.priceguard.data.repository.auth

import app.priceguard.data.dto.deleteaccount.DeleteAccountRequest
import app.priceguard.data.dto.login.LoginRequest
import app.priceguard.data.dto.password.ResetPasswordRequest
import app.priceguard.data.dto.signup.SignupRequest
import app.priceguard.data.dto.verifyemail.RequestVerificationCodeRequest
import app.priceguard.data.network.UserAPI
import app.priceguard.data.repository.APIResult
import app.priceguard.data.repository.RepositoryResult
Expand All @@ -21,10 +23,26 @@ class AuthRepositoryImpl @Inject constructor(private val userAPI: UserAPI) : Aut
RepositoryResult.Error(AuthErrorState.INVALID_REQUEST)
}

401 -> {
RepositoryResult.Error(AuthErrorState.UNAUTHORIZED)
}

404 -> {
RepositoryResult.Error(AuthErrorState.NOT_FOUND)
}

409 -> {
RepositoryResult.Error(AuthErrorState.DUPLICATED_EMAIL)
}

410 -> {
RepositoryResult.Error(AuthErrorState.EXPIRE)
}

429 -> {
RepositoryResult.Error(AuthErrorState.OVER_LIMIT)
}

else -> {
RepositoryResult.Error(AuthErrorState.UNDEFINED_ERROR)
}
Expand Down Expand Up @@ -55,7 +73,10 @@ class AuthRepositoryImpl @Inject constructor(private val userAPI: UserAPI) : Aut
}
}

override suspend fun login(email: String, password: String): RepositoryResult<LoginResult, AuthErrorState> {
override suspend fun login(
email: String,
password: String
): RepositoryResult<LoginResult, AuthErrorState> {
val response = getApiResult {
userAPI.login(LoginRequest(email, password))
}
Expand All @@ -75,7 +96,10 @@ class AuthRepositoryImpl @Inject constructor(private val userAPI: UserAPI) : Aut
}
}

override suspend fun deleteAccount(email: String, password: String): RepositoryResult<Boolean, AuthErrorState> {
override suspend fun deleteAccount(
email: String,
password: String
): RepositoryResult<Boolean, AuthErrorState> {
val response = getApiResult {
userAPI.deleteAccount(DeleteAccountRequest(email, password))
}
Expand All @@ -90,4 +114,37 @@ class AuthRepositoryImpl @Inject constructor(private val userAPI: UserAPI) : Aut
}
}
}

override suspend fun requestVerificationCode(email: String): RepositoryResult<Boolean, AuthErrorState> {
return when (
val response =
getApiResult { userAPI.requestVerificationCode(RequestVerificationCodeRequest(email)) }
) {
is APIResult.Success -> {
RepositoryResult.Success(true)
}

is APIResult.Error -> {
handleError(response.code)
}
}
}

override suspend fun resetPassword(
password: String,
verifyToken: String
): RepositoryResult<Boolean, AuthErrorState> {
return when (
val response =
getApiResult { userAPI.resetPassword("Bearer $verifyToken", ResetPasswordRequest(password)) }
) {
is APIResult.Success -> {
RepositoryResult.Success(true)
}

is APIResult.Error -> {
handleError(response.code)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package app.priceguard.data.repository.token

enum class TokenErrorState {
INVALID_REQUEST,
UNAUTHORIZED,
EXPIRED,
NOT_FOUND,
UNDEFINED_ERROR
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package app.priceguard.data.repository.token

import app.priceguard.data.repository.RepositoryResult
import app.priceguard.ui.data.UserDataResult
import app.priceguard.ui.data.VerifyEmailResult

interface TokenRepository {
suspend fun storeTokens(accessToken: String, refreshToken: String)
Expand All @@ -12,4 +13,5 @@ interface TokenRepository {
suspend fun getUserData(): UserDataResult
suspend fun renewTokens(refreshToken: String): RepositoryResult<Boolean, TokenErrorState>
suspend fun clearTokens()
suspend fun verifyEmail(email: String, verificationCode: String): RepositoryResult<VerifyEmailResult, TokenErrorState>
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ package app.priceguard.data.repository.token
import android.util.Log
import app.priceguard.data.datastore.TokenDataSource
import app.priceguard.data.dto.firebase.FirebaseTokenUpdateRequest
import app.priceguard.data.dto.verifyemail.VerifyEmailRequest
import app.priceguard.data.network.AuthAPI
import app.priceguard.data.network.UserAPI
import app.priceguard.data.repository.APIResult
import app.priceguard.data.repository.RepositoryResult
import app.priceguard.data.repository.getApiResult
import app.priceguard.ui.data.UserDataResult
import app.priceguard.ui.data.VerifyEmailResult
import com.google.firebase.Firebase
import com.google.firebase.messaging.FirebaseMessaging
import com.google.firebase.messaging.messaging
Expand All @@ -26,10 +28,18 @@ class TokenRepositoryImpl @Inject constructor(
code: Int?
): RepositoryResult<T, TokenErrorState> {
return when (code) {
400 -> {
RepositoryResult.Error(TokenErrorState.INVALID_REQUEST)
}

401 -> {
RepositoryResult.Error(TokenErrorState.UNAUTHORIZED)
}

404 -> {
RepositoryResult.Error(TokenErrorState.NOT_FOUND)
}

410 -> {
RepositoryResult.Error(TokenErrorState.EXPIRED)
}
Expand Down Expand Up @@ -108,4 +118,27 @@ class TokenRepositoryImpl @Inject constructor(
Firebase.messaging.deleteToken()
tokenDataSource.clearTokens()
}

override suspend fun verifyEmail(
email: String,
verificationCode: String
): RepositoryResult<VerifyEmailResult, TokenErrorState> {
val response = getApiResult {
authAPI.verifyEmail(VerifyEmailRequest(email, verificationCode))
}

return when (response) {
is APIResult.Success -> {
RepositoryResult.Success(
VerifyEmailResult(
response.data.verifyToken ?: ""
)
)
}

is APIResult.Error -> {
handleError(response.code)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package app.priceguard.ui.data

data class VerifyEmailResult(
val verifyToken: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import app.priceguard.R
import app.priceguard.databinding.ActivityLoginBinding
import app.priceguard.ui.home.HomeActivity
import app.priceguard.ui.login.LoginViewModel.LoginEvent
import app.priceguard.ui.login.findpassword.FindPasswordActivity
import app.priceguard.ui.signup.SignupActivity
import app.priceguard.ui.util.SystemNavigationColorState
import app.priceguard.ui.util.applySystemNavigationBarColor
Expand Down Expand Up @@ -49,6 +50,9 @@ class LoginActivity : AppCompatActivity() {
btnLoginSignup.setOnClickListener {
gotoSignUp()
}
tvFindPassword.setOnClickListener {
gotoFindPassword()
}
}
}

Expand Down Expand Up @@ -112,6 +116,10 @@ class LoginActivity : AppCompatActivity() {
startActivity(Intent(this, SignupActivity::class.java))
}

private fun gotoFindPassword() {
startActivity(Intent(this, FindPasswordActivity::class.java))
}

private fun gotoHomeActivity() {
val intent = Intent(this, HomeActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
Expand Down
Loading

0 comments on commit d388230

Please sign in to comment.