Added TestAuthActivity to do some experimentation with auth tokens in the
authorkenstir <kenstir@gmail.com>
Fri, 13 Nov 2015 00:02:49 +0000 (19:02 -0500)
committerkenstir <kenstir@gmail.com>
Fri, 13 Nov 2015 00:02:49 +0000 (19:02 -0500)
generic app.

This activity came from https://github.com/Udinic/AccountAuthenticator

Open-ILS/src/Android/core/res/layout/test_auth.xml [new file with mode: 0644]
Open-ILS/src/Android/core/src/org/evergreen_ils/auth/TestAuthActivity.java [new file with mode: 0644]
Open-ILS/src/Android/cwmars_app/AndroidManifest.xml

diff --git a/Open-ILS/src/Android/core/res/layout/test_auth.xml b/Open-ILS/src/Android/core/res/layout/test_auth.xml
new file mode 100644 (file)
index 0000000..69a78c2
--- /dev/null
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:padding="17dp"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent">
+
+    <Button android:id="@+id/btnAddAccount"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:padding="10dp"
+            android:text="addAccount"/>
+
+    <Button android:id="@+id/btnGetAuthToken"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:padding="10dp"
+            android:text="getAuthToken"/>
+
+    <Button android:id="@+id/btnGetAuthTokenByFeatures"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:padding="10dp"
+            android:text="getAuthTokenByFeatures"/>
+
+    <Button android:id="@+id/btnInvalidateAuthToken"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:padding="10dp"
+            android:text="invalidateAuthToken"/>
+
+    <TextView
+        android:id="@+id/txtLastAccountName"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical|center"
+        android:text="TextView" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/auth/TestAuthActivity.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/auth/TestAuthActivity.java
new file mode 100644 (file)
index 0000000..70326fc
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+Copyright 2013 Udi Cohen
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+ */
+package org.evergreen_ils.auth;
+
+import org.evergreen_ils.R;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AccountManagerCallback;
+import android.accounts.AccountManagerFuture;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.os.Build;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.ContextThemeWrapper;
+import android.view.View;
+import android.widget.TextView;
+import android.widget.Toast;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Udini
+ * Date: 21/03/13
+ * Time: 13:50
+ */
+public class TestAuthActivity extends Activity {
+       
+       private static final String STATE_DIALOG = "state_dialog";
+       private static final String STATE_INVALIDATE = "state_invalidate";
+    private static final String TAG = TestAuthActivity.class.getSimpleName();
+
+    private AccountManager mAccountManager;
+    private String mAccountType;
+    private AlertDialog mAlertDialog;
+    private boolean mInvalidate;
+    private TextView mLastTextView;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.test_auth);
+        mAccountManager = AccountManager.get(this);
+        mAccountType = getString(org.evergreen_ils.R.string.ou_account_type);
+
+        findViewById(R.id.btnAddAccount).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                addNewAccount(mAccountType,  Const.AUTHTOKEN_TYPE);
+            }
+        });
+
+        findViewById(R.id.btnGetAuthToken).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                showAccountPicker(Const.AUTHTOKEN_TYPE, false);
+            }
+        });
+
+        findViewById(R.id.btnGetAuthTokenByFeatures).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                getTokenForAccountCreateIfNeeded(mAccountType, Const.AUTHTOKEN_TYPE);
+            }
+        });
+        findViewById(R.id.btnInvalidateAuthToken).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                showAccountPicker(Const.AUTHTOKEN_TYPE, true);
+            }
+        });
+        
+        mLastTextView = (TextView)findViewById(R.id.txtLastAccountName);
+
+        if (savedInstanceState != null) {
+               boolean showDialog = savedInstanceState.getBoolean(STATE_DIALOG);
+               boolean invalidate = savedInstanceState.getBoolean(STATE_INVALIDATE);
+               if (showDialog) {
+                       showAccountPicker(Const.AUTHTOKEN_TYPE, invalidate);
+               }
+        }
+    }
+    
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+       super.onSaveInstanceState(outState);
+       if (mAlertDialog != null && mAlertDialog.isShowing()) {
+               outState.putBoolean(STATE_DIALOG, true);
+               outState.putBoolean(STATE_INVALIDATE, mInvalidate);
+       }
+    }
+
+    /**
+     * Add new account to the account manager
+     * @param accountType
+     * @param authTokenType
+     */
+    private void addNewAccount(String accountType, String authTokenType) {
+        //final AccountManagerFuture<Bundle> future = 
+        mAccountManager.addAccount(accountType, authTokenType, null, null, this, new AccountManagerCallback<Bundle>() {
+            @Override
+            public void run(AccountManagerFuture<Bundle> future) {
+                try {
+                    Bundle bnd = future.getResult();
+                    final String account_name = bnd.getString(AccountManager.KEY_ACCOUNT_NAME);
+                    showMessage("Account "+account_name+" was created");
+                    mLastTextView.setText(account_name);
+                    Log.d(TAG, "AddNewAccount Bundle is " + bnd);
+
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    showMessage(e.getMessage());
+                }
+            }
+        }, null);
+    }
+
+    /**
+     * Show all the accounts registered on the account manager. Request an auth token upon user select.
+     * @param authTokenType
+     */
+    private void showAccountPicker(final String authTokenType, final boolean invalidate) {
+       mInvalidate = invalidate;
+        final Account availableAccounts[] = mAccountManager.getAccountsByType(mAccountType);
+
+        if (availableAccounts.length == 0) {
+            Toast.makeText(this, "No accounts", Toast.LENGTH_SHORT).show();
+            addNewAccount(mAccountType, Const.AUTHTOKEN_TYPE);
+        } else {
+            String name[] = new String[availableAccounts.length];
+            for (int i = 0; i < availableAccounts.length; i++) {
+                name[i] = availableAccounts[i].name;
+            }
+
+            // Account picker
+            AlertDialog.Builder builder;
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+                builder = new AlertDialog.Builder(this);
+            } else {
+                // Without this hack, Gingerbread shows white-on-white text
+                ContextThemeWrapper wrapper = new ContextThemeWrapper(this, R.style.Theme_Base_AppCompat_Light);
+                builder = new AlertDialog.Builder(wrapper);
+            }
+            mAlertDialog = builder.setTitle("Pick Account").setItems(name, new DialogInterface.OnClickListener() {
+                @Override
+                public void onClick(DialogInterface dialog, int which) {
+                    if(invalidate)
+                        invalidateAuthToken(availableAccounts[which], authTokenType);
+                    else
+                        getExistingAccountAuthToken(availableAccounts[which], authTokenType);
+                }
+            }).create();
+
+            mAlertDialog.show();
+        }
+    }
+
+    /**
+     * Get the auth token for an existing account on the AccountManager
+     * @param account
+     * @param authTokenType
+     */
+    private void getExistingAccountAuthToken(final Account account, String authTokenType) {
+        final AccountManagerFuture<Bundle> future = mAccountManager.getAuthToken(account, authTokenType, null, this, null, null);
+
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    Bundle bnd = future.getResult();
+
+                    final String authtoken = bnd.getString(AccountManager.KEY_AUTHTOKEN);
+                    final String account_name = bnd.getString(AccountManager.KEY_ACCOUNT_NAME);
+                    Log.d("kcxxx","getExistingAccountAuthToken account.name "+account.name+" account_name "+account_name+" token "+authtoken);
+                    showMessage((authtoken != null) ? "SUCCESS with "+account_name+"\ntoken: " + authtoken : "FAIL");
+                    Log.d(TAG, "GetToken Bundle is " + bnd);
+                    mLastTextView.setText(account.name);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    showMessage(e.getMessage());
+                }
+            }
+        }).start();
+    }
+
+    private void reuseExistingAccountAuthToken(final String account_name, String authTokenType) {
+        final Account availableAccounts[] = mAccountManager.getAccountsByType(mAccountType);
+        final Account account = null;
+        for (int i = 0; i < availableAccounts.length; i++) {
+            if (account_name.equals(availableAccounts[i].name)) {
+                Toast.makeText(this, "Reusing last account "+account_name, Toast.LENGTH_SHORT);
+                getExistingAccountAuthToken(availableAccounts[i], authTokenType);
+            }
+        }
+    }
+    
+    /**
+     * Invalidates the auth token for the account
+     * @param account
+     * @param authTokenType
+     */
+    private void invalidateAuthToken(final Account account, String authTokenType) {
+        final AccountManagerFuture<Bundle> future = mAccountManager.getAuthToken(account, authTokenType, null, this, null,null);
+
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    Bundle bnd = future.getResult();
+
+                    final String authtoken = bnd.getString(AccountManager.KEY_AUTHTOKEN);
+                    mAccountManager.invalidateAuthToken(account.type, authtoken);
+                    showMessage(account.name + " invalidated");
+                    mLastTextView.setText("no account");
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    showMessage(e.getMessage());
+                }
+            }
+        }).start();
+    }
+
+    /**
+     * Get an auth token for the account.
+     * If not exist - add it and then return its auth token.
+     * If one exist - return its auth token.
+     * If more than one exists - show a picker and return the select account's auth token.
+     * @param accountType
+     * @param authTokenType
+     */
+    private void getTokenForAccountCreateIfNeeded(String accountType, String authTokenType) {
+        final AccountManagerFuture<Bundle> future = mAccountManager.getAuthTokenByFeatures(accountType, authTokenType, null, this, null, null,
+                new AccountManagerCallback<Bundle>() {
+                    @Override
+                    public void run(AccountManagerFuture<Bundle> future) {
+                        Bundle bnd = null;
+                        try {
+                            bnd = future.getResult();
+                            final String authtoken = bnd.getString(AccountManager.KEY_AUTHTOKEN);
+                            final String account_name = bnd.getString(AccountManager.KEY_ACCOUNT_NAME);
+                            showMessage((authtoken != null) ? "SUCCESS with "+account_name+"\ntoken: " + authtoken : "FAIL");
+                            Log.d(TAG, "GetTokenForAccount Bundle is " + bnd);
+                            mLastTextView.setText(account_name);
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                            showMessage(e.getMessage());
+                        }
+                    }
+                }
+        , null);
+    }
+
+    private void showMessage(final String msg) {
+       if (TextUtils.isEmpty(msg))
+            return;
+
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();
+                mLastTextView.setText(msg);
+            }
+        });
+    }
+}
index 4b615f4..d332b8b 100644 (file)
         <activity android:name="org.evergreen_ils.accountAccess.bookbags.BookBagDetails" >
         </activity>
 
+        <activity android:name="org.evergreen_ils.views.MainActivity">
+        </activity>
+
+        <activity android:name="org.evergreen_ils.auth.TestAuthActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+            </intent-filter>
+        </activity>
+
         <activity
             android:name="org.evergreen_ils.auth.AuthenticatorActivity"
             android:label="@string/ou_account_label">
         </activity>
 
-        <activity android:name="org.evergreen_ils.views.MainActivity">
-        </activity>
-
         <service
             android:name="org.evergreen_ils.auth.AuthenticatorService"
             android:exported="false" >