Implement: Adding MSISDN (WIP)
This commit is contained in:
parent
5a21249022
commit
e309b30203
@ -77,5 +77,6 @@ class RealmSessionStoreMigration @Inject constructor() : RealmMigration {
|
|||||||
.setRequired(PendingThreePidEntityFields.SEND_ATTEMPT, true)
|
.setRequired(PendingThreePidEntityFields.SEND_ATTEMPT, true)
|
||||||
.addField(PendingThreePidEntityFields.SID, String::class.java)
|
.addField(PendingThreePidEntityFields.SID, String::class.java)
|
||||||
.setRequired(PendingThreePidEntityFields.SID, true)
|
.setRequired(PendingThreePidEntityFields.SID, true)
|
||||||
|
.addField(PendingThreePidEntityFields.SUBMIT_URL, String::class.java)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,5 +27,6 @@ internal open class PendingThreePidEntity(
|
|||||||
var msisdn: String? = null,
|
var msisdn: String? = null,
|
||||||
var clientSecret: String = "",
|
var clientSecret: String = "",
|
||||||
var sendAttempt: Int = 0,
|
var sendAttempt: Int = 0,
|
||||||
var sid: String = ""
|
var sid: String = "",
|
||||||
|
var submitUrl: String? = null
|
||||||
) : RealmObject()
|
) : RealmObject()
|
||||||
|
@ -20,7 +20,7 @@ import com.squareup.moshi.Json
|
|||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
internal data class AddThreePidResponse(
|
internal data class AddEmailResponse(
|
||||||
/**
|
/**
|
||||||
* Required. The session ID. Session IDs are opaque strings that must consist entirely
|
* Required. The session ID. Session IDs are opaque strings that must consist entirely
|
||||||
* of the characters [0-9a-zA-Z.=_-]. Their length must not exceed 255 characters and they must not be empty.
|
* of the characters [0-9a-zA-Z.=_-]. Their length must not exceed 255 characters and they must not be empty.
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 New Vector Ltd
|
||||||
|
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.internal.session.profile
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
internal data class AddMsisdnBody(
|
||||||
|
/**
|
||||||
|
* Required. A unique string generated by the client, and used to identify the validation attempt.
|
||||||
|
* It must be a string consisting of the characters [0-9a-zA-Z.=_-]. Its length must not exceed
|
||||||
|
* 255 characters and it must not be empty.
|
||||||
|
*/
|
||||||
|
@Json(name = "client_secret")
|
||||||
|
val clientSecret: String,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Required. The two-letter uppercase ISO-3166-1 alpha-2 country code that the number in
|
||||||
|
* phone_number should be parsed as if it were dialled from.
|
||||||
|
*/
|
||||||
|
@Json(name = "country")
|
||||||
|
val country: String,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Required. The phone number to validate.
|
||||||
|
*/
|
||||||
|
@Json(name = "phone_number")
|
||||||
|
val phoneNumber: String,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Required. The server will only send an SMS if the send_attempt is a number greater than the most
|
||||||
|
* recent one which it has seen, scoped to that country + phone_number + client_secret triple. This
|
||||||
|
* is to avoid repeatedly sending the same SMS in the case of request retries between the POSTing user
|
||||||
|
* and the identity server. The client should increment this value if they desire a new SMS (e.g. a
|
||||||
|
* reminder) to be sent.
|
||||||
|
*/
|
||||||
|
@Json(name = "send_attempt")
|
||||||
|
val sendAttempt: Int
|
||||||
|
)
|
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.internal.session.profile
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
internal data class AddMsisdnResponse(
|
||||||
|
/**
|
||||||
|
* Required. The session ID. Session IDs are opaque strings that must consist entirely of the characters [0-9a-zA-Z.=_-].
|
||||||
|
* Their length must not exceed 255 characters and they must not be empty.
|
||||||
|
*/
|
||||||
|
@Json(name = "sid")
|
||||||
|
val sid: String,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An optional field containing a URL where the client must submit the validation token to, with identical parameters to the Identity
|
||||||
|
* Service API's POST /validate/email/submitToken endpoint (without the requirement for an access token).
|
||||||
|
* The homeserver must send this token to the user (if applicable), who should then be prompted to provide it to the client.
|
||||||
|
*
|
||||||
|
* If this field is not present, the client can assume that verification will happen without the client's involvement provided
|
||||||
|
* the homeserver advertises this specification version in the /versions response (ie: r0.5.0).
|
||||||
|
*/
|
||||||
|
@Json(name = "submit_url")
|
||||||
|
val submitUrl: String? = null,
|
||||||
|
|
||||||
|
/* ==========================================================================================
|
||||||
|
* It seems that the homeserver is sending more data, we may need it
|
||||||
|
* ========================================================================================== */
|
||||||
|
|
||||||
|
@Json(name = "msisdn")
|
||||||
|
val msisdn: String? = null,
|
||||||
|
|
||||||
|
@Json(name = "intl_fmt")
|
||||||
|
val formattedMsisdn: String? = null,
|
||||||
|
|
||||||
|
@Json(name = "success")
|
||||||
|
val success: Boolean? = null
|
||||||
|
)
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
package org.matrix.android.sdk.internal.session.profile
|
package org.matrix.android.sdk.internal.session.profile
|
||||||
|
|
||||||
|
import com.google.i18n.phonenumbers.PhoneNumberUtil
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import org.matrix.android.sdk.api.session.identity.ThreePid
|
import org.matrix.android.sdk.api.session.identity.ThreePid
|
||||||
@ -40,31 +41,76 @@ internal class DefaultAddThreePidTask @Inject constructor(
|
|||||||
private val eventBus: EventBus) : AddThreePidTask() {
|
private val eventBus: EventBus) : AddThreePidTask() {
|
||||||
|
|
||||||
override suspend fun execute(params: Params) {
|
override suspend fun execute(params: Params) {
|
||||||
|
when (params.threePid) {
|
||||||
|
is ThreePid.Email -> addEmail(params.threePid)
|
||||||
|
is ThreePid.Msisdn -> addMsisdn(params.threePid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun addEmail(threePid: ThreePid.Email) {
|
||||||
val clientSecret = UUID.randomUUID().toString()
|
val clientSecret = UUID.randomUUID().toString()
|
||||||
val sendAttempt = 1
|
val sendAttempt = 1
|
||||||
val result = when (params.threePid) {
|
|
||||||
is ThreePid.Email ->
|
val result = executeRequest<AddEmailResponse>(eventBus) {
|
||||||
executeRequest<AddThreePidResponse>(eventBus) {
|
val body = AddEmailBody(
|
||||||
val body = AddEmailBody(
|
clientSecret = clientSecret,
|
||||||
email = params.threePid.email,
|
email = threePid.email,
|
||||||
sendAttempt = sendAttempt,
|
sendAttempt = sendAttempt
|
||||||
clientSecret = clientSecret
|
)
|
||||||
)
|
apiCall = profileAPI.addEmail(body)
|
||||||
apiCall = profileAPI.addEmail(body)
|
|
||||||
}
|
|
||||||
is ThreePid.Msisdn -> TODO()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store as a pending three pid
|
// Store as a pending three pid
|
||||||
monarchy.awaitTransaction { realm ->
|
monarchy.awaitTransaction { realm ->
|
||||||
PendingThreePid(
|
PendingThreePid(
|
||||||
threePid = params.threePid,
|
threePid = threePid,
|
||||||
clientSecret = clientSecret,
|
clientSecret = clientSecret,
|
||||||
sendAttempt = sendAttempt,
|
sendAttempt = sendAttempt,
|
||||||
sid = result.sid
|
sid = result.sid,
|
||||||
|
submitUrl = null
|
||||||
)
|
)
|
||||||
.let { pendingThreePidMapper.map(it) }
|
.let { pendingThreePidMapper.map(it) }
|
||||||
.let { realm.copyToRealm(it) }
|
.let { realm.copyToRealm(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun addMsisdn(threePid: ThreePid.Msisdn) {
|
||||||
|
val clientSecret = UUID.randomUUID().toString()
|
||||||
|
val sendAttempt = 1
|
||||||
|
|
||||||
|
// Get country code from the phone number
|
||||||
|
val phoneNumber = threePid.msisdn
|
||||||
|
|
||||||
|
val parsedNumber = PhoneNumberUtil.getInstance().parse(phoneNumber, null)
|
||||||
|
val countryCode = parsedNumber.countryCode
|
||||||
|
|
||||||
|
val result = executeRequest<AddMsisdnResponse>(eventBus) {
|
||||||
|
val body = AddMsisdnBody(
|
||||||
|
clientSecret = clientSecret,
|
||||||
|
country = countryCode.asString(), // TODO Convert to String,
|
||||||
|
phoneNumber = parsedNumber.nationalNumber.toString(),
|
||||||
|
sendAttempt = sendAttempt
|
||||||
|
)
|
||||||
|
apiCall = profileAPI.addMsisdn(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store as a pending three pid
|
||||||
|
monarchy.awaitTransaction { realm ->
|
||||||
|
PendingThreePid(
|
||||||
|
threePid = threePid,
|
||||||
|
clientSecret = clientSecret,
|
||||||
|
sendAttempt = sendAttempt,
|
||||||
|
sid = result.sid,
|
||||||
|
submitUrl = result.submitUrl
|
||||||
|
)
|
||||||
|
.let { pendingThreePidMapper.map(it) }
|
||||||
|
.let { realm.copyToRealm(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Int.asString(): String {
|
||||||
|
// TODO
|
||||||
|
return ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,9 @@ internal data class PendingThreePid(
|
|||||||
val threePid: ThreePid,
|
val threePid: ThreePid,
|
||||||
val clientSecret: String,
|
val clientSecret: String,
|
||||||
val sendAttempt: Int,
|
val sendAttempt: Int,
|
||||||
val sid: String
|
// For Msisdn and Email
|
||||||
|
val sid: String,
|
||||||
|
// For Msisdn only
|
||||||
|
val submitUrl: String?
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,7 +29,8 @@ internal class PendingThreePidMapper @Inject constructor() {
|
|||||||
?: error("Invalid data"),
|
?: error("Invalid data"),
|
||||||
clientSecret = entity.clientSecret,
|
clientSecret = entity.clientSecret,
|
||||||
sendAttempt = entity.sendAttempt,
|
sendAttempt = entity.sendAttempt,
|
||||||
sid = entity.sid
|
sid = entity.sid,
|
||||||
|
submitUrl = entity.submitUrl
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +40,8 @@ internal class PendingThreePidMapper @Inject constructor() {
|
|||||||
msisdn = domain.threePid.takeIf { it is ThreePid.Msisdn }?.value,
|
msisdn = domain.threePid.takeIf { it is ThreePid.Msisdn }?.value,
|
||||||
clientSecret = domain.clientSecret,
|
clientSecret = domain.clientSecret,
|
||||||
sendAttempt = domain.sendAttempt,
|
sendAttempt = domain.sendAttempt,
|
||||||
sid = domain.sid
|
sid = domain.sid,
|
||||||
|
submitUrl = domain.submitUrl
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,13 @@ internal interface ProfileAPI {
|
|||||||
* Ref: https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-account-3pid-email-requesttoken
|
* Ref: https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-account-3pid-email-requesttoken
|
||||||
*/
|
*/
|
||||||
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/3pid/email/requestToken")
|
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/3pid/email/requestToken")
|
||||||
fun addEmail(@Body body: AddEmailBody): Call<AddThreePidResponse>
|
fun addEmail(@Body body: AddEmailBody): Call<AddEmailResponse>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ref: https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-account-3pid-msisdn-requesttoken
|
||||||
|
*/
|
||||||
|
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/3pid/msisdn/requestToken")
|
||||||
|
fun addMsisdn(@Body body: AddMsisdnBody): Call<AddMsisdnResponse>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ref: https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-account-3pid-add
|
* Ref: https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-account-3pid-add
|
||||||
|
@ -30,6 +30,7 @@ import im.vector.app.core.extensions.configureWith
|
|||||||
import im.vector.app.core.extensions.exhaustive
|
import im.vector.app.core.extensions.exhaustive
|
||||||
import im.vector.app.core.extensions.hideKeyboard
|
import im.vector.app.core.extensions.hideKeyboard
|
||||||
import im.vector.app.core.extensions.isEmail
|
import im.vector.app.core.extensions.isEmail
|
||||||
|
import im.vector.app.core.extensions.isMsisdn
|
||||||
import im.vector.app.core.platform.OnBackPressed
|
import im.vector.app.core.platform.OnBackPressed
|
||||||
import im.vector.app.core.platform.VectorBaseActivity
|
import im.vector.app.core.platform.VectorBaseActivity
|
||||||
import im.vector.app.core.platform.VectorBaseFragment
|
import im.vector.app.core.platform.VectorBaseFragment
|
||||||
@ -123,6 +124,11 @@ class ThreePidsSettingsFragment @Inject constructor(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!msisdn.isMsisdn()) {
|
||||||
|
viewModel.handle(ThreePidsSettingsAction.ChangeState(ThreePidsSettingsState.AddingPhoneNumber(getString(R.string.login_msisdn_error_other))))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
viewModel.handle(ThreePidsSettingsAction.AddThreePid(ThreePid.Msisdn(safeMsisdn)))
|
viewModel.handle(ThreePidsSettingsAction.AddThreePid(ThreePid.Msisdn(safeMsisdn)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user