Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions app/assets/locales/android_translatable_strings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,14 @@ notification.bad.certificate.detail=CommCare couldn't validate the security info
notification.bad.certificate.action=Check your device's time and date to make sure they are correct. If the problem persists, try to connect to a secure server with the phone's browser
notification.bad.certificate.button=Go to settings

notification.token.unavailable.title=Couldn't connect to the server.
notification.token.unavailable.detail=CommCare had an issue authenticating the user.
notification.token.unavailable.action=Check your device's time and date to make sure they are correct, then try again.

notification.token.denied.title=Couldn't connect to the server.
notification.token.denied.detail=CommCare can no longer communicate with the ConnectID server.
notification.token.denied.action=Please recover your ConnectID account, then try again.

notification.restore.storagefull.title=Couldn't save your application's resources
notification.restore.storagefull.detail=CommCare was not able to save one or more of your application's resources on the device. This could be because the entire application was too large, or because an individual fixture exceeded 1MB.
notification.restore.storagefull.action=Check the amount of space available on your device. If the SD card isn't full, then it's likely one of your fixtures is too large (> 1MB) and needs to be reduced or split.
Expand Down
2 changes: 2 additions & 0 deletions app/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,8 @@
<string name="recovery_forms_state_unavailable" cc:translatable="true">Forms are not available. Make sure your phone storage is available</string>
<string name="recovery_network_unavailable" cc:translatable="true">No network connection. Please check your internet and try again.</string>
<string name="recovery_network_outdated" cc:translatable="true">The app is outdated and can no longer communicate with the server. Please update the app on the Google Play Store.</string>
<string name="recovery_network_token_unavailable" cc:translatable="true">There was a network issue, please try again.</string>
<string name="recovery_network_token_request_rejected" cc:translatable="true">Lost ConnectID configuration with server, please recover account.</string>
<string name="recovery_app_manager" cc:translatable="true">Go to App Manager</string>
<string name="recovery_retry" cc:translatable="true">Retry Recovery</string>
<string name="notification_channel_errors_title" cc:translatable="true">Errors</string>
Expand Down
2 changes: 1 addition & 1 deletion app/src/org/commcare/activities/LoginActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -873,7 +873,7 @@ public void handlePullTaskResult(ResultAndError<DataPullTask.PullTaskResult> res
raiseLoginMessage(StockMessages.Empty_Url, true);
break;
case AUTH_FAILED:
if(ConnectManager.checkForFailedConnectIdAuth(uiController.getEnteredUsername())) {
if(ConnectManager.isSeatedAppLinkedToConnectId(uiController.getEnteredUsername())) {
Logger.exception("Token auth error for connect managed app",
new Throwable("Token Auth failed during login for a ConnectID managed app"));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public void handlePullTaskResult(ResultAndError<DataPullTask.PullTaskResult> res
case AUTH_FAILED:
String username = CommCareApplication.instance().getRecordForCurrentUser().getUsername();

if(ConnectManager.checkForFailedConnectIdAuth(username)) {
if(ConnectManager.isSeatedAppLinkedToConnectId(username)) {
Logger.exception("Token auth error for connect managed app",
new Throwable("Token Auth failed during sync for a ConnectID managed app"));
}
Expand Down
118 changes: 101 additions & 17 deletions app/src/org/commcare/connect/ConnectManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
import org.commcare.connect.network.ConnectNetworkHelper;
import org.commcare.connect.network.ConnectSsoHelper;
import org.commcare.connect.network.IApiCallback;
import org.commcare.connect.network.TokenRequestDeniedException;
import org.commcare.connect.network.TokenUnavailableException;
import org.commcare.connect.workers.ConnectHeartbeatWorker;
import org.commcare.core.network.AuthInfo;
import org.commcare.dalvik.R;
Expand Down Expand Up @@ -500,15 +502,25 @@ public static void checkConnectIdLink(CommCareActivity<?> activity, boolean auto
appRecordFinal.linkToConnectId(password);
ConnectAppDatabaseUtil.storeApp(activity, appRecordFinal);

//Link the HQ user by aqcuiring the SSO token for the first time
ConnectSsoHelper.retrieveHqSsoTokenAsync(activity, username, true, auth -> {
if (auth == null) {
//Toast.makeText(activity, "Failed to acquire SSO token", Toast.LENGTH_SHORT).show();
//TODO: Re-enable when token working again
//ConnectManager.forgetAppCredentials(appId, username);
//Link the HQ user by acquiring the SSO token for the first time
ConnectUserRecord user = ConnectUserDatabaseUtil.getUser(activity);
ConnectSsoHelper.retrieveHqSsoTokenAsync(activity, user, appRecordFinal, username, true, new ConnectSsoHelper.TokenCallback() {
@Override
public void tokenRetrieved(AuthInfo.TokenAuth token) {
callback.connectActivityComplete(true);
}

callback.connectActivityComplete(true);
@Override
public void tokenUnavailable() {
ConnectNetworkHelper.handleTokenUnavailableException(activity);
callback.connectActivityComplete(false);
}

@Override
public void tokenRequestDenied() {
ConnectNetworkHelper.handleTokenRequestDeniedException(activity);
callback.connectActivityComplete(false);
}
});
} else {
callback.connectActivityComplete(false);
Expand Down Expand Up @@ -570,7 +582,26 @@ public static void checkConnectIdLink(CommCareActivity<?> activity, boolean auto
callback.connectActivityComplete(false);
}

public static boolean checkForFailedConnectIdAuth(String username) {
public static AuthInfo.TokenAuth getHqTokenIfLinked(String username) throws TokenRequestDeniedException, TokenUnavailableException {
if (!isConnectIdConfigured()) {
return null;
}

ConnectUserRecord user = ConnectUserDatabaseUtil.getUser(manager.parentActivity);
if (user == null) {
return null;
}

String seatedAppId = CommCareApplication.instance().getCurrentApp().getUniqueId();
ConnectLinkedAppRecord appRecord = ConnectAppDatabaseUtil.getAppData(manager.parentActivity, seatedAppId, username);
if(appRecord == null) {
return null;
}

return ConnectSsoHelper.retrieveHqSsoTokenSync(CommCareApplication.instance(), user, appRecord, username, false);
}

public static boolean isSeatedAppLinkedToConnectId(String username) {
try {
if (isConnectIdConfigured()) {
String seatedAppId = CommCareApplication.instance().getCurrentApp().getUniqueId();
Expand Down Expand Up @@ -792,7 +823,7 @@ public void processSuccess(int responseCode, InputStream responseData) {
}

@Override
public void processFailure(int responseCode, IOException e) {
public void processFailure(int responseCode) {
Logger.log("ERROR", String.format(Locale.getDefault(), "Failed: %d", responseCode));
}

Expand All @@ -801,6 +832,16 @@ public void processNetworkFailure() {
Logger.log("ERROR", "Failed (network)");
}

@Override
public void processTokenUnavailableError() {
Logger.log("ERROR", "Failed (token unavailable)");
}

@Override
public void processTokenRequestDeniedError() {
ConnectNetworkHelper.handleTokenRequestDeniedException(context);
}

@Override
public void processOldApiError() {
ConnectNetworkHelper.showOutdatedApiError(context);
Expand All @@ -823,7 +864,8 @@ public static void updateJobProgress(Context context, ConnectJobRecord job, Conn
}

public static void updateLearningProgress(Context context, ConnectJobRecord job, ConnectActivityCompleteListener listener) {
ApiConnect.getLearnProgress(context, job.getJobId(), new IApiCallback() {
ConnectUserRecord user = getUser(context);
ApiConnect.getLearnProgress(context, user, job.getJobId(), new IApiCallback() {
private static void reportApiCall(boolean success) {
FirebaseAnalyticsUtil.reportCccApiLearnProgress(success);
}
Expand Down Expand Up @@ -868,7 +910,7 @@ public void processSuccess(int responseCode, InputStream responseData) {
}

@Override
public void processFailure(int responseCode, IOException e) {
public void processFailure(int responseCode) {
Logger.log("ERROR", String.format(Locale.getDefault(), "Failed: %d", responseCode));
reportApiCall(false);
listener.connectActivityComplete(false);
Expand All @@ -881,6 +923,20 @@ public void processNetworkFailure() {
listener.connectActivityComplete(false);
}

@Override
public void processTokenUnavailableError() {
ConnectNetworkHelper.handleTokenUnavailableException(context);
reportApiCall(false);
listener.connectActivityComplete(false);
}

@Override
public void processTokenRequestDeniedError() {
ConnectNetworkHelper.handleTokenRequestDeniedException(context);
reportApiCall(false);
listener.connectActivityComplete(false);
}

@Override
public void processOldApiError() {
ConnectNetworkHelper.showOutdatedApiError(context);
Expand All @@ -891,7 +947,8 @@ public void processOldApiError() {
}

public static void updateDeliveryProgress(Context context, ConnectJobRecord job, ConnectActivityCompleteListener listener) {
ApiConnect.getDeliveries(context, job.getJobId(), new IApiCallback() {
ConnectUserRecord user = getUser(context);
ApiConnect.getDeliveries(context, user, job.getJobId(), new IApiCallback() {
private static void reportApiCall(boolean success) {
FirebaseAnalyticsUtil.reportCccApiDeliveryProgress(success);
}
Expand Down Expand Up @@ -978,15 +1035,27 @@ public void processSuccess(int responseCode, InputStream responseData) {
}

@Override
public void processFailure(int responseCode, IOException e) {
Logger.log("ERROR", String.format(Locale.getDefault(), "Delivery progress call failed: %d", responseCode));
public void processFailure(int responseCode) {
reportApiCall(false);
listener.connectActivityComplete(false);
}

@Override
public void processNetworkFailure() {
Logger.log("ERROR", "Failed (network)");
reportApiCall(false);
listener.connectActivityComplete(false);
}

@Override
public void processTokenUnavailableError() {
ConnectNetworkHelper.handleTokenUnavailableException(context);
reportApiCall(false);
listener.connectActivityComplete(false);
}

@Override
public void processTokenRequestDeniedError() {
ConnectNetworkHelper.handleTokenRequestDeniedException(context);
reportApiCall(false);
listener.connectActivityComplete(false);
}
Expand All @@ -1001,7 +1070,8 @@ public void processOldApiError() {
}

public static void updatePaymentConfirmed(Context context, final ConnectJobPaymentRecord payment, boolean confirmed, ConnectActivityCompleteListener listener) {
ApiConnect.setPaymentConfirmed(context, payment.getPaymentId(), confirmed, new IApiCallback() {
ConnectUserRecord user = getUser(context);
ApiConnect.setPaymentConfirmed(context, user, payment.getPaymentId(), confirmed, new IApiCallback() {
private void reportApiCall(boolean success) {
FirebaseAnalyticsUtil.reportCccApiPaymentConfirmation(success);
}
Expand All @@ -1017,7 +1087,7 @@ public void processSuccess(int responseCode, InputStream responseData) {
}

@Override
public void processFailure(int responseCode, IOException e) {
public void processFailure(int responseCode) {
Toast.makeText(context, R.string.connect_payment_confirm_failed, Toast.LENGTH_SHORT).show();
reportApiCall(false);
listener.connectActivityComplete(false);
Expand All @@ -1030,6 +1100,20 @@ public void processNetworkFailure() {
listener.connectActivityComplete(false);
}

@Override
public void processTokenUnavailableError() {
ConnectNetworkHelper.handleTokenUnavailableException(context);
reportApiCall(false);
listener.connectActivityComplete(false);
}

@Override
public void processTokenRequestDeniedError() {
ConnectNetworkHelper.handleTokenRequestDeniedException(context);
reportApiCall(false);
listener.connectActivityComplete(false);
}
Comment on lines +1103 to +1115
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Handle payment confirmation failure more robustly.

In addition to showing a toast for token unavailability or a token request denial, consider offering a retry option or queueing the payment confirmation for automatic retry once the token becomes valid again.


@Override
public void processOldApiError() {
ConnectNetworkHelper.showOutdatedApiError(context);
Expand Down
Loading