From ee3f2877e954b48b3c6a093d51fddbf6da0c8ab8 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 21 Sep 2021 09:46:51 +0100 Subject: [PATCH] adding matrix SDK support for email adding and removing email pushes - email pushes make use of a new undocumented `brand` field, for now this field maps directly to the app display name so we can resuse it --- .../sdk/api/session/pushers/PushersService.kt | 28 ++++++++- .../sdk/internal/session/SessionComponent.kt | 4 +- ...HttpPusherWorker.kt => AddPusherWorker.kt} | 4 +- .../session/pushers/DefaultPushersService.kt | 61 +++++++++++++------ .../session/pushers/JsonPusherData.kt | 5 +- 5 files changed, 77 insertions(+), 25 deletions(-) rename matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/{AddHttpPusherWorker.kt => AddPusherWorker.kt} (95%) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt index a5ec100f64..2766147cc9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt @@ -27,7 +27,6 @@ interface PushersService { /** * Add a new HTTP pusher. - * Note that only `http` kind is supported by the SDK for now. * Ref: https://matrix.org/docs/spec/client_server/latest#post-matrix-client-r0-pushers-set * * @param pushkey This is a unique identifier for this pusher. The value you should use for @@ -64,6 +63,28 @@ interface PushersService { append: Boolean, withEventIdOnly: Boolean): UUID + /** + * Add a new Email pusher. + * Ref: https://matrix.org/docs/spec/client_server/latest#post-matrix-client-r0-pushers-set + * + * @param email The email address to send notifications to. + * If the kind is "email", this is the email address to send notifications to. + * @param lang The preferred language for receiving notifications (e.g. "en" or "en-US"). + * @param appDisplayName A human readable string that will allow the user to identify what application owns this pusher. + * @param deviceDisplayName A human readable string that will allow the user to identify what device owns this pusher. + * @param append If true, the homeserver should add another pusher with the given pushkey and App ID in addition + * to any others with different user IDs. Otherwise, the homeserver must remove any other pushers + * with the same App ID and pushkey for different users. + * @return A work request uuid. Can be used to listen to the status + * (LiveData status = workManager.getWorkInfoByIdLiveData()) + * @throws [InvalidParameterException] if a parameter is not correct + */ + fun addEmailPusher(email: String, + lang: String, + appDisplayName: String, + deviceDisplayName: String, + append: Boolean): UUID + /** * Directly ask the push gateway to send a push to this device * If successful, the push gateway has accepted the request. In this case, the app should receive a Push with the provided eventId. @@ -84,6 +105,11 @@ interface PushersService { */ suspend fun removeHttpPusher(pushkey: String, appId: String) + /** + * Remove the email pusher for a given email + */ + suspend fun removeEmailPusher(email: String) + /** * Get the current pushers, as a LiveData */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionComponent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionComponent.kt index 9a936b73c2..2003a66c94 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionComponent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionComponent.kt @@ -43,7 +43,7 @@ import org.matrix.android.sdk.internal.session.integrationmanager.IntegrationMan import org.matrix.android.sdk.internal.session.media.MediaModule import org.matrix.android.sdk.internal.session.openid.OpenIdModule import org.matrix.android.sdk.internal.session.profile.ProfileModule -import org.matrix.android.sdk.internal.session.pushers.AddHttpPusherWorker +import org.matrix.android.sdk.internal.session.pushers.AddPusherWorker import org.matrix.android.sdk.internal.session.pushers.PushersModule import org.matrix.android.sdk.internal.session.room.RoomModule import org.matrix.android.sdk.internal.session.room.relation.SendRelationWorker @@ -127,7 +127,7 @@ internal interface SessionComponent { fun inject(worker: SyncWorker) - fun inject(worker: AddHttpPusherWorker) + fun inject(worker: AddPusherWorker) fun inject(worker: SendVerificationMessageWorker) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/AddHttpPusherWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/AddPusherWorker.kt similarity index 95% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/AddHttpPusherWorker.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/AddPusherWorker.kt index c9d7ad2193..079fd1d3e5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/AddHttpPusherWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/AddPusherWorker.kt @@ -33,8 +33,8 @@ import org.matrix.android.sdk.internal.worker.SessionSafeCoroutineWorker import org.matrix.android.sdk.internal.worker.SessionWorkerParams import javax.inject.Inject -internal class AddHttpPusherWorker(context: Context, params: WorkerParameters) - : SessionSafeCoroutineWorker(context, params, Params::class.java) { +internal class AddPusherWorker(context: Context, params: WorkerParameters) + : SessionSafeCoroutineWorker(context, params, Params::class.java) { @JsonClass(generateAdapter = true) internal data class Params( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt index a772cf5ebb..a7fd3d435f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt @@ -66,27 +66,38 @@ internal class DefaultPushersService @Inject constructor( deviceDisplayName: String, url: String, append: Boolean, - withEventIdOnly: Boolean) - : UUID { - // Do some parameter checks. It's ok to throw Exception, to inform developer of the problem - if (pushkey.length > 512) throw InvalidParameterException("pushkey should not exceed 512 chars") - if (appId.length > 64) throw InvalidParameterException("appId should not exceed 64 chars") - if ("/_matrix/push/v1/notify" !in url) throw InvalidParameterException("url should contain '/_matrix/push/v1/notify'") + withEventIdOnly: Boolean + ) = addPusher( + JsonPusher( + pushKey = pushkey, + kind = "http", + appId = appId, + profileTag = profileTag, + lang = lang, + appDisplayName = appDisplayName, + deviceDisplayName = deviceDisplayName, + data = JsonPusherData(url, EVENT_ID_ONLY.takeIf { withEventIdOnly }), + append = append + ) + ) - val pusher = JsonPusher( - pushKey = pushkey, - kind = "http", - appId = appId, - appDisplayName = appDisplayName, - deviceDisplayName = deviceDisplayName, - profileTag = profileTag, - lang = lang, - data = JsonPusherData(url, EVENT_ID_ONLY.takeIf { withEventIdOnly }), - append = append) + override fun addEmailPusher(email: String, lang: String, appDisplayName: String, deviceDisplayName: String, append: Boolean) = addPusher( + JsonPusher(pushKey = email, + kind = "email", + appId = "m.email", + profileTag = "", + lang = lang, + appDisplayName = appDisplayName, + deviceDisplayName = deviceDisplayName, + data = JsonPusherData(brand = appDisplayName), + append = append + ) + ) - val params = AddHttpPusherWorker.Params(sessionId, pusher) - - val request = workManagerProvider.matrixOneTimeWorkRequestBuilder() + private fun addPusher(pusher: JsonPusher): UUID { + pusher.validateParameters() + val params = AddPusherWorker.Params(sessionId, pusher) + val request = workManagerProvider.matrixOneTimeWorkRequestBuilder() .setConstraints(WorkManagerProvider.workConstraints) .setInputData(WorkerParamsFactory.toData(params)) .setBackoffCriteria(BackoffPolicy.LINEAR, WorkManagerProvider.BACKOFF_DELAY_MILLIS, TimeUnit.MILLISECONDS) @@ -95,11 +106,23 @@ internal class DefaultPushersService @Inject constructor( return request.id } + private fun JsonPusher.validateParameters() { + // Do some parameter checks. It's ok to throw Exception, to inform developer of the problem + if (this.pushKey.length > 512) throw InvalidParameterException("pushkey should not exceed 512 chars") + if (this.appId.length > 64) throw InvalidParameterException("appId should not exceed 64 chars") + this.data?.url?.let { url -> if ("/_matrix/push/v1/notify" !in url) throw InvalidParameterException("url should contain '/_matrix/push/v1/notify'") } + } + override suspend fun removeHttpPusher(pushkey: String, appId: String) { val params = RemovePusherTask.Params(pushkey, appId) removePusherTask.execute(params) } + override suspend fun removeEmailPusher(email: String) { + val params = RemovePusherTask.Params(email, "m.email") + removePusherTask.execute(params) + } + override fun getPushersLive(): LiveData> { return monarchy.findAllMappedWithChanges( { realm -> PusherEntity.where(realm) }, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/JsonPusherData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/JsonPusherData.kt index c8d4d77fb1..42a8fa6ff3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/JsonPusherData.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/JsonPusherData.kt @@ -32,5 +32,8 @@ internal data class JsonPusherData( * Currently the only format available is 'event_id_only'. */ @Json(name = "format") - val format: String? = null + val format: String? = null, + + @Json(name = "brand") + val brand: String? = null )