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:
parent
daebbf6202
commit
4d976eb075
|
@ -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": [
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
273b5b51-0311-4d9e-a428-e5abca4d6a51
|
|
@ -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) => {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
|
@ -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>
|
||||||
) : (
|
) : (
|
||||||
|
|
Loading…
Reference in New Issue