From 763ac958bfa786ca310dd043ffe4c5457671f7b9 Mon Sep 17 00:00:00 2001 From: Jay Panchal Date: Fri, 25 Oct 2024 10:48:09 +0530 Subject: [PATCH 01/10] Working on HQ user Invitation Working on HQ user Invitation API integration --- app/AndroidManifest.xml | 28 ++++- app/res/layout/activity_hquser_invite.xml | 72 +++++++++++ app/res/values/strings.xml | 1 + .../connect/HQUserInviteActivity.java | 112 ++++++++++++++++++ .../connect/network/ApiConnectId.java | 32 +++-- 5 files changed, 230 insertions(+), 15 deletions(-) create mode 100644 app/res/layout/activity_hquser_invite.xml create mode 100644 app/src/org/commcare/activities/connect/HQUserInviteActivity.java diff --git a/app/AndroidManifest.xml b/app/AndroidManifest.xml index da9698ed6b..1c8cf8f6d9 100644 --- a/app/AndroidManifest.xml +++ b/app/AndroidManifest.xml @@ -1,7 +1,7 @@ - @@ -130,19 +130,35 @@ android:exported="true" android:permission="com.google.android.gms.auth.api.phone.permission.SEND"> - + + android:name="org.commcare.activities.connect.HQUserInviteActivity" + android:exported="true"> + + + + + + + + + + + + diff --git a/app/res/layout/activity_hquser_invite.xml b/app/res/layout/activity_hquser_invite.xml new file mode 100644 index 0000000000..f88c3549e7 --- /dev/null +++ b/app/res/layout/activity_hquser_invite.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/res/values/strings.xml b/app/res/values/strings.xml index bd8d815784..ed660f260f 100644 --- a/app/res/values/strings.xml +++ b/app/res/values/strings.xml @@ -42,6 +42,7 @@ https://%s/api/payment/%s/confirm https://connectid.dimagi.com/users/recover/initiate_deactivation https://connectid.dimagi.com/users/recover/confirm_deactivation + https://connectid.dimagi.com/settings/users/commcare/confirm_connectid_user diff --git a/app/src/org/commcare/activities/connect/HQUserInviteActivity.java b/app/src/org/commcare/activities/connect/HQUserInviteActivity.java new file mode 100644 index 0000000000..5fb02a6aa4 --- /dev/null +++ b/app/src/org/commcare/activities/connect/HQUserInviteActivity.java @@ -0,0 +1,112 @@ +package org.commcare.activities.connect; + +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.widget.Toast; + +import androidx.appcompat.app.AppCompatActivity; + +import org.commcare.connect.network.ApiConnectId; +import org.commcare.connect.network.IApiCallback; +import org.commcare.dalvik.R; +import org.commcare.dalvik.databinding.ActivityHquserInviteBinding; +import org.javarosa.core.io.StreamsUtil; +import org.javarosa.core.services.Logger; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.Locale; + +public class HQUserInviteActivity extends AppCompatActivity { + + private ActivityHquserInviteBinding binding; + String domain; + String inviteCode; + String username; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + binding = ActivityHquserInviteBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + Intent intent = getIntent(); + Uri data = intent.getData(); + + if (data != null && "connect".equals(data.getScheme())) { + List pathSegments = data.getPathSegments(); + if (pathSegments.size() >= 3) { + domain = pathSegments.get(0); + inviteCode = pathSegments.get(1); + username = pathSegments.get(2); + } + } + + binding.btnAcceptInvitation.setOnClickListener(view -> handleInvitation(HQUserInviteActivity.this, inviteCode, true)); + + binding.btnAcceptInvitation.setOnClickListener(view -> handleInvitation(HQUserInviteActivity.this, inviteCode, false)); + } + + private void handleInvitation(Context context, String inviteCode, boolean acceptStatus) { + IApiCallback callback = new IApiCallback() { + @Override + public void processSuccess(int responseCode, InputStream responseData) { + try { + String responseAsString = new String(StreamsUtil.inputStreamToByteArray(responseData)); + if (responseAsString.length() > 0) { + JSONObject json = new JSONObject(responseAsString); + + } + } catch (IOException | JSONException e) { + Logger.exception("Parsing return from OTP request", e); + } + } + + @Override + public void processFailure(int responseCode, IOException e) { + String message = ""; + if (responseCode > 0) { + message = String.format(Locale.getDefault(), "(%d)", responseCode); + } else if (e != null) { + message = e.toString(); + } + setErrorMessage("Error requesting SMS code" + message); + } + + @Override + public void processNetworkFailure() { + setErrorMessage(getString(R.string.recovery_network_unavailable)); + } + + @Override + public void processOldApiError() { + setErrorMessage(getString(R.string.recovery_network_outdated)); + } + }; + + boolean isBusy = !ApiConnectId.hqUserInvitation(HQUserInviteActivity.this, inviteCode, acceptStatus, callback); + if (isBusy) { + Toast.makeText(HQUserInviteActivity.this, R.string.busy_message, Toast.LENGTH_SHORT).show(); + } + } + + public void setErrorMessage(String message) { +// if (message == null) { +// binding.connectPhoneVerifyError.setVisibility(View.GONE); +// } else { +// binding.connectPhoneVerifyError.setVisibility(View.VISIBLE); +// binding.connectPhoneVerifyError.setText(message); +// } + } + + + @Override + protected void onDestroy() { + super.onDestroy(); + binding = null; + } +} diff --git a/app/src/org/commcare/connect/network/ApiConnectId.java b/app/src/org/commcare/connect/network/ApiConnectId.java index f330c39316..1deb5ddf25 100644 --- a/app/src/org/commcare/connect/network/ApiConnectId.java +++ b/app/src/org/commcare/connect/network/ApiConnectId.java @@ -7,10 +7,10 @@ import org.commcare.CommCareApplication; import org.commcare.android.database.connect.models.ConnectLinkedAppRecord; +import org.commcare.android.database.connect.models.ConnectUserRecord; import org.commcare.connect.ConnectConstants; import org.commcare.connect.ConnectDatabaseHelper; import org.commcare.connect.ConnectManager; -import org.commcare.android.database.connect.models.ConnectUserRecord; import org.commcare.core.network.AuthInfo; import org.commcare.dalvik.R; import org.commcare.preferences.HiddenPreferences; @@ -87,7 +87,7 @@ public static AuthInfo.TokenAuth retrieveHqTokenApi(Context context, String hqUs Date expiration = new Date(); key = ConnectConstants.CONNECT_KEY_EXPIRES; int seconds = json.has(key) ? json.getInt(key) : 0; - expiration.setTime(expiration.getTime() + ((long)seconds * 1000)); + expiration.setTime(expiration.getTime() + ((long) seconds * 1000)); String seatedAppId = CommCareApplication.instance().getCurrentApp().getUniqueId(); ConnectDatabaseHelper.storeHqToken(context, seatedAppId, hqUsername, token, expiration); @@ -106,7 +106,7 @@ public static ConnectNetworkHelper.PostResult makeHeartbeatRequestSync(Context c String url = context.getString(R.string.ConnectHeartbeatURL); HashMap params = new HashMap<>(); String token = FirebaseMessagingUtil.getFCMToken(); - if(token != null) { + if (token != null) { params.put("fcm_token", token); boolean useFormEncoding = true; return ConnectNetworkHelper.postSync(context, url, API_VERSION_CONNECT_ID, retrieveConnectIdTokenSync(context), params, useFormEncoding, true); @@ -147,7 +147,7 @@ public static AuthInfo.TokenAuth retrieveConnectIdTokenSync(Context context) { Date expiration = new Date(); key = ConnectConstants.CONNECT_KEY_EXPIRES; int seconds = json.has(key) ? json.getInt(key) : 0; - expiration.setTime(expiration.getTime() + ((long)seconds * 1000)); + expiration.setTime(expiration.getTime() + ((long) seconds * 1000)); user.updateConnectToken(token, expiration); ConnectDatabaseHelper.storeUser(context, user); @@ -288,11 +288,11 @@ public static boolean updateUserProfile(Context context, String username, int urlId = R.string.ConnectUpdateProfileURL; HashMap params = new HashMap<>(); - if(secondaryPhone != null) { + if (secondaryPhone != null) { params.put("secondary_phone", secondaryPhone); } - if(displayName != null) { + if (displayName != null) { params.put("name", displayName); } @@ -337,7 +337,7 @@ public static boolean requestRecoveryOtpSecondary(Context context, String phone, } public static boolean requestVerificationOtpSecondary(Context context, String username, String password, - IApiCallback callback) { + IApiCallback callback) { int urlId = R.string.ConnectVerifySecondaryURL; AuthInfo authInfo = new AuthInfo.ProvidedAuth(username, password, false); @@ -388,7 +388,7 @@ public static boolean confirmRecoveryOtpSecondary(Context context, String phone, } public static boolean confirmVerificationOtpSecondary(Context context, String username, String password, - String token, IApiCallback callback) { + String token, IApiCallback callback) { int urlId = R.string.ConnectVerifyConfirmSecondaryOTPURL; AuthInfo authInfo = new AuthInfo.ProvidedAuth(username, password, false); @@ -399,7 +399,7 @@ public static boolean confirmVerificationOtpSecondary(Context context, String us API_VERSION_CONNECT_ID, authInfo, params, false, false, callback); } - public static boolean requestInitiateAccountDeactivation(Context context, String phone,String secretKey, IApiCallback callback) { + public static boolean requestInitiateAccountDeactivation(Context context, String phone, String secretKey, IApiCallback callback) { int urlId = R.string.ConnectInitiateUserAccountDeactivationURL; AuthInfo authInfo = new AuthInfo.NoAuth(); @@ -424,4 +424,18 @@ public static boolean confirmUserDeactivation(Context context, String phone, Str return ConnectNetworkHelper.post(context, context.getString(urlId), API_VERSION_CONNECT_ID, authInfo, params, false, false, callback); } + + public static boolean hqUserInvitation(Context context, String invitationCode, boolean acceptStatus, IApiCallback callback) { + int urlId = R.string.ConnectConfirmUserInvitation; + AuthInfo authInfo = new AuthInfo.NoAuth(); + AuthInfo.TokenAuth connectIdToken = ApiConnectId.retrieveConnectIdTokenSync(context); + + HashMap params = new HashMap<>(); + params.put("invite_code", invitationCode); + params.put("token", connectIdToken.toString()); + params.put("accept", String.valueOf(acceptStatus)); + + return ConnectNetworkHelper.post(context, context.getString(urlId), + API_VERSION_CONNECT_ID, authInfo, params, false, false, callback); + } } From 10d717a208f1589af404574f2ef5c1d7390aad4d Mon Sep 17 00:00:00 2001 From: Jay Panchal Date: Tue, 12 Nov 2024 14:48:30 +0530 Subject: [PATCH 02/10] Set deep-linking code Set deep-linking code --- app/AndroidManifest.xml | 19 ++++++++++--------- app/res/layout/activity_hquser_invite.xml | 4 ++-- .../connect/HQUserInviteActivity.java | 15 +++++++++------ 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/app/AndroidManifest.xml b/app/AndroidManifest.xml index 1c8cf8f6d9..7b37f49106 100644 --- a/app/AndroidManifest.xml +++ b/app/AndroidManifest.xml @@ -143,22 +143,23 @@ - - - - - - - + + + + + + + + + + diff --git a/app/res/layout/activity_hquser_invite.xml b/app/res/layout/activity_hquser_invite.xml index f88c3549e7..05a5d23251 100644 --- a/app/res/layout/activity_hquser_invite.xml +++ b/app/res/layout/activity_hquser_invite.xml @@ -43,7 +43,7 @@ app:layout_constraintTop_toBottomOf="@+id/connectMediumTextView" app:roundButtonBackgroundColor="@color/connect_blue_color" app:roundButtonTextColor="@color/white" - app:roundButtonTextSize="6" + app:roundButtonTextSize="6sp" tools:text="Accept" /> pathSegments = data.getPathSegments(); if (pathSegments.size() >= 3) { - domain = pathSegments.get(0); - inviteCode = pathSegments.get(1); + callBackURL = pathSegments.get(1); username = pathSegments.get(2); + inviteCode = pathSegments.get(3); + domain = pathSegments.get(4); } } - binding.btnAcceptInvitation.setOnClickListener(view -> handleInvitation(HQUserInviteActivity.this, inviteCode, true)); binding.btnAcceptInvitation.setOnClickListener(view -> handleInvitation(HQUserInviteActivity.this, inviteCode, false)); @@ -59,7 +61,8 @@ public void processSuccess(int responseCode, InputStream responseData) { String responseAsString = new String(StreamsUtil.inputStreamToByteArray(responseData)); if (responseAsString.length() > 0) { JSONObject json = new JSONObject(responseAsString); - + startActivity(new Intent(HQUserInviteActivity.this, DispatchActivity.class)); + finish(); } } catch (IOException | JSONException e) { Logger.exception("Parsing return from OTP request", e); From 34c179c4fcf2642d042d2b273c6712877d3c50c5 Mon Sep 17 00:00:00 2001 From: Jay Panchal Date: Tue, 12 Nov 2024 19:37:26 +0530 Subject: [PATCH 03/10] Update update invitation logic Update update invitation logic --- app/res/layout/activity_hquser_invite.xml | 26 +++++++++++---- app/res/values-fr/strings.xml | 4 +++ app/res/values-pt/strings.xml | 4 +++ app/res/values/strings.xml | 4 +++ .../connect/HQUserInviteActivity.java | 33 +++++++++---------- .../connect/network/ApiConnectId.java | 5 +-- 6 files changed, 49 insertions(+), 27 deletions(-) diff --git a/app/res/layout/activity_hquser_invite.xml b/app/res/layout/activity_hquser_invite.xml index 05a5d23251..229ffa77b6 100644 --- a/app/res/layout/activity_hquser_invite.xml +++ b/app/res/layout/activity_hquser_invite.xml @@ -19,13 +19,13 @@ app:layout_constraintStart_toStartOf="parent" /> @@ -36,15 +36,15 @@ android:layout_height="40dp" android:layout_marginHorizontal="50dp" android:layout_marginTop="30dp" - android:text="Accept" + android:text="@string/connect_hq_invitation_accept" android:visibility="visible" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/connectMediumTextView" + app:layout_constraintTop_toBottomOf="@+id/tvHqInvitationHeaderTitle" app:roundButtonBackgroundColor="@color/connect_blue_color" app:roundButtonTextColor="@color/white" app:roundButtonTextSize="6sp" - tools:text="Accept" /> + tools:text="@string/connect_hq_invitation_accept" /> + tools:text="@string/connect_hq_invitation_denied" /> + + Apprendre Livraison Application CommCare + + Vous êtes invité au domaine du projet CommCareHQ en tant que %s + Accepter + Refusé diff --git a/app/res/values-pt/strings.xml b/app/res/values-pt/strings.xml index 2e011377a7..53bcb83964 100644 --- a/app/res/values-pt/strings.xml +++ b/app/res/values-pt/strings.xml @@ -481,4 +481,8 @@ Aprender Entrega Aplicativo CommCare + + Está convidado para o domínio do projeto CommCareHQ como %s + Aceitar + Negado \ No newline at end of file diff --git a/app/res/values/strings.xml b/app/res/values/strings.xml index ed660f260f..53c084c432 100644 --- a/app/res/values/strings.xml +++ b/app/res/values/strings.xml @@ -865,4 +865,8 @@ Delivery Expired CommCare App + + You are invited to CommCareHQ project domain as %s + Accept + Denied diff --git a/app/src/org/commcare/activities/connect/HQUserInviteActivity.java b/app/src/org/commcare/activities/connect/HQUserInviteActivity.java index a37e89249d..189d721641 100644 --- a/app/src/org/commcare/activities/connect/HQUserInviteActivity.java +++ b/app/src/org/commcare/activities/connect/HQUserInviteActivity.java @@ -1,10 +1,9 @@ package org.commcare.activities.connect; -import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Bundle; -import android.util.Log; +import android.view.View; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; @@ -16,8 +15,6 @@ import org.commcare.dalvik.databinding.ActivityHquserInviteBinding; import org.javarosa.core.io.StreamsUtil; import org.javarosa.core.services.Logger; -import org.json.JSONException; -import org.json.JSONObject; import java.io.IOException; import java.io.InputStream; @@ -39,7 +36,7 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(binding.getRoot()); Intent intent = getIntent(); Uri data = intent.getData(); - if(data != null) { + if (data != null) { List pathSegments = data.getPathSegments(); if (pathSegments.size() >= 3) { callBackURL = pathSegments.get(1); @@ -48,23 +45,24 @@ protected void onCreate(Bundle savedInstanceState) { domain = pathSegments.get(4); } } - binding.btnAcceptInvitation.setOnClickListener(view -> handleInvitation(HQUserInviteActivity.this, inviteCode, true)); + binding.btnAcceptInvitation.setOnClickListener(view -> handleInvitation(callBackURL, inviteCode, true)); - binding.btnAcceptInvitation.setOnClickListener(view -> handleInvitation(HQUserInviteActivity.this, inviteCode, false)); + binding.btnDeniedInvitation.setOnClickListener(view -> handleInvitation(callBackURL, inviteCode, false)); + + binding.tvHqInvitationHeaderTitle.setText(getString(R.string.connect_hq_invitation_heading,username)); } - private void handleInvitation(Context context, String inviteCode, boolean acceptStatus) { + private void handleInvitation(String callBackUrl, String inviteCode, boolean acceptStatus) { IApiCallback callback = new IApiCallback() { @Override public void processSuccess(int responseCode, InputStream responseData) { try { String responseAsString = new String(StreamsUtil.inputStreamToByteArray(responseData)); if (responseAsString.length() > 0) { - JSONObject json = new JSONObject(responseAsString); startActivity(new Intent(HQUserInviteActivity.this, DispatchActivity.class)); finish(); } - } catch (IOException | JSONException e) { + } catch (IOException e) { Logger.exception("Parsing return from OTP request", e); } } @@ -91,22 +89,21 @@ public void processOldApiError() { } }; - boolean isBusy = !ApiConnectId.hqUserInvitation(HQUserInviteActivity.this, inviteCode, acceptStatus, callback); + boolean isBusy = !ApiConnectId.hqUserInvitation(HQUserInviteActivity.this, callBackUrl, inviteCode, acceptStatus, callback); if (isBusy) { Toast.makeText(HQUserInviteActivity.this, R.string.busy_message, Toast.LENGTH_SHORT).show(); } } public void setErrorMessage(String message) { -// if (message == null) { -// binding.connectPhoneVerifyError.setVisibility(View.GONE); -// } else { -// binding.connectPhoneVerifyError.setVisibility(View.VISIBLE); -// binding.connectPhoneVerifyError.setText(message); -// } + if (message == null) { + binding.connectPhoneVerifyError.setVisibility(View.GONE); + } else { + binding.connectPhoneVerifyError.setVisibility(View.VISIBLE); + binding.connectPhoneVerifyError.setText(message); + } } - @Override protected void onDestroy() { super.onDestroy(); diff --git a/app/src/org/commcare/connect/network/ApiConnectId.java b/app/src/org/commcare/connect/network/ApiConnectId.java index 1deb5ddf25..362e4cc763 100644 --- a/app/src/org/commcare/connect/network/ApiConnectId.java +++ b/app/src/org/commcare/connect/network/ApiConnectId.java @@ -425,14 +425,15 @@ public static boolean confirmUserDeactivation(Context context, String phone, Str API_VERSION_CONNECT_ID, authInfo, params, false, false, callback); } - public static boolean hqUserInvitation(Context context, String invitationCode, boolean acceptStatus, IApiCallback callback) { + public static boolean hqUserInvitation(Context context,String callBackUrl, String invitationCode, boolean acceptStatus, IApiCallback callback) { int urlId = R.string.ConnectConfirmUserInvitation; AuthInfo authInfo = new AuthInfo.NoAuth(); AuthInfo.TokenAuth connectIdToken = ApiConnectId.retrieveConnectIdTokenSync(context); HashMap params = new HashMap<>(); + params.put("callback_url", callBackUrl); params.put("invite_code", invitationCode); - params.put("token", connectIdToken.toString()); + params.put("user_token", connectIdToken.toString()); params.put("accept", String.valueOf(acceptStatus)); return ConnectNetworkHelper.post(context, context.getString(urlId), From 44ee961f2b233875c203526dbb8c77c4300ab7fa Mon Sep 17 00:00:00 2001 From: Jay Panchal Date: Fri, 15 Nov 2024 16:49:40 +0530 Subject: [PATCH 04/10] Update API logic Update API logic --- app/AndroidManifest.xml | 2 +- .../connect/HQUserInviteActivity.java | 4 ++-- .../connect/network/ApiConnectId.java | 23 ++++++++++--------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/app/AndroidManifest.xml b/app/AndroidManifest.xml index 7b37f49106..9784dce196 100644 --- a/app/AndroidManifest.xml +++ b/app/AndroidManifest.xml @@ -137,7 +137,7 @@ - + diff --git a/app/src/org/commcare/activities/connect/HQUserInviteActivity.java b/app/src/org/commcare/activities/connect/HQUserInviteActivity.java index 189d721641..d7d5be084c 100644 --- a/app/src/org/commcare/activities/connect/HQUserInviteActivity.java +++ b/app/src/org/commcare/activities/connect/HQUserInviteActivity.java @@ -47,7 +47,7 @@ protected void onCreate(Bundle savedInstanceState) { } binding.btnAcceptInvitation.setOnClickListener(view -> handleInvitation(callBackURL, inviteCode, true)); - binding.btnDeniedInvitation.setOnClickListener(view -> handleInvitation(callBackURL, inviteCode, false)); + binding.btnDeniedInvitation.setOnClickListener(view -> finish()); binding.tvHqInvitationHeaderTitle.setText(getString(R.string.connect_hq_invitation_heading,username)); } @@ -89,7 +89,7 @@ public void processOldApiError() { } }; - boolean isBusy = !ApiConnectId.hqUserInvitation(HQUserInviteActivity.this, callBackUrl, inviteCode, acceptStatus, callback); + boolean isBusy = !ApiConnectId.hqUserInvitation(HQUserInviteActivity.this, callBackUrl, inviteCode, callback); if (isBusy) { Toast.makeText(HQUserInviteActivity.this, R.string.busy_message, Toast.LENGTH_SHORT).show(); } diff --git a/app/src/org/commcare/connect/network/ApiConnectId.java b/app/src/org/commcare/connect/network/ApiConnectId.java index 362e4cc763..d0e0b9f57a 100644 --- a/app/src/org/commcare/connect/network/ApiConnectId.java +++ b/app/src/org/commcare/connect/network/ApiConnectId.java @@ -425,18 +425,19 @@ public static boolean confirmUserDeactivation(Context context, String phone, Str API_VERSION_CONNECT_ID, authInfo, params, false, false, callback); } - public static boolean hqUserInvitation(Context context,String callBackUrl, String invitationCode, boolean acceptStatus, IApiCallback callback) { + public static boolean hqUserInvitation(Context context, String callBackUrl, String invitationCode, IApiCallback callback) { int urlId = R.string.ConnectConfirmUserInvitation; AuthInfo authInfo = new AuthInfo.NoAuth(); - AuthInfo.TokenAuth connectIdToken = ApiConnectId.retrieveConnectIdTokenSync(context); - - HashMap params = new HashMap<>(); - params.put("callback_url", callBackUrl); - params.put("invite_code", invitationCode); - params.put("user_token", connectIdToken.toString()); - params.put("accept", String.valueOf(acceptStatus)); - - return ConnectNetworkHelper.post(context, context.getString(urlId), - API_VERSION_CONNECT_ID, authInfo, params, false, false, callback); + AuthInfo.TokenAuth connectIdToken = retrieveConnectIdTokenSync(context); + if (connectIdToken == null) { + return false; + } else { + HashMap params = new HashMap<>(); + params.put("callback_url", callBackUrl); + params.put("invite_code", invitationCode); + params.put("user_token", connectIdToken.toString()); + return ConnectNetworkHelper.post(context, context.getString(urlId), + API_VERSION_CONNECT_ID, authInfo, params, false, false, callback); + } } } From 8a94a0af515ee37519b059b3209ae0110dc40899 Mon Sep 17 00:00:00 2001 From: Jay Panchal Date: Wed, 20 Nov 2024 14:49:22 +0530 Subject: [PATCH 05/10] Add connect-ID not configure scenario Add connect-ID not configure scenario --- app/res/layout/activity_hquser_invite.xml | 16 +++++++ app/res/values/strings.xml | 2 + .../connect/HQUserInviteActivity.java | 46 ++++++++++++++++--- .../connect/network/ApiConnectId.java | 18 ++++---- 4 files changed, 66 insertions(+), 16 deletions(-) diff --git a/app/res/layout/activity_hquser_invite.xml b/app/res/layout/activity_hquser_invite.xml index 229ffa77b6..5d3696f728 100644 --- a/app/res/layout/activity_hquser_invite.xml +++ b/app/res/layout/activity_hquser_invite.xml @@ -62,6 +62,22 @@ app:roundButtonTextSize="6sp" tools:text="@string/connect_hq_invitation_denied" /> + + You are invited to CommCareHQ project domain as %s Accept Denied + Go To Recovery + You have not configured your ConnectID. To accept this invitation, please configure your ConnectID first. Once configured, you\'ll be able to accept the invitation. diff --git a/app/src/org/commcare/activities/connect/HQUserInviteActivity.java b/app/src/org/commcare/activities/connect/HQUserInviteActivity.java index d7d5be084c..8a9f4356b9 100644 --- a/app/src/org/commcare/activities/connect/HQUserInviteActivity.java +++ b/app/src/org/commcare/activities/connect/HQUserInviteActivity.java @@ -6,9 +6,9 @@ import android.view.View; import android.widget.Toast; -import androidx.appcompat.app.AppCompatActivity; - +import org.commcare.activities.CommCareActivity; import org.commcare.activities.DispatchActivity; +import org.commcare.connect.ConnectManager; import org.commcare.connect.network.ApiConnectId; import org.commcare.connect.network.IApiCallback; import org.commcare.dalvik.R; @@ -21,7 +21,7 @@ import java.util.List; import java.util.Locale; -public class HQUserInviteActivity extends AppCompatActivity { +public class HQUserInviteActivity extends CommCareActivity { private ActivityHquserInviteBinding binding; String domain; @@ -45,11 +45,38 @@ protected void onCreate(Bundle savedInstanceState) { domain = pathSegments.get(4); } } - binding.btnAcceptInvitation.setOnClickListener(view -> handleInvitation(callBackURL, inviteCode, true)); + handleButtons(); + } + + private void handleButtons() { + boolean isTokenPresent = ConnectManager.isConnectIdConfigured(); + + setButtonVisibility(isTokenPresent); + setButtonListeners(isTokenPresent); + + binding.tvHqInvitationHeaderTitle.setText(isTokenPresent + ? getString(R.string.connect_hq_invitation_heading, username) + : getString(R.string.connect_hq_invitation_connectId_not_configure)); + } - binding.btnDeniedInvitation.setOnClickListener(view -> finish()); + private void setButtonVisibility(boolean isTokenPresent) { + binding.btnAcceptInvitation.setVisibility(isTokenPresent ? View.VISIBLE : View.GONE); + binding.btnDeniedInvitation.setVisibility(isTokenPresent ? View.VISIBLE : View.GONE); + binding.btnGoToRecovery.setVisibility(isTokenPresent ? View.GONE : View.VISIBLE); + } - binding.tvHqInvitationHeaderTitle.setText(getString(R.string.connect_hq_invitation_heading,username)); + private void setButtonListeners(boolean isTokenPresent) { + if (isTokenPresent) { + binding.btnAcceptInvitation.setOnClickListener(view -> handleInvitation(callBackURL, inviteCode, true)); + binding.btnDeniedInvitation.setOnClickListener(view -> finish()); + } else { + binding.btnGoToRecovery.setOnClickListener(view -> ConnectManager.registerUser(this, success -> { + if (success) { + ConnectManager.goToConnectJobsList(this); + } + }) + ); + } } private void handleInvitation(String callBackUrl, String inviteCode, boolean acceptStatus) { @@ -109,4 +136,11 @@ protected void onDestroy() { super.onDestroy(); binding = null; } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + finish(); + ConnectManager.handleFinishedActivity(this, requestCode, resultCode, data); + } } diff --git a/app/src/org/commcare/connect/network/ApiConnectId.java b/app/src/org/commcare/connect/network/ApiConnectId.java index d0e0b9f57a..451f3bfaad 100644 --- a/app/src/org/commcare/connect/network/ApiConnectId.java +++ b/app/src/org/commcare/connect/network/ApiConnectId.java @@ -1,6 +1,7 @@ package org.commcare.connect.network; import android.content.Context; +import android.util.Log; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; @@ -429,15 +430,12 @@ public static boolean hqUserInvitation(Context context, String callBackUrl, Stri int urlId = R.string.ConnectConfirmUserInvitation; AuthInfo authInfo = new AuthInfo.NoAuth(); AuthInfo.TokenAuth connectIdToken = retrieveConnectIdTokenSync(context); - if (connectIdToken == null) { - return false; - } else { - HashMap params = new HashMap<>(); - params.put("callback_url", callBackUrl); - params.put("invite_code", invitationCode); - params.put("user_token", connectIdToken.toString()); - return ConnectNetworkHelper.post(context, context.getString(urlId), - API_VERSION_CONNECT_ID, authInfo, params, false, false, callback); - } + Log.e("DEBUG_TESTING", "hqUserInvitation: " + connectIdToken.toString()); + HashMap params = new HashMap<>(); + params.put("callback_url", callBackUrl); + params.put("invite_code", invitationCode); + params.put("user_token", connectIdToken.toString()); + return ConnectNetworkHelper.post(context, context.getString(urlId), + API_VERSION_CONNECT_ID, authInfo, params, false, false, callback); } } From a0fa29a96b14881aadec09081244a29a7e47615d Mon Sep 17 00:00:00 2001 From: Jay Panchal Date: Wed, 27 Nov 2024 18:10:57 +0530 Subject: [PATCH 06/10] Set connect user name from url Set connect user name from url --- app/res/values-fr/strings.xml | 3 ++ app/res/values-pt/strings.xml | 3 ++ app/res/values/strings.xml | 1 + .../connect/HQUserInviteActivity.java | 37 ++++++++++++++----- 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/app/res/values-fr/strings.xml b/app/res/values-fr/strings.xml index 498a5442e5..e1ca64cb56 100644 --- a/app/res/values-fr/strings.xml +++ b/app/res/values-fr/strings.xml @@ -311,4 +311,7 @@ License. Vous êtes invité au domaine du projet CommCareHQ en tant que %s Accepter Refusé + Aller à la récupération + Vous n\'avez pas configuré votre ConnectID. Pour accepter cette invitation, veuillez d\'abord configurer votre ConnectID. Une fois configuré, vous pourrez accepter l'invitation. + Oups ! Il semble que l’invitation ait été envoyée à la mauvaise personne. diff --git a/app/res/values-pt/strings.xml b/app/res/values-pt/strings.xml index 53bcb83964..924234bd3f 100644 --- a/app/res/values-pt/strings.xml +++ b/app/res/values-pt/strings.xml @@ -485,4 +485,7 @@ Está convidado para o domínio do projeto CommCareHQ como %s Aceitar Negado + Vá para a recuperação + Não configurou o seu ConnectID. Para aceitar este convite, configure primeiro o seu ConnectID. Depois de configurado, poderá aceitar o convite. + Ops! Parece que o convite foi enviado para a pessoa errada. \ No newline at end of file diff --git a/app/res/values/strings.xml b/app/res/values/strings.xml index 10cd65d882..b2319b30b3 100644 --- a/app/res/values/strings.xml +++ b/app/res/values/strings.xml @@ -871,4 +871,5 @@ Denied Go To Recovery You have not configured your ConnectID. To accept this invitation, please configure your ConnectID first. Once configured, you\'ll be able to accept the invitation. + Oops! It seems like the invitation was sent to the wrong person. diff --git a/app/src/org/commcare/activities/connect/HQUserInviteActivity.java b/app/src/org/commcare/activities/connect/HQUserInviteActivity.java index 8a9f4356b9..9a9dbc4e97 100644 --- a/app/src/org/commcare/activities/connect/HQUserInviteActivity.java +++ b/app/src/org/commcare/activities/connect/HQUserInviteActivity.java @@ -8,6 +8,7 @@ import org.commcare.activities.CommCareActivity; import org.commcare.activities.DispatchActivity; +import org.commcare.android.database.connect.models.ConnectUserRecord; import org.commcare.connect.ConnectManager; import org.commcare.connect.network.ApiConnectId; import org.commcare.connect.network.IApiCallback; @@ -28,6 +29,7 @@ public class HQUserInviteActivity extends CommCareActivity String inviteCode; String username; String callBackURL; + String connectUserName; @Override protected void onCreate(Bundle savedInstanceState) { @@ -38,25 +40,34 @@ protected void onCreate(Bundle savedInstanceState) { Uri data = intent.getData(); if (data != null) { List pathSegments = data.getPathSegments(); - if (pathSegments.size() >= 3) { + if (pathSegments.size() >= 4) { callBackURL = pathSegments.get(1); username = pathSegments.get(2); inviteCode = pathSegments.get(3); domain = pathSegments.get(4); + connectUserName = pathSegments.get(5); } } handleButtons(); } private void handleButtons() { - boolean isTokenPresent = ConnectManager.isConnectIdConfigured(); - - setButtonVisibility(isTokenPresent); - setButtonListeners(isTokenPresent); + ConnectManager.init(this); - binding.tvHqInvitationHeaderTitle.setText(isTokenPresent - ? getString(R.string.connect_hq_invitation_heading, username) - : getString(R.string.connect_hq_invitation_connectId_not_configure)); + ConnectUserRecord user = ConnectManager.getUser(this); + boolean isTokenPresent = ConnectManager.isConnectIdConfigured(); + boolean isCorrectUser = user.getUserId().equals(connectUserName); + + if (isCorrectUser) { + binding.tvHqInvitationHeaderTitle.setText(isTokenPresent + ? getString(R.string.connect_hq_invitation_heading, username) + : getString(R.string.connect_hq_invitation_connectId_not_configure)); + setButtonVisibility(isTokenPresent); + setButtonListeners(isTokenPresent); + } else { + binding.tvHqInvitationHeaderTitle.setText(getString(R.string.connect_hq_invitation_wrong_user)); + hideInvitationButtons(); + } } private void setButtonVisibility(boolean isTokenPresent) { @@ -65,9 +76,15 @@ private void setButtonVisibility(boolean isTokenPresent) { binding.btnGoToRecovery.setVisibility(isTokenPresent ? View.GONE : View.VISIBLE); } + private void hideInvitationButtons() { + binding.btnAcceptInvitation.setVisibility(View.GONE); + binding.btnDeniedInvitation.setVisibility(View.GONE); + binding.btnGoToRecovery.setVisibility(View.GONE); + } + private void setButtonListeners(boolean isTokenPresent) { if (isTokenPresent) { - binding.btnAcceptInvitation.setOnClickListener(view -> handleInvitation(callBackURL, inviteCode, true)); + binding.btnAcceptInvitation.setOnClickListener(view -> handleInvitation(callBackURL, inviteCode)); binding.btnDeniedInvitation.setOnClickListener(view -> finish()); } else { binding.btnGoToRecovery.setOnClickListener(view -> ConnectManager.registerUser(this, success -> { @@ -79,7 +96,7 @@ private void setButtonListeners(boolean isTokenPresent) { } } - private void handleInvitation(String callBackUrl, String inviteCode, boolean acceptStatus) { + private void handleInvitation(String callBackUrl, String inviteCode) { IApiCallback callback = new IApiCallback() { @Override public void processSuccess(int responseCode, InputStream responseData) { From 5a745af5425637ec87cfbb4279e3a10fc33189c8 Mon Sep 17 00:00:00 2001 From: Jay Panchal Date: Wed, 27 Nov 2024 18:55:04 +0530 Subject: [PATCH 07/10] Set get data from query params instead of URL Set get data from query params instead of URL --- app/AndroidManifest.xml | 2 -- .../activities/connect/HQUserInviteActivity.java | 13 +++++-------- .../org/commcare/connect/network/ApiConnectId.java | 1 - 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/app/AndroidManifest.xml b/app/AndroidManifest.xml index 9784dce196..cd4137eb5d 100644 --- a/app/AndroidManifest.xml +++ b/app/AndroidManifest.xml @@ -145,10 +145,8 @@ - - pathSegments = data.getPathSegments(); - if (pathSegments.size() >= 4) { - callBackURL = pathSegments.get(1); - username = pathSegments.get(2); - inviteCode = pathSegments.get(3); - domain = pathSegments.get(4); - connectUserName = pathSegments.get(5); - } + callBackURL = data.getQueryParameter("callback_url"); + username = data.getQueryParameter("hq_username"); + inviteCode = data.getQueryParameter("invite_code"); + domain = data.getQueryParameter("hq_domain"); + connectUserName = data.getQueryParameter("connect_username"); } handleButtons(); } diff --git a/app/src/org/commcare/connect/network/ApiConnectId.java b/app/src/org/commcare/connect/network/ApiConnectId.java index 451f3bfaad..648a1c6a54 100644 --- a/app/src/org/commcare/connect/network/ApiConnectId.java +++ b/app/src/org/commcare/connect/network/ApiConnectId.java @@ -430,7 +430,6 @@ public static boolean hqUserInvitation(Context context, String callBackUrl, Stri int urlId = R.string.ConnectConfirmUserInvitation; AuthInfo authInfo = new AuthInfo.NoAuth(); AuthInfo.TokenAuth connectIdToken = retrieveConnectIdTokenSync(context); - Log.e("DEBUG_TESTING", "hqUserInvitation: " + connectIdToken.toString()); HashMap params = new HashMap<>(); params.put("callback_url", callBackUrl); params.put("invite_code", invitationCode); From d24b72b6e6c1595f5e0d6906cf2284642d6eaee3 Mon Sep 17 00:00:00 2001 From: Jay Panchal Date: Thu, 12 Dec 2024 16:41:51 +0530 Subject: [PATCH 08/10] Solved user not found issue Solved user not found issue --- app/res/values-fr/strings.xml | 2 +- .../commcare/activities/connect/HQUserInviteActivity.java | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/res/values-fr/strings.xml b/app/res/values-fr/strings.xml index e1ca64cb56..0c82eaaee2 100644 --- a/app/res/values-fr/strings.xml +++ b/app/res/values-fr/strings.xml @@ -312,6 +312,6 @@ License. Accepter Refusé Aller à la récupération - Vous n\'avez pas configuré votre ConnectID. Pour accepter cette invitation, veuillez d\'abord configurer votre ConnectID. Une fois configuré, vous pourrez accepter l'invitation. + Vous n\'avez pas configuré votre ConnectID. Pour accepter cette invitation, veuillez dabord configurer votre ConnectID. Une fois configuré, vous pourrez accepter invitation. Oups ! Il semble que l’invitation ait été envoyée à la mauvaise personne. diff --git a/app/src/org/commcare/activities/connect/HQUserInviteActivity.java b/app/src/org/commcare/activities/connect/HQUserInviteActivity.java index 853edfcbf0..6b98c9c5c5 100644 --- a/app/src/org/commcare/activities/connect/HQUserInviteActivity.java +++ b/app/src/org/commcare/activities/connect/HQUserInviteActivity.java @@ -3,6 +3,7 @@ import android.content.Intent; import android.net.Uri; import android.os.Bundle; +import android.util.Log; import android.view.View; import android.widget.Toast; @@ -19,7 +20,6 @@ import java.io.IOException; import java.io.InputStream; -import java.util.List; import java.util.Locale; public class HQUserInviteActivity extends CommCareActivity { @@ -53,7 +53,10 @@ private void handleButtons() { ConnectUserRecord user = ConnectManager.getUser(this); boolean isTokenPresent = ConnectManager.isConnectIdConfigured(); - boolean isCorrectUser = user.getUserId().equals(connectUserName); + boolean isCorrectUser = true; + if (user != null) { + isCorrectUser = user.getUserId().equals(connectUserName); + } if (isCorrectUser) { binding.tvHqInvitationHeaderTitle.setText(isTokenPresent From 28bf471977e746923cc9df59d7984e91bef3cdcd Mon Sep 17 00:00:00 2001 From: Jay Panchal Date: Fri, 13 Dec 2024 14:43:55 +0530 Subject: [PATCH 09/10] Working on API issue Working on API issue --- app/res/values/strings.xml | 2 +- .../commcare/activities/connect/HQUserInviteActivity.java | 4 ++-- app/src/org/commcare/connect/network/ApiConnectId.java | 6 ++---- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/app/res/values/strings.xml b/app/res/values/strings.xml index b2319b30b3..90a99ee99e 100644 --- a/app/res/values/strings.xml +++ b/app/res/values/strings.xml @@ -42,7 +42,7 @@ https://%s/api/payment/%s/confirm https://connectid.dimagi.com/users/recover/initiate_deactivation https://connectid.dimagi.com/users/recover/confirm_deactivation - https://connectid.dimagi.com/settings/users/commcare/confirm_connectid_user + https://connectid.dimagi.com/users/confirm_hq_invite diff --git a/app/src/org/commcare/activities/connect/HQUserInviteActivity.java b/app/src/org/commcare/activities/connect/HQUserInviteActivity.java index 6b98c9c5c5..1be87ba8f9 100644 --- a/app/src/org/commcare/activities/connect/HQUserInviteActivity.java +++ b/app/src/org/commcare/activities/connect/HQUserInviteActivity.java @@ -132,8 +132,8 @@ public void processOldApiError() { setErrorMessage(getString(R.string.recovery_network_outdated)); } }; - - boolean isBusy = !ApiConnectId.hqUserInvitation(HQUserInviteActivity.this, callBackUrl, inviteCode, callback); + ConnectUserRecord user = ConnectManager.getUser(this); + boolean isBusy = !ApiConnectId.hqUserInvitation(HQUserInviteActivity.this,user.getUserId(),user.getPassword(), callBackUrl, inviteCode, callback); if (isBusy) { Toast.makeText(HQUserInviteActivity.this, R.string.busy_message, Toast.LENGTH_SHORT).show(); } diff --git a/app/src/org/commcare/connect/network/ApiConnectId.java b/app/src/org/commcare/connect/network/ApiConnectId.java index 648a1c6a54..091604c8ec 100644 --- a/app/src/org/commcare/connect/network/ApiConnectId.java +++ b/app/src/org/commcare/connect/network/ApiConnectId.java @@ -426,15 +426,13 @@ public static boolean confirmUserDeactivation(Context context, String phone, Str API_VERSION_CONNECT_ID, authInfo, params, false, false, callback); } - public static boolean hqUserInvitation(Context context, String callBackUrl, String invitationCode, IApiCallback callback) { + public static boolean hqUserInvitation(Context context,String username,String password, String callBackUrl, String invitationCode, IApiCallback callback) { int urlId = R.string.ConnectConfirmUserInvitation; - AuthInfo authInfo = new AuthInfo.NoAuth(); AuthInfo.TokenAuth connectIdToken = retrieveConnectIdTokenSync(context); HashMap params = new HashMap<>(); params.put("callback_url", callBackUrl); params.put("invite_code", invitationCode); params.put("user_token", connectIdToken.toString()); - return ConnectNetworkHelper.post(context, context.getString(urlId), - API_VERSION_CONNECT_ID, authInfo, params, false, false, callback); + return ConnectNetworkHelper.post(context, context.getString(urlId), API_VERSION_CONNECT_ID, new AuthInfo.ProvidedAuth(username, password, false), params, false, false, callback); } } From d219577ea529139fbec252c0b37f591732532e7d Mon Sep 17 00:00:00 2001 From: Jay Panchal Date: Thu, 19 Dec 2024 11:11:38 +0530 Subject: [PATCH 10/10] Set loader while API call Set loader while API call --- app/res/layout/activity_hquser_invite.xml | 14 ++++++++++++++ .../activities/connect/HQUserInviteActivity.java | 6 ++++++ 2 files changed, 20 insertions(+) diff --git a/app/res/layout/activity_hquser_invite.xml b/app/res/layout/activity_hquser_invite.xml index 5d3696f728..34bbd99772 100644 --- a/app/res/layout/activity_hquser_invite.xml +++ b/app/res/layout/activity_hquser_invite.xml @@ -97,4 +97,18 @@ android:orientation="horizontal" app:layout_constraintGuide_percent="0.35" /> + + \ No newline at end of file diff --git a/app/src/org/commcare/activities/connect/HQUserInviteActivity.java b/app/src/org/commcare/activities/connect/HQUserInviteActivity.java index 1be87ba8f9..4c7cdd244a 100644 --- a/app/src/org/commcare/activities/connect/HQUserInviteActivity.java +++ b/app/src/org/commcare/activities/connect/HQUserInviteActivity.java @@ -30,6 +30,7 @@ public class HQUserInviteActivity extends CommCareActivity String username; String callBackURL; String connectUserName; + boolean isProgressVisible = false; @Override protected void onCreate(Bundle savedInstanceState) { @@ -100,6 +101,7 @@ private void handleInvitation(String callBackUrl, String inviteCode) { IApiCallback callback = new IApiCallback() { @Override public void processSuccess(int responseCode, InputStream responseData) { + binding.progressBar.setVisibility(View.GONE); try { String responseAsString = new String(StreamsUtil.inputStreamToByteArray(responseData)); if (responseAsString.length() > 0) { @@ -113,6 +115,7 @@ public void processSuccess(int responseCode, InputStream responseData) { @Override public void processFailure(int responseCode, IOException e) { + binding.progressBar.setVisibility(View.GONE); String message = ""; if (responseCode > 0) { message = String.format(Locale.getDefault(), "(%d)", responseCode); @@ -124,15 +127,18 @@ public void processFailure(int responseCode, IOException e) { @Override public void processNetworkFailure() { + binding.progressBar.setVisibility(View.GONE); setErrorMessage(getString(R.string.recovery_network_unavailable)); } @Override public void processOldApiError() { + binding.progressBar.setVisibility(View.GONE); setErrorMessage(getString(R.string.recovery_network_outdated)); } }; ConnectUserRecord user = ConnectManager.getUser(this); + binding.progressBar.setVisibility(View.VISIBLE); boolean isBusy = !ApiConnectId.hqUserInvitation(HQUserInviteActivity.this,user.getUserId(),user.getPassword(), callBackUrl, inviteCode, callback); if (isBusy) { Toast.makeText(HQUserInviteActivity.this, R.string.busy_message, Toast.LENGTH_SHORT).show();