Skip to content

Commit

Permalink
Rework passing credentials
Browse files Browse the repository at this point in the history
  • Loading branch information
jocmp committed Oct 21, 2024
1 parent 23b7759 commit 9850c06
Show file tree
Hide file tree
Showing 12 changed files with 164 additions and 33 deletions.
8 changes: 8 additions & 0 deletions .idea/codeInsightSettings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 11 additions & 5 deletions app/src/main/java/com/capyreader/app/ui/accounts/LoginViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.capyreader.app.common.AppPreferences
import com.capyreader.app.loadAccountModules
import com.jocmp.capy.Account
import com.jocmp.capy.AccountManager
import com.jocmp.capy.accounts.Credentials
import com.jocmp.capy.accounts.FeedbinCredentials
import com.jocmp.capy.accounts.Source
import com.jocmp.capy.accounts.verifyCredentials
import com.capyreader.app.common.AppPreferences
import com.jocmp.capy.common.Async
import com.capyreader.app.loadAccountModules
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
Expand Down Expand Up @@ -53,9 +54,14 @@ class LoginViewModel(
viewModelScope.launch(Dispatchers.IO) {
_result = Async.Loading

val isSuccessful = verifyCredentials(username = username, password = password)
val result = Credentials.verify(
credentials = FeedbinCredentials(
username = username,
secret = password,
),
)

if (isSuccessful) {
if (result.isSuccess) {
withContext(Dispatchers.Main) {
updateOrCreateAccount()
onSuccess()
Expand Down
Empty file.
16 changes: 0 additions & 16 deletions app/src/test/java/com/jocmp/capyreader/ExampleUnitTest.kt

This file was deleted.

1 change: 1 addition & 0 deletions capy/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ dependencies {
implementation(project(":feedbinclient"))
implementation(project(":feedfinder"))
implementation(project(":rssparser"))
implementation(project(":readerclient"))
testImplementation(kotlin("test"))
testImplementation(libs.sqldelight.sqlite.driver)
testImplementation(libs.tests.junit)
Expand Down
3 changes: 3 additions & 0 deletions capy/src/main/java/com/jocmp/capy/AccountPreferences.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ class AccountPreferences(
val username: Preference<String>
get() = store.getString("username", "")

val url: Preference<String>
get() = store.getString("api_url", "")

val password: Preference<String>
get() = store.getString("password", "")

Expand Down
61 changes: 61 additions & 0 deletions capy/src/main/java/com/jocmp/capy/accounts/Credentials.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.jocmp.capy.accounts

import com.jocmp.feedbinclient.Feedbin
import com.jocmp.readerclient.GoogleReader

interface Credentials {
val username: String
val secret: String

companion object {
suspend fun verify(credentials: Credentials): Result<Credentials> =
when (credentials) {
is FeedbinCredentials -> verifyFeedbin(credentials)
is ReaderCredentials -> verifyReader(credentials)
else -> throw UnsupportedOperationException()
}

private suspend fun verifyFeedbin(credentials: FeedbinCredentials): Result<FeedbinCredentials> {
val response = Feedbin.verifyCredentials(
username = credentials.username,
password = credentials.secret
)

return if (response.isSuccessful) {
Result.success(credentials)
} else {
Result.failure(Throwable("Failed with status ${response.message()}"))
}
}

private suspend fun verifyReader(credentials: ReaderCredentials): Result<ReaderCredentials> {
val response = GoogleReader.verifyCredentials(
username = credentials.username,
password = credentials.secret,
baseURL = credentials.url
)

val resultCredentials = ReaderCredentials(
username = "",
secret = "",
url = credentials.url,
)


return if (response.isSuccessful) {
Result.success(resultCredentials)
} else {
Result.failure(Throwable("Failed with status ${response.message()}"))
}
}
}
}

data class FeedbinCredentials(override val username: String, override val secret: String) :
Credentials

data class ReaderCredentials(
override val username: String,
override val secret: String,
val url: String
) : Credentials
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.jocmp.capy.accounts

/**
* Save Auth Token for later use
* self.credentials = Credentials(type: .readerAPIKey, username: credentials.username, secret: authString)
*/

This file was deleted.

63 changes: 63 additions & 0 deletions capy/src/test/java/com/jocmp/capy/accounts/CredentialsTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.jocmp.capy.accounts

import com.jocmp.feedbinclient.Feedbin
import io.mockk.coEvery
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkObject
import kotlinx.coroutines.test.runTest
import okhttp3.ResponseBody.Companion.toResponseBody
import retrofit2.Response
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue

class FeedbinCredentialsTest {
val username = "test@example.com"
val password = "its-a-secret-to-everybody"
val credentials = FeedbinCredentials(username, password)
lateinit var feedbin: Feedbin

@BeforeTest
fun setup() {
feedbin = mockk<Feedbin>()
mockkObject(Feedbin.Companion)
every { Feedbin.create(any(), any()) }.returns(feedbin)
}

@Test
fun verify_onSuccess_shouldReturnCredentials() = runTest {
coEvery { feedbin.authentication(authentication = any()) }.returns(Response.success(null))

val result = Credentials.verify(credentials).getOrNull()!!

assertEquals(actual = result.username, expected = username)
assertEquals(actual = result.secret, expected = password)
}

@Test
fun verify_onError_shouldReturnFailure() = runTest {
coEvery { feedbin.authentication(authentication = any()) }.returns(
Response.error(
401,
"".toResponseBody()
)
)

val result = Credentials.verify(credentials)

assertTrue(result.isFailure)
}
}

class ReaderCredentialsTest {
@Test
fun verify_onSuccess_shouldReturnCredentials() {

}

@Test
fun verify_onError_shouldReturnFailure() {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,12 @@ interface Feedbin {
password: String,
client: OkHttpClient = OkHttpClient(),
baseURL: String = DEFAULT_URL
): Boolean {
): Response<Void> {
val feedbin = create(client = client, baseURL = baseURL)

val authentication = Credentials.basic(username, password)

return feedbin
.authentication(authentication = authentication)
.isSuccessful
return feedbin.authentication(authentication = authentication)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ package com.jocmp.readerclient

import com.squareup.moshi.Moshi
import okhttp3.OkHttpClient
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.create

interface GoogleReader {


companion object {
fun create(
client: OkHttpClient,
Expand All @@ -23,5 +22,13 @@ interface GoogleReader {
.build()
.create()
}

fun verifyCredentials(
username: String,
password: String,
baseURL: String,
): Response<Void> {
TODO()
}
}
}

0 comments on commit 9850c06

Please sign in to comment.