Remove initAccount from Account interface

This commit is contained in:
sim 2024-11-04 12:31:28 +00:00
parent 0373d0eb63
commit 4c65a1d40f
9 changed files with 73 additions and 85 deletions

View File

@ -4,12 +4,29 @@ import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
interface Account { interface Account<T> {
var name: String? /** Nextcloud username. */
var url: String? val name: String?
fun initAccount(context: Context): Boolean
/** Nextcloud instance url. */
val url: String?
/** Are we connected to nextcloud ? */
var connected: Boolean
/** Connect to nextcloud. */
fun connect(activity: Activity) fun connect(activity: Activity)
/**
* Invoked after [connect].
*
* Used to import nextcloud account after linking to Nextcloud app
*/
fun onActivityResult(activity: Activity, requestCode: Int, resultCode: Int, data: Intent?, block: (success: Boolean) -> Unit) fun onActivityResult(activity: Activity, requestCode: Int, resultCode: Int, data: Intent?, block: (success: Boolean) -> Unit)
fun getAccount(context: Context): Any?
/** Get client used to request the server. */
fun getClient(context: Context): T?
/** Logout. */
fun logout(context: Context) fun logout(context: Context)
} }

View File

@ -2,9 +2,6 @@ package org.unifiedpush.distributor.nextpush.account
import android.content.Context import android.content.Context
import android.util.Log import android.util.Log
import android.widget.Toast
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException
import com.nextcloud.android.sso.exceptions.NoCurrentAccountSelectedException
import org.unifiedpush.distributor.nextpush.utils.TAG import org.unifiedpush.distributor.nextpush.utils.TAG
internal const val PREF_NAME = "NextPush" internal const val PREF_NAME = "NextPush"
@ -24,7 +21,7 @@ private fun Int.toAccountType(): AccountType {
} }
object AccountFactory { object AccountFactory {
private var account: Account? = null private var account: Account<out Any>? = null
var Context.accountType: AccountType var Context.accountType: AccountType
get() = this.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) get() = this.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
@ -48,39 +45,15 @@ object AccountFactory {
}.apply() }.apply()
} }
fun getAccount(context: Context, uninitialized: Boolean = false): Account? { fun getAccount(context: Context, connected: Boolean = true): Account<out Any>? {
return account return account
?: run { ?: run {
Log.d(TAG, "New account, type=${context.accountType}") Log.d(TAG, "New account, type=${context.accountType}")
when (context.accountType) { when (context.accountType) {
AccountType.SSO -> { AccountType.SSO -> SSOAccount(context)
try { AccountType.Direct -> DirectAccount(context)
SSOAccount().apply { }.takeIf { !connected || it.connected }.also {
initAccount(context) account = it
account = this
}
} catch (e: NextcloudFilesAppAccountNotFoundException) {
Toast.makeText(
context,
"Nextcloud application not found",
Toast.LENGTH_SHORT
).show()
Log.w(TAG, "Nextcloud application not found")
null
} catch (e: NoCurrentAccountSelectedException) {
if (uninitialized) {
SSOAccount()
} else {
null
}
}
}
AccountType.Direct -> {
DirectAccount().apply {
initAccount(context)
account = this
}
}
} }
} }
} }
@ -101,8 +74,4 @@ object AccountFactory {
accountType = AccountType.Direct accountType = AccountType.Direct
DirectAccount.setCredentials(this, url, username, password) DirectAccount.setCredentials(this, url, username, password)
} }
fun isConnected(context: Context): Boolean {
return getAccount(context)?.initAccount(context) == true
}
} }

View File

