Login speed improved and network usage reduced

This commit is contained in:
Caesar2011
2018-07-15 20:11:04 +02:00
parent 17e9c6e17d
commit 797f53eba6
8 changed files with 184 additions and 50 deletions

View File

@@ -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

View File

@@ -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</a> for more information.
*/
public interface OnLoginFragmentInteractionListener {
void onLoginFragmentInteraction(String username);
void onLoginFragmentInteraction(LoginToken loginToken);
}
}

View File

@@ -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<LastTokenCallback> updatingList;
private HashMap<String, Object> 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);

View File

@@ -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<LoginToken> callback, final NetworkErrorCallback error) {
public void login(String username, String password, NetworkCallback<LoginToken> 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<LoginToken> 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<LoginToken> 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);

View File

@@ -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");

View File

@@ -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<String, String> getCookies() {
HashMap<String, String> 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();

View File

@@ -27,12 +27,12 @@ import de.sebse.fuplanner.tools.SortedModuleList;
public class Modules implements Iterable<Modules.Module>, 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<Modules.Module>, Serializable {
context.deleteFile(FILE_NAME);
}
public String getUsername() {
return username;
public LoginToken getToken() {
return token;
}
public class Module implements Serializable {

View File

@@ -39,4 +39,13 @@
tools:text="Android Studio"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:visibility="gone" />
<TextView
android:id="@+id/login_mail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/nav_header_vertical_spacing"
tools:text="Android Studio"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:visibility="gone" />
</LinearLayout>