sign in and up with email confirmation

This commit is contained in:
Alexander Bell 2018-09-12 18:10:30 +02:00
parent 59beca4846
commit a1f7493ddf
7 changed files with 317 additions and 165 deletions

View File

@ -11,6 +11,7 @@ import { observer, inject } from 'mobx-react';
import Loading from './pages/Loading'; import Loading from './pages/Loading';
import Main from './pages/Main'; import Main from './pages/Main';
import Login from './pages/Login'; import Login from './pages/Login';
import VerifyEmail from './pages/VerifyEmail';
/* /*
@ -48,10 +49,13 @@ const App = inject("rootStore") ( observer(
} }
render() { render() {
console.log(this.stores.authStore.userData.uid)
if(this.stores.rootStore.isLoaded.app === true) { if(this.stores.rootStore.isLoaded.app === true) {
if(this.stores.authStore.userData.uid !== null) { if(this.stores.authStore.userData.uid !== null && this.stores.authStore.userData.userData !== null) {
return(<Main />); if(this.stores.authStore.userData.userData.emailVerified) {
return(<Main />);
} else {
return(<VerifyEmail />);
}
} else { } else {
return(<Login />); return(<Login />);
} }

View File

@ -1,4 +1,5 @@
import React, {Component} from 'react'; import React, {Component} from 'react';
import { observer, inject } from 'mobx-react';
import jss from 'jss'; import jss from 'jss';
import preset from 'jss-preset-default'; import preset from 'jss-preset-default';
import { Menu, Button } from 'semantic-ui-react' import { Menu, Button } from 'semantic-ui-react'
@ -28,79 +29,84 @@ Components -- END
class Main extends Component { const Main = inject("rootStore") ( observer(
constructor(props){ class Main extends Component {
super(props); constructor(props){
//Initial loading screen super(props);
//Initial loading screen
/* /*
* Expected props * Expected props
* - / * - /
*/ */
this.handleItemClick = this.handleItemClick.bind(this); //Stored information
this.stores = this.props.rootStore.stores;
this.state = { this.handleItemClick = this.handleItemClick.bind(this);
activeItem: 'Home'
this.state = {
activeItem: 'Home'
}
//Styles
this.styles = this.getStyles();
this.sheet = jss.createStyleSheet(this.styles);
const {classes} = this.sheet.attach();
this.classes = classes;
//Styles
} }
//Styles
this.styles = this.getStyles(); componentWillUnmount() {
this.sheet = jss.createStyleSheet(this.styles); this.sheet.detach()
const {classes} = this.sheet.attach(); }
this.classes = classes;
//Styles
}
componentWillUnmount() { handleItemClick(e, { name }) {
this.sheet.detach() this.setState({
} activeItem: name
});
}
handleItemClick(e, { name }) { render() {
this.setState({ const activeItem = this.state.activeItem
activeItem: name
});
}
return(
render() { <Menu stackable fixed="top">
const activeItem = this.state.activeItem <Menu.Item header>
<img alt="" src={require('../../files/images/logo.svg')} style={{display: 'block', width: '60px', height: '45px'}} />
return(
<Menu stackable fixed="top">
<Menu.Item header>
<img alt="" src={require('../../files/images/logo.svg')} style={{display: 'block', width: '60px', height: '45px'}} />
</Menu.Item>
<Menu.Item
name='Home'
active={activeItem === 'Home'}
onClick={this.handleItemClick}
>
Home
</Menu.Item>
<Menu.Item name='A' active={activeItem === 'A'} onClick={this.handleItemClick}>
Password manager
</Menu.Item>
<Menu.Menu position='right'>
<Menu.Item>
<Button primary>Sign out</Button>
</Menu.Item> </Menu.Item>
</Menu.Menu>
</Menu> <Menu.Item
); name='Home'
} active={activeItem === 'Home'}
onClick={this.handleItemClick}
>
Home
</Menu.Item>
<Menu.Item name='A' active={activeItem === 'A'} onClick={this.handleItemClick}>
Password manager
</Menu.Item>
<Menu.Menu position='right'>
<Menu.Item>
<Button primary onClick={this.stores.authStore.signOut}>Sign out</Button>
</Menu.Item>
</Menu.Menu>
</Menu>
);
}
getStyles() { getStyles() {
return { return {
}
} }
} }
} ));
export default Main; export default Main;

View File

