Browse Source

Wallet login - add seed type selection; check if entered seed fits the selected seed type

all-modes
petitPapillon 8 years ago
parent
commit
fd84260ef2
  1. 43
      react/src/components/login/login.js
  2. 71
      react/src/components/login/login.render.js
  3. 7
      react/src/translate/en.js
  4. 9
      react/src/util/crypto/passphrasegenerator.js

43
react/src/components/login/login.js

@ -1,21 +1,20 @@
import React from 'react'; import React from 'react';
import { translate } from '../../translate/translate';
import { import {
toggleAddcoinModal, toggleAddcoinModal,
iguanaWalletPassphrase, iguanaWalletPassphrase,
iguanaActiveHandle, iguanaActiveHandle,
startInterval, startInterval,
stopInterval,
getDexCoins, getDexCoins,
toggleSyncOnlyModal, toggleSyncOnlyModal,
getSyncOnlyForks, getSyncOnlyForks,
createNewWallet createNewWallet,
triggerToaster
} from '../../actions/actionCreators'; } from '../../actions/actionCreators';
import Store from '../../store'; import Store from '../../store';
import { PassPhraseGenerator } from '../../util/crypto/passphrasegenerator'; import {PassPhraseGenerator} from '../../util/crypto/passphrasegenerator';
import SwallModalRender from './swall-modal.render'; import SwallModalRender from './swall-modal.render';
import LoginRender from './login.render'; import LoginRender from './login.render';
import {translate} from '../../translate/translate';
const IGUNA_ACTIVE_HANDLE_TIMEOUT = 3000; const IGUNA_ACTIVE_HANDLE_TIMEOUT = 3000;
const IGUNA_ACTIVE_COINS_TIMEOUT = 10000; const IGUNA_ACTIVE_COINS_TIMEOUT = 10000;
@ -28,6 +27,7 @@ class Login extends React.Component {
activeLoginSection: 'activateCoin', activeLoginSection: 'activateCoin',
loginPassphrase: null, loginPassphrase: null,
seedInputVisibility: false, seedInputVisibility: false,
loginPassPhraseBitsOption: 256,
bitsOption: 256, bitsOption: 256,
randomSeed: PassPhraseGenerator.generatePassPhrase(256), randomSeed: PassPhraseGenerator.generatePassPhrase(256),
randomSeedConfirm: '', randomSeedConfirm: '',
@ -167,11 +167,41 @@ class Login extends React.Component {
} }
loginSeed() { loginSeed() {
if (!PassPhraseGenerator.isPassPhraseValid(this.state.loginPassphrase,
this.state.loginPassPhraseBitsOption)) {
Store.dispatch(triggerToaster(
`${translate('LOGIN.SEED_NOT_OF_TYPE')} ${this.selectedLoginSeedTypeLabel()}`,
translate('LOGIN.INVALID_SEED'),
'error',
false
));
return;
}
Store.dispatch( Store.dispatch(
iguanaWalletPassphrase(this.state.loginPassphrase) iguanaWalletPassphrase(this.state.loginPassphrase)
); );
} }
selectedLoginSeedTypeLabel() {
if (this.state.loginPassPhraseBitsOption === 256) {
return translate('LOGIN.IGUANA_SEED');
}
if (this.state.loginPassPhraseBitsOption === 160) {
return translate('LOGIN.WAVES_SEED');
}
if (this.state.loginPassPhraseBitsOption === 128) {
return translate('LOGIN.NXT_SEED');
}
}
onLoginPassPhraseBitsOptionChange(bitsOption) {
this.setState({
loginPassPhraseBitsOption: +bitsOption
});
}
updateActiveLoginSection(name) { updateActiveLoginSection(name) {
// reset login/create form // reset login/create form
this.setState({ this.setState({
@ -245,8 +275,7 @@ class Login extends React.Component {
} }
render() { render() {
if ((this.state && this.state.display) || if ((this.state && this.state.display) || !this.props.Main) {
!this.props.Main) {
return LoginRender.call(this); return LoginRender.call(this);
} }

71
react/src/components/login/login.render.js

@ -51,13 +51,60 @@ const LoginRender = function () {
<div className={ this.state.activeLoginSection === 'login' ? 'show' : 'hide' }> <div className={ this.state.activeLoginSection === 'login' ? 'show' : 'hide' }>
<h4 className="color-white">{translate('INDEX.WELCOME_LOGIN')}</h4> <h4 className="color-white">{translate('INDEX.WELCOME_LOGIN')}</h4>
<div className="login-form"> <div className="login-form">
<div>
<h4 className="hint color-white">
{ translate('INDEX.SELECT_SEED_TYPE') }:
</h4>
<div className="form-group form-material floating">
<div className="radio-custom radio-default radio-inline">
<input
id="loginPassPhraseOptionsIguana"
type="radio"
name="loginPassPhraseOptions"
value="256"
checked={ this.state.loginPassPhraseBitsOption === 256 }
onChange={ (e) => this.onLoginPassPhraseBitsOptionChange(e.target.value) }
/>
<label htmlFor="loginPassPhraseOptionsIguana">
{ translate('LOGIN.IGUANA_SEED') }
</label>
</div>
<div className="radio-custom radio-default radio-inline">
<input
id="loginPassPhraseOptionsWaves"
type="radio"
name="loginPassPhraseOptions"
value="160"
checked={ this.state.loginPassPhraseBitsOption === 160 }
onChange={ (e) => this.onLoginPassPhraseBitsOptionChange(e.target.value) }
/>
<label htmlFor="loginPassPhraseOptionsWaves">
{ translate('LOGIN.WAVES_SEED') }
</label>
</div>
<div className="radio-custom radio-default radio-inline">
<input
id="loginPassPhraseOptionsNXT"
type="radio"
name="loginPassPhraseOptions"
value="128"
checked={ this.state.loginPassPhraseBitsOption === 128 }
onChange={ (e) => this.onLoginPassPhraseBitsOptionChange(e.target.value) }
/>
<label htmlFor="loginPassPhraseOptionsNXT">
{ translate('LOGIN.NXT_SEED') }
</label>
</div>
</div>
</div>
</div>
<div className="form-group form-material floating"> <div className="form-group form-material floating">
<input <input
type={ this.state.seedInputVisibility ? 'text' : 'password' } type={ this.state.seedInputVisibility ? 'text' : 'password' }
className="form-control" className="form-control"
name="loginPassphrase" name="loginPassphrase"
onChange={ this.updateInput } onChange={ this.updateInput }
onKeyDown={ (event) => this.handleKeydown(event) } /> onKeyDown={ (event) => this.handleKeydown(event) }/>
<i <i
className={ this.state.seedInputVisibility ? 'seed-toggle fa fa-eye-slash' : 'seed-toggle fa fa-eye' } className={ this.state.seedInputVisibility ? 'seed-toggle fa fa-eye-slash' : 'seed-toggle fa fa-eye' }
onClick={ this.toggleSeedInputVisibility }></i> onClick={ this.toggleSeedInputVisibility }></i>
@ -69,7 +116,8 @@ const LoginRender = function () {
type="button" type="button"
className="btn btn-primary btn-block" className="btn btn-primary btn-block"
onClick={ this.loginSeed } onClick={ this.loginSeed }
disabled={ !this.state.loginPassphrase || !this.state.loginPassphrase.length }>{ translate('INDEX.SIGN_IN') }</button> disabled={ !this.state.loginPassphrase
|| !this.state.loginPassphrase.length }>{ translate('INDEX.SIGN_IN') }</button>
<div className="form-group form-material floating"> <div className="form-group form-material floating">
<button <button
className="btn btn-lg btn-flat btn-block waves-effect" className="btn btn-lg btn-flat btn-block waves-effect"
@ -87,7 +135,6 @@ const LoginRender = function () {
</button> </button>
</div> </div>
</div> </div>
</div>
<div className={ this.state.activeLoginSection === 'activateCoin' ? 'show' : 'hide' }> <div className={ this.state.activeLoginSection === 'activateCoin' ? 'show' : 'hide' }>
<h4 className="color-white">{ translate('INDEX.WELCOME_PLEASE_ADD') }</h4> <h4 className="color-white">{ translate('INDEX.WELCOME_PLEASE_ADD') }</h4>
@ -137,8 +184,10 @@ const LoginRender = function () {
<input <input
type="radio" type="radio"
name="PassPhraseOptions" name="PassPhraseOptions"
checked={ this.state.bitsOption === 256 ? true : false }/> checked={ this.state.bitsOption === 256 }/>
<label htmlFor="PassPhraseOptionsIguana">Iguana (256 bits)</label> <label htmlFor="PassPhraseOptionsIguana">
{ translate('LOGIN.IGUANA_SEED') }
</label>
</div> </div>
<div <div
className="radio-custom radio-default radio-inline" className="radio-custom radio-default radio-inline"
@ -146,8 +195,10 @@ const LoginRender = function () {
<input <input
type="radio" type="radio"
name="PassPhraseOptions" name="PassPhraseOptions"
checked={ this.state.bitsOption === 160 ? true : false }/> checked={ this.state.bitsOption === 160 }/>
<label htmlFor="PassPhraseOptionsWaves">Waves</label> <label htmlFor="PassPhraseOptionsWaves">
{ translate('LOGIN.WAVES_SEED') }
</label>
</div> </div>
<div <div
className="radio-custom radio-default radio-inline" className="radio-custom radio-default radio-inline"
@ -155,8 +206,10 @@ const LoginRender = function () {
<input <input
type="radio" type="radio"
name="PassPhraseOptions" name="PassPhraseOptions"
checked={ this.state.bitsOption === 128 ? true : false }/> checked={ this.state.bitsOption === 128 }/>
<label htmlFor="PassPhraseOptionsNXT">NXT</label> <label htmlFor="PassPhraseOptionsNXT">
{ translate('LOGIN.NXT_SEED') }
</label>
</div> </div>
</div> </div>
</div> </div>

7
react/src/translate/en.js

@ -403,7 +403,12 @@ export const _lang = {
'DISPLAY_SYNC_ONLY': 'Display sync only coins progress', 'DISPLAY_SYNC_ONLY': 'Display sync only coins progress',
'ENTER_VALUE_AGAIN': 'Please enter the same value again', 'ENTER_VALUE_AGAIN': 'Please enter the same value again',
'CUSTOM_WALLET_SEED': 'Custom wallet seed', 'CUSTOM_WALLET_SEED': 'Custom wallet seed',
'MUST_ENTER_SEED': 'You must enter a seed' 'MUST_ENTER_SEED': 'You must enter a seed',
'INVALID_SEED': 'Invalid Seed',
'SEED_NOT_OF_TYPE': 'The inserted seed is not of type',
'IGUANA_SEED': 'Iguana (256 bits)',
'WAVES_SEED': 'Waves',
'NXT_SEED': 'NXT'
}, },
'SIDEBAR': { 'SIDEBAR': {
'EDEX_MOTTO': 'Most Secure, Easy and Native Decentralised Exchange', 'EDEX_MOTTO': 'Most Secure, Easy and Native Decentralised Exchange',

9
react/src/util/crypto/passphrasegenerator.js

@ -80,6 +80,15 @@ export const PassPhraseGenerator = {
return this.passPhrase; return this.passPhrase;
}, },
// checks if it's possible that the pass phrase supplied as the first parameter
// was generated with the number of bits supplied as the second parameter
isPassPhraseValid: function (passPhrase, bits) {
// the required number of words based on the number of bits
// mirrors the generatePassPhrase function above
const wordsCount = bits / 32 * 3;
return passPhrase && passPhrase.split(" ").length === wordsCount;
},
reset: function() { reset: function() {
this.passPhrase = ""; this.passPhrase = "";
this.seeds = 0; this.seeds = 0;

Loading…
Cancel
Save