diff --git a/app/src/main/java/com/isolaatti/auth/data/AuthRepositoryImpl.kt b/app/src/main/java/com/isolaatti/auth/data/AuthRepositoryImpl.kt index 51114cf..723fffa 100644 --- a/app/src/main/java/com/isolaatti/auth/data/AuthRepositoryImpl.kt +++ b/app/src/main/java/com/isolaatti/auth/data/AuthRepositoryImpl.kt @@ -47,14 +47,6 @@ class AuthRepositoryImpl @Inject constructor( } } - override fun logout(): Flow = flow { - tokenStorage.removeToken() - try { - authApi.signOut().awaitResponse() - } catch(_: Exception) { } - emit(true) - } - override fun getCurrentToken(): AuthTokenDto? { return tokenStorage.token } diff --git a/app/src/main/java/com/isolaatti/auth/data/remote/AuthApi.kt b/app/src/main/java/com/isolaatti/auth/data/remote/AuthApi.kt index 20fe0ee..c747cfa 100644 --- a/app/src/main/java/com/isolaatti/auth/data/remote/AuthApi.kt +++ b/app/src/main/java/com/isolaatti/auth/data/remote/AuthApi.kt @@ -12,7 +12,4 @@ interface AuthApi { @POST("LogIn") fun signInWithEmailAndPassword(@Header("apiClientId") clientId: String, @Header("apiClientSecret") clientSecret: String, @Body credential: Credential): Call - - @GET("LogIn/SignOut") - fun signOut(): Call } \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/auth/domain/AuthRepository.kt b/app/src/main/java/com/isolaatti/auth/domain/AuthRepository.kt index cf6db3b..5577a01 100644 --- a/app/src/main/java/com/isolaatti/auth/domain/AuthRepository.kt +++ b/app/src/main/java/com/isolaatti/auth/domain/AuthRepository.kt @@ -6,7 +6,6 @@ import kotlinx.coroutines.flow.Flow interface AuthRepository { fun authWithEmailAndPassword(email: String, password: String): Flow> - fun logout(): Flow fun getCurrentToken(): AuthTokenDto? fun getUserId(): Flow suspend fun setToken(sessionDto: AuthTokenDto) diff --git a/app/src/main/java/com/isolaatti/settings/Module.kt b/app/src/main/java/com/isolaatti/settings/Module.kt index f20e6bf..3c1fc8d 100644 --- a/app/src/main/java/com/isolaatti/settings/Module.kt +++ b/app/src/main/java/com/isolaatti/settings/Module.kt @@ -1,8 +1,13 @@ package com.isolaatti.settings +import com.isolaatti.auth.data.local.TokenStorage +import com.isolaatti.connectivity.RetrofitClient import com.isolaatti.database.AppDatabase import com.isolaatti.settings.data.KeyValueDao import com.isolaatti.settings.data.SettingsRepositoryImpl +import com.isolaatti.settings.data.remote.AccountSettingsApi +import com.isolaatti.settings.data.repository.AccountSettingsRepositoryImpl +import com.isolaatti.settings.domain.AccountSettingsRepository import com.isolaatti.settings.domain.SettingsRepository import dagger.Module import dagger.Provides @@ -21,4 +26,14 @@ class Module { fun provideSettingsRepository(keyValueDao: KeyValueDao): SettingsRepository { return SettingsRepositoryImpl(keyValueDao) } + + @Provides + fun provideAccountSettingsApi(retrofitClient: RetrofitClient): AccountSettingsApi { + return retrofitClient.client.create(AccountSettingsApi::class.java) + } + + @Provides + fun provideAccountSettingsRepository(tokenStorage: TokenStorage, accountSettingsApi: AccountSettingsApi): AccountSettingsRepository { + return AccountSettingsRepositoryImpl(tokenStorage, accountSettingsApi) + } } \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/settings/data/remote/AccountSettingsApi.kt b/app/src/main/java/com/isolaatti/settings/data/remote/AccountSettingsApi.kt index 94c70f2..4774ed9 100644 --- a/app/src/main/java/com/isolaatti/settings/data/remote/AccountSettingsApi.kt +++ b/app/src/main/java/com/isolaatti/settings/data/remote/AccountSettingsApi.kt @@ -1,4 +1,25 @@ package com.isolaatti.settings.data.remote +import retrofit2.Call +import retrofit2.http.Body +import retrofit2.http.GET +import retrofit2.http.POST +import retrofit2.http.Query + interface AccountSettingsApi { + @GET("account/get_sessions") + fun getSessions(): Call + + @POST("account/password/change") + fun changePassword( + @Body changePasswordDto: ChangePasswordDto, + @Query("signOut") signOut: Boolean, + @Query("signOutCurrent") signOutCurrent: Boolean + ): Call + + @POST("account/sign_out") + fun signOut(): Call + + @POST("account/sign_out_sessions") + fun signOutSessions(@Body removeSessionsDto: RemoveSessionsDto): Call } \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/settings/data/remote/ChangePasswordDto.kt b/app/src/main/java/com/isolaatti/settings/data/remote/ChangePasswordDto.kt new file mode 100644 index 0000000..67de568 --- /dev/null +++ b/app/src/main/java/com/isolaatti/settings/data/remote/ChangePasswordDto.kt @@ -0,0 +1,6 @@ +package com.isolaatti.settings.data.remote + +data class ChangePasswordDto( + val oldPassword: String, + val newPassword: String +) diff --git a/app/src/main/java/com/isolaatti/settings/data/remote/ChangePasswordResponseDto.kt b/app/src/main/java/com/isolaatti/settings/data/remote/ChangePasswordResponseDto.kt new file mode 100644 index 0000000..2cd3006 --- /dev/null +++ b/app/src/main/java/com/isolaatti/settings/data/remote/ChangePasswordResponseDto.kt @@ -0,0 +1,12 @@ +package com.isolaatti.settings.data.remote + +data class ChangePasswordResponseDto( + val success: Boolean, + val reason: String? +) { + companion object { + const val ReasonUserDoesNotExist = "user_does_not_exist"; + const val ReasonOldPasswordMismatch = "old_password_mismatch"; + const val ReasonNewPasswordInvalid = "new_password_invalid"; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/settings/data/remote/RemoveSessionsDto.kt b/app/src/main/java/com/isolaatti/settings/data/remote/RemoveSessionsDto.kt new file mode 100644 index 0000000..3879bc4 --- /dev/null +++ b/app/src/main/java/com/isolaatti/settings/data/remote/RemoveSessionsDto.kt @@ -0,0 +1,5 @@ +package com.isolaatti.settings.data.remote + +data class RemoveSessionsDto( + val ids: List +) \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/settings/data/remote/SessionsDto.kt b/app/src/main/java/com/isolaatti/settings/data/remote/SessionsDto.kt new file mode 100644 index 0000000..b55c411 --- /dev/null +++ b/app/src/main/java/com/isolaatti/settings/data/remote/SessionsDto.kt @@ -0,0 +1,15 @@ +package com.isolaatti.settings.data.remote + +import java.time.ZonedDateTime + +data class SessionsDto( + val data: List +) { + data class SessionDto( + val id: String, + val date: ZonedDateTime, + val ip: String, + val userAgent: String, + val current: Boolean + ) +} diff --git a/app/src/main/java/com/isolaatti/settings/data/repository/AccountSettingsRepositoryImpl.kt b/app/src/main/java/com/isolaatti/settings/data/repository/AccountSettingsRepositoryImpl.kt index 338504b..b78346e 100644 --- a/app/src/main/java/com/isolaatti/settings/data/repository/AccountSettingsRepositoryImpl.kt +++ b/app/src/main/java/com/isolaatti/settings/data/repository/AccountSettingsRepositoryImpl.kt @@ -1,6 +1,76 @@ 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.ChangePasswordDto +import com.isolaatti.settings.data.remote.ChangePasswordResponseDto +import com.isolaatti.settings.data.remote.RemoveSessionsDto +import com.isolaatti.settings.data.remote.SessionsDto import com.isolaatti.settings.domain.AccountSettingsRepository +import com.isolaatti.utils.Resource +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import retrofit2.awaitResponse +import javax.inject.Inject -class AccountSettingsRepositoryImpl : AccountSettingsRepository { +class AccountSettingsRepositoryImpl @Inject constructor( + private val tokenStorage: TokenStorage, + private val accountSettingsApi: AccountSettingsApi +) : AccountSettingsRepository { + override fun logout(): Flow> = flow { + tokenStorage.removeToken() + try { + val response = accountSettingsApi.signOut().awaitResponse() + if(response.isSuccessful) { + emit(Resource.Success(true)) + } else { + emit(Resource.Error(Resource.Error.mapErrorCode(response.code()))) + } + + } catch (exception: Exception) { + emit(Resource.Error(Resource.Error.ErrorType.NetworkError)) + } + } + + override fun getSessions(): Flow>> = flow { + try { + val response = accountSettingsApi.getSessions().awaitResponse() + + if(response.isSuccessful) { + emit(Resource.Success(response.body()?.data)) + } else { + emit(Resource.Error(Resource.Error.mapErrorCode(response.code()))) + } + } catch(_: Exception) { + emit(Resource.Error(Resource.Error.ErrorType.NetworkError)) + } + } + + override fun signOutSessions(sessionIds: List): Flow> = flow { + try { + val response = accountSettingsApi.signOutSessions(RemoveSessionsDto(sessionIds)).awaitResponse() + if(response.isSuccessful) { + emit(Resource.Success(true)) + } else { + emit(Resource.Error(Resource.Error.mapErrorCode(response.code()))) + } + + } catch(_: Exception) { + emit(Resource.Error(Resource.Error.ErrorType.NetworkError)) + } + } + + override fun changePassword(oldPassword: String, newPassword: String, signOut: Boolean, signOutCurrent: Boolean): Flow> = flow { + try { + val response = accountSettingsApi.changePassword(ChangePasswordDto(oldPassword, newPassword), signOut, signOutCurrent).awaitResponse() + if(response.isSuccessful) { + emit(Resource.Success(response.body())) + } else { + emit(Resource.Error(Resource.Error.mapErrorCode(response.code()))) + } + + } catch(_: Exception) { + emit(Resource.Error(Resource.Error.ErrorType.NetworkError)) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/settings/domain/AccountSettingsRepository.kt b/app/src/main/java/com/isolaatti/settings/domain/AccountSettingsRepository.kt index a929bfa..b282116 100644 --- a/app/src/main/java/com/isolaatti/settings/domain/AccountSettingsRepository.kt +++ b/app/src/main/java/com/isolaatti/settings/domain/AccountSettingsRepository.kt @@ -1,5 +1,16 @@ package com.isolaatti.settings.domain -interface AccountSettingsRepository { +import com.isolaatti.settings.data.remote.ChangePasswordResponseDto +import com.isolaatti.settings.data.remote.SessionsDto +import com.isolaatti.utils.Resource +import kotlinx.coroutines.flow.Flow +interface AccountSettingsRepository { + fun logout(): Flow> + + fun getSessions(): Flow>> + + fun signOutSessions(sessionIds: List): Flow> + + fun changePassword(oldPassword: String, newPassword: String, signOut: Boolean, signOutCurrent: Boolean): Flow> } \ No newline at end of file