From fd18e4b61a2a91e52fd472a42556e266f6595d2a Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Tue, 18 Dec 2018 23:54:21 +0100 Subject: [PATCH] Login Finished --- .../java/de/sebse/fuplanner/MainActivity.java | 134 +++---- .../fuplanner/fragments/LoginFragment.java | 13 +- .../fuplanner/services/KVV/KVVListener.java | 3 + .../sebse/fuplanner/services/KVV/Login.java | 369 +++--------------- .../fuplanner/services/KVV/ModulesList.java | 2 + .../services/KVV/types/LoginToken.java | 51 +-- .../fuplanner/tools/CustomAccountManager.java | 134 +++++++ 7 files changed, 286 insertions(+), 420 deletions(-) create mode 100644 app/src/main/java/de/sebse/fuplanner/tools/CustomAccountManager.java diff --git a/app/src/main/java/de/sebse/fuplanner/MainActivity.java b/app/src/main/java/de/sebse/fuplanner/MainActivity.java index b007bb2..503f1d0 100644 --- a/app/src/main/java/de/sebse/fuplanner/MainActivity.java +++ b/app/src/main/java/de/sebse/fuplanner/MainActivity.java @@ -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 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; + } } 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 a481e4f..e3e8c9f 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/LoginFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/LoginFragment.java @@ -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 -> { diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java index 402899f..9747f7f 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java @@ -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(); } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/Login.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/Login.java index 70c2c92..0f364b0 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/Login.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/Login.java @@ -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 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 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> 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 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> callback, final NetworkErrorCallback errorCallback) { - HashMap 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 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> 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 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> callback, final NetworkErrorCallback errorCallback) { - HashMap cookies = new HashMap<>(); - cookies.put("JSESSIONID", JSESSIONID); - cookies.put("_idp_authn_lc_key", _idp_authn_lc_key); - cookies.put("ROUTEID", ROUTEID); - HashMap 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 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> callback, final NetworkErrorCallback errorCallback) { - HashMap 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 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> callback, final NetworkErrorCallback errorCallback) { - HashMap cookies = new HashMap<>(); - cookies.put("JSESSIONID", JSESSIONID); - HashMap 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 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> 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 getCookie(String cookies, String[] names) throws NoSuchFieldException { - HashMap result = new HashMap<>(); - for (String name: names) { - result.put(name,this.getCookie(cookies, name)); - } - return result; + public interface BooleanInterface { + void run(boolean bool); } } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java index 1c224aa..7c1d279 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java @@ -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 lvNumbers = new HashSet<>(); String kvv_lvnumbers = site.getJSONObject("props").optString("kvv_lvnumbers", null); 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 fff6473..544729f 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 @@ -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); + } } diff --git a/app/src/main/java/de/sebse/fuplanner/tools/CustomAccountManager.java b/app/src/main/java/de/sebse/fuplanner/tools/CustomAccountManager.java new file mode 100644 index 0000000..4406081 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/tools/CustomAccountManager.java @@ -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 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); + } +}