diff --git a/app/src/main/java/com/etesync/syncadapter/ui/AccountActivity.java b/app/src/main/java/com/etesync/syncadapter/ui/AccountActivity.java index 4ccfc867..a9eb0f4d 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/AccountActivity.java +++ b/app/src/main/java/com/etesync/syncadapter/ui/AccountActivity.java @@ -57,6 +57,7 @@ import com.etesync.syncadapter.model.CollectionInfo; import com.etesync.syncadapter.model.JournalEntity; import com.etesync.syncadapter.model.ServiceEntity; import com.etesync.syncadapter.resource.LocalCalendar; +import com.etesync.syncadapter.ui.setup.SetupUserInfoFragment; import com.etesync.syncadapter.utils.HintManager; import com.etesync.syncadapter.utils.ShowcaseBuilder; @@ -113,6 +114,10 @@ public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenu .playOn(tbCardDAV); HintManager.setHintSeen(this, HINT_VIEW_COLLECTION, true); } + + if (!SetupUserInfoFragment.hasUserInfo(this, account)) { + SetupUserInfoFragment.newInstance(account).show(getSupportFragmentManager(), null); + } } @Override diff --git a/app/src/main/java/com/etesync/syncadapter/ui/setup/SetupUserInfoFragment.java b/app/src/main/java/com/etesync/syncadapter/ui/setup/SetupUserInfoFragment.java new file mode 100644 index 00000000..eda1db14 --- /dev/null +++ b/app/src/main/java/com/etesync/syncadapter/ui/setup/SetupUserInfoFragment.java @@ -0,0 +1,142 @@ +package com.etesync.syncadapter.ui.setup; + +import android.accounts.Account; +import android.app.Dialog; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.AsyncTask; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.Fragment; +import android.support.v7.app.AlertDialog; +import android.widget.TextView; + +import com.etesync.syncadapter.AccountSettings; +import com.etesync.syncadapter.App; +import com.etesync.syncadapter.HttpClient; +import com.etesync.syncadapter.InvalidAccountException; +import com.etesync.syncadapter.R; +import com.etesync.syncadapter.journalmanager.Crypto; +import com.etesync.syncadapter.journalmanager.UserInfoManager; + +import lombok.RequiredArgsConstructor; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; + +import static com.etesync.syncadapter.Constants.KEY_ACCOUNT; + +public class SetupUserInfoFragment extends DialogFragment { + private Account account; + private AccountSettings settings; + + public static SetupUserInfoFragment newInstance(Account account) { + SetupUserInfoFragment frag = new SetupUserInfoFragment(); + Bundle args = new Bundle(1); + args.putParcelable(KEY_ACCOUNT, account); + frag.setArguments(args); + return frag; + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + ProgressDialog progress = new ProgressDialog(getActivity()); + progress.setTitle(R.string.login_encryption_setup_title); + progress.setMessage(getString(R.string.login_encryption_setup)); + progress.setIndeterminate(true); + progress.setCanceledOnTouchOutside(false); + setCancelable(false); + return progress; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + account = getArguments().getParcelable(KEY_ACCOUNT); + + try { + settings = new AccountSettings(getContext(), account); + } catch (Exception e) { + e.printStackTrace(); + } + + new SetupUserInfo().execute(account); + } + + public static boolean hasUserInfo(Context context, Account account) { + AccountSettings settings; + try { + settings = new AccountSettings(context, account); + } catch (InvalidAccountException e) { + e.printStackTrace(); + return false; + } + return settings.getKeyPair() != null; + } + + protected class SetupUserInfo extends AsyncTask { + ProgressDialog progressDialog; + + @Override + protected void onPreExecute() { + progressDialog = (ProgressDialog) getDialog(); + } + + @Override + protected SetupUserInfo.SetupUserInfoResult doInBackground(Account... accounts) { + try { + OkHttpClient httpClient = HttpClient.create(getContext(), account); + + Crypto.CryptoManager cryptoManager = new Crypto.CryptoManager(com.etesync.syncadapter.journalmanager.Constants.CURRENT_VERSION, settings.password(), "userInfo"); + UserInfoManager userInfoManager = new UserInfoManager(httpClient, HttpUrl.get(settings.getUri())); + UserInfoManager.UserInfo userInfo = userInfoManager.get(cryptoManager, account.name); + + if (userInfo == null) { + App.log.info("Creating userInfo for " + account.name); + userInfo = UserInfoManager.UserInfo.generate(cryptoManager, account.name); + userInfoManager.create(userInfo); + } else { + App.log.info("Fetched userInfo for " + account.name); + } + + Crypto.AsymmetricKeyPair keyPair = new Crypto.AsymmetricKeyPair(userInfo.getContent(cryptoManager), userInfo.getPubkey()); + + return new SetupUserInfoResult(keyPair, null); + } catch (Exception e) { + e.printStackTrace(); + return new SetupUserInfoResult(null, e); + } + } + + @Override + protected void onPostExecute(SetupUserInfoResult result) { + if (result.exception == null) { + settings.setKeyPair(result.keyPair); + } else { + Dialog dialog = new AlertDialog.Builder(getActivity()) + .setTitle(R.string.login_encryption_error_title) + .setIcon(R.drawable.ic_error_dark) + .setMessage(result.exception.getLocalizedMessage()) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // dismiss + } + }) + .create(); + dialog.show(); + } + + dismissAllowingStateLoss(); + } + + @RequiredArgsConstructor + class SetupUserInfoResult { + final Crypto.AsymmetricKeyPair keyPair; + final Exception exception; + } + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bc2f23b4..737018d7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -140,6 +140,10 @@ Setting up encryption Please wait, setting up encryption… + + Encryption Error + + Import Import Failed