Allow updating OAuth accounts

pull/190/head
M66B 5 years ago
parent 687795e3d4
commit ad439fd392

@ -92,6 +92,11 @@ public interface DaoAccount {
@Query("SELECT * FROM account WHERE name = :name") @Query("SELECT * FROM account WHERE name = :name")
EntityAccount getAccount(String name); EntityAccount getAccount(String name);
@Query("SELECT * FROM account" +
" WHERE user = :user" +
" AND auth_type = :auth_type")
EntityAccount getAccount(String user, int auth_type);
@Query("SELECT * FROM account WHERE `primary`") @Query("SELECT * FROM account WHERE `primary`")
EntityAccount getPrimaryAccount(); EntityAccount getPrimaryAccount();

@ -104,6 +104,12 @@ public interface DaoIdentity {
" AND host LIKE :domain") " AND host LIKE :domain")
int setIdentityPassword(long account, String user, String password, String domain); int setIdentityPassword(long account, String user, String password, String domain);
@Query("UPDATE identity SET password = :password" +
" WHERE account = :account" +
" AND user = :user" +
" AND auth_type = :auth_type")
int setIdentityPassword(long account, String user, String password, int auth_type);
@Query("UPDATE identity SET last_connected = :last_connected WHERE id = :id") @Query("UPDATE identity SET last_connected = :last_connected WHERE id = :id")
int setIdentityConnected(long id, long last_connected); int setIdentityConnected(long id, long last_connected);

