diff --git a/README.md b/README.md index c3fae70..b603585 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,6 @@ Trying to make using [Simperium][Simperium.com] in your Android app dead simple. Simperium for Android is configured as an [Android Library Project][]. -TODO: brief code example/tutorial :) - ## Contributing To get started first clone the project: @@ -28,6 +26,23 @@ Please provide unit tests for your contributions. Run tests with gradle: Unit tests use a mock networking and storage stack so that different components can be tested in isolation. The unit tests should not connect to any external services. +## Publish to S3 + +A new version of this library will be automatically published to S3 by CI in the following scenarios: + +**Note**: `sha1` corresponds to the commit hash. + +* For all tags -> Version: `{tag-name}` +* For all commits in `develop` (so PR merges) -> Version: `develop-{sha1}` +* For all commits for open PRs - you can open a draft PR to get it to publish -> Version: `{prNumber}-{sha1}` + +## Usage + +### Adding simperium as dependency + +```groovy +implementation 'com.automattic:simperium:' +``` [Android Studio]: http://developer.android.com/sdk/installing/studio.html [Gradle]: http://www.gradleware.com diff --git a/Simperium/src/main/java/com/simperium/android/CredentialsActivity.java b/Simperium/src/main/java/com/simperium/android/CredentialsActivity.java index 0500868..a053b9c 100644 --- a/Simperium/src/main/java/com/simperium/android/CredentialsActivity.java +++ b/Simperium/src/main/java/com/simperium/android/CredentialsActivity.java @@ -1,5 +1,8 @@ package com.simperium.android; +import static com.simperium.android.AuthenticationActivity.EXTRA_IS_LOGIN; +import static org.apache.http.protocol.HTTP.UTF_8; + import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; @@ -43,9 +46,6 @@ import java.net.URLEncoder; import java.util.regex.Pattern; -import static com.simperium.android.AuthenticationActivity.EXTRA_IS_LOGIN; -import static org.apache.http.protocol.HTTP.UTF_8; - public class CredentialsActivity extends AppCompatActivity { private static final Pattern PATTERN_NEWLINES_RETURNS_TABS = Pattern.compile("[\n\r\t]"); private static final String EXTRA_AUTOMATE_LOGIN = "EXTRA_AUTOMATE_LOGIN"; @@ -62,9 +62,9 @@ public class CredentialsActivity extends AppCompatActivity { private Simperium mSimperium; private TextInputLayout mInputEmail; private TextInputLayout mInputPassword; - private boolean mIsLogin; + protected boolean mIsLogin; - private AuthResponseListener mAuthListener = new AuthResponseListener() { + protected AuthResponseListener mAuthListener = new AuthResponseListener() { @Override public void onFailure(final User user, final AuthException error) { runOnUiThread( @@ -95,38 +95,11 @@ public void run() { @Override public void onSuccess(final User user, final String userId, final String token, final AuthProvider provider) { - runOnUiThread( - new Runnable() { - @Override - public void run() { - hideDialogProgress(); - InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - - if (inputMethodManager != null) { - inputMethodManager.hideSoftInputFromWindow(mButton.getWindowToken(), 0); - } - - // Use isValidPasswordLength(false) to check if password meets PASSWORD_LENGTH_MINIMUM. - if (isValidPassword(user.getEmail(), user.getPassword()) && isValidPasswordLength(false)) { - user.setStatus(User.Status.AUTHORIZED); - user.setAccessToken(token); - user.setUserId(userId); - provider.saveUser(user); - setResult(RESULT_OK); - finish(); - } else { - user.setStatus(User.Status.NOT_AUTHORIZED); - user.setAccessToken(""); - user.setUserId(""); - provider.saveUser(user); - showDialogErrorLoginReset(); - } - } - } - ); + handleResponseSuccess(user, userId, token, provider); } }; + @Override public void onBackPressed() { startActivity(new Intent(CredentialsActivity.this, AuthenticationActivity.class)); @@ -309,6 +282,39 @@ public void run() { } } + protected void handleResponseSuccess(final User user, final String userId, final String token, final AuthProvider provider) { + runOnUiThread( + new Runnable() { + @Override + public void run() { + hideDialogProgress(); + InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + + if (inputMethodManager != null) { + inputMethodManager.hideSoftInputFromWindow(mButton.getWindowToken(), 0); + } + + // Use isValidPasswordLength(false) to check if password meets PASSWORD_LENGTH_MINIMUM. + if (isValidPassword(user.getEmail(), user.getPassword()) && isValidPasswordLength(false)) { + user.setStatus(User.Status.AUTHORIZED); + user.setAccessToken(token); + user.setUserId(userId); + provider.saveUser(user); + setResult(RESULT_OK); + finish(); + } else { + user.setStatus(User.Status.NOT_AUTHORIZED); + user.setAccessToken(""); + user.setUserId(""); + provider.saveUser(user); + showDialogErrorLoginReset(); + } + } + } + ); + } + + @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { @@ -354,7 +360,7 @@ private String getEditTextString(@NonNull TextInputLayout inputLayout) { return inputLayout.getEditText() != null ? inputLayout.getEditText().getText().toString() : ""; } - private void hideDialogProgress() { + protected void hideDialogProgress() { if (mProgressDialogFragment != null && !mProgressDialogFragment.isHidden()) { mProgressDialogFragment.dismiss(); mProgressDialogFragment = null; @@ -407,7 +413,7 @@ private void setEditTextString(@NonNull TextInputLayout inputLayout, String text } } - private void showDialogError(String message) { + protected void showDialogError(String message) { hideDialogProgress(); Context context = new ContextThemeWrapper(CredentialsActivity.this, getTheme()); new AlertDialog.Builder(context) @@ -417,7 +423,7 @@ private void showDialogError(String message) { .show(); } - private void showDialogErrorExistingAccount() { + protected void showDialogErrorExistingAccount() { hideDialogProgress(); Context context = new ContextThemeWrapper(CredentialsActivity.this, getTheme()); new AlertDialog.Builder(context) @@ -441,7 +447,7 @@ public void onClick(DialogInterface dialog, int which) { .show(); } - private void showDialogErrorLoginReset() { + void showDialogErrorLoginReset() { hideDialogProgress(); final Context context = new ContextThemeWrapper(CredentialsActivity.this, getTheme()); new AlertDialog.Builder(context) @@ -487,7 +493,7 @@ public void onClick(DialogInterface dialog, int which) { .show(); } - private void showCompromisedPasswordDialog() { + protected void showCompromisedPasswordDialog() { hideDialogProgress(); final Context context = new ContextThemeWrapper(CredentialsActivity.this, getTheme()); new AlertDialog.Builder(context) @@ -524,12 +530,16 @@ private void startLogin() { mProgressDialogFragment = ProgressDialogFragment.newInstance(getString(R.string.simperium_dialog_progress_logging_in)); mProgressDialogFragment.setStyle(DialogFragment.STYLE_NO_TITLE, R.style.Simperium); mProgressDialogFragment.show(getSupportFragmentManager(), ProgressDialogFragment.TAG); - mSimperium.authorizeUser(email, password, mAuthListener); + mSimperium.authorizeUser(email, password, getAuthListener()); } else { showDialogError(getString(R.string.simperium_dialog_message_password_login, PASSWORD_LENGTH_LOGIN)); } } + protected AuthResponseListener getAuthListener() { + return mAuthListener; + } + private void startSignup() { final String email = getEditTextString(mInputEmail); final String password = getEditTextString(mInputPassword); @@ -543,4 +553,8 @@ private void startSignup() { showDialogError(getString(R.string.simperium_dialog_message_password, PASSWORD_LENGTH_MINIMUM)); } } + + protected String getEmail() { + return getEditTextString(mInputEmail); + } } diff --git a/Simperium/src/main/java/com/simperium/client/AuthException.java b/Simperium/src/main/java/com/simperium/client/AuthException.java index 0a0835e..cd6e90c 100644 --- a/Simperium/src/main/java/com/simperium/client/AuthException.java +++ b/Simperium/src/main/java/com/simperium/client/AuthException.java @@ -8,6 +8,7 @@ public class AuthException extends SimperiumException { static public final String GENERIC_FAILURE_MESSAGE = "Invalid username or password"; static public final String EXISTING_USER_FAILURE_MESSAGE = "Account already exists"; + static public final String UNVERIFIED_ACCOUNT_MESSAGE = "Account verification required"; static public final String COMPROMISED_PASSWORD_MESSAGE = "Password has been compromised"; static public final String COMPROMISED_PASSWORD_BODY = "compromised password"; @@ -16,7 +17,7 @@ public class AuthException extends SimperiumException { public final FailureType failureType; public enum FailureType { - INVALID_ACCOUNT, EXISTING_ACCOUNT, COMPROMISED_PASSWORD + INVALID_ACCOUNT, EXISTING_ACCOUNT, COMPROMISED_PASSWORD, UNVERIFIED_ACCOUNT } public AuthException(FailureType code, String message){ @@ -41,6 +42,8 @@ public static AuthException exceptionForStatusCode(int statusCode, Throwable cau switch (statusCode) { case 409: return new AuthException(FailureType.EXISTING_ACCOUNT, EXISTING_USER_FAILURE_MESSAGE, cause); + case 403: + return new AuthException(FailureType.UNVERIFIED_ACCOUNT, UNVERIFIED_ACCOUNT_MESSAGE, cause); case 401: // Code 401 can be obtain because credentials are wrong or the user's password has been compromised // To differentiate both responses, we check the response's body diff --git a/Simperium/src/main/res/values/strings.xml b/Simperium/src/main/res/values/strings.xml index 42e21fb..883d2e8 100644 --- a/Simperium/src/main/res/values/strings.xml +++ b/Simperium/src/main/res/values/strings.xml @@ -40,4 +40,7 @@ Change Password @string/app_name https://simperium.com/ + Account Verification Required + You must verify your email before logging in to your account. + Okay