Skip to content

Commit 42a20d7

Browse files
authored
Merge pull request #657 from lazycipher/GoogleOAuth
Implements GoogleOAuth via Passport and Cookie based auth
2 parents 4ec4c2f + 2dfce0f commit 42a20d7

File tree

9 files changed

+100
-88
lines changed

9 files changed

+100
-88
lines changed

src/App.js

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,10 @@ import { setCurrentUser, logoutUser } from "./actions/authAction";
99
import "./css/main.scss";
1010
import ReactGA from "react-ga";
1111

12-
// check if user already loggedIn
13-
const token = localStorage.getItem("jwtToken");
14-
console.log("CHECKING TOKEN ", token);
15-
if (token) {
16-
const decodedData = jwt_decode(token);
17-
// set auth token in axios header
18-
setAuthToken(token);
19-
// set user in the state
20-
setCurrentUser(decodedData);
21-
// check if token is valid or expired
22-
const currentTime = Date.now() / 1000; // in ms
23-
const expiryTime = decodedData.iat + 10800000; // 24 hrs
24-
if (expiryTime <= currentTime) {
25-
store.dispatch(logoutUser());
26-
window.location.href = "/";
27-
}
28-
}
29-
3012
function App() {
3113
useEffect(() => {
3214
ReactGA.initialize("UA-173245995-1");
15+
setAuthToken()
3316
});
3417
return (
3518
<Provider store={store}>

src/actions/authAction.js

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,40 @@
11
import { SET_CURRENT_USER, GET_USER_PROFILE, PASSWORD_SUCCESSFULLY_CHANGED, PASSWORD_CHANGE_REQUEST_SUCCESS, SET_ADMIN } from './types';
22
import axios from 'axios';
33
import { setAuthToken } from '../utils/setAuthToken';
4-
import jwt_decode from 'jwt-decode';
54
import { errorHandler } from '../utils/errorHandler';
65
import { setRequestStatus } from '../utils/setRequestStatus';
76
import { BASE_URL } from './baseApi';
87
import { customErrorHandler } from '../utils/customErrorHandler'
98
let forgotPasswordToken = "";
109

10+
export const loadUser = () => async(dispatch) => {
11+
try {
12+
const res = await axios.get(`${BASE_URL}/user/load_user`);
13+
14+
if(res.status === 200){
15+
dispatch(setRequestStatus(true));
16+
localStorage.setItem('userId', res.data.user._id)
17+
18+
dispatch(setCurrentUser(res.data.user._id))
19+
20+
// Update user name, role, orgId in localStorage
21+
localStorage.setItem('username', `${res.data.user.name.firstName} ${res.data.user.name.lastName}`)
22+
localStorage.setItem('admin', res.data.user.isAdmin)
23+
localStorage.setItem('ticketModerator', res.data.user.isTicketsModerator)
24+
localStorage.setItem('orgId', res.data.user.orgId)
25+
26+
// if user is admin update admin in store
27+
dispatch({
28+
type: SET_ADMIN,
29+
payload: res.data.user.isAdmin
30+
})
31+
}
32+
} catch(error) {
33+
console.log('error while loading user from localstorage', error)
34+
dispatch(errorHandler(error));
35+
}
36+
}
37+
1138
// to register user
1239
export const registerUser = (userInfo, history) => async (dispatch) => {
1340
try {
@@ -39,29 +66,14 @@ export const loginUser = (userInfo, history) => async (dispatch) => {
3966
dispatch(setRequestStatus(false));
4067
if(res.status === 200){
4168

42-
const token = res.data.token;
4369
dispatch(setRequestStatus(true));
44-
45-
localStorage.setItem("jwtToken", (token));
46-
setAuthToken(token);
47-
48-
// update state with user
49-
const decodedData = await jwt_decode(token);
50-
console.log("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! PRINTING RES.DATA.USER !!!!!!!!!!!!!!1");
51-
console.log(res.data.user);
5270
localStorage.setItem('userId', res.data.user._id)
53-
dispatch(setCurrentUser(decodedData));
71+
dispatch(setCurrentUser(res.data.user._id));
5472

55-
// Update user name in localStorage
73+
// Update user name, role, orgId in localStorage
5674
localStorage.setItem('username', `${res.data.user.name.firstName} ${res.data.user.name.lastName}`)
57-
58-
// update user role in localStorage
5975
localStorage.setItem('admin', res.data.user.isAdmin)
60-
61-
// update user role in localStorage
6276
localStorage.setItem('ticketModerator', res.data.user.isTicketsModerator)
63-
64-
// store orgId in localStorage
6577
localStorage.setItem('orgId', res.data.user.orgId);
6678

6779
// if user is admin update admin in store

src/common/PrivateRoute.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,4 @@ const mapStateToProps = (state) => {
2727
org: state.org
2828
}
2929
}
30-
export default connect(mapStateToProps)(PrivateRoute);
30+
export default connect(mapStateToProps)(PrivateRoute);

src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import ReactDOM from "react-dom";
33
import "./index.css";
44
import App from "./App";
55
import * as serviceWorker from "./serviceWorker";
6+
import axios from 'axios';
67

78
if (process.env.NODE_ENV !== "development") {
89
console.log = () => {};

src/reducers/authReducer.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ import { SET_CURRENT_USER, RESPONSE_MSG, SET_ADMIN, BLOCK_USER, UNBLOCK_USER, RE
22

33
const initialState = {
44
// make it false later, default is set to true so that contributors don't need to login for test
5-
isAuthenticated: true, // localStorage.getItem("jwtToken").length > 1
5+
isAuthenticated: false, // localStorage.getItem("jwtToken").length > 1
66
isAdmin: false,
77
isBlocked: false,
88
isRemoved: false,
99
resetPassReq: null,
1010
passUpdated: false,
11-
user: {},
11+
user: null,
1212
response_msg: "",
1313
};
1414

@@ -17,7 +17,7 @@ export default (state = initialState, action) => {
1717
case SET_CURRENT_USER: {
1818
return {
1919
...state,
20-
isAuthenticated: Boolean(typeof action.payload === 'object' && Object.keys(action.payload).length !== 0),
20+
isAuthenticated: Boolean(action.payload.length !== 0 && action.payload!==undefined && typeof action.payload === 'string'),
2121
user: action.payload
2222
}
2323
}
@@ -67,4 +67,4 @@ export default (state = initialState, action) => {
6767
return state
6868
}
6969
}
70-
}
70+
}

src/router.js

Lines changed: 55 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import React from "react";
2-
import { BrowserRouter, Route, Switch } from "react-router-dom";
1+
import React, {useEffect} from "react";
2+
import { BrowserRouter, Route, Switch, Redirect } from "react-router-dom";
33
import Login from "./user/auth/login/login";
44
import Dashboard from "./user/dashboard/dashboard";
55
import PinnedPosts from "./user/pinned-posts/pinned-posts";
@@ -25,44 +25,58 @@ import Activity from "./user/Activity/Activity";
2525
import IntegrationsPage from "./user/integrations/IntegrationsPage/IntegrationsPage";
2626
import UserIntegrations from "./user/integrations/UserIntegrations/UserIntegrations";
2727
import TicketDashboard from "../src/user/Admin/Tickets/TicketDashboard";
28+
import { loadUser } from './actions/authAction';
29+
import { connect } from 'react-redux';
2830

29-
const Router = () => (
30-
<BrowserRouter>
31-
<Switch>
32-
<Route exact path="/" component={Login} />
33-
<Route exact path="/login" component={Login} />
34-
<Route exact path="/maintenance" component={Maintenance}></Route>
35-
<PrivateRoute exact path="/dashboard" component={Dashboard} />
36-
<PrivateRoute exact path="/pinned-posts" component={PinnedPosts} />
37-
<PrivateRoute exact path="/profile/:id" component={Profile} />
38-
<PrivateRoute exact path="/:id/proj-info" component={ProjInfo} />
39-
<PrivateRoute exact path="/organization" component={Organization} />
40-
<PrivateRoute exact path="/wikis" component={Wikis} />
41-
<PrivateRoute exact path="/settings" component={Settings} />
42-
<PrivateRoute exact path="/projects" component={Projects} />
43-
<PrivateRoute exact path="/events" component={Events} />
44-
<PrivateRoute exact path="/proposal" component={UserProposalDashboard} />
45-
<PrivateRoute
46-
exact
47-
path="/proposaldiscussion"
48-
component={ProposalDiscussion}
49-
/>
50-
<PrivateRoute exact path="/proposaleditor" component={ProposalEditor} />
51-
<PrivateRoute exact path="/setup" component={Setup} />
52-
<AdminRoute exact path="/org-settings" component={CommunitySetting} />
53-
<AdminRoute exact path="/activity/:userId" component={Activity} />
54-
<PrivateRoute exact path="/insight" component={Insight} />
55-
<PrivateRoute exact path="/admin" component={Admin} />
56-
<PrivateRoute exact path="/integrations" component={IntegrationsPage} />
57-
<PrivateRoute
58-
exact
59-
path="/userintegrations"
60-
component={UserIntegrations}
61-
/>
62-
<PrivateRoute exact path="/tickets" component={TicketDashboard} />
63-
<Route component={NotFound} />
64-
</Switch>
65-
</BrowserRouter>
66-
);
31+
const Router = ({loadUser, auth}) => {
32+
useEffect(() => {
33+
loadUser();
34+
}, [])
35+
return (
36+
<BrowserRouter>
37+
{auth && auth.isAuthenticated?<Redirect to="/dashboard"/>:null}
38+
<Switch>
39+
<Route exact path="/" component={Login} />
40+
<Route exact path="/login" component={Login} />
41+
<Route exact path="/maintenance" component={Maintenance}></Route>
42+
<PrivateRoute exact path="/dashboard" component={Dashboard} />
43+
<PrivateRoute exact path="/pinned-posts" component={PinnedPosts} />
44+
<PrivateRoute exact path="/profile/:id" component={Profile} />
45+
<PrivateRoute exact path="/:id/proj-info" component={ProjInfo} />
46+
<PrivateRoute exact path="/organization" component={Organization} />
47+
<PrivateRoute exact path="/wikis" component={Wikis} />
48+
<PrivateRoute exact path="/settings" component={Settings} />
49+
<PrivateRoute exact path="/projects" component={Projects} />
50+
<PrivateRoute exact path="/events" component={Events} />
51+
<PrivateRoute exact path="/proposal" component={UserProposalDashboard} />
52+
<PrivateRoute
53+
exact
54+
path="/proposaldiscussion"
55+
component={ProposalDiscussion}
56+
/>
57+
<PrivateRoute exact path="/proposaleditor" component={ProposalEditor} />
58+
<PrivateRoute exact path="/setup" component={Setup} />
59+
<AdminRoute exact path="/org-settings" component={CommunitySetting} />
60+
<AdminRoute exact path="/activity/:userId" component={Activity} />
61+
<PrivateRoute exact path="/insight" component={Insight} />
62+
<PrivateRoute exact path="/admin" component={Admin} />
63+
<PrivateRoute exact path="/integrations" component={IntegrationsPage} />
64+
<PrivateRoute
65+
exact
66+
path="/userintegrations"
67+
component={UserIntegrations}
68+
/>
69+
<PrivateRoute exact path="/tickets" component={TicketDashboard} />
70+
<Route component={NotFound} />
71+
</Switch>
72+
</BrowserRouter>
73+
)
74+
};
6775

68-
export default Router;
76+
const mapStateToProps = (state) => {
77+
return {
78+
auth: state.auth
79+
}
80+
}
81+
82+
export default connect(mapStateToProps, {loadUser})(Router);

src/user/auth/login/login.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ import { connect } from 'react-redux';
1010
import { getLoginOptions } from '../../../actions/orgAction'
1111
import { HashLink } from 'react-router-hash-link';
1212
import "./login.scss";
13+
import { BASE_URL } from '../../../actions/baseApi'
14+
15+
const GITHUB_OAUTH_URL = BASE_URL + '/user/auth/github' || "http://localhost:5000/user/auth/github"
16+
const GOOGLE_OAUTH_URL = BASE_URL + '/user/auth/google' || "http://localhost:5000/user/auth/google"
1317

1418
class Login extends Component {
1519
constructor(props) {
@@ -86,7 +90,7 @@ class Login extends Component {
8690
{Boolean(loginOptions?.google === true) ? (
8791
<Col className = "button-column">
8892
<a
89-
href="http://localhost:5000/auth/google"
93+
href={GOOGLE_OAUTH_URL}
9094
style={{ padding: "1vh" }}
9195
>
9296
<Button
@@ -106,7 +110,7 @@ class Login extends Component {
106110
{Boolean(loginOptions?.github === true) ? (
107111
<Col className="button-column" >
108112
<a
109-
href="http://localhost:5000/auth/google"
113+
href={GITHUB_OAUTH_URL}
110114
style={{ padding: "1vh" }}
111115
>
112116
<Button

src/user/wikis/Layout/Layout.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ const Layout = (props) => {
1010
const { wikis, spinner, allWikis, isAdmin, oauthCheck, children } = props;
1111
return (
1212
<React.Fragment>
13-
<div className="navigation">
14-
<Navigation wikis={wikis}></Navigation>
15-
</div>
1613
<div id="wikis">
1714
<LoadingOverlay
1815
active={!!spinner}

src/utils/setAuthToken.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import axios from "axios";
22

33
export const setAuthToken = (token) => {
4+
axios.defaults.withCredentials = true;
45
if(token){
56
// set AUTHORIZATION in headers of all request
67
axios.defaults.headers.common['Authorization'] = token || localStorage.getItem("jwtToken");
78
} else {
89
// delete from the headers
910
delete axios.defaults.headers.common['Authorization'];
1011
}
11-
}
12+
}

0 commit comments

Comments
 (0)