UserManager.kt 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /*
  2. * Nextcloud Talk application
  3. *
  4. * @author Mario Danic
  5. * @author Andy Scherzinger
  6. * Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
  7. * Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
  8. *
  9. * This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation, either version 3 of the License, or
  12. * at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. */
  22. package com.nextcloud.talk.users
  23. import android.text.TextUtils
  24. import com.bluelinelabs.logansquare.LoganSquare
  25. import com.nextcloud.talk.data.user.UsersRepository
  26. import com.nextcloud.talk.data.user.model.User
  27. import com.nextcloud.talk.models.ExternalSignalingServer
  28. import com.nextcloud.talk.models.json.capabilities.Capabilities
  29. import com.nextcloud.talk.models.json.push.PushConfigurationState
  30. import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
  31. import io.reactivex.Maybe
  32. import io.reactivex.Single
  33. import java.lang.Boolean.TRUE
  34. @Suppress("TooManyFunctions")
  35. class UserManager internal constructor(private val userRepository: UsersRepository) : CurrentUserProviderNew {
  36. val users: Single<List<User>>
  37. get() = userRepository.getUsers()
  38. val usersScheduledForDeletion: Single<List<User>>
  39. get() = userRepository.getUsersScheduledForDeletion()
  40. private fun setAnyUserAndSetAsActive(): Single<User> {
  41. val results = userRepository.getUsersNotScheduledForDeletion()
  42. return results.map { users ->
  43. users
  44. .firstOrNull()
  45. ?.apply {
  46. current = true
  47. }.also { user ->
  48. userRepository.updateUser(user!!)
  49. }
  50. }
  51. }
  52. override val currentUser: Maybe<User>
  53. get() {
  54. return userRepository.getActiveUser()
  55. }
  56. fun deleteUser(internalId: Long) {
  57. userRepository.deleteUserWithId(internalId)
  58. }
  59. fun deleteUserWithId(internalId: Long) {
  60. userRepository.deleteUserWithId(internalId)
  61. }
  62. fun getUserById(userId: String): Maybe<User> {
  63. return userRepository.getUserWithUserId(userId)
  64. }
  65. fun getUserWithId(id: Long): Maybe<User> {
  66. return userRepository.getUserWithId(id)
  67. }
  68. fun disableAllUsersWithoutId(userId: Long): Single<Int> {
  69. val results = userRepository.getUsersWithoutUserId(userId)
  70. return results.map { users ->
  71. var count = 0
  72. if (users.isNotEmpty()) {
  73. for (entity in users) {
  74. entity.current = false
  75. userRepository.updateUser(entity)
  76. count++
  77. }
  78. }
  79. count
  80. }
  81. }
  82. fun checkIfUserIsScheduledForDeletion(username: String, server: String): Maybe<Boolean> {
  83. return userRepository.getUserWithUsernameAndServer(username, server).map { it.scheduledForDeletion }
  84. }
  85. fun getUserWithInternalId(id: Long): Maybe<User> {
  86. return userRepository.getUserWithIdNotScheduledForDeletion(id)
  87. }
  88. fun getIfUserWithUsernameAndServer(username: String, server: String): Maybe<Boolean> {
  89. return userRepository.getUserWithUsernameAndServer(username, server).map { TRUE }
  90. }
  91. fun scheduleUserForDeletionWithId(id: Long): Single<Boolean> {
  92. return userRepository.getUserWithId(id).map { user ->
  93. user.scheduledForDeletion = true
  94. user.current = false
  95. userRepository.updateUser(user)
  96. }
  97. .toSingle()
  98. .flatMap {
  99. setAnyUserAndSetAsActive()
  100. }.map { TRUE }
  101. }
  102. fun updateExternalSignalingServer(id: Long, externalSignalingServer: ExternalSignalingServer): Single<Int> {
  103. return userRepository.getUserWithId(id).map { user ->
  104. user.externalSignalingServer = externalSignalingServer
  105. userRepository.updateUser(user)
  106. }.toSingle()
  107. }
  108. fun updateOrCreateUser(user: User): Single<Int> {
  109. return Single.fromCallable {
  110. when (user.id) {
  111. null -> userRepository.insertUser(user).toInt()
  112. else -> userRepository.updateUser(user)
  113. }
  114. }
  115. }
  116. fun setUserAsActive(user: User): Single<Boolean> {
  117. return userRepository.setUserAsActiveWithId(user.id!!)
  118. }
  119. @Deprecated("Only available for migration, use updateExternalSignalingServer or create new methods")
  120. fun createOrUpdateUser(
  121. username: String?,
  122. userAttributes: UserAttributes,
  123. ): Maybe<User> {
  124. val userMaybe: Maybe<User> = if (userAttributes.id != null) {
  125. userRepository.getUserWithId(userAttributes.id)
  126. } else if (username != null && userAttributes.serverUrl != null) {
  127. userRepository.getUserWithUsernameAndServer(username, userAttributes.serverUrl)
  128. } else {
  129. Maybe.empty()
  130. }
  131. return userMaybe
  132. .map { user: User? ->
  133. when (user) {
  134. null -> createUser(
  135. username,
  136. userAttributes
  137. )
  138. else -> {
  139. updateUserData(
  140. user,
  141. userAttributes
  142. )
  143. user
  144. }
  145. }
  146. }
  147. .switchIfEmpty(Maybe.just(createUser(username, userAttributes)))
  148. .map { user ->
  149. userRepository.insertUser(user)
  150. }
  151. .flatMap { id ->
  152. userRepository.getUserWithId(id)
  153. }
  154. }
  155. fun getUserWithUsernameAndServer(username: String, server: String): Maybe<User> {
  156. return userRepository.getUserWithUsernameAndServer(username, server)
  157. }
  158. private fun updateUserData(user: User, userAttributes: UserAttributes) {
  159. user.userId = userAttributes.userId
  160. user.token = userAttributes.token
  161. user.displayName = userAttributes.displayName
  162. if (userAttributes.pushConfigurationState != null) {
  163. user.pushConfigurationState = LoganSquare
  164. .parse(userAttributes.pushConfigurationState, PushConfigurationState::class.java)
  165. }
  166. if (userAttributes.capabilities != null) {
  167. user.capabilities = LoganSquare
  168. .parse(userAttributes.capabilities, Capabilities::class.java)
  169. }
  170. user.clientCertificate = userAttributes.certificateAlias
  171. if (userAttributes.externalSignalingServer != null) {
  172. user.externalSignalingServer = LoganSquare
  173. .parse(userAttributes.externalSignalingServer, ExternalSignalingServer::class.java)
  174. }
  175. user.current = userAttributes.currentUser == true
  176. }
  177. private fun createUser(username: String?, userAttributes: UserAttributes): User {
  178. val user = User()
  179. user.baseUrl = userAttributes.serverUrl
  180. user.username = username
  181. user.token = userAttributes.token
  182. if (!TextUtils.isEmpty(userAttributes.displayName)) {
  183. user.displayName = userAttributes.displayName
  184. }
  185. if (userAttributes.pushConfigurationState != null) {
  186. user.pushConfigurationState = LoganSquare
  187. .parse(userAttributes.pushConfigurationState, PushConfigurationState::class.java)
  188. }
  189. if (!TextUtils.isEmpty(userAttributes.userId)) {
  190. user.userId = userAttributes.userId
  191. }
  192. if (!TextUtils.isEmpty(userAttributes.capabilities)) {
  193. user.capabilities = LoganSquare.parse(userAttributes.capabilities, Capabilities::class.java)
  194. }
  195. if (!TextUtils.isEmpty(userAttributes.certificateAlias)) {
  196. user.clientCertificate = userAttributes.certificateAlias
  197. }
  198. if (!TextUtils.isEmpty(userAttributes.externalSignalingServer)) {
  199. user.externalSignalingServer = LoganSquare
  200. .parse(userAttributes.externalSignalingServer, ExternalSignalingServer::class.java)
  201. }
  202. user.current = true
  203. return user
  204. }
  205. companion object {
  206. const val TAG = "UserManager"
  207. }
  208. data class UserAttributes(
  209. val id: Long?,
  210. val serverUrl: String?,
  211. val currentUser: Boolean?,
  212. val userId: String?,
  213. val token: String?,
  214. val displayName: String?,
  215. val pushConfigurationState: String?,
  216. val capabilities: String?,
  217. val certificateAlias: String?,
  218. val externalSignalingServer: String?
  219. )
  220. }