Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

sms verification modal #3336

Merged
merged 52 commits into from
Nov 17, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
7cb724b
put SMS verification into action bar
derhuerst Nov 3, 2016
f96e693
SMS verification modal
derhuerst Nov 3, 2016
fc76fa9
sms verification: basic stepper
derhuerst Nov 3, 2016
1a24540
query phone number & consent
derhuerst Nov 3, 2016
435d3c2
SendRequest -> GatherData
derhuerst Nov 7, 2016
14da2d2
sms verification: check if certified
derhuerst Nov 7, 2016
4c199ef
sms verification: collect data
derhuerst Nov 7, 2016
89a2917
boilerplate for third step
derhuerst Nov 7, 2016
d0d737d
sms verification: post request transaction
derhuerst Nov 8, 2016
3ef54f9
sms verification: wait for tx confirmations
derhuerst Nov 8, 2016
4931381
txHash component: add maxConfirmations prop
derhuerst Nov 8, 2016
a56a1d3
sms verification: request SMS
derhuerst Nov 8, 2016
ebf742f
sms verification: update contract address & ABI
derhuerst Nov 8, 2016
e84531f
sms verification: refactor contract call
derhuerst Nov 9, 2016
e7113e7
sms verification: show fee in consent form
derhuerst Nov 9, 2016
7996ac4
sms verification: polish UI, fix linting issues :shirt:
derhuerst Nov 9, 2016
f08e2a4
sms verification: query code
derhuerst Nov 9, 2016
a42140e
sms verification: send confirmation tx
derhuerst Nov 9, 2016
01cf88d
sms verification: merge step 1 & 2
derhuerst Nov 9, 2016
8028c0f
sms verification: check if already requested
derhuerst Nov 9, 2016
cde9f45
sms verification: polish UI
derhuerst Nov 9, 2016
89c1d9c
merge master into sms-verification-modal
derhuerst Nov 9, 2016
ac80276
sms verification: refactor checks & confirmation
derhuerst Nov 10, 2016
2309e53
sms verification: polish UI, linting issues :shirt:
derhuerst Nov 10, 2016
afdda48
sms verification: polish UI
derhuerst Nov 10, 2016
bd839d0
sms verification: polish UI, linting issues :shirt:
derhuerst Nov 10, 2016
01f1490
merge master into sms-verification-modal
derhuerst Nov 10, 2016
8db3414
Merge branch 'master' into sms-verification-modal
gavofyork Nov 14, 2016
1e696c4
[ci skip] js-precompiled 20161113-131228
jacogr Nov 13, 2016
594bd35
[ci skip] js-precompiled 20161113-131856
jacogr Nov 13, 2016
8ce362b
sms verification: add terms of service
derhuerst Nov 14, 2016
b1fcee7
sms verification: less block confirmations
derhuerst Nov 14, 2016
9df0d33
merge master into sms-verification-modal
derhuerst Nov 14, 2016
b5560d2
sms verification: pull out postToVerificationServer
derhuerst Nov 14, 2016
8ef9fff
sms verification: put process into MobX store
derhuerst Nov 15, 2016
7198624
sms verification: make GatherData component dumb
derhuerst Nov 15, 2016
f48a341
sms verification: make SendRequest component dumb
derhuerst Nov 15, 2016
377c16c
sms verification: make QueryCode component dumb
derhuerst Nov 15, 2016
90df237
sms verification: make SendConfirmation component dumb
derhuerst Nov 15, 2016
bfcc8d3
sms verification: make Done component dumb
derhuerst Nov 15, 2016
3e879aa
sms verification: use Mobx store
derhuerst Nov 15, 2016
aa8fc55
sms verification: simplify code
derhuerst Nov 15, 2016
7a83fb8
merge master into sms-verification-modal
derhuerst Nov 15, 2016
8d4b1a3
sms verification: bugfixes :bug:
derhuerst Nov 15, 2016
da8c70f
sms verification: check if tx failed, minor UI fixes
derhuerst Nov 16, 2016
ed2b8e1
merge master into sms-verification-modal
derhuerst Nov 16, 2016
1344893
sms verification: fix styling :sparkles:
derhuerst Nov 17, 2016
a595260
merge master into sms-verification-modal
derhuerst Nov 17, 2016
3f0053f
sms verification: move helper functions
derhuerst Nov 17, 2016
fff8743
sms verification: fetch contract address from Registry
derhuerst Nov 17, 2016
179078d
sms verification: loading step
derhuerst Nov 17, 2016
4ae58f7
move nullable PropType helper
derhuerst Nov 17, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
"mobx-react": "^3.5.8",
"mobx-react-devtools": "^4.2.9",
"moment": "^2.14.1",
"phoneformat.js": "^1.0.3",
"qs": "^6.3.0",
"react": "^15.2.1",
"react-ace": "^4.0.0",
Expand Down
2 changes: 2 additions & 0 deletions js/src/contracts/abi/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import githubhint from './githubhint.json';
import owned from './owned.json';
import registry from './registry.json';
import signaturereg from './signaturereg.json';
import smsverification from './sms-verification.json';
import tokenreg from './tokenreg.json';
import wallet from './wallet.json';

