Password is required when create/change profile

This commit is contained in:
Yaroslav Berezanskyi 2015-08-15 15:53:27 +03:00
parent 7d704147b3
commit e02c8b2714
8 changed files with 137 additions and 104 deletions

View File

@ -1,6 +1,7 @@
package io.syng.activity;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Intent;
import android.content.res.Configuration;
import android.net.Uri;
@ -15,6 +16,7 @@ import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.InputType;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Patterns;
import android.view.KeyEvent;
@ -172,62 +174,45 @@ public abstract class BaseActivity extends AppCompatActivity implements
mHandler.postDelayed(mRunnable, DRAWER_CLOSE_DELAY_SHORT);
}
protected void changeProfile(Profile profile) {
private void changeProfile(Profile profile) {
ProfileManager.setCurrentProfile(profile);
updateCurrentProfileName();
Glide.with(this).load(PrefsUtil.getBackgroundResourceId(profile.getId())).into(mHeaderImageView);
populateDApps();
flipDrawer();
}
protected void updateCurrentProfileName() {
private void updateCurrentProfileName() {
TextView textView = (TextView) findViewById(R.id.tv_name);
textView.setText(ProfileManager.getCurrentProfile().getName());
}
// protected void requestChangeProfile(final Profile profile) {
//
// new MaterialDialog.Builder(BaseActivity.this)
// .title(R.string.request_profile_password)
// .customView(R.layout.profile_password, true)
// .positiveText(R.string.ok)
// .negativeText(R.string.cancel)
// .contentColor(getResources().getColor(R.color.accent))
// .dividerColorRes(R.color.accent)
// .backgroundColorRes(R.color.primary_dark)
// .positiveColorRes(R.color.accent)
// .negativeColorRes(R.color.accent)
// .widgetColorRes(R.color.accent)
// .callback(new MaterialDialog.ButtonCallback() {
//
// @SuppressWarnings("ConstantConditions")
// @Override
// public void onPositive(MaterialDialog dialog) {
//
// View view = dialog.getCustomView();
// EditText passwordInput = (EditText) view.findViewById(R.id.passwordInput);
// if (profile.decrypt(passwordInput.getText().toString())) {
// changeProfile(profile);
// } else {
//// dialog.hide();
//// mAccountSpinner.setSelection(currentPosition, false);
// }
// }
//
// @Override
// public void onNegative(MaterialDialog dialog) {
//
//// dialog.hide();
//// mAccountSpinner.setSelection(currentPosition, false);
// }
// })
// .build()
// .show();
// }
private void requestChangeProfile(final Profile profile) {
Dialog dialog = new MaterialDialog.Builder(BaseActivity.this)
.title(R.string.request_profile_password)
.customView(R.layout.profile_password, true)
.positiveText(R.string.ok)
.negativeText(R.string.cancel)
.callback(new MaterialDialog.ButtonCallback() {
@SuppressWarnings("ConstantConditions")
@Override
public void onPositive(MaterialDialog dialog) {
View view = dialog.getCustomView();
EditText password = (EditText) view.findViewById(R.id.et_pass);
if (profile.checkPassword(password.getText().toString())) {
changeProfile(profile);
} else {
Toast.makeText(BaseActivity.this, "Password is not correct", Toast.LENGTH_SHORT).show();
}
}
})
.show();
EditText name = (EditText) dialog.findViewById(R.id.et_pass);
GeneralUtil.showKeyBoard(name, this);
}
private void initSearch() {
mSearchTextView.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@ -242,12 +227,9 @@ public abstract class BaseActivity extends AppCompatActivity implements
updateDAppList(searchValue);
}
});
mSearchTextView.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View view, int i, KeyEvent keyEvent) {
if (keyEvent.getAction() == KeyEvent.ACTION_DOWN && keyEvent.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
GeneralUtil.hideKeyBoard(mSearchTextView, BaseActivity.this);
return true;
@ -257,7 +239,7 @@ public abstract class BaseActivity extends AppCompatActivity implements
});
}
protected void updateDAppList(String filter) {
private void updateDAppList(String filter) {
List<Dapp> mDApps = ProfileManager.getCurrentProfile().getDapps();
ArrayList<Dapp> dapps = new ArrayList<>(mDApps.size());
int length = mDApps.size();
@ -317,28 +299,60 @@ public abstract class BaseActivity extends AppCompatActivity implements
flipDrawer();
break;
}
}
@SuppressWarnings("ConstantConditions")
private void showAccountCreateDialog() {
private void showProfileCreateDialog() {
MaterialDialog dialog = new MaterialDialog.Builder(this)
.title("New account")
.content("Put your name to create new account")
.inputType(InputType.TYPE_CLASS_TEXT)
.input("Name", "", new MaterialDialog.InputCallback() {
.positiveText(R.string.dialog_button_create)
.negativeText(R.string.dialog_button_cancel)
.customView(R.layout.profile_create_dialog, true)
.autoDismiss(false)
.callback(new MaterialDialog.ButtonCallback() {
@Override
public void onInput(MaterialDialog dialog, CharSequence input) {
Profile profile = new Profile();
profile.setName(input.toString());
ProfileManager.addProfile(profile);
mProfileDrawerAdapter.swapData(ProfileManager.getProfiles());
public void onPositive(MaterialDialog dialog) {
EditText name = (EditText) dialog.findViewById(R.id.et_profile_name);
EditText pass1 = (EditText) dialog.findViewById(R.id.et_profile_pass_1);
EditText pass2 = (EditText) dialog.findViewById(R.id.et_profile_pass_2);
String nameString = name.getText().toString();
String pass1String = pass1.getText().toString();
String pass2String = pass2.getText().toString();
if (TextUtils.isEmpty(nameString)) {
Toast.makeText(BaseActivity.this, "Profile name can't be empty", Toast.LENGTH_SHORT).show();
return;
}
if (TextUtils.isEmpty(pass1String) || TextUtils.isEmpty(pass2String)) {
Toast.makeText(BaseActivity.this, "Password name can't be empty", Toast.LENGTH_SHORT).show();
return;
}
if (!pass1.getText().toString().equals(pass2.getText().toString())) {
Toast.makeText(BaseActivity.this, "Passwords should be the same!", Toast.LENGTH_SHORT).show();
} else {
Profile profile = new Profile();
profile.setName(name.getText().toString());
profile.setPassword(pass1String);
ProfileManager.addProfile(profile);
mProfileDrawerAdapter.swapData(ProfileManager.getProfiles());
GeneralUtil.hideKeyBoard(name, BaseActivity.this);
GeneralUtil.hideKeyBoard(pass1, BaseActivity.this);
GeneralUtil.hideKeyBoard(pass2, BaseActivity.this);
dialog.dismiss();
}
}
@Override
public void onNegative(MaterialDialog dialog) {
dialog.dismiss();
}
}).show();
dialog.getInputEditText().setSingleLine();
EditText name = (EditText) dialog.findViewById(R.id.et_profile_name);
GeneralUtil.showKeyBoard(name, this);
}
private void flipDrawer() {
ImageView imageView = (ImageView) findViewById(R.id.drawer_indicator);
if (isDrawerFrontViewActive()) {
@ -373,8 +387,10 @@ public abstract class BaseActivity extends AppCompatActivity implements
@Override
public void onProfileClick(Profile profile) {
changeProfile(profile);
flipDrawer();
if (ProfileManager.getCurrentProfile().getId().equals(profile.getId())) {
return;
}
requestChangeProfile(profile);
}
@Override
@ -385,7 +401,6 @@ public abstract class BaseActivity extends AppCompatActivity implements
.positiveText(R.string.sImport)
.negativeText(R.string.cancel)
.callback(new MaterialDialog.ButtonCallback() {
@Override
public void onPositive(MaterialDialog dialog) {
RadioButton importJsonRadio = (RadioButton) dialog.findViewById(R.id.radio_import_json);
@ -414,7 +429,6 @@ public abstract class BaseActivity extends AppCompatActivity implements
Toast.makeText(BaseActivity.this, R.string.error_reading_file, Toast.LENGTH_SHORT).show();
logger.error("Error reading wallet file", e);
}
if (importJsonRadio.isChecked()) {
Profile profile = ProfileManager.getCurrentProfile();
if (profile.importWallet(fileContents, password)) {
@ -446,7 +460,6 @@ public abstract class BaseActivity extends AppCompatActivity implements
.positiveText(R.string.save)
.negativeText(R.string.cancel)
.callback(new MaterialDialog.ButtonCallback() {
@Override
public void onPositive(MaterialDialog dialog) {
EditText dappNameEdit = (EditText) dialog.findViewById(R.id.dapp_name);
@ -504,7 +517,6 @@ public abstract class BaseActivity extends AppCompatActivity implements
dialog.getInputEditText().setText(profile.getName());
}
@Override
public void onDAppAdd() {
new MaterialDialog.Builder(this)
@ -513,7 +525,6 @@ public abstract class BaseActivity extends AppCompatActivity implements
.positiveText(R.string.save)
.negativeText(R.string.cancel)
.callback(new MaterialDialog.ButtonCallback() {
@Override
public void onPositive(MaterialDialog dialog) {
EditText dappNameEdit = (EditText) dialog.findViewById(R.id.dapp_name);
@ -534,7 +545,6 @@ public abstract class BaseActivity extends AppCompatActivity implements
} else {
Toast.makeText(BaseActivity.this, R.string.invalid_url, Toast.LENGTH_SHORT).show();
}
}
@Override
@ -560,7 +570,7 @@ public abstract class BaseActivity extends AppCompatActivity implements
@Override
public void onNewProfile() {
showAccountCreateDialog();
showProfileCreateDialog();
}
@Override

View File

@ -24,7 +24,7 @@ public class Profile implements Serializable {
protected List<String> privateKeys = new ArrayList<>();
/* "password protect profile" (encrypt the private keys) */
protected boolean passwordProtectedProfile = false;
protected boolean passwordProtectedProfile;
protected List<Dapp> dapps = new ArrayList<>();
@ -32,22 +32,19 @@ public class Profile implements Serializable {
protected String passwordHash;
protected transient boolean isEncrypted = false;
protected transient boolean isEncrypted;
public Profile() {
this.privateKeys.add(createPrivateKey());
addDefaultApps();
}
public Profile(String privateKey) {
this.privateKeys.add(privateKey);
addDefaultApps();
}
public Profile(List<String> privateKeys) {
this.privateKeys = privateKeys;
addDefaultApps();
}
@ -70,49 +67,40 @@ public class Profile implements Serializable {
}
protected String createPrivateKey() {
byte[] privateKey = HashUtil.sha3(HashUtil.randomPeerId());
return Hex.toHexString(privateKey);
}
public List<String> getPrivateKeys() {
return privateKeys;
}
public void setPrivateKeys(List<String> privateKeys) {
this.privateKeys = privateKeys;
}
public void addPrivateKey(String privateKey) {
this.privateKeys.add(privateKey);
}
public void removePrivateKey(String privateKey) {
this.privateKeys.remove(privateKey);
}
public List<Dapp> getDapps() {
return dapps;
}
public void setDapps(List<Dapp> dapps) {
this.dapps = dapps;
}
public void addDapp(Dapp dapp) {
this.dapps.add(dapp);
}
public void updateDapp(Dapp dapp) {
for (Dapp item: dapps) {
for (Dapp item : dapps) {
if (item.getId().equals(dapp.getId())) {
int index = dapps.indexOf(item);
dapps.set(index, dapp);
@ -121,47 +109,42 @@ public class Profile implements Serializable {
}
public void removeDapp(Dapp dapp) {
this.dapps.remove(dapp);
}
public boolean getPasswordProtectedProfile() {
return passwordProtectedProfile;
}
public void setPasswordProtectedProfile(boolean passwordProtectedProfile) {
this.passwordProtectedProfile = passwordProtectedProfile;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
protected void setPassword(String password) {
public void setPassword(String password) {
this.passwordHash = Hex.toHexString(HashUtil.sha3(password.getBytes()));
}
public void encrypt(String password) {
public boolean checkPassword(String password) {
return passwordHash.equals(Hex.toHexString(HashUtil.sha3(password.getBytes())));
}
public void encrypt(String password) {
if (!passwordProtectedProfile) {
setPassword(password);
List<String> encrypted = new ArrayList<>();
@ -174,9 +157,8 @@ public class Profile implements Serializable {
}
public boolean decrypt(String password) {
if (passwordProtectedProfile) {
if (passwordHash != Hex.toHexString(HashUtil.sha3(password.getBytes()))) {
if (!passwordHash.equals(Hex.toHexString(HashUtil.sha3(password.getBytes())))) {
return false;
}
List<String> decrypted = new ArrayList<>();
@ -190,19 +172,16 @@ public class Profile implements Serializable {
}
protected String encryptPrivateKey(String privateKey, String password) {
// TODO: Encrypt private key
return privateKey;
}
protected String decryptPrivateKey(String privateKey, String password) {
// TODO: Decrypt private key
return privateKey;
}
public boolean importWallet(String jsonWallet, String password) {
try {
JSONObject json = new JSONObject(jsonWallet);
byte[] privateKey = null;
@ -241,9 +220,7 @@ public class Profile implements Serializable {
}
public void importPrivateKey(String privateKey, String password) {
privateKeys.add(decryptPrivateKey(privateKey, password));
}
}

View File

@ -22,6 +22,13 @@ public final class GeneralUtil {
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
public static void showKeyBoard(View view, Context context) {
if (view == null)
return;
InputMethodManager imm = (InputMethodManager) context.getApplicationContext().getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
}
public static void createHomeScreenIcon(final Context context, final String name, final String url) {
Intent shortcutIntent = new Intent(Intent.ACTION_VIEW);
shortcutIntent.setData(Uri.parse(url));

View File

@ -56,6 +56,7 @@ public final class ProfileManager {
byte[] cbAddr = HashUtil.sha3(secret.getBytes());
addresses.add(Hex.toHexString(cbAddr));
profile.setPrivateKeys(addresses);
profile.setPassword("qw");
ProfileManager.addProfile(profile);
ProfileManager.setCurrentProfile(profile);
return profile;

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="@+id/et_profile_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/hint.profile.name"
android:inputType="text"
android:singleLine="true"/>
<EditText
android:id="@+id/et_profile_pass_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/hint.profile.pass"
android:inputType="textPassword"
android:singleLine="true"/>
<EditText
android:id="@+id/et_profile_pass_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/hitn.profile.repeat.pass"
android:inputType="textPassword"
android:singleLine="true"/>
</LinearLayout>

View File

@ -5,8 +5,11 @@
android:orientation="vertical">
<EditText
android:id="@+id/passwordInput"
android:layout_width="fill_parent"
android:id="@+id/et_pass"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:password="true"/>
android:inputType="textPassword"
android:hint="@string/hint.profile.pass"
/>
</LinearLayout>

View File

@ -30,5 +30,10 @@
<string name="request_profile_password">Profile Password</string>
<string name="warning.message">This is PRE-ALPHA software and most likely contains numerous bugs. The layout, design, and functionality may change frequently. This also lacks numerous features that will be included in later versions. Using this software you agree that you hold yourself personally accountable for interacting with this software.</string>
<string name="warning.title">WARNING</string>
<string name="hint.profile.name">Profile name</string>
<string name="hint.profile.pass">Password</string>
<string name="hitn.profile.repeat.pass">Repeat password</string>
<string name="dialog.button.create">Create</string>
<string name="dialog.button.cancel">Cancel</string>
</resources>

View File

@ -8,7 +8,6 @@
android:singleLine="true"
android:title="@string/pref_json_rpc_server_title"/>
<ListPreference
android:defaultValue="3"
android:entries="@array/pref_running_modes_titles"