@ -16,27 +16,20 @@ private const val PREF_URL = "direct_account::url"
private const val PREF_USERNAME = "direct_account::username" private const val PREF_USERNAME = "direct_account::username"
private const val PREF_PASSWORD = "direct_account::password" private const val PREF_PASSWORD = "direct_account::password"
class DirectAccount : Account { class DirectAccount(context: Context) : Account<OkHttpClient> {
override var name: String? = null
override var url: String? = null
private var Context.connected: Boolean override val name: String? = context.username
get() = this.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) override val url: String? = context.url
.getBoolean(PREF_CONNECTED, false) override var connected = context.connected
set(value) = this.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.edit().putBoolean(PREF_CONNECTED, value)
.apply()
override fun initAccount(context: Context): Boolean { private fun setConnected(context: Context, value: Boolean) {
url = context.url connected = value
name = context.username context.connected = value
return context.connected
} }
override fun connect(activity: Activity) { override fun connect(activity: Activity) {
activity.connected = false setConnected(activity, false)
val client = getAccount(activity) as OkHttpClient? ?: return retActivity(activity) val client = getClient(activity) ?: return retActivity(activity)
val url = activity.url ?: return retActivity(activity) val url = activity.url ?: return retActivity(activity)
val request = try { val request = try {
@ -57,8 +50,8 @@ class DirectAccount : Account {
} }
override fun onResponse(call: Call, response: Response) { override fun onResponse(call: Call, response: Response) {
Log.e(TAG, "Status: ${response.code}") Log.d(TAG, "Status: ${response.code}")
activity.connected = response.code == 200 setConnected(activity, response.code == 200)
response.close() response.close()
retActivity(activity) retActivity(activity)
} }
@ -72,10 +65,10 @@ class DirectAccount : Account {
data: Intent?, data: Intent?,
block: (success: Boolean) -> Unit block: (success: Boolean) -> Unit
) { ) {
block(activity.connected) block(connected)
} }
override fun getAccount(context: Context): Any? { override fun getClient(context: Context): OkHttpClient? {
val username = context.username ?: return null val username = context.username ?: return null
val password = context.password ?: return null val password = context.password ?: return null
return OkHttpClient.Builder() return OkHttpClient.Builder()
@ -86,7 +79,7 @@ class DirectAccount : Account {
} }
override fun logout(context: Context) { override fun logout(context: Context) {
context.connected = false setConnected(context, false)
setCredentials(context, null, null, null) setCredentials(context, null, null, null)
} }
@ -158,6 +151,13 @@ class DirectAccount : Account {
.apply() .apply()
} }
private var Context.connected: Boolean
get() = this.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.getBoolean(PREF_CONNECTED, false)
set(value) = this.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.edit().putBoolean(PREF_CONNECTED, value)
.apply()
fun setCredentials(context: Context, url: String?, username: String?, password: String?) { fun setCredentials(context: Context, url: String?, username: String?, password: String?) {
context.url = url context.url = url
context.username = username context.username = username

View File

@ -14,27 +14,30 @@ import androidx.appcompat.app.AlertDialog
import com.nextcloud.android.sso.AccountImporter import com.nextcloud.android.sso.AccountImporter
import com.nextcloud.android.sso.exceptions.* // ktlint-disable no-wildcard-imports import com.nextcloud.android.sso.exceptions.* // ktlint-disable no-wildcard-imports
import com.nextcloud.android.sso.helper.SingleAccountHelper import com.nextcloud.android.sso.helper.SingleAccountHelper
import com.nextcloud.android.sso.model.SingleSignOnAccount
import com.nextcloud.android.sso.ui.UiExceptionManager import com.nextcloud.android.sso.ui.UiExceptionManager
import org.unifiedpush.distributor.nextpush.R import org.unifiedpush.distributor.nextpush.R
import org.unifiedpush.distributor.nextpush.utils.TAG import org.unifiedpush.distributor.nextpush.utils.TAG
class SSOAccount : Account { class SSOAccount(val context: Context) : Account<SingleSignOnAccount> {
override var name: String? = null override var name: String? = null
override var url: String? = null override var url: String? = null
override var connected = false
override fun initAccount(context: Context): Boolean { init {
try { try {
SingleAccountHelper.getCurrentSingleSignOnAccount(context).let { SingleAccountHelper.getCurrentSingleSignOnAccount(context).let {
name = it.name name = it.name
url = it.url url = it.url
} }
connected = true
} catch (e: NextcloudFilesAppAccountNotFoundException) { } catch (e: NextcloudFilesAppAccountNotFoundException) {
return false Log.d(TAG, "Nextcloud application not found")
connected = false
} catch (e: NoCurrentAccountSelectedException) { } catch (e: NoCurrentAccountSelectedException) {
Log.d(TAG, "Device is not connected") Log.d(TAG, "Device is not connected")
return false connected = false
} }
return true
} }
override fun connect(activity: Activity) { override fun connect(activity: Activity) {
@ -70,7 +73,7 @@ class SSOAccount : Account {
} }
} }
override fun getAccount(context: Context): Any? { override fun getClient(context: Context): SingleSignOnAccount? {
return try { return try {
SingleAccountHelper.getCurrentSingleSignOnAccount(context) SingleAccountHelper.getCurrentSingleSignOnAccount(context)
} catch (e: NextcloudFilesAppAccountNotFoundException) { } catch (e: NextcloudFilesAppAccountNotFoundException) {

View File

@ -30,8 +30,6 @@ import org.unifiedpush.distributor.nextpush.Database.Companion.getDb
import org.unifiedpush.distributor.nextpush.LocalNotification import org.unifiedpush.distributor.nextpush.LocalNotification
import org.unifiedpush.distributor.nextpush.R import org.unifiedpush.distributor.nextpush.R
import org.unifiedpush.distributor.nextpush.account.AccountFactory import org.unifiedpush.distributor.nextpush.account.AccountFactory
import org.unifiedpush.distributor.nextpush.account.AccountFactory.getAccount
import org.unifiedpush.distributor.nextpush.account.AccountFactory.isConnected
import org.unifiedpush.distributor.nextpush.activities.PermissionsRequest.requestAppPermissions import org.unifiedpush.distributor.nextpush.activities.PermissionsRequest.requestAppPermissions
import org.unifiedpush.distributor.nextpush.activities.StartActivity.Companion.goToStartActivity import org.unifiedpush.distributor.nextpush.activities.StartActivity.Companion.goToStartActivity
import org.unifiedpush.distributor.nextpush.distributor.Distributor import org.unifiedpush.distributor.nextpush.distributor.Distributor
@ -58,13 +56,14 @@ class MainActivity : AppCompatActivity() {
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
setSupportActionBar(findViewById(R.id.toolbar)) setSupportActionBar(findViewById(R.id.toolbar))
this.requestAppPermissions() this.requestAppPermissions()
if (!isConnected(this)) { if (AccountFactory.getAccount(this)?.connected != true) {
Log.d(TAG, "Not connected: going to StartActivity.")
goToStartActivity(this) goToStartActivity(this)
finish() finish()
} }
findViewById<TextView>(R.id.main_account_desc).text = findViewById<TextView>(R.id.main_account_desc).text =
format(getString(R.string.main_account_desc), getAccount(this)?.name) format(getString(R.string.main_account_desc), AccountFactory.getAccount(this)?.name)
invalidateOptionsMenu() invalidateOptionsMenu()
RestartWorker.startPeriodic(this) RestartWorker.startPeriodic(this)
setDebugInformationListener() setDebugInformationListener()

View File

@ -29,7 +29,7 @@ class StartActivity : AppCompatActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_start) setContentView(R.layout.activity_start)
this.requestAppPermissions() this.requestAppPermissions()
if (AccountFactory.isConnected(this)) { if (AccountFactory.getAccount(this)?.connected == true) {
goToMainActivity(this) goToMainActivity(this)
finish() finish()
} }
@ -74,7 +74,7 @@ class StartActivity : AppCompatActivity() {
} }
private fun login() { private fun login() {
AccountFactory.getAccount(this, uninitialized = true)?.let { AccountFactory.getAccount(this, connected = false)?.let {
onResult = { activity: Activity, i: Int, i1: Int, intent: Intent?, block: (success: Boolean) -> Unit -> onResult = { activity: Activity, i: Int, i1: Int, intent: Intent?, block: (success: Boolean) -> Unit ->
it.onActivityResult(activity, i, i1, intent, block) it.onActivityResult(activity, i, i1, intent, block)
} }

View File

@ -1,8 +1,8 @@
package org.unifiedpush.distributor.nextpush.api.provider package org.unifiedpush.distributor.nextpush.api.provider
import android.content.Context import android.content.Context
import okhttp3.* // ktlint-disable no-wildcard-imports import org.unifiedpush.distributor.nextpush.account.AccountFactory
import org.unifiedpush.distributor.nextpush.account.AccountFactory.getAccount import org.unifiedpush.distributor.nextpush.account.DirectAccount
import org.unifiedpush.distributor.nextpush.api.provider.ApiProvider.Companion.mApiEndpoint import org.unifiedpush.distributor.nextpush.api.provider.ApiProvider.Companion.mApiEndpoint
import retrofit2.Retrofit import retrofit2.Retrofit
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory
@ -10,13 +10,13 @@ import retrofit2.converter.gson.GsonConverterFactory
class ApiDirectFactory(val context: Context) : ApiProviderFactory { class ApiDirectFactory(val context: Context) : ApiProviderFactory {
override fun getProviderAndExecute(block: (ApiProvider, then: () -> Unit) -> Unit) { override fun getProviderAndExecute(block: (ApiProvider, then: () -> Unit) -> Unit) {
val account = getAccount(context) ?: run { val account = AccountFactory.getAccount(context) ?: run {
throw NoProviderException("No account found") throw NoProviderException("No account found")
} }
val url = account.url ?: run { val url = account.url ?: run {
throw NoProviderException("No url found") throw NoProviderException("No url found")
} }
val client = account.getAccount(context) as OkHttpClient? ?: run { val client = (account as DirectAccount).getClient(context) ?: run {
throw NoProviderException("No client found") throw NoProviderException("No client found")
} }
Retrofit.Builder() Retrofit.Builder()

View File

@ -4,8 +4,8 @@ import android.content.Context
import android.util.Log import android.util.Log
import com.google.gson.GsonBuilder import com.google.gson.GsonBuilder
import com.nextcloud.android.sso.api.NextcloudAPI import com.nextcloud.android.sso.api.NextcloudAPI
import com.nextcloud.android.sso.model.SingleSignOnAccount import org.unifiedpush.distributor.nextpush.account.AccountFactory
import org.unifiedpush.distributor.nextpush.account.AccountFactory.getAccount import org.unifiedpush.distributor.nextpush.account.SSOAccount
import retrofit2.NextcloudRetrofitApiBuilder import retrofit2.NextcloudRetrofitApiBuilder
class ApiSSOFactory(val context: Context) : ApiProviderFactory { class ApiSSOFactory(val context: Context) : ApiProviderFactory {
@ -14,10 +14,10 @@ class ApiSSOFactory(val context: Context) : ApiProviderFactory {
override fun getProviderAndExecute(block: (ApiProvider, then: () -> Unit) -> Unit) { override fun getProviderAndExecute(block: (ApiProvider, then: () -> Unit) -> Unit) {
var nextcloudAPI: NextcloudAPI? = null var nextcloudAPI: NextcloudAPI? = null
val account = getAccount(context) ?: run { val account = AccountFactory.getAccount(context) ?: run {
throw NoProviderException("No account found") throw NoProviderException("No account found")
} }
val client = account.getAccount(context) as SingleSignOnAccount? ?: run { val client = (account as SSOAccount).getClient(context) ?: run {
throw NoProviderException("No client found") throw NoProviderException("No client found")
} }
val ssoApiCallback = object : NextcloudAPI.ApiConnectedListener { val ssoApiCallback = object : NextcloudAPI.ApiConnectedListener {

View File

@ -11,7 +11,7 @@ import androidx.annotation.RequiresApi
import org.unifiedpush.distributor.nextpush.AppCompanion import org.unifiedpush.distributor.nextpush.AppCompanion
import org.unifiedpush.distributor.nextpush.Database.Companion.getDb import org.unifiedpush.distributor.nextpush.Database.Companion.getDb
import org.unifiedpush.distributor.nextpush.WakeLock import org.unifiedpush.distributor.nextpush.WakeLock
import org.unifiedpush.distributor.nextpush.account.AccountFactory.isConnected import org.unifiedpush.distributor.nextpush.account.AccountFactory
import org.unifiedpush.distributor.nextpush.distributor.* // ktlint-disable no-wildcard-imports import org.unifiedpush.distributor.nextpush.distributor.* // ktlint-disable no-wildcard-imports
import org.unifiedpush.distributor.nextpush.distributor.Distributor.checkToken import org.unifiedpush.distributor.nextpush.distributor.Distributor.checkToken
import org.unifiedpush.distributor.nextpush.distributor.Distributor.createApp import org.unifiedpush.distributor.nextpush.distributor.Distributor.createApp
@ -167,7 +167,7 @@ class RegisterBroadcastReceiver : BroadcastReceiver() {
private fun onRegisterNewToken(context: Context, connectorToken: String, application: String) { private fun onRegisterNewToken(context: Context, connectorToken: String, application: String) {
val appName = context.getApplicationName(application) ?: application val appName = context.getApplicationName(application) ?: application
when { when {
!isConnected(context) -> registrationFailedWithToast( AccountFactory.getAccount(context)?.connected != true -> registrationFailedWithToast(
context, context,
connectorToken, connectorToken,
application, application,