package org.commcare.activities;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import org.commcare.CommCareApplication;
import org.commcare.dalvik.R;
import org.commcare.android.database.app.models.UserKeyRecord;
import org.commcare.views.ManagedUi;
import org.commcare.views.UiElement;
import org.javarosa.core.services.locale.Localization;
/**
* When a user selects Set/Reset PIN from the home activity options menu, they must first
* authenticate themselves in order to be able to do so. This is the activity that launches to
* prompt the user to enter either their current PIN, if it exists, or their password if it does
* not, before proceeding to the CreatePinActivity
*
* @author Aliza Stone (astone@dimagi.com)
*/
@ManagedUi(R.layout.pin_auth_view)
public class PinAuthenticationActivity extends
SessionAwareCommCareActivity<PinAuthenticationActivity> {
@UiElement(R.id.pin_prompt_text)
private TextView promptText;
@UiElement(R.id.pin_entry)
private EditText pinEntry;
@UiElement(R.id.password_entry)
private EditText passwordEntry;
@UiElement(value = R.id.pin_confirm_button, locale = "pin.auth.enter.button")
private Button enterButton;
@UiElement(R.id.pin_cancel_button)
private Button cancelButton;
private LoginMode authMode;
private UserKeyRecord currentRecord;
@Override
protected void onCreateSessionSafe(Bundle savedInstanceState) {
super.onCreateSessionSafe(savedInstanceState);
if (!setRecordAndAuthMode()) {
return;
}
setupUI();
}
/**
* User the information in the current user's UKR to determine what auth mode we should be in
*
* @return If the call completed successfully
*/
private boolean setRecordAndAuthMode() {
currentRecord = CommCareApplication.instance().getRecordForCurrentUser();
if (currentRecord.hasPinSet()) {
// If a PIN is already set and the user is trying to change it, we can have them
// enter that, and then use it to get the password
authMode = LoginMode.PIN;
} else {
// Otherwise, we're going to need them to enter their password
authMode = LoginMode.PASSWORD;
}
return true;
}
private void setupUI() {
if (authMode == LoginMode.PASSWORD) {
setPasswordAuthModeUI();
} else {
setPinAuthModeUI();
}
pinEntry.addTextChangedListener(CreatePinActivity.getPinTextWatcher(enterButton));
pinEntry.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_NEXT) {
enterButton.performClick();
return true;
}
return false;
}
});
enterButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (authMode == LoginMode.PASSWORD) {
checkEnteredPassword();
} else {
checkEnteredPin();
}
}
});
cancelButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setResult(RESULT_CANCELED);
finish();
}
});
}
private void setPinAuthModeUI() {
promptText.setText(Localization.get("pin.auth.prompt.pin"));
pinEntry.setVisibility(View.VISIBLE);
pinEntry.setImeOptions(EditorInfo.IME_ACTION_NEXT);
passwordEntry.setVisibility(View.GONE);
enterButton.setEnabled(false);
}
private void setPasswordAuthModeUI() {
promptText.setText(Localization.get("pin.auth.prompt.password"));
passwordEntry.setVisibility(View.VISIBLE);
pinEntry.setVisibility(View.GONE);
enterButton.setEnabled(true);
}
private void checkEnteredPassword() {
String enteredPassword = passwordEntry.getText().toString();
if (currentRecord.isPasswordValid(enteredPassword)) {
onSuccessfulAuth();
} else {
onUnsuccessfulAuth();
}
}
private void checkEnteredPin() {
String enteredPin = pinEntry.getText().toString();
if (currentRecord.isPinValid(enteredPin)) {
onSuccessfulAuth();
} else {
onUnsuccessfulAuth();
}
}
private void onUnsuccessfulAuth() {
if (authMode == LoginMode.PIN) {
Toast.makeText(this, Localization.get("pin.auth.failed.pin"), Toast.LENGTH_LONG).show();
pinEntry.setText("");
} else {
Toast.makeText(this, Localization.get("pin.auth.failed.password"), Toast.LENGTH_LONG).show();
passwordEntry.setText("");
}
}
private void onSuccessfulAuth() {
setResult(RESULT_OK);
finish();
}
}