Merge pull request #1969 from vector-im/feature/dm_creation

DM creation: handled denied federation error
This commit is contained in:
Benoit Marty 2020-08-20 17:15:44 +02:00 committed by GitHub
commit 3bce0be96e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 64 additions and 27 deletions

View File

@ -4,7 +4,16 @@
<JetCodeStyleSettings> <JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS"> <option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value> <value>
<package name="kotlinx.android.synthetic" withSubpackages="true" static="false" /> <package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
</value>
</option>
<option name="PACKAGES_IMPORT_LAYOUT">
<value>
<package name="" alias="false" withSubpackages="true" />
<package name="java" alias="false" withSubpackages="true" />
<package name="javax" alias="false" withSubpackages="true" />
<package name="kotlin" alias="false" withSubpackages="true" />
<package name="" alias="true" withSubpackages="true" />
</value> </value>
</option> </option>
<option name="ALIGN_IN_COLUMNS_CASE_BRANCH" value="true" /> <option name="ALIGN_IN_COLUMNS_CASE_BRANCH" value="true" />

View File

@ -9,6 +9,7 @@ Improvements 🙌:
- Give user the possibility to prevent accidental call (#1869) - Give user the possibility to prevent accidental call (#1869)
- Display device information (name, id and key) in Cryptography setting screen (#1784) - Display device information (name, id and key) in Cryptography setting screen (#1784)
- Ensure users do not accidentally ignore other users (#1890) - Ensure users do not accidentally ignore other users (#1890)
- Better handling DM creation when invitees cannot be inviting due to denied federation
- Support new config.json format and config.domain.json files (#1682) - Support new config.json format and config.domain.json files (#1682)
- Increase Font size on Calling screen (#1643) - Increase Font size on Calling screen (#1643)
- Make the user's Avatar live in the general settings - Make the user's Avatar live in the general settings

View File

@ -18,8 +18,9 @@
package org.matrix.android.sdk.api.session.room.failure package org.matrix.android.sdk.api.session.room.failure
import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.Failure
import org.matrix.android.sdk.api.failure.MatrixError
sealed class CreateRoomFailure : Failure.FeatureFailure() { sealed class CreateRoomFailure : Failure.FeatureFailure() {
object CreatedWithTimeout : CreateRoomFailure()
object CreatedWithTimeout: CreateRoomFailure() data class CreatedWithFederationFailure(val matrixError: MatrixError) : CreateRoomFailure()
} }

View File

@ -18,6 +18,11 @@
package org.matrix.android.sdk.internal.session.room.create package org.matrix.android.sdk.internal.session.room.create
import com.zhuinden.monarchy.Monarchy import com.zhuinden.monarchy.Monarchy
import io.realm.RealmConfiguration
import kotlinx.coroutines.TimeoutCancellationException
import org.greenrobot.eventbus.EventBus
import org.matrix.android.sdk.api.failure.Failure
import org.matrix.android.sdk.api.failure.MatrixError
import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
@ -34,9 +39,6 @@ import org.matrix.android.sdk.internal.session.user.accountdata.DirectChatsHelpe
import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccountDataTask import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccountDataTask
import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.task.Task
import org.matrix.android.sdk.internal.util.awaitTransaction import org.matrix.android.sdk.internal.util.awaitTransaction
import io.realm.RealmConfiguration
import kotlinx.coroutines.TimeoutCancellationException
import org.greenrobot.eventbus.EventBus
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import javax.inject.Inject import javax.inject.Inject
@ -55,10 +57,26 @@ internal class DefaultCreateRoomTask @Inject constructor(
) : CreateRoomTask { ) : CreateRoomTask {
override suspend fun execute(params: CreateRoomParams): String { override suspend fun execute(params: CreateRoomParams): String {
val otherUserId = if (params.isDirect()) {
params.getFirstInvitedUserId()
?: throw IllegalStateException("You can't create a direct room without an invitedUser")
} else null
val createRoomBody = createRoomBodyBuilder.build(params) val createRoomBody = createRoomBodyBuilder.build(params)
val createRoomResponse = executeRequest<CreateRoomResponse>(eventBus) { val createRoomResponse = try {
apiCall = roomAPI.createRoom(createRoomBody) executeRequest<CreateRoomResponse>(eventBus) {
apiCall = roomAPI.createRoom(createRoomBody)
}
} catch (throwable: Throwable) {
if (throwable is Failure.ServerError
&& throwable.httpCode == 403
&& throwable.error.code == MatrixError.M_FORBIDDEN
&& throwable.error.message.startsWith("Federation denied with")) {
throw CreateRoomFailure.CreatedWithFederationFailure(throwable.error)
} else {
throw throwable
}
} }
val roomId = createRoomResponse.roomId val roomId = createRoomResponse.roomId
// Wait for room to come back from the sync (but it can maybe be in the DB if the sync response is received before) // Wait for room to come back from the sync (but it can maybe be in the DB if the sync response is received before)
@ -70,17 +88,14 @@ internal class DefaultCreateRoomTask @Inject constructor(
} catch (exception: TimeoutCancellationException) { } catch (exception: TimeoutCancellationException) {
throw CreateRoomFailure.CreatedWithTimeout throw CreateRoomFailure.CreatedWithTimeout
} }
if (params.isDirect()) { if (otherUserId != null) {
handleDirectChatCreation(params, roomId) handleDirectChatCreation(roomId, otherUserId)
} }
setReadMarkers(roomId) setReadMarkers(roomId)
return roomId return roomId
} }
private suspend fun handleDirectChatCreation(params: CreateRoomParams, roomId: String) { private suspend fun handleDirectChatCreation(roomId: String, otherUserId: String) {
val otherUserId = params.getFirstInvitedUserId()
?: throw IllegalStateException("You can't create a direct room without an invitedUser")
monarchy.awaitTransaction { realm -> monarchy.awaitTransaction { realm ->
RoomSummaryEntity.where(realm, roomId).findFirst()?.apply { RoomSummaryEntity.where(realm, roomId).findFirst()?.apply {
this.directUserId = otherUserId this.directUserId = otherUserId

View File

@ -48,9 +48,9 @@ import im.vector.app.features.userdirectory.UserDirectoryFragment
import im.vector.app.features.userdirectory.UserDirectorySharedAction import im.vector.app.features.userdirectory.UserDirectorySharedAction
import im.vector.app.features.userdirectory.UserDirectorySharedActionViewModel import im.vector.app.features.userdirectory.UserDirectorySharedActionViewModel
import im.vector.app.features.userdirectory.UserDirectoryViewModel import im.vector.app.features.userdirectory.UserDirectoryViewModel
import kotlinx.android.synthetic.main.activity.*
import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.Failure
import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure
import kotlinx.android.synthetic.main.activity.*
import java.net.HttpURLConnection import java.net.HttpURLConnection
import javax.inject.Inject import javax.inject.Inject
@ -138,19 +138,29 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() {
private fun renderCreationFailure(error: Throwable) { private fun renderCreationFailure(error: Throwable) {
hideWaitingView() hideWaitingView()
if (error is CreateRoomFailure.CreatedWithTimeout) { when (error) {
finish() is CreateRoomFailure.CreatedWithTimeout -> {
} else { finish()
val message = if (error is Failure.ServerError && error.httpCode == HttpURLConnection.HTTP_INTERNAL_ERROR /*500*/) { }
// This error happen if the invited userId does not exist. is CreateRoomFailure.CreatedWithFederationFailure -> {
getString(R.string.create_room_dm_failure) AlertDialog.Builder(this)
} else { .setMessage(getString(R.string.create_room_federation_error, error.matrixError.message))
errorFormatter.toHumanReadable(error) .setCancelable(false)
.setPositiveButton(R.string.ok) { _, _ -> finish() }
.show()
}
else -> {
val message = if (error is Failure.ServerError && error.httpCode == HttpURLConnection.HTTP_INTERNAL_ERROR /*500*/) {
// This error happen if the invited userId does not exist.
getString(R.string.create_room_dm_failure)
} else {
errorFormatter.toHumanReadable(error)
}
AlertDialog.Builder(this)
.setMessage(message)
.setPositiveButton(R.string.ok, null)
.show()
} }
AlertDialog.Builder(this)
.setMessage(message)
.setPositiveButton(R.string.ok, null)
.show()
} }
} }

View File

@ -1640,6 +1640,7 @@
<string name="create_room_public_description">"Anyone will be able to join this room"</string> <string name="create_room_public_description">"Anyone will be able to join this room"</string>
<string name="create_room_directory_title">"Room Directory"</string> <string name="create_room_directory_title">"Room Directory"</string>
<string name="create_room_directory_description">"Publish this room in the room directory"</string> <string name="create_room_directory_description">"Publish this room in the room directory"</string>
<string name="create_room_federation_error">"The room has been created, but some invitations have not been sent for the following reason:\n\n%s"</string>
<string name="keys_backup_unable_to_get_trust_info">"An error occurred getting trust info"</string> <string name="keys_backup_unable_to_get_trust_info">"An error occurred getting trust info"</string>
<string name="keys_backup_unable_to_get_keys_backup_data">"An error occurred getting keys backup data"</string> <string name="keys_backup_unable_to_get_keys_backup_data">"An error occurred getting keys backup data"</string>