mirror of
https://github.com/nextcloud/talk-android
synced 2025-07-19 18:55:05 +01:00
Migrate AccountVerificationController from requery to room
Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
This commit is contained in:
parent
8d87d5486b
commit
6e05056b2e
@ -26,6 +26,7 @@ import android.content.pm.ActivityInfo
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.work.Data
|
import androidx.work.Data
|
||||||
import androidx.work.OneTimeWorkRequest
|
import androidx.work.OneTimeWorkRequest
|
||||||
@ -39,15 +40,16 @@ import com.nextcloud.talk.application.NextcloudTalkApplication
|
|||||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||||
import com.nextcloud.talk.controllers.base.NewBaseController
|
import com.nextcloud.talk.controllers.base.NewBaseController
|
||||||
import com.nextcloud.talk.controllers.util.viewBinding
|
import com.nextcloud.talk.controllers.util.viewBinding
|
||||||
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.databinding.ControllerAccountVerificationBinding
|
import com.nextcloud.talk.databinding.ControllerAccountVerificationBinding
|
||||||
import com.nextcloud.talk.events.EventStatus
|
import com.nextcloud.talk.events.EventStatus
|
||||||
import com.nextcloud.talk.jobs.CapabilitiesWorker
|
import com.nextcloud.talk.jobs.CapabilitiesWorker
|
||||||
import com.nextcloud.talk.jobs.PushRegistrationWorker
|
import com.nextcloud.talk.jobs.PushRegistrationWorker
|
||||||
import com.nextcloud.talk.jobs.SignalingSettingsWorker
|
import com.nextcloud.talk.jobs.SignalingSettingsWorker
|
||||||
import com.nextcloud.talk.models.database.UserEntity
|
|
||||||
import com.nextcloud.talk.models.json.capabilities.CapabilitiesOverall
|
import com.nextcloud.talk.models.json.capabilities.CapabilitiesOverall
|
||||||
import com.nextcloud.talk.models.json.generic.Status
|
import com.nextcloud.talk.models.json.generic.Status
|
||||||
import com.nextcloud.talk.models.json.userprofile.UserProfileOverall
|
import com.nextcloud.talk.models.json.userprofile.UserProfileOverall
|
||||||
|
import com.nextcloud.talk.users.UserManager
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
import com.nextcloud.talk.utils.ClosedInterfaceImpl
|
import com.nextcloud.talk.utils.ClosedInterfaceImpl
|
||||||
import com.nextcloud.talk.utils.UriUtils
|
import com.nextcloud.talk.utils.UriUtils
|
||||||
@ -57,9 +59,8 @@ import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_IS_ACCOUNT_IMPORT
|
|||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ORIGINAL_PROTOCOL
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ORIGINAL_PROTOCOL
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_TOKEN
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_TOKEN
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_USERNAME
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_USERNAME
|
||||||
import com.nextcloud.talk.utils.database.user.UserUtils
|
|
||||||
import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder
|
import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder
|
||||||
import io.reactivex.CompletableObserver
|
import io.reactivex.MaybeObserver
|
||||||
import io.reactivex.Observer
|
import io.reactivex.Observer
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.disposables.Disposable
|
import io.reactivex.disposables.Disposable
|
||||||
@ -68,7 +69,6 @@ import org.greenrobot.eventbus.EventBus
|
|||||||
import org.greenrobot.eventbus.Subscribe
|
import org.greenrobot.eventbus.Subscribe
|
||||||
import org.greenrobot.eventbus.ThreadMode
|
import org.greenrobot.eventbus.ThreadMode
|
||||||
import java.net.CookieManager
|
import java.net.CookieManager
|
||||||
import java.util.ArrayList
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
@AutoInjector(NextcloudTalkApplication::class)
|
||||||
@ -83,7 +83,7 @@ class AccountVerificationController(args: Bundle? = null) :
|
|||||||
lateinit var ncApi: NcApi
|
lateinit var ncApi: NcApi
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var userUtils: UserUtils
|
lateinit var userManager: UserManager
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var cookieManager: CookieManager
|
lateinit var cookieManager: CookieManager
|
||||||
@ -248,21 +248,30 @@ class AccountVerificationController(args: Bundle? = null) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun storeProfile(displayName: String?, userId: String) {
|
private fun storeProfile(displayName: String?, userId: String) {
|
||||||
userUtils.createOrUpdateUser(
|
userManager.storeProfile(
|
||||||
username, token,
|
username,
|
||||||
baseUrl, displayName, null, java.lang.Boolean.TRUE,
|
UserManager.UserAttributes(
|
||||||
userId, null, null,
|
id = null,
|
||||||
appPreferences!!.temporaryClientCertAlias, null
|
serverUrl = baseUrl,
|
||||||
|
currentUser = true,
|
||||||
|
userId = userId,
|
||||||
|
token = token,
|
||||||
|
displayName = displayName,
|
||||||
|
pushConfigurationState = null,
|
||||||
|
capabilities = null,
|
||||||
|
certificateAlias = appPreferences!!.temporaryClientCertAlias,
|
||||||
|
externalSignalingServer = null
|
||||||
|
)
|
||||||
)
|
)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.subscribe(object : Observer<UserEntity> {
|
.subscribe(object : MaybeObserver<User> {
|
||||||
override fun onSubscribe(d: Disposable) {
|
override fun onSubscribe(d: Disposable) {
|
||||||
disposables.add(d)
|
disposables.add(d)
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
override fun onNext(userEntity: UserEntity) {
|
override fun onSuccess(user: User) {
|
||||||
internalAccountId = userEntity.id
|
internalAccountId = user.id!!
|
||||||
if (ClosedInterfaceImpl().isGooglePlayServicesAvailable) {
|
if (ClosedInterfaceImpl().isGooglePlayServicesAvailable) {
|
||||||
registerForPush()
|
registerForPush()
|
||||||
} else {
|
} else {
|
||||||
@ -283,7 +292,7 @@ class AccountVerificationController(args: Bundle? = null) :
|
|||||||
"""
|
"""
|
||||||
${binding.progressText.text}
|
${binding.progressText.text}
|
||||||
""".trimIndent() +
|
""".trimIndent() +
|
||||||
resources!!.getString(R.string.nc_display_name_not_stored)
|
resources!!.getString(R.string.nc_display_name_not_stored)
|
||||||
abortVerification()
|
abortVerification()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -431,10 +440,11 @@ class AccountVerificationController(args: Bundle? = null) :
|
|||||||
|
|
||||||
private fun proceedWithLogin() {
|
private fun proceedWithLogin() {
|
||||||
cookieManager.cookieStore.removeAll()
|
cookieManager.cookieStore.removeAll()
|
||||||
userUtils.disableAllUsersWithoutId(internalAccountId)
|
val userDisabledCount = userManager.disableAllUsersWithoutId(internalAccountId).blockingGet()
|
||||||
|
Log.d(TAG, "Disabled $userDisabledCount users that had no id")
|
||||||
if (activity != null) {
|
if (activity != null) {
|
||||||
activity!!.runOnUiThread {
|
activity!!.runOnUiThread {
|
||||||
if (userUtils.users.size == 1) {
|
if (userManager.users.blockingGet().size == 1) {
|
||||||
router.setRoot(
|
router.setRoot(
|
||||||
RouterTransaction.with(ConversationsListController(Bundle()))
|
RouterTransaction.with(ConversationsListController(Bundle()))
|
||||||
.pushChangeHandler(HorizontalChangeHandler())
|
.pushChangeHandler(HorizontalChangeHandler())
|
||||||
@ -472,18 +482,10 @@ class AccountVerificationController(args: Bundle? = null) :
|
|||||||
private fun abortVerification() {
|
private fun abortVerification() {
|
||||||
if (!isAccountImport) {
|
if (!isAccountImport) {
|
||||||
if (internalAccountId != -1L) {
|
if (internalAccountId != -1L) {
|
||||||
userUtils.deleteUserWithId(internalAccountId).subscribe(object : CompletableObserver {
|
val count = userManager.deleteUser(internalAccountId)
|
||||||
override fun onSubscribe(d: Disposable) {
|
if (count > 0) {
|
||||||
// unused atm
|
|
||||||
}
|
|
||||||
override fun onComplete() {
|
|
||||||
activity?.runOnUiThread { Handler().postDelayed({ router.popToRoot() }, DELAY_IN_MILLIS) }
|
activity?.runOnUiThread { Handler().postDelayed({ router.popToRoot() }, DELAY_IN_MILLIS) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
|
||||||
// unused atm
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
activity?.runOnUiThread { Handler().postDelayed({ router.popToRoot() }, DELAY_IN_MILLIS) }
|
activity?.runOnUiThread { Handler().postDelayed({ router.popToRoot() }, DELAY_IN_MILLIS) }
|
||||||
}
|
}
|
||||||
@ -498,7 +500,7 @@ class AccountVerificationController(args: Bundle? = null) :
|
|||||||
router.popToRoot()
|
router.popToRoot()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (userUtils.anyUserExists()) {
|
if (userManager.users.blockingGet().isNotEmpty()) {
|
||||||
router.setRoot(
|
router.setRoot(
|
||||||
RouterTransaction.with(ConversationsListController(Bundle()))
|
RouterTransaction.with(ConversationsListController(Bundle()))
|
||||||
.pushChangeHandler(HorizontalChangeHandler())
|
.pushChangeHandler(HorizontalChangeHandler())
|
||||||
@ -518,7 +520,7 @@ class AccountVerificationController(args: Bundle? = null) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TAG = "AccountVerificationController"
|
const val TAG = "AccountVerification"
|
||||||
const val DELAY_IN_MILLIS: Long = 7500
|
const val DELAY_IN_MILLIS: Long = 7500
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ package com.nextcloud.talk.data.user
|
|||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Delete
|
||||||
import androidx.room.Insert
|
import androidx.room.Insert
|
||||||
import androidx.room.OnConflictStrategy
|
import androidx.room.OnConflictStrategy
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
@ -45,8 +46,8 @@ abstract class UsersDao {
|
|||||||
@Query("SELECT * FROM User where current = 1")
|
@Query("SELECT * FROM User where current = 1")
|
||||||
abstract fun getActiveUserSynchronously(): UserEntity?
|
abstract fun getActiveUserSynchronously(): UserEntity?
|
||||||
|
|
||||||
@Query("DELETE FROM User WHERE id = :id")
|
@Delete
|
||||||
abstract fun deleteUserWithId(id: Long)
|
abstract fun deleteUser(user: UserEntity): Int
|
||||||
|
|
||||||
@Update
|
@Update
|
||||||
abstract fun updateUser(user: UserEntity): Int
|
abstract fun updateUser(user: UserEntity): Int
|
||||||
|
@ -40,7 +40,7 @@ interface UsersRepository {
|
|||||||
fun updateUser(user: User): Int
|
fun updateUser(user: User): Int
|
||||||
fun insertUser(user: User): Long
|
fun insertUser(user: User): Long
|
||||||
fun setUserAsActiveWithId(id: Long): Single<Boolean>
|
fun setUserAsActiveWithId(id: Long): Single<Boolean>
|
||||||
fun deleteUserWithId(id: Long)
|
fun deleteUser(user: User): Int
|
||||||
fun setAnyUserAsActive(): Boolean
|
fun setAnyUserAsActive(): Boolean
|
||||||
fun markUserForDeletion(id: Long): Boolean
|
fun markUserForDeletion(id: Long): Boolean
|
||||||
}
|
}
|
||||||
|
@ -77,8 +77,8 @@ class UsersRepositoryImpl(private val usersDao: UsersDao) : UsersRepository {
|
|||||||
return Single.just(usersDao.setUserAsActiveWithId(id))
|
return Single.just(usersDao.setUserAsActiveWithId(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun deleteUserWithId(id: Long) {
|
override fun deleteUser(user: User): Int {
|
||||||
usersDao.deleteUserWithId(id)
|
return usersDao.deleteUser(UserMapper.toEntity(user))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setAnyUserAsActive(): Boolean {
|
override fun setAnyUserAsActive(): Boolean {
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
package com.nextcloud.talk.users
|
package com.nextcloud.talk.users
|
||||||
|
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
|
import android.util.Log
|
||||||
import com.bluelinelabs.logansquare.LoganSquare
|
import com.bluelinelabs.logansquare.LoganSquare
|
||||||
import com.nextcloud.talk.data.user.UsersRepository
|
import com.nextcloud.talk.data.user.UsersRepository
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
@ -31,6 +32,7 @@ import com.nextcloud.talk.models.json.push.PushConfigurationState
|
|||||||
import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
|
import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
|
import java.lang.Boolean.FALSE
|
||||||
import java.lang.Boolean.TRUE
|
import java.lang.Boolean.TRUE
|
||||||
|
|
||||||
@Suppress("TooManyFunctions")
|
@Suppress("TooManyFunctions")
|
||||||
@ -41,9 +43,10 @@ class UserManager internal constructor(private val userRepository: UsersReposito
|
|||||||
val usersScheduledForDeletion: Single<List<User>>
|
val usersScheduledForDeletion: Single<List<User>>
|
||||||
get() = userRepository.getUsersScheduledForDeletion()
|
get() = userRepository.getUsersScheduledForDeletion()
|
||||||
|
|
||||||
private fun setAnyUserAndSetAsActive(): Single<User> {
|
private fun getAnyUserAndSetAsActive(): Single<User> {
|
||||||
val results = userRepository.getUsersNotScheduledForDeletion()
|
val results = userRepository.getUsersNotScheduledForDeletion()
|
||||||
|
|
||||||
|
// TODO needs to return Empty in case no user was found (and set active)
|
||||||
return results.map { users ->
|
return results.map { users ->
|
||||||
users
|
users
|
||||||
.firstOrNull()
|
.firstOrNull()
|
||||||
@ -60,12 +63,8 @@ class UserManager internal constructor(private val userRepository: UsersReposito
|
|||||||
return userRepository.getActiveUser()
|
return userRepository.getActiveUser()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteUser(internalId: Long) {
|
fun deleteUser(internalId: Long): Int {
|
||||||
userRepository.deleteUserWithId(internalId)
|
return userRepository.deleteUser(userRepository.getUserWithId(internalId).blockingGet())
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteUserWithId(internalId: Long) {
|
|
||||||
userRepository.deleteUserWithId(internalId)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getUserById(userId: String): Maybe<User> {
|
fun getUserById(userId: String): Maybe<User> {
|
||||||
@ -93,7 +92,15 @@ class UserManager internal constructor(private val userRepository: UsersReposito
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun checkIfUserIsScheduledForDeletion(username: String, server: String): Maybe<Boolean> {
|
fun checkIfUserIsScheduledForDeletion(username: String, server: String): Maybe<Boolean> {
|
||||||
return userRepository.getUserWithUsernameAndServer(username, server).map { it.scheduledForDeletion }
|
return userRepository
|
||||||
|
.getUserWithUsernameAndServer(username, server)
|
||||||
|
.switchIfEmpty(Maybe.empty())
|
||||||
|
.map { user: User? ->
|
||||||
|
when (user) {
|
||||||
|
null -> FALSE
|
||||||
|
else -> user.scheduledForDeletion
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getUserWithInternalId(id: Long): Maybe<User> {
|
fun getUserWithInternalId(id: Long): Maybe<User> {
|
||||||
@ -101,10 +108,19 @@ class UserManager internal constructor(private val userRepository: UsersReposito
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getIfUserWithUsernameAndServer(username: String, server: String): Maybe<Boolean> {
|
fun getIfUserWithUsernameAndServer(username: String, server: String): Maybe<Boolean> {
|
||||||
return userRepository.getUserWithUsernameAndServer(username, server).map { TRUE }
|
return userRepository
|
||||||
|
.getUserWithUsernameAndServer(username, server)
|
||||||
|
.map { user: User? ->
|
||||||
|
when (user) {
|
||||||
|
null -> FALSE
|
||||||
|
else -> TRUE
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun scheduleUserForDeletionWithId(id: Long): Single<Boolean> {
|
fun scheduleUserForDeletionWithId(id: Long): Single<Boolean> {
|
||||||
|
// TODO needs to return false in case getAnyUserAndSetAsActive doesn't return a user
|
||||||
|
// or getUserWithId(id) doesn't return a user
|
||||||
return userRepository.getUserWithId(id).map { user ->
|
return userRepository.getUserWithId(id).map { user ->
|
||||||
user.scheduledForDeletion = true
|
user.scheduledForDeletion = true
|
||||||
user.current = false
|
user.current = false
|
||||||
@ -112,7 +128,7 @@ class UserManager internal constructor(private val userRepository: UsersReposito
|
|||||||
}
|
}
|
||||||
.toSingle()
|
.toSingle()
|
||||||
.flatMap {
|
.flatMap {
|
||||||
setAnyUserAndSetAsActive()
|
getAnyUserAndSetAsActive()
|
||||||
}.map { TRUE }
|
}.map { TRUE }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,19 +152,50 @@ class UserManager internal constructor(private val userRepository: UsersReposito
|
|||||||
return userRepository.setUserAsActiveWithId(user.id!!)
|
return userRepository.setUserAsActiveWithId(user.id!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun storeProfile(username: String?, userAttributes: UserAttributes): Maybe<User> {
|
||||||
|
val userMaybe: Maybe<User> = findUser(null, userAttributes)
|
||||||
|
|
||||||
|
return userMaybe
|
||||||
|
.map { user: User? ->
|
||||||
|
when (user) {
|
||||||
|
null -> createUser(
|
||||||
|
username,
|
||||||
|
userAttributes
|
||||||
|
)
|
||||||
|
else -> {
|
||||||
|
user.token = userAttributes.token
|
||||||
|
user.baseUrl = userAttributes.serverUrl
|
||||||
|
user.current = true
|
||||||
|
user.userId = userAttributes.userId
|
||||||
|
user.token = userAttributes.token
|
||||||
|
user.displayName = userAttributes.displayName
|
||||||
|
user.clientCertificate = userAttributes.certificateAlias
|
||||||
|
|
||||||
|
updateUserData(
|
||||||
|
user,
|
||||||
|
userAttributes
|
||||||
|
)
|
||||||
|
|
||||||
|
user
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.switchIfEmpty(Maybe.just(createUser(username, userAttributes)))
|
||||||
|
.map { user ->
|
||||||
|
userRepository.insertUser(user)
|
||||||
|
}
|
||||||
|
.flatMap { id ->
|
||||||
|
userRepository.getUserWithId(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Deprecated("Only available for migration, use updateExternalSignalingServer or create new methods")
|
@Deprecated("Only available for migration, use updateExternalSignalingServer or create new methods")
|
||||||
fun createOrUpdateUser(
|
fun createOrUpdateUser(
|
||||||
username: String?,
|
username: String?,
|
||||||
userAttributes: UserAttributes,
|
userAttributes: UserAttributes,
|
||||||
): Maybe<User> {
|
): Maybe<User> {
|
||||||
|
|
||||||
val userMaybe: Maybe<User> = if (userAttributes.id != null) {
|
val userMaybe: Maybe<User> = findUser(username, userAttributes)
|
||||||
userRepository.getUserWithId(userAttributes.id)
|
|
||||||
} else if (username != null && userAttributes.serverUrl != null) {
|
|
||||||
userRepository.getUserWithUsernameAndServer(username, userAttributes.serverUrl)
|
|
||||||
} else {
|
|
||||||
Maybe.empty()
|
|
||||||
}
|
|
||||||
|
|
||||||
return userMaybe
|
return userMaybe
|
||||||
.map { user: User? ->
|
.map { user: User? ->
|
||||||
@ -175,6 +222,16 @@ class UserManager internal constructor(private val userRepository: UsersReposito
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun findUser(username: String?, userAttributes: UserAttributes): Maybe<User> {
|
||||||
|
return if (userAttributes.id != null) {
|
||||||
|
userRepository.getUserWithId(userAttributes.id)
|
||||||
|
} else if (username != null && userAttributes.serverUrl != null) {
|
||||||
|
userRepository.getUserWithUsernameAndServer(username, userAttributes.serverUrl)
|
||||||
|
} else {
|
||||||
|
Maybe.empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun getUserWithUsernameAndServer(username: String, server: String): Maybe<User> {
|
fun getUserWithUsernameAndServer(username: String, server: String): Maybe<User> {
|
||||||
return userRepository.getUserWithUsernameAndServer(username, server)
|
return userRepository.getUserWithUsernameAndServer(username, server)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user