@ -1,4 +1,5 @@
import React, {Component} from 'react'; import React, {Component} from 'react';
import { observer, inject } from 'mobx-react';
import jss from 'jss'; import jss from 'jss';
import preset from 'jss-preset-default'; import preset from 'jss-preset-default';
import { Container, Button, Form, Header, Segment, Input, Icon } from 'semantic-ui-react' import { Container, Button, Form, Header, Segment, Input, Icon } from 'semantic-ui-react'
@ -29,68 +30,120 @@ Components -- END
class Login extends Component { const Login = inject("rootStore") ( observer(
constructor(props){ class Login extends Component {
super(props); constructor(props){
//Initial loading screen super(props);
//Initial loading screen
/* /*
* Expected props * Expected props
* - / * - /
*/ */
//Styles //Stored information
this.styles = this.getStyles(); this.stores = this.props.rootStore.stores;
this.sheet = jss.createStyleSheet(this.styles);
const {classes} = this.sheet.attach(); this.handleChange = this.handleChange.bind(this);
this.classes = classes; this.handleSubmit = this.handleSubmit.bind(this);
//Styles
} this.state = {
email: '',
password: '',
loading: false
}
//Styles
this.styles = this.getStyles();
this.sheet = jss.createStyleSheet(this.styles);
const {classes} = this.sheet.attach();
this.classes = classes;
//Styles
}
componentWillUnmount() { componentWillUnmount() {
this.sheet.detach() this.sheet.detach()
} }
render() { handleChange(e) {
return( const value = e.target.value;
<Container className={this.classes.container}> const name = e.target.name;
<Segment padded="very">
<Form>
<Header as="h1">
Sign in
</Header>
<Form.Field> this.setState({
<label>Email adress:</label> [ name ]: value
<Input iconPosition='left' placeholder='example@example.com'> });
<Icon name='at' /> }
<input type="email" />
</Input>
</Form.Field>
<Form.Field>
<label>Password:</label>
<input type="password" placeholder='*******' />
</Form.Field>
<Button type='submit'>Next</Button>
</Form>
</Segment>
</Container>
);
}
getStyles() { handleSubmit() {
return { const email = this.state.email;
container: { const password = this.state.password;
padding: '20%',
paddingTop: '10%' this.stores.authStore.signIn(email, password).then(() => {
//Don't stop loading! Component already unmounted by then
}).catch((error) => {
console.log(error);
//Stop loading
this.setState({
loading: false
});
});
//Initialize loading
this.setState({
loading: true
});
}
render() {
return(
<div>
<LoadingPage />
<Container className={this.classes.container}>
<Segment padded="very">
<Form onSubmit={this.handleSubmit}>
<Header as="h1">
Sign in / up
</Header>
<Form.Field>
<label>Email adress:</label>
<Input iconPosition='left' placeholder='example@example.com'>
<Icon name='at' />
<input type="email" name="email" onChange={this.handleChange} autoComplete="off" required />
</Input>
</Form.Field>
<Form.Field>
<label>Password:</label>
<input type="password" name="password" onChange={this.handleChange} placeholder='**********' autoComplete="off" required />
</Form.Field>
<Button loading={this.state.loading} type='submit'>Go!</Button>
</Form>
</Segment>
</Container>
</div>
);
}
getStyles() {
return {
container: {
padding: '0%',
'@media (min-width: 500px)': {
padding: '20%',
paddingTop: '10%',
}
}
} }
} }
} }
} ));
export default Login; export default Login;

View File

