-
-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CCCT-469 || HQ User Invite Connect #2927
base: connect_qa
Are you sure you want to change the base?
Changes from all commits
763ac95
10d717a
34c179c
44ee961
8a94a0a
a0fa29a
5a745af
d24b72b
28bf471
d219577
0c8f519
f7c9ee9
bf10b1a
b5c9b56
f78a393
6bec357
695fa57
692d3c5
fe06158
c681ffd
973e5c0
30ad5e5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
xmlns:app="http://schemas.android.com/apk/res-auto" | ||
xmlns:tools="http://schemas.android.com/tools" | ||
android:id="@+id/main" | ||
android:layout_width="match_parent" | ||
android:layout_height="match_parent" | ||
tools:context="org.commcare.activities.connect.HQUserInviteActivity"> | ||
|
||
<ImageView | ||
android:id="@+id/imageView2" | ||
android:layout_width="match_parent" | ||
android:layout_height="wrap_content" | ||
android:layout_marginHorizontal="30dp" | ||
android:adjustViewBounds="true" | ||
android:src="@drawable/ic_dimagi_logo" | ||
app:layout_constraintBottom_toTopOf="@+id/guideline3" | ||
app:layout_constraintEnd_toEndOf="parent" | ||
app:layout_constraintStart_toStartOf="parent" /> | ||
|
||
<org.commcare.views.connect.connecttextview.ConnectMediumTextView | ||
android:id="@+id/tvHqInvitationHeaderTitle" | ||
android:layout_width="match_parent" | ||
android:layout_height="wrap_content" | ||
android:layout_marginHorizontal="30dp" | ||
android:layout_marginTop="20dp" | ||
android:gravity="center" | ||
android:text="" | ||
app:layout_constraintEnd_toEndOf="parent" | ||
app:layout_constraintStart_toStartOf="parent" | ||
app:layout_constraintTop_toBottomOf="@+id/imageView2" /> | ||
|
||
<com.google.android.material.button.MaterialButton | ||
android:id="@+id/btn_accept_invitation" | ||
android:layout_width="match_parent" | ||
android:layout_height="wrap_content" | ||
android:layout_marginHorizontal="50dp" | ||
android:layout_marginTop="30dp" | ||
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/tvHqInvitationHeaderTitle" | ||
tools:text="@string/connect_hq_invitation_accept" /> | ||
|
||
<com.google.android.material.button.MaterialButton | ||
android:id="@+id/btn_denied_invitation" | ||
android:layout_width="match_parent" | ||
android:layout_height="wrap_content" | ||
android:layout_marginHorizontal="50dp" | ||
android:layout_marginTop="15dp" | ||
android:text="@string/connect_hq_invitation_denied" | ||
android:visibility="visible" | ||
app:layout_constraintEnd_toEndOf="parent" | ||
app:layout_constraintStart_toStartOf="parent" | ||
app:layout_constraintTop_toBottomOf="@+id/btn_accept_invitation" | ||
tools:text="@string/connect_hq_invitation_denied" /> | ||
|
||
<com.google.android.material.button.MaterialButton | ||
android:id="@+id/btn_go_to_recovery" | ||
android:layout_width="match_parent" | ||
android:layout_height="wrap_content" | ||
android:layout_marginHorizontal="50dp" | ||
android:layout_marginTop="15dp" | ||
android:text="@string/connect_hq_invitation_go_to_recovery" | ||
android:visibility="visible" | ||
app:layout_constraintEnd_toEndOf="parent" | ||
app:layout_constraintStart_toStartOf="parent" | ||
app:layout_constraintTop_toBottomOf="@+id/btn_denied_invitation" | ||
tools:text="@string/connect_hq_invitation_go_to_recovery" /> | ||
|
||
<org.commcare.views.connect.connecttextview.ConnectMediumTextView | ||
android:layout_width="0dp" | ||
android:layout_height="wrap_content" | ||
android:text="" | ||
android:id="@+id/connect_phone_verify_error" | ||
android:textSize="16sp" | ||
android:layout_marginTop="10dp" | ||
android:textColor="@color/connect_red" | ||
app:layout_constraintEnd_toEndOf="@+id/btn_denied_invitation" | ||
app:layout_constraintStart_toStartOf="@+id/btn_denied_invitation" | ||
app:layout_constraintTop_toBottomOf="@+id/btn_denied_invitation" /> | ||
|
||
<androidx.constraintlayout.widget.Guideline | ||
android:id="@+id/guideline3" | ||
android:layout_width="wrap_content" | ||
android:layout_height="wrap_content" | ||
android:orientation="horizontal" | ||
app:layout_constraintGuide_percent="0.35" /> | ||
|
||
<ProgressBar | ||
android:id="@+id/progress_bar" | ||
android:layout_width="wrap_content" | ||
android:layout_height="wrap_content" | ||
style="?android:attr/progressBarStyle" | ||
android:layout_centerHorizontal="true" | ||
android:progressTint="@color/connect_blue_color" | ||
android:progressBackgroundTint="@color/connect_blue_color" | ||
android:visibility="gone" | ||
app:layout_constraintBottom_toBottomOf="parent" | ||
app:layout_constraintEnd_toEndOf="parent" | ||
app:layout_constraintStart_toStartOf="parent" | ||
app:layout_constraintTop_toBottomOf="@+id/btn_go_to_recovery" /> | ||
|
||
</androidx.constraintlayout.widget.ConstraintLayout> |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,7 @@ | |
<string name="ConnectClaimJobURL">https://%s/api/opportunity/%d/claim</string> | ||
<string name="ConnectDeliveriesURL">https://%s/api/opportunity/%d/delivery_progress</string> | ||
<string name="ConnectPaymentConfirmationURL">https://%s/api/payment/%s/confirm</string> | ||
<string name="ConnectConfirmUserInvitation">https://connectid.dimagi.com/users/confirm_hq_invite</string> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it possible to define only the relative url to host ? That makes the code more felxible in event we want to have configurable hosts or test environments. |
||
|
||
<!-- Connect Messaging URLs--> | ||
<string name="ConnectMessageRetrieveMessagesURL">https://connectid.dimagi.com/messaging/retrieve_messages/</string> | ||
|
@@ -776,11 +777,19 @@ | |
<string name="connect_learn">Learn</string> | ||
<string name="connect_delivery">Delivery</string> | ||
<string name="connect_expired">Expired</string> | ||
|
||
<string name="connect_hq_invitation_heading">You are invited to CommCareHQ project domain as %s</string> | ||
<string name="connect_hq_invitation_accept">Accept</string> | ||
<string name="connect_hq_invitation_denied">Decline</string> | ||
<string name="connect_hq_invitation_go_to_recovery">Go To Recovery</string> | ||
<string name="connect_hq_invitation_connectId_not_configure">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.</string> | ||
<string name="connect_hq_invitation_wrong_user">Oops! It seems like the invitation was sent to the wrong person.</string> | ||
<string name="connect_job_tile_daily_limit_description">Daily Limit reached. No Payment for submitting forms</string> | ||
<string name="connect_job_tile_daily_limit">Over Limit</string> | ||
<string name="connect_job_tile_daily_visits">Daily Visits</string> | ||
<string name="connect_appbar_title_app_lock">App Lock</string> | ||
<string name="connect_appbar_title_password_verification">Password Verification</string> | ||
<string name="connect_hq_invitation_accept_error">There was an error accepting the invitation, please contact support.</string> | ||
|
||
<string name="connect_db_corrupt">A problem occurred with the database, please recover your account.</string> | ||
</resources> |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,173 @@ | ||||||||||||||||||||||||||||||||||||
package org.commcare.activities.connect; | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
import android.content.Intent; | ||||||||||||||||||||||||||||||||||||
import android.net.Uri; | ||||||||||||||||||||||||||||||||||||
import android.os.Bundle; | ||||||||||||||||||||||||||||||||||||
import android.view.View; | ||||||||||||||||||||||||||||||||||||
import android.widget.Toast; | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
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; | ||||||||||||||||||||||||||||||||||||
import org.commcare.dalvik.R; | ||||||||||||||||||||||||||||||||||||
import org.commcare.dalvik.databinding.ActivityHquserInviteBinding; | ||||||||||||||||||||||||||||||||||||
import org.commcare.google.services.analytics.FirebaseAnalyticsUtil; | ||||||||||||||||||||||||||||||||||||
import org.commcare.utils.CrashUtil; | ||||||||||||||||||||||||||||||||||||
import org.javarosa.core.io.StreamsUtil; | ||||||||||||||||||||||||||||||||||||
import org.javarosa.core.services.Logger; | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
import java.io.IOException; | ||||||||||||||||||||||||||||||||||||
import java.io.InputStream; | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
public class HQUserInviteActivity extends CommCareActivity<HQUserInviteActivity> { | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
private ActivityHquserInviteBinding binding; | ||||||||||||||||||||||||||||||||||||
String domain; | ||||||||||||||||||||||||||||||||||||
String inviteCode; | ||||||||||||||||||||||||||||||||||||
String username; | ||||||||||||||||||||||||||||||||||||
String callBackURL; | ||||||||||||||||||||||||||||||||||||
String connectUserName; | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
@Override | ||||||||||||||||||||||||||||||||||||
protected void onCreate(Bundle savedInstanceState) { | ||||||||||||||||||||||||||||||||||||
super.onCreate(savedInstanceState); | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
Logger.log("HQInvite", "Entering HQ user invite activity"); | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
binding = ActivityHquserInviteBinding.inflate(getLayoutInflater()); | ||||||||||||||||||||||||||||||||||||
setContentView(binding.getRoot()); | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
Intent intent = getIntent(); | ||||||||||||||||||||||||||||||||||||
Uri data = intent.getData(); | ||||||||||||||||||||||||||||||||||||
if (data != null) { | ||||||||||||||||||||||||||||||||||||
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"); | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
FirebaseAnalyticsUtil.reportHQInvitationDeepLink(domain); | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
handleButtons(); | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
private void handleButtons() { | ||||||||||||||||||||||||||||||||||||
ConnectManager.init(this); | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
ConnectUserRecord user = ConnectManager.getUser(this); | ||||||||||||||||||||||||||||||||||||
boolean isTokenPresent = ConnectManager.isConnectIdConfigured(); | ||||||||||||||||||||||||||||||||||||
boolean isCorrectUser = user == null || 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)); | ||||||||||||||||||||||||||||||||||||
setButtonVisibility(false); | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
private void setButtonVisibility(boolean visible) { | ||||||||||||||||||||||||||||||||||||
binding.btnAcceptInvitation.setVisibility(visible ? View.VISIBLE : View.GONE); | ||||||||||||||||||||||||||||||||||||
binding.btnDeniedInvitation.setVisibility(visible ? View.VISIBLE : View.GONE); | ||||||||||||||||||||||||||||||||||||
binding.btnGoToRecovery.setVisibility(visible ? View.GONE : View.VISIBLE); | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we want to show the recovery button even when the user is incorrect ? |
||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
private void setButtonListeners(boolean isTokenPresent) { | ||||||||||||||||||||||||||||||||||||
if (isTokenPresent) { | ||||||||||||||||||||||||||||||||||||
binding.btnAcceptInvitation.setOnClickListener(view -> handleInvitation(callBackURL, inviteCode)); | ||||||||||||||||||||||||||||||||||||
binding.btnDeniedInvitation.setOnClickListener(view -> declineInvitation()); | ||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||
binding.btnGoToRecovery.setOnClickListener(view -> ConnectManager.registerUser(this, success -> { | ||||||||||||||||||||||||||||||||||||
if (success) { | ||||||||||||||||||||||||||||||||||||
ConnectManager.goToConnectJobsList(this); | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
private void declineInvitation() { | ||||||||||||||||||||||||||||||||||||
FirebaseAnalyticsUtil.reportHQInvitationResponse(domain, false, ""); | ||||||||||||||||||||||||||||||||||||
finish(); | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
private void handleInvitation(String callBackUrl, String inviteCode) { | ||||||||||||||||||||||||||||||||||||
Logger.log("HQInvite", "User accepted invitation"); | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use constants for Log Types otherwise we risk having a lot of different scattered categories in logs. You can add a connect specific class to signify logtypes like |
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
IApiCallback callback = new IApiCallback() { | ||||||||||||||||||||||||||||||||||||
@Override | ||||||||||||||||||||||||||||||||||||
public void processSuccess(int responseCode, InputStream responseData) { | ||||||||||||||||||||||||||||||||||||
FirebaseAnalyticsUtil.reportHQInvitationResponse(domain, true, ""); | ||||||||||||||||||||||||||||||||||||
Logger.log("HQInvite", "Acceptance succeeded"); | ||||||||||||||||||||||||||||||||||||
binding.progressBar.setVisibility(View.GONE); | ||||||||||||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||||||||||||
String responseAsString = new String(StreamsUtil.inputStreamToByteArray(responseData)); | ||||||||||||||||||||||||||||||||||||
if (responseAsString.length() > 0) { | ||||||||||||||||||||||||||||||||||||
startActivity(new Intent(HQUserInviteActivity.this, DispatchActivity.class)); | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What should happen when the user accepts the invitation? Seems like ideally we would take them to install an app next, but currently this just launches DispatchActivity and lets it make the call (login page). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would think user should land in some sort of connect workflow that initiates the app install if needed (I would think the install should happen only when they claim an opportunity). Would you be able to describe the user story here more in the PR description. For eg. It's not entirely clear to me when this feature will get used as a whole or when will someone invite a connect user to a project space and what we want to achive with it ? |
||||||||||||||||||||||||||||||||||||
finish(); | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
} catch (IOException e) { | ||||||||||||||||||||||||||||||||||||
CrashUtil.reportException(e); | ||||||||||||||||||||||||||||||||||||
setErrorMessage(getString(R.string.connect_hq_invitation_accept_error)); | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
@Override | ||||||||||||||||||||||||||||||||||||
public void processFailure(int responseCode, IOException e) { | ||||||||||||||||||||||||||||||||||||
FirebaseAnalyticsUtil.reportHQInvitationResponse(domain, false, "API error"); | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of using a loose string "API Error", we should use constants for different possible failure causes, This should also log the response code if available. |
||||||||||||||||||||||||||||||||||||
Logger.log("HQInvite", "Acceptance failed"); | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. probably log the IOException as Logger.exception() instead if it's not happening in the network layer itself. |
||||||||||||||||||||||||||||||||||||
binding.progressBar.setVisibility(View.GONE); | ||||||||||||||||||||||||||||||||||||
setErrorMessage(getString(R.string.connect_hq_invitation_accept_error)); | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
@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)); | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
Comment on lines
+132
to
+141
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should not we be logging |
||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||
ConnectUserRecord user = ConnectManager.getUser(this); | ||||||||||||||||||||||||||||||||||||
binding.progressBar.setVisibility(View.VISIBLE); | ||||||||||||||||||||||||||||||||||||
boolean isBusy = !ApiConnectId.hqUserInvitation(HQUserInviteActivity.this,user.getUserId(),user.getPassword(), callBackUrl, inviteCode, callback); | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: formatting is off |
||||||||||||||||||||||||||||||||||||
if (isBusy) { | ||||||||||||||||||||||||||||||||||||
Toast.makeText(HQUserInviteActivity.this, R.string.busy_message, Toast.LENGTH_SHORT).show(); | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
public void setErrorMessage(String message) { | ||||||||||||||||||||||||||||||||||||
boolean show = message != null; | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
binding.connectPhoneVerifyError.setVisibility(show ? View.VISIBLE : View.GONE); | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
if (show) { | ||||||||||||||||||||||||||||||||||||
binding.connectPhoneVerifyError.setText(message); | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
Comment on lines
+151
to
+159
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: can simplify under a single if to keep control flow simple.
Suggested change
|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
@Override | ||||||||||||||||||||||||||||||||||||
protected void onDestroy() { | ||||||||||||||||||||||||||||||||||||
super.onDestroy(); | ||||||||||||||||||||||||||||||||||||
binding = null; | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
@Override | ||||||||||||||||||||||||||||||||||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) { | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see us calling |
||||||||||||||||||||||||||||||||||||
super.onActivityResult(requestCode, resultCode, data); | ||||||||||||||||||||||||||||||||||||
finish(); | ||||||||||||||||||||||||||||||||||||
ConnectManager.handleFinishedActivity(this, requestCode, resultCode, data); | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
Additional security measures recommended for deep link handling
Based on the code analysis, while the activity implements basic deep link handling, several security improvements are needed:
callback_url
parameter, which could lead to potential security vulnerabilitiesRecommended actions:
🔗 Analysis chain
Verify security measures for exported activity handling deep links
The exported activity with deep link handling requires careful security review:
android:autoVerify="true"
is intended as it allows automatic verification of deep links🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
Length of output: 93
Script:
Length of output: 7692
Script:
Length of output: 3910
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that this is a concern and think we should probably improve both the intent filter and the data validation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@OrangeAndGreen Here are specific recommendations for both areas:
Would you like me to provide more detailed implementation for any of these areas?
🔗 Analysis chain
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
Length of output: 7592
✏️ Learnings added
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do agree with the suggestions here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.