@ -19,7 +19,6 @@ package eu.faircode.email;
Copyright 2018-2020 by Marcel Bokhorst (M66B) Copyright 2018-2020 by Marcel Bokhorst (M66B)
*/ */
import android.accounts.Account;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -27,7 +26,6 @@ import android.graphics.Color;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.provider.Settings;
import android.text.Editable; import android.text.Editable;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.TextWatcher; import android.text.TextWatcher;
@ -45,7 +43,6 @@ import android.widget.Button;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.CompoundButton; import android.widget.CompoundButton;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.RadioGroup; import android.widget.RadioGroup;
import android.widget.ScrollView; import android.widget.ScrollView;
import android.widget.Spinner; import android.widget.Spinner;
@ -64,7 +61,6 @@ import com.sun.mail.imap.protocol.IMAPProtocol;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -72,12 +68,9 @@ import java.util.Objects;
import javax.mail.Folder; import javax.mail.Folder;
import static android.accounts.AccountManager.newChooseAccountIntent;
import static android.app.Activity.RESULT_OK; import static android.app.Activity.RESULT_OK;
import static com.google.android.material.textfield.TextInputLayout.END_ICON_NONE; import static com.google.android.material.textfield.TextInputLayout.END_ICON_NONE;
import static com.google.android.material.textfield.TextInputLayout.END_ICON_PASSWORD_TOGGLE; import static com.google.android.material.textfield.TextInputLayout.END_ICON_PASSWORD_TOGGLE;
import static eu.faircode.email.GmailState.TYPE_GOOGLE;
import static eu.faircode.email.ServiceAuthenticator.AUTH_TYPE_GMAIL;
import static eu.faircode.email.ServiceAuthenticator.AUTH_TYPE_OAUTH; import static eu.faircode.email.ServiceAuthenticator.AUTH_TYPE_OAUTH;
import static eu.faircode.email.ServiceAuthenticator.AUTH_TYPE_PASSWORD; import static eu.faircode.email.ServiceAuthenticator.AUTH_TYPE_PASSWORD;
@ -96,7 +89,6 @@ public class FragmentAccount extends FragmentBase {
private RadioGroup rgEncryption; private RadioGroup rgEncryption;
private CheckBox cbInsecure; private CheckBox cbInsecure;
private EditText etPort; private EditText etPort;
private ImageButton ibAccount;
private EditText etUser; private EditText etUser;
private TextInputLayout tilPassword; private TextInputLayout tilPassword;
private TextView tvCharacters; private TextView tvCharacters;
@ -166,8 +158,7 @@ public class FragmentAccount extends FragmentBase {
private static final int REQUEST_COLOR = 1; private static final int REQUEST_COLOR = 1;
private static final int REQUEST_SAVE = 2; private static final int REQUEST_SAVE = 2;
private static final int REQUEST_ACCOUNT = 3; private static final int REQUEST_DELETE = 3;
private static final int REQUEST_DELETE = 4;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
@ -202,7 +193,6 @@ public class FragmentAccount extends FragmentBase {
etPort = view.findViewById(R.id.etPort); etPort = view.findViewById(R.id.etPort);
rgEncryption = view.findViewById(R.id.rgEncryption); rgEncryption = view.findViewById(R.id.rgEncryption);
cbInsecure = view.findViewById(R.id.cbInsecure); cbInsecure = view.findViewById(R.id.cbInsecure);
ibAccount = view.findViewById(R.id.ibAccount);
etUser = view.findViewById(R.id.etUser); etUser = view.findViewById(R.id.etUser);
tilPassword = view.findViewById(R.id.tilPassword); tilPassword = view.findViewById(R.id.tilPassword);
tvCharacters = view.findViewById(R.id.tvCharacters); tvCharacters = view.findViewById(R.id.tvCharacters);
@ -326,24 +316,6 @@ public class FragmentAccount extends FragmentBase {
} }
}); });
ibAccount.setEnabled(id >= 0 && auth == AUTH_TYPE_GMAIL);
ibAccount.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Account account = new Account(etUser.getText().toString(), TYPE_GOOGLE);
Intent intent = newChooseAccountIntent(
account,
new ArrayList(Arrays.asList(account)),
new String[]{TYPE_GOOGLE},
false,
null,
null,
null,
null);
startActivityForResult(intent, REQUEST_ACCOUNT);
}
});
tilPassword.getEditText().addTextChangedListener(new TextWatcher() { tilPassword.getEditText().addTextChangedListener(new TextWatcher() {
@Override @Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void beforeTextChanged(CharSequence s, int start, int count, int after) {
@ -1523,7 +1495,6 @@ public class FragmentAccount extends FragmentBase {
tilPassword.setEnabled(false); tilPassword.setEnabled(false);
btnCertificate.setEnabled(false); btnCertificate.setEnabled(false);
} }
ibAccount.setEnabled(auth == AUTH_TYPE_GMAIL);
cbOnDemand.setEnabled(cbSynchronize.isChecked()); cbOnDemand.setEnabled(cbSynchronize.isChecked());
cbPrimary.setEnabled(cbSynchronize.isChecked()); cbPrimary.setEnabled(cbSynchronize.isChecked());
@ -1640,10 +1611,6 @@ public class FragmentAccount extends FragmentBase {
} else if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) } else if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
getParentFragmentManager().popBackStack(); getParentFragmentManager().popBackStack();
break; break;
case REQUEST_ACCOUNT:
if (resultCode == RESULT_OK)
onAccount();
break;
case REQUEST_DELETE: case REQUEST_DELETE:
if (resultCode == RESULT_OK) if (resultCode == RESULT_OK)
onDelete(); onDelete();
@ -1654,13 +1621,6 @@ public class FragmentAccount extends FragmentBase {
} }
} }
private void onAccount() {
Intent sync = new Intent(Settings.ACTION_SYNC_SETTINGS)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (sync.resolveActivity(getContext().getPackageManager()) != null)
startActivity(sync);
}
private void onDelete() { private void onDelete() {
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putLong("id", id); args.putLong("id", id);

@ -396,72 +396,80 @@ public class FragmentGmail extends FragmentBase {
try { try {
db.beginTransaction(); db.beginTransaction();
EntityAccount primary = db.account().getPrimaryAccount(); EntityAccount update = db.account().getAccount(user, AUTH_TYPE_GMAIL);
if (update == null) {
// Create account EntityAccount primary = db.account().getPrimaryAccount();
EntityAccount account = new EntityAccount();
// Create account
account.host = provider.imap.host; EntityAccount account = new EntityAccount();
account.encryption = aencryption;
account.port = provider.imap.port; account.host = provider.imap.host;
account.auth_type = AUTH_TYPE_GMAIL; account.encryption = aencryption;
account.user = user; account.port = provider.imap.port;
account.password = password; account.auth_type = AUTH_TYPE_GMAIL;
account.user = user;
account.name = provider.name + "/" + username; account.password = password;
account.synchronize = true; account.name = provider.name + "/" + username;
account.primary = (primary == null);
account.synchronize = true;
account.created = new Date().getTime(); account.primary = (primary == null);
account.last_connected = account.created;
account.created = new Date().getTime();
account.id = db.account().insertAccount(account); account.last_connected = account.created;
args.putLong("account", account.id);
EntityLog.log(context, "Gmail account=" + account.name); account.id = db.account().insertAccount(account);
args.putLong("account", account.id);
// Create folders EntityLog.log(context, "Gmail account=" + account.name);
for (EntityFolder folder : folders) {
EntityFolder existing = db.folder().getFolderByName(account.id, folder.name); // Create folders
if (existing == null) { for (EntityFolder folder : folders) {
folder.account = account.id; EntityFolder existing = db.folder().getFolderByName(account.id, folder.name);
folder.id = db.folder().insertFolder(folder); if (existing == null) {
EntityLog.log(context, "Gmail folder=" + folder.name + " type=" + folder.type); folder.account = account.id;
if (folder.synchronize) folder.id = db.folder().insertFolder(folder);
EntityOperation.sync(context, folder.id, false); EntityLog.log(context, "Gmail folder=" + folder.name + " type=" + folder.type);
if (folder.synchronize)
EntityOperation.sync(context, folder.id, false);
}
} }
}
// Set swipe left/right folder
for (EntityFolder folder : folders)
if (EntityFolder.TRASH.equals(folder.type))
account.swipe_left = folder.id;
else if (EntityFolder.ARCHIVE.equals(folder.type))
account.swipe_right = folder.id;
db.account().updateAccount(account); // Set swipe left/right folder
for (EntityFolder folder : folders)
if (TextUtils.isEmpty(name)) if (EntityFolder.TRASH.equals(folder.type))
name = user.split("@")[0]; account.swipe_left = folder.id;
else if (EntityFolder.ARCHIVE.equals(folder.type))
// Create identity account.swipe_right = folder.id;
EntityIdentity identity = new EntityIdentity();
identity.name = name; db.account().updateAccount(account);
identity.email = user;
identity.account = account.id; if (TextUtils.isEmpty(name))
name = user.split("@")[0];
identity.host = provider.smtp.host;
identity.encryption = iencryption; // Create identity
identity.port = provider.smtp.port; EntityIdentity identity = new EntityIdentity();
identity.auth_type = AUTH_TYPE_GMAIL; identity.name = name;
identity.user = user; identity.email = user;
identity.password = password; identity.account = account.id;
identity.synchronize = true;
identity.primary = true; identity.host = provider.smtp.host;
identity.max_size = max_size; identity.encryption = iencryption;
identity.port = provider.smtp.port;
identity.id = db.identity().insertIdentity(identity); identity.auth_type = AUTH_TYPE_GMAIL;
EntityLog.log(context, "Gmail identity=" + identity.name + " email=" + identity.email); identity.user = user;
identity.password = password;
identity.synchronize = true;
identity.primary = true;
identity.max_size = max_size;
identity.id = db.identity().insertIdentity(identity);
EntityLog.log(context, "Gmail identity=" + identity.name + " email=" + identity.email);
} else {
args.putLong("account", update.id);
EntityLog.log(context, "Gmail update account=" + update.name);
db.account().setAccountPassword(update.id, password);
db.identity().setIdentityPassword(update.id, update.user, password, update.auth_type);
}
db.setTransactionSuccessful(); db.setTransactionSuccessful();
} finally { } finally {

@ -511,80 +511,88 @@ public class FragmentOAuth extends FragmentBase {
try { try {
db.beginTransaction(); db.beginTransaction();
EntityAccount primary = db.account().getPrimaryAccount(); EntityAccount update = db.account().getAccount(username, AUTH_TYPE_OAUTH);
if (update == null) {
// Create account EntityAccount primary = db.account().getPrimaryAccount();
EntityAccount account = new EntityAccount();
// Create account
account.host = provider.imap.host; EntityAccount account = new EntityAccount();
account.encryption = aencryption;
account.port = provider.imap.port; account.host = provider.imap.host;
account.auth_type = AUTH_TYPE_OAUTH; account.encryption = aencryption;
account.provider = provider.id; account.port = provider.imap.port;
account.user = username; account.auth_type = AUTH_TYPE_OAUTH;
account.password = state; account.provider = provider.id;
account.user = username;
int at = address.indexOf('@'); account.password = state;
String user = address.substring(0, at);
int at = address.indexOf('@');
account.name = provider.name + "/" + user; String user = address.substring(0, at);
account.synchronize = true; account.name = provider.name + "/" + user;
account.primary = (primary == null);
account.synchronize = true;
if (provider.keepalive > 0) account.primary = (primary == null);
account.poll_interval = provider.keepalive;
if (provider.keepalive > 0)
account.partial_fetch = provider.partial; account.poll_interval = provider.keepalive;
account.created = new Date().getTime(); account.partial_fetch = provider.partial;
account.last_connected = account.created;
account.created = new Date().getTime();
account.id = db.account().insertAccount(account); account.last_connected = account.created;
args.putLong("account", account.id);
EntityLog.log(context, "OAuth account=" + account.name); account.id = db.account().insertAccount(account);
args.putLong("account", account.id);
// Create folders EntityLog.log(context, "OAuth account=" + account.name);
for (EntityFolder folder : folders) {
EntityFolder existing = db.folder().getFolderByName(account.id, folder.name); // Create folders
if (existing == null) { for (EntityFolder folder : folders) {
folder.account = account.id; EntityFolder existing = db.folder().getFolderByName(account.id, folder.name);
folder.id = db.folder().insertFolder(folder); if (existing == null) {
EntityLog.log(context, "OAuth folder=" + folder.name + " type=" + folder.type); folder.account = account.id;
if (folder.synchronize) folder.id = db.folder().insertFolder(folder);
EntityOperation.sync(context, folder.id, false); EntityLog.log(context, "OAuth folder=" + folder.name + " type=" + folder.type);
if (folder.synchronize)
EntityOperation.sync(context, folder.id, false);
}
} }
}
// Set swipe left/right folder // Set swipe left/right folder
for (EntityFolder folder : folders) for (EntityFolder folder : folders)
if (EntityFolder.TRASH.equals(folder.type)) if (EntityFolder.TRASH.equals(folder.type))
account.swipe_left = folder.id; account.swipe_left = folder.id;
else if (EntityFolder.ARCHIVE.equals(folder.type)) else if (EntityFolder.ARCHIVE.equals(folder.type))
account.swipe_right = folder.id; account.swipe_right = folder.id;
db.account().updateAccount(account); db.account().updateAccount(account);
// Create identities // Create identities
for (Pair<String, String> identity : identities) { for (Pair<String, String> identity : identities) {
EntityIdentity ident = new EntityIdentity(); EntityIdentity ident = new EntityIdentity();
ident.name = identity.second; ident.name = identity.second;
ident.email = identity.first; ident.email = identity.first;
ident.account = account.id; ident.account = account.id;
ident.host = provider.smtp.host; ident.host = provider.smtp.host;
ident.encryption = iencryption; ident.encryption = iencryption;
ident.port = provider.smtp.port; ident.port = provider.smtp.port;
ident.auth_type = AUTH_TYPE_OAUTH; ident.auth_type = AUTH_TYPE_OAUTH;
ident.provider = provider.id; ident.provider = provider.id;
ident.user = username; ident.user = username;
ident.password = state; ident.password = state;
ident.synchronize = true; ident.synchronize = true;
ident.primary = ident.user.equals(ident.email); ident.primary = ident.user.equals(ident.email);
ident.max_size = max_size; ident.max_size = max_size;
ident.id = db.identity().insertIdentity(ident); ident.id = db.identity().insertIdentity(ident);
EntityLog.log(context, "OAuth identity=" + ident.name + " email=" + ident.email); EntityLog.log(context, "OAuth identity=" + ident.name + " email=" + ident.email);
}
} else {
args.putLong("account", update.id);
EntityLog.log(context, "OAuth update account=" + update.name);
db.account().setAccountPassword(update.id, state);
db.identity().setIdentityPassword(update.id, update.user, state, update.auth_type);
} }
db.setTransactionSuccessful(); db.setTransactionSuccessful();

@ -230,21 +230,8 @@
android:labelFor="@+id/etUser" android:labelFor="@+id/etUser"
android:text="@string/title_user" android:text="@string/title_user"
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintBottom_toBottomOf="@id/ibAccount" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/ibAccount" app:layout_constraintTop_toBottomOf="@id/etPort" />
app:layout_constraintStart_toStartOf="parent" />
<ImageButton
android:id="@+id/ibAccount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:paddingEnd="12dp"
android:tag="ignore"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/etPort"
app:srcCompat="@drawable/twotone_settings_24" />
<eu.faircode.email.EditTextPlain <eu.faircode.email.EditTextPlain
android:id="@+id/etUser" android:id="@+id/etUser"
@ -254,7 +241,7 @@
android:inputType="text" android:inputType="text"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/ibAccount" /> app:layout_constraintTop_toBottomOf="@id/tvUser" />
<!-- password --> <!-- password -->

Loading…
Cancel
Save