Identity - WIP (compilation ok)
This commit is contained in:
parent
f489265ce7
commit
ab6e7a3b8a
|
@ -129,6 +129,8 @@ data class MatrixError(
|
|||
/** (Not documented yet) */
|
||||
const val M_WRONG_ROOM_KEYS_VERSION = "M_WRONG_ROOM_KEYS_VERSION"
|
||||
|
||||
const val M_TERMS_NOT_SIGNED = "M_TERMS_NOT_SIGNED"
|
||||
|
||||
// Possible value for "limit_type"
|
||||
const val LIMIT_TYPE_MAU = "monthly_active_user"
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ import im.vector.matrix.android.api.session.crypto.CryptoService
|
|||
import im.vector.matrix.android.api.session.file.FileService
|
||||
import im.vector.matrix.android.api.session.group.GroupService
|
||||
import im.vector.matrix.android.api.session.homeserver.HomeServerCapabilitiesService
|
||||
import im.vector.matrix.android.api.session.identity.IdentityService
|
||||
import im.vector.matrix.android.api.session.profile.ProfileService
|
||||
import im.vector.matrix.android.api.session.pushers.PushersService
|
||||
import im.vector.matrix.android.api.session.room.RoomDirectoryService
|
||||
|
@ -145,6 +146,11 @@ interface Session :
|
|||
*/
|
||||
fun cryptoService(): CryptoService
|
||||
|
||||
/**
|
||||
* Returns the identity service associated with the session
|
||||
*/
|
||||
fun identityService(): IdentityService
|
||||
|
||||
/**
|
||||
* Add a listener to the session.
|
||||
* @param listener the listener to add.
|
||||
|
|
|
@ -14,15 +14,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.di
|
||||
|
||||
import javax.inject.Qualifier
|
||||
|
||||
@Qualifier
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class HomeserverAccessToken
|
||||
|
||||
@Qualifier
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class IdentityServerAccessToken
|
||||
package im.vector.matrix.android.api.session.identity
|
||||
|
||||
data class FoundThreePid(
|
||||
val threePid: ThreePid,
|
||||
val matrixId: String
|
||||
)
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.api.session.identity
|
||||
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
|
||||
/**
|
||||
* Provides access to the identity server configuration and services identity server can provide
|
||||
*/
|
||||
interface IdentityService {
|
||||
|
||||
/**
|
||||
* Return the default identity server of the homeserver (using Wellknown request)
|
||||
*/
|
||||
fun getDefaultIdentityServer(): String?
|
||||
|
||||
fun getCurrentIdentityServer(): String?
|
||||
|
||||
fun setNewIdentityServer(url: String?, callback: MatrixCallback<Unit>): Cancelable
|
||||
|
||||
fun disconnect()
|
||||
|
||||
fun bindThreePid()
|
||||
|
||||
fun unbindThreePid()
|
||||
|
||||
fun lookUp(threePids: List<ThreePid>, callback: MatrixCallback<List<FoundThreePid>>): Cancelable
|
||||
|
||||
fun addListener(listener: IdentityServiceListener)
|
||||
fun removeListener(listener: IdentityServiceListener)
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.api.session.identity
|
||||
|
||||
sealed class IdentityServiceError(cause: Throwable? = null) : Throwable(cause = cause) {
|
||||
object NoIdentityServerConfigured : IdentityServiceError(null)
|
||||
object TermsNotSignedException : IdentityServiceError(null)
|
||||
object BulkLookupSha256NotSupported : IdentityServiceError(null)
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.api.session.identity
|
||||
|
||||
interface IdentityServiceListener {
|
||||
fun onIdentityServerChange()
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.api.session.identity
|
||||
|
||||
sealed class ThreePid(open val value: String) {
|
||||
data class Email(val email: String) : ThreePid(email)
|
||||
data class Msisdn(val msisdn: String) : ThreePid(msisdn)
|
||||
}
|
|
@ -199,7 +199,7 @@ internal object MXEncryptedAttachments {
|
|||
.replace('_', '/')
|
||||
}
|
||||
|
||||
private fun base64ToBase64Url(base64: String): String {
|
||||
internal fun base64ToBase64Url(base64: String): String {
|
||||
return base64.replace("\n".toRegex(), "")
|
||||
.replace("\\+".toRegex(), "-")
|
||||
.replace('/', '_')
|
||||
|
|
|
@ -18,10 +18,15 @@ package im.vector.matrix.android.internal.di
|
|||
|
||||
import javax.inject.Qualifier
|
||||
|
||||
// TODO Add internal ?
|
||||
@Qualifier
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class Authenticated
|
||||
|
||||
@Qualifier
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class AuthenticatedIdentity
|
||||
|
||||
@Qualifier
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class Unauthenticated
|
||||
|
|
|
@ -17,9 +17,11 @@
|
|||
package im.vector.matrix.android.internal.network.token
|
||||
|
||||
import im.vector.matrix.android.internal.auth.SessionParamsStore
|
||||
import im.vector.matrix.android.internal.di.SessionId
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class HomeserverAccessTokenProvider(
|
||||
private val sessionId: String,
|
||||
internal class HomeserverAccessTokenProvider @Inject constructor(
|
||||
@SessionId private val sessionId: String,
|
||||
private val sessionParamsStore: SessionParamsStore
|
||||
) : AccessTokenProvider {
|
||||
override fun getToken() = sessionParamsStore.get(sessionId)?.credentials?.accessToken
|
||||
|
|
|
@ -50,6 +50,7 @@ import im.vector.matrix.android.internal.crypto.crosssigning.ShieldTrustUpdater
|
|||
import im.vector.matrix.android.internal.database.LiveEntityObserver
|
||||
import im.vector.matrix.android.internal.di.SessionId
|
||||
import im.vector.matrix.android.internal.di.WorkManagerProvider
|
||||
import im.vector.matrix.android.internal.session.identity.DefaultIdentityService
|
||||
import im.vector.matrix.android.internal.session.room.timeline.TimelineEventDecryptor
|
||||
import im.vector.matrix.android.internal.session.sync.SyncTokenStore
|
||||
import im.vector.matrix.android.internal.session.sync.job.SyncThread
|
||||
|
@ -97,7 +98,8 @@ internal class DefaultSession @Inject constructor(
|
|||
private val _sharedSecretStorageService: Lazy<SharedSecretStorageService>,
|
||||
private val accountService: Lazy<AccountService>,
|
||||
private val timelineEventDecryptor: TimelineEventDecryptor,
|
||||
private val shieldTrustUpdater: ShieldTrustUpdater)
|
||||
private val shieldTrustUpdater: ShieldTrustUpdater,
|
||||
private val defaultIdentityService: DefaultIdentityService)
|
||||
: Session,
|
||||
RoomService by roomService.get(),
|
||||
RoomDirectoryService by roomDirectoryService.get(),
|
||||
|
@ -133,6 +135,7 @@ internal class DefaultSession @Inject constructor(
|
|||
eventBus.register(this)
|
||||
timelineEventDecryptor.start()
|
||||
shieldTrustUpdater.start()
|
||||
defaultIdentityService.start()
|
||||
}
|
||||
|
||||
override fun requireBackgroundSync() {
|
||||
|
@ -175,6 +178,7 @@ internal class DefaultSession @Inject constructor(
|
|||
isOpen = false
|
||||
eventBus.unregister(this)
|
||||
shieldTrustUpdater.stop()
|
||||
defaultIdentityService.stop()
|
||||
}
|
||||
|
||||
override fun getSyncStateLive(): LiveData<SyncState> {
|
||||
|
@ -218,6 +222,8 @@ internal class DefaultSession @Inject constructor(
|
|||
|
||||
override fun cryptoService(): CryptoService = cryptoService.get()
|
||||
|
||||
override fun identityService() = defaultIdentityService
|
||||
|
||||
override fun addListener(listener: Session.Listener) {
|
||||
sessionListeners.addListener(listener)
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import im.vector.matrix.android.internal.session.filter.FilterModule
|
|||
import im.vector.matrix.android.internal.session.group.GetGroupDataWorker
|
||||
import im.vector.matrix.android.internal.session.group.GroupModule
|
||||
import im.vector.matrix.android.internal.session.homeserver.HomeServerCapabilitiesModule
|
||||
import im.vector.matrix.android.internal.session.identity.IdentityModule
|
||||
import im.vector.matrix.android.internal.session.openid.OpenIdModule
|
||||
import im.vector.matrix.android.internal.session.profile.ProfileModule
|
||||
import im.vector.matrix.android.internal.session.pushers.AddHttpPusherWorker
|
||||
|
@ -72,6 +73,7 @@ import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
|||
CryptoModule::class,
|
||||
PushersModule::class,
|
||||
OpenIdModule::class,
|
||||
IdentityModule::class,
|
||||
AccountDataModule::class,
|
||||
ProfileModule::class,
|
||||
SessionAssistedInjectModule::class,
|
||||
|
|
|
@ -36,7 +36,6 @@ import im.vector.matrix.android.api.session.accountdata.AccountDataService
|
|||
import im.vector.matrix.android.api.session.homeserver.HomeServerCapabilitiesService
|
||||
import im.vector.matrix.android.api.session.securestorage.SecureStorageService
|
||||
import im.vector.matrix.android.api.session.securestorage.SharedSecretStorageService
|
||||
import im.vector.matrix.android.internal.auth.SessionParamsStore
|
||||
import im.vector.matrix.android.internal.crypto.secrets.DefaultSharedSecretStorageService
|
||||
import im.vector.matrix.android.internal.crypto.verification.VerificationMessageLiveObserver
|
||||
import im.vector.matrix.android.internal.database.LiveEntityObserver
|
||||
|
@ -44,7 +43,6 @@ import im.vector.matrix.android.internal.database.RealmKeysUtils
|
|||
import im.vector.matrix.android.internal.database.SessionRealmConfigurationFactory
|
||||
import im.vector.matrix.android.internal.di.Authenticated
|
||||
import im.vector.matrix.android.internal.di.DeviceId
|
||||
import im.vector.matrix.android.internal.di.HomeserverAccessToken
|
||||
import im.vector.matrix.android.internal.di.IdentityDatabase
|
||||
import im.vector.matrix.android.internal.di.SessionCacheDirectory
|
||||
import im.vector.matrix.android.internal.di.SessionDatabase
|
||||
|
@ -216,14 +214,6 @@ internal abstract class SessionModule {
|
|||
.build()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@Authenticated
|
||||
fun providesAccessTokenProvider(@SessionId sessionId: String,
|
||||
sessionParamsStore: SessionParamsStore): AccessTokenProvider {
|
||||
return HomeserverAccessTokenProvider(sessionId, sessionParamsStore)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@SessionScope
|
||||
|
@ -266,7 +256,7 @@ internal abstract class SessionModule {
|
|||
}
|
||||
|
||||
@Binds
|
||||
@HomeserverAccessToken
|
||||
@Authenticated
|
||||
abstract fun bindAccessTokenProvider(provider: HomeserverAccessTokenProvider): AccessTokenProvider
|
||||
|
||||
@Binds
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.session.identity
|
||||
|
||||
import im.vector.matrix.android.api.session.identity.FoundThreePid
|
||||
import im.vector.matrix.android.api.session.identity.IdentityServiceError
|
||||
import im.vector.matrix.android.api.session.identity.ThreePid
|
||||
import im.vector.matrix.android.internal.crypto.attachments.MXEncryptedAttachments.base64ToBase64Url
|
||||
import im.vector.matrix.android.internal.crypto.tools.withOlmUtility
|
||||
import im.vector.matrix.android.internal.network.executeRequest
|
||||
import im.vector.matrix.android.internal.session.identity.db.IdentityServiceStore
|
||||
import im.vector.matrix.android.internal.session.identity.model.IdentityHashDetailResponse
|
||||
import im.vector.matrix.android.internal.session.identity.model.IdentityLookUpV2Params
|
||||
import im.vector.matrix.android.internal.session.identity.model.IdentityLookUpV2Response
|
||||
import im.vector.matrix.android.internal.task.Task
|
||||
import java.util.Locale
|
||||
import javax.inject.Inject
|
||||
|
||||
internal interface BulkLookupTask : Task<BulkLookupTask.Params, List<FoundThreePid>> {
|
||||
data class Params(
|
||||
val threePids: List<ThreePid>
|
||||
)
|
||||
}
|
||||
|
||||
internal class DefaultBulkLookupTask @Inject constructor(
|
||||
private val identityApiProvider: IdentityApiProvider,
|
||||
private val identityServiceStore: IdentityServiceStore
|
||||
) : BulkLookupTask {
|
||||
|
||||
override suspend fun execute(params: BulkLookupTask.Params): List<FoundThreePid> {
|
||||
val identityAPI = identityApiProvider.identityApi ?: throw IdentityServiceError.NoIdentityServerConfigured
|
||||
val entity = identityServiceStore.get()
|
||||
val pepper = entity.hashLookupPepper
|
||||
val hashDetailResponse = if (pepper == null) {
|
||||
// We need to fetch the hash details first
|
||||
executeRequest<IdentityHashDetailResponse>(null) {
|
||||
apiCall = identityAPI.hashDetails()
|
||||
}
|
||||
.also { identityServiceStore.setHashDetails(it) }
|
||||
} else {
|
||||
IdentityHashDetailResponse(pepper, entity.hashLookupAlgorithm.toList())
|
||||
}
|
||||
|
||||
if (hashDetailResponse.algorithms.contains("sha256").not()) {
|
||||
// TODO We should ask the user if he is ok to send their 3Pid in clear, but for the moment do not do it
|
||||
throw IdentityServiceError.BulkLookupSha256NotSupported
|
||||
}
|
||||
|
||||
val hashedAddresses = withOlmUtility { olmUtility ->
|
||||
params.threePids.map { threePid ->
|
||||
base64ToBase64Url(
|
||||
olmUtility.sha256(threePid.value.toLowerCase(Locale.ROOT)
|
||||
+ " " + threePid.toMedium() + " " + hashDetailResponse.pepper)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val identityLookUpV2Response = executeRequest<IdentityLookUpV2Response>(null) {
|
||||
apiCall = identityAPI.bulkLookupV2(IdentityLookUpV2Params(
|
||||
hashedAddresses,
|
||||
"sha256",
|
||||
hashDetailResponse.pepper
|
||||
))
|
||||
}
|
||||
|
||||
// TODO Catch invalid hash pepper and retry
|
||||
|
||||
// Convert back to List<FoundThreePid>
|
||||
return handleSuccess(params.threePids, hashedAddresses, identityLookUpV2Response)
|
||||
}
|
||||
|
||||
private fun handleSuccess(threePids: List<ThreePid>, hashedAddresses: List<String>, identityLookUpV2Response: IdentityLookUpV2Response): List<FoundThreePid> {
|
||||
return identityLookUpV2Response.mappings.keys.map { hashedAddress ->
|
||||
FoundThreePid(threePids[hashedAddresses.indexOf(hashedAddress)], identityLookUpV2Response.mappings[hashedAddress] ?: error(""))
|
||||
}
|
||||
}
|
||||
|
||||
private fun ThreePid.toMedium(): String {
|
||||
return when (this) {
|
||||
is ThreePid.Email -> "email"
|
||||
is ThreePid.Msisdn -> "msisdn"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.session.identity
|
||||
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.LifecycleRegistry
|
||||
import dagger.Lazy
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.failure.Failure
|
||||
import im.vector.matrix.android.api.failure.MatrixError
|
||||
import im.vector.matrix.android.api.session.events.model.toModel
|
||||
import im.vector.matrix.android.api.session.identity.FoundThreePid
|
||||
import im.vector.matrix.android.api.session.identity.IdentityService
|
||||
import im.vector.matrix.android.api.session.identity.IdentityServiceError
|
||||
import im.vector.matrix.android.api.session.identity.IdentityServiceListener
|
||||
import im.vector.matrix.android.api.session.identity.ThreePid
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
import im.vector.matrix.android.internal.di.AuthenticatedIdentity
|
||||
import im.vector.matrix.android.internal.di.Unauthenticated
|
||||
import im.vector.matrix.android.internal.network.RetrofitFactory
|
||||
import im.vector.matrix.android.internal.session.SessionScope
|
||||
import im.vector.matrix.android.internal.session.identity.db.IdentityServiceStore
|
||||
import im.vector.matrix.android.internal.session.identity.todelete.AccountDataDataSource
|
||||
import im.vector.matrix.android.internal.session.identity.todelete.observeNotNull
|
||||
import im.vector.matrix.android.internal.session.openid.GetOpenIdTokenTask
|
||||
import im.vector.matrix.android.internal.session.sync.model.accountdata.IdentityContent
|
||||
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountData
|
||||
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataIdentity
|
||||
import im.vector.matrix.android.internal.session.user.accountdata.UpdateUserAccountDataTask
|
||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||
import im.vector.matrix.android.internal.task.launchToCallback
|
||||
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import okhttp3.OkHttpClient
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import javax.net.ssl.HttpsURLConnection
|
||||
|
||||
@SessionScope
|
||||
internal class DefaultIdentityService @Inject constructor(
|
||||
private val identityServiceStore: IdentityServiceStore,
|
||||
private val openIdTokenTask: GetOpenIdTokenTask,
|
||||
private val bulkLookupTask: BulkLookupTask,
|
||||
private val identityRegisterTask: IdentityRegisterTask,
|
||||
private val taskExecutor: TaskExecutor,
|
||||
@Unauthenticated
|
||||
private val unauthenticatedOkHttpClient: Lazy<OkHttpClient>,
|
||||
@AuthenticatedIdentity
|
||||
private val okHttpClient: Lazy<OkHttpClient>,
|
||||
private val retrofitFactory: RetrofitFactory,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
private val updateUserAccountDataTask: UpdateUserAccountDataTask,
|
||||
private val identityApiProvider: IdentityApiProvider,
|
||||
private val accountDataDataSource: AccountDataDataSource
|
||||
) : IdentityService {
|
||||
|
||||
private val lifecycleOwner: LifecycleOwner = LifecycleOwner { lifecycleRegistry }
|
||||
private val lifecycleRegistry: LifecycleRegistry = LifecycleRegistry(lifecycleOwner)
|
||||
|
||||
private val listeners = mutableSetOf<IdentityServiceListener>()
|
||||
|
||||
fun start() {
|
||||
lifecycleRegistry.currentState = Lifecycle.State.STARTED
|
||||
// Observe the account data change
|
||||
accountDataDataSource
|
||||
.getLiveAccountDataEvent(UserAccountData.TYPE_IDENTITY)
|
||||
.observeNotNull(lifecycleOwner) {
|
||||
val identityServerContent = it.getOrNull()?.content?.toModel<UserAccountDataIdentity>()
|
||||
if (identityServerContent != null) {
|
||||
notifyIdentityServerUrlChange(identityServerContent.content?.baseUrl)
|
||||
}
|
||||
// TODO Handle the case where the account data is deleted?
|
||||
}
|
||||
}
|
||||
|
||||
private fun notifyIdentityServerUrlChange(baseUrl: String?) {
|
||||
// This is maybe not a real change (local echo of account data we are just setting
|
||||
if (identityServiceStore.get().identityServerUrl == baseUrl) {
|
||||
Timber.d("Local echo of identity server url change")
|
||||
} else {
|
||||
// Url has changed, we have to reset our store, update internal configuration and notify listeners
|
||||
identityServiceStore.setUrl(baseUrl)
|
||||
updateIdentityAPI(baseUrl)
|
||||
listeners.toList().forEach { it.onIdentityServerChange() }
|
||||
}
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
lifecycleRegistry.currentState = Lifecycle.State.DESTROYED
|
||||
}
|
||||
|
||||
override fun getDefaultIdentityServer(): String? {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun getCurrentIdentityServer(): String? {
|
||||
return identityServiceStore.get().identityServerUrl
|
||||
}
|
||||
|
||||
override fun disconnect() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun setNewIdentityServer(url: String?, callback: MatrixCallback<Unit>): Cancelable {
|
||||
return GlobalScope.launchToCallback(coroutineDispatchers.main, callback) {
|
||||
val current = getCurrentIdentityServer()
|
||||
when (url) {
|
||||
current ->
|
||||
// Nothing to do
|
||||
Timber.d("Same URL, nothing to do")
|
||||
null -> {
|
||||
// TODO
|
||||
// Disconnect previous one if any
|
||||
identityServiceStore.setUrl(null)
|
||||
updateAccountData(null)
|
||||
}
|
||||
else -> {
|
||||
// TODO: check first that it is a valid identity server
|
||||
updateAccountData(url)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun updateAccountData(url: String?) {
|
||||
updateUserAccountDataTask.execute(UpdateUserAccountDataTask.IdentityParams(
|
||||
identityContent = IdentityContent(baseUrl = url)
|
||||
))
|
||||
}
|
||||
|
||||
override fun bindThreePid() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun unbindThreePid() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun lookUp(threePids: List<ThreePid>, callback: MatrixCallback<List<FoundThreePid>>): Cancelable {
|
||||
return GlobalScope.launchToCallback(coroutineDispatchers.main, callback) {
|
||||
lookUpInternal(true, threePids)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun lookUpInternal(firstTime: Boolean, threePids: List<ThreePid>): List<FoundThreePid> {
|
||||
ensureToken()
|
||||
|
||||
return try {
|
||||
bulkLookupTask.execute(BulkLookupTask.Params(threePids))
|
||||
} catch (throwable: Throwable) {
|
||||
// Refresh token?
|
||||
when {
|
||||
throwable.isInvalidToken() && firstTime -> {
|
||||
identityServiceStore.setToken(null)
|
||||
lookUpInternal(false, threePids)
|
||||
}
|
||||
throwable.isTermsNotSigned() -> throw IdentityServiceError.TermsNotSignedException
|
||||
else -> throw throwable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun ensureToken() {
|
||||
val entity = identityServiceStore.get()
|
||||
val url = entity.identityServerUrl ?: throw IdentityServiceError.NoIdentityServerConfigured
|
||||
|
||||
if (entity.token == null) {
|
||||
// Try to get a token
|
||||
val openIdToken = openIdTokenTask.execute(Unit)
|
||||
|
||||
val api = retrofitFactory.create(unauthenticatedOkHttpClient, url).create(IdentityAuthAPI::class.java)
|
||||
val token = identityRegisterTask.execute(IdentityRegisterTask.Params(api, openIdToken))
|
||||
|
||||
identityServiceStore.setToken(token.token)
|
||||
}
|
||||
}
|
||||
|
||||
override fun addListener(listener: IdentityServiceListener) {
|
||||
listeners.add(listener)
|
||||
}
|
||||
|
||||
override fun removeListener(listener: IdentityServiceListener) {
|
||||
listeners.remove(listener)
|
||||
}
|
||||
|
||||
private fun updateIdentityAPI(url: String?) {
|
||||
if (url == null) {
|
||||
identityApiProvider.identityApi = null
|
||||
} else {
|
||||
val retrofit = retrofitFactory.create(okHttpClient, url)
|
||||
identityApiProvider.identityApi = retrofit.create(IdentityAPI::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Throwable.isInvalidToken(): Boolean {
|
||||
return this is Failure.ServerError
|
||||
&& this.httpCode == HttpsURLConnection.HTTP_UNAUTHORIZED /* 401 */
|
||||
}
|
||||
|
||||
private fun Throwable.isTermsNotSigned(): Boolean {
|
||||
return this is Failure.ServerError
|
||||
&& httpCode == HttpsURLConnection.HTTP_FORBIDDEN /* 403 */
|
||||
&& error.code == MatrixError.M_TERMS_NOT_SIGNED
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.session.identity
|
||||
|
||||
import im.vector.matrix.android.internal.auth.registration.SuccessResult
|
||||
import im.vector.matrix.android.internal.network.NetworkConstants
|
||||
import im.vector.matrix.android.internal.session.identity.model.IdentityAccountResponse
|
||||
import im.vector.matrix.android.internal.session.identity.model.IdentityHashDetailResponse
|
||||
import im.vector.matrix.android.internal.session.identity.model.IdentityLookUpV2Params
|
||||
import im.vector.matrix.android.internal.session.identity.model.IdentityLookUpV2Response
|
||||
import im.vector.matrix.android.internal.session.identity.model.IdentityRequestOwnershipParams
|
||||
import retrofit2.Call
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.Path
|
||||
|
||||
/**
|
||||
* Ref: https://matrix.org/docs/spec/identity_service/latest
|
||||
* This contain the requests which need an identity server token
|
||||
*/
|
||||
internal interface IdentityAPI {
|
||||
/**
|
||||
* Gets information about what user owns the access token used in the request.
|
||||
* Will return a 403 for when terms are not signed
|
||||
*/
|
||||
@GET(NetworkConstants.URI_IDENTITY_PATH_V2 + "account")
|
||||
fun getAccount(): Call<IdentityAccountResponse>
|
||||
|
||||
/**
|
||||
* Logs out the access token, preventing it from being used to authenticate future requests to the server.
|
||||
*/
|
||||
@POST(NetworkConstants.URI_IDENTITY_PATH_V2 + "logout")
|
||||
fun logout(): Call<Unit>
|
||||
|
||||
/**
|
||||
* Request the hash detail to request a bunch of 3PIDs
|
||||
*/
|
||||
@GET(NetworkConstants.URI_IDENTITY_PATH_V2 + "hash_details")
|
||||
fun hashDetails(): Call<IdentityHashDetailResponse>
|
||||
|
||||
/**
|
||||
* Request a bunch of 3PIDs
|
||||
*
|
||||
* @param body the body request
|
||||
*/
|
||||
@POST(NetworkConstants.URI_IDENTITY_PATH_V2 + "lookup")
|
||||
fun bulkLookupV2(@Body body: IdentityLookUpV2Params): Call<IdentityLookUpV2Response>
|
||||
|
||||
/**
|
||||
* Request the ownership validation of an email address or a phone number previously set
|
||||
* by [ProfileApi.requestEmailValidation]
|
||||
*
|
||||
* @param medium the medium of the 3pid
|
||||
*/
|
||||
@POST(NetworkConstants.URI_IDENTITY_PATH_V2 + "validate/{medium}/submitToken")
|
||||
fun requestOwnershipValidationV2(@Path("medium") medium: String?,
|
||||
@Body body: IdentityRequestOwnershipParams): Call<SuccessResult>
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.session.identity
|
||||
|
||||
import im.vector.matrix.android.internal.network.token.AccessTokenProvider
|
||||
import im.vector.matrix.android.internal.session.identity.db.IdentityServiceStore
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class IdentityAccessTokenProvider @Inject constructor(
|
||||
private val identityServiceStore: IdentityServiceStore
|
||||
) : AccessTokenProvider {
|
||||
override fun getToken() = identityServiceStore.get().token
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.session.identity
|
||||
|
||||
import im.vector.matrix.android.internal.session.SessionScope
|
||||
import javax.inject.Inject
|
||||
|
||||
@SessionScope
|
||||
internal class IdentityApiProvider @Inject constructor() {
|
||||
|
||||
var identityApi: IdentityAPI? = null
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.session.identity
|
||||
|
||||
import im.vector.matrix.android.internal.network.NetworkConstants
|
||||
import im.vector.matrix.android.internal.session.identity.model.IdentityRegisterResponse
|
||||
import im.vector.matrix.android.internal.session.openid.RequestOpenIdTokenResponse
|
||||
import retrofit2.Call
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.POST
|
||||
|
||||
/**
|
||||
* Ref: https://matrix.org/docs/spec/identity_service/latest
|
||||
* This contain the requests which do not need an identity server token
|
||||
*/
|
||||
internal interface IdentityAuthAPI {
|
||||
|
||||
/**
|
||||
* https://matrix.org/docs/spec/client_server/r0.4.0.html#server-discovery
|
||||
* Simple ping call to check if server alive
|
||||
*
|
||||
* Ref: https://matrix.org/docs/spec/identity_service/unstable#status-check
|
||||
*
|
||||
* @return 200 in case of success
|
||||
*/
|
||||
@GET(NetworkConstants.URI_API_PREFIX_IDENTITY)
|
||||
fun ping(): Call<Void>
|
||||
|
||||
/**
|
||||
* Exchanges an OpenID token from the homeserver for an access token to access the identity server.
|
||||
* The request body is the same as the values returned by /openid/request_token in the Client-Server API.
|
||||
*/
|
||||
@POST(NetworkConstants.URI_IDENTITY_PATH_V2 + "account/register")
|
||||
fun register(@Body openIdToken: RequestOpenIdTokenResponse): Call<IdentityRegisterResponse>
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.session.identity
|
||||
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import im.vector.matrix.android.internal.di.AuthenticatedIdentity
|
||||
import im.vector.matrix.android.internal.di.Unauthenticated
|
||||
import im.vector.matrix.android.internal.network.AccessTokenInterceptor
|
||||
import im.vector.matrix.android.internal.network.interceptors.CurlLoggingInterceptor
|
||||
import im.vector.matrix.android.internal.network.token.AccessTokenProvider
|
||||
import im.vector.matrix.android.internal.session.SessionScope
|
||||
import im.vector.matrix.android.internal.session.identity.db.IdentityServiceStore
|
||||
import im.vector.matrix.android.internal.session.identity.db.RealmIdentityServerStore
|
||||
import okhttp3.OkHttpClient
|
||||
|
||||
@Module
|
||||
internal abstract class IdentityModule {
|
||||
|
||||
@Module
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@SessionScope
|
||||
@AuthenticatedIdentity
|
||||
fun providesOkHttpClient(@Unauthenticated okHttpClient: OkHttpClient,
|
||||
@AuthenticatedIdentity accessTokenProvider: AccessTokenProvider): OkHttpClient {
|
||||
// TODO Create an helper because there is code duplication
|
||||
return okHttpClient.newBuilder()
|
||||
.apply {
|
||||
// Remove the previous CurlLoggingInterceptor, to add it after the accessTokenInterceptor
|
||||
val existingCurlInterceptors = interceptors().filterIsInstance<CurlLoggingInterceptor>()
|
||||
interceptors().removeAll(existingCurlInterceptors)
|
||||
|
||||
addInterceptor(AccessTokenInterceptor(accessTokenProvider))
|
||||
|
||||
// Re add eventually the curl logging interceptors
|
||||
existingCurlInterceptors.forEach {
|
||||
addInterceptor(it)
|
||||
}
|
||||
}
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
@Binds
|
||||
@AuthenticatedIdentity
|
||||
abstract fun bindAccessTokenProvider(provider: IdentityAccessTokenProvider): AccessTokenProvider
|
||||
|
||||
@Binds
|
||||
abstract fun bindIdentityServiceStore(store: RealmIdentityServerStore): IdentityServiceStore
|
||||
|
||||
@Binds
|
||||
abstract fun bindIdentityRegisterTask(task: DefaultIdentityRegisterTask): IdentityRegisterTask
|
||||
|
||||
@Binds
|
||||
abstract fun bindBulkLookupTask(task: DefaultBulkLookupTask): BulkLookupTask
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.session.identity
|
||||
|
||||
import im.vector.matrix.android.internal.network.executeRequest
|
||||
import im.vector.matrix.android.internal.session.identity.model.IdentityRegisterResponse
|
||||
import im.vector.matrix.android.internal.session.openid.RequestOpenIdTokenResponse
|
||||
import im.vector.matrix.android.internal.task.Task
|
||||
import javax.inject.Inject
|
||||
|
||||
internal interface IdentityRegisterTask : Task<IdentityRegisterTask.Params, IdentityRegisterResponse> {
|
||||
data class Params(
|
||||
val identityAuthAPI: IdentityAuthAPI,
|
||||
val openIdTokenResponse: RequestOpenIdTokenResponse
|
||||
)
|
||||
}
|
||||
|
||||
internal class DefaultIdentityRegisterTask @Inject constructor() : IdentityRegisterTask {
|
||||
|
||||
override suspend fun execute(params: IdentityRegisterTask.Params): IdentityRegisterResponse {
|
||||
return executeRequest(null) {
|
||||
apiCall = params.identityAuthAPI.register(params.openIdTokenResponse)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.session.identity.model
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class IdentityAccountResponse(
|
||||
@Json(name = "user_id")
|
||||
val userId: String
|
||||
)
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.session.identity.model
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
/**
|
||||
* Ref: https://github.com/matrix-org/matrix-doc/blob/hs/hash-identity/proposals/2134-identity-hash-lookup.md
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class IdentityLookUpV2Params(
|
||||
@Json(name = "addresses")
|
||||
val hashedAddresses: List<String>,
|
||||
|
||||
@JvmField
|
||||
@Json(name = "algorithm")
|
||||
val algorithm: String,
|
||||
|
||||
@JvmField
|
||||
@Json(name = "pepper")
|
||||
val pepper: String
|
||||
)
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.session.identity.model
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
/**
|
||||
* Ref: https://github.com/matrix-org/matrix-doc/blob/hs/hash-identity/proposals/2134-identity-hash-lookup.md
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class IdentityLookUpV2Response(
|
||||
@Json(name = "mappings")
|
||||
val mappings: Map<String, String>
|
||||
)
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.session.identity.model
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class IdentityRegisterResponse(
|
||||
/**
|
||||
* A token which can be used to authenticate future requests to the identity server.
|
||||
*/
|
||||
@Json(name = "token")
|
||||
val token: String
|
||||
)
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package im.vector.matrix.android.internal.session.identity.model
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class IdentityRequestOwnershipParams(
|
||||
@Json(name = "client_secret")
|
||||
var clientSecret: String? = null,
|
||||
|
||||
@Json(name = "sid")
|
||||
var sid: String? = null,
|
||||
|
||||
@Json(name = "token")
|
||||
var token: String? = null
|
||||
)
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.session.identity.todelete
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Transformations
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import im.vector.matrix.android.api.util.Optional
|
||||
import im.vector.matrix.android.api.util.toOptional
|
||||
import im.vector.matrix.android.internal.database.model.UserAccountDataEntity
|
||||
import im.vector.matrix.android.internal.database.model.UserAccountDataEntityFields
|
||||
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataEvent
|
||||
import io.realm.Realm
|
||||
import io.realm.RealmQuery
|
||||
import javax.inject.Inject
|
||||
|
||||
// There will be a duplicated class when Integration manager will be merged, so delete this one
|
||||
internal class AccountDataDataSource @Inject constructor(private val monarchy: Monarchy,
|
||||
private val accountDataMapper: AccountDataMapper) {
|
||||
|
||||
fun getAccountDataEvent(type: String): UserAccountDataEvent? {
|
||||
return getAccountDataEvents(setOf(type)).firstOrNull()
|
||||
}
|
||||
|
||||
fun getLiveAccountDataEvent(type: String): LiveData<Optional<UserAccountDataEvent>> {
|
||||
return Transformations.map(getLiveAccountDataEvents(setOf(type))) {
|
||||
it.firstOrNull()?.toOptional()
|
||||
}
|
||||
}
|
||||
|
||||
fun getAccountDataEvents(types: Set<String>): List<UserAccountDataEvent> {
|
||||
return monarchy.fetchAllMappedSync(
|
||||
{ accountDataEventsQuery(it, types) },
|
||||
accountDataMapper::map
|
||||
)
|
||||
}
|
||||
|
||||
fun getLiveAccountDataEvents(types: Set<String>): LiveData<List<UserAccountDataEvent>> {
|
||||
return monarchy.findAllMappedWithChanges(
|
||||
{ accountDataEventsQuery(it, types) },
|
||||
accountDataMapper::map
|
||||
)
|
||||
}
|
||||
|
||||
private fun accountDataEventsQuery(realm: Realm, types: Set<String>): RealmQuery<UserAccountDataEntity> {
|
||||
val query = realm.where(UserAccountDataEntity::class.java)
|
||||
if (types.isNotEmpty()) {
|
||||
query.`in`(UserAccountDataEntityFields.TYPE, types.toTypedArray())
|
||||
}
|
||||
return query
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.session.identity.todelete
|
||||
|
||||
import com.squareup.moshi.Moshi
|
||||
import im.vector.matrix.android.api.util.JSON_DICT_PARAMETERIZED_TYPE
|
||||
import im.vector.matrix.android.internal.database.model.UserAccountDataEntity
|
||||
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataEvent
|
||||
import javax.inject.Inject
|
||||
|
||||
// There will be a duplicated class when Integration manager will be merged, so delete this one
|
||||
internal class AccountDataMapper @Inject constructor(moshi: Moshi) {
|
||||
|
||||
private val adapter = moshi.adapter<Map<String, Any>>(JSON_DICT_PARAMETERIZED_TYPE)
|
||||
|
||||
fun map(entity: UserAccountDataEntity): UserAccountDataEvent {
|
||||
return UserAccountDataEvent(
|
||||
type = entity.type ?: "",
|
||||
content = entity.contentStr?.let { adapter.fromJson(it) } ?: emptyMap()
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.session.identity.todelete
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Observer
|
||||
|
||||
// There will be a duplicated class when Integration manager will be merged, so delete this one
|
||||
inline fun <T> LiveData<T>.observeK(owner: LifecycleOwner, crossinline observer: (T?) -> Unit) {
|
||||
this.observe(owner, Observer { observer(it) })
|
||||
}
|
||||
|
||||
inline fun <T> LiveData<T>.observeNotNull(owner: LifecycleOwner, crossinline observer: (T) -> Unit) {
|
||||
this.observe(owner, Observer { it?.run(observer) })
|
||||
}
|
|
@ -30,5 +30,6 @@ abstract class UserAccountData : AccountDataContent {
|
|||
const val TYPE_PREVIEW_URLS = "org.matrix.preview_urls"
|
||||
const val TYPE_WIDGETS = "m.widgets"
|
||||
const val TYPE_PUSH_RULES = "m.push_rules"
|
||||
const val TYPE_IDENTITY = "m.identity"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.session.sync.model.accountdata
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class UserAccountDataIdentity(
|
||||
@Json(name = "type") override val type: String = TYPE_IDENTITY,
|
||||
@Json(name = "content") val content: IdentityContent? = null
|
||||
) : UserAccountData()
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class IdentityContent(
|
||||
@Json(name = "base_url") val baseUrl: String? = null
|
||||
)
|
|
@ -19,6 +19,7 @@ package im.vector.matrix.android.internal.session.user.accountdata
|
|||
import im.vector.matrix.android.internal.di.UserId
|
||||
import im.vector.matrix.android.internal.network.executeRequest
|
||||
import im.vector.matrix.android.internal.session.sync.model.accountdata.BreadcrumbsContent
|
||||
import im.vector.matrix.android.internal.session.sync.model.accountdata.IdentityContent
|
||||
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountData
|
||||
import im.vector.matrix.android.internal.task.Task
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
|
@ -31,6 +32,15 @@ internal interface UpdateUserAccountDataTask : Task<UpdateUserAccountDataTask.Pa
|
|||
fun getData(): Any
|
||||
}
|
||||
|
||||
data class IdentityParams(override val type: String = UserAccountData.TYPE_IDENTITY,
|
||||
private val identityContent: IdentityContent
|
||||
) : Params {
|
||||
|
||||
override fun getData(): Any {
|
||||
return identityContent
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Use [UserAccountDataDirectMessages] class?
|
||||
data class DirectChatParams(override val type: String = UserAccountData.TYPE_DIRECT_MESSAGES,
|
||||
private val directMessages: Map<String, List<String>>
|
||||
|
|
Loading…
Reference in New Issue