@ -9,7 +9,6 @@ import preset from 'jss-preset-default';
/* /*
* Component imports * Component imports
*/ */
import LoadingPage from '../components/loadingPage';
import Menu from '../components/Menu/Menu'; import Menu from '../components/Menu/Menu';
jss.setup(preset()); jss.setup(preset());
@ -56,7 +55,6 @@ class Main extends Component {
render() { render() {
return( return(
<div> <div>
{/*<LoadingPage />*/}
<Menu /> <Menu />
</div> </div>
); );

92
src/pages/VerifyEmail.js Normal file
View File

@ -0,0 +1,92 @@
import React, {Component} from 'react';
import jss from 'jss';
import preset from 'jss-preset-default';
import { Container, Segment, Message, Button } from 'semantic-ui-react'
/*
* Functions import
*/
/*
* Component imports
*/
jss.setup(preset());
/*
###############################
Components -- START
###############################
*/
/*
###############################
Components -- END
###############################
*/
class VerifyEmail extends Component {
constructor(props){
super(props);
//Initial loading screen
/*
* Expected props
* - /
*/
//Styles
this.styles = this.getStyles();
this.sheet = jss.createStyleSheet(this.styles);
const {classes} = this.sheet.attach();
this.classes = classes;
//Styles
}
componentWillUnmount() {
this.sheet.detach()
}
reload() {
window.location.reload();
}
render() {
return(
<div>
<Container className={this.classes.container}>
<Segment padded="very">
<Message warning>
<Message.Header>Pease verify your email adress</Message.Header>
<p>Please check your emails and follow the instructions. Check your spam foulder if you didn't get it.</p>
<p>Reload this page after:</p>
<Button primary onClick={this.reload}>Reload</Button>
</Message>
</Segment>
</Container>
</div>
);
}
getStyles() {
return {
container: {
padding: '0%',
'@media (min-width: 500px)': {
padding: '20%',
paddingTop: '10%',
}
}
}
}
}
export default VerifyEmail;

View File

@ -5,7 +5,7 @@ import alertify from 'alertify.js';
var firebase = require('./fb').fb var firebase = require('./fb').fb
var firebase_orig = require('./fb').firebase var firebase_orig = require('./fb').firebase
// Initialize Cloud Firestore through Firebase // Initialize Cloud Firestore through Firebase
var db = firebase.firestore(); //var db = firebase.firestore();
class AuthStore { class AuthStore {
@ -36,9 +36,10 @@ class AuthStore {
if (user) { if (user) {
//Logged in //Logged in
console.info("Logged in as " + user.uid); console.info("Signed in as " + user.uid);
Object.assign(this.userData, { Object.assign(this.userData, {
uid: user.uid uid: user.uid,
userData: user
}); });
console.info("AuthStore loaded"); console.info("AuthStore loaded");
@ -47,7 +48,7 @@ class AuthStore {
} else { } else {
//Logged out //Logged out
console.info("Logged out"); console.info("Signed out");
Object.assign(this.userData, { Object.assign(this.userData, {
uid: null uid: null
}); });
@ -59,40 +60,46 @@ class AuthStore {
} }
signIn(){ signIn(email, password){
//Verify phone number and then sign in //Sign in user with email and password
return(
new Promise((resolve, reject) => {
firebase.auth().signInWithEmailAndPassword(email, password).then(function(){
alertify.success("Signed in");
resolve();
}).catch(function(error) {
var errorCode = error.code;
if(errorCode === 'auth/wrong-password') {
//Wrong password
alertify.error("Password incorrect!");
reject(error);
}
if(errorCode === 'auth/user-not-found') {
//User not signed up yet. Sign up user now
firebase.auth().createUserWithEmailAndPassword(email, password).then(function(){
alertify.success("Signed in");
console.info("Verify phone number"); var user = firebase.auth().currentUser;
const phoneNumber = this.userData.phoneCode + this.userData.phoneNumber; user.sendEmailVerification().then(function() {
// Confirmation email sent.
alertify.log("....Sending verification code...."); resolve();
firebase_orig.auth().signInWithPhoneNumber(phoneNumber, window.recaptchaVerifier).then(function (confirmationResult) { }).catch(function(error) {
//Code verification prompt // An error happened.
alertify.log("You will receive a SMS with a verification code soon."); reject(error);
alertify.prompt("You will receive a SMS with a verification code soon. Please check your SMS on your phone. Enter the code below:", });
function (val, ev) { }).catch(function(error) {
ev.preventDefault(); alertify.error("Something went wrong. Please check your internet connection");
//Confirm code reject(error);
confirmationResult.confirm(val).then(function (result){ });
alertify.success("Successfully signed in"); }
}).catch(function () { });
})
alertify.error("Wrong code!"); );
});
},
function(ev) {
ev.preventDefault();
alertify.error("You've cancelled the phone verification");
}
);
})
.catch(function (error) {
window.recaptchaVerifier.reset(window.recaptchaWidgetId);
alertify.delay(0).error("Base Web doesn't support signing up yet. Please install the mobile app to sign up! Refresh Base Web after!");
console.error(error.code);
});
} }
@ -100,7 +107,7 @@ class AuthStore {
//Signes user out //Signes user out
firebase_orig.auth().signOut().then(function(){ firebase_orig.auth().signOut().then(function(){
console.log('User signed out');
}).catch(function(error){ }).catch(function(error){
console.error(error); console.error(error);
}); });

View File

@ -9,21 +9,13 @@ require("firebase/storage");
var config = { var config = {
apiKey: "AIzaSyCjWyrIzayUmEBcMcQyPvcXjNDkQONfJA8", apiKey: "AIzaSyDpuphZnuu8U-5CDm1xxdiAFmXukOFav_g",
authDomain: "base-6d44c.firebaseapp.com", authDomain: "homepagelogin-d83db.firebaseapp.com",
databaseURL: "https://base-6d44c.firebaseio.com", databaseURL: "https://homepagelogin-d83db.firebaseio.com",
projectId: "base-6d44c", projectId: "homepagelogin-d83db",
storageBucket: "base-6d44c.appspot.com" storageBucket: "homepagelogin-d83db.appspot.com"
}; };
/*var config = {
apiKey: "AIzaSyDHnDObdPUAOFJfRpgC1tOG59NhheQYUmk",
authDomain: "netwoko-staging.firebaseapp.com",
databaseURL: "https://netwoko-staging.firebaseio.com",
projectId: "netwoko-staging",
storageBucket: "netwoko-staging.appspot.com"
};*/
var fb; var fb;
try { try {