Skip to content

Commit

Permalink
304 phone verification and sign up flow refactoring (steemit#433)
Browse files Browse the repository at this point in the history
* add newrelic; rebuild shrinkwrap

* update shrinkwrap

* A few more react 15.3.1 to 15.3.2 (steemit#369)

* Confirm mobile (work in progress) steemit#304

* Update mobile verification with schema change. steemit#304

* Update telesign example config

* Progress with signature matching telesig ruby example. steemit#304

* Telesign signature fix (includs missing content type header).

* Cleanup warnings

* Able to verify a phone number in the UI

* Adds telesig verify block check and updating of mobile

* Enable mobile recaptcha.  SMS verify for FB users only.

* Fixed verification code length steemit#304

* add sign up progress bar; refactor submit_email page

* integrate phone verification into sign up process

* check for existing email

* check if phone number was already used

* show SignupProgressBar on create_account page; some refactoring

* work in progress

* move ip and email checks out of oath module

* Add confirm_email path in console log to help with testing. steemit#304

* Update email address is confirmation is re-sent. steemit#304

* polishing sign up flow

* update wording as per TeleSign's recomendations
  • Loading branch information
Valentine Zavgorodnev authored Oct 7, 2016
1 parent 861ca30 commit 60fcea8
Show file tree
Hide file tree
Showing 20 changed files with 734 additions and 226 deletions.
7 changes: 6 additions & 1 deletion app/assets/stylesheets/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ a, path, circle {
clear: right;
}

.clear-left {
clear: left;
}

.clear-both {
clear: both;
}
Expand Down Expand Up @@ -104,6 +108,7 @@ label {

@media print {
.noPrint {
display:none;
display: none;
}
}

15 changes: 7 additions & 8 deletions app/components/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import Header from 'app/components/modules/Header';
import LpFooter from 'app/components/modules/lp/LpFooter';
import user from 'app/redux/User';
import g from 'app/redux/GlobalReducer';
import { Link } from 'react-router';
import TopRightMenu from 'app/components/modules/TopRightMenu';
import { browserHistory } from 'react-router';
import classNames from 'classnames';
Expand All @@ -14,7 +13,8 @@ import CloseButton from 'react-foundation-components/lib/global/close-button';
import Dialogs from 'app/components/modules/Dialogs';
import Modals from 'app/components/modules/Modals';
import Icon from 'app/components/elements/Icon';
import {key_utils} from 'shared/ecc'
import {key_utils} from 'shared/ecc';
import MiniHeader from 'app/components/modules/MiniHeader';

class App extends React.Component {
constructor(props) {
Expand Down Expand Up @@ -45,7 +45,6 @@ class App extends React.Component {
const p = this.props;
const n = nextProps;
return p.location !== n.location ||
p.loading !== n.loading ||
p.visitor !== n.visitor ||
p.flash !== n.flash || this.state !== nextState;
}
Expand Down Expand Up @@ -74,9 +73,10 @@ class App extends React.Component {
}

render() {
const {location, params, children, loading, flash, showSignUp, new_visitor,
const {location, params, children, flash, showSignUp, new_visitor,
depositSteem, signup_bonus} = this.props;
const lp = false; //location.pathname === '/';
const miniHeader = location.pathname === '/create_account';
const params_keys = Object.keys(params);
const ip = location.pathname === '/' || (params_keys.length === 2 && params_keys[0] === 'order' && params_keys[1] === 'category');
const alert = this.props.error || flash.get('alert');
Expand Down Expand Up @@ -149,7 +149,8 @@ class App extends React.Component {
);
}

return <div className={'App' + (lp ? ' LP' : '') + (ip ? ' index-page' : '')} onMouseMove={this.onEntropyEvent}>
return <div className={'App' + (lp ? ' LP' : '') + (ip ? ' index-page' : '') + (miniHeader ? ' mini-header' : '')}
onMouseMove={this.onEntropyEvent}>
<SidePanel ref="side_panel" alignment="right">
<TopRightMenu vertical navigate={this.navigate} />
<ul className="vertical menu">
Expand All @@ -171,7 +172,7 @@ class App extends React.Component {
<li><a href="/tos.html" onClick={this.navigate} rel="nofollow">Terms of Service</a></li>
</ul>
</SidePanel>
<Header toggleOffCanvasMenu={this.toggleOffCanvasMenu} menuOpen={this.state.open} />
{miniHeader ? <MiniHeader /> : <Header toggleOffCanvasMenu={this.toggleOffCanvasMenu} menuOpen={this.state.open} />}
<div className="App__content">
{welcome_screen}
{callout}
Expand All @@ -189,7 +190,6 @@ App.propTypes = {
children: AppPropTypes.Children,
location: React.PropTypes.object,
signup_bonus: React.PropTypes.string,
loading: React.PropTypes.bool,
loginUser: React.PropTypes.func.isRequired,
depositSteem: React.PropTypes.func.isRequired,
};
Expand All @@ -200,7 +200,6 @@ export default connect(
error: state.app.get('error'),
flash: state.offchain.get('flash'),
signup_bonus: state.offchain.get('signup_bonus'),
loading: state.app.get('loading'),
new_visitor: !state.user.get('current') &&
!state.offchain.get('user') &&
!state.offchain.get('account') &&
Expand Down
3 changes: 3 additions & 0 deletions app/components/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
@media screen and (min-width: 64.063em) {
margin-top: 3.5rem;
}
}

.mini-header .App__content {
margin-top: 0;
}

.welcomeWrapper {
Expand Down
1 change: 1 addition & 0 deletions app/components/all.scss
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
@import "./elements/Reputation";
@import "./elements/Reblog";
@import "./elements/YoutubePreview";
@import "./elements/SignupProgressBar";

// modules
@import "./modules/Header";
Expand Down
17 changes: 17 additions & 0 deletions app/components/elements/SignupProgressBar.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react';

export default function SignupProgressBar({steps, current}) {
const lis = steps.map((s, i) => {
const cn = i + 1 < current ? 'done' : (i + 1 == current ? 'current' : '');
return <li className={cn} key={i + 1}>{s}</li>
});
return <div className="SignupProgressBar__container expanded row">
<div className="column">
<div className="SignupProgressBar">
<ul>
{lis}
</ul>
</div>
</div>
</div>;
}
71 changes: 71 additions & 0 deletions app/components/elements/SignupProgressBar.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
.SignupProgressBar__container {
background-color: transparent;
padding-bottom: 0.5rem;
border-bottom: 1px solid $light-gray;
}

.SignupProgressBar {
width: 100%;
margin: 0 auto 50px 0;

> ul {
counter-reset: step;
}
> ul > li {
list-style-type: none;
width: 25%;
float: left;
font-size: 12px;
position: relative;
text-align: center;
text-transform: uppercase;
color: #7d7d7d;
}
> ul > li:before {
width: 30px;
height: 30px;
content: counter(step);
counter-increment: step;
line-height: 26px;
border: 2px solid #7d7d7d;
display: block;
text-align: center;
margin: 0 auto 10px auto;
border-radius: 50%;
background-color: white;
}
> ul > li:after {
width: 100%;
height: 2px;
content: '';
position: absolute;
background-color: #7d7d7d;
top: 15px;
left: -50%;
z-index: -1;
}
> ul > li:first-child:after {
content: none;
}
> ul > li.done {
color: #1A5099;
}
> ul > li.done:before {
content: "\2713";
color: #fff;
border-color: #4ba2f2;
background-color: #4ba2f2;
}
> ul > li.done:after {
background-color: #4ba2f2;
}
> ul > li.current {
color: #1A5099;
}
> ul > li.current:before {
border-color: #4ba2f2;
}
> ul > li.current:after {
background-color: #4ba2f2;
}
}
19 changes: 19 additions & 0 deletions app/components/modules/MiniHeader.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import Icon from 'app/components/elements/Icon.jsx';

export default function MiniHeader() {
return <header className="Header">
<div className="Header__top header">
<div className="expanded row">
<div className="columns">
<ul className="menu">
<li className="Header__top-logo">
<a href="/"><Icon name="steem" size="2x" /></a>
</li>
<li className="Header__top-steemit show-for-medium"><a href="/">steemit<span className="beta">beta</span></a></li>
</ul>
</div>
</div>
</div>
</header>;
}
99 changes: 56 additions & 43 deletions app/components/pages/CreateAccount.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* eslint react/prop-types: 0 */
import React from 'react';
import { browserHistory } from 'react-router';
import { connect } from 'react-redux';
import LoadingIndicator from 'app/components/elements/LoadingIndicator';
import Apis from 'shared/api_client/ApiInstances';
Expand All @@ -9,10 +8,8 @@ import user from 'app/redux/User';
import {validate_account_name} from 'app/utils/ChainValidation';
import SignUp from 'app/components/modules/SignUp';
import runTests from 'shared/ecc/test/BrowserTests';
import g from 'app/redux/GlobalReducer';
import GeneratedPasswordInput from 'app/components/elements/GeneratedPasswordInput';

const PASSWORD_MIN_LENGTH = 32;
import SignupProgressBar from 'app/components/elements/SignupProgressBar';

class CreateAccount extends React.Component {

Expand All @@ -31,7 +28,8 @@ class CreateAccount extends React.Component {
name_error: '',
server_error: '',
loading: false,
cryptographyFailure: false
cryptographyFailure: false,
showRules: false
};
this.onSubmit = this.onSubmit.bind(this);
this.onNameChange = this.onNameChange.bind(this);
Expand All @@ -42,7 +40,7 @@ class CreateAccount extends React.Component {
const cryptoTestResult = runTests();
if (cryptoTestResult !== undefined) {
console.error('CreateAccount - cryptoTestResult: ', cryptoTestResult);
this.setState({cryptographyFailure: true});
this.setState({cryptographyFailure: true}); // TODO: do not use setState in componentDidMount
}
}

Expand All @@ -63,6 +61,7 @@ class CreateAccount extends React.Component {
});
}

// createAccount
fetch('/api/v1/accounts', {
method: 'post',
mode: 'no-cors',
Expand Down Expand Up @@ -142,8 +141,8 @@ class CreateAccount extends React.Component {
}

const {
name, password_valid, showPasswordString,
name_error, server_error, loading, cryptographyFailure
name, password_valid, //showPasswordString,
name_error, server_error, loading, cryptographyFailure, showRules
} = this.state;

const {loggedIn, logout, offchainUser, serverBusy} = this.props;
Expand Down Expand Up @@ -203,45 +202,59 @@ class CreateAccount extends React.Component {
</div>;
}

const next_step = !server_error ? null :
server_error === 'Mobile is not confirmed' ? <div>
<a href="/enter_mobile">Verify a Mobile</a>
</div> : <div className="callout alert">
<h5>Couldn't create account. Server returned the following error:</h5>
<p>{server_error}</p>
{server_error === 'Email address is not confirmed' && <a href="/enter_email">Confirm Email</a>}
</div>

return (
<div className="CreateAccount row">
<div className="column large-7 small-10">
<h2>Sign Up</h2>
<div className="CreateAccount__rules">
<hr />
<p>
The first rule of Steemit is: Do not lose your password.<br />
The second rule of Steemit is: Do <strong>not</strong> lose your password.<br />
The third rule of Steemit is: We cannot recover your password.<br />
The fourth rule: If you can remember the password, it&apos;s not secure.<br />
The fifth rule: Use only randomly-generated passwords.<br />
The sixth rule: Do not tell anyone your password.<br />
The seventh rule: Always back up your password.
</p>
<hr />
</div>
<form onSubmit={this.onSubmit} autoComplete="off" noValidate method="post">
<div className={name_error ? 'error' : ''}>
<label>USERNAME
<input type="text" name="name" autoComplete="off" onChange={this.onNameChange} value={name} />
</label>
<p>{name_error}</p>
</div>
<GeneratedPasswordInput onChange={this.onPasswordChange} disabled={loading} showPasswordString={name.length > 0 && !name_error} />
<div>
<SignupProgressBar steps={[offchainUser.get('prv') || 'identity', 'email', 'phone', 'steem account']} current={4} />
<div className="CreateAccount row">
<div className="column" style={{maxWidth: '36rem', margin: '0 auto'}}>
<br />
{server_error && <div className="callout alert">
<h5>Couldn't create account. Server returned the following error:</h5>
<p>{server_error}</p>
{server_error === 'Email address is not confirmed' && <a href="/enter_email">Confirm Email</a>}
{showRules ? <div className="CreateAccount__rules">
<p>
The first rule of Steemit is: Do not lose your password.<br />
The second rule of Steemit is: Do <strong>not</strong> lose your password.<br />
The third rule of Steemit is: We cannot recover your password.<br />
The fourth rule: If you can remember the password, it&apos;s not secure.<br />
The fifth rule: Use only randomly-generated passwords.<br />
The sixth rule: Do not tell anyone your password.<br />
The seventh rule: Always back up your password.
</p>
<div className="text-center">
<a className="CreateAccount__rules-button" href="#" onClick={() => this.setState({showRules: false})}>
<span style={{display: 'inline-block', transform: 'rotate(-90deg)'}}>&raquo;</span>
</a>
</div>
<hr />
</div> : <div className="text-center">
<a className="CreateAccount__rules-button" href="#" onClick={() => this.setState({showRules: true})}>Steemit Rules &nbsp; &raquo;</a>
</div>}
<noscript>
<div className="callout alert">
<p>This form requires javascript to be enabled in your browser</p>
<form onSubmit={this.onSubmit} autoComplete="off" noValidate method="post">
<div className={name_error ? 'error' : ''}>
<label>ACCOUNT NAME
<input type="text" name="name" autoComplete="off" onChange={this.onNameChange} value={name} />
</label>
<p>{name_error}</p>
</div>
</noscript>
{loading && <LoadingIndicator type="circle" />}
<input disabled={submit_btn_disabled} type="submit" className={submit_btn_class} value="SIGN UP" />
</form>
<GeneratedPasswordInput onChange={this.onPasswordChange} disabled={loading} showPasswordString={name.length > 0 && !name_error} />
<br />
{next_step && <div>{next_step}<br /></div>}
<noscript>
<div className="callout alert">
<p>This form requires javascript to be enabled in your browser</p>
</div>
</noscript>
{loading && <LoadingIndicator type="circle" />}
<input disabled={submit_btn_disabled} type="submit" className={submit_btn_class} value="Create Account" />
</form>
</div>
</div>
</div>
);
Expand Down
9 changes: 9 additions & 0 deletions app/components/pages/CreateAccount.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,12 @@
text-align: center;
}
}

.CreateAccount__rules-button {
background-color: #f2f2f2;
padding: 0.2rem 1rem;
border-radius: 10px;
margin: 1rem 0;
font-size: 0.8rem;
color: $dark-gray;
}
4 changes: 4 additions & 0 deletions config/steem-example.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@
"confirm_email": "some_template_id"
}
},
"telesign": {
"customer_id": "",
"rest_api_key": ""
},
"recaptcha": {
"site_key": "",
"secret_key": ""
Expand Down
Loading

0 comments on commit 60fcea8

Please sign in to comment.