Login Finished
This commit is contained in:
@@ -1,12 +1,7 @@
|
||||
package de.sebse.fuplanner;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.AccountManagerFuture;
|
||||
import android.accounts.AuthenticatorException;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
@@ -19,7 +14,6 @@ import com.google.android.material.navigation.NavigationView;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
@@ -35,7 +29,6 @@ import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import de.sebse.fuplanner.fragments.CanteensFragment;
|
||||
import de.sebse.fuplanner.fragments.LoginFragment;
|
||||
import de.sebse.fuplanner.fragments.ModulesFragment;
|
||||
import de.sebse.fuplanner.fragments.NewsFragment;
|
||||
import de.sebse.fuplanner.fragments.PrefsFragment;
|
||||
@@ -54,6 +47,7 @@ import de.sebse.fuplanner.services.KVV.types.LoginToken;
|
||||
import de.sebse.fuplanner.services.KVV.types.Modules;
|
||||
import de.sebse.fuplanner.services.News.NewsManager;
|
||||
import de.sebse.fuplanner.services.newkvv.AccountGeneral;
|
||||
import de.sebse.fuplanner.tools.CustomAccountManager;
|
||||
import de.sebse.fuplanner.tools.MainActivityListener;
|
||||
import de.sebse.fuplanner.tools.NewAsyncQueue;
|
||||
import de.sebse.fuplanner.tools.Preferences;
|
||||
@@ -75,6 +69,7 @@ public class MainActivity extends AppCompatActivity
|
||||
private static final int FRAGMENT_STARTUP = 0;
|
||||
private static final int FRAGMENT_MODULES = 1;
|
||||
private static final int FRAGMENT_MODULES_DETAILS = 2;
|
||||
@Deprecated
|
||||
private static final int FRAGMENT_LOGIN = 3;
|
||||
private static final int FRAGMENT_SCHEDULE = 4;
|
||||
private static final int FRAGMENT_CANTEENS = 5;
|
||||
@@ -101,12 +96,14 @@ public class MainActivity extends AppCompatActivity
|
||||
private boolean mOfflineBanner;
|
||||
private final NewAsyncQueue mQueue = new NewAsyncQueue();
|
||||
private long mDoubleBackToExitPressedOnce = 0;
|
||||
private AccountManager mAccountManager;
|
||||
private CustomAccountManager mAccountManager;
|
||||
private boolean isPaused = false;
|
||||
private boolean isLoggedInBeforePause = false;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mAccountManager = AccountManager.get(this);
|
||||
mAccountManager = new CustomAccountManager(AccountManager.get(this), () -> MainActivity.this);
|
||||
int desiredPage = getDefaultFragmentAfterLogin();
|
||||
String desiredData = "";
|
||||
if (savedInstanceState != null) {
|
||||
@@ -128,12 +125,52 @@ public class MainActivity extends AppCompatActivity
|
||||
mNavigationView.setNavigationItemSelectedListener(this);
|
||||
mFragmentManager = getSupportFragmentManager();
|
||||
|
||||
if (!getKVV().account().restoreOnlineLogin()) {
|
||||
desiredPage = FRAGMENT_LOGIN;
|
||||
//if (mAccountManager.getAccountsByType(AccountGeneral.ACCOUNT_TYPE).length == 0) {
|
||||
if (!mAccountManager.hasAccounts(AccountGeneral.ACCOUNT_TYPE)) {
|
||||
desiredPage = getDefaultFragmentAfterLogout();
|
||||
desiredData = "";
|
||||
mAccountManager.getTokenForAccountCreateIfNeeded(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_KVV);
|
||||
updateNavigation();
|
||||
changeFragment(desiredPage, desiredData);
|
||||
} else {
|
||||
updateNavigation();
|
||||
changeFragment(FRAGMENT_STARTUP);
|
||||
int targetPage = desiredPage;
|
||||
String targetData = desiredData;
|
||||
getKVV().account().restoreOnlineLogin(isRestored -> {
|
||||
updateNavigation();
|
||||
if (isRestored)
|
||||
changeFragment(targetPage, targetData);
|
||||
else
|
||||
changeFragment(getDefaultFragmentAfterLogout());
|
||||
});
|
||||
}
|
||||
updateNavigation();
|
||||
changeFragment(desiredPage, desiredData);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
isPaused = true;
|
||||
isLoggedInBeforePause = getKVV().account().isLoggedIn();
|
||||
log.d("onPause", isPaused, isLoggedInBeforePause);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
log.d("onResume", isPaused, isLoggedInBeforePause);
|
||||
if (isPaused) {
|
||||
getKVV().account().reset();
|
||||
getKVV().account().restoreOnlineLogin(isRestored -> {
|
||||
log.d("onResume", isRestored);
|
||||
updateNavigation();
|
||||
if (isRestored && !isLoggedInBeforePause)
|
||||
changeFragment(getDefaultFragmentAfterLogin());
|
||||
else if (!isRestored && isLoggedInBeforePause)
|
||||
changeFragment(getDefaultFragmentAfterLogin());
|
||||
});
|
||||
}
|
||||
isPaused = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -163,12 +200,10 @@ public class MainActivity extends AppCompatActivity
|
||||
}
|
||||
} else if (getKVV().account().isLoggedIn() && mFragmentPage != getDefaultFragmentAfterLogin()) {
|
||||
changeFragment(getDefaultFragmentAfterLogin());
|
||||
} else if (!getKVV().account().isLoggedIn() && mFragmentPage != FRAGMENT_LOGIN) {
|
||||
changeFragment(FRAGMENT_LOGIN);
|
||||
} else {
|
||||
mDoubleBackToExitPressedOnce = System.currentTimeMillis();
|
||||
showToast(R.string.back_to_exit);
|
||||
getTokenForAccountCreateIfNeeded(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_KVV);
|
||||
//getTokenForAccountCreateIfNeeded(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_KVV);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -266,7 +301,7 @@ public class MainActivity extends AppCompatActivity
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle savedInstanceState) {
|
||||
if (mFragmentPage != FRAGMENT_STARTUP && mFragmentPage != FRAGMENT_NONE && mFragmentPage != FRAGMENT_LOGIN) {
|
||||
if (mFragmentPage != FRAGMENT_STARTUP && mFragmentPage != FRAGMENT_NONE) {
|
||||
Fragment fragment = mFragmentManager.findFragmentByTag(String.valueOf(mFragmentPage));
|
||||
savedInstanceState.putInt(ARG_FRAGMENT_PAGE, mFragmentPage);
|
||||
if (fragment instanceof ModDetailFragment) {
|
||||
@@ -323,11 +358,16 @@ public class MainActivity extends AppCompatActivity
|
||||
return FRAGMENT_MODULES;
|
||||
}
|
||||
|
||||
private int getDefaultFragmentAfterLogout() {
|
||||
return FRAGMENT_CANTEENS;
|
||||
}
|
||||
|
||||
private void toLogoutState() {
|
||||
setOfflineBanner(false);
|
||||
setRefreshFailedBanner(false);
|
||||
updateNavigation();
|
||||
changeFragment(FRAGMENT_LOGIN);
|
||||
changeFragment(getDefaultFragmentAfterLogout());
|
||||
mAccountManager.getTokenForAccountCreateIfNeeded(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_KVV);
|
||||
}
|
||||
|
||||
private void toLoginState(String fullName, String email, int newFragment, boolean onlineMode) {
|
||||
@@ -362,9 +402,9 @@ public class MainActivity extends AppCompatActivity
|
||||
case FRAGMENT_MODULES:
|
||||
fragment = ModulesFragment.newInstance();
|
||||
break;
|
||||
case FRAGMENT_LOGIN:
|
||||
/*case FRAGMENT_LOGIN:
|
||||
fragment = LoginFragment.newInstance();
|
||||
break;
|
||||
break;*/
|
||||
case FRAGMENT_SCHEDULE:
|
||||
fragment = ScheduleFragment.newInstance();
|
||||
break;
|
||||
@@ -486,7 +526,7 @@ public class MainActivity extends AppCompatActivity
|
||||
if (drawer.isDrawerOpen(GravityCompat.START)) {
|
||||
drawer.closeDrawer(GravityCompat.START);
|
||||
}
|
||||
changeFragment(FRAGMENT_LOGIN);
|
||||
mAccountManager.getTokenForAccountCreateIfNeeded(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_KVV);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -537,7 +577,7 @@ public class MainActivity extends AppCompatActivity
|
||||
menuItem.setIcon(R.drawable.ic_sms_failed);
|
||||
View view = View.inflate(this, R.layout.action_icon_number, null);
|
||||
TextView v = view.findViewById(R.id.number);
|
||||
((TextView) view.findViewById(R.id.number)).setText(String.format(Locale.getDefault(), "%d", i));
|
||||
v.setText(String.format(Locale.getDefault(), "%d", i));
|
||||
menuItem.setActionView(view);
|
||||
}
|
||||
if (++count[0] == MAX_COUNT) done.run();
|
||||
@@ -563,53 +603,8 @@ public class MainActivity extends AppCompatActivity
|
||||
});
|
||||
}
|
||||
|
||||
private void doInvalidateToken(String accountType, String authTokenType) {
|
||||
//String token = mAccountManager.blockingGetAuthToken();
|
||||
Account account = mAccountManager.getAccountsByType(accountType)[0];
|
||||
String token = null;
|
||||
try {
|
||||
token = mAccountManager.blockingGetAuthToken(account, authTokenType, true);
|
||||
log.d("hihihi", accountType, authTokenType, token);
|
||||
mAccountManager.invalidateAuthToken(accountType, token);
|
||||
} catch (AuthenticatorException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (OperationCanceledException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteAccount(String accountType) {
|
||||
Account[] accounts = mAccountManager.getAccountsByType(accountType);
|
||||
int[] count = {accounts.length};
|
||||
for (Account account: accounts) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
|
||||
mAccountManager.removeAccount(account, null, null, null);
|
||||
} else {
|
||||
mAccountManager.removeAccount(account, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void getTokenForAccountCreateIfNeeded(String accountType, String authTokenType) {
|
||||
deleteAccount(accountType);
|
||||
final AccountManagerFuture<Bundle> future = mAccountManager.getAuthTokenByFeatures(accountType, authTokenType, null, this, null, null,
|
||||
future1 -> {
|
||||
Bundle bnd = null;
|
||||
try {
|
||||
bnd = future1.getResult();
|
||||
final String authtoken = bnd.getString(AccountManager.KEY_AUTHTOKEN);
|
||||
showToast(((authtoken != null) ? "SUCCESS!\ntoken: " + authtoken : "FAIL"));
|
||||
log.d("udinic", "GetTokenForAccount Bundle is " + bnd);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
showToast(e.getMessage());
|
||||
}
|
||||
}
|
||||
, null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -705,4 +700,9 @@ public class MainActivity extends AppCompatActivity
|
||||
public void onKVVNetworkResponse(NetworkResponse error) {
|
||||
setRefreshFailedBanner(error != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomAccountManager getAccountManager() {
|
||||
return mAccountManager;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -47,12 +46,12 @@ public class LoginFragment extends Fragment {
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout for this fragment
|
||||
View v = inflater.inflate(R.layout.fragment_login, container, false);
|
||||
if (mActivityListener != null && mActivityListener.getKVV().account().isOfflineStoredAvailable()) {
|
||||
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, mActivityListener.getKVV().modules().list().getUsername()));
|
||||
offline_btn.setOnClickListener(v1 -> mActivityListener.getKVV().account().doOfflineLogin());
|
||||
}
|
||||
//if (mActivityListener != null && mActivityListener.getKVV().account().isOfflineStoredAvailable()) {
|
||||
// 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, mActivityListener.getKVV().modules().list().getUsername()));
|
||||
//offline_btn.setOnClickListener(v1 -> mActivityListener.getKVV().account().doOfflineLogin());
|
||||
//}
|
||||
|
||||
View btn_login = v.findViewById(R.id.btn_login);
|
||||
btn_login.setOnClickListener(view -> {
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.android.volley.NetworkResponse;
|
||||
|
||||
import de.sebse.fuplanner.services.GoogleAuth.Credentials;
|
||||
import de.sebse.fuplanner.services.KVV.types.LoginToken;
|
||||
import de.sebse.fuplanner.tools.CustomAccountManager;
|
||||
import de.sebse.fuplanner.tools.network.NetworkCallback;
|
||||
import de.sebse.fuplanner.tools.network.NetworkErrorCallback;
|
||||
|
||||
@@ -17,4 +18,6 @@ public interface KVVListener {
|
||||
void onModuleListChange();
|
||||
|
||||
void onKVVNetworkResponse(NetworkResponse error);
|
||||
|
||||
CustomAccountManager getAccountManager();
|
||||
}
|
||||
|
||||
@@ -2,19 +2,14 @@ package de.sebse.fuplanner.services.KVV;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import de.sebse.fuplanner.services.KVV.types.LoginToken;
|
||||
import de.sebse.fuplanner.services.newkvv.AccountGeneral;
|
||||
import de.sebse.fuplanner.tools.CustomAccountManager;
|
||||
import de.sebse.fuplanner.tools.NetworkCallbackCollector;
|
||||
import de.sebse.fuplanner.tools.network.HTTPService;
|
||||
import de.sebse.fuplanner.tools.network.NetworkCallback;
|
||||
@@ -33,63 +28,41 @@ public class Login extends HTTPService {
|
||||
this.mListener = listener;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
mToken = null;
|
||||
mLoginPending = false;
|
||||
mOnlineMode = false;
|
||||
}
|
||||
|
||||
public void doOnlineLogin(@NotNull String username, @NotNull String password, NetworkCallback<LoginToken> callback, NetworkErrorCallback errorCallback) {
|
||||
if (mLoginPending) {
|
||||
errorCallback.onError(new NetworkError(100160, -1, "Login already pending!"));
|
||||
log.t();
|
||||
|
||||
}
|
||||
|
||||
//public boolean restoreOnlineLogin() {
|
||||
// return restoreLogin(true);
|
||||
//}
|
||||
|
||||
//public boolean doOfflineLogin() {
|
||||
// return restoreLogin(false);
|
||||
//}
|
||||
|
||||
public void restoreOnlineLogin(BooleanInterface callback) {
|
||||
if (mLoginPending || mToken != null) {
|
||||
callback.run(false);
|
||||
return;
|
||||
}
|
||||
mLoginPending = true;
|
||||
doLogin(username, password, token -> {
|
||||
testLoginToken(token, token2 -> {
|
||||
setToken(token2, true);
|
||||
mLoginPending = false;
|
||||
callback.onResponse(token2);
|
||||
}, error -> {
|
||||
mLoginPending = false;
|
||||
errorCallback.onError(error);
|
||||
});
|
||||
}, error -> {
|
||||
LoginToken.load(mListener.getAccountManager(), token -> {
|
||||
boolean result = setToken(token, true);
|
||||
mLoginPending = false;
|
||||
errorCallback.onError(error);
|
||||
callback.run(result);
|
||||
});
|
||||
}
|
||||
|
||||
public boolean restoreOnlineLogin() {
|
||||
return restoreLogin(true);
|
||||
}
|
||||
|
||||
public boolean doOfflineLogin() {
|
||||
return restoreLogin(false);
|
||||
}
|
||||
|
||||
private boolean restoreLogin(boolean enteringOnlineMode) {
|
||||
if (mLoginPending || mToken != null)
|
||||
return false;
|
||||
mLoginPending = true;
|
||||
boolean result = false;
|
||||
try {
|
||||
result = setToken(LoginToken.load(getContext()), enteringOnlineMode);
|
||||
} catch (FileNotFoundException ignored) {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
mLoginPending = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean isOfflineStoredAvailable() {
|
||||
try {
|
||||
LoginToken load = LoginToken.load(getContext());
|
||||
return load != null;
|
||||
} catch (FileNotFoundException ignored) {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
public void isOfflineStoredAvailable(BooleanInterface callback) {
|
||||
LoginToken.load(mListener.getAccountManager(), token -> {
|
||||
callback.run(token != null);
|
||||
});
|
||||
}
|
||||
|
||||
public boolean logout(boolean delete) {
|
||||
@@ -98,7 +71,7 @@ public class Login extends HTTPService {
|
||||
if (mToken == null)
|
||||
return true;
|
||||
if (delete)
|
||||
mToken.delete(getContext());
|
||||
mToken.delete(mListener.getAccountManager());
|
||||
mToken = null;
|
||||
return handleCallbacks();
|
||||
}
|
||||
@@ -155,14 +128,25 @@ public class Login extends HTTPService {
|
||||
mRefreshCallbacks.add(success, error);
|
||||
if (!isFirst)
|
||||
return;
|
||||
mListener.getCredentials(credentials -> {
|
||||
CustomAccountManager manager = mListener.getAccountManager();
|
||||
manager.invalidate(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_KVV);
|
||||
reset();
|
||||
restoreOnlineLogin(isRestored -> {
|
||||
if (isRestored)
|
||||
testLoginToken(mRefreshCallbacks::responseResponse, mRefreshCallbacks::responseError);
|
||||
else {
|
||||
logout(true);
|
||||
mRefreshCallbacks.responseError(new NetworkError(100180, 403, "Re-login failed!"));
|
||||
}
|
||||
});
|
||||
/* mListener.getCredentials(credentials -> {
|
||||
doOnlineLogin(credentials.getUsername(), credentials.getPassword(),
|
||||
mRefreshCallbacks::responseResponse,
|
||||
mRefreshCallbacks::responseError);
|
||||
}, e -> {
|
||||
logout(false);
|
||||
mRefreshCallbacks.responseError(e);
|
||||
});
|
||||
});*/
|
||||
}
|
||||
|
||||
|
||||
@@ -182,272 +166,11 @@ public class Login extends HTTPService {
|
||||
return false;
|
||||
boolean isOnlyRefresh = mToken != null;
|
||||
mToken = token;
|
||||
if (enteringOnlineMode) {
|
||||
try {
|
||||
mToken.save(getContext());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
mOnlineMode = enteringOnlineMode;
|
||||
return isOnlyRefresh || handleCallbacks();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private void doLogin(String username, String password, NetworkCallback<LoginToken> callback, NetworkErrorCallback error) {
|
||||
startKVVSession(success -> {
|
||||
String kvvJSESSIONID = success.get("JSESSIONID");
|
||||
getSAMLRequest(kvvJSESSIONID, success1 -> startIdentSession(success1.get("Location"), success11 -> {
|
||||
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 -> {
|
||||
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 -> {
|
||||
LoginToken token = new LoginToken(username, success111112.get("shibsessionKey"), success111112.get("shibsessionName"), kvvJSESSIONID);
|
||||
finishKVVlogin(token, success11111 -> callback.onResponse(token), error);
|
||||
}, error), error);
|
||||
}, error), error);
|
||||
}, error), error);
|
||||
}, error);
|
||||
}
|
||||
|
||||
/*
|
||||
GET https://kvv.imp.fu-berlin.de/portal/login
|
||||
-> JSESSIONID 5c10406f-588c-4c16-96e9-c80d115417de.tomcat1
|
||||
*/
|
||||
private void startKVVSession(final NetworkCallback<HashMap<String, String>> callback, final NetworkErrorCallback errorCallback) {
|
||||
get("https://kvv.imp.fu-berlin.de/portal/login", null, response -> {
|
||||
String cookies = response.getHeaders().get("Set-Cookie");
|
||||
if (cookies==null) {
|
||||
errorCallback.onError(new NetworkError(100101, -1, "Error on starting KVV session!"));
|
||||
return;
|
||||
}
|
||||
HashMap<String, String> object;
|
||||
try {
|
||||
object = getCookie(cookies, new String[]{"JSESSIONID"});
|
||||
} catch (NoSuchFieldException e) {
|
||||
errorCallback.onError(new NetworkError(100102, -1, "Error on starting KVV session!"));
|
||||
return;
|
||||
}
|
||||
callback.onResponse(object);
|
||||
}, error -> errorCallback.onError(new NetworkError(100100, error.networkResponse.statusCode, "Error on starting KVV session!")));
|
||||
}
|
||||
|
||||
/*
|
||||
GET https://kvv.imp.fu-berlin.de/sakai-login-tool/container
|
||||
<- JSESSIONID
|
||||
-> (Location-Header) https://identity.fu-berlin.de/idp-fub/profile/SAML2/Redirect/SSO
|
||||
?SAMLRequest=fZLLb.....Q8yre3X1IHwkJKE0Mnpy/V9TH4A
|
||||
&RelayState=ss:mem:7ea01e29157b8bd906f7002176.....0d1a505f2c8bf
|
||||
*/
|
||||
private void getSAMLRequest(String JSESSIONID, final NetworkCallback<HashMap<String, String>> callback, final NetworkErrorCallback errorCallback) {
|
||||
HashMap<String, String> cookies = new HashMap<>();
|
||||
cookies.put("JSESSIONID", JSESSIONID);
|
||||
get("https://kvv.imp.fu-berlin.de/sakai-login-tool/container", cookies, response -> {
|
||||
String location = response.getHeaders().get("Location");
|
||||
if (location==null) {
|
||||
errorCallback.onError(new NetworkError(100111, -1, "Error on getting SAML request!"));
|
||||
return;
|
||||
}
|
||||
HashMap<String, String> object = new HashMap<>();
|
||||
object.put("Location", location);
|
||||
callback.onResponse(object);
|
||||
}, error -> errorCallback.onError(new NetworkError(100110, error.networkResponse.statusCode, "Error on getting SAML request!")));
|
||||
}
|
||||
|
||||
/*
|
||||
GET https://identity.fu-berlin.de/idp-fub/profile/SAML2/Redirect/SSO
|
||||
?SAMLRequest=fZLLbsIwEEV/JfI+cWJAUIsgpbAoEi2IpF10UznxUKw6dupxaPn7hkdb2LD29bkzRzNGUeuGZ63fmjV8toA++K61QX58SEnrDLcCFXIjakDuK55njwvOopg3znpbWU2CDBGcV9ZMrcG2BpeD26kKnteLlGy9b5BT+rHbRapuok0bluC0MpEEmm9VWVoNfhshWnpgM7pa5gUJZt0wyogD9h+iJBiv/P6aomQTbtqSdhNtlIYzZg1SOag8zfMlCeazlLyNqpHsy1gO2V1fVsNBMuqJoUyAJaxXDUaiiyG2MDfohfEpYXEyDJM4ZKxgCe/FPI5fSbA6L36vjFTm/bal8hRC/lAUq/C02gs4PK7VBchkfHDNj8Xuwv5trPhVTiY3BeOf4DG96DmVNvypA89nK6tVtQ8yre3X1IHwkJKE0Mnpy/V9TH4A
|
||||
&RelayState=ss:mem:7ea01e29157b8bd906f7002176213b6db5e1f45ebb88716a9820d1a505f2c8bf
|
||||
-> JSESSIONID C4B6A428BA1F50746235D03F5D107A57
|
||||
-> _idp_authn_lc_key 57a6ae26067f374cc3d0ccfc47e27b04b47752d2a3d4eb2782af0d3994535395
|
||||
-> ROUTEID .1
|
||||
*/
|
||||
private void startIdentSession(String url, final NetworkCallback<HashMap<String, String>> callback, final NetworkErrorCallback errorCallback) {
|
||||
get(url, null, response -> {
|
||||
String cookies = response.getHeaders().get("Set-Cookie");
|
||||
if (cookies==null) {
|
||||
errorCallback.onError(new NetworkError(100121, -1, "Error on starting Ident session!"));
|
||||
return;
|
||||
}
|
||||
HashMap<String, String> object;
|
||||
try {
|
||||
object = getCookie(cookies, new String[]{"JSESSIONID", "_idp_authn_lc_key", "ROUTEID"});
|
||||
} catch (NoSuchFieldException e) {
|
||||
errorCallback.onError(new NetworkError(100122, -1, "Error on starting Ident session!"));
|
||||
return;
|
||||
}
|
||||
callback.onResponse(object);
|
||||
}, error -> errorCallback.onError(new NetworkError(100120, error.networkResponse.statusCode, "Error on starting Ident session!")));
|
||||
}
|
||||
|
||||
/*
|
||||
POST https://identity.fu-berlin.de/idp-fub/Authn/UserPassword
|
||||
<- j_username seedorf96
|
||||
<- j_password neinhieristpatrick
|
||||
<- (Header-"Content-Type") application/x-www-form-urlencoded
|
||||
<- JSESSIONID
|
||||
<- _idp_authn_lc_key
|
||||
<- ROUTEID
|
||||
-> _idp_session OTMuMTkzLjg1LjMz|LQ==|OGYxOWI4MjA2NTQ4YWUwYzJkOWM4Mjk4YzcwZDMwZmJiZjBmMTdmMzkyZGU2OWIwY2JkNmZlNjlmNTRmNzBlMQ==|wLlzQal7VqyntmG2vLNn06wt8wQ=
|
||||
*/
|
||||
private void loginIdent(final boolean first, String username, String password, String JSESSIONID, String _idp_authn_lc_key, String ROUTEID, final NetworkCallback<HashMap<String, String>> callback, final NetworkErrorCallback errorCallback) {
|
||||
HashMap<String, String> cookies = new HashMap<>();
|
||||
cookies.put("JSESSIONID", JSESSIONID);
|
||||
cookies.put("_idp_authn_lc_key", _idp_authn_lc_key);
|
||||
cookies.put("ROUTEID", ROUTEID);
|
||||
HashMap<String, String> body = new HashMap<>();
|
||||
body.put("j_username", username);
|
||||
body.put("j_password", password);
|
||||
post("https://identity.fu-berlin.de/idp-fub/Authn/UserPassword", cookies, body, response -> {
|
||||
if (first) {
|
||||
callback.onResponse(new HashMap<>());
|
||||
return;
|
||||
}
|
||||
|
||||
String cookies1 = response.getHeaders().get("Set-Cookie");
|
||||
if (cookies1 ==null) {
|
||||
errorCallback.onError(new NetworkError(100131, -1, "Error on logging in to Identity Server!"));
|
||||
return;
|
||||
}
|
||||
HashMap<String, String> object;
|
||||
try {
|
||||
object = getCookie(cookies1, new String[]{"_idp_session"});
|
||||
} catch (NoSuchFieldException e) {
|
||||
errorCallback.onError(new NetworkError(100132, -1, "Error on logging in to Identity Server!"));
|
||||
return;
|
||||
}
|
||||
callback.onResponse(object);
|
||||
}, error -> errorCallback.onError(new NetworkError(100130, error.networkResponse.statusCode, "Error on logging in to Identity Server!")));
|
||||
}
|
||||
|
||||
/*
|
||||
GET https://identity.fu-berlin.de/idp-fub/profile/SAML2/Redirect/SSO
|
||||
<- JSESSIONID
|
||||
<- _idp_authn_lc_key
|
||||
<- ROUTEID
|
||||
<- _idp_session
|
||||
-> (BODY) RelayState 7ea01e29157b8bd906f7002176213b6db5e1f45ebb88716a9820d1a505f2c8bf
|
||||
-> (BODY) SAMLResponse PD94bWwgdmVyc2lvbj0...........wvc2FtbDJwOlJlc3BvbnNlPg==
|
||||
*/
|
||||
private void getSAMLResponse(String JSESSIONID, String _idp_authn_lc_key, String ROUTEID, String _idp_session, final NetworkCallback<HashMap<String, String>> callback, final NetworkErrorCallback errorCallback) {
|
||||
HashMap<String, String> cookies = new HashMap<>();
|
||||
cookies.put("JSESSIONID", JSESSIONID);
|
||||
cookies.put("_idp_authn_lc_key", _idp_authn_lc_key);
|
||||
cookies.put("ROUTEID", ROUTEID);
|
||||
cookies.put("_idp_session", _idp_session);
|
||||
get("https://identity.fu-berlin.de/idp-fub/profile/SAML2/Redirect/SSO", cookies, response -> {
|
||||
String body = response.getParsed();
|
||||
if (body == null) {
|
||||
errorCallback.onError(new NetworkError(100143, -1, "Error on getting SAML response!"));
|
||||
return;
|
||||
}
|
||||
|
||||
HashMap<String, String> object = new HashMap<>();
|
||||
|
||||
Pattern pattern = Pattern.compile("ss:mem:([0-9a-f]+)");
|
||||
Matcher matcher = pattern.matcher(body);
|
||||
if (!matcher.find()) {
|
||||
errorCallback.onError(new NetworkError(100142, -1, "Error on getting SAML response!"));
|
||||
return;
|
||||
}
|
||||
object.put("RelayState", "ss:mem:"+matcher.group(1));
|
||||
|
||||
pattern = Pattern.compile("name=\"SAMLResponse\" value=\"([0-9a-zA-Z+]+=*)");
|
||||
matcher = pattern.matcher(body);
|
||||
if (!matcher.find()) {
|
||||
errorCallback.onError(new NetworkError(100141, -1, "Error on getting SAML response!"));
|
||||
return;
|
||||
}
|
||||
object.put("SAMLResponse", matcher.group(1));
|
||||
|
||||
callback.onResponse(object);
|
||||
}, error -> errorCallback.onError(new NetworkError(100140, error.networkResponse.statusCode, "Error on getting SAML response!")));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
POST https://kvv.imp.fu-berlin.de/Shibboleth.sso/SAML2/POST
|
||||
<- RelayState 7ea01e29157b8bd906f7002176213b6db5e1f45ebb88716a9820d1a505f2c8bf
|
||||
<- SAMLResponse PD94bWwgdmVyc2lvbj0...........wvc2FtbDJwOlJlc3BvbnNlPg==
|
||||
<- JSESSIONID
|
||||
-> _shibsession_64656661756c7468747470733a2f2f6b76762e696d702e66752d6265726c696e2e64652f73686962626f6c657468
|
||||
_b1912c5a03d733a80bd3fee772bf68d4
|
||||
*/
|
||||
private void loginKVV(String RelayState, String SAMLResponse, String JSESSIONID, final NetworkCallback<HashMap<String, String>> callback, final NetworkErrorCallback errorCallback) {
|
||||
HashMap<String, String> cookies = new HashMap<>();
|
||||
cookies.put("JSESSIONID", JSESSIONID);
|
||||
HashMap<String, String> body = new HashMap<>();
|
||||
body.put("RelayState", RelayState);
|
||||
body.put("SAMLResponse", SAMLResponse);
|
||||
post("https://kvv.imp.fu-berlin.de/Shibboleth.sso/SAML2/POST", cookies, body, response -> {
|
||||
String cookies1 = response.getHeaders().get("Set-Cookie");
|
||||
if (cookies1 ==null) {
|
||||
errorCallback.onError(new NetworkError(100151, -1, "Error on starting KVV session!"));
|
||||
return;
|
||||
}
|
||||
HashMap<String, String> object = new HashMap<>();
|
||||
|
||||
|
||||
Pattern pattern = Pattern.compile("(_shibsession_[0-9a-f]+)=([^;]+);");
|
||||
Matcher matcher = pattern.matcher(cookies1);
|
||||
if (!matcher.find()) {
|
||||
errorCallback.onError(new NetworkError(100152, -1, "Error on starting Ident session!"));
|
||||
}
|
||||
object.put("shibsessionKey", matcher.group(1));
|
||||
object.put("shibsessionName", matcher.group(2));
|
||||
|
||||
callback.onResponse(object);
|
||||
}, error -> errorCallback.onError(new NetworkError(100150, error.networkResponse.statusCode, "Error on starting Ident session!")));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
GET https://kvv.imp.fu-berlin.de/sakai-login-tool/container
|
||||
<- JSESSIONID
|
||||
<- _shibsession_64656661756c7468747470733a2f2f6b76762e696d702e66752d6265726c696e2e64652f73686962626f6c657468
|
||||
_b1912c5a03d733a80bd3fee772bf68d4
|
||||
*/
|
||||
private void finishKVVlogin(LoginToken loginToken, final NetworkCallback<HashMap<String, String>> callback, final NetworkErrorCallback errorCallback) {
|
||||
get("https://kvv.imp.fu-berlin.de/sakai-login-tool/container", loginToken.getCookies(), response -> callback.onResponse(new HashMap<>()), error -> errorCallback.onError(new NetworkError(100160, error.networkResponse.statusCode, "Cannot finish login process!")));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private String getCookie(String cookies, String name) throws NoSuchFieldException {
|
||||
Pattern pattern = Pattern.compile(name+"=([^;]+);");
|
||||
Matcher matcher = pattern.matcher(cookies);
|
||||
if (!matcher.find()) {
|
||||
log.e("GETcookie failed", name);
|
||||
log.e("GETcookie failed", cookies);
|
||||
throw new NoSuchFieldException();
|
||||
}
|
||||
return matcher.group(1);
|
||||
}
|
||||
|
||||
private HashMap<String, String> getCookie(String cookies, String[] names) throws NoSuchFieldException {
|
||||
HashMap<String, String> result = new HashMap<>();
|
||||
for (String name: names) {
|
||||
result.put(name,this.getCookie(cookies, name));
|
||||
}
|
||||
return result;
|
||||
public interface BooleanInterface {
|
||||
void run(boolean bool);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,6 +163,8 @@ public class ModulesList extends HTTPService {
|
||||
try {
|
||||
JSONObject site = sites.getJSONObject(i);
|
||||
String semester_string = site.getJSONObject("props").optString("term_eid", null);
|
||||
if (semester_string == null)
|
||||
continue;
|
||||
Semester semester = new Semester(semester_string);
|
||||
HashSet<String> lvNumbers = new HashSet<>();
|
||||
String kvv_lvnumbers = site.getJSONObject("props").optString("kvv_lvnumbers", null);
|
||||
|
||||
@@ -5,23 +5,22 @@ import android.content.Context;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import de.sebse.fuplanner.services.newkvv.AccountGeneral;
|
||||
import de.sebse.fuplanner.tools.CustomAccountManager;
|
||||
import de.sebse.fuplanner.tools.logging.Logger;
|
||||
|
||||
/**
|
||||
* Created by sebastian on 29.10.17.
|
||||
*/
|
||||
|
||||
public class LoginToken implements Serializable {
|
||||
static Logger log = new Logger("LoginToken");
|
||||
private static final String FILE_NAME = "LoginTokenSaving";
|
||||
|
||||
private final String username;
|
||||
@@ -39,33 +38,35 @@ public class LoginToken implements Serializable {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static LoginToken load(Context context) throws IOException, ClassNotFoundException {
|
||||
FileInputStream fis;
|
||||
try {
|
||||
fis = context.openFileInput(FILE_NAME);
|
||||
} catch (FileNotFoundException e) {
|
||||
return null;
|
||||
public static void load(CustomAccountManager manager, LoginTokenInterface callback) {
|
||||
log.d("try to login");
|
||||
if (!manager.hasAccounts(AccountGeneral.ACCOUNT_TYPE)) {
|
||||
callback.run(null);
|
||||
return;
|
||||
}
|
||||
ObjectInputStream is = new ObjectInputStream(fis);
|
||||
Object readObject = is.readObject();
|
||||
if (!(readObject instanceof LoginToken))
|
||||
return null;
|
||||
LoginToken loginToken = (LoginToken) readObject;
|
||||
is.close();
|
||||
fis.close();
|
||||
return loginToken;
|
||||
log.d("has accounts");
|
||||
manager.getTokenByType(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_KVV, tokenString -> {
|
||||
//manager.getTokenByTypeSync(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_KVV);
|
||||
if (tokenString == null) {
|
||||
callback.run(null);
|
||||
return;
|
||||
}
|
||||
log.d("got token string", tokenString);
|
||||
callback.run(LoginToken.fromJsonString(tokenString));
|
||||
//return LoginToken.fromJsonString(tokenString);
|
||||
});
|
||||
}
|
||||
|
||||
public void save(Context context) throws IOException {
|
||||
FileOutputStream fos = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE);
|
||||
/*FileOutputStream fos = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE);
|
||||
ObjectOutputStream os = new ObjectOutputStream(fos);
|
||||
os.writeObject(this);
|
||||
os.close();
|
||||
fos.close();
|
||||
fos.close();*/
|
||||
}
|
||||
|
||||
public void delete(Context context) {
|
||||
context.deleteFile(FILE_NAME);
|
||||
public void delete(CustomAccountManager manager) {
|
||||
manager.deleteAccount(AccountGeneral.ACCOUNT_TYPE);
|
||||
}
|
||||
|
||||
public void setAdditionals(String fullName, String email) {
|
||||
@@ -156,4 +157,8 @@ public class LoginToken implements Serializable {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public interface LoginTokenInterface {
|
||||
void run(LoginToken token);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
package de.sebse.fuplanner.tools;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.AccountManagerFuture;
|
||||
import android.accounts.AuthenticatorException;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import de.sebse.fuplanner.MainActivity;
|
||||
import de.sebse.fuplanner.tools.logging.Logger;
|
||||
|
||||
public class CustomAccountManager {
|
||||
private final AccountManager mAccountManager;
|
||||
private final ActivityInterface mActivityInterface;
|
||||
private Logger log = new Logger(this);
|
||||
|
||||
public CustomAccountManager(AccountManager manager, ActivityInterface activityInterface) {
|
||||
mAccountManager = manager;
|
||||
this.mActivityInterface = activityInterface;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private void doInvalidateToken(String accountType, String authTokenType) {
|
||||
//String token = mAccountManager.blockingGetAuthToken();
|
||||
Account account = mAccountManager.getAccountsByType(accountType)[0];
|
||||
String token = null;
|
||||
try {
|
||||
token = mAccountManager.blockingGetAuthToken(account, authTokenType, true);
|
||||
//log.d("hihihi", accountType, authTokenType, token);
|
||||
mAccountManager.invalidateAuthToken(accountType, token);
|
||||
} catch (AuthenticatorException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (OperationCanceledException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteAccount(String accountType) {
|
||||
Account[] accounts = mAccountManager.getAccountsByType(accountType);
|
||||
int[] count = {accounts.length};
|
||||
for (Account account: accounts) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
|
||||
mAccountManager.removeAccount(account, null, null, null);
|
||||
} else {
|
||||
mAccountManager.removeAccount(account, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void getTokenForAccountCreateIfNeeded(String accountType, String authTokenType) {
|
||||
MainActivity activity = this.mActivityInterface.get();
|
||||
if (activity != null) {
|
||||
final AccountManagerFuture<Bundle> future = mAccountManager.getAuthTokenByFeatures(accountType, authTokenType, null, activity, null, null,
|
||||
future1 -> {
|
||||
Bundle bnd = null;
|
||||
try {
|
||||
bnd = future1.getResult();
|
||||
final String authtoken = bnd.getString(AccountManager.KEY_AUTHTOKEN);
|
||||
//showToast(((authtoken != null) ? "SUCCESS!\ntoken: " + authtoken : "FAIL"));
|
||||
//log.d("udinic", "GetTokenForAccount Bundle is " + bnd);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
//showToast(e.getMessage());
|
||||
}
|
||||
}
|
||||
, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void getTokenByType(String accountType, String authTokenType, StringInterface callback) {
|
||||
Account account = mAccountManager.getAccountsByType(accountType)[0];
|
||||
mAccountManager.getAuthToken(account, authTokenType, null, true, accountManagerFuture -> {
|
||||
try {
|
||||
Bundle bnd = accountManagerFuture.getResult();
|
||||
final String authtoken = bnd.getString(AccountManager.KEY_AUTHTOKEN);
|
||||
callback.run(authtoken);
|
||||
return;
|
||||
} catch (AuthenticatorException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (OperationCanceledException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
callback.run(null);
|
||||
}, null);
|
||||
}
|
||||
|
||||
public String getTokenByTypeSync(String accountType, String authTokenType) {
|
||||
Account account = mAccountManager.getAccountsByType(accountType)[0];
|
||||
MainActivity activity = this.mActivityInterface.get();
|
||||
if (activity != null) {
|
||||
try {
|
||||
return mAccountManager.blockingGetAuthToken(account, authTokenType, true);
|
||||
} catch (AuthenticatorException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (OperationCanceledException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hasAccounts(String accountType) {
|
||||
return mAccountManager.getAccountsByType(accountType).length != 0;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ActivityInterface {
|
||||
@Nullable
|
||||
MainActivity get();
|
||||
}
|
||||
|
||||
public interface StringInterface {
|
||||
void run(@Nullable String string);
|
||||
}
|
||||
|
||||
public void invalidate(String accountType, String authTokenType) {
|
||||
mAccountManager.invalidateAuthToken(accountType, authTokenType);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user