mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-21 04:29:45 +01:00
Notifications & various other bug fixes
This commit is contained in:
parent
ee7cd4d60b
commit
5ddd3f8422
@ -333,4 +333,5 @@ dependencies {
|
|||||||
findbugsPlugins 'com.mebigfatguy.fb-contrib:fb-contrib:7.4.7'
|
findbugsPlugins 'com.mebigfatguy.fb-contrib:fb-contrib:7.4.7'
|
||||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'
|
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'
|
||||||
implementation 'com.github.Kennyc1012:BottomSheet:2.4.1'
|
implementation 'com.github.Kennyc1012:BottomSheet:2.4.1'
|
||||||
|
implementation 'com.google.firebase:firebase-messaging:20.1.0'
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "androidx.work:work-gcm:2.3.0-alpha02"
|
implementation "androidx.work:work-gcm:2.3.0-beta01"
|
||||||
implementation "com.google.firebase:firebase-messaging:20.0.0"
|
implementation "com.google.firebase:firebase-messaging:20.1.0"
|
||||||
}
|
}
|
||||||
|
@ -20,10 +20,8 @@
|
|||||||
package com.nextcloud.talk.services.firebase
|
package com.nextcloud.talk.services.firebase
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import autodagger.AutoInjector
|
|
||||||
import com.google.firebase.messaging.FirebaseMessagingService
|
import com.google.firebase.messaging.FirebaseMessagingService
|
||||||
import com.google.firebase.messaging.RemoteMessage
|
import com.google.firebase.messaging.RemoteMessage
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
|
||||||
import com.nextcloud.talk.jobs.NotificationWorker
|
import com.nextcloud.talk.jobs.NotificationWorker
|
||||||
import com.nextcloud.talk.jobs.PushRegistrationWorker
|
import com.nextcloud.talk.jobs.PushRegistrationWorker
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys
|
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||||
@ -31,33 +29,31 @@ import androidx.work.Data
|
|||||||
import androidx.work.OneTimeWorkRequest
|
import androidx.work.OneTimeWorkRequest
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import com.nextcloud.talk.utils.preferences.AppPreferences
|
import com.nextcloud.talk.utils.preferences.AppPreferences
|
||||||
|
import org.koin.core.KoinComponent
|
||||||
|
import org.koin.core.inject
|
||||||
|
|
||||||
class MagicFirebaseMessagingService : FirebaseMessagingService(), KoinComponent {
|
class MagicFirebaseMessagingService : FirebaseMessagingService(), KoinComponent {
|
||||||
val appPreferences: AppPreferences by inject()
|
val appPreferences: AppPreferences by inject()
|
||||||
|
|
||||||
@Override
|
override fun onNewToken(token: String) {
|
||||||
fun onNewToken(token: String?) {
|
|
||||||
super.onNewToken(token)
|
super.onNewToken(token)
|
||||||
appPreferences.setPushToken(token)
|
appPreferences.pushToken = token
|
||||||
val pushRegistrationWork: OneTimeWorkRequest = Builder(PushRegistrationWorker::class.java).build()
|
val pushRegistrationWork: OneTimeWorkRequest = OneTimeWorkRequest.Builder(PushRegistrationWorker::class.java).build()
|
||||||
WorkManager.getInstance().enqueue(pushRegistrationWork)
|
WorkManager.getInstance().enqueue(pushRegistrationWork)
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("LongLogTag")
|
@SuppressLint("LongLogTag")
|
||||||
@Override
|
override fun onMessageReceived(remoteMessage: RemoteMessage) {
|
||||||
fun onMessageReceived(remoteMessage: RemoteMessage?) {
|
remoteMessage.data.let {
|
||||||
if (remoteMessage == null) {
|
val messageData: Data = Data.Builder()
|
||||||
return
|
.putString(BundleKeys.KEY_NOTIFICATION_SUBJECT, it["subject"])
|
||||||
}
|
.putString(BundleKeys.KEY_NOTIFICATION_SIGNATURE, it["signature"])
|
||||||
if (remoteMessage.getData() != null) {
|
|
||||||
val messageData: Data = Builder()
|
|
||||||
.putString(BundleKeys.INSTANCE.getKEY_NOTIFICATION_SUBJECT(), remoteMessage.getData().get("subject"))
|
|
||||||
.putString(BundleKeys.INSTANCE.getKEY_NOTIFICATION_SIGNATURE(), remoteMessage.getData().get("signature"))
|
|
||||||
.build()
|
.build()
|
||||||
val pushNotificationWork: OneTimeWorkRequest = Builder(NotificationWorker::class.java)
|
val pushNotificationWork: OneTimeWorkRequest = OneTimeWorkRequest.Builder(NotificationWorker::class.java)
|
||||||
.setInputData(messageData)
|
.setInputData(messageData)
|
||||||
.build()
|
.build()
|
||||||
WorkManager.getInstance().enqueue(pushNotificationWork)
|
WorkManager.getInstance().enqueue(pushNotificationWork)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -162,8 +162,6 @@ class NextcloudTalkApplication : Application(), LifecycleObserver {
|
|||||||
12, TimeUnit.HOURS
|
12, TimeUnit.HOURS
|
||||||
)
|
)
|
||||||
.build()
|
.build()
|
||||||
val capabilitiesUpdateWork = OneTimeWorkRequest.Builder(CapabilitiesWorker::class.java)
|
|
||||||
.build()
|
|
||||||
val signalingSettingsWork = OneTimeWorkRequest.Builder(SignalingSettingsWorker::class.java)
|
val signalingSettingsWork = OneTimeWorkRequest.Builder(SignalingSettingsWorker::class.java)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
@ -171,8 +169,6 @@ class NextcloudTalkApplication : Application(), LifecycleObserver {
|
|||||||
.enqueue(pushRegistrationWork)
|
.enqueue(pushRegistrationWork)
|
||||||
WorkManager.getInstance()
|
WorkManager.getInstance()
|
||||||
.enqueue(accountRemovalWork)
|
.enqueue(accountRemovalWork)
|
||||||
WorkManager.getInstance()
|
|
||||||
.enqueue(capabilitiesUpdateWork)
|
|
||||||
WorkManager.getInstance()
|
WorkManager.getInstance()
|
||||||
.enqueue(signalingSettingsWork)
|
.enqueue(signalingSettingsWork)
|
||||||
WorkManager.getInstance()
|
WorkManager.getInstance()
|
||||||
|
@ -1007,22 +1007,12 @@ class CallController(args: Bundle) : BaseController() {
|
|||||||
|
|
||||||
override fun onNext(capabilitiesOverall: CapabilitiesOverall) {
|
override fun onNext(capabilitiesOverall: CapabilitiesOverall) {
|
||||||
isMultiSession = capabilitiesOverall.ocs.data
|
isMultiSession = capabilitiesOverall.ocs.data
|
||||||
.capabilities != null && capabilitiesOverall.ocs.data
|
|
||||||
.capabilities.spreedCapability != null &&
|
|
||||||
capabilitiesOverall.ocs.data
|
|
||||||
.capabilities.spreedCapability
|
.capabilities.spreedCapability
|
||||||
.features != null && capabilitiesOverall.ocs.data
|
?.features?.contains("multi-room-users") == true
|
||||||
.capabilities.spreedCapability
|
|
||||||
.features.contains("multi-room-users")
|
|
||||||
|
|
||||||
needsPing = !(capabilitiesOverall.ocs.data
|
needsPing = capabilitiesOverall.ocs.data
|
||||||
.capabilities != null && capabilitiesOverall.ocs.data
|
|
||||||
.capabilities.spreedCapability != null &&
|
|
||||||
capabilitiesOverall.ocs.data
|
|
||||||
.capabilities.spreedCapability
|
.capabilities.spreedCapability
|
||||||
.features != null && capabilitiesOverall.ocs.data
|
?.features?.contains("no-ping") == false
|
||||||
.capabilities.spreedCapability
|
|
||||||
.features.contains("no-ping"))
|
|
||||||
|
|
||||||
if (!hasExternalSignalingServer) {
|
if (!hasExternalSignalingServer) {
|
||||||
joinRoomAndCall()
|
joinRoomAndCall()
|
||||||
|
@ -59,6 +59,8 @@ import com.nextcloud.talk.models.json.conversations.Conversation
|
|||||||
import com.nextcloud.talk.models.json.conversations.RoomsOverall
|
import com.nextcloud.talk.models.json.conversations.RoomsOverall
|
||||||
import com.nextcloud.talk.models.json.participants.Participant
|
import com.nextcloud.talk.models.json.participants.Participant
|
||||||
import com.nextcloud.talk.models.json.participants.ParticipantsOverall
|
import com.nextcloud.talk.models.json.participants.ParticipantsOverall
|
||||||
|
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
||||||
|
import com.nextcloud.talk.newarch.local.models.getCredentials
|
||||||
import com.nextcloud.talk.newarch.utils.getCredentials
|
import com.nextcloud.talk.newarch.utils.getCredentials
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
import com.nextcloud.talk.utils.DoNotDisturbUtils
|
import com.nextcloud.talk.utils.DoNotDisturbUtils
|
||||||
@ -108,7 +110,7 @@ class CallNotificationController(private val originalBundle: Bundle) : BaseContr
|
|||||||
@BindView(R.id.incomingTextRelativeLayout)
|
@BindView(R.id.incomingTextRelativeLayout)
|
||||||
var incomingTextRelativeLayout: RelativeLayout? = null
|
var incomingTextRelativeLayout: RelativeLayout? = null
|
||||||
private val roomId: String
|
private val roomId: String
|
||||||
private val userBeingCalled: UserEntity?
|
private val userBeingCalled: UserNgEntity?
|
||||||
private val credentials: String?
|
private val credentials: String?
|
||||||
private var currentConversation: Conversation? = null
|
private var currentConversation: Conversation? = null
|
||||||
private var mediaPlayer: MediaPlayer? = null
|
private var mediaPlayer: MediaPlayer? = null
|
||||||
@ -282,7 +284,7 @@ class CallNotificationController(private val originalBundle: Bundle) : BaseContr
|
|||||||
|
|
||||||
var importantConversation = false
|
var importantConversation = false
|
||||||
val arbitraryStorageEntity: ArbitraryStorageEntity? = arbitraryStorageUtils.getStorageSetting(
|
val arbitraryStorageEntity: ArbitraryStorageEntity? = arbitraryStorageUtils.getStorageSetting(
|
||||||
userBeingCalled!!.id,
|
userBeingCalled!!.id!!,
|
||||||
"important_conversation",
|
"important_conversation",
|
||||||
currentConversation!!.token
|
currentConversation!!.token
|
||||||
)
|
)
|
||||||
|
@ -20,29 +20,150 @@
|
|||||||
|
|
||||||
package com.nextcloud.talk.jobs
|
package com.nextcloud.talk.jobs
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Application
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.text.TextUtils
|
||||||
|
import android.util.Base64
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.work.CoroutineWorker
|
||||||
import androidx.work.ListenableWorker.Result
|
import androidx.work.ListenableWorker.Result
|
||||||
import androidx.work.Worker
|
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
|
import com.nextcloud.talk.R
|
||||||
|
import com.nextcloud.talk.api.NcApi
|
||||||
|
import com.nextcloud.talk.events.EventStatus
|
||||||
|
import com.nextcloud.talk.models.json.push.PushConfigurationState
|
||||||
|
import com.nextcloud.talk.models.json.push.PushRegistrationOverall
|
||||||
import com.nextcloud.talk.newarch.domain.repository.offline.UsersRepository
|
import com.nextcloud.talk.newarch.domain.repository.offline.UsersRepository
|
||||||
|
import com.nextcloud.talk.newarch.local.models.getCredentials
|
||||||
|
import com.nextcloud.talk.newarch.utils.hashWithAlgorithm
|
||||||
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
import com.nextcloud.talk.utils.PushUtils
|
import com.nextcloud.talk.utils.PushUtils
|
||||||
|
import com.nextcloud.talk.utils.preferences.AppPreferences
|
||||||
|
import io.reactivex.Observer
|
||||||
|
import io.reactivex.disposables.Disposable
|
||||||
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
import org.koin.core.KoinComponent
|
import org.koin.core.KoinComponent
|
||||||
import org.koin.core.inject
|
import org.koin.core.inject
|
||||||
|
import java.security.PublicKey
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
class PushRegistrationWorker(
|
class PushRegistrationWorker(
|
||||||
context: Context,
|
context: Context,
|
||||||
workerParams: WorkerParameters
|
workerParams: WorkerParameters
|
||||||
) : Worker(context, workerParams), KoinComponent {
|
) : CoroutineWorker(context, workerParams), KoinComponent {
|
||||||
|
|
||||||
val usersRepository: UsersRepository by inject()
|
val usersRepository: UsersRepository by inject()
|
||||||
|
val eventBus: EventBus by inject()
|
||||||
|
val appPreferences: AppPreferences by inject()
|
||||||
|
val application: Application by inject()
|
||||||
|
val ncApi: NcApi by inject()
|
||||||
|
|
||||||
override fun doWork(): Result {
|
override suspend fun doWork(): Result {
|
||||||
val pushUtils = PushUtils(usersRepository)
|
val pushUtils = PushUtils(usersRepository)
|
||||||
pushUtils.generateRsa2048KeyPair()
|
pushUtils.generateRsa2048KeyPair()
|
||||||
pushUtils.pushRegistrationToServer()
|
pushRegistrationToServer()
|
||||||
return Result.success()
|
return Result.success()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun pushRegistrationToServer() {
|
||||||
|
val token: String = appPreferences.pushToken
|
||||||
|
if (!TextUtils.isEmpty(token)) {
|
||||||
|
var credentials: String
|
||||||
|
val pushUtils = PushUtils(usersRepository)
|
||||||
|
val pushTokenHash = token.hashWithAlgorithm("SHA-512")
|
||||||
|
val devicePublicKey = pushUtils.readKeyFromFile(true) as PublicKey?
|
||||||
|
if (devicePublicKey != null) {
|
||||||
|
val publicKeyBytes: ByteArray? =
|
||||||
|
Base64.encode(devicePublicKey.encoded, Base64.NO_WRAP)
|
||||||
|
var publicKey = String(publicKeyBytes!!)
|
||||||
|
publicKey = publicKey.replace("(.{64})".toRegex(), "$1\n")
|
||||||
|
publicKey = "-----BEGIN PUBLIC KEY-----\n$publicKey\n-----END PUBLIC KEY-----\n"
|
||||||
|
val users = usersRepository.getUsers()
|
||||||
|
if (users.count() > 0) {
|
||||||
|
var accountPushData: PushConfigurationState?
|
||||||
|
for (userEntityObject in users) {
|
||||||
|
accountPushData = userEntityObject.pushConfiguration
|
||||||
|
if (accountPushData == null || accountPushData.pushToken != token) {
|
||||||
|
val queryMap: MutableMap<String, String> =
|
||||||
|
HashMap()
|
||||||
|
queryMap["format"] = "json"
|
||||||
|
queryMap["pushTokenHash"] = pushTokenHash
|
||||||
|
queryMap["devicePublicKey"] = publicKey
|
||||||
|
queryMap["proxyServer"] = application.getString(R.string.nc_push_server_url)
|
||||||
|
credentials = userEntityObject.getCredentials()
|
||||||
|
ncApi.registerDeviceForNotificationsWithNextcloud(
|
||||||
|
credentials,
|
||||||
|
ApiUtils.getUrlNextcloudPush(userEntityObject.baseUrl),
|
||||||
|
queryMap
|
||||||
|
)
|
||||||
|
.blockingSubscribe(object : Observer<PushRegistrationOverall> {
|
||||||
|
override fun onSubscribe(d: Disposable) {}
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
|
override fun onNext(pushRegistrationOverall: PushRegistrationOverall) {
|
||||||
|
val proxyMap: MutableMap<String, String> =
|
||||||
|
HashMap()
|
||||||
|
proxyMap["pushToken"] = token
|
||||||
|
proxyMap["deviceIdentifier"] =
|
||||||
|
pushRegistrationOverall.ocs.data.deviceIdentifier
|
||||||
|
proxyMap["deviceIdentifierSignature"] = pushRegistrationOverall.ocs
|
||||||
|
.data.signature
|
||||||
|
proxyMap["userPublicKey"] = pushRegistrationOverall.ocs
|
||||||
|
.data.publicKey
|
||||||
|
ncApi.registerDeviceForNotificationsWithProxy(
|
||||||
|
ApiUtils.getUrlPushProxy(), proxyMap
|
||||||
|
).subscribe({
|
||||||
|
val pushConfigurationState = PushConfigurationState()
|
||||||
|
pushConfigurationState.pushToken = token
|
||||||
|
pushConfigurationState.deviceIdentifier = proxyMap["deviceIdentifier"]
|
||||||
|
pushConfigurationState.deviceIdentifierSignature = proxyMap["deviceIdentifierSignature"]
|
||||||
|
pushConfigurationState.userPublicKey = proxyMap["userPublicKey"]
|
||||||
|
pushConfigurationState.usesRegularPass = false
|
||||||
|
GlobalScope.launch {
|
||||||
|
val user = usersRepository.getUserWithId(userEntityObject.id!!)
|
||||||
|
user.pushConfiguration = pushConfigurationState
|
||||||
|
usersRepository.updateUser(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
eventBus.post(
|
||||||
|
EventStatus(
|
||||||
|
userEntityObject.id!!,
|
||||||
|
EventStatus.EventType.PUSH_REGISTRATION,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}, {
|
||||||
|
eventBus.post(
|
||||||
|
EventStatus(
|
||||||
|
userEntityObject.id!!,
|
||||||
|
EventStatus.EventType.PUSH_REGISTRATION,
|
||||||
|
false))
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(e: Throwable) {
|
||||||
|
eventBus.post(
|
||||||
|
EventStatus(
|
||||||
|
userEntityObject.id!!,
|
||||||
|
EventStatus.EventType.PUSH_REGISTRATION,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onComplete() {}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TAG = "PushRegistrationWorker"
|
const val TAG = "PushRegistrationWorker"
|
||||||
}
|
}
|
||||||
|
@ -36,8 +36,6 @@ data class ExternalSignalingServer(
|
|||||||
var externalSignalingServer: String? = null,
|
var externalSignalingServer: String? = null,
|
||||||
@JsonField(name = ["externalSignalingTicket"])
|
@JsonField(name = ["externalSignalingTicket"])
|
||||||
var externalSignalingTicket: String? = null
|
var externalSignalingTicket: String? = null
|
||||||
|
|
||||||
|
|
||||||
) : Parcelable {
|
) : Parcelable {
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
|
@ -1,64 +0,0 @@
|
|||||||
/*
|
|
||||||
* Nextcloud Talk application
|
|
||||||
*
|
|
||||||
* @author Mario Danic
|
|
||||||
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.nextcloud.talk.models.json.capabilities;
|
|
||||||
|
|
||||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
|
||||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
|
||||||
|
|
||||||
import org.parceler.Parcel;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Parcel
|
|
||||||
@Data
|
|
||||||
@JsonObject
|
|
||||||
public class Capabilities {
|
|
||||||
@JsonField(name = "spreed")
|
|
||||||
public SpreedCapability spreedCapability;
|
|
||||||
|
|
||||||
@JsonField(name = "notifications")
|
|
||||||
public NotificationsCapability notificationsCapability;
|
|
||||||
|
|
||||||
@JsonField(name = "theming")
|
|
||||||
public ThemingCapability themingCapability;
|
|
||||||
|
|
||||||
/*@JsonField(name = "external")
|
|
||||||
public HashMap<String, List<String>> externalCapability;*/
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (!(o instanceof Capabilities)) return false;
|
|
||||||
Capabilities that = (Capabilities) o;
|
|
||||||
return Objects.equals(spreedCapability, that.spreedCapability) &&
|
|
||||||
Objects.equals(notificationsCapability, that.notificationsCapability) &&
|
|
||||||
Objects.equals(themingCapability, that.themingCapability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(spreedCapability, notificationsCapability, themingCapability);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Nextcloud Talk application
|
||||||
|
*
|
||||||
|
* @author Mario Danic
|
||||||
|
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.nextcloud.talk.models.json.capabilities
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import com.bluelinelabs.logansquare.annotation.JsonField
|
||||||
|
import com.bluelinelabs.logansquare.annotation.JsonObject
|
||||||
|
import kotlinx.android.parcel.Parcelize
|
||||||
|
import lombok.Data
|
||||||
|
import org.parceler.Parcel
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Parcel
|
||||||
|
@JsonObject
|
||||||
|
@Parcelize
|
||||||
|
data class Capabilities(
|
||||||
|
@JsonField(name = ["spreed"])
|
||||||
|
var spreedCapability: SpreedCapability? = null,
|
||||||
|
@JsonField(name = ["notifications"])
|
||||||
|
var notificationsCapability: NotificationsCapability? = null,
|
||||||
|
@JsonField(name = ["theming"])
|
||||||
|
var themingCapability: ThemingCapability? = null
|
||||||
|
): Parcelable {
|
||||||
|
override fun equals(o: Any?): Boolean {
|
||||||
|
if (this === o) return true
|
||||||
|
if (o !is Capabilities) return false
|
||||||
|
return (spreedCapability == o.spreedCapability &&
|
||||||
|
notificationsCapability == o.notificationsCapability &&
|
||||||
|
themingCapability == o.themingCapability)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return Objects.hash(spreedCapability, notificationsCapability, themingCapability)
|
||||||
|
}
|
||||||
|
}
|
@ -17,36 +17,32 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
package com.nextcloud.talk.models.json.capabilities
|
||||||
|
|
||||||
package com.nextcloud.talk.models.json.capabilities;
|
import android.os.Parcelable
|
||||||
|
import com.bluelinelabs.logansquare.annotation.JsonField
|
||||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
import com.bluelinelabs.logansquare.annotation.JsonObject
|
||||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
import kotlinx.android.parcel.Parcelize
|
||||||
|
import lombok.Data
|
||||||
import org.parceler.Parcel;
|
import org.parceler.Parcel
|
||||||
|
import java.util.*
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Parcel
|
@Parcel
|
||||||
@Data
|
@Data
|
||||||
@JsonObject
|
@JsonObject
|
||||||
public class NotificationsCapability {
|
@Parcelize
|
||||||
@JsonField(name = "ocs-endpoints")
|
data class NotificationsCapability(
|
||||||
public List<String> features;
|
@JsonField(name = ["ocs-endpoints"])
|
||||||
|
var features: List<String>? = null
|
||||||
|
): Parcelable {
|
||||||
|
|
||||||
@Override
|
override fun equals(o: Any?): Boolean {
|
||||||
public boolean equals(Object o) {
|
if (this === o) return true
|
||||||
if (this == o) return true;
|
if (o !is NotificationsCapability) return false
|
||||||
if (!(o instanceof NotificationsCapability)) return false;
|
return features == o.features
|
||||||
NotificationsCapability that = (NotificationsCapability) o;
|
|
||||||
return Objects.equals(features, that.features);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun hashCode(): Int {
|
||||||
public int hashCode() {
|
return Objects.hash(features)
|
||||||
return Objects.hash(features);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,57 +0,0 @@
|
|||||||
/*
|
|
||||||
* Nextcloud Talk application
|
|
||||||
*
|
|
||||||
* @author Mario Danic
|
|
||||||
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.nextcloud.talk.models.json.capabilities;
|
|
||||||
|
|
||||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
|
||||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
|
||||||
|
|
||||||
import org.parceler.Parcel;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Parcel
|
|
||||||
@Data
|
|
||||||
@JsonObject
|
|
||||||
public class SpreedCapability {
|
|
||||||
@JsonField(name = "features")
|
|
||||||
public List<String> features;
|
|
||||||
|
|
||||||
@JsonField(name = "config")
|
|
||||||
public HashMap<String, HashMap<String, String>> config;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (!(o instanceof SpreedCapability)) return false;
|
|
||||||
SpreedCapability that = (SpreedCapability) o;
|
|
||||||
return Objects.equals(features, that.features) &&
|
|
||||||
Objects.equals(config, that.config);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(features, config);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Nextcloud Talk application
|
||||||
|
*
|
||||||
|
* @author Mario Danic
|
||||||
|
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.nextcloud.talk.models.json.capabilities
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import com.bluelinelabs.logansquare.annotation.JsonField
|
||||||
|
import com.bluelinelabs.logansquare.annotation.JsonObject
|
||||||
|
import kotlinx.android.parcel.Parcelize
|
||||||
|
import lombok.Data
|
||||||
|
import org.parceler.Parcel
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
@Parcel
|
||||||
|
@Data
|
||||||
|
@JsonObject
|
||||||
|
@Parcelize
|
||||||
|
data class SpreedCapability(
|
||||||
|
@JsonField(name = ["features"])
|
||||||
|
var features: List<String>? = null,
|
||||||
|
@JsonField(name = ["config"])
|
||||||
|
var config: HashMap<String, HashMap<String, String>>? = null
|
||||||
|
): Parcelable {
|
||||||
|
|
||||||
|
override fun equals(o: Any?): Boolean {
|
||||||
|
if (this === o) return true
|
||||||
|
if (o !is SpreedCapability) return false
|
||||||
|
val that = o
|
||||||
|
return features == that.features &&
|
||||||
|
config == that.config
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return Objects.hash(features, config)
|
||||||
|
}
|
||||||
|
}
|
@ -1,87 +0,0 @@
|
|||||||
/*
|
|
||||||
* Nextcloud Talk application
|
|
||||||
*
|
|
||||||
* @author Mario Danic
|
|
||||||
* Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.nextcloud.talk.models.json.capabilities;
|
|
||||||
|
|
||||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
|
||||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
|
||||||
|
|
||||||
import org.parceler.Parcel;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Parcel
|
|
||||||
@Data
|
|
||||||
@JsonObject
|
|
||||||
class ThemingCapability {
|
|
||||||
@JsonField(name = "name")
|
|
||||||
String name;
|
|
||||||
|
|
||||||
@JsonField(name = "url")
|
|
||||||
String url;
|
|
||||||
|
|
||||||
@JsonField(name = "slogan")
|
|
||||||
String slogan;
|
|
||||||
|
|
||||||
@JsonField(name = "color")
|
|
||||||
String color;
|
|
||||||
|
|
||||||
@JsonField(name = "color-text")
|
|
||||||
String colorText;
|
|
||||||
|
|
||||||
@JsonField(name = "color-element")
|
|
||||||
String colorElement;
|
|
||||||
|
|
||||||
@JsonField(name = "logo")
|
|
||||||
String logo;
|
|
||||||
|
|
||||||
@JsonField(name = "background")
|
|
||||||
String background;
|
|
||||||
|
|
||||||
@JsonField(name = "background-plain")
|
|
||||||
boolean backgroundPlain;
|
|
||||||
|
|
||||||
@JsonField(name = "background-default")
|
|
||||||
boolean backgroundDefault;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (!(o instanceof ThemingCapability)) return false;
|
|
||||||
ThemingCapability that = (ThemingCapability) o;
|
|
||||||
return backgroundPlain == that.backgroundPlain &&
|
|
||||||
backgroundDefault == that.backgroundDefault &&
|
|
||||||
Objects.equals(name, that.name) &&
|
|
||||||
Objects.equals(url, that.url) &&
|
|
||||||
Objects.equals(slogan, that.slogan) &&
|
|
||||||
Objects.equals(color, that.color) &&
|
|
||||||
Objects.equals(colorText, that.colorText) &&
|
|
||||||
Objects.equals(colorElement, that.colorElement) &&
|
|
||||||
Objects.equals(logo, that.logo) &&
|
|
||||||
Objects.equals(background, that.background);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(name, url, slogan, color, colorText, colorElement, logo, background, backgroundPlain, backgroundDefault);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Nextcloud Talk application
|
||||||
|
*
|
||||||
|
* @author Mario Danic
|
||||||
|
* Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.nextcloud.talk.models.json.capabilities
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import com.bluelinelabs.logansquare.annotation.JsonField
|
||||||
|
import com.bluelinelabs.logansquare.annotation.JsonObject
|
||||||
|
import kotlinx.android.parcel.Parcelize
|
||||||
|
import lombok.Data
|
||||||
|
import org.parceler.Parcel
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
@Parcel
|
||||||
|
@Data
|
||||||
|
@JsonObject
|
||||||
|
@Parcelize
|
||||||
|
data class ThemingCapability(
|
||||||
|
@JsonField(name = ["name"])
|
||||||
|
var name: String? = null,
|
||||||
|
@JsonField(name = ["url"])
|
||||||
|
var url: String? = null,
|
||||||
|
@JsonField(name = ["slogan"])
|
||||||
|
var slogan: String? = null,
|
||||||
|
@JsonField(name = ["color"])
|
||||||
|
var color: String? = null,
|
||||||
|
@JsonField(name = ["color-text"])
|
||||||
|
var colorText: String? = null,
|
||||||
|
@JsonField(name = ["color-element"])
|
||||||
|
var colorElement: String? = null,
|
||||||
|
@JsonField(name = ["logo"])
|
||||||
|
var logo: String? = null,
|
||||||
|
@JsonField(name = ["background"])
|
||||||
|
var background: String? = null,
|
||||||
|
@JsonField(name = ["background-plain"])
|
||||||
|
var backgroundPlain: Boolean = false,
|
||||||
|
@JsonField(name = ["background-default"])
|
||||||
|
var backgroundDefault: Boolean = false
|
||||||
|
): Parcelable {
|
||||||
|
|
||||||
|
override fun equals(o: Any?): Boolean {
|
||||||
|
if (this === o) return true
|
||||||
|
if (o !is ThemingCapability) return false
|
||||||
|
val that = o
|
||||||
|
return backgroundPlain == that.backgroundPlain && backgroundDefault == that.backgroundDefault &&
|
||||||
|
name == that.name &&
|
||||||
|
url == that.url &&
|
||||||
|
slogan == that.slogan &&
|
||||||
|
color == that.color &&
|
||||||
|
colorText == that.colorText &&
|
||||||
|
colorElement == that.colorElement &&
|
||||||
|
logo == that.logo &&
|
||||||
|
background == that.background
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return Objects.hash(name, url, slogan, color, colorText, colorElement, logo, background, backgroundPlain, backgroundDefault)
|
||||||
|
}
|
||||||
|
}
|
@ -31,7 +31,7 @@ import org.parceler.Parcel
|
|||||||
@Data
|
@Data
|
||||||
@JsonObject
|
@JsonObject
|
||||||
@Parcelize
|
@Parcelize
|
||||||
class PushConfigurationState(
|
data class PushConfigurationState(
|
||||||
@JsonField(name = ["pushToken"])
|
@JsonField(name = ["pushToken"])
|
||||||
var pushToken: String? = null,
|
var pushToken: String? = null,
|
||||||
@JsonField(name = ["deviceIdentifier"])
|
@JsonField(name = ["deviceIdentifier"])
|
||||||
|
@ -216,7 +216,6 @@ class ConversationsListView : BaseView(), OnQueryTextListener,
|
|||||||
})
|
})
|
||||||
|
|
||||||
conversationsLiveData.observe(this@ConversationsListView, Observer {
|
conversationsLiveData.observe(this@ConversationsListView, Observer {
|
||||||
Log.d("MARIO", "TRIGGER")
|
|
||||||
if (it.isEmpty()) {
|
if (it.isEmpty()) {
|
||||||
if (viewState.value != LOADED_EMPTY) {
|
if (viewState.value != LOADED_EMPTY) {
|
||||||
viewState.value = LOADED_EMPTY
|
viewState.value = LOADED_EMPTY
|
||||||
|
@ -20,7 +20,9 @@
|
|||||||
|
|
||||||
package com.nextcloud.talk.newarch.local.models
|
package com.nextcloud.talk.newarch.local.models
|
||||||
|
|
||||||
|
import android.os.Parcel
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
|
import android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE
|
||||||
import androidx.room.ColumnInfo
|
import androidx.room.ColumnInfo
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
@ -29,8 +31,10 @@ import com.nextcloud.talk.models.json.capabilities.Capabilities
|
|||||||
import com.nextcloud.talk.models.json.push.PushConfigurationState
|
import com.nextcloud.talk.models.json.push.PushConfigurationState
|
||||||
import com.nextcloud.talk.newarch.local.models.other.UserStatus
|
import com.nextcloud.talk.newarch.local.models.other.UserStatus
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
|
import kotlinx.android.parcel.Parceler
|
||||||
import kotlinx.android.parcel.Parcelize
|
import kotlinx.android.parcel.Parcelize
|
||||||
import kotlinx.android.parcel.RawValue
|
import kotlinx.android.parcel.RawValue
|
||||||
|
import org.parceler.Parcels
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
@Entity(tableName = "users")
|
@Entity(tableName = "users")
|
||||||
@ -44,7 +48,7 @@ data class UserNgEntity(
|
|||||||
@ColumnInfo(
|
@ColumnInfo(
|
||||||
name = "push_configuration"
|
name = "push_configuration"
|
||||||
) var pushConfiguration: PushConfigurationState? = null,
|
) var pushConfiguration: PushConfigurationState? = null,
|
||||||
@ColumnInfo(name = "capabilities") var capabilities: @RawValue Capabilities? = null,
|
@ColumnInfo(name = "capabilities") var capabilities: Capabilities? = null,
|
||||||
@ColumnInfo(name = "client_auth_cert") var clientCertificate: String? = null,
|
@ColumnInfo(name = "client_auth_cert") var clientCertificate: String? = null,
|
||||||
@ColumnInfo(
|
@ColumnInfo(
|
||||||
name = "external_signaling"
|
name = "external_signaling"
|
||||||
|
@ -22,5 +22,11 @@ package com.nextcloud.talk.newarch.utils
|
|||||||
|
|
||||||
import com.nextcloud.talk.models.database.UserEntity
|
import com.nextcloud.talk.models.database.UserEntity
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
|
import java.security.MessageDigest
|
||||||
|
|
||||||
fun UserEntity.getCredentials() = ApiUtils.getCredentials(username, token)
|
fun UserEntity.getCredentials() = ApiUtils.getCredentials(username, token)
|
||||||
|
fun String.hashWithAlgorithm(algorithm: String): String {
|
||||||
|
val digest = MessageDigest.getInstance(algorithm)
|
||||||
|
val bytes = digest.digest(this.toByteArray(Charsets.UTF_8))
|
||||||
|
return bytes.fold("", { str, it -> str + "%02x".format(it) })
|
||||||
|
}
|
||||||
|
@ -36,7 +36,6 @@ import com.nextcloud.talk.models.json.push.PushConfigurationState
|
|||||||
import com.nextcloud.talk.models.json.push.PushRegistrationOverall
|
import com.nextcloud.talk.models.json.push.PushRegistrationOverall
|
||||||
import com.nextcloud.talk.newarch.domain.repository.offline.UsersRepository
|
import com.nextcloud.talk.newarch.domain.repository.offline.UsersRepository
|
||||||
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
||||||
import com.nextcloud.talk.utils.database.user.UserUtils
|
|
||||||
import com.nextcloud.talk.utils.preferences.AppPreferences
|
import com.nextcloud.talk.utils.preferences.AppPreferences
|
||||||
import io.reactivex.Observer
|
import io.reactivex.Observer
|
||||||
import io.reactivex.disposables.Disposable
|
import io.reactivex.disposables.Disposable
|
||||||
@ -53,14 +52,12 @@ import java.util.*
|
|||||||
import kotlin.experimental.and
|
import kotlin.experimental.and
|
||||||
|
|
||||||
class PushUtils(val usersRepository: UsersRepository) : KoinComponent {
|
class PushUtils(val usersRepository: UsersRepository) : KoinComponent {
|
||||||
val userUtils: UserUtils by inject()
|
|
||||||
val appPreferences: AppPreferences by inject()
|
val appPreferences: AppPreferences by inject()
|
||||||
val eventBus: EventBus by inject()
|
val eventBus: EventBus by inject()
|
||||||
val ncApi: NcApi by inject()
|
val ncApi: NcApi by inject()
|
||||||
private val keysFile: File
|
private val keysFile: File
|
||||||
private val publicKeyFile: File
|
private val publicKeyFile: File
|
||||||
private val privateKeyFile: File
|
private val privateKeyFile: File
|
||||||
private val proxyServer: String
|
|
||||||
fun verifySignature(
|
fun verifySignature(
|
||||||
signatureBytes: ByteArray?,
|
signatureBytes: ByteArray?,
|
||||||
subjectBytes: ByteArray?
|
subjectBytes: ByteArray?
|
||||||
@ -74,7 +71,7 @@ class PushUtils(val usersRepository: UsersRepository) : KoinComponent {
|
|||||||
val userEntities: List<UserNgEntity> = usersRepository.getUsers()
|
val userEntities: List<UserNgEntity> = usersRepository.getUsers()
|
||||||
try {
|
try {
|
||||||
signature = Signature.getInstance("SHA512withRSA")
|
signature = Signature.getInstance("SHA512withRSA")
|
||||||
if (userEntities.size > 0) {
|
if (userEntities.isNotEmpty()) {
|
||||||
for (userEntity in userEntities) {
|
for (userEntity in userEntities) {
|
||||||
pushConfigurationState = userEntity.pushConfiguration
|
pushConfigurationState = userEntity.pushConfiguration
|
||||||
if (pushConfigurationState?.userPublicKey != null) {
|
if (pushConfigurationState?.userPublicKey != null) {
|
||||||
@ -127,29 +124,6 @@ class PushUtils(val usersRepository: UsersRepository) : KoinComponent {
|
|||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateSHA512Hash(pushToken: String): String {
|
|
||||||
var messageDigest: MessageDigest? = null
|
|
||||||
try {
|
|
||||||
messageDigest = MessageDigest.getInstance("SHA-512")
|
|
||||||
messageDigest.update(pushToken.toByteArray())
|
|
||||||
return bytesToHex(messageDigest.digest())
|
|
||||||
} catch (e: NoSuchAlgorithmException) {
|
|
||||||
Log.d(TAG, "SHA-512 algorithm not supported")
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun bytesToHex(bytes: ByteArray): String {
|
|
||||||
val result = StringBuilder()
|
|
||||||
for (individualByte in bytes) {
|
|
||||||
result.append(
|
|
||||||
((individualByte and 0xff.toByte()) + 0x100).toString(16)
|
|
||||||
.substring(1)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return result.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun generateRsa2048KeyPair(): Int {
|
fun generateRsa2048KeyPair(): Int {
|
||||||
if (!publicKeyFile.exists() && !privateKeyFile.exists()) {
|
if (!publicKeyFile.exists() && !privateKeyFile.exists()) {
|
||||||
if (!keysFile.exists()) {
|
if (!keysFile.exists()) {
|
||||||
@ -186,139 +160,6 @@ class PushUtils(val usersRepository: UsersRepository) : KoinComponent {
|
|||||||
return -2
|
return -2
|
||||||
}
|
}
|
||||||
|
|
||||||
fun pushRegistrationToServer() {
|
|
||||||
val token: String = appPreferences.pushToken
|
|
||||||
if (!TextUtils.isEmpty(token)) {
|
|
||||||
var credentials: String
|
|
||||||
val pushTokenHash = generateSHA512Hash(token).toLowerCase()
|
|
||||||
val devicePublicKey =
|
|
||||||
readKeyFromFile(true) as PublicKey?
|
|
||||||
if (devicePublicKey != null) {
|
|
||||||
val publicKeyBytes: ByteArray? =
|
|
||||||
Base64.encode(devicePublicKey.encoded, Base64.NO_WRAP)
|
|
||||||
var publicKey = String(publicKeyBytes!!)
|
|
||||||
publicKey = publicKey.replace("(.{64})".toRegex(), "$1\n")
|
|
||||||
publicKey = "-----BEGIN PUBLIC KEY-----\n$publicKey\n-----END PUBLIC KEY-----\n"
|
|
||||||
if (userUtils.anyUserExists()) {
|
|
||||||
var accountPushData: PushConfigurationState? = null
|
|
||||||
for (userEntityObject in usersRepository.getUsers()) {
|
|
||||||
val userEntity = userEntityObject
|
|
||||||
accountPushData = userEntity.pushConfiguration
|
|
||||||
if (accountPushData == null || accountPushData.pushToken != token) {
|
|
||||||
val queryMap: MutableMap<String, String> =
|
|
||||||
HashMap()
|
|
||||||
queryMap["format"] = "json"
|
|
||||||
queryMap["pushTokenHash"] = pushTokenHash
|
|
||||||
queryMap["devicePublicKey"] = publicKey
|
|
||||||
queryMap["proxyServer"] = proxyServer
|
|
||||||
credentials = ApiUtils.getCredentials(
|
|
||||||
userEntity.username, userEntity.token
|
|
||||||
)
|
|
||||||
val finalCredentials = credentials
|
|
||||||
ncApi.registerDeviceForNotificationsWithNextcloud(
|
|
||||||
credentials,
|
|
||||||
ApiUtils.getUrlNextcloudPush(userEntity.baseUrl),
|
|
||||||
queryMap
|
|
||||||
)
|
|
||||||
.subscribe(object : Observer<PushRegistrationOverall> {
|
|
||||||
override fun onSubscribe(d: Disposable) {}
|
|
||||||
override fun onNext(pushRegistrationOverall: PushRegistrationOverall) {
|
|
||||||
val proxyMap: MutableMap<String, String> =
|
|
||||||
HashMap()
|
|
||||||
proxyMap["pushToken"] = token
|
|
||||||
proxyMap["deviceIdentifier"] =
|
|
||||||
pushRegistrationOverall.ocs.data.deviceIdentifier
|
|
||||||
proxyMap["deviceIdentifierSignature"] = pushRegistrationOverall.ocs
|
|
||||||
.data.signature
|
|
||||||
proxyMap["userPublicKey"] = pushRegistrationOverall.ocs
|
|
||||||
.data.publicKey
|
|
||||||
ncApi.registerDeviceForNotificationsWithProxy(
|
|
||||||
ApiUtils.getUrlPushProxy(), proxyMap
|
|
||||||
)
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.subscribe(object : Observer<Void> {
|
|
||||||
override fun onSubscribe(d: Disposable) {}
|
|
||||||
override fun onNext(aVoid: Void) {
|
|
||||||
val pushConfigurationState =
|
|
||||||
PushConfigurationState()
|
|
||||||
pushConfigurationState.pushToken = token
|
|
||||||
pushConfigurationState.deviceIdentifier = pushRegistrationOverall
|
|
||||||
.ocs.data.deviceIdentifier
|
|
||||||
pushConfigurationState.deviceIdentifierSignature =
|
|
||||||
pushRegistrationOverall.ocs.data.signature
|
|
||||||
pushConfigurationState.userPublicKey = pushRegistrationOverall.ocs
|
|
||||||
.data.publicKey
|
|
||||||
pushConfigurationState.usesRegularPass = false
|
|
||||||
try {
|
|
||||||
userUtils.createOrUpdateUser(
|
|
||||||
null,
|
|
||||||
null, null,
|
|
||||||
userEntity.displayName,
|
|
||||||
LoganSquare.serialize(
|
|
||||||
pushConfigurationState
|
|
||||||
), null,
|
|
||||||
null, userEntity.id, null, null, null
|
|
||||||
)
|
|
||||||
.subscribe(object : Observer<UserEntity> {
|
|
||||||
override fun onSubscribe(d: Disposable) {}
|
|
||||||
override fun onNext(userEntity: UserEntity) {
|
|
||||||
eventBus.post(
|
|
||||||
EventStatus(
|
|
||||||
userEntity.id,
|
|
||||||
PUSH_REGISTRATION,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
|
||||||
eventBus.post(
|
|
||||||
EventStatus(
|
|
||||||
userEntity.id!!,
|
|
||||||
PUSH_REGISTRATION, false
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onComplete() {}
|
|
||||||
})
|
|
||||||
} catch (e: IOException) {
|
|
||||||
Log.e(TAG, "IOException while updating user")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
|
||||||
eventBus.post(
|
|
||||||
EventStatus(
|
|
||||||
userEntity.id!!,
|
|
||||||
PUSH_REGISTRATION,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onComplete() {}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
|
||||||
eventBus.post(
|
|
||||||
EventStatus(
|
|
||||||
userEntity.id!!,
|
|
||||||
PUSH_REGISTRATION,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onComplete() {}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun readKeyFromString(
|
private fun readKeyFromString(
|
||||||
readPublicKey: Boolean,
|
readPublicKey: Boolean,
|
||||||
@ -417,8 +258,5 @@ class PushUtils(val usersRepository: UsersRepository) : KoinComponent {
|
|||||||
Context.MODE_PRIVATE
|
Context.MODE_PRIVATE
|
||||||
), "push_key.priv"
|
), "push_key.priv"
|
||||||
)
|
)
|
||||||
proxyServer =
|
|
||||||
sharedApplication!!.resources
|
|
||||||
.getString(string.nc_push_server_url)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user