Handle public instances #126
@ -128,7 +128,7 @@ class LoginActivity : AppCompatActivity(), DIAware {
|
||||
|
||||
private fun goToMain() {
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
repository.updateApiVersion()
|
||||
repository.updateApiInformation()
|
||||
ACRA.errorReporter.putCustomData("SELFOSS_API_VERSION", appSettingsService.getApiVersion().toString())
|
||||
}
|
||||
val intent = Intent(this, HomeActivity::class.java)
|
||||
|
@ -49,7 +49,7 @@ class RepositoryTest {
|
||||
repository = Repository(api, appSettingsService, isConnectionAvailable, db)
|
||||
|
||||
runBlocking {
|
||||
repository.updateApiVersion()
|
||||
repository.updateApiInformation()
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,9 +61,9 @@ class RepositoryTest {
|
||||
every { appSettingsService.isItemCachingEnabled() } returns false
|
||||
every { appSettingsService.isUpdateSourcesEnabled() } returns false
|
||||
|
||||
coEvery { api.version() } returns StatusAndData(
|
||||
coEvery { api.apiInformation() } returns StatusAndData(
|
||||
success = true,
|
||||
data = SelfossModel.ApiVersion("2.19-ba1e8e3", "4.0.0")
|
||||
data = SelfossModel.ApiInformation("2.19-ba1e8e3", "4.0.0")
|
||||
)
|
||||
coEvery { api.stats() } returns StatusAndData(
|
||||
success = true,
|
||||
@ -81,7 +81,7 @@ class RepositoryTest {
|
||||
fun instantiate_repository() {
|
||||
initializeRepository()
|
||||
|
||||
coVerify(exactly = 1) { api.version() }
|
||||
coVerify(exactly = 1) { api.apiInformation() }
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -90,7 +90,7 @@ class RepositoryTest {
|
||||
|
||||
initializeRepository(MutableStateFlow(false))
|
||||
|
||||
coVerify(exactly = 0) { api.version() }
|
||||
coVerify(exactly = 0) { api.apiInformation() }
|
||||
coVerify(exactly = 0) { api.stats() }
|
||||
}
|
||||
|
||||
@ -113,7 +113,7 @@ class RepositoryTest {
|
||||
@Test
|
||||
fun get_api_1_date_with_api_4_version_stored() {
|
||||
every { appSettingsService.getApiVersion() } returns 4
|
||||
coEvery { api.version() } returns StatusAndData(success = false, null)
|
||||
coEvery { api.apiInformation() } returns StatusAndData(success = false, null)
|
||||
val itemParameters = FakeItemParameters()
|
||||
itemParameters.datetime = "2021-04-23 11:45:32"
|
||||
coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns
|
||||
|
@ -35,17 +35,32 @@ class SelfossModel {
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ApiVersion(
|
||||
data class ApiInformation(
|
||||
val version: String?,
|
||||
val apiversion: String?
|
||||
val apiversion: String?,
|
||||
val configuration: ApiConfiguration?
|
||||
) {
|
||||
fun getApiMajorVersion() : Int {
|
||||
fun getApiMajorVersion(): Int {
|
||||
var versionNumber = 0
|
||||
if (apiversion != null) {
|
||||
versionNumber = apiversion.substringBefore(".").toInt()
|
||||
}
|
||||
return versionNumber
|
||||
}
|
||||
|
||||
fun getApiConfiguration() = configuration ?: ApiConfiguration(null, null)
|
||||
}
|
||||
|
||||
@kotlinx.serialization.Serializable
|
||||
|
||||
data class ApiConfiguration(
|
||||
@Serializable(with = BooleanSerializer::class)
|
||||
val publicMode: Boolean?,
|
||||
@Serializable(with = BooleanSerializer::class)
|
||||
val authEnabled: Boolean?
|
||||
) {
|
||||
fun isAuthEnabled() = authEnabled ?: true
|
||||
|
||||
fun isPublicModeEnabled() = publicMode ?: false
|
||||
}
|
||||
|
||||
@Serializable
|
||||
|
@ -439,13 +439,20 @@ class Repository(
|
||||
api.refreshLoginInformation()
|
||||
}
|
||||
|
||||
suspend fun updateApiVersion() {
|
||||
suspend fun updateApiInformation() {
|
||||
val apiMajorVersion = appSettingsService.getApiVersion()
|
||||
|
||||
if (isNetworkAvailable()) {
|
||||
val fetchedVersion = api.version()
|
||||
if (fetchedVersion.success && fetchedVersion.data != null && fetchedVersion.data.getApiMajorVersion() != apiMajorVersion) {
|
||||
appSettingsService.updateApiVersion(fetchedVersion.data.getApiMajorVersion())
|
||||
val fetchedInformation = api.apiInformation()
|
||||
if (fetchedInformation.success && fetchedInformation.data != null) {
|
||||
if (fetchedInformation.data.getApiMajorVersion() != apiMajorVersion) {
|
||||
appSettingsService.updateApiVersion(fetchedInformation.data.getApiMajorVersion())
|
||||
}
|
||||
if (appSettingsService.getUserName().isEmpty()
|
||||
&& fetchedInformation.data.getApiConfiguration().isAuthEnabled()
|
||||
&& fetchedInformation.data.getApiConfiguration().isPublicModeEnabled()) {
|
||||
AmineB
commented
I didn't look into how public instances work, but this condition seems weird.
They seem to mean different things. I didn't look into how public instances work, but this condition seems weird.
`isAuthEnabled` and `isPublicModeEnabled` can be `true` at the same time ?
They seem to mean different things.
davidoskky
commented
Yes, it is the normal case in fact; the weird condition is actually Yes, it is the normal case in fact; the weird condition is actually `isAuthEnabled` `false` and `isPublicModeEnabled` `true`.
Authentication is enabled because the administrator user can log in and read/favourite articles or edit sources while everyone else can just read the articles (and not mark them as read). Having authentication disabled simply means that no password is required to access and thus everyone is administrator, in this case it would make no sense to enable public mode as well.
AmineB
commented
Can you please add this to a comment ? Can you please add this to a comment ?
|
||||
appSettingsService.updatePublicAccess(true)
|
||||
AmineB
commented
`appSettingsService.updatePublicAccess(fetchedInformation.data.getApiConfiguration().isPublicModeEnabled())` isn't enough ?
davidoskky
commented
No, public mode might be enabled but we could still log into the instance with username and password. No, public mode might be enabled but we could still log into the instance with username and password.
Public mode has limitations, thus if one had the credentials to access the instance, that would actually be the preferred option.
davidoskky
commented
I'll rectify to explain what I mean. In the settings I am not storing the remote value of the configuration, I am directly storing whether we connected through public mode or not; in this way in any point of the application in which this information is required, that'll be readily available without any further processing. That's because we could connect trough the normal authentication method even if public mode was enabled. I'll rectify to explain what I mean. In the settings I am not storing the remote value of the configuration, I am directly storing whether we connected through public mode or not; in this way in any point of the application in which this information is required, that'll be readily available without any further processing. That's because we could connect trough the normal authentication method even if public mode was enabled.
Alternatively, I'd have to store both values of the remote configuration: `isPublicModeEnabled` and `isAuthEnabled` and each time check if these imply that we're connecting through public mode.
Since we are not using these information for anything else, storing it would be redundant.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -191,7 +191,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||
}
|
||||
})
|
||||
|
||||
suspend fun version(): StatusAndData<SelfossModel.ApiVersion> =
|
||||
suspend fun apiInformation(): StatusAndData<SelfossModel.ApiInformation> =
|
||||
bodyOrFailure(client.tryToGet(url("/api/about")))
|
||||
|
||||
suspend fun markAsRead(id: String): SuccessResponse =
|
||||
|
@ -7,6 +7,7 @@ class AppSettingsService {
|
||||
|
||||
// Api related
|
||||
private var _apiVersion: Int = -1
|
||||
private var _publicAccess: Boolean? = null
|
||||
private var _baseUrl: String = ""
|
||||
private var _userName: String = ""
|
||||
private var _password: String = ""
|
||||
@ -48,10 +49,32 @@ class AppSettingsService {
|
||||
return _apiVersion
|
||||
}
|
||||
|
||||
|
||||
fun updateApiVersion(apiMajorVersion: Int) {
|
||||
settings.putInt(API_VERSION_MAJOR, apiMajorVersion)
|
||||
refreshApiVersion()
|
||||
}
|
||||
|
||||
private fun refreshApiVersion() {
|
||||
_apiVersion = settings.getInt(API_VERSION_MAJOR, -1)
|
||||
}
|
||||
|
||||
fun getPublicAccess(): Boolean {
|
||||
if (_publicAccess == null) {
|
||||
refreshPublicAccess()
|
||||
}
|
||||
return _publicAccess!!
|
||||
}
|
||||
|
||||
fun updatePublicAccess(publicAccess: Boolean) {
|
||||
settings.putBoolean(API_PUBLIC_ACCESS, publicAccess)
|
||||
refreshPublicAccess()
|
||||
}
|
||||
|
||||
private fun refreshPublicAccess() {
|
||||
_publicAccess = settings.getBoolean(API_PUBLIC_ACCESS, false)
|
||||
}
|
||||
|
||||
fun getBaseUrl(): String {
|
||||
if (_baseUrl.isEmpty()) {
|
||||
refreshBaseUrl()
|
||||
@ -333,6 +356,7 @@ class AppSettingsService {
|
||||
refreshUsername()
|
||||
refreshBaseUrl()
|
||||
refreshApiVersion()
|
||||
refreshPublicAccess()
|
||||
}
|
||||
|
||||
fun refreshUserSettings() {
|
||||
@ -376,11 +400,6 @@ class AppSettingsService {
|
||||
refreshApiSettings()
|
||||
}
|
||||
|
||||
fun updateApiVersion(apiMajorVersion: Int) {
|
||||
settings.putInt(API_VERSION_MAJOR, apiMajorVersion)
|
||||
refreshApiVersion()
|
||||
}
|
||||
|
||||
fun clearAll() {
|
||||
settings.clear()
|
||||
refreshApiSettings()
|
||||
@ -409,6 +428,8 @@ class AppSettingsService {
|
||||
|
||||
const val API_VERSION_MAJOR = "apiVersionMajor"
|
||||
|
||||
const val API_PUBLIC_ACCESS = "apiPublicAccess"
|
||||
|
||||
const val API_ITEMS_NUMBER = "prefer_api_items_number"
|
||||
|
||||
const val API_TIMEOUT = "api_timeout"
|
||||
|
Can be changed to
@Serializable