Expand All @@ -36,6 +37,7 @@ export {
owned,
registry,
signaturereg,
smsverification,
tokenreg,
wallet
};
1 change: 1 addition & 0 deletions js/src/contracts/abi/sms-verification.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_who","type":"address"}],"name":"certify","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"request","outputs":[],"payable":true,"type":"function"},{"constant":false,"inputs":[{"name":"_who","type":"address"},{"name":"_puzzle","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":"_new","type":"uint256"}],"name":"setFee","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_who","type":"address"}],"name":"revoke","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":"delegate","outputs":[{"name":"","type":"address"}],"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":false,"inputs":[{"name":"_new","type":"address"}],"name":"setDelegate","outputs":[],"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"}],"name":"Requested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"},{"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"}]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add it to index.js for the contracts as well, import via that.

5 changes: 5 additions & 0 deletions js/src/contracts/contracts.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import Registry from './registry';
import SignatureReg from './signaturereg';
import TokenReg from './tokenreg';
import GithubHint from './githubhint';
import smsVerification from './sms-verification';

let instance = null;

Expand Down Expand Up @@ -54,6 +55,10 @@ export default class Contracts {
return this._githubhint;
}

get smsVerification () {
return smsVerification;
}

static create (api) {
return new Contracts(api);
}
Expand Down
52 changes: 52 additions & 0 deletions js/src/contracts/sms-verification.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// 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 <http://www.gnu.org/licenses/>.

import { stringify } from 'querystring';

export const checkIfVerified = (contract, account) => {
return contract.instance.certified.call({}, [account]);
};

export const checkIfRequested = (contract, account) => {
return new Promise((resolve, reject) => {
contract.subscribe('Requested', {
fromBlock: 0, toBlock: 'pending'
}, (err, logs) => {
if (err) {
return reject(err);
}
const e = logs.find((l) => {
return l.type === 'mined' && l.params.who && l.params.who.value === account;
});
resolve(e ? e.transactionHash : false);
});
});
};

export const postToServer = (query) => {
query = stringify(query);
return fetch('https://sms-verification.parity.io/?' + 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');
});
});
};
31 changes: 31 additions & 0 deletions js/src/modals/SMSVerification/Done/done.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
.spacing {
margin-top: 1.5em;
}

.container {
margin-top: .5em;
display: flex;
align-items: center;
}

