From 797f53eba629d8b0a2717600d66d84d49d9fa3aa Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Sun, 15 Jul 2018 20:11:04 +0200 Subject: [PATCH] Login speed improved and network usage reduced --- .../java/de/sebse/fuplanner/MainActivity.java | 41 +++++---- .../fuplanner/fragments/LoginFragment.java | 9 +- .../de/sebse/fuplanner/services/KVV/KVV.java | 13 ++- .../fuplanner/services/KVV/KVVLogin.java | 91 ++++++++++++++++--- .../fuplanner/services/KVV/KVVModuleList.java | 4 +- .../services/KVV/types/LoginToken.java | 57 +++++++++++- .../fuplanner/services/KVV/types/Modules.java | 10 +- app/src/main/res/layout/nav_header_main.xml | 9 ++ 8 files changed, 184 insertions(+), 50 deletions(-) diff --git a/app/src/main/java/de/sebse/fuplanner/MainActivity.java b/app/src/main/java/de/sebse/fuplanner/MainActivity.java index 72aba7f..eea3738 100644 --- a/app/src/main/java/de/sebse/fuplanner/MainActivity.java +++ b/app/src/main/java/de/sebse/fuplanner/MainActivity.java @@ -2,33 +2,33 @@ package de.sebse.fuplanner; import android.content.Intent; import android.net.Uri; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentTransaction; import android.os.Bundle; import android.support.annotation.NonNull; -import android.util.Pair; -import android.view.View; import android.support.design.widget.NavigationView; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentTransaction; import android.support.v4.view.GravityCompat; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; +import android.util.Pair; import android.view.Menu; import android.view.MenuItem; +import android.view.View; import android.widget.TextView; import java.util.Calendar; import java.util.Iterator; import de.sebse.fuplanner.fragments.LoginFragment; -import de.sebse.fuplanner.fragments.ScheduleFragment; -import de.sebse.fuplanner.fragments.moddetails.ModDetailFragment; import de.sebse.fuplanner.fragments.ModulesFragment; +import de.sebse.fuplanner.fragments.ScheduleFragment; import de.sebse.fuplanner.fragments.StartupFragment; -import de.sebse.fuplanner.services.GoogleAuth.Credentials; +import de.sebse.fuplanner.fragments.moddetails.ModDetailFragment; import de.sebse.fuplanner.services.GoogleAuth.GoogleAuth; import de.sebse.fuplanner.services.KVV.KVV; +import de.sebse.fuplanner.services.KVV.types.LoginToken; import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.Conversion; import de.sebse.fuplanner.tools.logging.Logger; @@ -79,16 +79,16 @@ public class MainActivity extends AppCompatActivity this.getGoogleAuth().connect(() -> { getGoogleAuth().getLoginState(credentials -> { if (credentials == null || credentials.getUsername() == null || credentials.getPassword() == null) { - MainActivity.this.getKVV().endUpdate(); + this.getKVV().endUpdate(); toLogoutState(); return; } - MainActivity.this.getKVV().login(credentials.getUsername(), credentials.getPassword(), success -> { - MainActivity.this.getKVV().endUpdate(); - toLoginState(credentials); + this.getKVV().login(credentials.getUsername(), credentials.getPassword(), success -> { + this.getKVV().endUpdate(); + toLoginState(success); }, error -> { log.e(error); - MainActivity.this.getKVV().endUpdate(); + this.getKVV().endUpdate(); toLogoutState(); }); }); @@ -204,11 +204,11 @@ public class MainActivity extends AppCompatActivity return this.mKVV; } - private void toLoginState(Credentials credentials) { - if (credentials == null) { + private void toLoginState(LoginToken loginToken) { + if (loginToken == null) { toLogoutState(); } else { - toLoginState(credentials.getUsername()); + toLoginState(loginToken.getFullname(), loginToken.getEmail()); } } @@ -222,6 +222,7 @@ public class MainActivity extends AppCompatActivity View header = mNavigationView.getHeaderView(0); header.findViewById(R.id.imageView).setVisibility(View.GONE); header.findViewById(R.id.login_name).setVisibility(View.GONE); + header.findViewById(R.id.login_mail).setVisibility(View.GONE); header.findViewById(R.id.btn_login_page).setVisibility(View.VISIBLE); header.findViewById(R.id.btn_login_page).setOnClickListener(v -> { DrawerLayout drawer = findViewById(R.id.drawer_layout); @@ -233,7 +234,7 @@ public class MainActivity extends AppCompatActivity mNavigationView.inflateMenu(R.menu.activity_main_drawer); } - private void toLoginState(String username) { + private void toLoginState(String fullname, String email) { setTitle(R.string.courses); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.replace(R.id.fragcontainer, ModulesFragment.newInstance()); @@ -243,7 +244,9 @@ public class MainActivity extends AppCompatActivity View header = mNavigationView.getHeaderView(0); header.findViewById(R.id.imageView).setVisibility(View.VISIBLE); header.findViewById(R.id.login_name).setVisibility(View.VISIBLE); - ((TextView) header.findViewById(R.id.login_name)).setText(username); + header.findViewById(R.id.login_mail).setVisibility(View.VISIBLE); + ((TextView) header.findViewById(R.id.login_name)).setText(fullname); + ((TextView) header.findViewById(R.id.login_mail)).setText(email); header.findViewById(R.id.btn_login_page).setVisibility(View.GONE); mNavigationView.getMenu().clear(); mNavigationView.inflateMenu(R.menu.activity_main_drawer_login); @@ -275,8 +278,8 @@ public class MainActivity extends AppCompatActivity @Override - public void onLoginFragmentInteraction(String username) { - toLoginState(username); + public void onLoginFragmentInteraction(LoginToken loginToken) { + toLoginState(loginToken.getFullname(), loginToken.getEmail()); } @Override diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/LoginFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/LoginFragment.java index 7e0fc22..52a0cc1 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/LoginFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/LoginFragment.java @@ -17,6 +17,7 @@ import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; import de.sebse.fuplanner.services.GoogleAuth.GoogleAuth; import de.sebse.fuplanner.services.KVV.KVV; +import de.sebse.fuplanner.services.KVV.types.LoginToken; import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.logging.Logger; @@ -66,8 +67,8 @@ public class LoginFragment extends Fragment { if (modules != null) { Button offline_btn = v.findViewById(R.id.btn_offline); offline_btn.setVisibility(View.VISIBLE); - offline_btn.setText(v.getResources().getString(R.string.enter_offline_mode, modules.getUsername())); - offline_btn.setOnClickListener(v1 -> mListener.onLoginFragmentInteraction(modules.getUsername())); + offline_btn.setText(v.getResources().getString(R.string.enter_offline_mode, modules.getToken().getUsername())); + offline_btn.setOnClickListener(v1 -> mListener.onLoginFragmentInteraction(modules.getToken())); } } } catch (IOException e) { @@ -100,7 +101,7 @@ public class LoginFragment extends Fragment { progressDialog.dismiss(); gauth.setLoginState(username, password); if (mListener != null) - mListener.onLoginFragmentInteraction(username); + mListener.onLoginFragmentInteraction(success); }, error -> { progressDialog.dismiss(); log.e("Error on KVV login!", error); @@ -142,6 +143,6 @@ public class LoginFragment extends Fragment { * >Communicating with Other Fragments for more information. */ public interface OnLoginFragmentInteractionListener { - void onLoginFragmentInteraction(String username); + void onLoginFragmentInteraction(LoginToken loginToken); } } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVV.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVV.java index d48d15c..dbb691e 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVV.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVV.java @@ -10,7 +10,6 @@ import java.util.HashMap; import de.sebse.fuplanner.services.KVV.types.LoginToken; import de.sebse.fuplanner.services.KVV.types.Modules; -import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; @@ -24,10 +23,8 @@ public class KVV { private boolean isUpdating; private ArrayList updatingList; private HashMap addons = new HashMap<>(); - private Logger log = new Logger(this); public KVV(Context context) { - log.d("new kvv"); this.context = context; this.isUpdating = false; this.updatingList = new ArrayList<>(); @@ -37,12 +34,20 @@ public class KVV { KVVLogin login = new KVVLogin(this.context); login.login(username, password, success -> { lastToken = success; + try { + login.saveOffline(this.context); + } catch (IOException e) { + e.printStackTrace(); + } callback.onResponse(success); }, error); } public void logout() { - lastToken = null; + if (lastToken != null) { + lastToken.delete(this.context); + lastToken = null; + } KVVModuleList modules = (KVVModuleList) addons.get("modules"); if (modules != null) { modules.deleteModulesOffline(this.context); diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVLogin.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVLogin.java index a470bc3..4267930 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVLogin.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVLogin.java @@ -1,8 +1,11 @@ package de.sebse.fuplanner.services.KVV; import android.content.Context; -import android.util.Log; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.IOException; import java.util.HashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -18,23 +21,71 @@ import de.sebse.fuplanner.tools.network.NetworkErrorCallback; */ class KVVLogin extends HTTPService { - public KVVLogin(Context context) { + private LoginToken loginToken; + + KVVLogin(Context context) { super(context, false); + try { + this.loginToken = LoginToken.load(context); + } catch (IOException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } } - public void login(final String username, final String password, final NetworkCallback callback, final NetworkErrorCallback error) { + public void login(String username, String password, NetworkCallback callback, NetworkErrorCallback errorCallback) { + if (this.loginToken != null) { + if (this.loginToken.getUsername().equals(username)) { + log.d("Old login found!"); + testLogin(this.loginToken, success -> callback.onResponse(this.loginToken), error -> { + this.loginToken = null; + log.d("Old login invalid! Re-login..."); + login(username, password, callback, errorCallback); + }); + } else { + this.loginToken = null; + log.d("Login name no no match! Re-login..."); + login(username, password, callback, errorCallback); + } + } else { + log.d("No login found! Loggin in!"); + doLogin(username, password, token -> { + this.loginToken = token; + log.d("Logged in successfully! Testing..."); + testLogin(this.loginToken, success -> callback.onResponse(this.loginToken), errorCallback); + }, errorCallback); + } + } + + public void deleteOffline(Context context) { + if (this.loginToken != null) + this.loginToken.delete(context); + } + + public void saveOffline(Context context) throws IOException { + if (this.loginToken != null) + this.loginToken.save(context); + } + + + + + + + private void doLogin(String username, String password, NetworkCallback callback, NetworkErrorCallback error) { startKVVSession(success -> { - final String kvvJSESSIONID = success.get("JSESSIONID"); + String kvvJSESSIONID = success.get("JSESSIONID"); getSAMLRequest(kvvJSESSIONID, success1 -> startIdentSession(success1.get("Location"), success11 -> { - final String identJSESSIONID = success11.get("JSESSIONID"); - final String ident_idp_authn_lc_key = success11.get("_idp_authn_lc_key"); - final String identROUTEID = success11.get("ROUTEID"); + String identJSESSIONID = success11.get("JSESSIONID"); + String ident_idp_authn_lc_key = success11.get("_idp_authn_lc_key"); + String identROUTEID = success11.get("ROUTEID"); loginIdent(true, username, password, identJSESSIONID, ident_idp_authn_lc_key, identROUTEID, success111 -> loginIdent(false, username, password, identJSESSIONID, ident_idp_authn_lc_key, identROUTEID, success11112 -> { - final String ident_idp_session = success11112.get("_idp_session"); + String ident_idp_session = success11112.get("_idp_session"); getSAMLResponse(identJSESSIONID, ident_idp_authn_lc_key, identROUTEID, ident_idp_session, success1111 -> loginKVV(success1111.get("RelayState"), success1111.get("SAMLResponse"), kvvJSESSIONID, success111112 -> { - final LoginToken token = new LoginToken(username, success111112.get("shibsessionKey"), success111112.get("shibsessionName"), kvvJSESSIONID); + LoginToken token = new LoginToken(username, success111112.get("shibsessionKey"), success111112.get("shibsessionName"), kvvJSESSIONID); finishKVVlogin(token, success11111 -> { - Log.d("KVVMaster", "Login worked!"); + log.d("Login worked!"); callback.onResponse(token); }, error); }, error), error); @@ -43,6 +94,22 @@ class KVVLogin extends HTTPService { }, error); } + private void testLogin(LoginToken loginToken, NetworkCallback callback, NetworkErrorCallback errorCallback) { + get(String.format("https://kvv.imp.fu-berlin.de/direct/profile/%s.json", loginToken.getUsername()), loginToken.getCookies(), response -> { + String body = response.getParsed(); + try { + JSONObject json = new JSONObject(body); + String displayName = json.getString("displayName"); + String email = json.getString("email"); + loginToken.setAdditionals(displayName, email); + callback.onResponse(loginToken); + } catch (JSONException e) { + errorCallback.onError(new NetworkError(100201, 403, "Cannot parse announcements!")); + return; + } + }, error -> errorCallback.onError(new NetworkError(100200, error.networkResponse.statusCode, "Testing login failed!"))); + } + /* GET https://kvv.imp.fu-berlin.de/portal/login -> JSESSIONID 5c10406f-588c-4c16-96e9-c80d115417de.tomcat1 @@ -253,8 +320,8 @@ class KVVLogin extends HTTPService { Pattern pattern = Pattern.compile(name+"=([^;]+);"); Matcher matcher = pattern.matcher(cookies); if (!matcher.find()) { - Log.d("GETcookie failed", name); - Log.d("GETcookie failed", cookies); + log.d("GETcookie failed", name); + log.d("GETcookie failed", cookies); throw new NoSuchFieldException(); } return matcher.group(1); diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModuleList.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModuleList.java index 927d190..49c85fb 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModuleList.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModuleList.java @@ -46,7 +46,7 @@ public class KVVModuleList extends HTTPService { this.token = token; try { Modules modules = Modules.load(context); - if (token == null || modules.getUsername().equals(token.getUsername())) + if (token == null || token.isSameUser(modules.getToken())) this.moduleList = modules; } catch (IOException e) { e.printStackTrace(); @@ -84,7 +84,7 @@ public class KVVModuleList extends HTTPService { errorCallback.onError(new NetworkError(101101, 403, "No module list retrieved!")); return; } - Modules modules = new Modules(token.getUsername()); + Modules modules = new Modules(token); try { JSONObject json = new JSONObject(body); JSONArray sites = json.getJSONArray("site_collection"); diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/LoginToken.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/LoginToken.java index fcb6e32..7401945 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/LoginToken.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/LoginToken.java @@ -1,16 +1,27 @@ package de.sebse.fuplanner.services.KVV.types; +import android.content.Context; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; import java.util.HashMap; /** * Created by sebastian on 29.10.17. */ -public class LoginToken { +public class LoginToken implements Serializable { + private static final String FILE_NAME = "LoginTokenSaving"; private final String username; private final String shibsessionKey; private final String shibsessionName; private String JSESSIONID; + private String fullname; + private String email; public LoginToken(String username, String shibsessionKey, String shibsessionName, String JSESSIONID) { this.username = username; @@ -19,22 +30,56 @@ public class LoginToken { this.JSESSIONID = JSESSIONID; } + public static LoginToken load(Context context) throws IOException, ClassNotFoundException { + FileInputStream fis = context.openFileInput(FILE_NAME); + ObjectInputStream is = new ObjectInputStream(fis); + LoginToken loginToken = (LoginToken) is.readObject(); + is.close(); + fis.close(); + return loginToken; + } + + public void save(Context context) throws IOException { + FileOutputStream fos = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE); + ObjectOutputStream os = new ObjectOutputStream(fos); + os.writeObject(this); + os.close(); + fos.close(); + } + + public void delete(Context context) { + context.deleteFile(FILE_NAME); + } + + public void setAdditionals(String fullname, String email) { + this.fullname = fullname; + this.email = email; + } + public String getUsername() { return username; } - public String getShibsessionKey() { + private String getShibsessionKey() { return shibsessionKey; } - public String getShibsessionName() { + private String getShibsessionName() { return shibsessionName; } - public String getJSESSIONID() { + private String getJSESSIONID() { return JSESSIONID; } + public String getFullname() { + return fullname; + } + + public String getEmail() { + return email; + } + public HashMap getCookies() { HashMap cookies = new HashMap<>(); cookies.put("JSESSIONID", getJSESSIONID()); @@ -43,6 +88,10 @@ public class LoginToken { return cookies; } + public boolean isSameUser(LoginToken token) { + return token != null && this.getUsername().equals(token.getUsername()); + } + @Override public String toString() { StringBuilder result = new StringBuilder(); diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Modules.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Modules.java index bbda85e..9192910 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Modules.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Modules.java @@ -27,12 +27,12 @@ import de.sebse.fuplanner.tools.SortedModuleList; public class Modules implements Iterable, Serializable { private final SortedModuleList list; private String latestSemester = null; - private String username; + private LoginToken token; //private transient Logger log = new Logger(this); private static final String FILE_NAME = "ModuleListSaving"; - public Modules(String username) { - this.username = username; + public Modules(LoginToken loginToken) { + this.token = loginToken; this.list = new SortedModuleList(); } @@ -177,8 +177,8 @@ public class Modules implements Iterable, Serializable { context.deleteFile(FILE_NAME); } - public String getUsername() { - return username; + public LoginToken getToken() { + return token; } public class Module implements Serializable { diff --git a/app/src/main/res/layout/nav_header_main.xml b/app/src/main/res/layout/nav_header_main.xml index 2c10a22..cc487e1 100644 --- a/app/src/main/res/layout/nav_header_main.xml +++ b/app/src/main/res/layout/nav_header_main.xml @@ -39,4 +39,13 @@ tools:text="Android Studio" android:textAppearance="@style/TextAppearance.AppCompat.Body1" android:visibility="gone" /> + +