Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 87f66adb authored by David Luhmer's avatar David Luhmer
Browse files

Merge branch 'sso'

# Conflicts:
#	.gitignore
#	README.md
#	build.gradle
#	gradle/wrapper/gradle-wrapper.jar
#	gradle/wrapper/gradle-wrapper.properties
#	src/main/java/de/luhmer/owncloud/accountimporter/helper/AccountImporter.java
#	src/main/res/values/strings.xml
parents 39fdb225 70831be8
Loading
Loading
Loading
Loading
+274 KiB
Loading image diff...
+1 −0
Original line number Diff line number Diff line
<mxfile userAgent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36" version="8.6.5" editor="www.draw.io" type="device"><diagram name="Page-1" id="9361dd3d-8414-5efd-6122-117bd74ce7a7">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</diagram></mxfile>
 No newline at end of file
+1 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ group='com.github.nextcloud'

android {
    compileSdkVersion 27
    buildToolsVersion '27.0.3'
    defaultConfig {
        //applicationId 'de.luhmer.owncloud.accountimporter'
        minSdkVersion 14
+22 −0
Original line number Diff line number Diff line
/***
	Copyright (c) 2008-2011 CommonsWare, LLC
	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.

	From _The Busy Coder's Guide to Advanced Android Development_
		http://commonsware.com/AdvAndroid


	More information here: https://github.com/abeluck/android-streams-ipc
*/

package de.luhmer.owncloud.accountimporter.aidl;

interface IInputStreamService {
    ParcelFileDescriptor performNextcloudRequest(in ParcelFileDescriptor input);
}
+172 −0
Original line number Diff line number Diff line
package de.luhmer.owncloud.accountimporter;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.widget.Toast;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import de.luhmer.owncloud.accountimporter.exceptions.NextcloudFilesAppNotInstalledException;
import de.luhmer.owncloud.accountimporter.helper.AsyncTaskHelper;
import de.luhmer.owncloud.accountimporter.model.SingleSignOnAccount;

/**
 *  Nextcloud SingleSignOn
 *
 *  @author David Luhmer
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

public class AccountImporter {

    private static final String TAG = AccountImporter.class.getCanonicalName();
    private static final String PREF_FILE_NAME = "PrefNextcloudAccount";
    private static final String PREF_ACCOUNT_STRING = "PREF_ACCOUNT_STRING";

    private static final String AUTH_TOKEN = "NextcloudSSO";

    public static final int CHOOSE_ACCOUNT_SSO = 4242;

    public static boolean AccountsToImportAvailable(Context context) {
        return FindAccounts(context).size() > 0;
    }


    public static void PickNewAccount(android.support.v4.app.Fragment fragment) throws NextcloudFilesAppNotInstalledException {
        if(AppInstalledOrNot(fragment.getContext(), "com.nextcloud.client")) {
            Intent intent = AccountManager.newChooseAccountIntent(null, null, new String[]{"nextcloud"},
                    true, null, null, null, null);
            fragment.startActivityForResult(intent, CHOOSE_ACCOUNT_SSO);
        } else {
            throw new NextcloudFilesAppNotInstalledException();
        }
    }

    private static boolean AppInstalledOrNot(Context context, String uri) {
        PackageManager pm = context.getPackageManager();
        try {
            pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES);
            return true;
        } catch (PackageManager.NameNotFoundException e) {
        }
        return false;
    }

    // Find all currently installed nextcloud accounts on the phone
    private static List<Account> FindAccounts(Context context) {
        final AccountManager accMgr = AccountManager.get(context);
        final Account[] accounts = accMgr.getAccounts();

        List<Account> accountsAvailable = new ArrayList<>();
        for (Account account : accounts) {
            if (account.type.equals("nextcloud")) {
                accountsAvailable.add(account);
            }
        }
        return accountsAvailable;
    }




    public static Account GetAccountForName(Context context, String name) {
        for (Account account : FindAccounts(context)) {
            if (account.name.equals(name)) {
                return account;
            }
        }
        return null;
    }

    @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)
    public static SingleSignOnAccount BlockingGetAuthToken(final Context context, final Account account) throws Exception {
        SingleSignOnAccount result = AsyncTaskHelper.ExecuteBlockingRequest(new Callable<SingleSignOnAccount>() {
            @Override
            public SingleSignOnAccount call() throws Exception {
                return AccountImporter.GetAuthToken(context, account);
            }
        });
        return result;
    }

    // Get the AuthToken (Password) for a selected account
    public static SingleSignOnAccount GetAuthToken(Context context, Account account) throws AuthenticatorException, OperationCanceledException, IOException {
        final AccountManager accMgr = AccountManager.get(context);
        Bundle options = new Bundle();
        accMgr.invalidateAuthToken(account.type, AUTH_TOKEN);
        //accMgr.getAuthToken(account, AUTH_TOKEN, null, true, new AccountManagerCallback<Bundle>() {


        // Synchronously access auth token
        Bundle future;
        if (context instanceof Activity) {
            future = accMgr.getAuthToken(account, AUTH_TOKEN, options, (Activity) context, null, null).getResult(); // Show activity
        } else {
            future = accMgr.getAuthToken(account, AUTH_TOKEN, options, true, null, null).getResult(); // Show notification instead
        }

        String auth_token = future.getString(AccountManager.KEY_AUTHTOKEN);
        String auth_account_type = future.getString(AccountManager.KEY_ACCOUNT_TYPE);
        accMgr.invalidateAuthToken(auth_account_type, auth_token);

        //String accountName = future.getString(AccountManager.KEY_ACCOUNT_NAME);
        String username = future.getString("username");
        String password = future.getString("password");
        String server_url = future.getString("server_url");
        boolean dhnv = future.getBoolean("disable_hostname_verification");

        return new SingleSignOnAccount(account.name, username, password, server_url, dhnv);
    }


    public static SingleSignOnAccount GetAuthTokenInSeparateThread(final Context context, final Account account) {
        SingleSignOnAccount ssoAccount = null;
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Callable<SingleSignOnAccount> callable = new Callable<SingleSignOnAccount>() {
            @Override
            public SingleSignOnAccount call() throws AuthenticatorException, OperationCanceledException, IOException {
                return AccountImporter.GetAuthToken(context, account);

            }
        };
        Future<SingleSignOnAccount> future = executor.submit(callable);
        try {
            ssoAccount = future.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        executor.shutdown();

        return ssoAccount;
    }
}
Loading