change user auth to have a login page for the users to sign in to the site

This commit is contained in:
Nuwan 2021-11-11 07:52:46 +05:30
parent 4dcb1c4dd8
commit 2ec02ee436
22 changed files with 218 additions and 110 deletions

View File

@ -1,7 +1,7 @@
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import AppContext from './context/Context';
import { AuthProvider } from "./context/AuthContext";
import { settings } from './config';
import toggleStylesheet from './helpers/toggleStylesheet';
import { getItemFromStore, setItemToStore, themeColors } from './helpers/utils';
@ -118,15 +118,13 @@ const Main = props => {
);
}
return <AppContext.Provider value={value}>
<CookiesProvider>
<AuthProvider>
<Provider store={store}>
{props.children}
</Provider>
</AuthProvider>
</CookiesProvider>
</AppContext.Provider>;
return (
<AppContext.Provider value={value}>
<CookiesProvider>
<Provider store={store}>{props.children}</Provider>
</CookiesProvider>
</AppContext.Provider>
);
};
Main.propTypes = { children: PropTypes.node };

View File

@ -6,8 +6,8 @@ import { Button, Form, Row, Col, FormGroup, Input, CustomInput, Label } from 're
import Divider from '../common/Divider';
import SocialAuthButtons from './SocialAuthButtons';
import withRedirect from '../../hoc/withRedirect';
import { useAuth } from '../../context/AuthContext';
import { signin } from '../../services/authService';
import { useAuth } from '../../context/UserAuth';
//import { signin } from '../../services/authService';
const LoginForm = ({ setRedirect, hasLabel, layout }) => {
// State
@ -17,19 +17,19 @@ const LoginForm = ({ setRedirect, hasLabel, layout }) => {
const [isDisabled, setIsDisabled] = useState(true);
const history = useHistory();
const { setCurrentUser} = useAuth();
const { login, setCurrentUser } = useAuth();
// Handler
const handleSubmit = async e => {
e.preventDefault();
const credentials = {email, password}
const user = await signin(credentials)
const user = await login(credentials)
console.log("handleSubmit", user);
if(user){
setCurrentUser(user)
localStorage.setItem('user', user)
//localStorage.setItem('user', user)
toast.success(`Signed in as ${email}`);
setRedirect(true);
setRedirect(true)
}else{
toast.error("Incorrect email or password");
}
@ -81,8 +81,8 @@ const LoginForm = ({ setRedirect, hasLabel, layout }) => {
Log in
</Button>
</FormGroup>
<Divider className="mt-4">or log in with</Divider>
<SocialAuthButtons />
{/* <Divider className="mt-4">or log in with</Divider>
<SocialAuthButtons /> */}
</Form>
);
};

View File

@ -1,25 +1,25 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Redirect, Route, Switch, withRouter } from 'react-router-dom';
//import Login from './Login';
import Login from './Login';
import Start from './Start';
import Logout from './Logout';
// import Registration from './Registration';
// import ForgetPassword from './ForgetPassword';
// import PasswordReset from './PasswordReset';
// import ConfirmMail from './ConfirmMail';
// import LockScreen from './LockScreen';
import Registration from './Registration';
import ForgetPassword from './ForgetPassword';
import PasswordReset from './PasswordReset';
import ConfirmMail from './ConfirmMail';
import LockScreen from './LockScreen';
const AuthBasicRoutes = ({ match: { url } }) => (
<Switch>
{/* <Route path={`${url}/login`} exact component={Login} /> */}
<Route path={`${url}/login`} exact component={Login} />
<Route path={`${url}/start`} exact component={Start} />
<Route path={`${url}/logout`} exact component={Logout} />
{/* <Route path={`${url}/register`} exact component={Registration} />
<Route path={`${url}/register`} exact component={Registration} />
<Route path={`${url}/forget-password`} exact component={ForgetPassword} />
<Route path={`${url}/confirm-mail`} exact component={ConfirmMail} />
<Route path={`${url}/password-reset`} exact component={PasswordReset} />
<Route path={`${url}/lock-screen`} exact component={LockScreen} /> */}
<Route path={`${url}/lock-screen`} exact component={LockScreen} />
{/*Redirect*/}
<Redirect to="/errors/404" />

View File

@ -7,13 +7,13 @@ const Login = () => (
<Fragment>
<Row className="text-left justify-content-between">
<Col xs="auto">
<h5>Log in</h5>
<h5>Sign in</h5>
</Col>
<Col xs="auto">
{/* <Col xs="auto">
<p className="fs--1 text-600">
or <Link to="/authentication/basic/register">create an account</Link>
</p>
</Col>
</Col> */}
</Row>
<LoginForm />
</Fragment>

View File

@ -1,5 +1,6 @@
import React, { useContext, useEffect } from 'react';
import { Route, Switch } from 'react-router-dom';
import PrivateRoute from '../../helpers/privateRoute';
import NavbarTop from '../navbar/JKNavbarTop';
import NavbarVertical from '../navbar/JKNavbarVertical';
@ -14,8 +15,8 @@ import { addMessage } from "../../store/features/textMessagesSlice"
import { add as addNotification } from '../../store/features/notificationSlice';
import Home from './JKHomePage';
import loadable from '@loadable/component';
import loadable from '@loadable/component';
const DashboardRoutes = loadable(() => import('../../layouts/JKDashboardRoutes'));
function JKDashboard() {
@ -123,7 +124,7 @@ function JKDashboard() {
<div className="content">
<NavbarTop />
<Switch>
<Route path="/" exact component={Home} />
<PrivateRoute path="/" exact component={Home} />
<DashboardRoutes />
</Switch>
{!isKanban && <Footer />}

View File

@ -11,7 +11,7 @@ import Notification from '../notification/JKNotification';
import { fetchNotifications } from '../../store/features/notificationSlice';
import { useDispatch, useSelector } from 'react-redux';
import { useAuth } from '../../context/AuthContext';
import { useAuth } from '../../context/UserAuth';
const JKNotificationDropdown = () => {
const { currentUser } = useAuth();

View File

@ -1,24 +1,24 @@
//import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import React, { useState } from 'react';
import { DropdownItem, DropdownMenu, DropdownToggle, Dropdown } from 'reactstrap';
import { useAuth } from '../../context/AuthContext';
import { useAuth } from '../../context/UserAuth';
import JKProfileAvatar from '../profile/JKProfileAvatar';
import { useCookies } from 'react-cookie';
const ProfileDropdown = () => {
const [dropdownOpen, setDropdownOpen] = useState(false);
const toggle = () => setDropdownOpen(prevState => !prevState);
const { currentUser, setCurrentUser } = useAuth();
const { currentUser, setCurrentUser, logout } = useAuth();
const [cookies, setCookie, removeCookie] = useCookies(['remember_token']);
const handleLogout = event => {
const handleLogout = async (event) => {
event.preventDefault();
removeCookie('remember_token', {
domain: `.${process.env.REACT_APP_ORIGIN}`
});
setCurrentUser(null);
window.location.reload(false);
logout()
};
return (

View File

@ -2,7 +2,7 @@ import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { Row, Col } from 'reactstrap';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { useAuth } from '../../context/AuthContext';
import { useAuth } from '../../context/UserAuth';
import { truncate } from '../../helpers/utils';
import { fetchPerson } from '../../store/features/peopleSlice'
import { useDispatch, useSelector } from 'react-redux'

View File

@ -3,7 +3,7 @@ import { Modal, ModalHeader, ModalBody, Row, Col, Button, ModalFooter } from 're
import { Scrollbar } from 'react-scrollbars-custom';
import TimeAgo from '../common/JKTimeAgo'
import JKProfileAvatar from './JKProfileAvatar';
import { useAuth } from '../../context/AuthContext';
import { useAuth } from '../../context/UserAuth';
import { useDispatch, useSelector } from 'react-redux';
import { fetchMessagesByReceiverId, postNewMessage } from '../../store/features/textMessagesSlice';
import { isIterableArray } from '../../helpers/utils';

View File

@ -7,7 +7,7 @@ import moment from 'moment';
import { Modal, ModalBody, ModalHeader } from 'reactstrap';
import ScrollBarCustom from '../common/ScrollBarCustom';
import { useAuth } from '../../context/AuthContext';
import { useAuth } from '../../context/UserAuth';
import { useTranslation } from "react-i18next";
import JKProfileAvatar from './JKProfileAvatar';

View File

@ -0,0 +1,63 @@
import React, { useState, useEffect, createContext, useContext } from 'react';
import PropTypes from 'prop-types';
import { checkIsAuthenticated, authSignUp, authLogin, authLogout } from '../services/auth'
export const UserAuthContext = createContext({});
export const useAuth = () => useContext(UserAuthContext)
export default function UserAuth({ children, path }) {
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [currentUser, setCurrentUser] = useState(null)
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
console.log('checking auth........', path);
checkAuth();
}, [path]);
const checkAuth = () =>
checkIsAuthenticated()
.then((user) => {
setIsAuthenticated(true)
setCurrentUser(user)
window.currentUser = user;
})
.catch(() => {
setIsAuthenticated(false)
setCurrentUser(null)
window.currentUser = null;
})
.then(() => setIsLoading(false));
const login = credentials =>
authLogin(credentials)
.then(setIsAuthenticated(true))
.catch(error => {
console.log(error);
setIsAuthenticated(false);
});
const logout = () => {
authLogout()
setIsAuthenticated(false);
};
const signUp = credentials =>
authSignUp(credentials)
.then(setIsAuthenticated(true))
.catch(error => {
console.log(error);
setIsAuthenticated(false);
});
return (
<UserAuthContext.Provider value={{ currentUser, setCurrentUser, isAuthenticated, isLoading, login, logout, signUp }}>
{children}
</UserAuthContext.Provider>
);
}
// UserAuth.propTypes = {
// children: PropTypes.oneOfType([PropTypes.func, PropTypes.array])
// };

View File

@ -32,7 +32,6 @@ function secureFetch(path, options) {
switch (response.status) {
case 403:
console.log('apiFetch Authentication error');
// window.location.href = `${process.env.REACT_APP_LEGACY_BASE_URL}/signin`
break;
case 404:
console.log('apiFetch Object not found');

View File

@ -0,0 +1,33 @@
import React, { useContext } from 'react';
import { Route, Redirect } from 'react-router-dom';
import PropTypes from 'prop-types';
import { UserAuthContext } from '../context/UserAuth';
//import Loading from '../../views/Loading/Loading';
const PrivateRoute = ({ component: Component, ...otherProps }) => {
const { isAuthenticated, isLoading } = useContext(UserAuthContext);
return (
<Route
{...otherProps}
render={props =>
!isLoading ? (
isAuthenticated ? (
<Component {...props} />
) : (
<Redirect to={otherProps.redirectTo ? otherProps.redirectTo : '/authentication/basic/login'} />
)
) : (
// <Loading />
<span>loading...</span>
)
}
/>
);
};
PrivateRoute.propTypes = {
component: PropTypes.func.isRequired
};
export default PrivateRoute;

View File

@ -51,13 +51,13 @@ export const getInstruments = () => {
})
}
export const getCurrentUser = () => {
return new Promise((resolve, reject) => {
apiFetch('/me')
.then(response => resolve(response))
.catch(error => reject(error))
})
}
// export const getCurrentUser = () => {
// return new Promise((resolve, reject) => {
// apiFetch('/me')
// .then(response => resolve(response))
// .catch(error => reject(error))
// })
// }
export const addFriend = (userId, friendId) => {
return new Promise((resolve, reject) => {

View File

@ -3,15 +3,18 @@ import { Card, CardBody, Col, Row } from 'reactstrap';
import Logo from '../components/navbar/Logo';
import Section from '../components/common/Section';
import AuthBasicRoutes from '../components/auth/basic/AuthBasicRoutes';
import UserAuth from '../context/UserAuth';
const AuthBasicLayout = () => (
const AuthBasicLayout = ({location}) => (
<Section className="py-0">
<Row className="flex-center min-vh-100 py-6">
<Col sm={10} md={8} lg={6} xl={5} className="col-xxl-4">
<Logo />
<Card>
<CardBody className="fs--1 font-weight-normal p-5">
<UserAuth path={location.pathname}>
<AuthBasicRoutes />
</UserAuth>
</CardBody>
</Card>
</Col>

View File

@ -1,71 +1,22 @@
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
//import { Route, Redirect } from 'react-router-dom';
import DashboardLoadingIndicator from '../components/dashboard/JKDashboardLoadingIndicator';
import LoginRequest from '../components/auth/JKLoginRequest';
import JKDashboard from '../components/dashboard/JKDashboardMain';
import { useAuth } from '../context/AuthContext';
import { getCurrentUser } from '../helpers/rest';
const AUTH_STAGES = {
loading: 1,
authenticated: 2,
unauthenticated: 3
};
//import DashboardLoadingIndicator from '../components/dashboard/JKDashboardLoadingIndicator';
import Dashboard from '../components/dashboard/JKDashboardMain';
import UserAuth from '../context/UserAuth';
const DashboardLayout = ({ location }) => {
const { setCurrentUser } = useAuth();
const [stage, setStage] = useState(AUTH_STAGES['loading']);
useEffect(() => {
getCurrentUser()
.then(resp => {
if (resp.ok) {
return resp.json();
}
})
.then(user => {
setCurrentUser(user);
window.currentUser = user;
setStage(AUTH_STAGES['authenticated']);
})
.catch(error => {
setStage(AUTH_STAGES['unauthenticated']);
console.log(error);
});
}, [location.pathname]);
useEffect(() => {
window.scrollTo(0, 0);
}, [location.pathname]);
switch (stage) {
case AUTH_STAGES['authenticated']:
return <JKDashboard />;
case AUTH_STAGES['unauthenticated']:
return <LoginRequest />;
default:
return <DashboardLoadingIndicator />;
}
return (
<UserAuth path={location.pathname}>
<Dashboard />
</UserAuth>
);
};
// const ProtectedRoute = ({ component: Component, ...rest }) => {
// const { currentUser } = useAuth();
// return (
// // Show the component only when the user is logged in
// // Otherwise, redirect the user to /login page
// <Route
// {...rest}
// render={props =>
// currentUser ? <Component {...props} /> : <Redirect to={{ pathname: '/authentication/basic/start' }} />
// }
// />
// );
// };
DashboardLayout.propTypes = { location: PropTypes.object.isRequired };
export default DashboardLayout;

View File

@ -1,13 +1,15 @@
import React from 'react';
import { Redirect, Route, Switch } from 'react-router-dom';
import PrivateRoute from '../helpers/privateRoute';
import JKPeople from '../components/page/JKPeople';
import JKNotifications from '../components/page/JKNotifications';
const JKDashboardRoutes = () => (
<Switch>
<Route path="/friends" component={JKPeople} />
<Route path="/notifications" component={JKNotifications} />
<PrivateRoute path="/friends" component={JKPeople} />
<PrivateRoute path="/notifications" component={JKNotifications} />
{/*Redirect*/}
<Redirect to="/errors/404" />
</Switch>

View File

@ -1,4 +1,4 @@
import React from 'react';
import React, {useEffect} from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import { toast, ToastContainer } from 'react-toastify';
import { CloseButton, Fade } from '../components/common/Toast';
@ -7,11 +7,19 @@ import DashboardLayout from './JKDashboardLayout';
import ErrorLayout from './ErrorLayout';
import BuildMeta from "./JKBuildMeta";
import loadable from '@loadable/component';
const AuthBasicLayout = loadable(() => import('./AuthBasicLayout'));
const Layout = () => {
useEffect(() => {
AuthBasicLayout.preload();
}, []);
return (
<Router fallback={<span />}>
<Switch>
<Route path="/errors" component={ErrorLayout} />
<Route path="/authentication/basic" component={AuthBasicLayout} />
<Route component={DashboardLayout} />
</Switch>
<ToastContainer transition={Fade} closeButton={<CloseButton />} position={toast.POSITION.BOTTOM_RIGHT} />

View File

@ -0,0 +1,37 @@
import { getCurrentUser } from '../helpers/rest';
import apiFetch from "../helpers/apiFetch";
import { reject } from 'lodash';
export const checkIsAuthenticated = () => {
// return new Promise((resolve, reject) => {
// getCurrentUser()
// .then((resp) => resolve(resp.json()))
// .catch((err) => reject(err))
// });
return new Promise((resolve, reject) => {
apiFetch('/me')
.then(response => resolve(response))
.catch(error => reject(error))
})
}
export const authSignUp = () => {}
export const authLogin = (credentials) => {
return new Promise((resolve, reject) => {
apiFetch('/auths/login', {
method: 'POST',
body: JSON.stringify(credentials)
})
.then(response => resolve(response))
.catch(error => reject(error))
})
}
export const authLogout = () => {
return new Promise((resolve, reject) => {
apiFetch('/auths/logout')
.then((response) => resolve(response))
.catch((error) => reject(error))
})
}

View File

@ -25,4 +25,9 @@ class ApiAuthsController < ApiController
}, :status => :ok
end
end
def logout
sign_out
render :json => {}, :status => :ok
end
end

View File

@ -34,7 +34,14 @@ class ApiUsersController < ApiController
end
def me
render json: { id: current_user.id, first_name: current_user.first_name, last_name: current_user.last_name, name: current_user.name, photo_url: current_user.photo_url }, status: 200
render json: {
id: current_user.id,
first_name: current_user.first_name,
last_name: current_user.last_name,
name: current_user.name,
email: current_user.email,
photo_url: current_user.photo_url
}, status: 200
end
def show

View File

@ -252,6 +252,7 @@ Rails.application.routes.draw do
scope '/api' do
post '/auths/login' => 'api_auths#login'
post '/auths/logout' => 'api_auths#logout'
# live streams
match '/live_streams' => 'api_live_streams#index', :via => :get