Skip to content

Commit 86eef5b

Browse files
author
gondzo
committed
Merge branch 'improveLogin' into dev
# Conflicts: # README.md # package.json # src/routes/DronesMap/modules/DronesMap.js # src/routes/index.js # src/services/APIService.js
2 parents 046ed5a + afa8296 commit 86eef5b

File tree

17 files changed

+575
-93
lines changed

17 files changed

+575
-93
lines changed

.env.example

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
REACT_APP_API_BASE_PATH=https://kb-dsp-server.herokuapp.com
2-
REACT_APP_SOCKET_URL=https://kb-dsp-server.herokuapp.com
3-
REACT_APP_AUTH0_CLIEND_ID=3CGKzjS2nVSqHxHHE64RhvvKY6e0TYpK
4-
REACT_APP_AUTH0_DOMAIN=dronetest.auth0.com
5-
REACT_APP_GOOGLE_API_KEY=AIzaSyCR3jfBdv9prCBYBOf-fPUDhjPP4K05YjE
1+
GOOGLE_API_KEY=AIzaSyCrL-O319wNJK8kk8J_JAYsWgu6yo5YsDI
2+
API_BASE_PATH=http://localhost:3500
3+
REACT_APP_AUTH0_CLIENT_ID=h7p6V93Shau3SSvqGrl6V4xrATlkrVGm
4+
REACT_APP_AUTH0_CLIENT_DOMAIN=spanhawk.auth0.com
5+
REACT_APP_SOCKET_URL=http://localhost:3500

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,24 @@ See Guild https://github.com/lorenwest/node-config/wiki/Configuration-Files
2424
|`REACT_APP_AUTH0_DOMAIN`| The React app auth0 domain`|
2525

2626
Environment variables will be loaded from the .env file during build. Create the .env file based on the provided env.example
27+
### Auth0 setup
28+
- Create an account on auth0.
29+
- Click on clients in left side menu, it will redirect you to client page. Click on CREATE CLIENT button
30+
to create a new client.
31+
- Copy the client id and client domain and export them as environment variables.
32+
- Add `http://localhost:3000` as Allowed callback url's in client settings.
33+
34+
### Add social connections
35+
36+
### Facebook social connection
37+
- To add facebook social connection to auth0, you have to create a facebook app.
38+
Go to facebook [developers](https://developers.facebook.com/apps) and create a new app.
39+
- Copy the app secret and app id to auth0 social connections facebook tab.
40+
- You have to setup the oauth2 callback in app oauth settings.
41+
- For more information visit auth0 [docs](https://auth0.com/docs/connections/social/facebook)
42+
43+
### Google social connection
44+
- For more information on how to connect google oauth2 client, visit official [docs](https://auth0.com/docs/connections/social/google)
2745

2846
## Install dependencies
2947
`npm i`

config/default.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable import/no-commonjs */
22
/**
3-
* Main config file
3+
* Main config file for the server which is hosting the reat app
44
*/
55
module.exports = {
66
// below env variables are NOT visible in frontend

src/api/User.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,17 @@ class UserApi {
5656
})});
5757
}
5858

