Skip to content
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

feat: add an option to immediately remote verify #228

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,10 @@ public class AttestationActivity extends AppCompatActivity {

private static final int PERMISSIONS_REQUEST_CAMERA = 0;
private static final int PERMISSIONS_REQUEST_POST_NOTIFICATIONS_REMOTE_VERIFY = 1;

private static final int PERMISSIONS_REQUEST_POST_NOTIFICATIONS_SUBMIT_SAMPLE = 2;

private static final int PERMISSIONS_REQUEST_POST_NOTIFICATIONS_IMMEDIATE_REMOTE_VERIFY = 3;
private static final ExecutorService executor = Executors.newSingleThreadExecutor();

private ActivityAttestationBinding binding;
Expand Down Expand Up @@ -468,6 +470,9 @@ public void onRequestPermissionsResult(int requestCode,
}
} else if (requestCode == PERMISSIONS_REQUEST_POST_NOTIFICATIONS_REMOTE_VERIFY) {
QRScannerActivityLauncher.launch(new Intent(this, QRScannerActivity.class));
} else if (requestCode == PERMISSIONS_REQUEST_POST_NOTIFICATIONS_IMMEDIATE_REMOTE_VERIFY) {
RemoteVerifyJob.schedule(this, -1);
snackbar.setText(R.string.remote_verify_now).show();
} else if (requestCode == PERMISSIONS_REQUEST_POST_NOTIFICATIONS_SUBMIT_SAMPLE) {
SubmitSampleJob.schedule(this);
snackbar.setText(R.string.schedule_submit_sample_success).show();
Expand Down Expand Up @@ -502,6 +507,7 @@ public boolean onPrepareOptionsMenu(final Menu menu) {
menu.findItem(R.id.action_enable_remote_verify)
.setEnabled(isSupportedAuditee && !isRemoteVerifyEnabled);
menu.findItem(R.id.action_disable_remote_verify).setEnabled(isRemoteVerifyEnabled);
menu.findItem(R.id.action_remote_verify_now).setEnabled(isRemoteVerifyEnabled);
menu.findItem(R.id.action_submit_sample).setEnabled(canSubmitSample &&
!SubmitSampleJob.isScheduled(this));
return true;
Expand Down Expand Up @@ -544,7 +550,19 @@ public boolean onOptionsItemSelected(final MenuItem item) {
stage = Stage.EnableRemoteVerify;
startQrScanner();
return true;
} else if (itemId == R.id.action_disable_remote_verify) {
}
else if (itemId == R.id.action_remote_verify_now) {
Copy link
Author

Choose a reason for hiding this comment

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

Would it be right to use PERMISSIONS_REQUEST_POST_NOTIFICATIONS_REMOTE_VERIFY?

Copy link
Author

Choose a reason for hiding this comment

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

Thanks! Makes sense.

Copy link
Author

@zarakik zarakik Apr 23, 2023

Choose a reason for hiding this comment

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

I've added a new flow for immediate remote verify in onRequestPermission result and schedules an immediate remote verify. If for some reasons, the notification permissions are disabled, on clicking "Remote Verify Now" now asks the user to enable notification. Otherwise, if the notification permissions were already granted when doing "Enable remote verification", it wouldn't ask the user again for it.

if (checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.POST_NOTIFICATIONS},
PERMISSIONS_REQUEST_POST_NOTIFICATIONS_IMMEDIATE_REMOTE_VERIFY);
} else {
RemoteVerifyJob.schedule(this, -1);
snackbar.setText(R.string.remote_verify_now).show();
}
return true;
}

