From 797e8489004307370c122fa3a3edbdbc73023d63 Mon Sep 17 00:00:00 2001
From: Joshua <8Joshua@web.de>
Date: Mon, 3 Dec 2018 18:32:06 +0100
Subject: [PATCH 1/6] Login Authenticator Added
---
app/src/main/AndroidManifest.xml | 31 +-
.../java/de/sebse/fuplanner/MainActivity.java | 28 ++
.../services/newkvv/AccountGeneral.java | 7 +
.../services/newkvv/FUAuthenticator.java | 104 ++++++
.../newkvv/FUAuthenticatorActivity.java | 329 ++++++++++++++++++
.../newkvv/FUAuthenticatorService.java | 13 +
.../services/newkvv/UserLoginTask.java | 92 +++++
.../res/layout/activity_fu_authenticator.xml | 78 +++++
app/src/main/res/values/strings.xml | 13 +
app/src/main/res/xml/authenticator.xml | 6 +
10 files changed, 697 insertions(+), 4 deletions(-)
create mode 100644 app/src/main/java/de/sebse/fuplanner/services/newkvv/AccountGeneral.java
create mode 100644 app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticator.java
create mode 100644 app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorActivity.java
create mode 100644 app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorService.java
create mode 100644 app/src/main/java/de/sebse/fuplanner/services/newkvv/UserLoginTask.java
create mode 100644 app/src/main/res/layout/activity_fu_authenticator.xml
create mode 100644 app/src/main/res/xml/authenticator.xml
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2115831..c60a17b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,28 +2,39 @@
+
-
+
+
+
+
+
+ android:theme="@style/FUTheme">
+
+
+ android:resource="@xml/provider_paths" />
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/de/sebse/fuplanner/MainActivity.java b/app/src/main/java/de/sebse/fuplanner/MainActivity.java
index 0a1ce48..f74b149 100644
--- a/app/src/main/java/de/sebse/fuplanner/MainActivity.java
+++ b/app/src/main/java/de/sebse/fuplanner/MainActivity.java
@@ -1,5 +1,8 @@
package de.sebse.fuplanner;
+import android.accounts.AccountManager;
+import android.accounts.AccountManagerCallback;
+import android.accounts.AccountManagerFuture;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
@@ -46,6 +49,7 @@ import de.sebse.fuplanner.services.KVV.KVVListener;
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.MainActivityListener;
import de.sebse.fuplanner.tools.NewAsyncQueue;
import de.sebse.fuplanner.tools.Preferences;
@@ -93,10 +97,12 @@ public class MainActivity extends AppCompatActivity
private boolean mOfflineBanner;
private final NewAsyncQueue mQueue = new NewAsyncQueue();
private long mDoubleBackToExitPressedOnce = 0;
+ private AccountManager mAccountManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ mAccountManager = AccountManager.get(this);
int desiredPage = getDefaultFragmentAfterLogin();
String desiredData = "";
if (savedInstanceState != null) {
@@ -158,6 +164,7 @@ public class MainActivity extends AppCompatActivity
} else {
mDoubleBackToExitPressedOnce = System.currentTimeMillis();
showToast(R.string.back_to_exit);
+ getTokenForAccountCreateIfNeeded(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_KVV);
}
}
}
@@ -552,6 +559,27 @@ public class MainActivity extends AppCompatActivity
});
}
+ private void getTokenForAccountCreateIfNeeded(String accountType, String authTokenType) {
+ final AccountManagerFuture future = mAccountManager.getAuthTokenByFeatures(accountType, authTokenType, null, this, null, null,
+ new AccountManagerCallback() {
+ @Override
+ public void run(AccountManagerFuture future) {
+ Bundle bnd = null;
+ try {
+ bnd = future.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);
+ }
+
diff --git a/app/src/main/java/de/sebse/fuplanner/services/newkvv/AccountGeneral.java b/app/src/main/java/de/sebse/fuplanner/services/newkvv/AccountGeneral.java
new file mode 100644
index 0000000..2d98253
--- /dev/null
+++ b/app/src/main/java/de/sebse/fuplanner/services/newkvv/AccountGeneral.java
@@ -0,0 +1,7 @@
+package de.sebse.fuplanner.services.newkvv;
+
+public class AccountGeneral {
+ public static final String ACCOUNT_TYPE = "de.sebse.fuplanner.fuauth";
+ public static final String AUTHTOKEN_TYPE_KVV = "KVV";
+ public static final String AUTHTOKEN_TYPE_BLACKBOARD = "Blackboard";
+}
diff --git a/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticator.java b/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticator.java
new file mode 100644
index 0000000..cd4ab43
--- /dev/null
+++ b/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticator.java
@@ -0,0 +1,104 @@
+package de.sebse.fuplanner.services.newkvv;
+
+import android.accounts.AbstractAccountAuthenticator;
+import android.accounts.Account;
+import android.accounts.AccountAuthenticatorResponse;
+import android.accounts.AccountManager;
+import android.accounts.NetworkErrorException;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+
+import java.util.concurrent.ExecutionException;
+
+public class FUAuthenticator extends AbstractAccountAuthenticator {
+
+ private final Context mContext;
+
+ public FUAuthenticator(Context context) {
+ super(context);
+ this.mContext = context;
+ }
+
+ @Override
+ public Bundle editProperties(AccountAuthenticatorResponse accountAuthenticatorResponse, String s) {
+ return null;
+ }
+
+ @Override
+ public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options) throws NetworkErrorException {
+ final Intent intent = new Intent(mContext, FUAuthenticatorActivity.class);
+ intent.putExtra(FUAuthenticatorActivity.ARG_ACCOUNT_TYPE, accountType);
+ intent.putExtra(FUAuthenticatorActivity.ARG_AUTH_TYPE, authTokenType);
+ intent.putExtra(FUAuthenticatorActivity.ARG_IS_ADDING_NEW_ACCOUNT, true);
+ intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
+ final Bundle bundle = new Bundle();
+ bundle.putParcelable(AccountManager.KEY_INTENT, intent);
+ return bundle;
+ }
+
+ @Override
+ public Bundle confirmCredentials(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, Bundle bundle) throws NetworkErrorException {
+ return null;
+ }
+
+ @Override
+ public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
+
+ // Extract the username and password from the Account Manager, and ask
+ // the server for an appropriate AuthToken.
+ final AccountManager am = AccountManager.get(mContext);
+
+ String authToken = am.peekAuthToken(account, authTokenType);
+
+ // Lets give another try to authenticate the user
+ if (TextUtils.isEmpty(authToken)) {
+ final String password = am.getPassword(account);
+ if (password != null) {
+ try {
+ authToken = new UserLoginTask(account.name, password, authTokenType, null).execute((Void) null).get();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } catch (ExecutionException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ // If we get an authToken - we return it
+ if (!TextUtils.isEmpty(authToken)) {
+ final Bundle result = new Bundle();
+ result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
+ result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
+ result.putString(AccountManager.KEY_AUTHTOKEN, authToken);
+ return result;
+ }
+
+ // If we get here, then we couldn't access the user's password - so we
+ // need to re-prompt them for their credentials. We do that by creating
+ // an intent to display our AuthenticatorActivity.
+ final Intent intent = new Intent(mContext, FUAuthenticatorActivity.class);
+ intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
+ intent.putExtra(FUAuthenticatorActivity.ARG_ACCOUNT_TYPE, account.type);
+ intent.putExtra(FUAuthenticatorActivity.ARG_AUTH_TYPE, authTokenType);
+ final Bundle bundle = new Bundle();
+ bundle.putParcelable(AccountManager.KEY_INTENT, intent);
+ return bundle;
+ }
+
+ @Override
+ public String getAuthTokenLabel(String s) {
+ return null;
+ }
+
+ @Override
+ public Bundle updateCredentials(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, String s, Bundle bundle) throws NetworkErrorException {
+ return null;
+ }
+
+ @Override
+ public Bundle hasFeatures(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, String[] strings) throws NetworkErrorException {
+ return null;
+ }
+}
diff --git a/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorActivity.java b/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorActivity.java
new file mode 100644
index 0000000..339f03a
--- /dev/null
+++ b/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorActivity.java
@@ -0,0 +1,329 @@
+package de.sebse.fuplanner.services.newkvv;
+
+import android.accounts.Account;
+import android.accounts.AccountAuthenticatorActivity;
+import android.accounts.AccountManager;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.annotation.TargetApi;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+
+import androidx.annotation.NonNull;
+
+import android.app.LoaderManager.LoaderCallbacks;
+
+import android.content.CursorLoader;
+import android.content.Loader;
+import android.database.Cursor;
+import android.net.Uri;
+
+import android.os.Build;
+import android.os.Bundle;
+import android.provider.ContactsContract;
+import android.text.TextUtils;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.inputmethod.EditorInfo;
+import android.widget.ArrayAdapter;
+import android.widget.AutoCompleteTextView;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import de.sebse.fuplanner.R;
+
+import static de.sebse.fuplanner.services.newkvv.UserLoginTask.PARAM_USER_PASS;
+
+/**
+ * A login screen that offers login via email/password.
+ */
+public class FUAuthenticatorActivity extends AccountAuthenticatorActivity implements LoaderCallbacks {
+
+ /**
+ * Id to identity READ_CONTACTS permission request.
+ */
+ private static final int REQUEST_READ_CONTACTS = 0;
+
+ /**
+ * Keep track of the login task to ensure we can cancel it if requested.
+ */
+ UserLoginTask mAuthTask = null;
+
+ // UI references.
+ private AutoCompleteTextView mEmailView;
+ EditText mPasswordView;
+ private View mProgressView;
+ private View mLoginFormView;
+
+
+
+ public static final String ARG_ACCOUNT_TYPE = "ARG_ACCOUNT_TYPE";
+ public static final String ARG_AUTH_TYPE = "ARG_AUTH_TYPE";
+ public static final String ARG_IS_ADDING_NEW_ACCOUNT = "ARG_IS_ADDING_NEW_ACCOUNT";
+ private String mAccountType;
+ private String mAuthTokenType;
+ private boolean mIsAddingNewAccount;
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mAccountType = getIntent().getStringExtra(ARG_ACCOUNT_TYPE);
+ mAuthTokenType = getIntent().getStringExtra(ARG_AUTH_TYPE);
+ mIsAddingNewAccount = getIntent().getBooleanExtra(ARG_IS_ADDING_NEW_ACCOUNT, false);
+
+ setContentView(R.layout.activity_fu_authenticator);
+ // Set up the login form.
+ mEmailView = (AutoCompleteTextView) findViewById(R.id.email);
+ populateAutoComplete();
+
+ mPasswordView = (EditText) findViewById(R.id.password);
+ mPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
+ @Override
+ public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
+ if (id == EditorInfo.IME_ACTION_DONE || id == EditorInfo.IME_NULL) {
+ attemptLogin();
+ return true;
+ }
+ return false;
+ }
+ });
+
+ Button mEmailSignInButton = (Button) findViewById(R.id.email_sign_in_button);
+ mEmailSignInButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ attemptLogin();
+ }
+ });
+
+ mLoginFormView = findViewById(R.id.login_form);
+ mProgressView = findViewById(R.id.login_progress);
+ }
+
+ private void populateAutoComplete() {
+ if (!mayRequestContacts()) {
+ return;
+ }
+
+ getLoaderManager().initLoader(0, null, this);
+ }
+
+ private boolean mayRequestContacts() {
+ /*if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
+ return true;
+ }
+ if (checkSelfPermission(READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
+ return true;
+ }
+ if (shouldShowRequestPermissionRationale(READ_CONTACTS)) {
+ Snackbar.make(mEmailView, R.string.permission_rationale, Snackbar.LENGTH_INDEFINITE)
+ .setAction(android.R.string.ok, new View.OnClickListener() {
+ @Override
+ @TargetApi(Build.VERSION_CODES.M)
+ public void onClick(View v) {
+ requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
+ }
+ });
+ } else {
+ requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
+ }*/
+ return false;
+ }
+
+ /**
+ * Callback received when a permissions request has been completed.
+ */
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
+ @NonNull int[] grantResults) {
+ if (requestCode == REQUEST_READ_CONTACTS) {
+ if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ populateAutoComplete();
+ }
+ }
+ }
+
+
+ /**
+ * Attempts to sign in or register the account specified by the login form.
+ * If there are form errors (invalid email, missing fields, etc.), the
+ * errors are presented and no actual login attempt is made.
+ */
+ private void attemptLogin() {
+ if (mAuthTask != null) {
+ return;
+ }
+
+ // Reset errors.
+ mEmailView.setError(null);
+ mPasswordView.setError(null);
+
+ // Store values at the time of the login attempt.
+ String email = mEmailView.getText().toString();
+ String password = mPasswordView.getText().toString();
+
+ boolean cancel = false;
+ View focusView = null;
+
+ // Check for a valid password, if the user entered one.
+ if (!TextUtils.isEmpty(password) && !isPasswordValid(password)) {
+ mPasswordView.setError(getString(R.string.error_invalid_password));
+ focusView = mPasswordView;
+ cancel = true;
+ }
+
+ // Check for a valid email address.
+ if (TextUtils.isEmpty(email)) {
+ mEmailView.setError(getString(R.string.error_field_required));
+ focusView = mEmailView;
+ cancel = true;
+ } else if (!isEmailValid(email)) {
+ mEmailView.setError(getString(R.string.error_invalid_email));
+ focusView = mEmailView;
+ cancel = true;
+ }
+
+ if (cancel) {
+ // There was an error; don't attempt login and focus the first
+ // form field with an error.
+ focusView.requestFocus();
+ } else {
+ // Show a progress spinner, and kick off a background task to
+ // perform the user login attempt.
+ showProgress(true);
+ mAuthTask = new UserLoginTask(email, password, mAuthTokenType, this);
+ mAuthTask.execute((Void) null);
+ }
+ }
+
+ private boolean isEmailValid(String email) {
+ //TODO: Replace this with your own logic
+ return email.contains("@");
+ }
+
+ private boolean isPasswordValid(String password) {
+ //TODO: Replace this with your own logic
+ return password.length() > 4;
+ }
+
+ /**
+ * Shows the progress UI and hides the login form.
+ */
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
+ void showProgress(final boolean show) {
+ // On Honeycomb MR2 we have the ViewPropertyAnimator APIs, which allow
+ // for very easy animations. If available, use these APIs to fade-in
+ // the progress spinner.
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
+ int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime);
+
+ mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
+ mLoginFormView.animate().setDuration(shortAnimTime).alpha(
+ show ? 0 : 1).setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
+ }
+ });
+
+ mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
+ mProgressView.animate().setDuration(shortAnimTime).alpha(
+ show ? 1 : 0).setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
+ }
+ });
+ } else {
+ // The ViewPropertyAnimator APIs are not available, so simply show
+ // and hide the relevant UI components.
+ mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
+ mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
+ }
+ }
+
+ @Override
+ public Loader onCreateLoader(int i, Bundle bundle) {
+ return new CursorLoader(this,
+ // Retrieve data rows for the device user's 'profile' contact.
+ Uri.withAppendedPath(ContactsContract.Profile.CONTENT_URI,
+ ContactsContract.Contacts.Data.CONTENT_DIRECTORY), ProfileQuery.PROJECTION,
+
+ // Select only email addresses.
+ ContactsContract.Contacts.Data.MIMETYPE +
+ " = ?", new String[]{ContactsContract.CommonDataKinds.Email
+ .CONTENT_ITEM_TYPE},
+
+ // Show primary email addresses first. Note that there won't be
+ // a primary email address if the user hasn't specified one.
+ ContactsContract.Contacts.Data.IS_PRIMARY + " DESC");
+ }
+
+ @Override
+ public void onLoadFinished(Loader cursorLoader, Cursor cursor) {
+ List emails = new ArrayList<>();
+ cursor.moveToFirst();
+ while (!cursor.isAfterLast()) {
+ emails.add(cursor.getString(ProfileQuery.ADDRESS));
+ cursor.moveToNext();
+ }
+
+ addEmailsToAutoComplete(emails);
+ }
+
+ @Override
+ public void onLoaderReset(Loader cursorLoader) {
+
+ }
+
+ private void addEmailsToAutoComplete(List emailAddressCollection) {
+ //Create adapter to tell the AutoCompleteTextView what to show in its dropdown list.
+ ArrayAdapter adapter =
+ new ArrayAdapter<>(FUAuthenticatorActivity.this,
+ android.R.layout.simple_dropdown_item_1line, emailAddressCollection);
+
+ mEmailView.setAdapter(adapter);
+ }
+
+
+ private interface ProfileQuery {
+ String[] PROJECTION = {
+ ContactsContract.CommonDataKinds.Email.ADDRESS,
+ ContactsContract.CommonDataKinds.Email.IS_PRIMARY,
+ };
+
+ int ADDRESS = 0;
+ int IS_PRIMARY = 1;
+ }
+
+ void finishLogin(Intent intent) {
+ String accountName = intent.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
+ String accountPassword = intent.getStringExtra(PARAM_USER_PASS);
+ final Account account = new Account(accountName, intent.getStringExtra(AccountManager.KEY_ACCOUNT_TYPE));
+ final AccountManager mAccountManager = AccountManager.get(this);
+
+ if (getIntent().getBooleanExtra(ARG_IS_ADDING_NEW_ACCOUNT, false)) {
+ String authtoken = intent.getStringExtra(AccountManager.KEY_AUTHTOKEN);
+ String authtokenType = mAuthTokenType;
+
+ // Creating the account on the device and setting the auth token we got
+ // (Not setting the auth token will cause another call to the server to authenticate the user)
+ mAccountManager.addAccountExplicitly(account, accountPassword, null);
+ mAccountManager.setAuthToken(account, authtokenType, authtoken);
+ } else {
+ mAccountManager.setPassword(account, accountPassword);
+ }
+
+ setAccountAuthenticatorResult(intent.getExtras());
+ setResult(RESULT_OK, intent);
+ finish();
+ }
+}
+
diff --git a/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorService.java b/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorService.java
new file mode 100644
index 0000000..a6f1516
--- /dev/null
+++ b/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorService.java
@@ -0,0 +1,13 @@
+package de.sebse.fuplanner.services.newkvv;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+public class FUAuthenticatorService extends Service {
+ @Override
+ public IBinder onBind(Intent intent) {
+ FUAuthenticator authenticator = new FUAuthenticator(this);
+ return authenticator.getIBinder();
+ }
+}
diff --git a/app/src/main/java/de/sebse/fuplanner/services/newkvv/UserLoginTask.java b/app/src/main/java/de/sebse/fuplanner/services/newkvv/UserLoginTask.java
new file mode 100644
index 0000000..8aa3c65
--- /dev/null
+++ b/app/src/main/java/de/sebse/fuplanner/services/newkvv/UserLoginTask.java
@@ -0,0 +1,92 @@
+package de.sebse.fuplanner.services.newkvv;
+
+import android.accounts.AccountManager;
+import android.annotation.SuppressLint;
+import android.content.Intent;
+import android.os.AsyncTask;
+import android.os.Build;
+
+import androidx.annotation.Nullable;
+import de.sebse.fuplanner.R;
+
+
+/**
+ * Represents an asynchronous login/registration task used to authenticate
+ * the user.
+ */
+public class UserLoginTask extends AsyncTask {
+
+ /**
+ * A dummy authentication store containing known user names and passwords.
+ * TODO: remove after connecting to a real authentication system.
+ */
+ private static final String[] DUMMY_CREDENTIALS = new String[]{
+ "foo@example.com:hello", "bar@example.com:world"
+ };
+ static final String PARAM_USER_PASS = "PARAM_USER_PASS";
+
+ private final String mEmail;
+ private final String mPassword;
+ private String mTokenType;
+ @SuppressLint("StaticFieldLeak")
+ @Nullable
+ private FUAuthenticatorActivity mActivity;
+
+ UserLoginTask(String email, String password, String tokenType, @Nullable FUAuthenticatorActivity activity) {
+ mEmail = email;
+ mPassword = password;
+ mTokenType = tokenType;
+ mActivity = activity;
+ }
+
+ @Override
+ protected String doInBackground(Void... params) {
+ // TODO: attempt authentication against a network service.
+
+ try {
+ // Simulate network access.
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ return null;
+ }
+
+ for (String credential : DUMMY_CREDENTIALS) {
+ String[] pieces = credential.split(":");
+ if (pieces[0].equals(mEmail)) {
+ // Account exists, return true if the password matches.
+ return pieces[1].equals(mPassword) ? "auth token here" : null;
+ }
+ }
+
+ // TODO: register the new account here.
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(final String success) {
+ if (mActivity == null || mActivity.isFinishing())
+ return;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && mActivity.isDestroyed())
+ return;
+ mActivity.mAuthTask = null;
+ mActivity.showProgress(false);
+
+ if (success != null) {
+ final Intent res = new Intent();
+ res.putExtra(AccountManager.KEY_ACCOUNT_NAME, mEmail);
+ res.putExtra(AccountManager.KEY_ACCOUNT_TYPE, AccountGeneral.ACCOUNT_TYPE);
+ res.putExtra(AccountManager.KEY_AUTHTOKEN, success);
+ res.putExtra(PARAM_USER_PASS, mPassword);
+ mActivity.finishLogin(res);
+ } else {
+ mActivity.mPasswordView.setError(mActivity.getString(R.string.error_incorrect_password));
+ mActivity.mPasswordView.requestFocus();
+ }
+ }
+
+ @Override
+ protected void onCancelled() {
+ mActivity.mAuthTask = null;
+ mActivity.showProgress(false);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_fu_authenticator.xml b/app/src/main/res/layout/activity_fu_authenticator.xml
new file mode 100644
index 0000000..3e432df
--- /dev/null
+++ b/app/src/main/res/layout/activity_fu_authenticator.xml
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 9d5d76d..f750d1e 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -90,4 +90,17 @@
Update News
Tips/Tricks
Please click BACK again to exit!
+ Sign in
+
+ Email
+ Password (optional)
+ Sign in or register
+ Sign in
+ This email address is invalid
+ This password is too short
+ This password is incorrect
+ This field is required
+ "Contacts permissions are needed for providing email
+ completions."
+
diff --git a/app/src/main/res/xml/authenticator.xml b/app/src/main/res/xml/authenticator.xml
new file mode 100644
index 0000000..1d552a4
--- /dev/null
+++ b/app/src/main/res/xml/authenticator.xml
@@ -0,0 +1,6 @@
+
+
From c807dda73c1cc508f286bdedf2e7c9deb9e19e37 Mon Sep 17 00:00:00 2001
From: Caesar2011
Date: Thu, 6 Dec 2018 13:32:39 +0100
Subject: [PATCH 2/6] Activity Active Bugfix
---
.../de/sebse/fuplanner/services/newkvv/UserLoginTask.java | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/app/src/main/java/de/sebse/fuplanner/services/newkvv/UserLoginTask.java b/app/src/main/java/de/sebse/fuplanner/services/newkvv/UserLoginTask.java
index 8aa3c65..02d5721 100644
--- a/app/src/main/java/de/sebse/fuplanner/services/newkvv/UserLoginTask.java
+++ b/app/src/main/java/de/sebse/fuplanner/services/newkvv/UserLoginTask.java
@@ -86,6 +86,10 @@ public class UserLoginTask extends AsyncTask {
@Override
protected void onCancelled() {
+ if (mActivity == null || mActivity.isFinishing())
+ return;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && mActivity.isDestroyed())
+ return;
mActivity.mAuthTask = null;
mActivity.showProgress(false);
}
From cde5fc3582cb31d859e0d0317fe5b771cac5011f Mon Sep 17 00:00:00 2001
From: Caesar2011
Date: Mon, 17 Dec 2018 16:14:50 +0100
Subject: [PATCH 3/6] Login Testing
---
app/src/main/AndroidManifest.xml | 3 +
.../java/de/sebse/fuplanner/MainActivity.java | 63 +++-
.../services/KVV/types/LoginToken.java | 38 +++
.../services/newkvv/FUAuthenticator.java | 2 +-
.../newkvv/FUAuthenticatorActivity.java | 12 +-
.../services/newkvv/UserLoginTask.java | 46 ++-
.../services/newkvv/network/Login.java | 297 ++++++++++++++++++
.../fuplanner/tools/network/HTTPService.java | 2 +-
8 files changed, 428 insertions(+), 35 deletions(-)
create mode 100644 app/src/main/java/de/sebse/fuplanner/services/newkvv/network/Login.java
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c60a17b..ca1fede 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -9,6 +9,9 @@
+
diff --git a/app/src/main/java/de/sebse/fuplanner/MainActivity.java b/app/src/main/java/de/sebse/fuplanner/MainActivity.java
index f74b149..b007bb2 100644
--- a/app/src/main/java/de/sebse/fuplanner/MainActivity.java
+++ b/app/src/main/java/de/sebse/fuplanner/MainActivity.java
@@ -1,9 +1,12 @@
package de.sebse.fuplanner;
+import android.accounts.Account;
import android.accounts.AccountManager;
-import android.accounts.AccountManagerCallback;
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;
@@ -16,6 +19,7 @@ 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;
@@ -559,22 +563,49 @@ public class MainActivity extends AppCompatActivity
});
}
- private void getTokenForAccountCreateIfNeeded(String accountType, String authTokenType) {
- final AccountManagerFuture future = mAccountManager.getAuthTokenByFeatures(accountType, authTokenType, null, this, null, null,
- new AccountManagerCallback() {
- @Override
- public void run(AccountManagerFuture future) {
- Bundle bnd = null;
- try {
- bnd = future.getResult();
- final String authtoken = bnd.getString(AccountManager.KEY_AUTHTOKEN);
- showToast(((authtoken != null) ? "SUCCESS!\ntoken: " + authtoken : "FAIL"));
- log.d("udinic", "GetTokenForAccount Bundle is " + bnd);
+ 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();
+ }
+ }
- } catch (Exception e) {
- e.printStackTrace();
- showToast(e.getMessage());
- }
+ 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);
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 0657069..fff6473 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
@@ -2,6 +2,9 @@ package de.sebse.fuplanner.services.KVV.types;
import android.content.Context;
+import org.json.JSONException;
+import org.json.JSONObject;
+
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@@ -118,4 +121,39 @@ public class LoginToken implements Serializable {
}
return result.substring(0, result.length()-1);
}
+
+ public String toJsonString() {
+ JSONObject json = new JSONObject();
+ try {
+ json.put("username", username);
+ json.put("shibsessionKey", shibsessionKey);
+ json.put("shibsessionName", shibsessionName);
+ json.put("JSESSIONID", JSESSIONID);
+ json.put("fullName", fullName);
+ json.put("email", email);
+ } catch (JSONException e) {
+ return null;
+ }
+ return json.toString();
+ }
+
+ public static LoginToken fromJsonString(String tokenString) {
+ try {
+ JSONObject json = new JSONObject(tokenString);
+ LoginToken token = new LoginToken(
+ json.getString("username"),
+ json.getString("shibsessionName"),
+ json.getString("shibsessionName"),
+ json.getString("JSESSIONID"));
+ if (!json.isNull("fullName"))
+ token.setAdditionals(
+ json.getString("fullName"),
+ json.getString("email")
+ );
+ return token;
+ } catch (JSONException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
}
diff --git a/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticator.java b/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticator.java
index cd4ab43..6dfba9c 100644
--- a/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticator.java
+++ b/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticator.java
@@ -57,7 +57,7 @@ public class FUAuthenticator extends AbstractAccountAuthenticator {
final String password = am.getPassword(account);
if (password != null) {
try {
- authToken = new UserLoginTask(account.name, password, authTokenType, null).execute((Void) null).get();
+ authToken = new UserLoginTask(account.name, password, authTokenType, mContext).execute((Void) null).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
diff --git a/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorActivity.java b/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorActivity.java
index 339f03a..39855e0 100644
--- a/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorActivity.java
+++ b/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorActivity.java
@@ -6,18 +6,13 @@ import android.accounts.AccountManager;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.TargetApi;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-
-import androidx.annotation.NonNull;
-
import android.app.LoaderManager.LoaderCallbacks;
-
import android.content.CursorLoader;
+import android.content.Intent;
import android.content.Loader;
+import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
-
import android.os.Build;
import android.os.Bundle;
import android.provider.ContactsContract;
@@ -35,6 +30,7 @@ import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
+import androidx.annotation.NonNull;
import de.sebse.fuplanner.R;
import static de.sebse.fuplanner.services.newkvv.UserLoginTask.PARAM_USER_PASS;
@@ -205,7 +201,7 @@ public class FUAuthenticatorActivity extends AccountAuthenticatorActivity implem
private boolean isEmailValid(String email) {
//TODO: Replace this with your own logic
- return email.contains("@");
+ return true;//email.contains("@");
}
private boolean isPasswordValid(String password) {
diff --git a/app/src/main/java/de/sebse/fuplanner/services/newkvv/UserLoginTask.java b/app/src/main/java/de/sebse/fuplanner/services/newkvv/UserLoginTask.java
index 02d5721..3338106 100644
--- a/app/src/main/java/de/sebse/fuplanner/services/newkvv/UserLoginTask.java
+++ b/app/src/main/java/de/sebse/fuplanner/services/newkvv/UserLoginTask.java
@@ -2,12 +2,21 @@ package de.sebse.fuplanner.services.newkvv;
import android.accounts.AccountManager;
import android.annotation.SuppressLint;
+import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Build;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicReference;
+
import androidx.annotation.Nullable;
import de.sebse.fuplanner.R;
+import de.sebse.fuplanner.services.KVV.types.LoginToken;
+import de.sebse.fuplanner.services.newkvv.network.Login;
+import de.sebse.fuplanner.tools.logging.Logger;
/**
@@ -20,37 +29,56 @@ public class UserLoginTask extends AsyncTask {
* A dummy authentication store containing known user names and passwords.
* TODO: remove after connecting to a real authentication system.
*/
- private static final String[] DUMMY_CREDENTIALS = new String[]{
+ /*private static final String[] DUMMY_CREDENTIALS = new String[]{
"foo@example.com:hello", "bar@example.com:world"
- };
+ };*/
static final String PARAM_USER_PASS = "PARAM_USER_PASS";
private final String mEmail;
private final String mPassword;
+ private final Login mVolleyLogin;
private String mTokenType;
+ private Logger log = new Logger(this);
@SuppressLint("StaticFieldLeak")
@Nullable
private FUAuthenticatorActivity mActivity;
- UserLoginTask(String email, String password, String tokenType, @Nullable FUAuthenticatorActivity activity) {
+ UserLoginTask(String email, String password, String tokenType, @NotNull Context context) {
mEmail = email;
mPassword = password;
mTokenType = tokenType;
- mActivity = activity;
+ mVolleyLogin = new Login(context);
+ if (context instanceof FUAuthenticatorActivity)
+ mActivity = (FUAuthenticatorActivity) context;
}
@Override
protected String doInBackground(Void... params) {
// TODO: attempt authentication against a network service.
+ CountDownLatch latch = new CountDownLatch(1);
+ AtomicReference login = new AtomicReference<>();
+ mVolleyLogin.doLogin(mEmail, mPassword, success -> {
+ mVolleyLogin.testLoginToken(success, success1 -> {
+ login.set(success);
+ latch.countDown();
+ }, error -> latch.countDown());
+ }, error -> latch.countDown());
try {
- // Simulate network access.
- Thread.sleep(2000);
+ latch.await();
} catch (InterruptedException e) {
- return null;
+ e.printStackTrace();
}
- for (String credential : DUMMY_CREDENTIALS) {
+ log.d(login.get());
+
+ if (login.get() == null) {
+ return null;
+ } else {
+ return login.get().toJsonString();
+ }
+
+ /*for (String credential : DUMMY_CREDENTIALS) {
String[] pieces = credential.split(":");
if (pieces[0].equals(mEmail)) {
// Account exists, return true if the password matches.
@@ -59,7 +87,7 @@ public class UserLoginTask extends AsyncTask {
}
// TODO: register the new account here.
- return null;
+ return null;*/
}
@Override
diff --git a/app/src/main/java/de/sebse/fuplanner/services/newkvv/network/Login.java b/app/src/main/java/de/sebse/fuplanner/services/newkvv/network/Login.java
new file mode 100644
index 0000000..5c67b22
--- /dev/null
+++ b/app/src/main/java/de/sebse/fuplanner/services/newkvv/network/Login.java
@@ -0,0 +1,297 @@
+package de.sebse.fuplanner.services.newkvv.network;
+
+import android.content.Context;
+
+import org.jetbrains.annotations.NotNull;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.HashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import de.sebse.fuplanner.services.KVV.types.LoginToken;
+import de.sebse.fuplanner.tools.network.HTTPService;
+import de.sebse.fuplanner.tools.network.NetworkCallback;
+import de.sebse.fuplanner.tools.network.NetworkError;
+import de.sebse.fuplanner.tools.network.NetworkErrorCallback;
+
+public class Login extends HTTPService {
+ public Login(Context context) {
+ super(context);
+ }
+
+
+ public void testLoginToken(@NotNull LoginToken token, @NotNull NetworkCallback callback, @NotNull NetworkErrorCallback errorCallback) {
+ get(String.format("https://kvv.imp.fu-berlin.de/direct/profile/%s.json", token.getUsername()), token.getCookies(), response -> {
+ String body = response.getParsed();
+ if (body == null) {
+ errorCallback.onError(new NetworkError(100172, 403, "Testing login failed!"));
+ return;
+ }
+ try {
+ JSONObject json = new JSONObject(body);
+ String displayName = json.getString("displayName");
+ String email = json.getString("email");
+ token.setAdditionals(displayName, email);
+ callback.onResponse(token);
+ } catch (JSONException e) {
+ errorCallback.onError(new NetworkError(100171, 403, "Cannot parse profile!"));
+ }
+ }, error -> errorCallback.onError(new NetworkError(100170, error.networkResponse.statusCode, "Testing login failed!")));
+ }
+
+
+
+
+
+
+ public 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;
+ }
+}
diff --git a/app/src/main/java/de/sebse/fuplanner/tools/network/HTTPService.java b/app/src/main/java/de/sebse/fuplanner/tools/network/HTTPService.java
index 3ae5cd5..f035efc 100644
--- a/app/src/main/java/de/sebse/fuplanner/tools/network/HTTPService.java
+++ b/app/src/main/java/de/sebse/fuplanner/tools/network/HTTPService.java
@@ -31,7 +31,7 @@ public class HTTPService {
private final EventListener errorResponseListener = new EventListener<>();
private final EventListener successResponseListener = new EventListener<>();
- protected HTTPService(Context context) {
+ public HTTPService(Context context) {
this.mContext = context;
requestQueue = Volley.newRequestQueue(context, new BetterHurlStack(false));
}
From fd18e4b61a2a91e52fd472a42556e266f6595d2a Mon Sep 17 00:00:00 2001
From: Caesar2011
Date: Tue, 18 Dec 2018 23:54:21 +0100
Subject: [PATCH 4/6] 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);
+ }
+}
From 4d226136720538621fa3150f63251cf17acc32bb Mon Sep 17 00:00:00 2001
From: Caesar2011
Date: Wed, 19 Dec 2018 01:08:39 +0100
Subject: [PATCH 5/6] Login Improved; Still Bug when re-login
---
.../java/de/sebse/fuplanner/MainActivity.java | 8 +-
.../fuplanner/fragments/LoginFragment.java | 111 ------------------
.../sebse/fuplanner/services/KVV/Login.java | 22 ++--
.../newkvv/FUAuthenticatorActivity.java | 94 +++++----------
.../fuplanner/tools/CustomAccountManager.java | 64 +++++-----
.../res/layout/activity_fu_authenticator.xml | 107 ++++++++++-------
app/src/main/res/layout/fragment_login.xml | 2 +-
7 files changed, 137 insertions(+), 271 deletions(-)
delete mode 100644 app/src/main/java/de/sebse/fuplanner/fragments/LoginFragment.java
diff --git a/app/src/main/java/de/sebse/fuplanner/MainActivity.java b/app/src/main/java/de/sebse/fuplanner/MainActivity.java
index 503f1d0..abc59d2 100644
--- a/app/src/main/java/de/sebse/fuplanner/MainActivity.java
+++ b/app/src/main/java/de/sebse/fuplanner/MainActivity.java
@@ -69,8 +69,6 @@ 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;
private static final int FRAGMENT_CANTEENS_DETAILS = 6;
@@ -129,7 +127,7 @@ public class MainActivity extends AppCompatActivity
if (!mAccountManager.hasAccounts(AccountGeneral.ACCOUNT_TYPE)) {
desiredPage = getDefaultFragmentAfterLogout();
desiredData = "";
- mAccountManager.getTokenForAccountCreateIfNeeded(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_KVV);
+ mAccountManager.getTokenByType(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_KVV, null);
updateNavigation();
changeFragment(desiredPage, desiredData);
} else {
@@ -367,7 +365,7 @@ public class MainActivity extends AppCompatActivity
setRefreshFailedBanner(false);
updateNavigation();
changeFragment(getDefaultFragmentAfterLogout());
- mAccountManager.getTokenForAccountCreateIfNeeded(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_KVV);
+ mAccountManager.getTokenByType(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_KVV, null);
}
private void toLoginState(String fullName, String email, int newFragment, boolean onlineMode) {
@@ -526,7 +524,7 @@ public class MainActivity extends AppCompatActivity
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
}
- mAccountManager.getTokenForAccountCreateIfNeeded(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_KVV);
+ mAccountManager.getTokenByType(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_KVV, null);
});
}
diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/LoginFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/LoginFragment.java
deleted file mode 100644
index e3e8c9f..0000000
--- a/app/src/main/java/de/sebse/fuplanner/fragments/LoginFragment.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package de.sebse.fuplanner.fragments;
-
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.EditText;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
-import de.sebse.fuplanner.R;
-import de.sebse.fuplanner.tools.MainActivityListener;
-import de.sebse.fuplanner.tools.logging.Logger;
-
-/**
- * A simple {@link Fragment} subclass.
- * Use the {@link LoginFragment#newInstance} factory method to
- * create an instance of this fragment.
- */
-public class LoginFragment extends Fragment {
- private final Logger log = new Logger(this);
- @Nullable private MainActivityListener mActivityListener;
-
- public LoginFragment() {
- // Required empty public constructor
- }
-
- /**
- * Use this factory method to create a new instance of
- * this fragment using the provided parameters.
- *
- * @return A new instance of fragment LoginFragment.
- */
- public static LoginFragment newInstance() {
- LoginFragment fragment = new LoginFragment();
- Bundle args = new Bundle();
- fragment.setArguments(args);
- return fragment;
- }
-
- @Override
- public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
- 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());
- //}
-
- View btn_login = v.findViewById(R.id.btn_login);
- btn_login.setOnClickListener(view -> {
- final ProgressDialog progressDialog = new ProgressDialog(LoginFragment.this.getContext(),
- R.style.FUTheme_Dialog);
- progressDialog.setIndeterminate(true);
- progressDialog.setMessage("Authenticating...");
- progressDialog.show();
-
- EditText input_usr = ((View) view.getParent()).findViewById(R.id.input_username);
- EditText input_pwd = ((View) view.getParent()).findViewById(R.id.input_password);
-
- String username = input_usr.getText().toString();
- String password = input_pwd.getText().toString();
-
- mActivityListener.getKVV().account().doOnlineLogin(username, password, success -> {
- progressDialog.dismiss();
- mActivityListener.getGoogleAuth().setLoginState(username, password);
- input_usr.setError(null);
- input_pwd.setError(null);
- }, error -> {
- progressDialog.dismiss();
- // Invalid password
- if (mActivityListener != null) {
- if (error.getCode() == 100131) {
- mActivityListener.showToast(R.string.invalid_credentials);
- input_usr.setError(input_usr.getResources().getString(R.string.invalid_credentials));
- input_pwd.setError(input_pwd.getResources().getString(R.string.invalid_credentials));
- } else {
- mActivityListener.showToast(v.getResources().getString(R.string.error_occurred_code, error.getCode()));
- }
- }
- log.e("Error on KVV login!", error);
- });
- });
-
- return v;
- }
-
-
-
- @Override
- public void onAttach(Context context) {
- super.onAttach(context);
- if (context instanceof MainActivityListener) {
- mActivityListener = (MainActivityListener) context;
- mActivityListener.onTitleTextChange(R.string.log_in);
- } else
- throw new RuntimeException(context.toString() + " must implement MainActivityListener");
- }
-
- @Override
- public void onDetach() {
- super.onDetach();
- mActivityListener = null;
- }
-}
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 0f364b0..84c8908 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
@@ -55,6 +55,7 @@ public class Login extends HTTPService {
LoginToken.load(mListener.getAccountManager(), token -> {
boolean result = setToken(token, true);
mLoginPending = false;
+ log.d("loginToken", token != null ? token.toString() : null);
callback.run(result);
});
}
@@ -129,15 +130,18 @@ public class Login extends HTTPService {
if (!isFirst)
return;
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!"));
- }
+ manager.doInvalidateToken(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_KVV, ignored -> {
+ reset();
+ log.d("try restore", ignored);
+ restoreOnlineLogin(isRestored -> {
+ log.d("restore", isRestored, mToken);
+ 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(),
diff --git a/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorActivity.java b/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorActivity.java
index 39855e0..5d4ef13 100644
--- a/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorActivity.java
+++ b/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorActivity.java
@@ -17,18 +17,10 @@ import android.os.Build;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.text.TextUtils;
-import android.view.KeyEvent;
import android.view.View;
-import android.view.View.OnClickListener;
import android.view.inputmethod.EditorInfo;
-import android.widget.ArrayAdapter;
-import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.EditText;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-import java.util.List;
import androidx.annotation.NonNull;
import de.sebse.fuplanner.R;
@@ -51,7 +43,7 @@ public class FUAuthenticatorActivity extends AccountAuthenticatorActivity implem
UserLoginTask mAuthTask = null;
// UI references.
- private AutoCompleteTextView mEmailView;
+ private EditText mEmailView;
EditText mPasswordView;
private View mProgressView;
private View mLoginFormView;
@@ -76,28 +68,20 @@ public class FUAuthenticatorActivity extends AccountAuthenticatorActivity implem
setContentView(R.layout.activity_fu_authenticator);
// Set up the login form.
- mEmailView = (AutoCompleteTextView) findViewById(R.id.email);
+ mEmailView = findViewById(R.id.input_username);
populateAutoComplete();
- mPasswordView = (EditText) findViewById(R.id.password);
- mPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
- @Override
- public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
- if (id == EditorInfo.IME_ACTION_DONE || id == EditorInfo.IME_NULL) {
- attemptLogin();
- return true;
- }
- return false;
+ mPasswordView = findViewById(R.id.input_password);
+ mPasswordView.setOnEditorActionListener((textView, id, keyEvent) -> {
+ if (id == EditorInfo.IME_ACTION_DONE || id == EditorInfo.IME_NULL) {
+ attemptLogin();
+ return true;
}
+ return false;
});
- Button mEmailSignInButton = (Button) findViewById(R.id.email_sign_in_button);
- mEmailSignInButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View view) {
- attemptLogin();
- }
- });
+ Button mEmailSignInButton = findViewById(R.id.btn_login);
+ mEmailSignInButton.setOnClickListener(view -> attemptLogin());
mLoginFormView = findViewById(R.id.login_form);
mProgressView = findViewById(R.id.login_progress);
@@ -217,32 +201,25 @@ public class FUAuthenticatorActivity extends AccountAuthenticatorActivity implem
// On Honeycomb MR2 we have the ViewPropertyAnimator APIs, which allow
// for very easy animations. If available, use these APIs to fade-in
// the progress spinner.
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
- int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime);
+ int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime);
- mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
- mLoginFormView.animate().setDuration(shortAnimTime).alpha(
- show ? 0 : 1).setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
- }
- });
+ mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
+ mLoginFormView.animate().setDuration(shortAnimTime).alpha(
+ show ? 0 : 1).setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
+ }
+ });
- mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
- mProgressView.animate().setDuration(shortAnimTime).alpha(
- show ? 1 : 0).setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
- }
- });
- } else {
- // The ViewPropertyAnimator APIs are not available, so simply show
- // and hide the relevant UI components.
- mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
- mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
- }
+ mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
+ mProgressView.animate().setDuration(shortAnimTime).alpha(
+ show ? 1 : 0).setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
+ }
+ });
}
@Override
@@ -264,14 +241,6 @@ public class FUAuthenticatorActivity extends AccountAuthenticatorActivity implem
@Override
public void onLoadFinished(Loader cursorLoader, Cursor cursor) {
- List emails = new ArrayList<>();
- cursor.moveToFirst();
- while (!cursor.isAfterLast()) {
- emails.add(cursor.getString(ProfileQuery.ADDRESS));
- cursor.moveToNext();
- }
-
- addEmailsToAutoComplete(emails);
}
@Override
@@ -279,15 +248,6 @@ public class FUAuthenticatorActivity extends AccountAuthenticatorActivity implem
}
- private void addEmailsToAutoComplete(List emailAddressCollection) {
- //Create adapter to tell the AutoCompleteTextView what to show in its dropdown list.
- ArrayAdapter adapter =
- new ArrayAdapter<>(FUAuthenticatorActivity.this,
- android.R.layout.simple_dropdown_item_1line, emailAddressCollection);
-
- mEmailView.setAdapter(adapter);
- }
-
private interface ProfileQuery {
String[] PROJECTION = {
diff --git a/app/src/main/java/de/sebse/fuplanner/tools/CustomAccountManager.java b/app/src/main/java/de/sebse/fuplanner/tools/CustomAccountManager.java
index 4406081..02f9d2f 100644
--- a/app/src/main/java/de/sebse/fuplanner/tools/CustomAccountManager.java
+++ b/app/src/main/java/de/sebse/fuplanner/tools/CustomAccountManager.java
@@ -2,7 +2,6 @@ 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;
@@ -12,6 +11,7 @@ import java.io.IOException;
import androidx.annotation.Nullable;
import de.sebse.fuplanner.MainActivity;
+import de.sebse.fuplanner.services.KVV.Login;
import de.sebse.fuplanner.tools.logging.Logger;
public class CustomAccountManager {
@@ -28,13 +28,10 @@ public class CustomAccountManager {
- private void doInvalidateToken(String accountType, String authTokenType) {
- //String token = mAccountManager.blockingGetAuthToken();
+ public void doInvalidateTokenSync(String accountType, String authTokenType) {
Account account = mAccountManager.getAccountsByType(accountType)[0];
- String token = null;
try {
- token = mAccountManager.blockingGetAuthToken(account, authTokenType, true);
- //log.d("hihihi", accountType, authTokenType, token);
+ String token = mAccountManager.blockingGetAuthToken(account, authTokenType, true);
mAccountManager.invalidateAuthToken(accountType, token);
} catch (AuthenticatorException e) {
e.printStackTrace();
@@ -45,6 +42,28 @@ public class CustomAccountManager {
}
}
+ public void doInvalidateToken(String accountType, String authTokenType, Login.BooleanInterface callback) {
+ Account account = mAccountManager.getAccountsByType(accountType)[0];
+ mAccountManager.getAuthToken(account, authTokenType, null, true, accountManagerFuture -> {
+ try {
+ Bundle bnd = accountManagerFuture.getResult();
+ String token = bnd.getString(AccountManager.KEY_AUTHTOKEN);
+ mAccountManager.invalidateAuthToken(accountType, token);
+ if (callback != null)
+ callback.run(true);
+ return;
+ } catch (AuthenticatorException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (OperationCanceledException e) {
+ e.printStackTrace();
+ }
+ if (callback != null)
+ callback.run(false);
+ }, null);
+ }
+
public void deleteAccount(String accountType) {
Account[] accounts = mAccountManager.getAccountsByType(accountType);
int[] count = {accounts.length};
@@ -57,34 +76,14 @@ public class CustomAccountManager {
}
}
- 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) {
+ public void getTokenByType(String accountType, String authTokenType, @Nullable 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);
+ if (callback != null)
+ callback.run(authtoken);
return;
} catch (AuthenticatorException e) {
e.printStackTrace();
@@ -93,7 +92,8 @@ public class CustomAccountManager {
} catch (OperationCanceledException e) {
e.printStackTrace();
}
- callback.run(null);
+ if (callback != null)
+ callback.run(null);
}, null);
}
@@ -127,8 +127,4 @@ public class CustomAccountManager {
public interface StringInterface {
void run(@Nullable String string);
}
-
- public void invalidate(String accountType, String authTokenType) {
- mAccountManager.invalidateAuthToken(accountType, authTokenType);
- }
}
diff --git a/app/src/main/res/layout/activity_fu_authenticator.xml b/app/src/main/res/layout/activity_fu_authenticator.xml
index 3e432df..6cae445 100644
--- a/app/src/main/res/layout/activity_fu_authenticator.xml
+++ b/app/src/main/res/layout/activity_fu_authenticator.xml
@@ -19,60 +19,79 @@
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:visibility="gone" />
-
+ android:layout_height="match_parent"
+ android:fitsSystemWindows="true"
+ android:id="@+id/login_form"
+ tools:context="de.sebse.fuplanner.services.newkvv.FUAuthenticatorActivity">
+ android:paddingTop="56dp"
+ android:paddingLeft="24dp"
+ android:paddingRight="24dp">
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="8dp">
+
+
+
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
+
+
+
diff --git a/app/src/main/res/layout/fragment_login.xml b/app/src/main/res/layout/fragment_login.xml
index ab9f3ee..93ae522 100644
--- a/app/src/main/res/layout/fragment_login.xml
+++ b/app/src/main/res/layout/fragment_login.xml
@@ -3,7 +3,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
- tools:context="de.sebse.fuplanner.fragments.LoginFragment">
+ tools:context="de.sebse.fuplanner.services.newkvv.FUAuthenticatorActivity">
Date: Wed, 19 Dec 2018 15:46:12 +0100
Subject: [PATCH 6/6] Login Bugs removed
---
app/src/main/java/de/sebse/fuplanner/MainActivity.java | 7 ++++---
.../main/java/de/sebse/fuplanner/services/KVV/Login.java | 4 ++--
.../fuplanner/services/newkvv/FUAuthenticatorActivity.java | 5 +++++
.../de/sebse/fuplanner/tools/CustomAccountManager.java | 4 ++--
4 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/app/src/main/java/de/sebse/fuplanner/MainActivity.java b/app/src/main/java/de/sebse/fuplanner/MainActivity.java
index abc59d2..21043a4 100644
--- a/app/src/main/java/de/sebse/fuplanner/MainActivity.java
+++ b/app/src/main/java/de/sebse/fuplanner/MainActivity.java
@@ -158,14 +158,15 @@ public class MainActivity extends AppCompatActivity
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());
+ else if (!isRestored && isLoggedInBeforePause) {
+ getKVV().account().logout(false);
+ changeFragment(getDefaultFragmentAfterLogout());
+ }
});
}
isPaused = false;
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 84c8908..ca47f2e 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
@@ -28,6 +28,7 @@ public class Login extends HTTPService {
this.mListener = listener;
}
+ @Deprecated
public void reset() {
mToken = null;
mLoginPending = false;
@@ -47,7 +48,7 @@ public class Login extends HTTPService {
//}
public void restoreOnlineLogin(BooleanInterface callback) {
- if (mLoginPending || mToken != null) {
+ if (mLoginPending) {
callback.run(false);
return;
}
@@ -131,7 +132,6 @@ public class Login extends HTTPService {
return;
CustomAccountManager manager = mListener.getAccountManager();
manager.doInvalidateToken(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_KVV, ignored -> {
- reset();
log.d("try restore", ignored);
restoreOnlineLogin(isRestored -> {
log.d("restore", isRestored, mToken);
diff --git a/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorActivity.java b/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorActivity.java
index 5d4ef13..03ee6cd 100644
--- a/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorActivity.java
+++ b/app/src/main/java/de/sebse/fuplanner/services/newkvv/FUAuthenticatorActivity.java
@@ -7,6 +7,7 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.TargetApi;
import android.app.LoaderManager.LoaderCallbacks;
+import android.content.Context;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
@@ -19,6 +20,7 @@ import android.provider.ContactsContract;
import android.text.TextUtils;
import android.view.View;
import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
@@ -137,6 +139,9 @@ public class FUAuthenticatorActivity extends AccountAuthenticatorActivity implem
* errors are presented and no actual login attempt is made.
*/
private void attemptLogin() {
+ InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
+ if (inputManager != null && getCurrentFocus() != null)
+ inputManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
if (mAuthTask != null) {
return;
}
diff --git a/app/src/main/java/de/sebse/fuplanner/tools/CustomAccountManager.java b/app/src/main/java/de/sebse/fuplanner/tools/CustomAccountManager.java
index 02f9d2f..25d13d9 100644
--- a/app/src/main/java/de/sebse/fuplanner/tools/CustomAccountManager.java
+++ b/app/src/main/java/de/sebse/fuplanner/tools/CustomAccountManager.java
@@ -77,8 +77,8 @@ public class CustomAccountManager {
}
public void getTokenByType(String accountType, String authTokenType, @Nullable StringInterface callback) {
- Account account = mAccountManager.getAccountsByType(accountType)[0];
- mAccountManager.getAuthToken(account, authTokenType, null, true, accountManagerFuture -> {
+ //Account account = mAccountManager.getAccountsByType(accountType)[0];
+ mAccountManager.getAuthTokenByFeatures(accountType, authTokenType, null, mActivityInterface.get(), null, null, accountManagerFuture -> {
try {
Bundle bnd = accountManagerFuture.getResult();
final String authtoken = bnd.getString(AccountManager.KEY_AUTHTOKEN);