59-
registerSocialUser(name, email) {
59+
registerSocialUser(name, email, token) {
6060
const url = `${this.basePath}/api/v1/login/social`;
6161

6262
return reqwest({
6363
url,
6464
method: 'post',
6565
type: 'json',
6666
contentType: 'application/json',
67+
headers: {
68+
Authorization: `Bearer ${token}`,
69+
},
6770
data: JSON.stringify({
6871
name,
6972
email,

src/components/TextField/TextField.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
width: 100%;
33
border: 1px solid #ebebeb;
44

5+
input[type="password"],
56
input[type="text"] {
67
width: 100%;
78
padding: 0 10px;

src/config/index.js

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,14 @@
1+
/* eslint-disable import/no-commonjs */
12
/**
2-
* Copyright (c) 2016 Topcoder Inc, All rights reserved.
3+
* Main config file for the react app
34
*/
4-
5-
/**
6-
* Webapp configuration
7-
*
8-
* @author TCSCODER
9-
* @version 1.0.0
10-
*/
11-
12-
const config = {
13-
api: {
14-
basePath: process.env.REACT_APP_API_BASE_PATH || 'http://localhost:3500',
15-
},
5+
module.exports = {
6+
// below env variables are visible in frontend
7+
API_BASE_PATH: process.env.API_BASE_PATH || 'http://localhost:3500',
8+
REACT_APP_AUTH0_CLIENT_ID: process.env.REACT_APP_AUTH0_CLIENT_ID || 'h7p6V93Shau3SSvqGrl6V4xrATlkrVGm',
9+
REACT_APP_AUTH0_CLIENT_DOMAIN: process.env.REACT_APP_AUTH0_CLIENT_DOMAIN || 'spanhawk.auth0.com',
10+
AUTH0_CALLBACK: 'http://localhost:3000',
1611
socket: {
1712
url: process.env.REACT_APP_SOCKET_URL || 'http://localhost:3500',
1813
},
19-
AUTH0_CLIEND_ID: process.env.REACT_APP_AUTH0_CLIEND_ID || '3CGKzjS2nVSqHxHHE64RhvvKY6e0TYpK',
20-
AUTH0_DOMAIN: process.env.REACT_APP_AUTH0_DOMAIN || 'dronetest.auth0.com',
2114
};
22-
23-
export default config;

src/routes/Home/components/LoginModal/LoginModal.jsx

Lines changed: 142 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ import Button from 'components/Button';
77
import Checkbox from 'components/Checkbox';
88
import TextField from 'components/TextField';
99
import styles from './LoginModal.scss';
10+
import APIService from '../../../../services/APIService';
11+
import {toastr} from 'react-redux-toastr';
12+
import {defaultAuth0Service} from '../../../../services/AuthService';
13+
14+
const EMAIL_REGEX = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i;
15+
1016
/*
1117
* customStyles
1218
*/
@@ -50,10 +56,11 @@ FormField.propTypes = {
5056
*/
5157

5258
class LogInModal extends React.Component {
53-
constructor() {
54-
super();
59+
constructor(props) {
60+
super(props);
5561
this.state = {
5662
modalLoginIsOpen: false,
63+
showForgetPassword: false,
5764
};
5865
}
5966

@@ -62,15 +69,14 @@ class LogInModal extends React.Component {
6269
}
6370

6471
closeLoginModal() {
65-
this.setState({modalLoginIsOpen: false});
72+
this.setState({modalLoginIsOpen: false, showForgetPassword: false});
6673
}
6774

6875
login() {
6976
this.setState({modalLoginIsOpen: true});
7077
}
7178

7279
handleLogin(handleLoggedIn, loggedUser) {
73-
handleLoggedIn();
7480
const _self = this;
7581
setTimeout(() => {
7682
handleLoggedIn();
@@ -81,9 +87,53 @@ class LogInModal extends React.Component {
8187
}, 100);
8288
}
8389

90+
forgetPassword() {
91+
this.setState({showForgetPassword: true});
92+
}
93+
94+
/**
95+
* Login using google social network,
96+
* this method internally uses auth0 service
97+
*/
98+
googleLogin() {
99+
defaultAuth0Service.login({connection: 'google-oauth2'}, (error) => {
100+
if (error) {
101+
const message = error.message || 'something went wrong, please try again';
102+
toastr.error(message);
103+
}
104+
});
105+
}
106+
107+
/**
108+
* Login using facebook social network,
109+
* this method internally uses auth0 service
110+
*/
111+
facebookLogin() {
112+
defaultAuth0Service.login({connection: 'facebook'}, (error) => {
113+
if (error) {
114+
const message = error.message || 'something went wrong, please try again';
115+
toastr.error(message);
116+
}
117+
});
118+
}
119+
120+
/**
121+
* This method is invoked when reset password request is submitted
122+
*/
123+
handleForgetPassword(data) {
124+
APIService.forgotPassword({email: data.emailUp}).then(() => {
125+
toastr.success('', 'Reset password link emailed to your email address');
126+
this.closeLoginModal();
127+
}).catch((reason) => {
128+
const message = reason.response.body.error || 'something went wrong, please try again';
129+
toastr.error(message);
130+
this.closeLoginModal();
131+
});
132+
}
133+
84134
render() {
135+
const _self = this;
85136
const {handleSubmit, fields, handleLoggedIn, loggedUser, hasError, errorText} = this.props;
86-
87137
return (
88138
<div styleName="signin-modal">
89139
<div styleName="login-signup">
@@ -100,71 +150,88 @@ class LogInModal extends React.Component {
100150

101151
<div styleName="modal-header">
102152
<div onClick={this.closeLoginModal.bind(this)} styleName="icon-close-modal" />
103-
<div styleName="title">Login to Your Account</div>
153+
{this.state.showForgetPassword === false && <div styleName="title">Login to Your Account</div>}
154+
{this.state.showForgetPassword === true && <div styleName="title">Reset forgotten password</div>}
104155
</div>
156+
{this.state.showForgetPassword === false &&
157+
<form styleName="login-form" onSubmit={handleSubmit}>
158+
<div styleName="login-with-fb">
159+
<a href="javascript:;" onClick={this.facebookLogin.bind(this)}>
160+
<i styleName="icon-facebook" />
161+
<span>Log In with Facebook</span>
162+
</a>
163+
</div>
105164

106-
<form styleName="login-form" onSubmit={handleSubmit}>
107-
<div styleName="login-with-fb">
108-
<a href="javascript:;">
109-
<i styleName="icon-facebook" />
110-
<span>Log In with Facebook</span>
111-
</a>
112-
</div>
113-
114-
<div styleName="login-with-gplus">
115-
<a href="javascript:;">
116-
<i styleName="icon-gplus" />
117-
<span>Log In with Google Plus</span>
118-
</a>
119-
</div>
120-
{/* login with end */}
121-
<div styleName="or-border">
122-
<div styleName="left-line" />
123-
<div styleName="or">or</div>
124-
<div styleName="right-line" />
125-
</div>
126-
{/* or end */}
127-
<div>
128-
{hasError && <span className="error-msg">{errorText.error}</span>}
129-
<div styleName="email-input">
130-
<FormField {...fields.email}>
131-
<TextField {...fields.email} login type="email" label="Email" />
132-
</FormField>
165+
<div styleName="login-with-gplus">
166+
<a href="javascript:;" onClick={this.googleLogin.bind(this)}>
167+
<i styleName="icon-gplus" />
168+
<span>Log In with Google Plus</span>
169+
</a>
170+
</div>
171+
{/* login with end */}
172+
<div styleName="or-border">
173+
<div styleName="left-line" />
174+
<div styleName="or">or</div>
175+
<div styleName="right-line" />
133176
</div>
177+
{/* or end */}
134178
<div>
135-
<FormField {...fields.password}>
136-
<TextField {...fields.password} login type="password" label="Password" />
137-
</FormField>
179+
{hasError && <span className="error-msg">{errorText.error}</span>}
180+
<div styleName="email-input">
181+
<FormField {...fields.email}>
182+
<TextField {...fields.email} login type="email" label="Email" />
183+
</FormField>
184+
</div>
185+
<div>
186+
<FormField {...fields.password}>
187+
<TextField {...fields.password} login type="password" label="Password" />
188+
</FormField>
189+
</div>
138190
</div>
139-
</div>
140-
{/* input end */}
141-
<div styleName="rem-forget">
142-
<div styleName="rem-checkbox">
143-
<Checkbox
144-
checked={!this.props.fields.remember.value}
145-
onChange={() => this.props.fields.remember.onChange(!this.props.fields.remember.value)}
146-
id="remember"
191+
{/* input end */}
192+
<div styleName="rem-forget">
193+
<div styleName="rem-checkbox">
194+
<Checkbox
195+
checked={!this.props.fields.remember.value}
196+
onChange={() => this.props.fields.remember.onChange(!this.props.fields.remember.value)}
197+
id="remember"
198+
>
199+
Remember me
200+
</Checkbox>
201+
</div>
202+
<div styleName="forget"><a href="javascript:;" onClick={this.forgetPassword.bind(this)}>Forget Password?</a></div>
203+
</div>
204+
<div styleName="login-btn">
205+
<Button
206+
type="submit" color="black"
207+
className={styles.btnLogin} onClick={() => this.handleLogin(handleLoggedIn, loggedUser)}
147208
>
148-
Remember me
149-
</Checkbox>
209+
Log In
210+
</Button>
211+
</div>
212+
<div styleName="dont-have">
213+
Don&#8217;t have an account? <a href="javascript:;" className="singup">Sign Up</a>
214+
</div>
215+
</form>
216+
}
217+
{ this.state.showForgetPassword === true &&
218+
<form styleName="login-form" onSubmit={handleSubmit((data) => _self.handleForgetPassword(data))}>
219+
<div>
220+
{hasError && <span className="error-msg">{errorText.error}</span>}
221+
<div styleName="email-input">
222+
<FormField {...fields.emailUp}>
223+
<TextField {...fields.emailUp} login type="email" label="Email" />
224+
</FormField>
225+
</div>
226+
</div>
227+
<div styleName="login-btn">
228+
<Button type="submit" color="black" className={styles.btnLogin}>
229+
Reset Password
230+
</Button>
150231
</div>
151-
<div styleName="forget"><a href="javascript:;">Forget Password?</a></div>
152-
</div>
153-
<div styleName="login-btn">
154-
<Button
155-
type="submit" color="black"
156-
className={styles.btnLogin} onClick={() => this.handleLogin(handleLoggedIn, loggedUser)}
157-
>
158-
Log In
159-
</Button>
160-
</div>
161-
<div styleName="dont-have">
162-
Don&#8217;t have an account? <a href="javascript:;" className="singup" >Sign Up</a>
163-
</div>
164-
</form>
232+
</form>
233+
}
165234
</Modal>
166-
167-
168235
</div>
169236
);
170237
}
@@ -183,9 +250,21 @@ const fields = ['remember', 'email', 'password', 'emailUp', 'passwordUp'];
183250

184251
const validate = (values) => {
185252
const errors = {};
253+
if (!values.emailUp && !values.email) {
254+
errors.emailUp = 'Email is required';
255+
} else if (!EMAIL_REGEX.test(values.emailUp) && !values.email) {
256+
errors.emailUp = 'Invalid email address';
257+
}
258+
259+
if (errors.emailUp && (values.emailUp || values.email)) {
260+
return errors;
261+
} else if (values.emailUp) {
262+
return errors;
263+
}
264+
186265
if (!values.email) {
187266
errors.email = 'Email is required';
188-
} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
267+
} else if (!EMAIL_REGEX.test(values.email)) {
189268
errors.email = 'Invalid email address';
190269
}
191270
if (!values.password) {

0 commit comments

Comments
 (0)