else if (itemId == R.id.action_disable_remote_verify) {
new AlertDialog.Builder(this)
.setMessage(getString(R.string.action_disable_remote_verify) + "?")
.setPositiveButton(R.string.disable, (dialogInterface, i) -> {
Expand Down
31 changes: 21 additions & 10 deletions app/src/main/java/app/attestation/auditor/RemoteVerifyJob.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ public class RemoteVerifyJob extends JobService {
private static final String TAG = "RemoteVerifyJob";
private static final int PERIODIC_JOB_ID = 0;
private static final int FIRST_RUN_JOB_ID = 1;

private static final int FIRE_ONCE_JOB_ID = 2;
static final String DOMAIN = "attestation.app";
private static final String CHALLENGE_URL = "https://" + DOMAIN + "/challenge";
private static final String VERIFY_URL = "https://" + DOMAIN + "/verify";
Expand Down Expand Up @@ -76,12 +78,15 @@ static void restore(final Context context) {
}

static void schedule(final Context context, int interval) {
if (interval < MIN_INTERVAL) {
interval = MIN_INTERVAL;
Log.e(TAG, "invalid interval " + interval + " clamped to MIN_INTERVAL " + MIN_INTERVAL);
} else if (interval > MAX_INTERVAL) {
interval = MAX_INTERVAL;
Log.e(TAG, "invalid interval " + interval + " clamped to MAX_INTERVAL " + MAX_INTERVAL);
boolean scheduleNow = interval == -1; // if interval = -1, the job needs to be scheduled now and only once.
if (!scheduleNow) {
if (interval < MIN_INTERVAL) {
interval = MIN_INTERVAL;
Log.e(TAG, "invalid interval " + interval + " clamped to MIN_INTERVAL " + MIN_INTERVAL);
} else if (interval > MAX_INTERVAL) {
interval = MAX_INTERVAL;
Log.e(TAG, "invalid interval " + interval + " clamped to MAX_INTERVAL " + MAX_INTERVAL);
}
}
final JobScheduler scheduler = context.getSystemService(JobScheduler.class);
final JobInfo jobInfo = scheduler.getPendingJob(PERIODIC_JOB_ID);
Expand All @@ -91,7 +96,8 @@ static void schedule(final Context context, int interval) {
jobInfo.getEstimatedNetworkDownloadBytes() == ESTIMATED_DOWNLOAD_BYTES &&
jobInfo.getEstimatedNetworkUploadBytes() == ESTIMATED_UPLOAD_BYTES &&
jobInfo.getIntervalMillis() == intervalMillis &&
jobInfo.getFlexMillis() == flexMillis) {
jobInfo.getFlexMillis() == flexMillis &&
!scheduleNow) {
Log.d(TAG, "job already registered");
return;
}
Expand All @@ -111,11 +117,16 @@ static void schedule(final Context context, int interval) {
throw new RuntimeException("job schedule failed");
}
}
final JobInfo.Builder builder = new JobInfo.Builder(PERIODIC_JOB_ID, serviceName)
.setPeriodic(intervalMillis, flexMillis)
final JobInfo.Builder builder = scheduleNow ?
new JobInfo.Builder(FIRE_ONCE_JOB_ID, serviceName)
.setPersisted(true)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
: new JobInfo.Builder(PERIODIC_JOB_ID, serviceName)
.setPersisted(true)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setEstimatedNetworkBytes(ESTIMATED_DOWNLOAD_BYTES, ESTIMATED_UPLOAD_BYTES);
.setEstimatedNetworkBytes(ESTIMATED_DOWNLOAD_BYTES, ESTIMATED_UPLOAD_BYTES)
.setPeriodic(intervalMillis, flexMillis);

if (scheduler.schedule(builder.build()) == JobScheduler.RESULT_FAILURE) {
throw new RuntimeException("job schedule failed");
}
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/menu/menu_attestation.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
<item android:id="@+id/action_disable_remote_verify"
android:title="@string/action_disable_remote_verify"
app:showAsAction="never" />
<item android:id="@+id/action_remote_verify_now"
android:title="@string/action_remote_verify_now"
app:showAsAction="never" />
<item android:id="@+id/action_submit_sample"
android:title="@string/action_submit_sample"
app:showAsAction="never" />
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@
<string name="action_clear_auditor">Clear Auditor pairings</string>
<string name="action_enable_remote_verify">Enable remote verification</string>
<string name="action_disable_remote_verify">Disable remote verification</string>
<string name="action_remote_verify_now">Remote verify now</string>
<string name="action_submit_sample">Submit sample data</string>
<string name="action_help">Help</string>

<string name="enable_remote_verify_success">Scheduled regular remote verification</string>
<string name="disable_remote_verify_success">Disabled remote verification</string>
<string name="remote_verify_now">Scheduled immediate remote verification</string>
<string name="schedule_submit_sample_success">Scheduled submitting sample data</string>
<string name="clear_auditee_pairings_success">Cleared Auditee pairings</string>
<string name="clear_auditee_pairings_failure">Failed to fully clear Auditee pairings</string>
Expand Down