.message {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small comment - just an extra line-break here would be good. (Consistency in this file and with the rest - and it doesn't hurt readability either.)

margin-top: 0;
margin-bottom: 0;
margin-left: .5em;
}
31 changes: 31 additions & 0 deletions js/src/modals/SMSVerification/Done/done.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// 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 <http://www.gnu.org/licenses/>.

import React, { Component } from 'react';
import SuccessIcon from 'material-ui/svg-icons/navigation/check';

import styles from './done.css';

export default class Done extends Component {
render () {
return (
<div className={ styles.container }>
<SuccessIcon />
<p className={ styles.message }>Congratulations, your account is verified!</p>
</div>
);
}
}
17 changes: 17 additions & 0 deletions js/src/modals/SMSVerification/Done/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// 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 <http://www.gnu.org/licenses/>.

export default from './done';
49 changes: 49 additions & 0 deletions js/src/modals/SMSVerification/GatherData/gatherData.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/* 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 <http://www.gnu.org/licenses/>.
*/

.list li {
padding: .1em 0;
}

.spacing {
margin-top: 1.5em;
}

.container {
margin-top: .5em;
display: flex;
align-items: center;
}
.message {
margin-top: 0;
margin-bottom: 0;
margin-left: .5em;
}

.terms {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could/should be nested -

.terms {
  ul {
  }

  li {
  }
}

line-height: 1.3;
opacity: .7;

ul {
padding-left: 1.5em;
}

li {
margin-top: .2em;
margin-bottom: .2em;
}
}
151 changes: 151 additions & 0 deletions js/src/modals/SMSVerification/GatherData/gatherData.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
// 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 <http://www.gnu.org/licenses/>.

import React, { Component, PropTypes } from 'react';
import nullable from '../../../util/nullable-proptype';
import BigNumber from 'bignumber.js';
import { Checkbox } from 'material-ui';
import InfoIcon from 'material-ui/svg-icons/action/info-outline';
import SuccessIcon from 'material-ui/svg-icons/navigation/check';
import ErrorIcon from 'material-ui/svg-icons/navigation/close';

import { fromWei } from '../../../api/util/wei';
import { Form, Input } from '../../../ui';

import terms from '../terms-of-service';
import styles from './gatherData.css';

export default class GatherData extends Component {
static propTypes = {
fee: React.PropTypes.instanceOf(BigNumber),
isNumberValid: PropTypes.bool.isRequired,
isVerified: nullable(PropTypes.bool.isRequired),
hasRequested: nullable(PropTypes.bool.isRequired),
setNumber: PropTypes.func.isRequired,
setConsentGiven: PropTypes.func.isRequired
}

render () {
const { isNumberValid, isVerified } = this.props;

return (
<Form>
<p>The following steps will let you prove that you control both an account and a phone number.</p>
<ol className={ styles.list }>
<li>You send a verification request to a specific contract.</li>
<li>Our server puts a puzzle into this contract.</li>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Real nitpick: Not convinced about the use of the word "puzzle" although we call it that way internally. (If I didn't know what we mean, I wouldn't be able to decipher it)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gavofyork @KenKappler

I'm not sure about the wording here. This is supposed to be a very brief description of how the process works.

Although the "Challenge Response" mechanism is well-known among programmers, I don't think it is among normal users. Still I want to give this indication here that the "verification" actually happens & is stored in the contract.

<li>The code you receive via SMS is the solution to this puzzle.</li>
</ol>
{ this.renderFee() }
{ this.renderCertified() }
{ this.renderRequested() }
<Input
label={ 'phone number' }
hint={ 'the SMS will be sent to this number' }
error={ isNumberValid ? null : 'invalid number' }
disabled={ isVerified }
onChange={ this.numberOnChange }
onSubmit={ this.numberOnSubmit }
/>
<Checkbox
className={ styles.spacing }
label={ 'I agree to the terms and conditions below.' }
disabled={ isVerified }
onCheck={ this.consentOnChange }
/>
<div className={ styles.terms }>{ terms }</div>
</Form>
);
}

renderFee () {
const { fee } = this.props;

if (!fee) {
return (<p>Fetching the fee…</p>);
}
return (
<div className={ styles.container }>
<InfoIcon />
<p className={ styles.message }>The fee is { fromWei(fee).toFixed(3) } ETH.</p>
</div>
);
}

renderCertified () {
const { isVerified } = this.props;

if (isVerified) {
return (
<div className={ styles.container }>
<ErrorIcon />
<p className={ styles.message }>Your account is already verified.</p>
</div>
);
} else if (isVerified === false) {
return (
<div className={ styles.container }>
<SuccessIcon />
<p className={ styles.message }>Your account is not verified yet.</p>
</div>
);
}
return (
<p className={ styles.message }>Checking if your account is verified…</p>
);
}

renderRequested () {
const { isVerified, hasRequested } = this.props;

// If the account is verified, don't show that it has requested verification.
if (isVerified) {
return null;
}

if (hasRequested) {
return (
<div className={ styles.container }>
<InfoIcon />
<p className={ styles.message }>You already requested verification.</p>
</div>
);
}
if (hasRequested === false) {
return (
<div className={ styles.container }>
<SuccessIcon />
<p className={ styles.message }>You did not request verification yet.</p>
</div>
);
}
return (
<p className={ styles.message }>Checking if you requested verification…</p>
);
}

numberOnSubmit = (value) => {
this.props.setNumber(value);
}

numberOnChange = (_, value) => {
this.props.setNumber(value);
}

consentOnChange = (_, consentGiven) => {
this.props.setConsentGiven(consentGiven);
}
}
17 changes: 17 additions & 0 deletions js/src/modals/SMSVerification/GatherData/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// 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 <http://www.gnu.org/licenses/>.

export default from './gatherData';
Loading