From 600a7e5ccc84609f8e088d9eb33624cff6ae8bf6 Mon Sep 17 00:00:00 2001
From: Jannis R
Date: Tue, 6 Dec 2016 15:09:11 +0100
Subject: [PATCH 01/21] make SMS verification contract general purpose
---
js/src/contracts/contracts.js | 7 +++++--
js/src/contracts/{sms-verification.js => verification.js} | 0
js/src/modals/SMSVerification/store.js | 2 +-
3 files changed, 6 insertions(+), 3 deletions(-)
rename js/src/contracts/{sms-verification.js => verification.js} (100%)
diff --git a/js/src/contracts/contracts.js b/js/src/contracts/contracts.js
index f61a63690..f30f67efb 100644
--- a/js/src/contracts/contracts.js
+++ b/js/src/contracts/contracts.js
@@ -19,7 +19,7 @@ import Registry from './registry';
import SignatureReg from './signaturereg';
import TokenReg from './tokenreg';
import GithubHint from './githubhint';
-import * as smsVerification from './sms-verification';
+import * as verification from './verification';
import BadgeReg from './badgereg';
let instance = null;
@@ -58,7 +58,10 @@ export default class Contracts {
}
get smsVerification () {
- return smsVerification;
+ return verification;
+ }
+ get emailVerification () {
+ return verification;
}
static create (api) {
diff --git a/js/src/contracts/sms-verification.js b/js/src/contracts/verification.js
similarity index 100%
rename from js/src/contracts/sms-verification.js
rename to js/src/contracts/verification.js
diff --git a/js/src/modals/SMSVerification/store.js b/js/src/modals/SMSVerification/store.js
index 49b91fa70..279329ca5 100644
--- a/js/src/modals/SMSVerification/store.js
+++ b/js/src/modals/SMSVerification/store.js
@@ -20,7 +20,7 @@ import { sha3 } from '~/api/util/sha3';
import Contracts from '~/contracts';
-import { checkIfVerified, checkIfRequested, awaitPuzzle } from '~/contracts/sms-verification';
+import { checkIfVerified, checkIfRequested, awaitPuzzle } from '~/contracts/verification';
import { postToServer } from '../../3rdparty/sms-verification';
import checkIfTxFailed from '../../util/check-if-tx-failed';
import waitForConfirmations from '../../util/wait-for-block-confirmations';
From b5b529f8c2442bbeb6675225f46141dd7a583085 Mon Sep 17 00:00:00 2001
From: Jannis R
Date: Tue, 6 Dec 2016 15:09:54 +0100
Subject: [PATCH 02/21] modals/SMSVerification -> modals/Verification
---
.../modals/{SMSVerification => Verification}/Done/done.css | 0
.../modals/{SMSVerification => Verification}/Done/done.js | 0
.../modals/{SMSVerification => Verification}/Done/index.js | 0
.../GatherData/gatherData.css | 0
.../GatherData/gatherData.js | 0
.../{SMSVerification => Verification}/GatherData/index.js | 0
.../{SMSVerification => Verification}/QueryCode/index.js | 0
.../QueryCode/queryCode.js | 0
.../SendConfirmation/index.js | 0
.../SendConfirmation/sendConfirmation.css | 0
.../SendConfirmation/sendConfirmation.js | 0
.../{SMSVerification => Verification}/SendRequest/index.js | 0
.../SendRequest/sendRequest.css | 0
.../SendRequest/sendRequest.js | 0
js/src/modals/{SMSVerification => Verification}/index.js | 2 +-
js/src/modals/{SMSVerification => Verification}/store.js | 0
.../SMSVerification.js => Verification/verification.js} | 4 ++--
js/src/modals/index.js | 4 ++--
js/src/views/Account/account.js | 6 +++---
19 files changed, 8 insertions(+), 8 deletions(-)
rename js/src/modals/{SMSVerification => Verification}/Done/done.css (100%)
rename js/src/modals/{SMSVerification => Verification}/Done/done.js (100%)
rename js/src/modals/{SMSVerification => Verification}/Done/index.js (100%)
rename js/src/modals/{SMSVerification => Verification}/GatherData/gatherData.css (100%)
rename js/src/modals/{SMSVerification => Verification}/GatherData/gatherData.js (100%)
rename js/src/modals/{SMSVerification => Verification}/GatherData/index.js (100%)
rename js/src/modals/{SMSVerification => Verification}/QueryCode/index.js (100%)
rename js/src/modals/{SMSVerification => Verification}/QueryCode/queryCode.js (100%)
rename js/src/modals/{SMSVerification => Verification}/SendConfirmation/index.js (100%)
rename js/src/modals/{SMSVerification => Verification}/SendConfirmation/sendConfirmation.css (100%)
rename js/src/modals/{SMSVerification => Verification}/SendConfirmation/sendConfirmation.js (100%)
rename js/src/modals/{SMSVerification => Verification}/SendRequest/index.js (100%)
rename js/src/modals/{SMSVerification => Verification}/SendRequest/sendRequest.css (100%)
rename js/src/modals/{SMSVerification => Verification}/SendRequest/sendRequest.js (100%)
rename js/src/modals/{SMSVerification => Verification}/index.js (94%)
rename js/src/modals/{SMSVerification => Verification}/store.js (100%)
rename js/src/modals/{SMSVerification/SMSVerification.js => Verification/verification.js} (97%)
diff --git a/js/src/modals/SMSVerification/Done/done.css b/js/src/modals/Verification/Done/done.css
similarity index 100%
rename from js/src/modals/SMSVerification/Done/done.css
rename to js/src/modals/Verification/Done/done.css
diff --git a/js/src/modals/SMSVerification/Done/done.js b/js/src/modals/Verification/Done/done.js
similarity index 100%
rename from js/src/modals/SMSVerification/Done/done.js
rename to js/src/modals/Verification/Done/done.js
diff --git a/js/src/modals/SMSVerification/Done/index.js b/js/src/modals/Verification/Done/index.js
similarity index 100%
rename from js/src/modals/SMSVerification/Done/index.js
rename to js/src/modals/Verification/Done/index.js
diff --git a/js/src/modals/SMSVerification/GatherData/gatherData.css b/js/src/modals/Verification/GatherData/gatherData.css
similarity index 100%
rename from js/src/modals/SMSVerification/GatherData/gatherData.css
rename to js/src/modals/Verification/GatherData/gatherData.css
diff --git a/js/src/modals/SMSVerification/GatherData/gatherData.js b/js/src/modals/Verification/GatherData/gatherData.js
similarity index 100%
rename from js/src/modals/SMSVerification/GatherData/gatherData.js
rename to js/src/modals/Verification/GatherData/gatherData.js
diff --git a/js/src/modals/SMSVerification/GatherData/index.js b/js/src/modals/Verification/GatherData/index.js
similarity index 100%
rename from js/src/modals/SMSVerification/GatherData/index.js
rename to js/src/modals/Verification/GatherData/index.js
diff --git a/js/src/modals/SMSVerification/QueryCode/index.js b/js/src/modals/Verification/QueryCode/index.js
similarity index 100%
rename from js/src/modals/SMSVerification/QueryCode/index.js
rename to js/src/modals/Verification/QueryCode/index.js
diff --git a/js/src/modals/SMSVerification/QueryCode/queryCode.js b/js/src/modals/Verification/QueryCode/queryCode.js
similarity index 100%
rename from js/src/modals/SMSVerification/QueryCode/queryCode.js
rename to js/src/modals/Verification/QueryCode/queryCode.js
diff --git a/js/src/modals/SMSVerification/SendConfirmation/index.js b/js/src/modals/Verification/SendConfirmation/index.js
similarity index 100%
rename from js/src/modals/SMSVerification/SendConfirmation/index.js
rename to js/src/modals/Verification/SendConfirmation/index.js
diff --git a/js/src/modals/SMSVerification/SendConfirmation/sendConfirmation.css b/js/src/modals/Verification/SendConfirmation/sendConfirmation.css
similarity index 100%
rename from js/src/modals/SMSVerification/SendConfirmation/sendConfirmation.css
rename to js/src/modals/Verification/SendConfirmation/sendConfirmation.css
diff --git a/js/src/modals/SMSVerification/SendConfirmation/sendConfirmation.js b/js/src/modals/Verification/SendConfirmation/sendConfirmation.js
similarity index 100%
rename from js/src/modals/SMSVerification/SendConfirmation/sendConfirmation.js
rename to js/src/modals/Verification/SendConfirmation/sendConfirmation.js
diff --git a/js/src/modals/SMSVerification/SendRequest/index.js b/js/src/modals/Verification/SendRequest/index.js
similarity index 100%
rename from js/src/modals/SMSVerification/SendRequest/index.js
rename to js/src/modals/Verification/SendRequest/index.js
diff --git a/js/src/modals/SMSVerification/SendRequest/sendRequest.css b/js/src/modals/Verification/SendRequest/sendRequest.css
similarity index 100%
rename from js/src/modals/SMSVerification/SendRequest/sendRequest.css
rename to js/src/modals/Verification/SendRequest/sendRequest.css
diff --git a/js/src/modals/SMSVerification/SendRequest/sendRequest.js b/js/src/modals/Verification/SendRequest/sendRequest.js
similarity index 100%
rename from js/src/modals/SMSVerification/SendRequest/sendRequest.js
rename to js/src/modals/Verification/SendRequest/sendRequest.js
diff --git a/js/src/modals/SMSVerification/index.js b/js/src/modals/Verification/index.js
similarity index 94%
rename from js/src/modals/SMSVerification/index.js
rename to js/src/modals/Verification/index.js
index d9b0990db..9c29a7165 100644
--- a/js/src/modals/SMSVerification/index.js
+++ b/js/src/modals/Verification/index.js
@@ -14,4 +14,4 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see .
-export default from './SMSVerification';
+export default from './verification';
diff --git a/js/src/modals/SMSVerification/store.js b/js/src/modals/Verification/store.js
similarity index 100%
rename from js/src/modals/SMSVerification/store.js
rename to js/src/modals/Verification/store.js
diff --git a/js/src/modals/SMSVerification/SMSVerification.js b/js/src/modals/Verification/verification.js
similarity index 97%
rename from js/src/modals/SMSVerification/SMSVerification.js
rename to js/src/modals/Verification/verification.js
index 86f027a52..65447c4f9 100644
--- a/js/src/modals/SMSVerification/SMSVerification.js
+++ b/js/src/modals/Verification/verification.js
@@ -37,7 +37,7 @@ import SendConfirmation from './SendConfirmation';
import Done from './Done';
@observer
-export default class SMSVerification extends Component {
+export default class Verification extends Component {
static propTypes = {
store: PropTypes.any.isRequired,
account: PropTypes.string.isRequired,
@@ -54,7 +54,7 @@ export default class SMSVerification extends Component {
}
render () {
- const phase = SMSVerification.phases[this.props.store.step];
+ const phase = Verification.phases[this.props.store.step];
const { error, isStepValid } = this.props.store;
return (
diff --git a/js/src/modals/index.js b/js/src/modals/index.js
index 0f0844e40..1daee8663 100644
--- a/js/src/modals/index.js
+++ b/js/src/modals/index.js
@@ -24,7 +24,7 @@ import EditMeta from './EditMeta';
import ExecuteContract from './ExecuteContract';
import FirstRun from './FirstRun';
import Shapeshift from './Shapeshift';
-import SMSVerification from './SMSVerification';
+import Verification from './Verification';
import Transfer from './Transfer';
import PasswordManager from './PasswordManager';
import SaveContract from './SaveContract';
@@ -42,7 +42,7 @@ export {
ExecuteContract,
FirstRun,
Shapeshift,
- SMSVerification,
+ Verification,
Transfer,
PasswordManager,
LoadContract,
diff --git a/js/src/views/Account/account.js b/js/src/views/Account/account.js
index 98b0a5e97..1fd654fde 100644
--- a/js/src/views/Account/account.js
+++ b/js/src/views/Account/account.js
@@ -23,7 +23,7 @@ import ContentSend from 'material-ui/svg-icons/content/send';
import LockIcon from 'material-ui/svg-icons/action/lock';
import VerifyIcon from 'material-ui/svg-icons/action/verified-user';
-import { EditMeta, DeleteAccount, Shapeshift, SMSVerification, Transfer, PasswordManager } from '~/modals';
+import { EditMeta, DeleteAccount, Shapeshift, Verification, Transfer, PasswordManager } from '~/modals';
import { Actionbar, Button, Page } from '~/ui';
import shapeshiftBtn from '../../../assets/images/shapeshift-btn.png';
@@ -32,7 +32,7 @@ import Header from './Header';
import Transactions from './Transactions';
import { setVisibleAccounts } from '~/redux/providers/personalActions';
-import VerificationStore from '~/modals/SMSVerification/store';
+import VerificationStore from '~/modals/Verification/store';
import styles from './account.css';
@@ -228,7 +228,7 @@ class Account extends Component {
const { address } = this.props.params;
return (
-
From 1672cbad7be46f49af7e2b0b1eaf66b08f9a95a4 Mon Sep 17 00:00:00 2001
From: Jannis R
Date: Tue, 6 Dec 2016 16:09:02 +0100
Subject: [PATCH 03/21] factor out SMS-specific logic
---
.../Verification/SendRequest/sendRequest.js | 6 +-
js/src/modals/Verification/sms-store.js | 66 +++++++++++++++++++
js/src/modals/Verification/store.js | 55 +++-------------
js/src/modals/Verification/verification.js | 8 +--
js/src/views/Account/account.js | 2 +-
5 files changed, 83 insertions(+), 54 deletions(-)
create mode 100644 js/src/modals/Verification/sms-store.js
diff --git a/js/src/modals/Verification/SendRequest/sendRequest.js b/js/src/modals/Verification/SendRequest/sendRequest.js
index 933de9265..41dc7c06c 100644
--- a/js/src/modals/Verification/SendRequest/sendRequest.js
+++ b/js/src/modals/Verification/SendRequest/sendRequest.js
@@ -19,7 +19,7 @@ import React, { Component, PropTypes } from 'react';
import { nullableProptype } from '~/util/proptypes';
import TxHash from '~/ui/TxHash';
import {
- POSTING_REQUEST, POSTED_REQUEST, REQUESTING_SMS
+ POSTING_REQUEST, POSTED_REQUEST, REQUESTING_CODE
} from '../store';
import styles from './sendRequest.css';
@@ -45,9 +45,9 @@ export default class SendRequest extends Component {
);
- case REQUESTING_SMS:
+ case REQUESTING_CODE:
return (
- Requesting an SMS from the Parity server and waiting for the puzzle to be put into the contract.
+ Requesting a code from the Parity server and waiting for the puzzle to be put into the contract.
);
default:
diff --git a/js/src/modals/Verification/sms-store.js b/js/src/modals/Verification/sms-store.js
new file mode 100644
index 000000000..58b79ebfb
--- /dev/null
+++ b/js/src/modals/Verification/sms-store.js
@@ -0,0 +1,66 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see .
+
+import { observable, computed, action } from 'mobx';
+import phone from 'phoneformat.js';
+
+import VerificationStore, {
+ LOADING, QUERY_DATA, QUERY_CODE, POSTED_CONFIRMATION, DONE
+} from './store';
+import { postToServer } from '../../3rdparty/sms-verification';
+
+export default class SMSVerificationStore extends VerificationStore {
+ @observable number = '';
+
+ @computed get isNumberValid () {
+ return phone.isValidNumber(this.number);
+ }
+
+ @computed get isStepValid () {
+ if (this.step === DONE) {
+ return true;
+ }
+ if (this.error) {
+ return false;
+ }
+
+ switch (this.step) {
+ case LOADING:
+ return this.contract && this.fee && this.isVerified !== null && this.hasRequested !== null;
+ case QUERY_DATA:
+ return this.isNumberValid && this.consentGiven;
+ case QUERY_CODE:
+ return this.requestTx && this.isCodeValid === true;
+ case POSTED_CONFIRMATION:
+ return !!this.confirmationTx;
+ default:
+ return false;
+ }
+ }
+
+ constructor (api, account, isTestnet) {
+ return super(api, account, isTestnet, 'smsverification');
+ }
+
+ @action setNumber = (number) => {
+ this.number = number;
+ }
+
+ requestCode = () => {
+ const { number, account, isTestnet } = this;
+ return postToServer({ number, address: account }, isTestnet);
+ }
+}
diff --git a/js/src/modals/Verification/store.js b/js/src/modals/Verification/store.js
index 279329ca5..f8542786b 100644
--- a/js/src/modals/Verification/store.js
+++ b/js/src/modals/Verification/store.js
@@ -14,14 +14,11 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see .
-import { observable, computed, autorun, action } from 'mobx';
-import phone from 'phoneformat.js';
+import { observable, autorun, action } from 'mobx';
import { sha3 } from '~/api/util/sha3';
-
import Contracts from '~/contracts';
import { checkIfVerified, checkIfRequested, awaitPuzzle } from '~/contracts/verification';
-import { postToServer } from '../../3rdparty/sms-verification';
import checkIfTxFailed from '../../util/check-if-tx-failed';
import waitForConfirmations from '../../util/wait-for-block-confirmations';
@@ -29,7 +26,7 @@ export const LOADING = 'fetching-contract';
export const QUERY_DATA = 'query-data';
export const POSTING_REQUEST = 'posting-request';
export const POSTED_REQUEST = 'posted-request';
-export const REQUESTING_SMS = 'requesting-sms';
+export const REQUESTING_CODE = 'requesting-code';
export const QUERY_CODE = 'query-code';
export const POSTING_CONFIRMATION = 'posting-confirmation';
export const POSTED_CONFIRMATION = 'posted-confirmation';
@@ -44,45 +41,18 @@ export default class VerificationStore {
@observable isVerified = null;
@observable hasRequested = null;
@observable consentGiven = false;
- @observable number = '';
@observable requestTx = null;
@observable code = '';
@observable isCodeValid = null;
@observable confirmationTx = null;
- @computed get isNumberValid () {
- return phone.isValidNumber(this.number);
- }
-
- @computed get isStepValid () {
- if (this.step === DONE) {
- return true;
- }
- if (this.error) {
- return false;
- }
-
- switch (this.step) {
- case LOADING:
- return this.contract && this.fee && this.isVerified !== null && this.hasRequested !== null;
- case QUERY_DATA:
- return this.isNumberValid && this.consentGiven;
- case QUERY_CODE:
- return this.requestTx && this.isCodeValid === true;
- case POSTED_CONFIRMATION:
- return !!this.confirmationTx;
- default:
- return false;
- }
- }
-
- constructor (api, account, isTestnet) {
+ constructor (api, account, isTestnet, name) {
this.api = api;
this.account = account;
this.isTestnet = isTestnet;
this.step = LOADING;
- Contracts.create(api).registry.getContract('smsverification')
+ Contracts.create(api).registry.getContract(name)
.then((contract) => {
this.contract = contract;
this.load();
@@ -93,7 +63,7 @@ export default class VerificationStore {
autorun(() => {
if (this.error) {
- console.error('sms verification: ' + this.error);
+ console.error('verification: ' + this.error);
}
});
}
@@ -136,10 +106,6 @@ export default class VerificationStore {
});
}
- @action setNumber = (number) => {
- this.number = number;
- }
-
@action setConsentGiven = (consentGiven) => {
this.consentGiven = consentGiven;
}
@@ -168,7 +134,7 @@ export default class VerificationStore {
}
@action sendRequest = () => {
- const { api, account, contract, fee, number, hasRequested } = this;
+ const { api, account, contract, fee, hasRequested } = this;
const request = contract.functions.find((fn) => fn.name === 'request');
const options = { from: account, value: fee.toString() };
@@ -201,18 +167,15 @@ export default class VerificationStore {
chain
.then(() => {
- return api.parity.netChain();
- })
- .then((chain) => {
- this.step = REQUESTING_SMS;
- return postToServer({ number, address: account }, this.isTestnet);
+ this.step = REQUESTING_CODE;
+ return this.requestCode();
})
.then(() => awaitPuzzle(api, contract, account))
.then(() => {
this.step = QUERY_CODE;
})
.catch((err) => {
- this.error = 'Failed to request a confirmation SMS: ' + err.message;
+ this.error = 'Failed to request a confirmation code: ' + err.message;
});
}
diff --git a/js/src/modals/Verification/verification.js b/js/src/modals/Verification/verification.js
index 65447c4f9..b05ed353a 100644
--- a/js/src/modals/Verification/verification.js
+++ b/js/src/modals/Verification/verification.js
@@ -25,7 +25,7 @@ import {
LOADING,
QUERY_DATA,
POSTING_REQUEST, POSTED_REQUEST,
- REQUESTING_SMS, QUERY_CODE,
+ REQUESTING_CODE, QUERY_CODE,
POSTING_CONFIRMATION, POSTED_CONFIRMATION,
DONE
} from './store';
@@ -47,7 +47,7 @@ export default class Verification extends Component {
static phases = { // mapping (store steps -> steps)
[LOADING]: 0,
[QUERY_DATA]: 1,
- [POSTING_REQUEST]: 2, [POSTED_REQUEST]: 2, [REQUESTING_SMS]: 2,
+ [POSTING_REQUEST]: 2, [POSTED_REQUEST]: 2, [REQUESTING_CODE]: 2,
[QUERY_CODE]: 3,
[POSTING_CONFIRMATION]: 4, [POSTED_CONFIRMATION]: 4,
[DONE]: 5
@@ -60,7 +60,7 @@ export default class Verification extends Component {
return (
Loading SMS Verification.
+ Loading Verification.
);
case 1:
diff --git a/js/src/views/Account/account.js b/js/src/views/Account/account.js
index 1fd654fde..240ca2f9b 100644
--- a/js/src/views/Account/account.js
+++ b/js/src/views/Account/account.js
@@ -32,7 +32,7 @@ import Header from './Header';
import Transactions from './Transactions';
import { setVisibleAccounts } from '~/redux/providers/personalActions';
-import VerificationStore from '~/modals/Verification/store';
+import VerificationStore from '~/modals/Verification/sms-store';
import styles from './account.css';
From 1ac3421f3327778306c21997e9acdcecde32ad6d Mon Sep 17 00:00:00 2001
From: Jannis R
Date: Tue, 6 Dec 2016 17:16:54 +0100
Subject: [PATCH 04/21] step to select verification method
---
js/src/modals/Verification/verification.js | 109 ++++++++++++++++-----
js/src/views/Account/account.js | 29 ++++--
2 files changed, 105 insertions(+), 33 deletions(-)
diff --git a/js/src/modals/Verification/verification.js b/js/src/modals/Verification/verification.js
index b05ed353a..5982933a9 100644
--- a/js/src/modals/Verification/verification.js
+++ b/js/src/modals/Verification/verification.js
@@ -20,6 +20,13 @@ import DoneIcon from 'material-ui/svg-icons/action/done-all';
import CancelIcon from 'material-ui/svg-icons/content/clear';
import { Button, IdentityIcon, Modal } from '~/ui';
+import RadioButtons from '~/ui/Form/RadioButtons';
+import { nullableProptype } from '~/util/proptypes';
+
+const methods = {
+ sms: { label: 'SMS Verification', key: 0, value: 'sms' },
+ email: { label: 'E-mail Verification', key: 1, value: 'email' }
+};
import {
LOADING,
@@ -39,23 +46,34 @@ import Done from './Done';
@observer
export default class Verification extends Component {
static propTypes = {
- store: PropTypes.any.isRequired,
+ store: nullableProptype(PropTypes.object).isRequired,
account: PropTypes.string.isRequired,
+ onSelectMethod: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired
}
static phases = { // mapping (store steps -> steps)
- [LOADING]: 0,
- [QUERY_DATA]: 1,
- [POSTING_REQUEST]: 2, [POSTED_REQUEST]: 2, [REQUESTING_CODE]: 2,
- [QUERY_CODE]: 3,
- [POSTING_CONFIRMATION]: 4, [POSTED_CONFIRMATION]: 4,
- [DONE]: 5
+ [LOADING]: 1,
+ [QUERY_DATA]: 2,
+ [POSTING_REQUEST]: 3, [POSTED_REQUEST]: 3, [REQUESTING_CODE]: 3,
+ [QUERY_CODE]: 4,
+ [POSTING_CONFIRMATION]: 5, [POSTED_CONFIRMATION]: 5,
+ [DONE]: 6
}
+ state = {
+ method: 'sms'
+ };
+
render () {
- const phase = Verification.phases[this.props.store.step];
- const { error, isStepValid } = this.props.store;
+ const { store } = this.props;
+ let phase = 0; let error = false; let isStepValid = true;
+
+ if (store) {
+ phase = Verification.phases[store.step];
+ error = store.error;
+ isStepValid = store.isStepValid;
+ }
return (
{ this.renderStep(phase, error) }
@@ -85,7 +103,7 @@ export default class Verification extends Component {
return ({ cancel }
);
}
- if (phase === 5) {
+ if (phase === 6) {
return (
{ cancel }
@@ -101,16 +119,23 @@ export default class Verification extends Component {
let action = () => {};
switch (phase) {
- case 1:
- action = store.sendRequest;
+ case 0:
+ action = () => {
+ const { onSelectMethod } = this.props;
+ const { method } = this.state;
+ onSelectMethod(method);
+ };
break;
case 2:
- action = store.queryCode;
+ action = store.sendRequest;
break;
case 3:
- action = store.sendConfirmation;
+ action = store.queryCode;
break;
case 4:
+ action = store.sendConfirmation;
+ break;
+ case 5:
action = store.done;
break;
}
@@ -133,6 +158,19 @@ export default class Verification extends Component {
return (
{ error }
);
}
+ if (phase === 0) {
+ const { method } = this.state;
+ const values = Object.values(methods);
+ const value = values.findIndex((v) => v.value === method);
+ return (
+
+ );
+ }
+
const {
step,
fee, number, isNumberValid, isVerified, hasRequested,
@@ -141,13 +179,34 @@ export default class Verification extends Component {
} = this.props.store;
switch (phase) {
- case 0:
+ case 1:
return (
Loading Verification.
);
- case 1:
- const { setNumber, setConsentGiven } = this.props.store;
+ case 2:
+ const { method } = this.state;
+ const { setConsentGiven } = this.props.store;
+
+ const fields = []
+ if (method === 'sms') {
+ fields.push({
+ key: 'number',
+ label: 'phone number in international format',
+ hint: 'the SMS will be sent to this number',
+ error: this.props.store.isNumberValid ? null : 'invalid number',
+ onChange: this.props.store.setNumber
+ });
+ } else if (method === 'email') {
+ fields.push({
+ key: 'email',
+ label: 'email address',
+ hint: 'the code will be sent to this address',
+ error: this.props.store.isEmailValid ? null : 'invalid email',
+ onChange: this.props.store.setEmail
+ });
+ }
+
return (
);
- case 2:
+ case 3:
return (
);
- case 3:
+ case 4:
return (
);
- case 4:
+ case 5:
return (
);
- case 5:
+ case 6:
return (
);
@@ -183,4 +242,8 @@ export default class Verification extends Component {
return null;
}
}
+
+ selectMethod = (choice, i) => {
+ this.setState({ method: choice.value });
+ }
}
diff --git a/js/src/views/Account/account.js b/js/src/views/Account/account.js
index 240ca2f9b..3f262bce4 100644
--- a/js/src/views/Account/account.js
+++ b/js/src/views/Account/account.js
@@ -32,7 +32,8 @@ import Header from './Header';
import Transactions from './Transactions';
import { setVisibleAccounts } from '~/redux/providers/personalActions';
-import VerificationStore from '~/modals/Verification/sms-store';
+import SMSVerificationStore from '~/modals/Verification/sms-store';
+import EmailVerificationStore from '~/modals/Verification/email-store';
import styles from './account.css';
@@ -72,15 +73,6 @@ class Account extends Component {
if (prevAddress !== nextAddress) {
this.setVisibleAccounts(nextProps);
}
-
- const { isTestnet } = nextProps;
- if (typeof isTestnet === 'boolean' && !this.state.verificationStore) {
- const { api } = this.context;
- const { address } = nextProps.params;
- this.setState({
- verificationStore: new VerificationStore(api, address, isTestnet)
- });
- }
}
componentWillUnmount () {
@@ -230,6 +222,7 @@ class Account extends Component {
return (
);
@@ -303,6 +296,22 @@ class Account extends Component {
this.setState({ showVerificationDialog: true });
}
+ selectVerificationMethod = (name) => {
+ const { isTestnet } = this.props;
+ if (typeof isTestnet !== 'boolean' || this.state.verificationStore) return;
+
+ const { api } = this.context;
+ const { address } = this.props.params;
+
+ let verificationStore = null;
+ if (name === 'sms') {
+ verificationStore = new SMSVerificationStore(api, address, isTestnet);
+ } else if (name === 'email') {
+ verificationStore = new EmailVerificationStore(api, address, isTestnet);
+ }
+ this.setState({ verificationStore });
+ }
+
onVerificationClose = () => {
this.setState({ showVerificationDialog: false });
}
From d3fd71d9534ac540d72f7d8263e13a5e8461fa53 Mon Sep 17 00:00:00 2001
From: Jannis R
Date: Tue, 6 Dec 2016 17:45:34 +0100
Subject: [PATCH 05/21] add email-specific contract, helpers, store
---
js/src/3rdparty/email-verification/index.js | 53 +++++++++++++++
js/src/3rdparty/email-verification/styles.css | 20 ++++++
js/src/3rdparty/sms-verification/index.js | 13 ++++
js/src/3rdparty/sms-verification/styles.css | 20 ++++++
js/src/contracts/abi/email-verification.json | 1 +
js/src/contracts/abi/index.js | 2 +
js/src/modals/Verification/email-store.js | 66 +++++++++++++++++++
7 files changed, 175 insertions(+)
create mode 100644 js/src/3rdparty/email-verification/index.js
create mode 100644 js/src/3rdparty/email-verification/styles.css
create mode 100644 js/src/3rdparty/sms-verification/styles.css
create mode 100644 js/src/contracts/abi/email-verification.json
create mode 100644 js/src/modals/Verification/email-store.js
diff --git a/js/src/3rdparty/email-verification/index.js b/js/src/3rdparty/email-verification/index.js
new file mode 100644
index 000000000..5f4885f3b
--- /dev/null
+++ b/js/src/3rdparty/email-verification/index.js
@@ -0,0 +1,53 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see .
+
+import { stringify } from 'querystring';
+import React from 'react';
+
+import styles from './styles.css';
+
+export const howItWorks = (
+
+
The following steps will let you prove that you control both an account and an e-mail address.
+
+ - You send a verification request to a specific contract.
+ - Our server puts a puzzle into this contract.
+ - The code you receive via e-mail is the solution to this puzzle.
+
+
+);
+
+export const termsOfService = (
+
+);
+
+export const postToServer = (query, isTestnet = false) => {
+ const port = isTestnet ? 28443 : 18443;
+ query = stringify(query);
+ return fetch(`https://email-verification.parity.io:${port}/?` + query, {
+ method: 'POST', mode: 'cors', cache: 'no-store'
+ })
+ .then((res) => {
+ return res.json().then((data) => {
+ if (res.ok) {
+ return data.message;
+ }
+ throw new Error(data.message || 'unknown error');
+ });
+ });
+};
diff --git a/js/src/3rdparty/email-verification/styles.css b/js/src/3rdparty/email-verification/styles.css
new file mode 100644
index 000000000..daa4c605c
--- /dev/null
+++ b/js/src/3rdparty/email-verification/styles.css
@@ -0,0 +1,20 @@
+/* Copyright 2015, 2016 Ethcore (UK) Ltd.
+/* This file is part of Parity.
+/*
+/* Parity is free software: you can redistribute it and/or modify
+/* it under the terms of the GNU General Public License as published by
+/* the Free Software Foundation, either version 3 of the License, or
+/* (at your option) any later version.
+/*
+/* Parity is distributed in the hope that it will be useful,
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+/* GNU General Public License for more details.
+/*
+/* You should have received a copy of the GNU General Public License
+/* along with Parity. If not, see .
+*/
+
+.list li {
+ padding: .1em 0;
+}
diff --git a/js/src/3rdparty/sms-verification/index.js b/js/src/3rdparty/sms-verification/index.js
index c50b2331a..46faf084c 100644
--- a/js/src/3rdparty/sms-verification/index.js
+++ b/js/src/3rdparty/sms-verification/index.js
@@ -17,6 +17,19 @@
import { stringify } from 'querystring';
import React from 'react';
+import styles from './styles.css';
+
+export const howItWorks = (
+
+
The following steps will let you prove that you control both an account and a phone number.
+
+ - You send a verification request to a specific contract.
+ - Our server puts a puzzle into this contract.
+ - The code you receive via SMS is the solution to this puzzle.
+
+
+);
+
export const termsOfService = (
- This privacy notice relates to your use of the Parity SMS verification service. We take your privacy seriously and deal in an honest, direct and transparent way when it comes to your data.
diff --git a/js/src/3rdparty/sms-verification/styles.css b/js/src/3rdparty/sms-verification/styles.css
new file mode 100644
index 000000000..daa4c605c
--- /dev/null
+++ b/js/src/3rdparty/sms-verification/styles.css
@@ -0,0 +1,20 @@
+/* Copyright 2015, 2016 Ethcore (UK) Ltd.
+/* This file is part of Parity.
+/*
+/* Parity is free software: you can redistribute it and/or modify
+/* it under the terms of the GNU General Public License as published by
+/* the Free Software Foundation, either version 3 of the License, or
+/* (at your option) any later version.
+/*
+/* Parity is distributed in the hope that it will be useful,
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+/* GNU General Public License for more details.
+/*
+/* You should have received a copy of the GNU General Public License
+/* along with Parity. If not, see .
+*/
+
+.list li {
+ padding: .1em 0;
+}
diff --git a/js/src/contracts/abi/email-verification.json b/js/src/contracts/abi/email-verification.json
new file mode 100644
index 000000000..baa6db483
--- /dev/null
+++ b/js/src/contracts/abi/email-verification.json
@@ -0,0 +1 @@
+[{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"reverse","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_who","type":"address"},{"name":"_puzzle","type":"bytes32"},{"name":"_emailHash","type":"bytes32"}],"name":"puzzle","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_emailHash","type":"bytes32"}],"name":"request","outputs":[],"payable":true,"type":"function"},{"constant":false,"inputs":[{"name":"_new","type":"uint256"}],"name":"setFee","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_code","type":"bytes32"}],"name":"confirm","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"drain","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getUint","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"}],"name":"certified","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"get","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"},{"indexed":false,"name":"emailHash","type":"bytes32"}],"name":"Requested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"},{"indexed":true,"name":"emailHash","type":"bytes32"},{"indexed":false,"name":"puzzle","type":"bytes32"}],"name":"Puzzled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"}],"name":"Confirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"}],"name":"Revoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}]
\ No newline at end of file
diff --git a/js/src/contracts/abi/index.js b/js/src/contracts/abi/index.js
index f15765b1a..c8cb851dd 100644
--- a/js/src/contracts/abi/index.js
+++ b/js/src/contracts/abi/index.js
@@ -19,6 +19,7 @@ import basiccoin from './basiccoin.json';
import basiccoinmanager from './basiccoinmanager.json';
import dappreg from './dappreg.json';
import eip20 from './eip20.json';
+import emailverification from './email-verification.json';
import gavcoin from './gavcoin.json';
import githubhint from './githubhint.json';
import owned from './owned.json';
@@ -34,6 +35,7 @@ export {
basiccoinmanager,
dappreg,
eip20,
+ emailverification,
gavcoin,
githubhint,
owned,
diff --git a/js/src/modals/Verification/email-store.js b/js/src/modals/Verification/email-store.js
new file mode 100644
index 000000000..14179cfe2
--- /dev/null
+++ b/js/src/modals/Verification/email-store.js
@@ -0,0 +1,66 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see .
+
+import { observable, computed, action } from 'mobx';
+
+import VerificationStore, {
+ LOADING, QUERY_DATA, QUERY_CODE, POSTED_CONFIRMATION, DONE
+} from './store';
+import { postToServer } from '../../3rdparty/email-verification';
+
+export default class EmailVerificationStore extends VerificationStore {
+ @observable email = '';
+
+ @computed get isEmailValid () {
+ // See https://davidcel.is/posts/stop-validating-email-addresses-with-regex/
+ return this.email && this.email.indexOf('@') >= 0;
+ }
+
+ @computed get isStepValid () {
+ if (this.step === DONE) {
+ return true;
+ }
+ if (this.error) {
+ return false;
+ }
+
+ switch (this.step) {
+ case LOADING:
+ return this.contract && this.fee && this.isVerified !== null && this.hasRequested !== null;
+ case QUERY_DATA:
+ return this.isEmailValid && this.consentGiven;
+ case QUERY_CODE:
+ return this.requestTx && this.isCodeValid === true;
+ case POSTED_CONFIRMATION:
+ return !!this.confirmationTx;
+ default:
+ return false;
+ }
+ }
+
+ constructor (api, account, isTestnet) {
+ return super(api, account, isTestnet, 'emailverification');
+ }
+
+ @action setEmail = (email) => {
+ this.email = email;
+ }
+
+ requestCode = () => {
+ const { email, account, isTestnet } = this;
+ return postToServer({ email, address: account }, isTestnet);
+ }
+}
From 052f9258a5f1c596adac6e3b2ab490032303da5b Mon Sep 17 00:00:00 2001
From: Jannis R
Date: Wed, 7 Dec 2016 11:53:48 +0100
Subject: [PATCH 06/21] pass fields to query into GatherData
---
.../Verification/GatherData/gatherData.css | 4 --
.../Verification/GatherData/gatherData.js | 52 +++++++++++--------
js/src/modals/Verification/verification.js | 8 +--
3 files changed, 33 insertions(+), 31 deletions(-)
diff --git a/js/src/modals/Verification/GatherData/gatherData.css b/js/src/modals/Verification/GatherData/gatherData.css
index 680986981..13563b6a5 100644
--- a/js/src/modals/Verification/GatherData/gatherData.css
+++ b/js/src/modals/Verification/GatherData/gatherData.css
@@ -15,10 +15,6 @@
/* along with Parity. If not, see .
*/
-.list li {
- padding: .1em 0;
-}
-
.spacing {
margin-top: 1.5em;
}
diff --git a/js/src/modals/Verification/GatherData/gatherData.js b/js/src/modals/Verification/GatherData/gatherData.js
index f5f09578e..24f870fc6 100644
--- a/js/src/modals/Verification/GatherData/gatherData.js
+++ b/js/src/modals/Verification/GatherData/gatherData.js
@@ -25,41 +25,31 @@ import { fromWei } from '~/api/util/wei';
import { Form, Input } from '~/ui';
import { nullableProptype } from '~/util/proptypes';
-import { termsOfService } from '../../../3rdparty/sms-verification';
+import * as sms from '../../../3rdparty/sms-verification';
+import * as email from '../../../3rdparty/email-verification';
import styles from './gatherData.css';
export default class GatherData extends Component {
static propTypes = {
fee: React.PropTypes.instanceOf(BigNumber),
- isNumberValid: PropTypes.bool.isRequired,
+ method: PropTypes.string.isRequired,
+ fields: PropTypes.array.isRequired,
isVerified: nullableProptype(PropTypes.bool.isRequired),
hasRequested: nullableProptype(PropTypes.bool.isRequired),
- setNumber: PropTypes.func.isRequired,
setConsentGiven: PropTypes.func.isRequired
}
render () {
- const { isNumberValid, isVerified } = this.props;
+ const { method, isVerified } = this.props;
+ const { howItWorks, termsOfService } = method === 'email' ? email : sms;
return (