fixed userData persisting problem, logout bug fixes and cookie expiration problem (#2045)

- Clearing data on logout was not happening (fixed)
- User was unable to login due to token not being set properly (fixed)
- Persistor was not storing the userData immediately (fixed)

Signed-off-by: arkajyotiMukherjee <arkajyoti.mukherjee@mayadata.io>
This commit is contained in:
Arkajyoti Mukherjee 2020-09-12 13:39:43 +05:30 committed by GitHub
parent daebbf6202
commit 4d976eb075
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 53 additions and 28 deletions

View File

@ -18,7 +18,6 @@
} }
}, },
"rules": { "rules": {
"import/no-cycle": 0,
"new-cap": 0, "new-cap": 0,
"no-underscore-dangle": 0, "no-underscore-dangle": 0,
"react/static-property-placement": [ "react/static-property-placement": [

View File

@ -0,0 +1 @@
273b5b51-0311-4d9e-a428-e5abca4d6a51

View File

@ -23,7 +23,7 @@ import {
import { ProjectsCallBackType } from '../../models/header'; import { ProjectsCallBackType } from '../../models/header';
import useActions from '../../redux/actions'; import useActions from '../../redux/actions';
import * as UserActions from '../../redux/actions/user'; import * as UserActions from '../../redux/actions/user';
import { history } from '../../redux/configureStore'; import configureStore, { history } from '../../redux/configureStore';
import { RootState } from '../../redux/reducers'; import { RootState } from '../../redux/reducers';
import getToken from '../../utils/getToken'; import getToken from '../../utils/getToken';
import userAvatar from '../../utils/user'; import userAvatar from '../../utils/user';
@ -67,10 +67,11 @@ const ProfileInfoDropdownItems: React.FC<ProfileInfoDropdownItemProps> = ({
const [switchableProjects, setSwitchableProjects] = useState<Project[]>([]); const [switchableProjects, setSwitchableProjects] = useState<Project[]>([]);
const [loggedOut, doLogout] = useState(false); const [loggedOut, doLogout] = useState(false);
const userData = useSelector((state: RootState) => state.userData); const userData = useSelector((state: RootState) => state.userData);
// Use the persistor object
const { persistor } = configureStore();
const logOut = () => { const logOut = () => {
doLogout(true); doLogout(true);
user.userLogout();
fetch(`${config.auth.url}/logout`, { fetch(`${config.auth.url}/logout`, {
method: 'POST', method: 'POST',
@ -86,6 +87,9 @@ const ProfileInfoDropdownItems: React.FC<ProfileInfoDropdownItemProps> = ({
.catch((err) => { .catch((err) => {
console.error(err); console.error(err);
}); });
user.userLogout();
// Clear data from persistor
persistor.purge();
}; };
const CallbackFromProjectListItem = (selectedProjectIDFromList: string) => { const CallbackFromProjectListItem = (selectedProjectIDFromList: string) => {

View File

@ -15,6 +15,7 @@ import {
import { Message, NotificationIds } from '../../models/header'; import { Message, NotificationIds } from '../../models/header';
import useActions from '../../redux/actions'; import useActions from '../../redux/actions';
import * as UserActions from '../../redux/actions/user'; import * as UserActions from '../../redux/actions/user';
import configureStore from '../../redux/configureStore';
import { RootState } from '../../redux/reducers'; import { RootState } from '../../redux/reducers';
import CustomBreadCrumbs from '../BreadCrumbs'; import CustomBreadCrumbs from '../BreadCrumbs';
import NotificationsDropdown from './NotificationDropdown'; import NotificationsDropdown from './NotificationDropdown';
@ -30,8 +31,10 @@ interface SelectedProjectDetails {
const Header: React.FC = () => { const Header: React.FC = () => {
const classes = useStyles(); const classes = useStyles();
const userData = useSelector((state: RootState) => state.userData); const userData = useSelector((state: RootState) => state.userData);
const user = useActions(UserActions); const user = useActions(UserActions);
// Use the persistor object
const { persistor } = configureStore();
// Query to get user details // Query to get user details
const { data } = useQuery<CurrentUserDetails, CurrentUserDedtailsVars>( const { data } = useQuery<CurrentUserDetails, CurrentUserDedtailsVars>(
GET_USER, GET_USER,
@ -61,6 +64,9 @@ const Header: React.FC = () => {
userRole: member.role, userRole: member.role,
selectedProjectName: project.name, selectedProjectName: project.name,
}); });
// Flush data to persistor immediately
persistor.flush();
setSelectedProjectDetails({ setSelectedProjectDetails({
selectedProjectID, selectedProjectID,
selectedUserRole: member.role, selectedUserRole: member.role,

View File

@ -6,6 +6,7 @@ import { useSelector } from 'react-redux';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import config from '../../config'; import config from '../../config';
import { CREATE_USER } from '../../graphql'; import { CREATE_USER } from '../../graphql';
import { CreateUserData } from '../../models/graphql/user';
import { RootState } from '../../redux/reducers'; import { RootState } from '../../redux/reducers';
import getToken from '../../utils/getToken'; import getToken from '../../utils/getToken';
import { import {
@ -26,15 +27,16 @@ const CStepper: React.FC<CStepperProps> = ({ handleModal }) => {
const classes = useStyles(); const classes = useStyles();
const { t } = useTranslation(); const { t } = useTranslation();
const { userData } = useSelector((state: RootState) => state); const userData = useSelector((state: RootState) => state.userData);
const [activeStep, setActiveStep] = React.useState<number>(0); const [activeStep, setActiveStep] = React.useState<number>(0);
const isError = useRef(true); const isError = useRef(true);
const isSuccess = useRef(false); const isSuccess = useRef(false);
const [info, setInfo] = React.useState({ const [info, setInfo] = React.useState<CreateUserData>({
username: userData.username,
email: '', email: '',
name: '', name: '',
projectName: '', project_name: '',
}); });
const handleBack = () => { const handleBack = () => {
@ -57,7 +59,7 @@ const CStepper: React.FC<CStepperProps> = ({ handleModal }) => {
window.location.reload(); window.location.reload();
}; };
const [CreateUser] = useMutation(CREATE_USER, { const [CreateUser] = useMutation<CreateUserData>(CREATE_USER, {
onCompleted: () => { onCompleted: () => {
rerender(); rerender();
}, },
@ -86,7 +88,7 @@ const CStepper: React.FC<CStepperProps> = ({ handleModal }) => {
username: userData.username, username: userData.username,
email: info.email, email: info.email,
name: info.name, name: info.name,
project_name: info.projectName, project_name: info.project_name,
}, },
}, },
}); });
@ -117,8 +119,8 @@ const CStepper: React.FC<CStepperProps> = ({ handleModal }) => {
// [Button State: Disabled] // [Button State: Disabled]
if (activeStep === 0) { if (activeStep === 0) {
if ( if (
info.projectName.length > 0 && info.project_name.length > 0 &&
validateStartEmptySpacing(info.projectName) === false validateStartEmptySpacing(info.project_name) === false
) { ) {
isError.current = false; isError.current = false;
} else { } else {
@ -242,19 +244,19 @@ const CStepper: React.FC<CStepperProps> = ({ handleModal }) => {
<div className={classes.inputArea} data-cy="InputProjectName"> <div className={classes.inputArea} data-cy="InputProjectName">
<InputField <InputField
label={t('welcomeModel.case-0.label')} label={t('welcomeModel.case-0.label')}
value={info.projectName} value={info.project_name}
required required
helperText={ helperText={
validateStartEmptySpacing(info.projectName) validateStartEmptySpacing(info.project_name)
? 'Should not start with an empty space' ? 'Should not start with an empty space'
: '' : ''
} }
validationError={validateStartEmptySpacing( validationError={validateStartEmptySpacing(
info.projectName info.project_name
)} )}
type="text" type="text"
handleChange={(event) => { handleChange={(event) => {
setData('projectName', event.target.value); setData('project_name', event.target.value);
}} }}
/> />
</div> </div>

View File

@ -35,3 +35,10 @@ export interface CurrentUserDetails {
export interface CurrentUserDedtailsVars { export interface CurrentUserDedtailsVars {
username: string; username: string;
} }
export interface CreateUserData {
username: string;
email: string;
name: string;
project_name: string;
}

View File

@ -21,7 +21,7 @@ import useActions from '../../redux/actions';
import * as TabActions from '../../redux/actions/tabs'; import * as TabActions from '../../redux/actions/tabs';
import * as TemplateSelectionActions from '../../redux/actions/template'; import * as TemplateSelectionActions from '../../redux/actions/template';
import * as UserActions from '../../redux/actions/user'; import * as UserActions from '../../redux/actions/user';
import { history } from '../../redux/configureStore'; import configureStore, { history } from '../../redux/configureStore';
import { RootState } from '../../redux/reducers'; import { RootState } from '../../redux/reducers';
import useStyles from './style'; import useStyles from './style';
@ -63,6 +63,8 @@ const HomePage: React.FC = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const user = useActions(UserActions); const user = useActions(UserActions);
const tabs = useActions(TabActions); const tabs = useActions(TabActions);
// Use the persistor object
const { persistor } = configureStore();
// Query to get user details // Query to get user details
const { data, loading } = useQuery< const { data, loading } = useQuery<
@ -82,7 +84,10 @@ const HomePage: React.FC = () => {
if (data?.getUser.username === userData.username) { if (data?.getUser.username === userData.username) {
setIsOpen(false); setIsOpen(false);
if (userData.selectedProjectID === '') { if (userData.selectedProjectID === '') {
let isOwnerOfProject = { id: '', name: '' }; let isOwnerOfProject = {
id: '',
name: '',
};
const projectList: Project[] = data?.getUser.projects; const projectList: Project[] = data?.getUser.projects;
projectList.forEach((project) => { projectList.forEach((project) => {
const memberList: Member[] = project.members; const memberList: Member[] = project.members;
@ -91,7 +96,10 @@ const HomePage: React.FC = () => {
member.user_name === data?.getUser.username && member.user_name === data?.getUser.username &&
member.role === 'Owner' member.role === 'Owner'
) { ) {
isOwnerOfProject = { id: project.id, name: project.name }; isOwnerOfProject = {
id: project.id,
name: project.name,
};
} }
}); });
}); });
@ -100,6 +108,8 @@ const HomePage: React.FC = () => {
userRole: 'Owner', userRole: 'Owner',
selectedProjectName: isOwnerOfProject.name, selectedProjectName: isOwnerOfProject.name,
}); });
// Flush data to persistor immediately
persistor.flush();
} }
} }
}, [data]); }, [data]);

View File

@ -7,7 +7,6 @@ import {
UserData, UserData,
} from '../../models/redux/user'; } from '../../models/redux/user';
import { setCookie } from '../../utils/cookies'; import { setCookie } from '../../utils/cookies';
import { history } from '../configureStore';
import createReducer from './createReducer'; import createReducer from './createReducer';
const initialState: UserData = { const initialState: UserData = {
@ -22,11 +21,9 @@ export const userData = createReducer<UserData>(initialState, {
try { try {
const jwt = action.payload as string; const jwt = action.payload as string;
const data: any = jwtDecode.decode(jwt); const data: any = jwtDecode.decode(jwt);
const expirationTime = const expirationTime = (data.exp - data.iat) / 3600;
new Date(data.exp * 1000).getHours() -
new Date(data.iat * 1000).getHours();
setCookie('token', jwt, expirationTime); setCookie('token', jwt, expirationTime);
return { return {
...state, ...state,
...data, ...data,
@ -46,7 +43,6 @@ export const userData = createReducer<UserData>(initialState, {
}, },
[UserActions.LOGOUT_USER](state: UserData, action: UserAction) { [UserActions.LOGOUT_USER](state: UserData, action: UserAction) {
setCookie('token', '', 1); setCookie('token', '', 1);
history.push('/login');
return { return {
...initialState, ...initialState,
}; };

View File

@ -115,7 +115,7 @@ const UserManagement: React.FC = () => {
setAnchorEl(null); setAnchorEl(null);
}; };
const [currRow, setCurrRow] = React.useState<UserData>(rows[0]); const [currRow, setCurrRow] = React.useState<UserData>();
const formatDate = (date: string) => { const formatDate = (date: string) => {
const day = moment(date).format('Do MMM,YYYY LT'); const day = moment(date).format('Do MMM,YYYY LT');
@ -135,9 +135,9 @@ const UserManagement: React.FC = () => {
<div> <div>
<EditUser <EditUser
handleDiv={() => setEditDiv(false)} handleDiv={() => setEditDiv(false)}
email={currRow.email} email={currRow?.email ?? ''}
fullName={currRow.name} fullName={currRow?.name ?? ''}
userName={currRow.username} userName={currRow?.username ?? ''}
/> />
</div> </div>
) : ( ) : (