package org.azavea.otm; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.os.Handler.Callback; import android.os.Message; import org.azavea.helpers.Logger; import org.azavea.otm.data.User; import org.azavea.otm.rest.RequestGenerator; import org.azavea.otm.rest.handlers.RestHandler; import org.azavea.otm.ui.InstanceSwitcherActivity; import org.json.JSONException; import cz.msebera.android.httpclient.client.HttpResponseException; public class LoginManager { private static final String MESSAGE_KEY = "message"; private static final String USER_KEY = "user"; private static final String PASS_KEY = "pass"; private final Context context; private final SharedPreferences prefs; public User loggedInUser = null; public LoginManager(Context context) { this.context = context; this.prefs = getPreferences(); } /** * Store new password in user preferences */ public void storePassword(String newpass) { prefs.edit().putString(PASS_KEY, newpass).commit(); } public boolean isLoggedIn() { return loggedInUser != null; } public void logIn(final Context activityContext, final String username, final String password, final Callback callback) { final RequestGenerator rg = new RequestGenerator(); rg.logIn(activityContext, username, password, new RestHandler<User>(new User()) { final Message resultMessage = new Message(); private void handleCallback(Bundle data) { resultMessage.setData(data); if (App.hasInstanceCode()) { App.reloadInstanceInfo(msg -> { callback.handleMessage(resultMessage); return true; }); } else { callback.handleMessage(resultMessage); } } @Override public void failure(Throwable e, String message) { final Bundle data = new Bundle(); data.putBoolean(SUCCESS_KEY, false); data.putString(MESSAGE_KEY, activityContext.getString(R.string.could_not_connect)); if (e instanceof HttpResponseException) { final HttpResponseException actualError = (HttpResponseException) e; if (actualError.getStatusCode() == 401) { data.putString(MESSAGE_KEY, activityContext.getString(R.string.incorrect_username_or_password)); } } handleCallback(data); rg.cancelRequests(activityContext); } @Override public void dataReceived(User response) { final Bundle data = new Bundle(); prefs.edit().putString(USER_KEY, username).commit(); storePassword(password); App.getAppInstance().setUserOnAnalyticsTracker(response); loggedInUser = response; try { loggedInUser.setPassword(password); } catch (JSONException e) { Logger.error("Error setting user password", e); } data.putBoolean(SUCCESS_KEY, true); handleCallback(data); } }); } public void logOut(Activity activity) { logOut(); if (!App.hasSkinCode()) { Intent intent = new Intent(activity, InstanceSwitcherActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); activity.startActivity(intent); activity.finish(); } } private void logOut() { // Previous instance info is now invalid App.removeCurrentInstance(); loggedInUser = null; prefs.edit().remove(USER_KEY).commit(); prefs.edit().remove(PASS_KEY).commit(); App.getAppInstance().setUserOnAnalyticsTracker(null); } /** * Automatically and silently authenticate if credentials have been saved */ public void autoLogin(final Callback callback) { String user = prefs.getString(USER_KEY, null); String pass = prefs.getString(PASS_KEY, null); if (user != null && pass != null) { logIn(context, user, pass, msg -> { Bundle data = msg.getData(); if (data == null || !data.getBoolean(RestHandler.SUCCESS_KEY)) { logOut(); } return callback.handleMessage(msg); }); } else if (App.hasInstanceCode()) { // If there is no user to auto login, the app still needs to // make an instance request, which is otherwise associated and // instigated after a login attempt App.reloadInstanceInfo(callback); } else { Message msg = Message.obtain(); Bundle args = new Bundle(); args.putBoolean(RestHandler.SUCCESS_KEY, false); msg.setData(args); callback.handleMessage(msg); } } private SharedPreferences getPreferences() { return context.getSharedPreferences(context.getString(R.string.app_name), Context.MODE_PRIVATE); } }