Skip to content
Open

dev #17

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.stslex.atten.core.core.di.ModuleCore
import com.stslex.atten.core.database.di.ModuleCoreDatabase
import com.stslex.atten.core.network.client.di.ModuleCoreNetwork
import com.stslex.atten.core.paging.di.ModuleCorePaging
import com.stslex.atten.core.store.di.ModuleCoreStore
import com.stslex.atten.core.todo.di.ModuleCoreToDo
import com.stslex.atten.core.ui.kit.utils.ModuleCoreUiUtils
import com.stslex.atten.feature.details.di.ModuleFeatureDetails
Expand All @@ -20,6 +21,7 @@ val appModules: List<Module> = listOf(
ModuleCorePaging().module,
ModuleCoreUiUtils().module,
ModuleCoreAuth().module,
ModuleCoreStore().module,
ModuleCoreNetwork().module,
ModuleFeatureHome().module,
ModuleFeatureDetails().module,
Expand Down
2 changes: 2 additions & 0 deletions core/auth/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ kotlin {
commonMain.dependencies {
implementation(project(":core:core"))
implementation(project(":core:ui:kit"))
implementation(project(":core:network:api"))
implementation(project(":core:network:client"))
}
androidMain.dependencies {
implementation(libs.gms.auth)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import com.google.android.gms.auth.api.identity.Identity
import com.google.android.gms.common.Scopes
import com.google.android.gms.common.api.Scope
import com.stslex.atten.core.auth.callback.GoogleAuthCallback
import com.stslex.atten.core.auth.model.GoogleAuthData
import com.stslex.atten.core.auth.model.GoogleAuthResult
import com.stslex.atten.core.core.logger.Log
import com.stslex.atten.core.ui.kit.utils.ActivityHolder
Expand All @@ -34,18 +35,28 @@ internal actual class GoogleAuthControllerImpl actual constructor(
) { result ->
logger.d("activity_result: $result, ${result.data}")
val activity = checkNotNull(activityHolder.activity as? ComponentActivity)
val result = if (result.resultCode == Activity.RESULT_OK) {
val authorizationResult = Identity
.getAuthorizationClient(activity)
.getAuthorizationResultFromIntent(result.data)
val uiResult = GoogleAuthResult(
accessToken = authorizationResult.accessToken,
serverAuthCode = authorizationResult.serverAuthCode
)
Result.success(uiResult)
} else {
val msg = "auth fail with ${result.resultCode} code"
Result.failure(IllegalStateException(msg))
val result = when (result.resultCode) {
Activity.RESULT_OK -> {
val authorizationResult = Identity
.getAuthorizationClient(activity)
.getAuthorizationResultFromIntent(result.data)
val uiResult = GoogleAuthData(
accessToken = authorizationResult.accessToken,
serverAuthCode = authorizationResult.serverAuthCode
)
Result.success(GoogleAuthResult.Success(uiResult))
}

Activity.RESULT_CANCELED -> {
logger.i("auth cancelled by user")
Result.success(GoogleAuthResult.Cancelled)
return@rememberLauncherForActivityResult
}

else -> {
val msg = "auth fail with ${result.resultCode} code"
Result.failure(IllegalStateException(msg))
}
}
callback.process(result)
}
Expand Down Expand Up @@ -73,11 +84,11 @@ internal actual class GoogleAuthControllerImpl actual constructor(
logger.e(e, "Couldn't start Authorization UI: " + e.localizedMessage)
}
} else {
val uiResult = GoogleAuthResult(
val uiResult = GoogleAuthData(
accessToken = result.accessToken,
serverAuthCode = result.serverAuthCode
)
callback.process(Result.success(uiResult))
callback.process(Result.success(GoogleAuthResult.Success(uiResult)))
}
}
.addOnFailureListener {
Expand All @@ -91,4 +102,5 @@ internal actual class GoogleAuthControllerImpl actual constructor(
private val logger = Log.tag(TAG)
private const val TAG = "GOOGLE_AUTH_CONTROLLER"
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,3 @@ interface GoogleAuthController {

fun auth(block: (Result<GoogleAuthResult>) -> Unit)
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.stslex.atten.core.auth.model

import androidx.compose.runtime.Stable

@Stable
data class GoogleAuthData(
val serverAuthCode: String?,
val accessToken: String?,
)

Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package com.stslex.atten.core.auth.model

import androidx.compose.runtime.Stable
sealed interface GoogleAuthResult {

@Stable
data class GoogleAuthResult(
val serverAuthCode: String?,
val accessToken: String?,
)
data class Success(val data: GoogleAuthData) : GoogleAuthResult

data object Cancelled : GoogleAuthResult
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.stslex.atten.core.auth.repository

import com.stslex.atten.core.auth.repository.model.TokenDataModel
import com.stslex.atten.core.core.result.AppResult

interface AuthRepository {

suspend fun authGoogle(googleToken: String): AppResult<TokenDataModel>

suspend fun requestAuthGithub(): AppResult<String>

suspend fun authGithub(code: String): AppResult<TokenDataModel>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.stslex.atten.core.auth.repository

import com.stslex.atten.core.auth.repository.model.TokenDataMapper
import com.stslex.atten.core.auth.repository.model.TokenDataModel
import com.stslex.atten.core.core.result.AppResult
import com.stslex.atten.core.core.result.ResultUtils.suspendRunCatching
import com.stslex.atten.core.network.api.AuthApiClient
import org.koin.core.annotation.Single

@Single
internal class AuthRepositoryImpl(
private val authClient: AuthApiClient
) : AuthRepository {

override suspend fun authGoogle(
googleToken: String
): AppResult<TokenDataModel> = suspendRunCatching(TokenDataMapper) {
authClient.googleAuth(googleToken)
}

override suspend fun requestAuthGithub(): AppResult<String> = suspendRunCatching {
authClient.githubRequestAuth().accessToken
}

override suspend fun authGithub(
code: String
): AppResult<TokenDataModel> = suspendRunCatching(TokenDataMapper) {
authClient.githubAuth(code)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.stslex.atten.core.auth.repository.model

import com.stslex.atten.core.core.result.Mapping
import com.stslex.atten.core.network.api.model.response.TokenResponseModel

object TokenDataMapper : Mapping<TokenResponseModel, TokenDataModel> {

override fun invoke(data: TokenResponseModel): TokenDataModel = with(data) {
TokenDataModel(
uuid = uuid,
email = email,
accessToken = accessToken,
refreshToken = refreshToken
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.stslex.atten.core.auth.repository.model

data class TokenDataModel(
val uuid: String,
val email: String,
val accessToken: String,
val refreshToken: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import kotlinx.coroutines.withContext

class AppCoroutineScope(
private val scope: CoroutineScope,
private val appDispatcher: AppDispatcher,
val appDispatcher: AppDispatcher,
) {

private fun exceptionHandler(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ internal class AppLoggerCreator(
)
}

override fun e(message: String) {
Log.e(
tag = tag,
message = message
)
}

override fun i(message: String) {
Log.i(
tag = tag,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ object Log : AtTenLogger {
)
}

fun e(
message: String,
tag: String? = null,
) {
if (isDebug.not()) return
// todo firebase crashlytics
Logger.Companion.e(
tag = tag ?: DEFAULT_TAG,
messageString = message,
)
}

fun d(
message: String,
tag: String? = null,
Expand Down Expand Up @@ -61,6 +73,10 @@ object Log : AtTenLogger {
e(throwable = throwable, tag = DEFAULT_TAG, message = message)
}

override fun e(message: String) {
e(tag = DEFAULT_TAG, message = message)
}

override fun d(message: String) {
d(message = message, tag = DEFAULT_TAG)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ interface Logger {
message: String? = null
)

fun e(message: String)

fun d(message: String)

fun i(message: String)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ open class AppError(
) : Throwable(
message = message,
cause = cause,
)
)
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
package com.stslex.atten.core.core.model
package com.stslex.atten.core.core.model

abstract class IgnoreError(
message: String? = null,
cause: Throwable? = null
) : AppError(
message = message,
cause = cause
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.stslex.atten.core.core.model

data class UnresolveError(
override val cause: Throwable? = null,
override val message: String? = null,
) : AppError(
message = message,
cause = cause
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.stslex.atten.core.core.result

import com.stslex.atten.core.core.model.AppError
import com.stslex.atten.core.core.model.UnresolveError

sealed interface AppResult<out T : Any> : AppResultMapper<T> {

data class Success<T : Any>(val data: T) : AppResult<T> {

override fun <R : Any> map(mapper: Mapping<T, R>): AppResult<R> = Success(mapper(data))
}

data class Error(val error: AppError) : AppResult<Nothing> {

override fun <R : Any> map(mapper: Mapping<Nothing, R>): AppResult<R> = Error(error)
}

data object Loading : AppResult<Nothing> {

override fun <R : Any> map(mapper: Mapping<Nothing, R>): AppResult<R> = Loading
}

companion object {

fun <T : Any> success(value: T): AppResult<T> = Success(value)

fun <T : Any> error(error: AppError): AppResult<T> = Error(error)

fun <T : Any> error(
error: Throwable
): AppResult<T> = if (error is AppError) {
error(error)
} else {
error(UnresolveError(error))
}

fun <T : Any> loading(): AppResult<T> = Loading

inline fun <T : Any> AppResult<T>.onError(
action: (AppError) -> Unit
): AppResult<T> = apply { (this as? Error)?.let { action(it.error) } }

inline fun <T : Any> AppResult<T>.onLoading(action: () -> Unit): AppResult<T> = apply {
if (this is Loading) action()
}

inline fun <T : Any> AppResult<T>.onSuccess(
action: (T) -> Unit
): AppResult<T> = this.apply {
(this as? Success<T>)?.let { action(it.data) }
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.stslex.atten.core.core.result

interface AppResultMapper<out T : Any> {

fun <R : Any> map(mapper: Mapping<T, R>): AppResult<R>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.stslex.atten.core.core.result

fun interface Mapping<in T : Any, R : Any> {

operator fun invoke(data: T): R
}
Loading
Loading