mirror of https://github.com/M66B/FairEmail.git
Cloud sync: activate
This commit is contained in:
parent
f731796480
commit
0ccc27d55c
|
@ -170,6 +170,7 @@ android {
|
|||
buildConfigField "String", "BITBUCKET_DOWNLOADS_URI", "\"https://bitbucket.org/M66B/fairemail-test/downloads/\""
|
||||
buildConfigField "String", "ANNOUNCEMENT_URI", "\"https://gist.githubusercontent.com/M66B/d544192ca56224839d6ba0f2f6314c1f/raw/\""
|
||||
buildConfigField "String", "CLOUD_URI", "\"https://api.fairemail.net/sync\""
|
||||
buildConfigField "String", "CLOUD_EMAIL", "\"cloud@in.faircode.eu\""
|
||||
buildConfigField "String", "TX_URI", localProperties.getProperty("paypal.uri", "\"\"")
|
||||
buildConfigField "String", "GPA_URI", localProperties.getProperty("gpa.uri", "\"\"")
|
||||
buildConfigField "String", "INFO_URI", localProperties.getProperty("info.uri", "\"\"")
|
||||
|
@ -191,6 +192,7 @@ android {
|
|||
buildConfigField "String", "BITBUCKET_DOWNLOADS_URI", "\"https://bitbucket.org/M66B/fairemail-test/downloads/\""
|
||||
buildConfigField "String", "ANNOUNCEMENT_URI", "\"https://gist.githubusercontent.com/M66B/d544192ca56224839d6ba0f2f6314c1f/raw/\""
|
||||
buildConfigField "String", "CLOUD_URI", "\"https://api.fairemail.net/sync\""
|
||||
buildConfigField "String", "CLOUD_EMAIL", "\"cloud@in.faircode.eu\""
|
||||
buildConfigField "String", "TX_URI", "\"\""
|
||||
buildConfigField "String", "GPA_URI", "\"\""
|
||||
buildConfigField "String", "INFO_URI", "\"\""
|
||||
|
@ -213,6 +215,7 @@ android {
|
|||
buildConfigField "String", "BITBUCKET_DOWNLOADS_URI", "\"\""
|
||||
buildConfigField "String", "ANNOUNCEMENT_URI", "\"\""
|
||||
buildConfigField "String", "CLOUD_URI", "\"\""
|
||||
buildConfigField "String", "CLOUD_EMAIL", "\"\""
|
||||
buildConfigField "String", "TX_URI", "\"\""
|
||||
buildConfigField "String", "GPA_URI", "\"\""
|
||||
buildConfigField "String", "INFO_URI", "\"\""
|
||||
|
@ -235,6 +238,7 @@ android {
|
|||
buildConfigField "String", "BITBUCKET_DOWNLOADS_URI", "\"\""
|
||||
buildConfigField "String", "ANNOUNCEMENT_URI", "\"\""
|
||||
buildConfigField "String", "CLOUD_URI", "\"\""
|
||||
buildConfigField "String", "CLOUD_EMAIL", "\"\""
|
||||
buildConfigField "String", "TX_URI", "\"\""
|
||||
buildConfigField "String", "GPA_URI", "\"\""
|
||||
buildConfigField "String", "INFO_URI", "\"\""
|
||||
|
|
|
@ -71,9 +71,21 @@ public class ActivityCompose extends ActivityBase implements FragmentManager.OnB
|
|||
@Override
|
||||
public void onBackStackChanged() {
|
||||
if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
|
||||
String action = getIntent().getAction();
|
||||
if (!isShared(action) &&
|
||||
(action == null || !action.startsWith("widget:"))) {
|
||||
Intent intent = getIntent();
|
||||
|
||||
String action = intent.getAction();
|
||||
boolean widget = (action != null && action.startsWith("widget:"));
|
||||
|
||||
String[] tos = intent.getStringArrayExtra(Intent.EXTRA_EMAIL);
|
||||
boolean cloud = (tos != null && tos.length == 1 && BuildConfig.CLOUD_EMAIL.equals(tos[0]));
|
||||
|
||||
if (cloud) {
|
||||
Intent setup = new Intent(this, ActivitySetup.class)
|
||||
.setAction("misc")
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
||||
.putExtra("tab", "backup");
|
||||
startActivity(setup);
|
||||
} else if (!isShared(action) && !widget) {
|
||||
Intent parent = getParentActivityIntent();
|
||||
if (parent != null)
|
||||
if (shouldUpRecreateTask(parent))
|
||||
|
|
|
@ -576,12 +576,24 @@ public class CloudSync {
|
|||
}
|
||||
}
|
||||
|
||||
private static JSONObject _call(Context context, String user, String password, JSONObject jrequest)
|
||||
throws GeneralSecurityException, JSONException, IOException, InvalidCipherTextException {
|
||||
byte[] salt = MessageDigest.getInstance("SHA256").digest(user.getBytes());
|
||||
private static byte[] getSalt(String user) throws NoSuchAlgorithmException {
|
||||
return MessageDigest.getInstance("SHA256").digest(user.getBytes());
|
||||
}
|
||||
|
||||
static String getCloudUser(String user) throws NoSuchAlgorithmException {
|
||||
return getCloudUser(getSalt(user));
|
||||
}
|
||||
|
||||
private static String getCloudUser(byte[] salt) throws NoSuchAlgorithmException {
|
||||
byte[] huser = MessageDigest.getInstance("SHA256").digest(salt);
|
||||
byte[] userid = Arrays.copyOfRange(huser, 0, 8);
|
||||
String cloudUser = Base64.encodeToString(userid, Base64.NO_PADDING | Base64.NO_WRAP);
|
||||
return Base64.encodeToString(userid, Base64.NO_PADDING | Base64.NO_WRAP);
|
||||
}
|
||||
|
||||
private static JSONObject _call(Context context, String user, String password, JSONObject jrequest)
|
||||
throws GeneralSecurityException, JSONException, IOException, InvalidCipherTextException {
|
||||
byte[] salt = getSalt(user);
|
||||
String cloudUser = getCloudUser(salt);
|
||||
|
||||
Pair<byte[], byte[]> key;
|
||||
String lookup = Helper.hex(salt) + ":" + password;
|
||||
|
|
|
@ -128,6 +128,7 @@ public class FragmentOptionsBackup extends FragmentBase implements SharedPrefere
|
|||
private Button btnLogout;
|
||||
private CheckBox cbDelete;
|
||||
private Group grpLogin;
|
||||
private Group grpActivate;
|
||||
private Group grpLogout;
|
||||
|
||||
private DateFormat DTF;
|
||||
|
@ -171,6 +172,7 @@ public class FragmentOptionsBackup extends FragmentBase implements SharedPrefere
|
|||
btnLogout = view.findViewById(R.id.btnLogout);
|
||||
cbDelete = view.findViewById(R.id.cbDelete);
|
||||
grpLogin = view.findViewById(R.id.grpLogin);
|
||||
grpActivate = view.findViewById(R.id.grpActivate);
|
||||
grpLogout = view.findViewById(R.id.grpLogout);
|
||||
|
||||
// Wire controls
|
||||
|
@ -215,7 +217,18 @@ public class FragmentOptionsBackup extends FragmentBase implements SharedPrefere
|
|||
btnActivate.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
// TODO
|
||||
try {
|
||||
String user = prefs.getString("cloud_user", null);
|
||||
Intent intent = new Intent(Intent.ACTION_SEND)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
.setType("text/plain")
|
||||
.putExtra(Intent.EXTRA_EMAIL, new String[]{BuildConfig.CLOUD_EMAIL})
|
||||
.putExtra(Intent.EXTRA_SUBJECT, CloudSync.getCloudUser(user))
|
||||
.putExtra(Intent.EXTRA_TEXT, "Activate");
|
||||
v.getContext().startActivity(intent);
|
||||
} catch (Throwable ex) {
|
||||
Log.e(ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -256,7 +269,6 @@ public class FragmentOptionsBackup extends FragmentBase implements SharedPrefere
|
|||
!TextUtils.isEmpty(BuildConfig.CLOUD_URI)
|
||||
? View.VISIBLE : View.GONE);
|
||||
Helper.linkPro(tvCloudPro);
|
||||
btnActivate.setVisibility(View.GONE);
|
||||
|
||||
cbSend.setChecked(prefs.getBoolean("cloud_send", true));
|
||||
cbReceive.setChecked(prefs.getBoolean("cloud_receive", false));
|
||||
|
@ -278,10 +290,14 @@ public class FragmentOptionsBackup extends FragmentBase implements SharedPrefere
|
|||
if (key == null ||
|
||||
"cloud_user".equals(key) ||
|
||||
"cloud_password".equals(key) ||
|
||||
"cloud_activated".equals(key) ||
|
||||
"cloud_busy".equals(key) ||
|
||||
"cloud_last_sync".equals(key)) {
|
||||
String user = prefs.getString("cloud_user", null);
|
||||
String password = prefs.getString("cloud_password", null);
|
||||
boolean auth = !(TextUtils.isEmpty(user) || TextUtils.isEmpty(password));
|
||||
boolean activated = prefs.getBoolean("cloud_activated", false);
|
||||
boolean busy = prefs.getBoolean("cloud_busy", false);
|
||||
long last_sync = prefs.getLong("cloud_last_sync", 0);
|
||||
|
||||
etUser.setText(user);
|
||||
|
@ -291,6 +307,7 @@ public class FragmentOptionsBackup extends FragmentBase implements SharedPrefere
|
|||
last_sync == 0 ? "-" : DTF.format(last_sync)));
|
||||
cbDelete.setChecked(false);
|
||||
grpLogin.setVisibility(auth ? View.GONE : View.VISIBLE);
|
||||
grpActivate.setVisibility(auth && !activated && !busy ? View.VISIBLE : View.GONE);
|
||||
grpLogout.setVisibility(auth ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
@ -1522,15 +1539,19 @@ public class FragmentOptionsBackup extends FragmentBase implements SharedPrefere
|
|||
}
|
||||
|
||||
private void cloud(Bundle args) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||
|
||||
new SimpleTask<Void>() {
|
||||
@Override
|
||||
protected void onPreExecute(Bundle args) {
|
||||
Helper.setViewsEnabled(cardCloud, false);
|
||||
prefs.edit().putBoolean("cloud_busy", true).apply();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Bundle args) {
|
||||
Helper.setViewsEnabled(cardCloud, true);
|
||||
prefs.edit().putBoolean("cloud_busy", false).apply();
|
||||
WorkerSync.init(getContext());
|
||||
}
|
||||
|
||||
|
@ -1566,7 +1587,8 @@ public class FragmentOptionsBackup extends FragmentBase implements SharedPrefere
|
|||
|
||||
@Override
|
||||
protected void onExecuted(Bundle args, Void data) {
|
||||
btnActivate.setVisibility(View.GONE);
|
||||
prefs.edit().putBoolean("cloud_activated", true).apply();
|
||||
|
||||
view.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -1577,8 +1599,9 @@ public class FragmentOptionsBackup extends FragmentBase implements SharedPrefere
|
|||
|
||||
@Override
|
||||
protected void onException(Bundle args, Throwable ex) {
|
||||
btnActivate.setVisibility(ex instanceof OperationCanceledException ? View.VISIBLE : View.GONE);
|
||||
if (ex instanceof SecurityException) {
|
||||
if (ex instanceof OperationCanceledException)
|
||||
prefs.edit().putBoolean("cloud_activated", false).apply();
|
||||
else if (ex instanceof SecurityException) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext())
|
||||
.setIcon(R.drawable.twotone_warning_24)
|
||||
.setTitle(getString(R.string.title_advanced_cloud_invalid))
|
||||
|
@ -1587,7 +1610,7 @@ public class FragmentOptionsBackup extends FragmentBase implements SharedPrefere
|
|||
if (!TextUtils.isEmpty(message))
|
||||
builder.setMessage(message);
|
||||
builder.show();
|
||||
} else if (!(ex instanceof OperationCanceledException))
|
||||
} else
|
||||
Log.unexpectedError(getParentFragmentManager(), ex);
|
||||
}
|
||||
}.execute(FragmentOptionsBackup.this, args, "cloud");
|
||||
|
|
|
@ -324,11 +324,22 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/btnLogin" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvLogin"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:text="username"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvRegister" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnActivate"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:backgroundTint="?attr/colorInfoBackground"
|
||||
android:drawableEnd="@drawable/twotone_redeem_24"
|
||||
android:drawablePadding="6dp"
|
||||
|
@ -340,16 +351,17 @@
|
|||
android:textStyle="bold"
|
||||
app:drawableTint="?attr/colorInfoForeground"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvRegister" />
|
||||
app:layout_constraintTop_toBottomOf="@id/tvLogin" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvLogin"
|
||||
android:layout_width="wrap_content"
|
||||
android:id="@+id/tvActivateRemark"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:text="username"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginTop="6dp"
|
||||
android:text="@string/title_advanced_cloud_activate_remark"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:textStyle="italic"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/btnActivate" />
|
||||
|
||||
|
@ -363,7 +375,7 @@
|
|||
android:textStyle="italic"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvLogin" />
|
||||
app:layout_constraintTop_toBottomOf="@id/tvActivateRemark" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbSend"
|
||||
|
@ -436,6 +448,13 @@
|
|||
tvUser,etUser,tvPassword,tilPassword,tvPasswordRemark,
|
||||
btnLogin,tvRegister" />
|
||||
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/grpActivate"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:constraint_referenced_ids="
|
||||
btnActivate,tvActivateRemark" />
|
||||
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/grpLogout"
|
||||
android:layout_width="0dp"
|
||||
|
|
|
@ -989,6 +989,10 @@
|
|||
<string name="title_advanced_cloud_password_remark" translatable="false">You can change the password by wiping the data and logging in again</string>
|
||||
<string name="title_advanced_cloud_invalid" translatable="false">Invalid username or password</string>
|
||||
<string name="title_advanced_cloud_activate" translatable="false">Activate</string>
|
||||
<string name="title_advanced_cloud_activate_remark" translatable="false">
|
||||
Please use the same email address you used to activate the pro features.
|
||||
The cloud account and the email address will not be linked.
|
||||
</string>
|
||||
<string name="title_advanced_cloud_account_remark" translatable="false">
|
||||
Only enabled accounts and identities will be synchronized.
|
||||
Folder properties will not be synchronized.
|
||||
|
|
Loading…
Reference in New Issue