From 049d8ff20486db31e4b23b5cf96977a750e9e2c1 Mon Sep 17 00:00:00 2001 From: petitPapillon Date: Sat, 26 Aug 2017 10:54:16 +0200 Subject: [PATCH 01/18] Login pin - WIP --- react/src/actions/actionCreators.js | 10 +- react/src/actions/actions/pin.js | 110 +++++++++++++++++++++ react/src/actions/storeType.js | 3 +- react/src/components/app/app.js | 1 + react/src/components/login/login.js | 58 ++++++++++- react/src/components/login/login.render.js | 68 +++++++++++++ react/src/components/login/login.scss | 5 + react/src/reducers/index.js | 2 + react/src/reducers/login.js | 19 ++++ react/src/translate/en.js | 3 + 10 files changed, 274 insertions(+), 5 deletions(-) create mode 100644 react/src/actions/actions/pin.js create mode 100644 react/src/reducers/login.js diff --git a/react/src/actions/actionCreators.js b/react/src/actions/actionCreators.js index 5919f83..b2562e3 100644 --- a/react/src/actions/actionCreators.js +++ b/react/src/actions/actionCreators.js @@ -29,7 +29,8 @@ import { DISPLAY_COIND_DOWN_MODAL, DISPLAY_CLAIM_INTEREST_MODAL, START_INTERVAL, - STOP_INTERVAL + STOP_INTERVAL, + GET_PIN_LIST } from './storeType'; import { logGuiHttp, @@ -376,4 +377,11 @@ export function toggleClaimInterestModal(display) { type: DISPLAY_CLAIM_INTEREST_MODAL, displayClaimInterestModal: display, } +} + +export function getPinList(pinList) { + return { + type: GET_PIN_LIST, + pinList: pinList + } } \ No newline at end of file diff --git a/react/src/actions/actions/pin.js b/react/src/actions/actions/pin.js new file mode 100644 index 0000000..bc970e2 --- /dev/null +++ b/react/src/actions/actions/pin.js @@ -0,0 +1,110 @@ +import Config from '../../config'; +import { getDecryptedPassphrase, getPinList, triggerToaster } from "../actionCreators"; +import { iguanaWalletPassphrase } from "./walletAuth"; + +export function encryptPassphrase(passphrase, key, pubKey) { + const payload = { + 'string': passphrase, + 'key': key, + 'pubkey': pubKey + }; + + return dispatch => { + return fetch(`http://127.0.0.1:${Config.agamaPort}/shepherd/encryptkey`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(payload), + }) + .catch(function(error) { + console.log(error); + dispatch( + triggerToaster( + 'encryptKey', + 'Error', + 'error' + ) + ); + }) + .then(response => response.json()) + .then(json => { + console.log('encrypt result', json); + dispatch( + triggerToaster( + 'passphrase successfully encrypted', + 'Success', + 'success' + ) + ); + }) + } +} + +export function loginWithPin(key, pubKey) { + const payload = { + 'key': key, + 'pubkey': pubKey + }; + + return dispatch => { + return fetch(`http://127.0.0.1:${Config.agamaPort}/shepherd/decryptkey`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(payload), + }) + .catch(function(error) { + console.log(error); + dispatch( + triggerToaster( + 'decryptKey', + 'Error', + 'error' + ) + ); + }) + .then(response => response.json()) + .then(json => { + console.log('decrypt result', json); + dispatch(iguanaWalletPassphrase(json.result)); + }) + } +} + +export function loadPinList() { + return dispatch => { + return fetch(`http://127.0.0.1:${Config.agamaPort}/shepherd/getpinlist`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + } + }) + .catch(function(error) { + console.log(error); + dispatch( + triggerToaster( + 'getPinList', + 'Error', + 'error' + ) + ); + }) + .then(response => response.json()) + .then(json => { + console.log('getpinlist result', json); + dispatch( + triggerToaster( + 'getPinList', + 'Success', + 'success' + ) + ); + + dispatch( + getPinList(json.result) + ) + }) + } +} \ No newline at end of file diff --git a/react/src/actions/storeType.js b/react/src/actions/storeType.js index 1e4c8af..c1b3d5f 100644 --- a/react/src/actions/storeType.js +++ b/react/src/actions/storeType.js @@ -46,4 +46,5 @@ export const CLI = 'CLI'; export const LOGOUT = 'LOGOUT'; export const DISPLAY_COIND_DOWN_MODAL = 'DISPLAY_COIND_DOWN_MODAL'; export const DISPLAY_LOGIN_SETTINGS_MODAL = 'DISPLAY_LOGIN_SETTINGS_MODAL'; -export const DISPLAY_CLAIM_INTEREST_MODAL = 'DISPLAY_CLAIM_INTEREST_MODAL'; \ No newline at end of file +export const DISPLAY_CLAIM_INTEREST_MODAL = 'DISPLAY_CLAIM_INTEREST_MODAL'; +export const GET_PIN_LIST = 'GET_PIN_LIST'; \ No newline at end of file diff --git a/react/src/components/app/app.js b/react/src/components/app/app.js index 81ab7f4..acb1bbf 100644 --- a/react/src/components/app/app.js +++ b/react/src/components/app/app.js @@ -5,6 +5,7 @@ import Main from '../main/main'; function mapStateToProps(state) { return { + login: state.login, toaster: state.toaster, AddCoin: state.AddCoin, Main: state.Main, diff --git a/react/src/components/login/login.js b/react/src/components/login/login.js index 185f5b2..ef93f04 100644 --- a/react/src/components/login/login.js +++ b/react/src/components/login/login.js @@ -17,6 +17,7 @@ import { PassPhraseGenerator } from '../../util/crypto/passphrasegenerator'; import SwallModalRender from './swall-modal.render'; import LoginRender from './login.render'; import { translate } from '../../translate/translate'; +import { encryptPassphrase, loadPinList, loginWithPin } from "../../actions/actions/pin"; const IGUNA_ACTIVE_HANDLE_TIMEOUT = 3000; const IGUNA_ACTIVE_COINS_TIMEOUT = 10000; @@ -44,6 +45,10 @@ class Login extends React.Component { trimPassphraseTimer: null, displayLoginSettingsDropdown: false, displayLoginSettingsDropdownSection: null, + shouldEncryptPassword: false, + encryptKey: '', + decryptKey: '', + selectedPin: '' }; this.toggleActivateCoinForm = this.toggleActivateCoinForm.bind(this); this.updateRegisterConfirmPassPhraseInput = this.updateRegisterConfirmPassPhraseInput.bind(this); @@ -57,6 +62,9 @@ class Login extends React.Component { this.execWalletCreate = this.execWalletCreate.bind(this); this.resizeLoginTextarea = this.resizeLoginTextarea.bind(this); this.toggleLoginSettingsDropdown = this.toggleLoginSettingsDropdown.bind(this); + this.updateEncryptKey = this.updateEncryptKey.bind(this); + this.updateDecryptKey = this.updateDecryptKey.bind(this); + this.loadPinList = this.loadPinList.bind(this); } // the setInterval handler for 'activeCoins' @@ -96,6 +104,28 @@ class Login extends React.Component { }); } + shouldEncryptPassword() { + return this.state.shouldEncryptPassword; + } + + toggleShouldEncryptPassword() { + this.setState({ + shouldEncryptPassword: !this.state.shouldEncryptPassword + }); + } + + updateEncryptKey(e) { + this.setState({ + encryptKey: e.target.value + }); + } + + updateDecryptKey(e) { + this.setState({ + decryptKey: e.target.value + }); + } + openSyncOnlyModal() { Store.dispatch(getSyncOnlyForks()); @@ -117,6 +147,7 @@ class Login extends React.Component { componentDidMount() { Store.dispatch(iguanaActiveHandle(true)); + this.loadPinList(); } toggleSeedInputVisibility() { @@ -244,9 +275,30 @@ class Login extends React.Component { loginPassPhraseSeedType: null, }); - Store.dispatch( - iguanaWalletPassphrase(this.state.loginPassphrase) - ); + console.log('LOGIN SEED', this.state.shouldEncryptPassword, this.state.encryptKey); + + if (this.state.shouldEncryptPassword) { + Store.dispatch(encryptPassphrase(this.state.loginPassphrase, this.state.encryptKey, 'blabla')); + } + + console.log('selected pin', this.state.selectedPin); + if (this.state.selectedPin) { + Store.dispatch(loginWithPin(this.state.decryptKey, 'blabla')); + } else { + Store.dispatch( + iguanaWalletPassphrase(this.state.loginPassphrase) + ); + } + } + + loadPinList() { + Store.dispatch(loadPinList()); + } + + updateSelectedPin(e) { + this.setState({ + selectedPin: e.target.value + }); } getLoginPassPhraseSeedType(passPhrase) { diff --git a/react/src/components/login/login.render.js b/react/src/components/login/login.render.js index bbef743..89f0a89 100644 --- a/react/src/components/login/login.render.js +++ b/react/src/components/login/login.render.js @@ -54,6 +54,9 @@ const LoginRender = function () {

{ translate('INDEX.WELCOME_LOGIN') }

+ { this.props.login.pinList.length > 0 && + You can login be entering a login seed or by selecting a pin + }
{ this.state.loginPassPhraseSeedType }
} + + { this.state.loginPassphrase && +
+
+ + +
this.toggleShouldEncryptPassword() }> + { translate('LOGIN.ENCRYPT_PASSWORD') } +
+
+
+ +
+ +
+
+ } + +
+ + { this.props.login.pinList.length > 0 && +
+
+ +
+
+ +
+
+ } + + + ); +}; \ No newline at end of file diff --git a/react/src/components/dashboard/receiveCoin/receiveCoin.js b/react/src/components/dashboard/receiveCoin/receiveCoin.js index c9f0097..f069c1e 100644 --- a/react/src/components/dashboard/receiveCoin/receiveCoin.js +++ b/react/src/components/dashboard/receiveCoin/receiveCoin.js @@ -99,11 +99,17 @@ class ReceiveCoin extends React.Component { } renderAddressActions(address, type) { + let qrContent = { + qrAddress: address, + qrAmount: address.amount, + qrCoin: this.props.coin, + }; + console.log(qrContent); if (this.isBasiliskMode()) { return AddressActionsBasiliskModeRender.call(this, address); } - return AddressActionsNonBasiliskModeRender.call(this, address, type); + return AddressActionsNonBasiliskModeRender.call(this, address, type, qrContent); } hasNoAmount(address) { diff --git a/react/src/components/dashboard/receiveCoin/receiveCoin.render.js b/react/src/components/dashboard/receiveCoin/receiveCoin.render.js index 13dc485..8cb9932 100644 --- a/react/src/components/dashboard/receiveCoin/receiveCoin.render.js +++ b/react/src/components/dashboard/receiveCoin/receiveCoin.render.js @@ -1,6 +1,7 @@ import React from 'react'; import { translate } from '../../../translate/translate'; import QRModal from '../qrModal/qrModal'; +import InvoiceModal from '../invoiceModal/invoiceModal'; export const AddressActionsBasiliskModeRender = function(address) { return ( @@ -31,7 +32,7 @@ export const AddressActionsBasiliskModeRender = function(address) { ); }; -export const AddressActionsNonBasiliskModeRender = function(address, type) { +export const AddressActionsNonBasiliskModeRender = function(address, type,qrContent) { return ( @@ -69,6 +70,7 @@ export const _ReceiveCoinTableRender = function() {