package me.ccrama.redditslide; import android.app.Activity; import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; import android.os.AsyncTask; import android.util.Log; import android.widget.Toast; import com.afollestad.materialdialogs.AlertDialogWrapper; import net.dean.jraw.RedditClient; import net.dean.jraw.http.LoggingMode; import net.dean.jraw.http.NetworkException; import net.dean.jraw.http.OkHttpAdapter; import net.dean.jraw.http.UserAgent; import net.dean.jraw.http.oauth.Credentials; import net.dean.jraw.http.oauth.OAuthData; import net.dean.jraw.http.oauth.OAuthHelper; import net.dean.jraw.models.LoggedInAccount; import java.util.Calendar; import java.util.HashSet; import java.util.UUID; import me.ccrama.redditslide.util.LogUtil; import me.ccrama.redditslide.util.NetworkUtil; import okhttp3.Protocol; /** * Created by ccrama on 3/30/2015. */ public class Authentication { private static final String CLIENT_ID = "KI2Nl9A_ouG9Qw"; private static final String REDIRECT_URL = "http://www.ccrama.me"; public static boolean isLoggedIn; public static RedditClient reddit; public static LoggedInAccount me; public static boolean mod; public static String name; public static SharedPreferences authentication; public static String refresh; public boolean hasDone; public static boolean didOnline; private static OkHttpAdapter httpAdapter; public static void resetAdapter() { new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { if (httpAdapter != null && httpAdapter.getNativeClient() != null) { httpAdapter.getNativeClient().connectionPool().evictAll(); } return null; } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } public Authentication(Context context) { Reddit.setDefaultErrorHandler(context); if (NetworkUtil.isConnected(context)) { hasDone = true; httpAdapter = new OkHttpAdapter(Reddit.client, Protocol.HTTP_2); isLoggedIn = false; reddit = new RedditClient( UserAgent.of("android:me.ccrama.RedditSlide:v" + BuildConfig.VERSION_NAME), httpAdapter); reddit.setRetryLimit(2); if (BuildConfig.DEBUG) reddit.setLoggingMode(LoggingMode.ALWAYS); didOnline = true; new VerifyCredentials(context).execute(); } else { isLoggedIn = Reddit.appRestart.getBoolean("loggedin", false); name = Reddit.appRestart.getString("name", ""); if ((name.isEmpty() || !isLoggedIn) && !authentication.getString("lasttoken", "") .isEmpty()) { for (String s : Authentication.authentication.getStringSet("accounts", new HashSet<String>())) { if (s.contains(authentication.getString("lasttoken", ""))) { name = (s.split(":")[0]); break; } } isLoggedIn = true; } } } public void updateToken(Context c) { if (BuildConfig.DEBUG) LogUtil.v("Executing update token"); if (reddit == null) { hasDone = true; isLoggedIn = false; reddit = new RedditClient( UserAgent.of("android:me.ccrama.RedditSlide:v" + BuildConfig.VERSION_NAME)); reddit.setLoggingMode(LoggingMode.ALWAYS); didOnline = true; new VerifyCredentials(c).execute(); } else { new UpdateToken(c).execute(); } } public static boolean authedOnce; public class UpdateToken extends AsyncTask<Void, Void, Void> { Context context; public UpdateToken(Context c) { this.context = c; } @Override protected Void doInBackground(Void... params) { if (authedOnce && NetworkUtil.isConnected(context)) { didOnline = true; if (name != null && !name.isEmpty()) { Log.v(LogUtil.getTag(), "REAUTH"); if (isLoggedIn) { try { final Credentials credentials = Credentials.installedApp(CLIENT_ID, REDIRECT_URL); Log.v(LogUtil.getTag(), "REAUTH LOGGED IN"); OAuthHelper oAuthHelper = reddit.getOAuthHelper(); oAuthHelper.setRefreshToken(refresh); OAuthData finalData; if (authentication.contains("backedCreds") && authentication.getLong("expires", 0) > Calendar.getInstance() .getTimeInMillis()) { finalData = oAuthHelper.refreshToken(credentials, authentication.getString("backedCreds", "")); //does a request } else { finalData = oAuthHelper.refreshToken(credentials); //does a request authentication.edit() .putLong("expires", Calendar.getInstance().getTimeInMillis() + 3000000) .apply(); } authentication.edit() .putString("backedCreds", finalData.getDataNode().toString()) .apply(); reddit.authenticate(finalData); refresh = oAuthHelper.getRefreshToken(); refresh = reddit.getOAuthHelper().getRefreshToken(); if (reddit.isAuthenticated()) { if (me == null) { me = reddit.me(); } Reddit.over18 = me.isOver18(); Authentication.isLoggedIn = true; } Log.v(LogUtil.getTag(), "AUTHENTICATED"); } catch (Exception e) { e.printStackTrace(); } } else { final Credentials fcreds = Credentials.userlessApp(CLIENT_ID, UUID.randomUUID()); OAuthData authData; if (BuildConfig.DEBUG) LogUtil.v("Not logged in"); try { authData = reddit.getOAuthHelper().easyAuth(fcreds); authentication.edit() .putLong("expires", Calendar.getInstance().getTimeInMillis() + 3000000) .apply(); authentication.edit() .putString("backedCreds", authData.getDataNode().toString()) .apply(); Authentication.name = "LOGGEDOUT"; mod = false; reddit.authenticate(authData); Log.v(LogUtil.getTag(), "REAUTH LOGGED IN"); } catch (Exception e) { try { ((Activity) context).runOnUiThread(new Runnable() { @Override public void run() { try { new AlertDialogWrapper.Builder(context).setTitle( R.string.err_general) .setMessage(R.string.err_no_connection) .setPositiveButton(R.string.btn_yes, new DialogInterface.OnClickListener() { @Override public void onClick( DialogInterface dialog, int which) { new UpdateToken( context).executeOnExecutor( AsyncTask.THREAD_POOL_EXECUTOR); } }) .setNegativeButton(R.string.btn_no, new DialogInterface.OnClickListener() { @Override public void onClick( DialogInterface dialog, int which) { Reddit.forceRestart(context); } }) .show(); } catch (Exception ignored) { } } }); } catch (Exception e2) { Toast.makeText(context, "Reddit could not be reached. Try again soon", Toast.LENGTH_SHORT).show(); } //TODO fail } } } } if (BuildConfig.DEBUG) LogUtil.v("Done loading token"); return null; } } public static class VerifyCredentials extends AsyncTask<String, Void, Void> { Context mContext; String lastToken; boolean single; public VerifyCredentials(Context context) { mContext = context; lastToken = authentication.getString("lasttoken", ""); } @Override protected Void doInBackground(String... subs) { doVerify(lastToken, reddit,single,mContext); return null; } } public static void doVerify(String lastToken, RedditClient baseReddit,boolean single, Context mContext){ try { String token = lastToken; if (BuildConfig.DEBUG) LogUtil.v("TOKEN IS " + token); if (!token.isEmpty()) { Credentials credentials = Credentials.installedApp(CLIENT_ID, REDIRECT_URL); OAuthHelper oAuthHelper = baseReddit.getOAuthHelper(); oAuthHelper.setRefreshToken(token); try { OAuthData finalData; if (!single && authentication.contains("backedCreds") && authentication.getLong("expires", 0) > Calendar.getInstance() .getTimeInMillis()) { finalData = oAuthHelper.refreshToken(credentials, authentication.getString("backedCreds", "")); } else { finalData = oAuthHelper.refreshToken(credentials); //does a request if (!single) { authentication.edit() .putLong("expires", Calendar.getInstance().getTimeInMillis() + 3000000) .apply(); } } baseReddit.authenticate(finalData); if (!single) { authentication.edit() .putString("backedCreds", finalData.getDataNode().toString()) .apply(); refresh = oAuthHelper.getRefreshToken(); if (BuildConfig.DEBUG) { LogUtil.v("ACCESS TOKEN IS " + finalData.getAccessToken()); } Authentication.isLoggedIn = true; UserSubscriptions.doCachedModSubs(); } } catch (Exception e) { e.printStackTrace(); if (e instanceof NetworkException) { Toast.makeText(mContext, "Error " + ((NetworkException) e).getResponse() .getStatusMessage() + ": " + (e).getMessage(), Toast.LENGTH_LONG).show(); } } didOnline = true; } else if (!single) { if (BuildConfig.DEBUG) LogUtil.v("NOT LOGGED IN"); final Credentials fcreds = Credentials.userlessApp(CLIENT_ID, UUID.randomUUID()); OAuthData authData; try { authData = reddit.getOAuthHelper().easyAuth(fcreds); authentication.edit() .putLong("expires", Calendar.getInstance().getTimeInMillis() + 3000000) .apply(); authentication.edit() .putString("backedCreds", authData.getDataNode().toString()) .apply(); reddit.authenticate(authData); Authentication.name = "LOGGEDOUT"; Reddit.notFirst = true; didOnline = true; } catch (Exception e) { e.printStackTrace(); if (e instanceof NetworkException) { Toast.makeText(mContext, "Error " + ((NetworkException) e).getResponse() .getStatusMessage() + ": " + (e).getMessage(), Toast.LENGTH_LONG).show(); } } } if (!single) authedOnce = true; } catch (Exception e) { //TODO fail } } }