/* * Copyright 2014 OpenMarket Ltd * Copyright 2017 Vector Creations 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 org.matrix.androidsdk.rest.model; import android.content.Context; import android.text.TextUtils; import org.matrix.androidsdk.R; import org.matrix.androidsdk.rest.callback.ApiCallback; import org.matrix.androidsdk.rest.client.ThirdPidRestClient; import java.util.UUID; /** * 3 pid */ public class ThreePid implements java.io.Serializable { /** * Types of third party media. * The list is not exhaustive and depends on the Identity server capabilities. */ public static final String MEDIUM_EMAIL = "email"; public static final String MEDIUM_MSISDN = "msisdn"; // state public static final int AUTH_STATE_TOKEN_UNKNOWN = 0; public static final int AUTH_STATE_TOKEN_REQUESTED = 1; public static final int AUTH_STATE_TOKEN_RECEIVED = 2; public static final int AUTH_STATE_TOKEN_SUBMITTED = 3; public static final int AUTH_STATE_TOKEN_AUTHENTIFICATED = 4; /** * Types of third party media. */ public String medium; /** * The email of the user * Used when MEDIUM_EMAIL */ public String emailAddress; /** * The phone number of the user * Used when MEDIUM_MSISDN */ public String phoneNumber; /** * The country of the user * Usedwhen MEDIUM_MSISDN */ public String country; /** * The current client secret key used during email validation. */ public String clientSecret; /** * The current session identifier during email validation. */ public String sid; /** * The number of attempts */ public int sendAttempt; /** * Current validation state (AUTH_STATE_XXX) */ private int mValidationState; /** * Two params constructors (MEDIUM_EMAIL) * * @param emailAddress the email address. * @param medium the identifier medium, MEDIUM_EMAIL in that case */ public ThreePid(String emailAddress, String medium) { this.medium = medium; this.emailAddress = emailAddress; if (TextUtils.equals(MEDIUM_EMAIL, this.medium) && !TextUtils.isEmpty(emailAddress)) { this.emailAddress = this.emailAddress.toLowerCase(); } this.clientSecret = UUID.randomUUID().toString(); } /** * Build a ThreePid with the given phone number and country (MEDIUM_MSISDN) * * @param phoneNumber the phone number (national or international format) * @param country country code of the phone number (can be empty if phone number has international format and starts by "+") * @param medium the identifier medium, MEDIUM_MSISDN in that case */ public ThreePid(String phoneNumber, String country, String medium) { this.medium = medium; this.phoneNumber = phoneNumber; this.country = country == null ? "" : country.toUpperCase(); clientSecret = UUID.randomUUID().toString(); } /** * Clear the validation parameters */ private void resetValidationParameters() { mValidationState = AUTH_STATE_TOKEN_UNKNOWN; clientSecret = UUID.randomUUID().toString(); sendAttempt = 1; sid = null; } /** * Request an email validation token. * @param restClient the rest client to use. * @param nextLink the nextLink * @param callback the callback when the operation is done */ public void requestEmailValidationToken(final ThirdPidRestClient restClient, String nextLink, final ApiCallback<Void> callback) { // sanity check if ((null != restClient) && (mValidationState != AUTH_STATE_TOKEN_REQUESTED)) { if (mValidationState != AUTH_STATE_TOKEN_UNKNOWN) { resetValidationParameters(); } mValidationState = AUTH_STATE_TOKEN_REQUESTED; restClient.requestEmailValidationToken(emailAddress, clientSecret, sendAttempt, nextLink, new ApiCallback<RequestEmailValidationResponse>() { @Override public void onSuccess(RequestEmailValidationResponse requestEmailValidationResponse) { if (TextUtils.equals(requestEmailValidationResponse.clientSecret, clientSecret)) { mValidationState = AUTH_STATE_TOKEN_RECEIVED; sid = requestEmailValidationResponse.sid; callback.onSuccess(null); } } private void commonError() { sendAttempt++; mValidationState = AUTH_STATE_TOKEN_UNKNOWN; } @Override public void onNetworkError(Exception e) { commonError(); callback.onNetworkError(e); } @Override public void onMatrixError(MatrixError e) { commonError(); callback.onMatrixError(e); } @Override public void onUnexpectedError(Exception e) { commonError(); callback.onUnexpectedError(e); } }); } } /** * Request a phone number validation token. * @param restClient the rest client to use. * @param nextLink the nextLink * @param callback the callback when the operation is done */ public void requestPhoneNumberValidationToken(final ThirdPidRestClient restClient, String nextLink, final ApiCallback<RequestPhoneNumberValidationResponse> callback) { // sanity check if ((null != restClient) && (mValidationState != AUTH_STATE_TOKEN_REQUESTED)) { if (mValidationState != AUTH_STATE_TOKEN_UNKNOWN) { resetValidationParameters(); } mValidationState = AUTH_STATE_TOKEN_REQUESTED; restClient.requestPhoneNumberValidationToken(phoneNumber, country, clientSecret, sendAttempt, nextLink, new ApiCallback<RequestPhoneNumberValidationResponse>() { @Override public void onSuccess(RequestPhoneNumberValidationResponse requestPhoneNumberValidationResponse) { if (TextUtils.equals(requestPhoneNumberValidationResponse.clientSecret, clientSecret)) { mValidationState = AUTH_STATE_TOKEN_RECEIVED; sid = requestPhoneNumberValidationResponse.sid; callback.onSuccess(requestPhoneNumberValidationResponse); } } private void commonError() { sendAttempt++; mValidationState = AUTH_STATE_TOKEN_UNKNOWN; } @Override public void onNetworkError(Exception e) { commonError(); callback.onNetworkError(e); } @Override public void onMatrixError(MatrixError e) { commonError(); callback.onMatrixError(e); } @Override public void onUnexpectedError(Exception e) { commonError(); callback.onUnexpectedError(e); } }); } } /** * Request the ownership validation of an email address or a phone number previously set * by {@link #requestEmailValidationToken(ThirdPidRestClient, String, ApiCallback)}. * @param restClient REST client * @param token the token generated by the requestEmailValidationToken or requestPhoneNumberValidationToken call * @param clientSecret the client secret which was supplied in the requestEmailValidationToken or requestPhoneNumberValidationToken call * @param sid the sid for the session * @param respCallback asynchronous callback response */ public void submitValidationToken(final ThirdPidRestClient restClient, final String token, final String clientSecret, final String sid, final ApiCallback<Boolean> respCallback) { // sanity check if (null != restClient) { restClient.submitValidationToken(medium, token, clientSecret, sid, respCallback); } } /** * Get the friendly name of the medium * * @param medium medium of the 3pid * @param context * @return friendly name of the medium */ public static String getMediumFriendlyName(final String medium, final Context context){ String mediumFriendlyName = ""; switch (medium){ case MEDIUM_EMAIL: mediumFriendlyName = context.getString(R.string.medium_email); break; case MEDIUM_MSISDN: mediumFriendlyName = context.getString(R.string.medium_phone_number); break; } return mediumFriendlyName; } }